Xinqi Bao's Git

ram: Consistency with line breaks
[slstatus.git] / components / keymap.c
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 }