keymap.c (1867B)
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 11 static int 12 valid_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 25 static char * 26 get_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 47 const char * 48 keymap(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); 80 end: 81 XkbFreeKeyboard(desc, XkbSymbolsNameMask, 1); 82 if (XCloseDisplay(dpy)) 83 warn("XCloseDisplay: Failed to close display"); 84 85 return layout; 86 }