aboutsummaryrefslogtreecommitdiff
path: root/unsaver.c
diff options
context:
space:
mode:
Diffstat (limited to 'unsaver.c')
-rw-r--r--unsaver.c48
1 files changed, 40 insertions, 8 deletions
diff --git a/unsaver.c b/unsaver.c
index ec502df..2cba2dc 100644
--- a/unsaver.c
+++ b/unsaver.c
@@ -17,6 +17,7 @@
#include <X11/X.h>
#include <X11/Xlib.h>
+#include <X11/XKBlib.h>
#include <X11/extensions/XTest.h>
#include <linux/joystick.h>
@@ -661,31 +662,62 @@ void connect_to_x(void) {
}
}
-/* XXX: XKeycodeToKeysym() is deprecated. I must learn XKB. */
+/* XKeycodeToKeysym() is deprecated, hence the pragma fugliness.
+ Deprecated or not, the xmodmap command still uses it, and it
+ still works. However, XKB is the new hotness, we'll use that if
+ it's available. */
+KeySym keycode_is_mapped(XkbDescPtr xkbd, int i) {
+ if(xkbd) {
+ return XkbKeyNumGroups(xkbd, i) > 0;
+ } else {
+ /* if xkbd is NULL, the caller failed to init XKB. */
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
-KeySym get_keysym(int i) {
- return XKeycodeToKeysym(xdisp, i, 0);
-}
+ return XKeycodeToKeysym(xdisp, i, 0) != NoSymbol;
#pragma GCC diagnostic pop
+ }
+}
-/* the goggles, they do nothing! */
+/* The goggles, they do nothing!
+ Find an unused keycode in the keymap. From the shell, this would
+ be something like: xmodmap -pke|grep '= *$'|head -1 */
void find_keycode() {
- int i, min_code = 0, max_code = 0;
-
+ int i, ignoreme, min_code = 0, max_code = 0;
+ int major = XkbMajorVersion, minor = XkbMinorVersion;
+ XkbDescPtr xkbd = NULL;
+
+ /* not sure any X server still running on planet Earth will lack
+ the XKB extension, but in case I'm wrong... */
+ if(XkbQueryExtension(
+ xdisp,
+ &ignoreme,
+ &ignoreme,
+ &ignoreme,
+ &major,
+ &minor))
+ {
+ xkbd = XkbGetMap(xdisp, XkbAllClientInfoMask, XkbUseCoreKbd);
+ fprintf(stderr, "using XKB extension major %d, minor %d\n", major, minor);
+ } else {
+ fprintf(stderr, "XKB extension not supported, fall back to XKeycodeToKeysym\n");
+ }
+
/* man page doesn't document the return value */
(void)XDisplayKeycodes(xdisp, &min_code, &max_code);
if(debug) fprintf(stderr, "XDisplayKeycodes min %d, max %d\n", min_code, max_code);
for(i = min_code; i <= max_code; i++) {
- if(get_keysym(i) == NoSymbol) {
+ if(!keycode_is_mapped(xkbd, i)) {
keycode = i;
if(debug) fprintf(stderr, "using keycode %d\n", keycode);
break;
}
}
+ if(xkbd)
+ XkbFreeKeyboard(xkbd, XkbAllClientInfoMask, 1);
+
if(keycode < 0) {
fprintf(stderr,
"%s: can't find a free keycode in the keymap, using %d\n",