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.
This commit is contained in:
Emmanuele Bassi 2010-01-15 12:22:29 +00:00
parent e0b8d63159
commit d8e167f151
4 changed files with 81 additions and 66 deletions

View File

@ -99,12 +99,11 @@ static void
clutter_x11_register_input_devices (ClutterBackendX11 *backend) clutter_x11_register_input_devices (ClutterBackendX11 *backend)
{ {
ClutterDeviceManager *manager; ClutterDeviceManager *manager;
gboolean have_an_xpointer = FALSE; ClutterInputDevice *device;
#ifdef HAVE_XINPUT #ifdef HAVE_XINPUT
XDeviceInfo *x_devices = NULL; XDeviceInfo *x_devices = NULL;
int res, opcode, event, error; int res, opcode, event, error;
int i, n_devices; int i, n_devices;
GSList *devices = NULL;
#endif /* HAVE_XINPUT */ #endif /* HAVE_XINPUT */
manager = clutter_device_manager_get_default (); manager = clutter_device_manager_get_default ();
@ -126,6 +125,8 @@ clutter_x11_register_input_devices (ClutterBackendX11 *backend)
goto default_device; goto default_device;
} }
backend->xi_event_base = event;
x_devices = XListInputDevices (backend->xdpy, &n_devices); x_devices = XListInputDevices (backend->xdpy, &n_devices);
if (n_devices == 0) if (n_devices == 0)
{ {
@ -149,14 +150,12 @@ clutter_x11_register_input_devices (ClutterBackendX11 *backend)
info->use == IsXExtensionDevice) info->use == IsXExtensionDevice)
{ {
ClutterInputDeviceType device_type; ClutterInputDeviceType device_type;
ClutterInputDevice *device;
gint n_events = 0; gint n_events = 0;
switch (info->use) switch (info->use)
{ {
case IsXExtensionPointer: case IsXExtensionPointer:
device_type = CLUTTER_POINTER_DEVICE; device_type = CLUTTER_POINTER_DEVICE;
have_an_xpointer = TRUE;
break; break;
#if 0 #if 0
@ -178,40 +177,14 @@ clutter_x11_register_input_devices (ClutterBackendX11 *backend)
NULL); NULL);
n_events = _clutter_input_device_x11_construct (device, backend); n_events = _clutter_input_device_x11_construct (device, backend);
if (info->use == IsXExtensionPointer && n_events > 0) _clutter_device_manager_add_device (manager, device);
have_an_xpointer = TRUE;
/* add it to a temporary list; we don't add the device if (info->use == IsXExtensionPointer && n_events > 0)
* straight to the device manager because the XInput backend->have_xinput = TRUE;
* initialization might still fail
*/
devices = g_slist_prepend (devices, device);
} }
} }
XFree (x_devices); 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 */ #endif /* HAVE_XINPUT */
default_device: default_device:
@ -220,35 +193,31 @@ default_device:
* - we do not have XInput support compiled in * - we do not have XInput support compiled in
* - we do not have XInput support enabled * - we do not have XInput support enabled
* - we do not have the XInput extension * - we do not have the XInput extension
* - we do not have a XInput pointer device
* *
* we register two default devices, one for the pointer * 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) device = g_object_new (CLUTTER_TYPE_INPUT_DEVICE_X11,
{ "id", 0,
ClutterInputDevice *d; "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;
d = g_object_new (CLUTTER_TYPE_INPUT_DEVICE_X11, device = g_object_new (CLUTTER_TYPE_INPUT_DEVICE_X11,
"id", 0, "id", 1,
"name", "Core Pointer", "name", "Core Keyboard",
"device-type", CLUTTER_POINTER_DEVICE, "device-type", CLUTTER_KEYBOARD_DEVICE,
"is-core", TRUE, "is-core", TRUE,
NULL); NULL);
CLUTTER_NOTE (BACKEND, "Added core pointer device %d", d->id); CLUTTER_NOTE (BACKEND, "Added core keyboard device");
_clutter_device_manager_add_device (manager, d); _clutter_device_manager_add_device (manager, device);
backend->core_pointer = d; backend->core_keyboard = device;
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;
}
} }
gboolean gboolean

