Always register core devices
authorEmmanuele Bassi <ebassi@linux.intel.com>
Fri, 15 Jan 2010 12:22:29 +0000 (12:22 +0000)
committerEmmanuele Bassi <ebassi@linux.intel.com>
Wed, 20 Jan 2010 00:38:53 +0000 (00:38 +0000)
Even with XInput support we should always register core devices. This
allows us to handle enter and leave events correctly on the Stage and
to have a working XInput 1.x support in Clutter.

clutter/x11/clutter-backend-x11.c
clutter/x11/clutter-backend-x11.h
clutter/x11/clutter-event-x11.c
clutter/x11/clutter-input-device-x11.c

index 484e1f7..55fb65a 100644 (file)
@@ -99,12 +99,11 @@ static void
 clutter_x11_register_input_devices (ClutterBackendX11 *backend)
 {
   ClutterDeviceManager *manager;
-  gboolean have_an_xpointer = FALSE;
+  ClutterInputDevice *device;
 #ifdef HAVE_XINPUT
   XDeviceInfo *x_devices = NULL;
   int res, opcode, event, error;
   int i, n_devices;
-  GSList *devices = NULL;
 #endif /* HAVE_XINPUT */
 
   manager = clutter_device_manager_get_default ();
@@ -126,6 +125,8 @@ clutter_x11_register_input_devices (ClutterBackendX11 *backend)
       goto default_device;
     }
 
+  backend->xi_event_base = event;
+
   x_devices = XListInputDevices (backend->xdpy, &n_devices);
   if (n_devices == 0)
     {
@@ -149,14 +150,12 @@ clutter_x11_register_input_devices (ClutterBackendX11 *backend)
           info->use == IsXExtensionDevice)
         {
           ClutterInputDeviceType device_type;
-          ClutterInputDevice *device;
           gint n_events = 0;
 
           switch (info->use)
             {
             case IsXExtensionPointer:
               device_type = CLUTTER_POINTER_DEVICE;
-              have_an_xpointer = TRUE;
               break;
 
 #if 0
@@ -178,40 +177,14 @@ clutter_x11_register_input_devices (ClutterBackendX11 *backend)
                                  NULL);
           n_events = _clutter_input_device_x11_construct (device, backend);
 
-          if (info->use == IsXExtensionPointer && n_events > 0)
-            have_an_xpointer = TRUE;
+          _clutter_device_manager_add_device (manager, device);
 
-          /* add it to a temporary list; we don't add the device
-           * straight to the device manager because the XInput
-           * initialization might still fail
-           */
-          devices = g_slist_prepend (devices, device);
+          if (info->use == IsXExtensionPointer && n_events > 0)
+            backend->have_xinput = TRUE;
         }
     }
 
   XFree (x_devices);
-
-  devices = g_slist_reverse (devices);
-
-  if (have_an_xpointer)
-    {
-      GSList *l;
-
-      for (l = devices; l != NULL; l = l->next)
-        _clutter_device_manager_add_device (manager, l->data);
-
-      backend->have_xinput = TRUE;
-    }
-  else
-    {
-      g_warning ("No usable XInput pointer devices found");
-
-      g_slist_foreach (devices, (GFunc) g_object_unref, NULL);
-
-      backend->have_xinput = FALSE;
-    }
-
-  g_slist_free (devices);
 #endif /* HAVE_XINPUT */
 
 default_device:
@@ -220,35 +193,31 @@ default_device:
    *  - we do not have XInput support compiled in
    *  - we do not have XInput support enabled
    *  - we do not have the XInput extension
-   *  - we do not have a XInput pointer device
    *
    * we register two default devices, one for the pointer
-   * and one for the keyboard
+   * and one for the keyboard. this block must also be
+   * executed for the XInput support because XI does not
+   * cover core devices
    */
-  if (!have_an_xpointer)
-    {
-      ClutterInputDevice *d;
-
-      d = g_object_new (CLUTTER_TYPE_INPUT_DEVICE_X11,
-                        "id", 0,
-                        "name", "Core Pointer",
-                        "device-type", CLUTTER_POINTER_DEVICE,
-                        "is-core", TRUE,
-                        NULL);
-      CLUTTER_NOTE (BACKEND, "Added core pointer device %d", d->id);
-      _clutter_device_manager_add_device (manager, d);
-      backend->core_pointer = d;
-
-      d = g_object_new (CLUTTER_TYPE_INPUT_DEVICE_X11,
-                        "id", 1,
-                        "name", "Core Keyboard",
-                        "device-type", CLUTTER_KEYBOARD_DEVICE,
-                        "is-core", TRUE,
-                        NULL);
-      CLUTTER_NOTE (BACKEND, "Added core keyboard device %d", d->id);
-      _clutter_device_manager_add_device (manager, d);
-      backend->core_keyboard = d;
-    }
+  device = g_object_new (CLUTTER_TYPE_INPUT_DEVICE_X11,
+                         "id", 0,
+                         "name", "Core Pointer",
+                         "device-type", CLUTTER_POINTER_DEVICE,
+                         "is-core", TRUE,
+                         NULL);
+  CLUTTER_NOTE (BACKEND, "Added core pointer device");
+  _clutter_device_manager_add_device (manager, device);
+  backend->core_pointer = device;
+
+  device = g_object_new (CLUTTER_TYPE_INPUT_DEVICE_X11,
+                         "id", 1,
+                         "name", "Core Keyboard",
+                         "device-type", CLUTTER_KEYBOARD_DEVICE,
+                         "is-core", TRUE,
+                         NULL);
+  CLUTTER_NOTE (BACKEND, "Added core keyboard device");
+  _clutter_device_manager_add_device (manager, device);
+  backend->core_keyboard = device;
 }
 
 gboolean
