slstatus

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

keymap.c (1863B)


      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, *layout;
     54 
     55 	layout = NULL;
     56 
     57 	if (!(dpy = XOpenDisplay(NULL))) {
     58 		warn("XOpenDisplay: Failed to open display");
     59 		return NULL;
     60 	}
     61 	if (!(desc = XkbAllocKeyboard())) {
     62 		warn("XkbAllocKeyboard: Failed to allocate keyboard");
     63 		goto end;
     64 	}
     65 	if (XkbGetNames(dpy, XkbSymbolsNameMask, desc)) {
     66 		warn("XkbGetNames: Failed to retrieve key symbols");
     67 		goto end;
     68 	}
     69 	if (XkbGetState(dpy, XkbUseCoreKbd, &state)) {
     70 		warn("XkbGetState: Failed to retrieve keyboard state");
     71 		goto end;
     72 	}
     73 	if (!(symbols = XGetAtomName(dpy, desc->names->symbols))) {
     74 		warn("XGetAtomName: Failed to get atom name");
     75 		goto end;
     76 	}
     77 	layout = (char *)bprintf("%s", get_layout(symbols, state.group));
     78 	XFree(symbols);
     79 end:
     80 	XkbFreeKeyboard(desc, XkbSymbolsNameMask, 1);
     81 	if (XCloseDisplay(dpy))
     82 		warn("XCloseDisplay: Failed to close display");
     83 
     84 	return layout;
     85 }