From 359f59aef558076fb5519cfec6a7cd64339ee260 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Sat, 1 Oct 2016 14:22:10 -0700 Subject: [PATCH] Fixed bug 3130 - Spacebar not responding Alex Baines Make sure group is valid before passing it to XkbKeysymToKeycode. --- src/video/x11/SDL_x11keyboard.c | 44 ++++++++++++++++++++++++++++++--- src/video/x11/SDL_x11sym.h | 3 +++ src/video/x11/SDL_x11video.h | 4 +++ 3 files changed, 47 insertions(+), 4 deletions(-) diff --git a/src/video/x11/SDL_x11keyboard.c b/src/video/x11/SDL_x11keyboard.c index e16d9f178518b..4e7a848321a8c 100644 --- a/src/video/x11/SDL_x11keyboard.c +++ b/src/video/x11/SDL_x11keyboard.c @@ -179,14 +179,36 @@ X11_KeyCodeToSDLScancode(Display *display, KeyCode keycode) } static Uint32 -X11_KeyCodeToUcs4(Display *display, KeyCode keycode, unsigned char group) +X11_KeyCodeToUcs4(SDL_VideoData *data, KeyCode keycode, unsigned char group) { KeySym keysym; #if SDL_VIDEO_DRIVER_X11_HAS_XKBKEYCODETOKEYSYM - keysym = X11_XkbKeycodeToKeysym(display, keycode, group, 0); + if (data->xkb) { + int num_groups = XkbKeyNumGroups(data->xkb, keycode); + unsigned char info = XkbKeyGroupInfo(data->xkb, keycode); + + if (num_groups && group >= num_groups) { + + int action = XkbOutOfRangeGroupAction(info); + + if (action == XkbRedirectIntoRange) { + if ((group = XkbOutOfRangeGroupNumber(info)) >= num_groups) { + group = 0; + } + } else if (action == XkbClampIntoRange) { + group = num_groups - 1; + } else { + group %= num_groups; + } + } + } else { + group = 0; + } + + keysym = X11_XkbKeycodeToKeysym(data->display, keycode, group, 0); #else - keysym = X11_XKeycodeToKeysym(display, keycode, 0); + keysym = X11_XKeycodeToKeysym(data->display, keycode, 0); #endif if (keysym == NoSymbol) { return 0; @@ -308,6 +330,12 @@ X11_UpdateKeymap(_THIS) #if SDL_VIDEO_DRIVER_X11_HAS_XKBKEYCODETOKEYSYM { + if (data->xkb) { + X11_XkbGetUpdatedMap(data->display, XkbAllClientInfoMask, data->xkb); + } else { + data->xkb = X11_XkbGetMap(data->display, XkbAllClientInfoMask, XkbUseCoreKbd); + } + XkbStateRec state; if (X11_XkbGetState(data->display, XkbUseCoreKbd, &state) == Success) { group = state.group; @@ -326,7 +354,7 @@ X11_UpdateKeymap(_THIS) } /* See if there is a UCS keycode for this scancode */ - key = X11_KeyCodeToUcs4(data->display, (KeyCode)i, group); + key = X11_KeyCodeToUcs4(data, (KeyCode)i, group); if (key) { keymap[scancode] = key; } else { @@ -360,6 +388,14 @@ X11_UpdateKeymap(_THIS) void X11_QuitKeyboard(_THIS) { + SDL_VideoData *data = (SDL_VideoData *) _this->driverdata; + +#if SDL_VIDEO_DRIVER_X11_HAS_XKBKEYCODETOKEYSYM + if (data->xkb) { + X11_XkbFreeClientMap(data->xkb, 0, True); + } +#endif + #ifdef SDL_USE_IBUS SDL_IBus_Quit(); #endif diff --git a/src/video/x11/SDL_x11sym.h b/src/video/x11/SDL_x11sym.h index 1caf383a88749..d3af2aff1e1c1 100644 --- a/src/video/x11/SDL_x11sym.h +++ b/src/video/x11/SDL_x11sym.h @@ -175,6 +175,9 @@ SDL_X11_SYM(KeySym,XkbKeycodeToKeysym,(Display* a,unsigned int b,int c,int d),(a SDL_X11_SYM(KeySym,XkbKeycodeToKeysym,(Display* a,KeyCode b,int c,int d),(a,b,c,d),return) #endif SDL_X11_SYM(Status,XkbGetState,(Display* a,unsigned int b,XkbStatePtr c),(a,b,c),return) +SDL_X11_SYM(Status,XkbGetUpdatedMap,(Display* a,unsigned int b,XkbDescPtr c),(a,b,c),return) +SDL_X11_SYM(XkbDescPtr,XkbGetMap,(Display* a,unsigned int b,unsigned int c),(a,b,c),return) +SDL_X11_SYM(void,XkbFreeClientMap,(XkbDescPtr a,unsigned int b, Bool c),(a,b,c),) #endif #if NeedWidePrototypes diff --git a/src/video/x11/SDL_x11video.h b/src/video/x11/SDL_x11video.h index 912cf483e7a71..d5b82447feace 100644 --- a/src/video/x11/SDL_x11video.h +++ b/src/video/x11/SDL_x11video.h @@ -129,6 +129,10 @@ typedef struct SDL_VideoData SDL_bool global_mouse_changed; SDL_Point global_mouse_position; Uint32 global_mouse_buttons; + +#if SDL_VIDEO_DRIVER_X11_HAS_XKBKEYCODETOKEYSYM + XkbDescPtr xkb; +#endif } SDL_VideoData; extern SDL_bool X11_UseDirectColorVisuals(void);