mirror of https://github.com/libsdl-org/SDL
x11: Add keymap support
XkbKeycodeToKeySym is replaced with XkbLookupKeySym, which can take the modifier states. The associated cmake check has been renamed for consistency. Only the XKB path is currently handled. The deprecated XKeycodeToKeysym path is TODO.
This commit is contained in:
parent
c874a78ffb
commit
974bbea20b
|
@ -371,7 +371,7 @@ macro(CheckX11)
|
||||||
set(SDL_VIDEO_DRIVER_X11_SUPPORTS_GENERIC_EVENTS 1)
|
set(SDL_VIDEO_DRIVER_X11_SUPPORTS_GENERIC_EVENTS 1)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
check_symbol_exists(XkbKeycodeToKeysym "X11/Xlib.h;X11/XKBlib.h" SDL_VIDEO_DRIVER_X11_HAS_XKBKEYCODETOKEYSYM)
|
check_symbol_exists(XkbLookupKeySym "X11/Xlib.h;X11/XKBlib.h" SDL_VIDEO_DRIVER_X11_HAS_XKBLOOKUPKEYSYM)
|
||||||
|
|
||||||
if(SDL_X11_XCURSOR AND HAVE_XCURSOR_H AND XCURSOR_LIB)
|
if(SDL_X11_XCURSOR AND HAVE_XCURSOR_H AND XCURSOR_LIB)
|
||||||
set(HAVE_X11_XCURSOR TRUE)
|
set(HAVE_X11_XCURSOR TRUE)
|
||||||
|
|
|
@ -400,7 +400,7 @@
|
||||||
#cmakedefine SDL_VIDEO_DRIVER_X11_DYNAMIC_XINPUT2 @SDL_VIDEO_DRIVER_X11_DYNAMIC_XINPUT2@
|
#cmakedefine SDL_VIDEO_DRIVER_X11_DYNAMIC_XINPUT2 @SDL_VIDEO_DRIVER_X11_DYNAMIC_XINPUT2@
|
||||||
#cmakedefine SDL_VIDEO_DRIVER_X11_DYNAMIC_XRANDR @SDL_VIDEO_DRIVER_X11_DYNAMIC_XRANDR@
|
#cmakedefine SDL_VIDEO_DRIVER_X11_DYNAMIC_XRANDR @SDL_VIDEO_DRIVER_X11_DYNAMIC_XRANDR@
|
||||||
#cmakedefine SDL_VIDEO_DRIVER_X11_DYNAMIC_XSS @SDL_VIDEO_DRIVER_X11_DYNAMIC_XSS@
|
#cmakedefine SDL_VIDEO_DRIVER_X11_DYNAMIC_XSS @SDL_VIDEO_DRIVER_X11_DYNAMIC_XSS@
|
||||||
#cmakedefine SDL_VIDEO_DRIVER_X11_HAS_XKBKEYCODETOKEYSYM @SDL_VIDEO_DRIVER_X11_HAS_XKBKEYCODETOKEYSYM@
|
#cmakedefine SDL_VIDEO_DRIVER_X11_HAS_XKBLOOKUPKEYSYM @SDL_VIDEO_DRIVER_X11_HAS_XKBLOOKUPKEYSYM@
|
||||||
#cmakedefine SDL_VIDEO_DRIVER_X11_SUPPORTS_GENERIC_EVENTS @SDL_VIDEO_DRIVER_X11_SUPPORTS_GENERIC_EVENTS@
|
#cmakedefine SDL_VIDEO_DRIVER_X11_SUPPORTS_GENERIC_EVENTS @SDL_VIDEO_DRIVER_X11_SUPPORTS_GENERIC_EVENTS@
|
||||||
#cmakedefine SDL_VIDEO_DRIVER_X11_XCURSOR @SDL_VIDEO_DRIVER_X11_XCURSOR@
|
#cmakedefine SDL_VIDEO_DRIVER_X11_XCURSOR @SDL_VIDEO_DRIVER_X11_XCURSOR@
|
||||||
#cmakedefine SDL_VIDEO_DRIVER_X11_XDBE @SDL_VIDEO_DRIVER_X11_XDBE@
|
#cmakedefine SDL_VIDEO_DRIVER_X11_XDBE @SDL_VIDEO_DRIVER_X11_XDBE@
|
||||||
|
|
|
@ -194,7 +194,7 @@
|
||||||
#define SDL_VIDEO_DRIVER_X11_XRANDR 1
|
#define SDL_VIDEO_DRIVER_X11_XRANDR 1
|
||||||
#define SDL_VIDEO_DRIVER_X11_XSCRNSAVER 1
|
#define SDL_VIDEO_DRIVER_X11_XSCRNSAVER 1
|
||||||
#define SDL_VIDEO_DRIVER_X11_XSHAPE 1
|
#define SDL_VIDEO_DRIVER_X11_XSHAPE 1
|
||||||
#define SDL_VIDEO_DRIVER_X11_HAS_XKBKEYCODETOKEYSYM 1
|
#define SDL_VIDEO_DRIVER_X11_HAS_XKBLOOKUPKEYSYM 1
|
||||||
|
|
||||||
#ifdef MAC_OS_X_VERSION_10_8
|
#ifdef MAC_OS_X_VERSION_10_8
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
#include <X11/Xatom.h>
|
#include <X11/Xatom.h>
|
||||||
#include <X11/Xresource.h>
|
#include <X11/Xresource.h>
|
||||||
|
|
||||||
#ifdef SDL_VIDEO_DRIVER_X11_HAS_XKBKEYCODETOKEYSYM
|
#ifdef SDL_VIDEO_DRIVER_X11_HAS_XKBLOOKUPKEYSYM
|
||||||
#include <X11/XKBlib.h>
|
#include <X11/XKBlib.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -1131,6 +1131,7 @@ static void X11_DispatchEvent(SDL_VideoDevice *_this, XEvent *xevent)
|
||||||
printf("window %p: KeymapNotify!\n", data);
|
printf("window %p: KeymapNotify!\n", data);
|
||||||
#endif
|
#endif
|
||||||
if (SDL_GetKeyboardFocus() != NULL) {
|
if (SDL_GetKeyboardFocus() != NULL) {
|
||||||
|
X11_UpdateKeymap(_this, SDL_TRUE);
|
||||||
X11_ReconcileKeyboardState(_this);
|
X11_ReconcileKeyboardState(_this);
|
||||||
}
|
}
|
||||||
} else if (xevent->type == MappingNotify) {
|
} else if (xevent->type == MappingNotify) {
|
||||||
|
|
|
@ -72,7 +72,7 @@ static SDL_bool X11_ScancodeIsRemappable(SDL_Scancode scancode)
|
||||||
/* This function only correctly maps letters and numbers for keyboards in US QWERTY layout */
|
/* This function only correctly maps letters and numbers for keyboards in US QWERTY layout */
|
||||||
static SDL_Scancode X11_KeyCodeToSDLScancode(SDL_VideoDevice *_this, KeyCode keycode)
|
static SDL_Scancode X11_KeyCodeToSDLScancode(SDL_VideoDevice *_this, KeyCode keycode)
|
||||||
{
|
{
|
||||||
const KeySym keysym = X11_KeyCodeToSym(_this, keycode, 0);
|
const KeySym keysym = X11_KeyCodeToSym(_this, keycode, 0, 0);
|
||||||
|
|
||||||
if (keysym == NoSymbol) {
|
if (keysym == NoSymbol) {
|
||||||
return SDL_SCANCODE_UNKNOWN;
|
return SDL_SCANCODE_UNKNOWN;
|
||||||
|
@ -81,24 +81,15 @@ static SDL_Scancode X11_KeyCodeToSDLScancode(SDL_VideoDevice *_this, KeyCode key
|
||||||
return SDL_GetScancodeFromKeySym(keysym, keycode);
|
return SDL_GetScancodeFromKeySym(keysym, keycode);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Uint32 X11_KeyCodeToUcs4(SDL_VideoDevice *_this, KeyCode keycode, unsigned char group)
|
KeySym X11_KeyCodeToSym(SDL_VideoDevice *_this, KeyCode keycode, unsigned char group, unsigned int mod_mask)
|
||||||
{
|
|
||||||
KeySym keysym = X11_KeyCodeToSym(_this, keycode, group);
|
|
||||||
|
|
||||||
if (keysym == NoSymbol) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return SDL_KeySymToUcs4(keysym);
|
|
||||||
}
|
|
||||||
|
|
||||||
KeySym
|
|
||||||
X11_KeyCodeToSym(SDL_VideoDevice *_this, KeyCode keycode, unsigned char group)
|
|
||||||
{
|
{
|
||||||
SDL_VideoData *data = _this->driverdata;
|
SDL_VideoData *data = _this->driverdata;
|
||||||
KeySym keysym;
|
KeySym keysym;
|
||||||
|
unsigned int mods_ret[16];
|
||||||
|
|
||||||
#ifdef SDL_VIDEO_DRIVER_X11_HAS_XKBKEYCODETOKEYSYM
|
SDL_zero(mods_ret);
|
||||||
|
|
||||||
|
#ifdef SDL_VIDEO_DRIVER_X11_HAS_XKBLOOKUPKEYSYM
|
||||||
if (data->xkb) {
|
if (data->xkb) {
|
||||||
int num_groups = XkbKeyNumGroups(data->xkb, keycode);
|
int num_groups = XkbKeyNumGroups(data->xkb, keycode);
|
||||||
unsigned char info = XkbKeyGroupInfo(data->xkb, keycode);
|
unsigned char info = XkbKeyGroupInfo(data->xkb, keycode);
|
||||||
|
@ -118,13 +109,16 @@ X11_KeyCodeToSym(SDL_VideoDevice *_this, KeyCode keycode, unsigned char group)
|
||||||
group %= num_groups;
|
group %= num_groups;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
keysym = X11_XkbKeycodeToKeysym(data->display, keycode, group, 0);
|
|
||||||
} else {
|
if (X11_XkbLookupKeySym(data->display, keycode, XkbBuildCoreState(mod_mask, group), mods_ret, &keysym) == NoSymbol) {
|
||||||
|
keysym = NoSymbol;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
/* TODO: Handle groups and modifiers on the legacy path. */
|
||||||
keysym = X11_XKeycodeToKeysym(data->display, keycode, 0);
|
keysym = X11_XKeycodeToKeysym(data->display, keycode, 0);
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
keysym = X11_XKeycodeToKeysym(data->display, keycode, 0);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return keysym;
|
return keysym;
|
||||||
}
|
}
|
||||||
|
@ -153,7 +147,7 @@ int X11_InitKeyboard(SDL_VideoDevice *_this)
|
||||||
int distance;
|
int distance;
|
||||||
Bool xkb_repeat = 0;
|
Bool xkb_repeat = 0;
|
||||||
|
|
||||||
#ifdef SDL_VIDEO_DRIVER_X11_HAS_XKBKEYCODETOKEYSYM
|
#ifdef SDL_VIDEO_DRIVER_X11_HAS_XKBLOOKUPKEYSYM
|
||||||
{
|
{
|
||||||
int xkb_major = XkbMajorVersion;
|
int xkb_major = XkbMajorVersion;
|
||||||
int xkb_minor = XkbMinorVersion;
|
int xkb_minor = XkbMinorVersion;
|
||||||
|
@ -334,6 +328,21 @@ int X11_InitKeyboard(SDL_VideoDevice *_this)
|
||||||
|
|
||||||
void X11_UpdateKeymap(SDL_VideoDevice *_this, SDL_bool send_event)
|
void X11_UpdateKeymap(SDL_VideoDevice *_this, SDL_bool send_event)
|
||||||
{
|
{
|
||||||
|
struct Keymod_masks
|
||||||
|
{
|
||||||
|
SDL_Keymod sdl_mask;
|
||||||
|
unsigned int xkb_mask;
|
||||||
|
} const keymod_masks[] = {
|
||||||
|
{ SDL_KMOD_NONE, 0 },
|
||||||
|
{ SDL_KMOD_SHIFT, ShiftMask },
|
||||||
|
{ SDL_KMOD_CAPS, LockMask },
|
||||||
|
{ SDL_KMOD_SHIFT | SDL_KMOD_CAPS, ShiftMask | LockMask },
|
||||||
|
{ SDL_KMOD_MODE, Mod5Mask },
|
||||||
|
{ SDL_KMOD_MODE | SDL_KMOD_SHIFT, Mod5Mask | ShiftMask },
|
||||||
|
{ SDL_KMOD_MODE | SDL_KMOD_CAPS, Mod5Mask | LockMask },
|
||||||
|
{ SDL_KMOD_MODE | SDL_KMOD_SHIFT | SDL_KMOD_CAPS, Mod5Mask | ShiftMask | LockMask }
|
||||||
|
};
|
||||||
|
|
||||||
SDL_VideoData *data = _this->driverdata;
|
SDL_VideoData *data = _this->driverdata;
|
||||||
int i;
|
int i;
|
||||||
SDL_Scancode scancode;
|
SDL_Scancode scancode;
|
||||||
|
@ -342,7 +351,7 @@ void X11_UpdateKeymap(SDL_VideoDevice *_this, SDL_bool send_event)
|
||||||
|
|
||||||
keymap = SDL_CreateKeymap();
|
keymap = SDL_CreateKeymap();
|
||||||
|
|
||||||
#ifdef SDL_VIDEO_DRIVER_X11_HAS_XKBKEYCODETOKEYSYM
|
#ifdef SDL_VIDEO_DRIVER_X11_HAS_XKBLOOKUPKEYSYM
|
||||||
if (data->xkb) {
|
if (data->xkb) {
|
||||||
XkbStateRec state;
|
XkbStateRec state;
|
||||||
X11_XkbGetUpdatedMap(data->display, XkbAllClientInfoMask, data->xkb);
|
X11_XkbGetUpdatedMap(data->display, XkbAllClientInfoMask, data->xkb);
|
||||||
|
@ -353,49 +362,54 @@ void X11_UpdateKeymap(SDL_VideoDevice *_this, SDL_bool send_event)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// FIXME: Need to get the mapping for all modifiers, not just the first one
|
for (int m = 0; m < SDL_arraysize(keymod_masks); ++m) {
|
||||||
for (i = 0; i < SDL_arraysize(data->key_layout); i++) {
|
for (i = 0; i < SDL_arraysize(data->key_layout); i++) {
|
||||||
Uint32 key;
|
SDL_Keycode keycode;
|
||||||
SDL_Keycode keycode;
|
|
||||||
|
|
||||||
/* Make sure this is a valid scancode */
|
/* Make sure this is a valid scancode */
|
||||||
scancode = data->key_layout[i];
|
scancode = data->key_layout[i];
|
||||||
if (scancode == SDL_SCANCODE_UNKNOWN) {
|
if (scancode == SDL_SCANCODE_UNKNOWN) {
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
|
|
||||||
/* See if there is a UCS keycode for this scancode */
|
|
||||||
key = X11_KeyCodeToUcs4(_this, (KeyCode)i, group);
|
|
||||||
if (key) {
|
|
||||||
keycode = (SDL_Keycode)key;
|
|
||||||
} else {
|
|
||||||
SDL_Scancode keyScancode = X11_KeyCodeToSDLScancode(_this, (KeyCode)i);
|
|
||||||
|
|
||||||
switch (keyScancode) {
|
|
||||||
case SDL_SCANCODE_UNKNOWN:
|
|
||||||
keycode = SDLK_UNKNOWN;
|
|
||||||
break;
|
|
||||||
case SDL_SCANCODE_RETURN:
|
|
||||||
keycode = SDLK_RETURN;
|
|
||||||
break;
|
|
||||||
case SDL_SCANCODE_ESCAPE:
|
|
||||||
keycode = SDLK_ESCAPE;
|
|
||||||
break;
|
|
||||||
case SDL_SCANCODE_BACKSPACE:
|
|
||||||
keycode = SDLK_BACKSPACE;
|
|
||||||
break;
|
|
||||||
case SDL_SCANCODE_TAB:
|
|
||||||
keycode = SDLK_TAB;
|
|
||||||
break;
|
|
||||||
case SDL_SCANCODE_DELETE:
|
|
||||||
keycode = SDLK_DELETE;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
keycode = SDL_SCANCODE_TO_KEYCODE(keyScancode);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
KeySym keysym = X11_KeyCodeToSym(_this, i, group, keymod_masks[m].xkb_mask);
|
||||||
|
|
||||||
|
/* Note: The default SDL scancode table sets this to right alt instead of AltGr/Mode, so handle it separately. */
|
||||||
|
if (keysym != XK_ISO_Level3_Shift) {
|
||||||
|
keycode = SDL_KeySymToUcs4(keysym);
|
||||||
|
} else {
|
||||||
|
keycode = SDLK_MODE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!keycode) {
|
||||||
|
SDL_Scancode keyScancode = SDL_GetScancodeFromKeySym(keysym, (KeyCode)i);
|
||||||
|
|
||||||
|
switch (keyScancode) {
|
||||||
|
case SDL_SCANCODE_UNKNOWN:
|
||||||
|
keycode = SDLK_UNKNOWN;
|
||||||
|
break;
|
||||||
|
case SDL_SCANCODE_RETURN:
|
||||||
|
keycode = SDLK_RETURN;
|
||||||
|
break;
|
||||||
|
case SDL_SCANCODE_ESCAPE:
|
||||||
|
keycode = SDLK_ESCAPE;
|
||||||
|
break;
|
||||||
|
case SDL_SCANCODE_BACKSPACE:
|
||||||
|
keycode = SDLK_BACKSPACE;
|
||||||
|
break;
|
||||||
|
case SDL_SCANCODE_TAB:
|
||||||
|
keycode = SDLK_TAB;
|
||||||
|
break;
|
||||||
|
case SDL_SCANCODE_DELETE:
|
||||||
|
keycode = SDLK_DELETE;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
keycode = SDL_SCANCODE_TO_KEYCODE(keyScancode);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SDL_SetKeymapEntry(keymap, scancode, keymod_masks[m].sdl_mask, keycode);
|
||||||
}
|
}
|
||||||
SDL_SetKeymapEntry(keymap, scancode, SDL_KMOD_NONE, keycode);
|
|
||||||
}
|
}
|
||||||
SDL_SetKeymap(keymap, send_event);
|
SDL_SetKeymap(keymap, send_event);
|
||||||
}
|
}
|
||||||
|
@ -404,7 +418,7 @@ void X11_QuitKeyboard(SDL_VideoDevice *_this)
|
||||||
{
|
{
|
||||||
SDL_VideoData *data = _this->driverdata;
|
SDL_VideoData *data = _this->driverdata;
|
||||||
|
|
||||||
#ifdef SDL_VIDEO_DRIVER_X11_HAS_XKBKEYCODETOKEYSYM
|
#ifdef SDL_VIDEO_DRIVER_X11_HAS_XKBLOOKUPKEYSYM
|
||||||
if (data->xkb) {
|
if (data->xkb) {
|
||||||
X11_XkbFreeKeyboard(data->xkb, 0, True);
|
X11_XkbFreeKeyboard(data->xkb, 0, True);
|
||||||
data->xkb = NULL;
|
data->xkb = NULL;
|
||||||
|
|
|
@ -33,6 +33,6 @@ extern SDL_bool X11_HasScreenKeyboardSupport(SDL_VideoDevice *_this);
|
||||||
extern void X11_ShowScreenKeyboard(SDL_VideoDevice *_this, SDL_Window *window);
|
extern void X11_ShowScreenKeyboard(SDL_VideoDevice *_this, SDL_Window *window);
|
||||||
extern void X11_HideScreenKeyboard(SDL_VideoDevice *_this, SDL_Window *window);
|
extern void X11_HideScreenKeyboard(SDL_VideoDevice *_this, SDL_Window *window);
|
||||||
extern SDL_bool X11_IsScreenKeyboardShown(SDL_VideoDevice *_this, SDL_Window *window);
|
extern SDL_bool X11_IsScreenKeyboardShown(SDL_VideoDevice *_this, SDL_Window *window);
|
||||||
extern KeySym X11_KeyCodeToSym(SDL_VideoDevice *_this, KeyCode, unsigned char group);
|
extern KeySym X11_KeyCodeToSym(SDL_VideoDevice *_this, KeyCode, unsigned char group, unsigned int mod_mask);
|
||||||
|
|
||||||
#endif /* SDL_x11keyboard_h_ */
|
#endif /* SDL_x11keyboard_h_ */
|
||||||
|
|
|
@ -178,12 +178,12 @@ SDL_X11_SYM(Bool,XGetEventData,(Display* a,XGenericEventCookie* b),(a,b),return)
|
||||||
SDL_X11_SYM(void,XFreeEventData,(Display* a,XGenericEventCookie* b),(a,b),)
|
SDL_X11_SYM(void,XFreeEventData,(Display* a,XGenericEventCookie* b),(a,b),)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef SDL_VIDEO_DRIVER_X11_HAS_XKBKEYCODETOKEYSYM
|
#ifdef SDL_VIDEO_DRIVER_X11_HAS_XKBLOOKUPKEYSYM
|
||||||
SDL_X11_SYM(Bool,XkbQueryExtension,(Display* a,int * b,int * c,int * d,int * e, int *f),(a,b,c,d,e,f),return)
|
SDL_X11_SYM(Bool,XkbQueryExtension,(Display* a,int * b,int * c,int * d,int * e, int *f),(a,b,c,d,e,f),return)
|
||||||
#if NeedWidePrototypes
|
#if NeedWidePrototypes
|
||||||
SDL_X11_SYM(KeySym,XkbKeycodeToKeysym,(Display* a,unsigned int b,int c,int d),(a,b,c,d),return)
|
SDL_X11_SYM(Bool,XkbLookupKeySym,(Display* a, unsigned int b, unsigned int c, unsigned int* d, KeySym* e),(a,b,c,d,e),return)
|
||||||
#else
|
#else
|
||||||
SDL_X11_SYM(KeySym,XkbKeycodeToKeysym,(Display* a,KeyCode b,int c,int d),(a,b,c,d),return)
|
SDL_X11_SYM(Bool,XkbLookupKeySym,(Display* a, KeyCode b, unsigned int c, unsigned int* d, KeySym* e),(a,b,c,d,e),return)
|
||||||
#endif
|
#endif
|
||||||
SDL_X11_SYM(Status,XkbGetState,(Display* a,unsigned int b,XkbStatePtr c),(a,b,c),return)
|
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(Status,XkbGetUpdatedMap,(Display* a,unsigned int b,XkbDescPtr c),(a,b,c),return)
|
||||||
|
|
|
@ -121,7 +121,7 @@ struct SDL_VideoData
|
||||||
|
|
||||||
int xrandr_event_base;
|
int xrandr_event_base;
|
||||||
|
|
||||||
#ifdef SDL_VIDEO_DRIVER_X11_HAS_XKBKEYCODETOKEYSYM
|
#ifdef SDL_VIDEO_DRIVER_X11_HAS_XKBLOOKUPKEYSYM
|
||||||
XkbDescPtr xkb;
|
XkbDescPtr xkb;
|
||||||
#endif
|
#endif
|
||||||
int xkb_event;
|
int xkb_event;
|
||||||
|
|
Loading…
Reference in New Issue