x11: Add support for touch events

For the time being, we just relay everything we get from the X server to
the Clutter application.
This commit is contained in:
Emmanuele Bassi 2012-03-19 14:28:34 +00:00
parent d15b828cc5
commit 09a317d23d
6 changed files with 207 additions and 1 deletions

View File

@ -5,6 +5,9 @@
G_BEGIN_DECLS
void _clutter_event_set_pointer_emulated (ClutterEvent *event,
gboolean is_emulated);
/* Reinjecting queued events for processing */
void _clutter_process_event (ClutterEvent *event);

View File

@ -53,6 +53,8 @@ typedef struct _ClutterEventPrivate {
gdouble delta_y;
gpointer platform_data;
guint is_pointer_emulated : 1;
} ClutterEventPrivate;
static GHashTable *all_events = NULL;
@ -108,6 +110,16 @@ _clutter_event_set_platform_data (ClutterEvent *event,
((ClutterEventPrivate *) event)->platform_data = data;
}
void
_clutter_event_set_pointer_emulated (ClutterEvent *event,
gboolean is_emulated)
{
if (!is_event_allocated (event))
return;
((ClutterEventPrivate *) event)->is_pointer_emulated = !!is_emulated;
}
/**
* clutter_event_type:
* @event: a #ClutterEvent

View File

@ -255,6 +255,8 @@ clutter_backend_x11_create_device_manager (ClutterBackendX11 *backend_x11)
"backend", backend_x11,
"opcode", event_base,
NULL);
backend_x11->xi_minor = minor;
}
else
#endif /* HAVE_XINPUT_2 */
@ -267,6 +269,7 @@ clutter_backend_x11_create_device_manager (ClutterBackendX11 *backend_x11)
"event-base", first_event,
NULL);
backend_x11->xi_minor = -1;
}
}
}
@ -279,6 +282,8 @@ clutter_backend_x11_create_device_manager (ClutterBackendX11 *backend_x11)
g_object_new (CLUTTER_TYPE_DEVICE_MANAGER_X11,
"backend", backend_x11,
NULL);
backend_x11->xi_minor = -1;
}
backend = CLUTTER_BACKEND (backend_x11);

View File

@ -100,6 +100,7 @@ struct _ClutterBackendX11
ClutterDeviceManager *device_manager;
gboolean has_xinput;
int xi_minor;
XSettingsClient *xsettings;
Window xsettings_xwin;

View File

