mirror of
https://github.com/libsdl-org/SDL.git
synced 2026-04-19 23:05:33 +02:00
x11: Use XInput2 events to pass through the keyboard ID to core key events
XInput2 keyboard handling has limitations: system keys that shouldn't be passed through when the keyboard isn't grabbed can be seen, and the text input system needs key events to flow through the X server to function properly (passing synthesized events through the filter function is not sufficient and doesn't work with non-Latin character sets). The primary bit of information missing from the core X key events that XInput2 provides is the source device, so use the XInput2 slave keyboard device events to store that value, and apply it to core X key events with the same serial. XInput2 events always arrive before core events so this works universally.
This commit is contained in:
@@ -1834,12 +1834,16 @@ static void X11_DispatchEvent(SDL_VideoDevice *_this, XEvent *xevent)
|
||||
case KeyPress:
|
||||
case KeyRelease:
|
||||
{
|
||||
SDL_KeyboardID keyboardID = SDL_GLOBAL_KEYBOARD_ID;
|
||||
if (data->xinput2_keyboard_enabled) {
|
||||
// This input is being handled by XInput2
|
||||
// This input is being handled by XInput2.
|
||||
break;
|
||||
} else if (xevent->xkey.serial == videodata->xinput_last_key_serial) {
|
||||
// Use the device ID from the XInput2 event if the serials match.
|
||||
keyboardID = videodata->xinput_last_keyboard_device;
|
||||
}
|
||||
|
||||
X11_HandleKeyEvent(_this, data, SDL_GLOBAL_KEYBOARD_ID, xevent);
|
||||
X11_HandleKeyEvent(_this, data, keyboardID, xevent);
|
||||
} break;
|
||||
|
||||
case MotionNotify:
|
||||
|
||||
@@ -140,6 +140,8 @@ struct SDL_VideoData
|
||||
|
||||
SDL_XInput2DeviceInfo *mouse_device_info;
|
||||
unsigned long xinput_last_button_serial;
|
||||
unsigned long xinput_last_key_serial;
|
||||
int xinput_last_keyboard_device;
|
||||
int xinput_master_pointer_device;
|
||||
bool xinput_hierarchy_changed;
|
||||
|
||||
|
||||
@@ -303,6 +303,12 @@ bool X11_InitXinput2(SDL_VideoDevice *_this)
|
||||
eventmask.mask_len = sizeof(mask);
|
||||
eventmask.mask = mask;
|
||||
|
||||
#ifndef USE_XINPUT2_KEYBOARD
|
||||
// If not using the full keyboard handling, register for keypresses to get the event source devices.
|
||||
XISetMask(mask, XI_KeyPress);
|
||||
XISetMask(mask, XI_KeyRelease);
|
||||
#endif
|
||||
|
||||
XISetMask(mask, XI_HierarchyChanged);
|
||||
X11_XISelectEvents(data->display, DefaultRootWindow(data->display), &eventmask, 1);
|
||||
|
||||
@@ -535,6 +541,8 @@ void X11_HandleXinput2Event(SDL_VideoDevice *_this, XGenericEventCookie *cookie)
|
||||
case XI_KeyRelease:
|
||||
{
|
||||
const XIDeviceEvent *xev = (const XIDeviceEvent *)cookie->data;
|
||||
|
||||
#ifdef XINPUT2_USE_KEYBOARD
|
||||
SDL_WindowData *windowdata = X11_FindWindow(videodata, xev->event);
|
||||
XEvent xevent;
|
||||
|
||||
@@ -564,6 +572,13 @@ void X11_HandleXinput2Event(SDL_VideoDevice *_this, XGenericEventCookie *cookie)
|
||||
xevent.xkey.same_screen = 1;
|
||||
|
||||
X11_HandleKeyEvent(_this, windowdata, (SDL_KeyboardID)xev->sourceid, &xevent);
|
||||
#else
|
||||
/* Keys are handled through core X events, however, note the device ID and
|
||||
* associated serial, so that the source device ID can be passed through.
|
||||
*/
|
||||
videodata->xinput_last_key_serial = xev->serial;
|
||||
videodata->xinput_last_keyboard_device = xev->sourceid;
|
||||
#endif
|
||||
} break;
|
||||
|
||||
case XI_RawButtonPress:
|
||||
|
||||
Reference in New Issue
Block a user