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