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.
This commit is contained in:
Emmanuele Bassi 2010-01-20 19:40:58 +00:00
parent 94f9f3bd93
commit 8a4b647154
4 changed files with 48 additions and 17 deletions

View File

@ -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;

View File

@ -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 */
{

View File

@ -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,

View File

@ -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",