@ -186,18 +186,61 @@ translate_device_classes (Display *xdisplay,
}
}
static gboolean
is_touch_device (XIAnyClassInfo **classes,
guint n_classes,
ClutterInputDeviceType *device_type,
guint *n_touch_points)
{
#ifdef XINPUT_2_2
guint i;
for (i = 0; i < n_classes; i++)
{
XITouchClassInfo *class = (XITouchClassInfo *) classes[i];
if (class->type != XITouchClass)
continue;
if (class->num_touches > 0)
{
if (class->mode == XIDirectTouch)
*device_type = CLUTTER_TOUCHSCREEN_DEVICE;
else if (class->mode == XIDependentTouch)
*device_type = CLUTTER_TOUCHPAD_DEVICE;
else
continue;
*n_touch_points = class->num_touches;
return TRUE;
}
}
#endif
return FALSE;
}
static ClutterInputDevice *
create_device (ClutterDeviceManagerXI2 *manager_xi2,
ClutterBackendX11 *backend_x11,
XIDeviceInfo *info)
{
ClutterInputDeviceType source;
ClutterInputDeviceType source, touch_source;
ClutterInputDevice *retval;
ClutterInputMode mode;
gboolean is_enabled;
guint num_touches = 0;
if (info->use == XIMasterKeyboard || info->use == XISlaveKeyboard)
source = CLUTTER_KEYBOARD_DEVICE;
else if (info->use == XISlavePointer &&
is_touch_device (info->classes, info->num_classes,
&touch_source,
&num_touches))
{
source = touch_source;
}
else
{
gchar *name;
@ -208,6 +251,9 @@ create_device (ClutterDeviceManagerXI2 *manager_xi2,
source = CLUTTER_ERASER_DEVICE;
else if (strstr (name, "cursor") != NULL)
source = CLUTTER_CURSOR_DEVICE;
else if (strstr (name, "finger") != NULL ||
(strstr (name, "touch") != NULL && strstr (name, "touchpad") == NULL))
source = CLUTTER_TOUCHSCREEN_DEVICE;
else if (strstr (name, "wacom") != NULL || strstr (name, "pen") != NULL)
source = CLUTTER_PEN_DEVICE;
else
@ -440,6 +486,11 @@ get_event_stage (ClutterEventTranslator *translator,
case XI_ButtonPress:
case XI_ButtonRelease:
case XI_Motion:
#ifdef XINPUT_2_2
case XI_TouchBegin:
case XI_TouchUpdate:
case XI_TouchEnd:
#endif /* XINPUT_2_2 */
{
XIDeviceEvent *xev = (XIDeviceEvent *) xi_event;
@ -807,6 +858,10 @@ clutter_device_manager_xi2_translate_event (ClutterEventTranslator *translator,
stage_x11,
&xev->valuators);
#ifdef XINPUT_2_2
if (xev->flags & XIPointerEmulated)
_clutter_event_set_pointer_emulated (event, TRUE);
#endif /* XINPUT_2_2 */
break;
default:
@ -855,6 +910,11 @@ clutter_device_manager_xi2_translate_event (ClutterEventTranslator *translator,
event->button.y,
event->button.axes != NULL ? "yes" : "no");
#ifdef XINPUT_2_2
if (xev->flags & XIPointerEmulated)
_clutter_event_set_pointer_emulated (event, TRUE);
#endif /* XINPUT_2_2 */
if (xi_event->evtype == XI_ButtonPress)
_clutter_stage_x11_set_user_time (stage_x11, event->button.time);
@ -930,6 +990,11 @@ clutter_device_manager_xi2_translate_event (ClutterEventTranslator *translator,
if (source_device != NULL && device->stage != NULL)
_clutter_input_device_set_stage (source_device, device->stage);
#ifdef XINPUT_2_2
if (xev->flags & XIPointerEmulated)
_clutter_event_set_pointer_emulated (event, TRUE);
#endif /* XINPUT_2_2 */
CLUTTER_NOTE (EVENT, "motion: win:0x%x device:%s (x:%.2f, y:%.2f, axes:%s)",
(unsigned int) stage_x11->xwin,
event->motion.device->device_name,
@ -941,6 +1006,116 @@ clutter_device_manager_xi2_translate_event (ClutterEventTranslator *translator,
}
break;
#ifdef XINPUT_2_2
case XI_TouchBegin:
case XI_TouchEnd:
{
XIDeviceEvent *xev = (XIDeviceEvent *) xi_event;
source_device = g_hash_table_lookup (manager_xi2->devices_by_id,
GINT_TO_POINTER (xev->sourceid));
if (xi_event->evtype == XI_TouchBegin)
event->touch.type = event->type = CLUTTER_TOUCH_BEGIN;
else
event->touch.type = event->type = CLUTTER_TOUCH_END;
event->touch.stage = stage;
event->touch.time = xev->time;
event->touch.x = xev->event_x;
event->touch.y = xev->event_y;
event->touch.modifier_state =
_clutter_input_device_xi2_translate_state (&xev->mods,
&xev->buttons);
clutter_event_set_source_device (event, source_device);
device = g_hash_table_lookup (manager_xi2->devices_by_id,
GINT_TO_POINTER (xev->deviceid));
clutter_event_set_device (event, device);
event->touch.axes = translate_axes (event->motion.device,
event->motion.x,
event->motion.y,
stage_x11,
&xev->valuators);
if (source_device != NULL && device->stage != NULL)
_clutter_input_device_set_stage (source_device, device->stage);
if (xi_event->evtype == XI_TouchBegin)
{
event->touch.modifier_state |= CLUTTER_BUTTON1_MASK;
_clutter_stage_x11_set_user_time (stage_x11, event->touch.time);
}
event->touch.sequence = GUINT_TO_POINTER (xev->detail);
if (xev->flags & XITouchEmulatingPointer)
_clutter_event_set_pointer_emulated (event, TRUE);
CLUTTER_NOTE (EVENT, "touch %s: win:0x%x device:%s (x:%.2f, y:%.2f, axes:%s)",
event->type == CLUTTER_TOUCH_BEGIN ? "begin" : "end",
(unsigned int) stage_x11->xwin,
event->touch.device->device_name,
event->touch.x,
event->touch.y,
event->touch.axes != NULL ? "yes" : "no");
retval = CLUTTER_TRANSLATE_QUEUE;
}
break;
case XI_TouchUpdate:
{
XIDeviceEvent *xev = (XIDeviceEvent *) xi_event;
source_device = g_hash_table_lookup (manager_xi2->devices_by_id,
GINT_TO_POINTER (xev->sourceid));
event->touch.type = event->type = CLUTTER_TOUCH_UPDATE;
event->touch.stage = stage;
event->touch.time = xev->time;
event->touch.sequence = GUINT_TO_POINTER (xev->detail);
event->touch.x = xev->event_x;
event->touch.y = xev->event_y;
clutter_event_set_source_device (event, source_device);
device = g_hash_table_lookup (manager_xi2->devices_by_id,
GINT_TO_POINTER (xev->deviceid));
clutter_event_set_device (event, device);
event->touch.axes = translate_axes (event->motion.device,
event->motion.x,
event->motion.y,
stage_x11,
&xev->valuators);
if (source_device != NULL && device->stage != NULL)
_clutter_input_device_set_stage (source_device, device->stage);
event->touch.modifier_state =
_clutter_input_device_xi2_translate_state (&xev->mods,
&xev->buttons);
event->touch.modifier_state |= CLUTTER_BUTTON1_MASK;
if (xev->flags & XITouchEmulatingPointer)
_clutter_event_set_pointer_emulated (event, TRUE);
CLUTTER_NOTE (EVENT, "touch update: win:0x%x device:%s (x:%.2f, y:%.2f, axes:%s)",
(unsigned int) stage_x11->xwin,
event->touch.device->device_name,
event->touch.x,
event->touch.y,
event->touch.axes != NULL ? "yes" : "no");
retval = CLUTTER_TRANSLATE_QUEUE;
}
break;
#endif /* XINPUT_2_2 */
case XI_Enter:
case XI_Leave:
{

View File

@ -92,6 +92,16 @@ clutter_input_device_xi2_select_stage_events (ClutterInputDevice *device,
if (event_mask & LeaveWindowMask)
XISetMask (mask, XI_Leave);
#ifdef XINPUT_2_2
/* enable touch event support if we're running on XInput 2.2 */
if (backend_x11->xi_minor >= 2)
{
XISetMask (mask, XI_TouchBegin);
XISetMask (mask, XI_TouchUpdate);
XISetMask (mask, XI_TouchEnd);
}
#endif /* XINPUT_2_2 */
xi_event_mask.deviceid = device_xi2->device_id;
xi_event_mask.mask = mask;
xi_event_mask.mask_len = len;