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.
This commit is contained in:
Denis Bernard 2019-05-30 00:37:26 +02:00
parent 3a5e99e59a
commit 594a8dc350
3 changed files with 28 additions and 10 deletions

View File

@ -54,7 +54,7 @@ static int translateKeyCode(int scancode)
// Note: This way we always force "NumLock = ON", which is intentional // Note: This way we always force "NumLock = ON", which is intentional
// since the returned key code should correspond to a physical // since the returned key code should correspond to a physical
// location. // location.
keySym = XkbKeycodeToKeysym(_glfw.x11.display, scancode, 0, 1); keySym = XkbKeycodeToKeysym(_glfw.x11.display, scancode, _glfw.x11.xkb.group, 1);
switch (keySym) switch (keySym)
{ {
case XK_KP_0: return GLFW_KEY_KP_0; 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) // Now try primary keysym for function keys (non-printable keys)
// These should not depend on the current keyboard layout // 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 else
{ {
@ -659,6 +659,14 @@ static GLFWbool initExtensions(void)
if (supported) if (supported)
_glfw.x11.xkb.detectable = GLFW_TRUE; _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__) #if defined(__CYGWIN__)

View File

@ -323,13 +323,14 @@ typedef struct _GLFWlibraryX11
} randr; } randr;
struct { struct {
GLFWbool available; GLFWbool available;
GLFWbool detectable; GLFWbool detectable;
int majorOpcode; int majorOpcode;
int eventBase; int eventBase;
int errorBase; int errorBase;
int major; int major;
int minor; int minor;
unsigned int group;
} xkb; } xkb;
struct { struct {

View File

@ -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 (event->type == GenericEvent)
{ {
if (_glfw.x11.xi.available) if (_glfw.x11.xi.available)
@ -2780,7 +2789,7 @@ const char* _glfwPlatformGetScancodeName(int scancode)
if (!_glfw.x11.xkb.available) if (!_glfw.x11.xkb.available)
return NULL; 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) if (keysym == NoSymbol)
return NULL; return NULL;