slstatus

status monitor
git clone git://git.suckless.org/slstatus
Log | Files | Refs | README | LICENSE

keymap.c (1867B)


      1 /* See LICENSE file for copyright and license details. */
      2 #include <ctype.h>
      3 #include <stdlib.h>
      4 #include <string.h>
      5 #include <X11/XKBlib.h>
      6 #include <X11/Xlib.h>
      7 
      8 #include "../slstatus.h"
      9 #include "../util.h"
     10 
     11 static int
     12 valid_layout_or_variant(char *sym)
     13 {
     14 	size_t i;
     15 	/* invalid symbols from xkb rules config */
     16 	static const char *invalid[] = { "evdev", "inet", "pc", "base" };
     17 
     18 	for (i = 0; i < LEN(invalid); i++)
     19 		if (!strncmp(sym, invalid[i], strlen(invalid[i])))
     20 			return 0;
     21 
     22 	return 1;
     23 }
     24 
     25 static char *
     26 get_layout(char *syms, int grp_num)
     27 {
     28 	char *tok, *layout;
     29 	int grp;
     30 
     31 	layout = NULL;
     32 	tok = strtok(syms, "+:");
     33 	for (grp = 0; tok && grp <= grp_num; tok = strtok(NULL, "+:")) {
     34 		if (!valid_layout_or_variant(tok)) {
     35 			continue;
     36 		} else if (strlen(tok) == 1 && isdigit(tok[0])) {
     37 			/* ignore :2, :3, :4 (additional layout groups) */
     38 			continue;
     39 		}
     40 		layout = tok;
     41 		grp++;
     42 	}
     43 
     44 	return layout;
     45 }
     46 
     47 const char *
     48 keymap(const char *unused)
     49 {
     50 	Display *dpy;
     51 	XkbDescRec *desc;
     52 	XkbStateRec state;
     53 	char *symbols;
     54 	const char *layout;
     55 
     56 	layout = NULL;
     57 
     58 	if (!(dpy = XOpenDisplay(NULL))) {
     59 		warn("XOpenDisplay: Failed to open display");
     60 		return NULL;
     61 	}
     62 	if (!(desc = XkbAllocKeyboard())) {
     63 		warn("XkbAllocKeyboard: Failed to allocate keyboard");
     64 		goto end;
     65 	}
     66 	if (XkbGetNames(dpy, XkbSymbolsNameMask, desc)) {
     67 		warn("XkbGetNames: Failed to retrieve key symbols");
     68 		goto end;
     69 	}
     70 	if (XkbGetState(dpy, XkbUseCoreKbd, &state)) {
     71 		warn("XkbGetState: Failed to retrieve keyboard state");
     72 		goto end;
     73 	}
     74 	if (!(symbols = XGetAtomName(dpy, desc->names->symbols))) {
     75 		warn("XGetAtomName: Failed to get atom name");
     76 		goto end;
     77 	}
     78 	layout = bprintf("%s", get_layout(symbols, state.group));
     79 	XFree(symbols);
     80 end:
     81 	XkbFreeKeyboard(desc, XkbSymbolsNameMask, 1);
     82 	if (XCloseDisplay(dpy))
     83 		warn("XCloseDisplay: Failed to close display");
     84 
     85 	return layout;
     86 }