From 594a8dc3509a0cf92f40aa107ce480d3e3b13dca Mon Sep 17 00:00:00 2001 From: Denis Bernard Date: Thu, 30 May 2019 00:37:26 +0200 Subject: [PATCH] Query and keep track of Xkb group index Ubuntu 18.04: for users with multiple keyboard layouts configured, glfwGetKeyName works fine only with the primary layout. Switching layouts results in changing the group index. This commit querries the current group index when initializing keyboard input and keeps track of any change to it. As a result the scancode -> keyname mapping may change while the program is running (needs to be documented). This needs to be tested on other linux distros. --- src/x11_init.c | 12 ++++++++++-- src/x11_platform.h | 15 ++++++++------- src/x11_window.c | 11 ++++++++++- 3 files changed, 28 insertions(+), 10 deletions(-) diff --git a/src/x11_init.c b/src/x11_init.c index 9d072ab47..ae76d36be 100644 --- a/src/x11_init.c +++ b/src/x11_init.c @@ -54,7 +54,7 @@ static int translateKeyCode(int scancode) // Note: This way we always force "NumLock = ON", which is intentional // since the returned key code should correspond to a physical // location. - keySym = XkbKeycodeToKeysym(_glfw.x11.display, scancode, 0, 1); + keySym = XkbKeycodeToKeysym(_glfw.x11.display, scancode, _glfw.x11.xkb.group, 1); switch (keySym) { case XK_KP_0: return GLFW_KEY_KP_0; @@ -76,7 +76,7 @@ static int translateKeyCode(int scancode) // Now try primary keysym for function keys (non-printable keys) // These should not depend on the current keyboard layout - keySym = XkbKeycodeToKeysym(_glfw.x11.display, scancode, 0, 0); + keySym = XkbKeycodeToKeysym(_glfw.x11.display, scancode, _glfw.x11.xkb.group, 0); } else { @@ -659,6 +659,14 @@ static GLFWbool initExtensions(void) if (supported) _glfw.x11.xkb.detectable = GLFW_TRUE; } + + _glfw.x11.xkb.group = 0; + XkbStateRec state; + if (XkbGetState(_glfw.x11.display, XkbUseCoreKbd, &state) == Success) + { + XkbSelectEventDetails(_glfw.x11.display, XkbUseCoreKbd, XkbStateNotify, XkbAllStateComponentsMask, XkbGroupStateMask); + _glfw.x11.xkb.group = (unsigned int)state.group; + } } #if defined(__CYGWIN__) diff --git a/src/x11_platform.h b/src/x11_platform.h index 8bdab83f2..dbbe9d1ff 100644 --- a/src/x11_platform.h +++ b/src/x11_platform.h @@ -323,13 +323,14 @@ typedef struct _GLFWlibraryX11 } randr; struct { - GLFWbool available; - GLFWbool detectable; - int majorOpcode; - int eventBase; - int errorBase; - int major; - int minor; + GLFWbool available; + GLFWbool detectable; + int majorOpcode; + int eventBase; + int errorBase; + int major; + int minor; + unsigned int group; } xkb; struct { diff --git a/src/x11_window.c b/src/x11_window.c index db7ab19c5..1670d4785 100644 --- a/src/x11_window.c +++ b/src/x11_window.c @@ -1180,6 +1180,15 @@ static void processEvent(XEvent *event) } } + if (_glfw.x11.xkb.available && event->type == _glfw.x11.xkb.eventBase) + { + if (((XkbEvent *)event)->any.xkb_type == XkbStateNotify && + ((XkbEvent *)event)->state.changed & XkbGroupStateMask) + { + _glfw.x11.xkb.group = ((XkbEvent *)event)->state.group; + } + } + if (event->type == GenericEvent) { if (_glfw.x11.xi.available) @@ -2780,7 +2789,7 @@ const char* _glfwPlatformGetScancodeName(int scancode) if (!_glfw.x11.xkb.available) return NULL; - const KeySym keysym = XkbKeycodeToKeysym(_glfw.x11.display, scancode, 0, 0); + const KeySym keysym = XkbKeycodeToKeysym(_glfw.x11.display, scancode, _glfw.x11.xkb.group, 0); if (keysym == NoSymbol) return NULL;