--- Makefile | 2 +- components/keymap.c | 96 +++++++++++++++++++++++++++++++++++++++++++++ config.def.h | 2 + slstatus.h | 6 +-- 4 files changed, 102 insertions(+), 4 deletions(-) create mode 100644 components/keymap.c diff --git a/Makefile b/Makefile index 8e18969..c7b9d0c 100644 --- a/Makefile +++ b/Makefile _AT_@ -6,7 +6,6 @@ include config.mk REQ = util COM =\ - components/backlight\ components/battery\ components/cpu\ components/datetime\ _AT_@ -15,6 +14,7 @@ COM =\ components/hostname\ components/ip\ components/kernel_release\ + components/keymap\ components/keyboard_indicators\ components/load_avg\ components/netspeeds\ diff --git a/components/keymap.c b/components/keymap.c new file mode 100644 index 0000000..67d605e --- /dev/null +++ b/components/keymap.c _AT_@ -0,0 +1,96 @@ +/* See LICENSE file for copyright and license details. */ +#include <ctype.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. + */ +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; +} + +/* Given a xkb_symbols string (syms) retrieve + * and populate the provided layout and variant + * strings + */ +void +GetKeyLayout(char *syms, char layout[], int groupNum) +{ + char *token, + *copy, + *delims = "+:"; + int 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); + } +} + +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; + } + + desc = XkbAllocKeyboard(); + if (!desc) { + warn("XkbGetNames: failed to get XkbSymbolsNameMask keyboard component"); + 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; +} diff --git a/config.def.h b/config.def.h index 45320a3..33da6a4 100644 --- a/config.def.h +++ b/config.def.h _AT_@ -34,6 +34,8 @@ static const char unknown_str[] = "n/a"; * ipv6 IPv6 address interface name (eth0) * kernel_release `uname -r` NULL * keyboard_indicators caps/num lock indicators NULL + * keymap layout (variant) of current NULL + * keyboard * load_avg load average NULL * netspeed_rx receive network speed interface name (wlan0) * netspeed_tx transfer network speed interface name (wlan0) diff --git a/slstatus.h b/slstatus.h index a18b881..079a8db 100644 --- a/slstatus.h +++ b/slstatus.h _AT_@ -1,8 +1,5 @@ /* See LICENSE file for copyright and license details. */ -/* backlight */ -const char *backlight_perc(const char *); - /* battery */ const char *battery_perc(const char *); const char *battery_state(const char *); _AT_@ -37,6 +34,9 @@ const char *kernel_release(void); /* keyboard_indicators */ const char *keyboard_indicators(void); +/* keymap */ +const char *keymap(void); + /* load_avg */ const char *load_avg(const char *); -- 2.17.0Received on Tue May 22 2018 - 23:50:19 CEST
This archive was generated by hypermail 2.3.0 : Wed May 23 2018 - 00:00:27 CEST