From e29c982243f4d1201e93ad3afcfafbf1ee7c3f25 Mon Sep 17 00:00:00 2001 From: "B. Watson" Date: Sat, 23 May 2020 01:51:39 -0400 Subject: use XKB extension instead of deprecated API --- unsaver.1 | 10 ++++------ unsaver.c | 48 ++++++++++++++++++++++++++++++++++++++++-------- unsaver.html | 13 ++++++------- unsaver.rst | 10 ++++------ 4 files changed, 54 insertions(+), 27 deletions(-) diff --git a/unsaver.1 b/unsaver.1 index 5fcf97a..623a291 100644 --- a/unsaver.1 +++ b/unsaver.1 @@ -1,6 +1,6 @@ .\" Man page generated from reStructuredText. . -.TH UNSAVER 1 "2020-05-20" "0.3.0" "Urchlay" +.TH UNSAVER 1 "2020-05-23" "0.4.0" "Urchlay" .SH NAME unsaver \- deactivate screensaver on joystick activity . @@ -102,6 +102,7 @@ Only one of \fB\-k\fP/\fB\-b\fP/\fB\-m\fP/\fB\-c\fP/\fB\-x\fP is accepted. .TP .BI \-k \ Send this keycode when activity is detected. Default +(with no \fB\-k\fP/\fB\-b\fP/\fB\-m\fP/\fB\-c\fP/\fB\-x\fP options) is to search the keymap for an unused code. If you set this manually, it should be a keycode that \fIdoesn\(aqt\fP map to a keysym in your usual keymapping (use "xmodmap \-pk" to find one). @@ -202,15 +203,12 @@ numbers (it\(aqs better to autodetect). .sp Normally once daemonized, unsaver is very robust. However, if something does go wrong, there\(aqs no way to find out what. Probably there should -be a log file, or use syslog (or is that overkill?). +be a log file, or use syslog (or is that overkill?). The best you can +do for now is run it with \-d and maybe redirect stderr to a log file. .sp It should be (but currently isn\(aqt) possible to at least work in mouse\-motion mode even without the XTest extension, via XWarpPointer(). .sp -I \fIreally\fP need to use the XKB extension rather than the old & deprecated -Xlib keyboard API. This mainly affects the default "find an unused -keycode" mode. -.sp unsaver isn\(aqt portable. It only works on Linux, at least for now, for three reasons: .INDENT 0.0 diff --git a/unsaver.c b/unsaver.c index ec502df..2cba2dc 100644 --- a/unsaver.c +++ b/unsaver.c @@ -17,6 +17,7 @@ #include #include +#include #include #include @@ -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", diff --git a/unsaver.html b/unsaver.html index 17188e3..e64c712 100644 --- a/unsaver.html +++ b/unsaver.html @@ -5,7 +5,7 @@ unsaver - +