From 8a4b64715486699dd8d0ea2146d0adea37d2a6c7 Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Wed, 20 Jan 2010 19:40:58 +0000 Subject: [PATCH] x11: Re-enable XI1 extension keyboards The extension keyboard support in XInput 1.x is hopelessly broken. Nevertheless, it's possible to use some bits of it, as we prefer the core keyboard events to the XInput events, thus at least having proper handling for X11 key events on the Stage window. --- clutter/x11/clutter-backend-x11.c | 2 -- clutter/x11/clutter-event-x11.c | 28 ++++++++++++++++++++++++-- clutter/x11/clutter-input-device-x11.c | 21 ++++++++++++------- tests/interactive/test-devices.c | 14 +++++++------ 4 files changed, 48 insertions(+), 17 deletions(-) diff --git a/clutter/x11/clutter-backend-x11.c b/clutter/x11/clutter-backend-x11.c index 55fb65a3b..d3d59df6b 100644 --- a/clutter/x11/clutter-backend-x11.c +++ b/clutter/x11/clutter-backend-x11.c @@ -158,12 +158,10 @@ clutter_x11_register_input_devices (ClutterBackendX11 *backend) device_type = CLUTTER_POINTER_DEVICE; break; -#if 0 /* XInput1 is broken for keyboards */ case IsXExtensionKeyboard: device_type = CLUTTER_KEYBOARD_DEVICE; break; -#endif case IsXExtensionDevice: device_type = CLUTTER_EXTENSION_DEVICE; diff --git a/clutter/x11/clutter-event-x11.c b/clutter/x11/clutter-event-x11.c index 6858cfd65..1a3a260fc 100644 --- a/clutter/x11/clutter-event-x11.c +++ b/clutter/x11/clutter-event-x11.c @@ -267,9 +267,10 @@ set_user_time (ClutterBackendX11 *backend_x11, } } -#if 0 /* See XInput keyboard comment below HAVE_XINPUT */ +#ifdef HAVE_XINPUT static void -convert_xdevicekey_to_xkey (XDeviceKeyEvent *xkev, XEvent *xevent) +convert_xdevicekey_to_xkey (XDeviceKeyEvent *xkev, + XEvent *xevent) { xevent->xany.type = xevent->xkey.type = xkev->type; xevent->xkey.serial = xkev->serial; @@ -808,11 +809,14 @@ event_translate (ClutterBackend *backend, #ifdef HAVE_XINPUT int *ev_types = backend_x11->event_types; int button_press, button_release; + int key_press, key_release; int motion_notify; button_press = ev_types[CLUTTER_X11_XINPUT_BUTTON_PRESS_EVENT]; button_release = ev_types[CLUTTER_X11_XINPUT_BUTTON_RELEASE_EVENT]; motion_notify = ev_types[CLUTTER_X11_XINPUT_MOTION_NOTIFY_EVENT]; + key_press = ev_types[CLUTTER_X11_XINPUT_KEY_PRESS_EVENT]; + key_release = ev_types[CLUTTER_X11_XINPUT_KEY_RELEASE_EVENT]; CLUTTER_NOTE (EVENT, "XInput event type: %d", xevent->type); @@ -924,6 +928,26 @@ event_translate (ClutterBackend *backend, res = TRUE; } + else if (xevent->type == key_press || xevent->type == key_release) + { + /* the XInput 1.x handling of key presses/releases is broken: + * it makes key repeat, key presses and releases outside the + * window not generate events even when the window has focus + */ + XDeviceKeyEvent *xkev = (XDeviceKeyEvent *) xevent; + XEvent xevent_converted; + + convert_xdevicekey_to_xkey (xkev, &xevent_converted); + + event->key.type = event->type = (xevent->type == key_press) + ? CLUTTER_KEY_PRESS + : CLUTTER_KEY_RELEASE; + + translate_key_event (backend, event, &xevent_converted); + + if (xevent->type == key_press) + set_user_time (backend_x11, &xwindow, xkev->time); + } else #endif /* HAVE_XINPUT */ { diff --git a/clutter/x11/clutter-input-device-x11.c b/clutter/x11/clutter-input-device-x11.c index 94b67d2a9..b62ca8a0c 100644 --- a/clutter/x11/clutter-input-device-x11.c +++ b/clutter/x11/clutter-input-device-x11.c @@ -142,6 +142,7 @@ _clutter_input_device_x11_construct (ClutterInputDevice *device, { XInputClassInfo *xclass_info = x_device->classes + i; int *button_press, *button_release, *motion_notify; + int *key_press, *key_release; button_press = &backend->event_types[CLUTTER_X11_XINPUT_BUTTON_PRESS_EVENT]; @@ -150,22 +151,28 @@ _clutter_input_device_x11_construct (ClutterInputDevice *device, motion_notify = &backend->event_types[CLUTTER_X11_XINPUT_MOTION_NOTIFY_EVENT]; + key_press = + &backend->event_types[CLUTTER_X11_XINPUT_KEY_PRESS_EVENT]; + key_release = + &backend->event_types[CLUTTER_X11_XINPUT_KEY_RELEASE_EVENT]; + switch (xclass_info->input_class) { -#if 0 - /* XInput 1.x is broken for keyboards: */ + /* event though XInput 1.x is broken for keyboard-like devices + * it might still be useful to track them down; the core keyboard + * will handle the right events anyway + */ case KeyClass: - DeviceKeyPress (xdevice, - backend->event_types[CLUTTER_X11_XINPUT_KEY_PRESS_EVENT], + DeviceKeyPress (x_device, + *key_press, device_x11->xevent_list[n_events]); n_events++; - DeviceKeyRelease (xdevice, - backend->event_types[CLUTTER_X11_XINPUT_KEY_RELEASE_EVENT], + DeviceKeyRelease (x_device, + *key_release, device_x11->xevent_list[n_events]); n_events++; break; -#endif case ButtonClass: DeviceButtonPress (x_device, diff --git a/tests/interactive/test-devices.c b/tests/interactive/test-devices.c index 6af0ce590..e286a064c 100644 --- a/tests/interactive/test-devices.c +++ b/tests/interactive/test-devices.c @@ -105,13 +105,15 @@ test_devices_main (int argc, char **argv) ClutterInputDeviceType device_type; ClutterActor *hand = NULL; - device_type = clutter_input_device_get_device_type (device); - if (device_type == CLUTTER_POINTER_DEVICE) - { - g_print ("got a pointer device '%s' with id %d...\n", - clutter_input_device_get_device_name (device), - clutter_input_device_get_device_id (device)); + g_print ("got a %s device '%s' with id %d...\n", + device_type_name (device), + clutter_input_device_get_device_name (device), + clutter_input_device_get_device_id (device)); + device_type = clutter_input_device_get_device_type (device); + if (device_type == CLUTTER_POINTER_DEVICE || + device_type == CLUTTER_EXTENSION_DEVICE) + { hand = clutter_texture_new_from_file (TESTS_DATADIR G_DIR_SEPARATOR_S "redhand.png",