From d8e167f1519499a27ee04a9a0d167b5ffed3ce8e Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Fri, 15 Jan 2010 12:22:29 +0000 Subject: [PATCH] Always register core devices 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 | 87 +++++++++++----------------------- clutter/x11/clutter-backend-x11.h | 1 + clutter/x11/clutter-event-x11.c | 47 +++++++++++++++++- clutter/x11/clutter-input-device-x11.c | 14 +++--- 4 files changed, 82 insertions(+), 67 deletions(-) diff --git a/clutter/x11/clutter-backend-x11.c b/clutter/x11/clutter-backend-x11.c index 484e1f7..55fb65a 100644 --- a/clutter/x11/clutter-backend-x11.c +++ b/clutter/x11/clutter-backend-x11.c @@ -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 diff --git a/clutter/x11/clutter-backend-x11.h b/clutter/x11/clutter-backend-x11.h index 807dd36..92a5fb8 100644 --- a/clutter/x11/clutter-backend-x11.h +++ b/clutter/x11/clutter-backend-x11.h @@ -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; diff --git a/clutter/x11/clutter-event-x11.c b/clutter/x11/clutter-event-x11.c index d6be645..264f619 100644 --- a/clutter/x11/clutter-event-x11.c +++ b/clutter/x11/clutter-event-x11.c @@ -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, diff --git a/clutter/x11/clutter-input-device-x11.c b/clutter/x11/clutter-input-device-x11.c index 2be771d..94b67d2 100644 --- a/clutter/x11/clutter-input-device-x11.c +++ b/clutter/x11/clutter-input-device-x11.c @@ -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; -- 2.7.4