add initial X11 version - libsl - draw back-ends for dwm, dmenu, etc
(HTM) git clone git://git.codemadness.org/libsl
(DIR) Log
(DIR) Files
(DIR) Refs
(DIR) LICENSE
---
(DIR) commit b450cbeceb639c6372733d14d1a3af95550109d2
(DIR) parent 09ba5ebb3fb9c4b4766d7efb7a477a624734f135
(HTM) Author: Hiltjo Posthuma <hiltjo@codemadness.org>
Date: Thu, 26 Sep 2019 23:03:21 +0200
add initial X11 version
based on a combination of the current drw logic and the "old" X11 version code.
Diffstat:
A x11/drw.c | 254 +++++++++++++++++++++++++++++++
A x11/drw.h | 58 ++++++++++++++++++++++++++++++
2 files changed, 312 insertions(+), 0 deletions(-)
---
(DIR) diff --git a/x11/drw.c b/x11/drw.c
@@ -0,0 +1,254 @@
+/* See LICENSE file for copyright and license details. */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <X11/Xlib.h>
+
+#include "drw.h"
+#include "util.h"
+
+Drw *
+drw_create(Display *dpy, int screen, Window root, unsigned int w, unsigned int h)
+{
+ Drw *drw;
+
+ drw = ecalloc(1, sizeof(Drw));
+ drw->dpy = dpy;
+ drw->screen = screen;
+ drw->root = root;
+ drw->w = w;
+ drw->h = h;
+ drw->drawable = XCreatePixmap(dpy, root, w, h, DefaultDepth(dpy, screen));
+ drw->gc = XCreateGC(dpy, root, 0, NULL);
+ XSetLineAttributes(dpy, drw->gc, 1, LineSolid, CapButt, JoinMiter);
+
+ return drw;
+}
+
+void
+drw_resize(Drw *drw, unsigned int w, unsigned int h)
+{
+ drw->w = w;
+ drw->h = h;
+ if (drw->drawable)
+ XFreePixmap(drw->dpy, drw->drawable);
+ drw->drawable = XCreatePixmap(drw->dpy, drw->root, w, h, DefaultDepth(drw->dpy, drw->screen));
+}
+
+void
+drw_free(Drw *drw)
+{
+ XFreePixmap(drw->dpy, drw->drawable);
+ XFreeGC(drw->dpy, drw->gc);
+ free(drw);
+}
+
+static Fnt *
+xfont_create(Display *dpy, const char *fontname)
+{
+ Fnt *font;
+ XFontStruct **xfonts;
+ char **font_names;
+ char *def, **missing;
+ int n;
+
+ font = ecalloc(1, sizeof(Fnt));
+ font->dpy = dpy;
+ font->set = XCreateFontSet(dpy, fontname, &missing, &n, &def);
+ if (missing) {
+ while (n--)
+ fprintf(stderr, "drw: missing fontset: %s\n", missing[n]);
+ XFreeStringList(missing);
+ }
+ if (font->set) {
+ XExtentsOfFontSet(font->set);
+ n = XFontsOfFontSet(font->set, &xfonts, &font_names);
+ while (n--) {
+ font->ascent = MAX(font->ascent, (*xfonts)->ascent);
+ font->descent = MAX(font->descent,(*xfonts)->descent);
+ xfonts++;
+ }
+ } else {
+ if (!(font->xfont = XLoadQueryFont(dpy, fontname))
+ && !(font->xfont = XLoadQueryFont(dpy, "fixed")))
+ die("error, cannot load font: '%s'\n", fontname);
+ font->ascent = font->xfont->ascent;
+ font->descent = font->xfont->descent;
+ }
+ font->h = font->ascent + font->descent;
+
+ return font;
+}
+
+void
+xfont_free(Display *dpy, Fnt *font)
+{
+ if (font->set)
+ XFreeFontSet(dpy, font->set);
+ else
+ XFreeFont(dpy, font->xfont);
+ free(font);
+}
+
+Fnt *
+drw_fontset_create(Drw* drw, const char *fonts[], size_t fontcount)
+{
+ /* just create using first font */
+ /* TODO: more? */
+ drw->fonts = xfont_create(drw->dpy, fonts[0]);
+ return drw->fonts;
+}
+
+void
+drw_fontset_free(Fnt *font)
+{
+ xfont_free(font->dpy, font);
+}
+
+void
+drw_clr_create(Drw *drw, Clr *dest, const char *clrname)
+{
+ Colormap cmap;
+ XColor ecolor;
+
+ cmap = DefaultColormap(drw->dpy, drw->screen);
+ if (!XAllocNamedColor(drw->dpy, cmap, clrname, dest, &ecolor))
+ die("error, cannot allocate color '%s'\n", clrname);
+}
+
+/* Wrapper to create color schemes. The caller has to call free(3) on the
+ * returned color scheme when done using it. */
+Clr *
+drw_scm_create(Drw *drw, const char *clrnames[], size_t clrcount)
+{
+ size_t i;
+ Clr *ret;
+
+ ret = ecalloc(clrcount, sizeof(Clr));
+ for (i = 0; i < clrcount; i++)
+ drw_clr_create(drw, &ret[i], clrnames[i]);
+
+ return ret;
+}
+
+void
+drw_setfontset(Drw *drw, Fnt *set)
+{
+ drw->fonts = set;
+}
+
+void
+drw_setscheme(Drw *drw, Clr *scheme)
+{
+ drw->scheme = scheme;
+}
+
+void
+drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled,
+ int invert)
+{
+ int dx;
+
+ XSetForeground(drw->dpy, drw->gc, drw->scheme[invert ? ColBg : ColFg].pixel);
+ dx = (drw->fonts->ascent + drw->fonts->descent + 2) / 4;
+ if (filled)
+ XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w + 1, h + 1);
+ else
+ XDrawRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h);
+}
+
+int
+drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad,
+ const char *text, int invert)
+{
+ char buf[256];
+ int i, tx, ty, th, len, olen;
+ unsigned int texw, texh;
+
+ /* TODO: lpad */
+
+ XSetForeground(drw->dpy, drw->gc, drw->scheme[invert ? ColFg : ColBg].pixel);
+ XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h);
+
+ olen = strlen(text);
+ drw_font_getexts(drw->fonts, text, olen, &texw, &texh);
+ th = drw->fonts->ascent + drw->fonts->descent;
+ ty = y + (h / 2) - (th / 2) + drw->fonts->ascent;
+ tx = x + (h / 2);
+ /* shorten text if necessary */
+ for (len = MIN(olen, sizeof buf); len && (texw > w - texh || w < texh); len--)
+ drw_font_getexts(drw->fonts, text, len, &texw, &texh);
+ if (!len)
+ return x;
+ memcpy(buf, text, len);
+ if (len < olen)
+ for (i = len; i && i > len - 3; buf[--i] = '.')
+ ;
+ XSetForeground(drw->dpy, drw->gc, invert ? drw->scheme[ColBg].pixel : drw->scheme[ColFg].pixel);
+ if (drw->fonts->set)
+ XmbDrawString(drw->dpy, drw->drawable, drw->fonts->set, drw->gc, tx, ty, buf, len);
+ else
+ XDrawString(drw->dpy, drw->drawable, drw->gc, tx, ty, buf, len);
+
+ return x + w;
+}
+
+void
+drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h)
+{
+ XCopyArea(drw->dpy, drw->drawable, win, drw->gc, x, y, w, h, x, y);
+ XSync(drw->dpy, False);
+}
+
+static unsigned int
+drw_font_getexts_width(Fnt *font, const char *text, unsigned int len)
+{
+ unsigned int w;
+
+ drw_font_getexts(font, text, len, &w, NULL);
+
+ return w;
+}
+
+unsigned int
+drw_fontset_getwidth(Drw *drw, const char *text)
+{
+ return drw_font_getexts_width(drw->fonts, text, strlen(text));
+}
+
+void
+drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h)
+{
+ XRectangle r;
+
+ if (font->set) {
+ XmbTextExtents(font->set, text, len, NULL, &r);
+ if (w)
+ *w = r.width;
+ if (h)
+ *h = r.height;
+ } else {
+ if (h)
+ *h = font->ascent + font->descent;
+ if (w)
+ *w = XTextWidth(font->xfont, text, len);
+ }
+}
+
+Cur *
+drw_cur_create(Drw *drw, int shape)
+{
+ Cur *cur;
+
+ cur = ecalloc(1, sizeof(Cur));
+ cur->cursor = XCreateFontCursor(drw->dpy, shape);
+
+ return cur;
+}
+
+void
+drw_cur_free(Drw *drw, Cur *cursor)
+{
+ XFreeCursor(drw->dpy, cursor->cursor);
+ free(cursor);
+}
(DIR) diff --git a/x11/drw.h b/x11/drw.h
@@ -0,0 +1,58 @@
+/* See LICENSE file for copyright and license details. */
+
+typedef struct {
+ Cursor cursor;
+} Cur;
+
+typedef struct {
+ Display *dpy;
+ int ascent;
+ int descent;
+ unsigned int h;
+ XFontSet set;
+ XFontStruct *xfont;
+} Fnt;
+
+enum { ColFg, ColBg, ColBorder }; /* Clr scheme index */
+typedef XColor Clr;
+
+typedef struct {
+ unsigned int w, h;
+ Display *dpy;
+ int screen;
+ Window root;
+ Drawable drawable;
+ GC gc;
+ Clr *scheme;
+ Fnt *fonts;
+} Drw;
+
+/* Drawable abstraction */
+Drw *drw_create(Display *dpy, int screen, Window win, unsigned int w, unsigned int h);
+void drw_resize(Drw *drw, unsigned int w, unsigned int h);
+void drw_free(Drw *drw);
+
+/* Fnt abstraction */
+Fnt *drw_fontset_create(Drw* drw, const char *fonts[], size_t fontcount);
+void drw_fontset_free(Fnt* set);
+unsigned int drw_fontset_getwidth(Drw *drw, const char *text);
+void drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h);
+
+/* Colorscheme abstraction */
+void drw_clr_create(Drw *drw, Clr *dest, const char *clrname);
+Clr *drw_scm_create(Drw *drw, const char *clrnames[], size_t clrcount);
+
+/* Cursor abstraction */
+Cur *drw_cur_create(Drw *drw, int shape);
+void drw_cur_free(Drw *drw, Cur *cursor);
+
+/* Drawing context manipulation */
+void drw_setfontset(Drw *drw, Fnt *set);
+void drw_setscheme(Drw *drw, Clr *scm);
+
+/* Drawing functions */
+void drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int invert);
+int drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, const char *text, int invert);
+
+/* Map functions */
+void drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h);