[clutter] x11: Add support for touch events
- From: Emmanuele Bassi <ebassi src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [clutter] x11: Add support for touch events
- Date: Mon, 19 Mar 2012 14:49:25 +0000 (UTC)
commit 09a317d23dc7d4785c31f8393b54392b5f473f60
Author: Emmanuele Bassi <ebassi linux intel com>
Date: Mon Mar 19 14:28:34 2012 +0000
x11: Add support for touch events
For the time being, we just relay everything we get from the X server to
the Clutter application.
clutter/clutter-event-private.h | 3 +
clutter/clutter-event.c | 12 ++
clutter/x11/clutter-backend-x11.c | 5 +
clutter/x11/clutter-backend-x11.h | 1 +
clutter/x11/clutter-device-manager-xi2.c | 177 +++++++++++++++++++++++++++++-
clutter/x11/clutter-input-device-xi2.c | 10 ++
6 files changed, 207 insertions(+), 1 deletions(-)
---
diff --git a/clutter/clutter-event-private.h b/clutter/clutter-event-private.h
index 1b3f9bb..eeb1080 100644
--- a/clutter/clutter-event-private.h
+++ b/clutter/clutter-event-private.h
@@ -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);
diff --git a/clutter/clutter-event.c b/clutter/clutter-event.c
index 1e2d251..fb5587e 100644
--- a/clutter/clutter-event.c
+++ b/clutter/clutter-event.c
@@ -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
diff --git a/clutter/x11/clutter-backend-x11.c b/clutter/x11/clutter-backend-x11.c
index 7cd6a78..be02d34 100644
--- a/clutter/x11/clutter-backend-x11.c
+++ b/clutter/x11/clutter-backend-x11.c
@@ -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);
diff --git a/clutter/x11/clutter-backend-x11.h b/clutter/x11/clutter-backend-x11.h
index 2922733..2ffe2f6 100644
--- a/clutter/x11/clutter-backend-x11.h
+++ b/clutter/x11/clutter-backend-x11.h
@@ -100,6 +100,7 @@ struct _ClutterBackendX11
ClutterDeviceManager *device_manager;
gboolean has_xinput;
+ int xi_minor;
XSettingsClient *xsettings;
Window xsettings_xwin;
diff --git a/clutter/x11/clutter-device-manager-xi2.c b/clutter/x11/clutter-device-manager-xi2.c
index da669bb..aad69c7 100644
--- a/clutter/x11/clutter-device-manager-xi2.c
+++ b/clutter/x11/clutter-device-manager-xi2.c
@@ -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:
{
diff --git a/clutter/x11/clutter-input-device-xi2.c b/clutter/x11/clutter-input-device-xi2.c
index 620df91..fb9f272 100644
--- a/clutter/x11/clutter-input-device-xi2.c
+++ b/clutter/x11/clutter-input-device-xi2.c
@@ -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;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]