Introduction
Introduction Statistics Contact Development Disclaimer Help
Added Xft support (in the same fashion as done in dmenu by Hiltjo Posthuma), Xi…
git clone git://git.suckless.org/svkbd
Log
Files
Refs
README
LICENSE
---
commit c8ee269e7344f7e1deeaa8c4ce1b4a16c6f5b26b
parent 915b95b03d33e960e477fbdbe9d108ffc90aaacf
Author: Maarten van Gompel <[email protected]>
Date: Sun, 2 Aug 2020 15:46:12 +0200
Added Xft support (in the same fashion as done in dmenu by Hiltjo Posthuma), Xi…
Signed-off-by: Miles Alan <[email protected]>
Diffstat:
M LICENSE | 1 +
M Makefile | 13 +++----------
M config.def.h | 18 ++++++++++--------
M config.mk | 12 ++++++++----
A drw.c | 417 +++++++++++++++++++++++++++++…
A drw.h | 51 +++++++++++++++++++++++++++++…
M layout.sxmo.h | 38 ++++++++++++++++-------------…
M svkbd.c | 202 ++++++++++-------------------…
A util.c | 35 +++++++++++++++++++++++++++++…
A util.h | 8 ++++++++
10 files changed, 613 insertions(+), 182 deletions(-)
---
diff --git a/LICENSE b/LICENSE
@@ -2,6 +2,7 @@ MIT/X Consortium License
© 2011 Christoph Lohmann <[email protected]>
© 2008-2011 Enno Boland <g # s01 ' de>
+© 2020 Maarten van Gompel <[email protected]>
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
diff --git a/Makefile b/Makefile
@@ -3,12 +3,12 @@
.POSIX:
NAME = svkbd
-VERSION = 0.1
+VERSION = 0.2
include config.mk
BIN = ${NAME}-${LAYOUT}
-SRC = ${NAME}.c
+SRC = drw.c ${NAME}.c util.c
OBJ = ${NAME}-${LAYOUT}.o
MAN1 = ${NAME}.1
@@ -24,15 +24,8 @@ options:
config.h:
cp config.def.h $@
-${BIN}: config.h ${OBJ}
-
-${OBJ}: config.h
-
-${OBJ}:
- ${CC} -o $@ -c ${SRC} ${SVKBD_CFLAGS} ${SVKBD_CPPFLAGS}
-
${BIN}:
- ${CC} -o ${BIN} ${OBJ} ${SVKBD_LDFLAGS}
+ ${CC} -o $@ ${SRC} ${SVKBD_CFLAGS} ${SVKBD_CPPFLAGS} ${SVKBD_LDFLAGS}
clean:
rm -f ${NAME}-?? ${NAME}-??.o ${OBJ}
diff --git a/config.def.h b/config.def.h
@@ -1,9 +1,11 @@
static const Bool wmborder = True;
-static const char font[] = "-*-terminus-medium-r-normal-*-14-*-*-*-*-*-*-*";
-static const char normbgcolor[] = "#cccccc";
-static const char normfgcolor[] = "#000000";
-static const char pressbgcolor[] = "#0000cc";
-static const char pressfgcolor[] = "#ffffff";
-static const char highlightbgcolor[] = "#0000cc";
-static const char highlightfgcolor[] = "#ffffff";
-
+static int fontsize = 16;
+static const char *fonts[] = {
+ "monospace:size=16"
+};
+static const char *colors[SchemeLast][2] = {
+ /* fg bg */
+ [SchemeNorm] = { "#58a7c6", "#14313d" },
+ [SchemePress] = { "#ffffff", "#005577" },
+ [SchemeHighlight] = { "#58a7c6", "#005577" },
+};
diff --git a/config.mk b/config.mk
@@ -1,4 +1,4 @@
-LAYOUT = en
+LAYOUT = sxmo
# paths
PREFIX = /usr/local
@@ -7,11 +7,15 @@ MANPREFIX = ${PREFIX}/share/man
X11INC = /usr/X11R6/include
X11LIB = /usr/X11R6/lib
+# Xinerama, comment if you don't want it
+XINERAMALIBS = -L${X11LIB} -lXinerama
+XINERAMAFLAGS = -DXINERAMA
+
# includes and libs
-INCS = -I. -I./layouts -I${X11INC}
-LIBS = -L${X11LIB} -lX11 -lXtst
+INCS = -I. -I./layouts -I${X11INC} -I/usr/include/freetype2
+LIBS = -L${X11LIB} -lX11 -lXtst -lfontconfig -lXft ${XINERAMALIBS}
# use system flags
SVKBD_CFLAGS = ${CFLAGS}
SVKBD_LDFLAGS = ${LDFLAGS} ${LIBS}
-SVKBD_CPPFLAGS = ${CPPFLAGS} ${INCS} -DVERSION=\"VERSION\" -DLAYOUT=\"layout.$…
+SVKBD_CPPFLAGS = ${CPPFLAGS} ${INCS} -DVERSION=\"VERSION\" ${XINERAMAFLAGS} -D…
diff --git a/drw.c b/drw.c
@@ -0,0 +1,417 @@
+/* See LICENSE file for copyright and license details. */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <X11/Xlib.h>
+#include <X11/Xft/Xft.h>
+
+#include "drw.h"
+#include "util.h"
+
+#define UTF_INVALID 0xFFFD
+#define UTF_SIZ 4
+
+static const unsigned char utfbyte[UTF_SIZ + 1] = {0x80, 0, 0xC0, 0xE0, 0xF…
+static const unsigned char utfmask[UTF_SIZ + 1] = {0xC0, 0x80, 0xE0, 0xF0, 0xF…
+static const long utfmin[UTF_SIZ + 1] = { 0, 0, 0x80, 0x800, 0x100…
+static const long utfmax[UTF_SIZ + 1] = {0x10FFFF, 0x7F, 0x7FF, 0xFFFF, 0x10FF…
+
+static long
+utf8decodebyte(const char c, size_t *i)
+{
+ for (*i = 0; *i < (UTF_SIZ + 1); ++(*i))
+ if (((unsigned char)c & utfmask[*i]) == utfbyte[*i])
+ return (unsigned char)c & ~utfmask[*i];
+ return 0;
+}
+
+static size_t
+utf8validate(long *u, size_t i)
+{
+ if (!BETWEEN(*u, utfmin[i], utfmax[i]) || BETWEEN(*u, 0xD800, 0xDFFF))
+ *u = UTF_INVALID;
+ for (i = 1; *u > utfmax[i]; ++i)
+ ;
+ return i;
+}
+
+static size_t
+utf8decode(const char *c, long *u, size_t clen)
+{
+ size_t i, j, len, type;
+ long udecoded;
+
+ *u = UTF_INVALID;
+ if (!clen)
+ return 0;
+ udecoded = utf8decodebyte(c[0], &len);
+ if (!BETWEEN(len, 1, UTF_SIZ))
+ return 1;
+ for (i = 1, j = 1; i < clen && j < len; ++i, ++j) {
+ udecoded = (udecoded << 6) | utf8decodebyte(c[i], &type);
+ if (type)
+ return j;
+ }
+ if (j < len)
+ return 0;
+ *u = udecoded;
+ utf8validate(u, len);
+
+ return len;
+}
+
+Drw *
+drw_create(Display *dpy, int screen, Window root, unsigned int w, unsigned int…
+{
+ 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, scree…
+ 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)
+{
+ if (!drw)
+ return;
+
+ drw->w = w;
+ drw->h = h;
+ if (drw->drawable)
+ XFreePixmap(drw->dpy, drw->drawable);
+ drw->drawable = XCreatePixmap(drw->dpy, drw->root, w, h, DefaultDepth(…
+}
+
+void
+drw_free(Drw *drw)
+{
+ XFreePixmap(drw->dpy, drw->drawable);
+ XFreeGC(drw->dpy, drw->gc);
+ drw_fontset_free(drw->fonts);
+ free(drw);
+}
+
+/* This function is an implementation detail. Library users should use
+ * drw_fontset_create instead.
+ */
+static Fnt *
+xfont_create(Drw *drw, const char *fontname, FcPattern *fontpattern)
+{
+ Fnt *font;
+ XftFont *xfont = NULL;
+ FcPattern *pattern = NULL;
+
+ if (fontname) {
+ /* Using the pattern found at font->xfont->pattern does not yi…
+ * same substitution results as using the pattern returned by
+ * FcNameParse; using the latter results in the desired fallba…
+ * behaviour whereas the former just results in missing-charac…
+ * rectangles being drawn, at least with some fonts. */
+ if (!(xfont = XftFontOpenName(drw->dpy, drw->screen, fontname)…
+ fprintf(stderr, "error, cannot load font from name: '%…
+ return NULL;
+ }
+ if (!(pattern = FcNameParse((FcChar8 *) fontname))) {
+ fprintf(stderr, "error, cannot parse font name to patt…
+ XftFontClose(drw->dpy, xfont);
+ return NULL;
+ }
+ } else if (fontpattern) {
+ if (!(xfont = XftFontOpenPattern(drw->dpy, fontpattern))) {
+ fprintf(stderr, "error, cannot load font from pattern.…
+ return NULL;
+ }
+ } else {
+ die("no font specified.");
+ }
+
+ /* Do not allow using color fonts. This is a workaround for a BadLength
+ * error from Xft with color glyphs. Modelled on the Xterm workaround.…
+ * https://bugzilla.redhat.com/show_bug.cgi?id=1498269
+ * https://lists.suckless.org/dev/1701/30932.html
+ * https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=916349
+ * and lots more all over the internet.
+ */
+ FcBool iscol;
+ if(FcPatternGetBool(xfont->pattern, FC_COLOR, 0, &iscol) == FcResultMa…
+ XftFontClose(drw->dpy, xfont);
+ return NULL;
+ }
+
+ font = ecalloc(1, sizeof(Fnt));
+ font->xfont = xfont;
+ font->pattern = pattern;
+ font->h = xfont->ascent + xfont->descent;
+ font->dpy = drw->dpy;
+
+ return font;
+}
+
+static void
+xfont_free(Fnt *font)
+{
+ if (!font)
+ return;
+ if (font->pattern)
+ FcPatternDestroy(font->pattern);
+ XftFontClose(font->dpy, font->xfont);
+ free(font);
+}
+
+Fnt*
+drw_fontset_create(Drw* drw, const char *fonts[], size_t fontcount)
+{
+ Fnt *cur, *ret = NULL;
+ size_t i;
+
+ if (!drw || !fonts)
+ return NULL;
+
+ for (i = 1; i <= fontcount; i++) {
+ if ((cur = xfont_create(drw, fonts[fontcount - i], NULL))) {
+ cur->next = ret;
+ ret = cur;
+ }
+ }
+ return (drw->fonts = ret);
+}
+
+void
+drw_fontset_free(Fnt *font)
+{
+ if (font) {
+ drw_fontset_free(font->next);
+ xfont_free(font);
+ }
+}
+
+void
+drw_clr_create(Drw *drw, Clr *dest, const char *clrname)
+{
+ if (!drw || !dest || !clrname)
+ return;
+
+ if (!XftColorAllocName(drw->dpy, DefaultVisual(drw->dpy, drw->screen),
+ DefaultColormap(drw->dpy, drw->screen),
+ clrname, dest))
+ die("error, cannot allocate color '%s'", 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;
+
+ /* need at least two colors for a scheme */
+ if (!drw || !clrnames || clrcount < 2 || !(ret = ecalloc(clrcount, siz…
+ die("error, cannot create color scheme (drw=%d) (clrcount=%d)"…
+
+ for (i = 0; i < clrcount; i++)
+ drw_clr_create(drw, &ret[i], clrnames[i]);
+ return ret;
+}
+
+void
+drw_setfontset(Drw *drw, Fnt *set)
+{
+ if (drw)
+ drw->fonts = set;
+}
+
+void
+drw_setscheme(Drw *drw, Clr *scm)
+{
+ if (drw)
+ drw->scheme = scm;
+}
+
+void
+drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, i…
+{
+ if (!drw || !drw->scheme)
+ return;
+ XSetForeground(drw->dpy, drw->gc, invert ? drw->scheme[ColBg].pixel : …
+ if (filled)
+ XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h);
+ else
+ XDrawRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w - 1, …
+}
+
+int
+drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int …
+{
+ char buf[1024];
+ int ty;
+ unsigned int ew;
+ XftDraw *d = NULL;
+ Fnt *usedfont, *curfont, *nextfont;
+ size_t i, len;
+ int utf8strlen, utf8charlen, render = x || y || w || h;
+ long utf8codepoint = 0;
+ const char *utf8str;
+ FcCharSet *fccharset;
+ FcPattern *fcpattern;
+ FcPattern *match;
+ XftResult result;
+ int charexists = 0;
+
+ if (!drw || (render && !drw->scheme) || !text || !drw->fonts)
+ return 0;
+
+ if (!render) {
+ w = ~w;
+ } else {
+ XSetForeground(drw->dpy, drw->gc, drw->scheme[invert ? ColFg :…
+ XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h);
+ d = XftDrawCreate(drw->dpy, drw->drawable,
+ DefaultVisual(drw->dpy, drw->screen),
+ DefaultColormap(drw->dpy, drw->screen));
+ x += lpad;
+ w -= lpad;
+ }
+
+ usedfont = drw->fonts;
+ while (1) {
+ utf8strlen = 0;
+ utf8str = text;
+ nextfont = NULL;
+ while (*text) {
+ utf8charlen = utf8decode(text, &utf8codepoint, UTF_SIZ…
+ for (curfont = drw->fonts; curfont; curfont = curfont-…
+ charexists = charexists || XftCharExists(drw->…
+ if (charexists) {
+ if (curfont == usedfont) {
+ utf8strlen += utf8charlen;
+ text += utf8charlen;
+ } else {
+ nextfont = curfont;
+ }
+ break;
+ }
+ }
+
+ if (!charexists || nextfont)
+ break;
+ else
+ charexists = 0;
+ }
+
+ if (utf8strlen) {
+ drw_font_getexts(usedfont, utf8str, utf8strlen, &ew, N…
+ /* shorten text if necessary */
+ for (len = MIN(utf8strlen, sizeof(buf) - 1); len && ew…
+ drw_font_getexts(usedfont, utf8str, len, &ew, …
+
+ if (len) {
+ memcpy(buf, utf8str, len);
+ buf[len] = '\0';
+ if (len < utf8strlen)
+ for (i = len; i && i > len - 3; buf[--…
+ ; /* NOP */
+
+ if (render) {
+ ty = y + (h - usedfont->h) / 2 + usedf…
+ XftDrawStringUtf8(d, &drw->scheme[inve…
+ usedfont->xfont, x, …
+ }
+ x += ew;
+ w -= ew;
+ }
+ }
+
+ if (!*text) {
+ break;
+ } else if (nextfont) {
+ charexists = 0;
+ usedfont = nextfont;
+ } else {
+ /* Regardless of whether or not a fallback font is fou…
+ * character must be drawn. */
+ charexists = 1;
+
+ fccharset = FcCharSetCreate();
+ FcCharSetAddChar(fccharset, utf8codepoint);
+
+ if (!drw->fonts->pattern) {
+ /* Refer to the comment in xfont_create for mo…
+ die("the first font in the cache must be loade…
+ }
+
+ fcpattern = FcPatternDuplicate(drw->fonts->pattern);
+ FcPatternAddCharSet(fcpattern, FC_CHARSET, fccharset);
+ FcPatternAddBool(fcpattern, FC_SCALABLE, FcTrue);
+ FcPatternAddBool(fcpattern, FC_COLOR, FcFalse);
+
+ FcConfigSubstitute(NULL, fcpattern, FcMatchPattern);
+ FcDefaultSubstitute(fcpattern);
+ match = XftFontMatch(drw->dpy, drw->screen, fcpattern,…
+
+ FcCharSetDestroy(fccharset);
+ FcPatternDestroy(fcpattern);
+
+ if (match) {
+ usedfont = xfont_create(drw, NULL, match);
+ if (usedfont && XftCharExists(drw->dpy, usedfo…
+ for (curfont = drw->fonts; curfont->ne…
+ ; /* NOP */
+ curfont->next = usedfont;
+ } else {
+ xfont_free(usedfont);
+ usedfont = drw->fonts;
+ }
+ }
+ }
+ }
+ if (d)
+ XftDrawDestroy(d);
+
+ return x + (render ? w : 0);
+}
+
+void
+drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h)
+{
+ if (!drw)
+ return;
+
+ XCopyArea(drw->dpy, drw->drawable, win, drw->gc, x, y, w, h, x, y);
+}
+
+void
+drw_sync(Drw *drw) {
+ XSync(drw->dpy, False);
+}
+
+unsigned int
+drw_fontset_getwidth(Drw *drw, const char *text)
+{
+ if (!drw || !drw->fonts || !text)
+ return 0;
+ return drw_text(drw, 0, 0, 0, 0, 0, text, 0);
+}
+
+void
+drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *…
+{
+ XGlyphInfo ext;
+
+ if (!font || !text)
+ return;
+
+ XftTextExtentsUtf8(font->dpy, font->xfont, (XftChar8 *)text, len, &ext…
+ if (w)
+ *w = ext.xOff;
+ if (h)
+ *h = font->h;
+}
diff --git a/drw.h b/drw.h
@@ -0,0 +1,51 @@
+/* See LICENSE file for copyright and license details. */
+
+typedef struct Fnt {
+ Display *dpy;
+ unsigned int h;
+ XftFont *xfont;
+ FcPattern *pattern;
+ struct Fnt *next;
+} Fnt;
+
+enum { ColFg, ColBg }; /* Clr scheme index */
+typedef XftColor 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…
+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 …
+
+/* 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);
+
+
+/* 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 fill…
+int drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned …
+
+/* Map functions */
+void drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int …
+void drw_sync(Drw *drw);
diff --git a/layout.sxmo.h b/layout.sxmo.h
@@ -37,20 +37,20 @@ static Key keys_en[40] = {
{ 0, XK_m, 1 },
/*{ "/?", XK_slash, 1 },*/
{ "Tab", XK_Tab, 1 },
- { "<-", XK_BackSpace, 2 },
+ { "⇍ Bksp", XK_BackSpace, 2 },
{ 0 }, /* New row */
- { "Layer 2", XK_Cancel, 1},
- { "Shift", XK_Shift_L, 1 },
+ { "↺", XK_Cancel, 1},
+ { "Shft", XK_Shift_L, 1 },
/*{ "L", XK_Left, 1 },*/
- { "D", XK_Down, 1 },
- { "U", XK_Up, 1 },
+ { "↓", XK_Down, 1 },
+ { "↑", XK_Up, 1 },
/*{ "R", XK_Right, 1 },*/
{ "", XK_space, 2 },
{ "Esc", XK_Escape, 1 },
{ "Ctrl", XK_Control_L, 1 },
/*{ "Alt", XK_Alt_L, 1 },*/
- { "Enter", XK_Return, 2 },
+ { "↲ Enter", XK_Return, 2 },
};
static Key keys_symbols[40] = {
@@ -80,28 +80,28 @@ static Key keys_symbols[40] = {
{ 0 }, /* New row */
- { " ", XK_Shift_L|XK_bar, 1 },
- { " ", XK_Shift_L|XK_bar, 1 },
- { "L", XK_Left, 1 },
- { "R", XK_Right, 1 },
- { " ", XK_Shift_L|XK_bar, 1 },
- { " ", XK_Shift_L|XK_bar, 1 },
- { " ", XK_Shift_L|XK_bar, 1 },
+ { "", XK_Shift_L|XK_bar, 1 },
+ { "⇤", XK_Home, 1 },
+ { "←", XK_Left, 1 },
+ { "→", XK_Right, 1 },
+ { "⇥", XK_End, 1 },
+ { "⇊", XK_Next, 1 },
+ { "⇈", XK_Prior, 1 },
{ "Tab", XK_Tab, 1 },
- { "<-", XK_BackSpace, 2 },
+ { "⇍ Bksp", XK_BackSpace, 2 },
{ 0 }, /* New row */
- { "Layer 1", XK_Cancel, 1},
- { "Shift", XK_Shift_L, 1 },
+ { "↺", XK_Cancel, 1},
+ { "Shft", XK_Shift_L, 1 },
/*{ "L", XK_Left, 1 },*/
- { "D", XK_Down, 1 },
- { "U", XK_Up, 1 },
+ { "↓", XK_Down, 1 },
+ { "↑", XK_Up, 1 },
/*{ "R", XK_Right, 1 },*/
{ "", XK_space, 2 },
{ "Esc", XK_Escape, 1 },
{ "Ctrl", XK_Control_L, 1 },
/*{ "Alt", XK_Alt_L, 1 },*/
- { "Enter", XK_Return, 2 },
+ { "↲ Enter", XK_Return, 2 },
};
Buttonmod buttonmods[] = {
diff --git a/svkbd.c b/svkbd.c
@@ -13,16 +13,24 @@
#include <X11/Xutil.h>
#include <X11/Xproto.h>
#include <X11/extensions/XTest.h>
+#include <X11/Xft/Xft.h>
+#ifdef XINERAMA
+#include <X11/extensions/Xinerama.h>
+#endif
#include <signal.h>
#include <sys/select.h>
+#include "drw.h"
+#include "util.h"
+
+
/* macros */
-#define MAX(a, b) ((a) > (b) ? (a) : (b))
#define LENGTH(x) (sizeof x / sizeof x[0])
+#define TEXTW(X) (drw_fontset_getwidth(drw, (X)))
/* enums */
-enum { ColFG, ColBG, ColLast };
+enum { SchemeNorm, SchemePress, SchemeHighlight, SchemeLast };
enum { NetWMWindowType, NetLast };
/* typedefs */
@@ -30,22 +38,6 @@ typedef unsigned int uint;
typedef unsigned long ulong;
typedef struct {
- ulong norm[ColLast];
- ulong press[ColLast];
- ulong high[ColLast];
-
- Drawable drawable;
- GC gc;
- struct {
- int ascent;
- int descent;
- int height;
- XFontSet set;
- XFontStruct *xfont;
- } font;
-} DC; /* draw context */
-
-typedef struct {
char *label;
KeySym keysym;
uint width;
@@ -66,18 +58,15 @@ static void buttonrelease(XEvent *e);
static void cleanup(void);
static void configurenotify(XEvent *e);
static void countrows();
-static void die(const char *errstr, ...);
static void drawkeyboard(void);
static void drawkey(Key *k);
static void expose(XEvent *e);
static Key *findkey(int x, int y);
-static ulong getcolor(const char *colstr);
-static void initfont(const char *fontstr);
static void leavenotify(XEvent *e);
static void press(Key *k, KeySym mod);
static void run(void);
static void setup(void);
-static int textnw(const char *text, uint len);
+static void togglelayer();
static void unpress(Key *k, KeySym mod);
static void updatekeys();
@@ -93,8 +82,9 @@ static void (*handler[LASTEvent]) (XEvent *) = {
};
static Atom netatom[NetLast];
static Display *dpy;
-static DC dc;
+static Drw *drw;
static Window root, win;
+static Clr* scheme[SchemeLast];
static Bool running = True, isdock = False;
static KeySym pressedmod = 0;
static int rows = 0, ww = 0, wh = 0, wx = 0, wy = 0;
@@ -203,14 +193,12 @@ cleanup(void) {
XTestFakeKeyEvent(dpy, XKeysymToKeycode(dpy, keys[i].k…
}
}
- XSync(dpy, False);
- if(dc.font.set)
- XFreeFontSet(dpy, dc.font.set);
- else
- XFreeFont(dpy, dc.font.xfont);
- XFreePixmap(dpy, dc.drawable);
- XFreeGC(dpy, dc.gc);
+ for (i = 0; i < SchemeLast; i++)
+ free(scheme[i]);
+ drw_free(drw);
+ drw_sync(drw);
+ XSync(dpy, False);
XDestroyWindow(dpy, win);
XSync(dpy, False);
XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime);
@@ -223,9 +211,7 @@ configurenotify(XEvent *e) {
if(ev->window == win && (ev->width != ww || ev->height != wh)) {
ww = ev->width;
wh = ev->height;
- XFreePixmap(dpy, dc.drawable);
- dc.drawable = XCreatePixmap(dpy, root, ww, wh,
- DefaultDepth(dpy, screen));
+ drw_resize(drw, ww, wh);
updatekeys();
}
}
@@ -240,15 +226,6 @@ countrows() {
}
}
-void
-die(const char *errstr, ...) {
- va_list ap;
-
- va_start(ap, errstr);
- vfprintf(stderr, errstr, ap);
- va_end(ap);
- exit(EXIT_FAILURE);
-}
void
drawkeyboard(void) {
@@ -262,42 +239,29 @@ drawkeyboard(void) {
void
drawkey(Key *k) {
- int x, y, h, len;
- XRectangle r = { k->x, k->y, k->w, k->h};
+ int x, y, w, h;
const char *l;
- ulong *col;
if(k->pressed)
- col = dc.press;
+ drw_setscheme(drw, scheme[SchemePress]);
else if(k->highlighted)
- col = dc.high;
+ drw_setscheme(drw, scheme[SchemeHighlight]);
else
- col = dc.norm;
-
- XSetForeground(dpy, dc.gc, col[ColBG]);
- XFillRectangles(dpy, dc.drawable, dc.gc, &r, 1);
- XSetForeground(dpy, dc.gc, dc.norm[ColFG]);
- r.height -= 1;
- r.width -= 1;
- XDrawRectangles(dpy, dc.drawable, dc.gc, &r, 1);
- XSetForeground(dpy, dc.gc, col[ColFG]);
+ drw_setscheme(drw, scheme[SchemeNorm]);
+ drw_rect(drw, k->x, k->y, k->w, k->h, 1, 1);
+ drw_rect(drw, k->x, k->y, k->w, k->h, 0, 0);
+
if(k->label) {
l = k->label;
} else {
l = XKeysymToString(k->keysym);
}
- len = strlen(l);
- h = dc.font.ascent + dc.font.descent;
- y = k->y + (k->h / 2) - (h / 2) + dc.font.ascent;
- x = k->x + (k->w / 2) - (textnw(l, len) / 2);
- if(dc.font.set) {
- XmbDrawString(dpy, dc.drawable, dc.font.set, dc.gc, x, y, l,
- len);
- } else {
- XDrawString(dpy, dc.drawable, dc.gc, x, y, l, len);
- }
- XCopyArea(dpy, dc.drawable, win, dc.gc, k->x, k->y, k->w, k->h,
- k->x, k->y);
+ h = fontsize * 2;
+ y = k->y + (k->h / 2) - (h / 2);
+ w = TEXTW(l);
+ x = k->x + (k->w / 2) - (w / 2);
+ drw_text(drw, x, y, w, h, 0, l, 0);
+ drw_map(drw, win, k->x, k->y, k->w, k->h);
}
void
@@ -322,52 +286,7 @@ findkey(int x, int y) {
return NULL;
}
-ulong
-getcolor(const char *colstr) {
- Colormap cmap = DefaultColormap(dpy, screen);
- XColor color;
- if(!XAllocNamedColor(dpy, cmap, colstr, &color, &color))
- die("error, cannot allocate color '%s'\n", colstr);
- return color.pixel;
-}
-
-void
-initfont(const char *fontstr) {
- char *def, **missing;
- int i, n;
-
- missing = NULL;
- if(dc.font.set)
- XFreeFontSet(dpy, dc.font.set);
- dc.font.set = XCreateFontSet(dpy, fontstr, &missing, &n, &def);
- if(missing) {
- while(n--)
- fprintf(stderr, "svkbd: missing fontset: %s\n", missin…
- XFreeStringList(missing);
- }
- if(dc.font.set) {
- XFontStruct **xfonts;
- char **font_names;
- dc.font.ascent = dc.font.descent = 0;
- n = XFontsOfFontSet(dc.font.set, &xfonts, &font_names);
- for(i = 0, dc.font.ascent = 0, dc.font.descent = 0; i < n; i++…
- dc.font.ascent = MAX(dc.font.ascent, (*xfonts)->ascent…
- dc.font.descent = MAX(dc.font.descent,(*xfonts)->desce…
- xfonts++;
- }
- } else {
- if(dc.font.xfont)
- XFreeFont(dpy, dc.font.xfont);
- dc.font.xfont = NULL;
- if(!(dc.font.xfont = XLoadQueryFont(dpy, fontstr))
- && !(dc.font.xfont = XLoadQueryFont(dpy, "fixed")))
- die("error, cannot load font: '%s'\n", fontstr);
- dc.font.ascent = dc.font.xfont->ascent;
- dc.font.descent = dc.font.xfont->descent;
- }
- dc.font.height = dc.font.ascent + dc.font.descent;
-}
void
leavenotify(XEvent *e) {
@@ -487,15 +406,36 @@ setup(void) {
XSizeHints *sizeh = NULL;
XClassHint *ch;
Atom atype = -1;
- int i, sh, sw;
+ int i, j, sh, sw;
XWMHints *wmh;
+ #if XINERAMA
+ XineramaScreenInfo *info = NULL;
+ #endif
+
/* init screen */
screen = DefaultScreen(dpy);
root = RootWindow(dpy, screen);
- sw = DisplayWidth(dpy, screen);
- sh = DisplayHeight(dpy, screen);
- initfont(font);
+ #if XINERAMA
+ if(XineramaIsActive(dpy)) {
+ info = XineramaQueryScreens(dpy, &i);
+ sw = info[0].width;
+ sh = info[0].height;
+ XFree(info);
+ } else
+ #endif
+ {
+ sw = DisplayWidth(dpy, screen);
+ sh = DisplayHeight(dpy, screen);
+ }
+ drw = drw_create(dpy, screen, root, sw, sh);
+ if (!drw_fontset_create(drw, fonts, LENGTH(fonts)))
+ die("no fonts could be loaded.");
+ drw_setscheme(drw, scheme[SchemeNorm]);
+
+ /* init appearance */
+ for (j = 0; j < SchemeLast; j++)
+ scheme[j] = drw_scm_create(drw, colors[j], 2);
/* init atoms */
if(isdock) {
@@ -520,23 +460,12 @@ setup(void) {
if(wy < 0)
wy = sh + wy - wh;
- dc.norm[ColBG] = getcolor(normbgcolor);
- dc.norm[ColFG] = getcolor(normfgcolor);
- dc.press[ColBG] = getcolor(pressbgcolor);
- dc.press[ColFG] = getcolor(pressfgcolor);
- dc.high[ColBG] = getcolor(highlightbgcolor);
- dc.high[ColFG] = getcolor(highlightfgcolor);
- dc.drawable = XCreatePixmap(dpy, root, ww, wh,
- DefaultDepth(dpy, screen));
- dc.gc = XCreateGC(dpy, root, 0, 0);
- if(!dc.font.set)
- XSetFont(dpy, dc.gc, dc.font.xfont->fid);
for(i = 0; i < LENGTH(keys); i++)
keys[i].pressed = 0;
wa.override_redirect = !wmborder;
- wa.border_pixel = dc.norm[ColFG];
- wa.background_pixel = dc.norm[ColBG];
+ wa.border_pixel = scheme[SchemeNorm][ColFg].pixel;
+ wa.background_pixel = scheme[SchemeNorm][ColBg].pixel;
win = XCreateWindow(dpy, root, wx, wy, ww, wh, 0,
CopyFromParent, CopyFromParent, CopyFromParent,
CWOverrideRedirect | CWBorderPixel |
@@ -575,20 +504,11 @@ setup(void) {
}
XMapRaised(dpy, win);
+ drw_resize(drw, ww, wh);
updatekeys();
drawkeyboard();
}
-int
-textnw(const char *text, uint len) {
- XRectangle r;
-
- if(dc.font.set) {
- XmbTextExtents(dc.font.set, text, len, NULL, &r);
- return r.width;
- }
- return XTextWidth(dc.font.xfont, text, len);
-}
void
updatekeys() {
@@ -642,7 +562,7 @@ main(int argc, char *argv[]) {
signal(SIGTERM, sigterm);
for (i = 1; argv[i]; i++) {
if(!strcmp(argv[i], "-v")) {
- die("svkbd-"VERSION", © 2006-2016 svkbd engineers,"
+ die("svkbd-"VERSION", © 2006-2020 svkbd engineers,"
" see LICENSE for details\n");
} else if(!strcmp(argv[i], "-d")) {
isdock = True;
diff --git a/util.c b/util.c
@@ -0,0 +1,35 @@
+/* See LICENSE file for copyright and license details. */
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "util.h"
+
+void *
+ecalloc(size_t nmemb, size_t size)
+{
+ void *p;
+
+ if (!(p = calloc(nmemb, size)))
+ die("calloc:");
+ return p;
+}
+
+void
+die(const char *fmt, ...) {
+ va_list ap;
+
+ va_start(ap, fmt);
+ vfprintf(stderr, fmt, ap);
+ va_end(ap);
+
+ if (fmt[0] && fmt[strlen(fmt)-1] == ':') {
+ fputc(' ', stderr);
+ perror(NULL);
+ } else {
+ fputc('\n', stderr);
+ }
+
+ exit(1);
+}
diff --git a/util.h b/util.h
@@ -0,0 +1,8 @@
+/* See LICENSE file for copyright and license details. */
+
+#define MAX(A, B) ((A) > (B) ? (A) : (B))
+#define MIN(A, B) ((A) < (B) ? (A) : (B))
+#define BETWEEN(X, A, B) ((A) <= (X) && (X) <= (B))
+
+void die(const char *fmt, ...);
+void *ecalloc(size_t nmemb, size_t size);
You are viewing proxied material from suckless.org. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.