[hackers] [slstatus][PATCH keymap 1/2] Add keymap component

From: <michaelbuch12_AT_gmail.com>
Date: Tue, 22 May 2018 22:50:19 +0100

From: Michael Buch <michaelbuch12_AT_gmail.com>

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.
---
 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.0
Received 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