View File

@ -76,6 +76,7 @@ struct _ClutterBackendX11
Atom atom_NET_WM_NAME; Atom atom_NET_WM_NAME;
Atom atom_UTF8_STRING; Atom atom_UTF8_STRING;
int xi_event_base;
int event_types[CLUTTER_X11_XINPUT_LAST_EVENT]; int event_types[CLUTTER_X11_XINPUT_LAST_EVENT];
gboolean have_xinput; gboolean have_xinput;

View File

@ -803,11 +803,54 @@ event_translate (ClutterBackend *backend,
CLUTTER_NOTE (EVENT, "XInput event type: %d", xevent->type); 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; XDeviceButtonEvent *xbev = (XDeviceButtonEvent *) xevent;
device = _clutter_x11_get_device_for_xid (xbev->deviceid); device = _clutter_x11_get_device_for_xid (xbev->deviceid);
_clutter_input_device_set_stage (device, stage);
CLUTTER_NOTE (EVENT, CLUTTER_NOTE (EVENT,
"XI ButtonPress for %li ('%s') at %d, %d", "XI ButtonPress for %li ('%s') at %d, %d",
@ -858,6 +901,7 @@ event_translate (ClutterBackend *backend,
XDeviceButtonEvent *xbev = (XDeviceButtonEvent *)xevent; XDeviceButtonEvent *xbev = (XDeviceButtonEvent *)xevent;
device = _clutter_x11_get_device_for_xid (xbev->deviceid); 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", CLUTTER_NOTE (EVENT, "XI ButtonRelease for %li ('%s') at %d, %d",
xbev->deviceid, xbev->deviceid,
@ -887,6 +931,7 @@ event_translate (ClutterBackend *backend,
XDeviceMotionEvent *xmev = (XDeviceMotionEvent *)xevent; XDeviceMotionEvent *xmev = (XDeviceMotionEvent *)xevent;
device = _clutter_x11_get_device_for_xid (xmev->deviceid); 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", CLUTTER_NOTE(EVENT, "XI Motion for %li ('%s') at %d, %d",
xmev->deviceid, xmev->deviceid,

View File

@ -141,14 +141,14 @@ _clutter_input_device_x11_construct (ClutterInputDevice *device,
for (i = 0; i < x_device->num_classes; i++) for (i = 0; i < x_device->num_classes; i++)
{ {
XInputClassInfo *xclass_info = x_device->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 = button_press =
backend->event_types[CLUTTER_X11_XINPUT_BUTTON_PRESS_EVENT]; &backend->event_types[CLUTTER_X11_XINPUT_BUTTON_PRESS_EVENT];
button_release = button_release =
backend->event_types[CLUTTER_X11_XINPUT_BUTTON_RELEASE_EVENT]; &backend->event_types[CLUTTER_X11_XINPUT_BUTTON_RELEASE_EVENT];
motion_notify = 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) switch (xclass_info->input_class)
{ {
@ -169,19 +169,19 @@ _clutter_input_device_x11_construct (ClutterInputDevice *device,
case ButtonClass: case ButtonClass:
DeviceButtonPress (x_device, DeviceButtonPress (x_device,
button_press, *button_press,
device_x11->xevent_list[n_events]); device_x11->xevent_list[n_events]);
n_events++; n_events++;
DeviceButtonRelease (x_device, DeviceButtonRelease (x_device,
button_release, *button_release,
device_x11->xevent_list[n_events]); device_x11->xevent_list[n_events]);
n_events++; n_events++;
break; break;
case ValuatorClass: case ValuatorClass:
DeviceMotionNotify (x_device, DeviceMotionNotify (x_device,
motion_notify, *motion_notify,
device_x11->xevent_list[n_events]); device_x11->xevent_list[n_events]);
n_events++; n_events++;
break; break;