x11: Re-enable XI1 extension keyboards
authorEmmanuele Bassi <ebassi@linux.intel.com>
Wed, 20 Jan 2010 19:40:58 +0000 (19:40 +0000)
committerEmmanuele Bassi <ebassi@linux.intel.com>
Wed, 20 Jan 2010 19:40:58 +0000 (19:40 +0000)
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
clutter/x11/clutter-event-x11.c
clutter/x11/clutter-input-device-x11.c
tests/interactive/test-devices.c

index 55fb65a..d3d59df 100644 (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;
index 6858cfd..1a3a260 100644 (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 */
         {
index 94b67d2..b62ca8a 100644 (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,
index 6af0ce5..e286a06 100644 (file)
@@ -105,13 +105,15 @@ test_devices_main (int argc, char **argv)
       ClutterInputDeviceType device_type;
       ClutterActor *hand = NULL;
 
+      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)
+      if (device_type == CLUTTER_POINTER_DEVICE ||
+          device_type == CLUTTER_EXTENSION_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));
-
           hand = clutter_texture_new_from_file (TESTS_DATADIR
                                                 G_DIR_SEPARATOR_S
                                                 "redhand.png",