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}