all repos — slstatus @ 943b42de05cc3328ea74b0d9f527f17e1fcf47e7

my build of slstatus (tools.suckless.org/slstatus/)

Add keymap component

Adding a new keymap component that will
indicate the current keyboard layout (language)
and variant if any was set. I use the
standard X11 XKB APIs to retrieve and parse
the xkb_symbols set with setxkbmap.
Michael Buch michaelbuch12@gmail.com
Wed, 23 May 2018 07:16:30 +0100
commit

943b42de05cc3328ea74b0d9f527f17e1fcf47e7

parent

57f69e900bf7e3e7c60a720bf09f2134b724c5cc

4 files changed, 103 insertions(+), 0 deletions(-)

jump to
M MakefileMakefile

@@ -16,6 +16,7 @@ components/hostname\

components/ip\ components/kernel_release\ components/keyboard_indicators\ + components/keymap\ components/load_avg\ components/netspeeds\ components/num_files\
A components/keymap.c

@@ -0,0 +1,97 @@

+/* 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; +}
M config.def.hconfig.def.h

@@ -34,6 +34,8 @@ * ipv4 IPv4 address interface name (eth0)

* ipv6 IPv6 address interface name (eth0) * kernel_release `uname -r` NULL * keyboard_indicators caps/num lock indicators NULL + * keymap layout (variant) of current NULL + * keymap * load_avg load average NULL * netspeed_rx receive network speed interface name (wlan0) * netspeed_tx transfer network speed interface name (wlan0)
M slstatus.hslstatus.h

@@ -37,6 +37,9 @@

/* keyboard_indicators */ const char *keyboard_indicators(void); +/* keymap */ +const char *keymap(void); + /* load_avg */ const char *load_avg(const char *);