mirror of
https://github.com/brl/mutter.git
synced 2024-12-01 20:30:41 -05:00
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:
parent
d15b828cc5
commit
09a317d23d
@ -5,6 +5,9 @@
|
|||||||
|
|
||||||
G_BEGIN_DECLS
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
void _clutter_event_set_pointer_emulated (ClutterEvent *event,
|
||||||
|
gboolean is_emulated);
|
||||||
|
|
||||||
/* Reinjecting queued events for processing */
|
/* Reinjecting queued events for processing */
|
||||||
void _clutter_process_event (ClutterEvent *event);
|
void _clutter_process_event (ClutterEvent *event);
|
||||||
|
|
||||||
|
@ -53,6 +53,8 @@ typedef struct _ClutterEventPrivate {
|
|||||||
gdouble delta_y;
|
gdouble delta_y;
|
||||||
|
|
||||||
gpointer platform_data;
|
gpointer platform_data;
|
||||||
|
|
||||||
|
guint is_pointer_emulated : 1;
|
||||||
} ClutterEventPrivate;
|
} ClutterEventPrivate;
|
||||||
|
|
||||||
static GHashTable *all_events = NULL;
|
static GHashTable *all_events = NULL;
|
||||||
@ -108,6 +110,16 @@ _clutter_event_set_platform_data (ClutterEvent *event,
|
|||||||
((ClutterEventPrivate *) event)->platform_data = data;
|
((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:
|
* clutter_event_type:
|
||||||
* @event: a #ClutterEvent
|
* @event: a #ClutterEvent
|
||||||
|
@ -255,6 +255,8 @@ clutter_backend_x11_create_device_manager (ClutterBackendX11 *backend_x11)
|
|||||||
"backend", backend_x11,
|
"backend", backend_x11,
|
||||||
"opcode", event_base,
|
"opcode", event_base,
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
|
backend_x11->xi_minor = minor;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif /* HAVE_XINPUT_2 */
|
#endif /* HAVE_XINPUT_2 */
|
||||||
@ -267,6 +269,7 @@ clutter_backend_x11_create_device_manager (ClutterBackendX11 *backend_x11)
|
|||||||
"event-base", first_event,
|
"event-base", first_event,
|
||||||
NULL);
|
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,
|
g_object_new (CLUTTER_TYPE_DEVICE_MANAGER_X11,
|
||||||
"backend", backend_x11,
|
"backend", backend_x11,
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
|
backend_x11->xi_minor = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
backend = CLUTTER_BACKEND (backend_x11);
|
backend = CLUTTER_BACKEND (backend_x11);
|
||||||
|
@ -100,6 +100,7 @@ struct _ClutterBackendX11
|
|||||||
|
|
||||||
ClutterDeviceManager *device_manager;
|
ClutterDeviceManager *device_manager;
|
||||||
gboolean has_xinput;
|
gboolean has_xinput;
|
||||||
|
int xi_minor;
|
||||||
|
|
||||||
XSettingsClient *xsettings;
|
XSettingsClient *xsettings;
|
||||||
Window xsettings_xwin;
|
Window xsettings_xwin;
|
||||||
|
@ -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 *
|
static ClutterInputDevice *
|
||||||
create_device (ClutterDeviceManagerXI2 *manager_xi2,
|
create_device (ClutterDeviceManagerXI2 *manager_xi2,
|
||||||
ClutterBackendX11 *backend_x11,
|
ClutterBackendX11 *backend_x11,
|
||||||
XIDeviceInfo *info)
|
XIDeviceInfo *info)
|
||||||
{
|
{
|
||||||
ClutterInputDeviceType source;
|
ClutterInputDeviceType source, touch_source;
|
||||||
ClutterInputDevice *retval;
|
ClutterInputDevice *retval;
|
||||||
ClutterInputMode mode;
|
ClutterInputMode mode;
|
||||||
gboolean is_enabled;
|
gboolean is_enabled;
|
||||||
|
guint num_touches = 0;
|
||||||
|
|
||||||
if (info->use == XIMasterKeyboard || info->use == XISlaveKeyboard)
|
if (info->use == XIMasterKeyboard || info->use == XISlaveKeyboard)
|
||||||
source = CLUTTER_KEYBOARD_DEVICE;
|
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
|
else
|
||||||
{
|
{
|
||||||
gchar *name;
|
gchar *name;
|
||||||
@ -208,6 +251,9 @@ create_device (ClutterDeviceManagerXI2 *manager_xi2,
|
|||||||
source = CLUTTER_ERASER_DEVICE;
|
source = CLUTTER_ERASER_DEVICE;
|
||||||
else if (strstr (name, "cursor") != NULL)
|
else if (strstr (name, "cursor") != NULL)
|
||||||
source = CLUTTER_CURSOR_DEVICE;
|
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)
|
else if (strstr (name, "wacom") != NULL || strstr (name, "pen") != NULL)
|
||||||
source = CLUTTER_PEN_DEVICE;
|
source = CLUTTER_PEN_DEVICE;
|
||||||
else
|
else
|
||||||
@ -440,6 +486,11 @@ get_event_stage (ClutterEventTranslator *translator,
|
|||||||
case XI_ButtonPress:
|
case XI_ButtonPress:
|
||||||
case XI_ButtonRelease:
|
case XI_ButtonRelease:
|
||||||
case XI_Motion:
|
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;
|
XIDeviceEvent *xev = (XIDeviceEvent *) xi_event;
|
||||||
|
|
||||||
@ -807,6 +858,10 @@ clutter_device_manager_xi2_translate_event (ClutterEventTranslator *translator,
|
|||||||
stage_x11,
|
stage_x11,
|
||||||
&xev->valuators);
|
&xev->valuators);
|
||||||
|
|
||||||
|
#ifdef XINPUT_2_2
|
||||||
|
if (xev->flags & XIPointerEmulated)
|
||||||
|
_clutter_event_set_pointer_emulated (event, TRUE);
|
||||||
|
#endif /* XINPUT_2_2 */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -855,6 +910,11 @@ clutter_device_manager_xi2_translate_event (ClutterEventTranslator *translator,
|
|||||||
event->button.y,
|
event->button.y,
|
||||||
event->button.axes != NULL ? "yes" : "no");
|
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)
|
if (xi_event->evtype == XI_ButtonPress)
|
||||||
_clutter_stage_x11_set_user_time (stage_x11, event->button.time);
|
_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)
|
if (source_device != NULL && device->stage != NULL)
|
||||||
_clutter_input_device_set_stage (source_device, device->stage);
|
_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)",
|
CLUTTER_NOTE (EVENT, "motion: win:0x%x device:%s (x:%.2f, y:%.2f, axes:%s)",
|
||||||
(unsigned int) stage_x11->xwin,
|
(unsigned int) stage_x11->xwin,
|
||||||
event->motion.device->device_name,
|
event->motion.device->device_name,
|
||||||
@ -941,6 +1006,116 @@ clutter_device_manager_xi2_translate_event (ClutterEventTranslator *translator,
|
|||||||
}
|
}
|
||||||
break;
|
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_Enter:
|
||||||
case XI_Leave:
|
case XI_Leave:
|
||||||
{
|
{
|
||||||
|
@ -92,6 +92,16 @@ clutter_input_device_xi2_select_stage_events (ClutterInputDevice *device,
|
|||||||
if (event_mask & LeaveWindowMask)
|
if (event_mask & LeaveWindowMask)
|
||||||
XISetMask (mask, XI_Leave);
|
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.deviceid = device_xi2->device_id;
|
||||||
xi_event_mask.mask = mask;
|
xi_event_mask.mask = mask;
|
||||||
xi_event_mask.mask_len = len;
|
xi_event_mask.mask_len = len;
|
||||||
|
Loading…
Reference in New Issue
Block a user