suckless/slstatus

components/keymap.c in master
Repositories | Summary | Log | Files | README | LICENSE

keymap.c (1867B) download


 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
11static int
12valid_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
25static char *
26get_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
47const char *
48keymap(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);
80end:
81	XkbFreeKeyboard(desc, XkbSymbolsNameMask, 1);
82	if (XCloseDisplay(dpy))
83		warn("XCloseDisplay: Failed to close display");
84
85	return layout;
86}