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
88
89
90
91
92
93
94
95
96
97
98
/* 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" #define LAYOUT_MAX 256 /* Given a token (sym) from the xkb_symbols string * check whether it is a valid layout/variant. The * EXCLUDES array contains invalid layouts/variants * that are part of the xkb rules config. */ static int IsLayoutOrVariant(char *sym) { static const char* EXCLUDES[] = { "evdev", "inet", "pc", "base" }; size_t i; for (i = 0; i < sizeof(EXCLUDES)/sizeof(EXCLUDES[0]); ++i) { if (strstr(sym, EXCLUDES[i])) { return 0; } } return 1; } static void GetKeyLayout(char *syms, char layout[], int groupNum) { char *token, *copy, *delims; int group; delims = "+:"; group = 0; copy = strdup(syms); token = strtok(copy, delims); while (token != NULL && group <= groupNum) { /* Ignore :2,:3,:4 which represent additional layout * groups */ if (IsLayoutOrVariant(token) && !(strlen(token) == 1 && isdigit(token[0]))) { strncpy (layout, token, LAYOUT_MAX); group++; } token = strtok(NULL,delims); } free(copy); } const char * keymap(void) { static char layout[LAYOUT_MAX]; Display *dpy; char *symbols = NULL; XkbDescRec* desc = NULL; memset(layout, '\0', LAYOUT_MAX); if (!(dpy = XOpenDisplay(NULL))) { warn("XOpenDisplay: Failed to open display"); return NULL; } ; if (!(desc = XkbAllocKeyboard())) { warn("XkbAllocKeyboard: failed to allocate keyboard"); XCloseDisplay(dpy); return NULL; } XkbGetNames(dpy, XkbSymbolsNameMask, desc); if (desc->names) { XkbStateRec state; XkbGetState(dpy, XkbUseCoreKbd, &state); symbols = XGetAtomName(dpy, desc->names->symbols); GetKeyLayout(symbols, layout, state.group); XFree(symbols); } else { warn("XkbGetNames: failed to retrieve symbols for keys"); return NULL; } XkbFreeKeyboard(desc, XkbSymbolsNameMask, 1); XCloseDisplay(dpy); return layout; }