slstatus

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

keymap.c (1840B)


      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 "../util.h"
      9 
     10 static int
     11 valid_layout_or_variant(char *sym)
     12 {
     13 	size_t i;
     14 	/* invalid symbols from xkb rules config */
     15 	static const char *invalid[] = { "evdev", "inet", "pc", "base" };
     16 
     17 	for (i = 0; i < LEN(invalid); i++) {
     18 		if (!strncmp(sym, invalid[i], strlen(invalid[i]))) {
     19 			return 0;
     20 		}
     21 	}
     22 
     23 	return 1;
     24 }
     25 
     26 static char *
     27 get_layout(char *syms, int grp_num)
     28 {
     29 	char *tok, *layout;
     30 	int grp;
     31 
     32 	layout = NULL;
     33 	tok = strtok(syms, "+:");
     34 	for (grp = 0; tok && grp <= grp_num; tok = strtok(NULL, "+:")) {
     35 		if (!valid_layout_or_variant(tok)) {
     36 			continue;
     37 		} else if (strlen(tok) == 1 && isdigit(tok[0])) {
     38 			/* ignore :2, :3, :4 (additional layout groups) */
     39 			continue;
     40 		}
     41 		layout = tok;
     42 		grp++;
     43 	}
     44 
     45 	return layout;
     46 }
     47 
     48 const char *
     49 keymap(void)
     50 {
     51 	Display *dpy;
     52 	XkbDescRec *desc;
     53 	XkbStateRec state;
     54 	char *symbols, *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 = (char *)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 
     86 	return layout;
     87 }