# HG changeset patch # User Alex Baines # Date 1443642381 -3600 # Wed Sep 30 20:46:21 2015 +0100 # Node ID c74cf9e30de6b7134bce63a25954207d0c7fd6ee # Parent e4607152d80a43a971f696430e6036700354e05a Make sure group is valid before passing it to XkbKeysymToKeycode. diff -r e4607152d80a -r c74cf9e30de6 src/video/x11/SDL_x11keyboard.c --- a/src/video/x11/SDL_x11keyboard.c Wed Sep 30 04:16:09 2015 +0100 +++ b/src/video/x11/SDL_x11keyboard.c Wed Sep 30 20:46:21 2015 +0100 @@ -178,14 +178,35 @@ } 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); + + int action = XkbOutOfRangeGroupAction(info); + + if (action == XkbRedirectIntoRange) { + if ((group = XkbOutOfRangeGroupInfo(info)) > num_groups) { + group = 0; + } + } else if (action == XkbClampIntoRange) { + group = num_groups - 1; + } else { + if (num_groups) { + 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; @@ -307,6 +328,12 @@ #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; @@ -325,7 +352,7 @@ } /* 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 { @@ -359,6 +386,14 @@ 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 -r e4607152d80a -r c74cf9e30de6 src/video/x11/SDL_x11sym.h --- a/src/video/x11/SDL_x11sym.h Wed Sep 30 04:16:09 2015 +0100 +++ b/src/video/x11/SDL_x11sym.h Wed Sep 30 20:46:21 2015 +0100 @@ -166,6 +166,9 @@ 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 -r e4607152d80a -r c74cf9e30de6 src/video/x11/SDL_x11video.h --- a/src/video/x11/SDL_x11video.h Wed Sep 30 04:16:09 2015 +0100 +++ b/src/video/x11/SDL_x11video.h Wed Sep 30 20:46:21 2015 +0100 @@ -117,6 +117,11 @@ SDL_bool selection_waiting; Uint32 last_mode_change_deadline; + +#if SDL_VIDEO_DRIVER_X11_HAS_XKBKEYCODETOKEYSYM + XkbDescPtr xkb; +#endif + } SDL_VideoData; extern SDL_bool X11_UseDirectColorVisuals(void);