index 807dd36..92a5fb8 100644 (file)
@@ -76,6 +76,7 @@ struct _ClutterBackendX11
   Atom atom_NET_WM_NAME;
   Atom atom_UTF8_STRING;
 
+  int xi_event_base;
   int event_types[CLUTTER_X11_XINPUT_LAST_EVENT];
   gboolean have_xinput;
 
index d6be645..264f619 100644 (file)
@@ -803,11 +803,54 @@ event_translate (ClutterBackend *backend,
 
           CLUTTER_NOTE (EVENT, "XInput event type: %d", xevent->type);
 
-          if (xevent->type == button_press)
+          if (xevent->type == EnterNotify)
+            {
+              device = backend_x11->core_pointer;
+
+              /* Convert enter notifies to motion events because X
+                 doesn't emit the corresponding motion notify */
+              event->motion.type = event->type = CLUTTER_MOTION;
+              event->motion.time = xevent->xcrossing.time;
+              event->motion.x = xevent->xcrossing.x;
+              event->motion.y = xevent->xcrossing.y;
+              event->motion.modifier_state = xevent->xcrossing.state;
+              event->motion.source = CLUTTER_ACTOR (stage);
+              event->motion.device = device;
+
+              /* we know that we are entering the stage here */
+              _clutter_input_device_set_stage (device, stage);
+              CLUTTER_NOTE (EVENT, "Entering the stage");
+            }
+          else if (xevent->type == LeaveNotify)
+            {
+              device = backend_x11->core_pointer;
+
+              if (device->stage == NULL)
+                {
+                  CLUTTER_NOTE (EVENT,
+                                "Discarding LeaveNotify for ButtonRelease "
+                                "event off-stage");
+                  return FALSE;
+                }
+
+              event->crossing.type = event->type = CLUTTER_LEAVE;
+              event->crossing.time = xevent->xcrossing.time;
+              event->crossing.x = xevent->xcrossing.x;
+              event->crossing.y = xevent->xcrossing.y;
+              event->crossing.source = CLUTTER_ACTOR (stage);
+              event->crossing.device = device;
+
+              /* we know that we are leaving the stage here */
+              _clutter_input_device_set_stage (device, NULL);
+              CLUTTER_NOTE (EVENT, "Leaving the stage (time:%u)",
+                            event->crossing.time);
+            }
+          else if (xevent->type == button_press)
             {
               XDeviceButtonEvent *xbev = (XDeviceButtonEvent *) xevent;
 
               device = _clutter_x11_get_device_for_xid (xbev->deviceid);
+              _clutter_input_device_set_stage (device, stage);
 
               CLUTTER_NOTE (EVENT,
                             "XI ButtonPress for %li ('%s') at %d, %d",
@@ -858,6 +901,7 @@ event_translate (ClutterBackend *backend,
               XDeviceButtonEvent *xbev = (XDeviceButtonEvent *)xevent;
 
               device = _clutter_x11_get_device_for_xid (xbev->deviceid);
+              _clutter_input_device_set_stage (device, stage);
 
               CLUTTER_NOTE (EVENT, "XI ButtonRelease for %li ('%s') at %d, %d",
                             xbev->deviceid,
@@ -887,6 +931,7 @@ event_translate (ClutterBackend *backend,
               XDeviceMotionEvent *xmev = (XDeviceMotionEvent *)xevent;
 
               device = _clutter_x11_get_device_for_xid (xmev->deviceid);
+              _clutter_input_device_set_stage (device, stage);
 
               CLUTTER_NOTE(EVENT, "XI Motion for %li ('%s') at %d, %d",
                            xmev->deviceid,
index 2be771d..94b67d2 100644 (file)
@@ -141,14 +141,14 @@ _clutter_input_device_x11_construct (ClutterInputDevice *device,
   for (i = 0; i < x_device->num_classes; i++)
     {
       XInputClassInfo *xclass_info = x_device->classes + i;
-      int button_press, button_release, motion_notify;
+      int *button_press, *button_release, *motion_notify;
 
       button_press =
-        backend->event_types[CLUTTER_X11_XINPUT_BUTTON_PRESS_EVENT];
+        &backend->event_types[CLUTTER_X11_XINPUT_BUTTON_PRESS_EVENT];
       button_release =
-        backend->event_types[CLUTTER_X11_XINPUT_BUTTON_RELEASE_EVENT];
+        &backend->event_types[CLUTTER_X11_XINPUT_BUTTON_RELEASE_EVENT];
       motion_notify =
-        backend->event_types[CLUTTER_X11_XINPUT_MOTION_NOTIFY_EVENT];
+        &backend->event_types[CLUTTER_X11_XINPUT_MOTION_NOTIFY_EVENT];
 
       switch (xclass_info->input_class)
         {
@@ -169,19 +169,19 @@ _clutter_input_device_x11_construct (ClutterInputDevice *device,
 
         case ButtonClass:
           DeviceButtonPress (x_device,
-                             button_press,
+                             *button_press,
                              device_x11->xevent_list[n_events]);
           n_events++;
 
           DeviceButtonRelease (x_device,
-                               button_release,
+                               *button_release,
                                device_x11->xevent_list[n_events]);
           n_events++;
           break;
 
         case ValuatorClass:
           DeviceMotionNotify (x_device,
-                              motion_notify,
+                              *motion_notify,
                               device_x11->xevent_list[n_events]);
           n_events++;
           break;