Xinqi Bao's Git

358a2cab64b7d15026bb07806c645ff27c642c9a
[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 #define LAYOUT_MAX 256
11
12 /* Given a token (sym) from the xkb_symbols string
13 * check whether it is a valid layout/variant. The
14 * EXCLUDES array contains invalid layouts/variants
15 * that are part of the xkb rules config.
16 */
17 static int
18 IsLayoutOrVariant(char *sym)
19 {
20 static const char* EXCLUDES[] = { "evdev", "inet", "pc", "base" };
21
22 size_t i;
23 for (i = 0; i < sizeof(EXCLUDES)/sizeof(EXCLUDES[0]); ++i)
24 if (strstr(sym, EXCLUDES[i])) {
25 return 0;
26 }
27
28 return 1;
29 }
30
31 static void
32 GetKeyLayout(char *syms, char layout[], int groupNum)
33 {
34 char *token, *copy, *delims;
35 int group;
36
37 delims = "+:";
38 group = 0;
39 copy = strdup(syms);
40 token = strtok(copy, delims);
41 while (token != NULL && group <= groupNum) {
42 /* Ignore :2,:3,:4 which represent additional layout
43 * groups
44 */
45 if (IsLayoutOrVariant(token)
46 && !(strlen(token) == 1 && isdigit(token[0]))) {
47 strncpy (layout, token, LAYOUT_MAX);
48 group++;
49 }
50
51 token = strtok(NULL,delims);
52 }
53
54 free(copy);
55 }
56
57 const char *
58 keymap(void)
59 {
60 static char layout[LAYOUT_MAX];
61
62 Display *dpy;
63 char *symbols = NULL;
64 XkbDescRec* desc = NULL;
65
66 memset(layout, '\0', LAYOUT_MAX);
67
68 if (!(dpy = XOpenDisplay(NULL))) {
69 warn("XOpenDisplay: Failed to open display");
70 return NULL;
71 }
72
73 ;
74 if (!(desc = XkbAllocKeyboard())) {
75 warn("XkbAllocKeyboard: failed to allocate keyboard");
76 XCloseDisplay(dpy);
77 return NULL;
78 }
79
80 XkbGetNames(dpy, XkbSymbolsNameMask, desc);
81 if (desc->names) {
82 XkbStateRec state;
83 XkbGetState(dpy, XkbUseCoreKbd, &state);
84
85 symbols = XGetAtomName(dpy, desc->names->symbols);
86 GetKeyLayout(symbols, layout, state.group);
87 XFree(symbols);
88 } else {
89 warn("XkbGetNames: failed to retrieve symbols for keys");
90 return NULL;
91 }
92
93 XkbFreeKeyboard(desc, XkbSymbolsNameMask, 1);
94 XCloseDisplay(dpy);
95
96 return layout;
97 }