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)
{
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;
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;
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", 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

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

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

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