mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-26 19:51:11 +00:00
xvimagesink: Add touch event support
Send touch events for XI_TouchBegin, XI_TouchEnd, and XI_TouchUpdate events, grouping events with identical timestamps into one TOUCH_FRAME. Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/1633>
This commit is contained in:
parent
3b7f397863
commit
9389754d1a
4 changed files with 328 additions and 7 deletions
|
@ -19,7 +19,7 @@ if xvideo_dep.found()
|
||||||
xvimage_sources,
|
xvimage_sources,
|
||||||
c_args : gst_plugins_base_args + no_warn_args,
|
c_args : gst_plugins_base_args + no_warn_args,
|
||||||
include_directories: [configinc, libsinc],
|
include_directories: [configinc, libsinc],
|
||||||
dependencies : glib_deps + [video_dep, gst_base_dep, gst_dep, x11_dep, xshm_dep, xvideo_dep, libm],
|
dependencies : glib_deps + [video_dep, gst_base_dep, gst_dep, x11_dep, xshm_dep, xvideo_dep, xi_dep, libm],
|
||||||
install : true,
|
install : true,
|
||||||
install_dir : plugins_install_dir,
|
install_dir : plugins_install_dir,
|
||||||
)
|
)
|
||||||
|
|
|
@ -33,6 +33,11 @@
|
||||||
/* for XkbKeycodeToKeysym */
|
/* for XkbKeycodeToKeysym */
|
||||||
#include <X11/XKBlib.h>
|
#include <X11/XKBlib.h>
|
||||||
|
|
||||||
|
/* for touchscreen events */
|
||||||
|
#ifdef HAVE_XI2
|
||||||
|
#include <X11/extensions/XInput2.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
GST_DEBUG_CATEGORY (gst_debug_xv_context);
|
GST_DEBUG_CATEGORY (gst_debug_xv_context);
|
||||||
#define GST_CAT_DEFAULT gst_debug_xv_context
|
#define GST_CAT_DEFAULT gst_debug_xv_context
|
||||||
|
|
||||||
|
@ -642,8 +647,12 @@ gst_xvcontext_new (GstXvContextConfig * config, GError ** error)
|
||||||
"XV_BRIGHTNESS", "XV_CONTRAST"
|
"XV_BRIGHTNESS", "XV_CONTRAST"
|
||||||
};
|
};
|
||||||
int opcode, event, err;
|
int opcode, event, err;
|
||||||
int major = XkbMajorVersion;
|
int xkb_major = XkbMajorVersion;
|
||||||
int minor = XkbMinorVersion;
|
int xkb_minor = XkbMinorVersion;
|
||||||
|
#ifdef HAVE_XI2
|
||||||
|
int xi2_major = XI_2_Major;
|
||||||
|
int xi2_minor = XI_2_Minor;
|
||||||
|
#endif
|
||||||
|
|
||||||
g_return_val_if_fail (config != NULL, NULL);
|
g_return_val_if_fail (config != NULL, NULL);
|
||||||
|
|
||||||
|
@ -726,7 +735,8 @@ gst_xvcontext_new (GstXvContextConfig * config, GError ** error)
|
||||||
context->use_xshm = FALSE;
|
context->use_xshm = FALSE;
|
||||||
GST_DEBUG ("xvimagesink is not using XShm extension");
|
GST_DEBUG ("xvimagesink is not using XShm extension");
|
||||||
}
|
}
|
||||||
if (XkbQueryExtension (context->disp, &opcode, &event, &err, &major, &minor)) {
|
if (XkbQueryExtension (context->disp, &opcode, &event, &err, &xkb_major,
|
||||||
|
&xkb_minor)) {
|
||||||
context->use_xkb = TRUE;
|
context->use_xkb = TRUE;
|
||||||
GST_DEBUG ("xvimagesink is using Xkb extension");
|
GST_DEBUG ("xvimagesink is using Xkb extension");
|
||||||
} else {
|
} else {
|
||||||
|
@ -734,6 +744,22 @@ gst_xvcontext_new (GstXvContextConfig * config, GError ** error)
|
||||||
GST_DEBUG ("xvimagesink is not using Xkb extension");
|
GST_DEBUG ("xvimagesink is not using Xkb extension");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Search for XInput extension support */
|
||||||
|
#ifdef HAVE_XI2
|
||||||
|
if (XQueryExtension (context->disp, "XInputExtension",
|
||||||
|
&(context->xi_opcode), &event, &err)
|
||||||
|
&& (XIQueryVersion (context->disp, &xi2_major, &xi2_minor) == Success
|
||||||
|
&& (xi2_major > 2 || (xi2_major == 2 && xi2_minor >= 2)))) {
|
||||||
|
context->use_xi2 = TRUE;
|
||||||
|
GST_DEBUG ("xvimagesink is using XInput extension");
|
||||||
|
} else
|
||||||
|
#endif /* HAVE_XI2 */
|
||||||
|
{
|
||||||
|
context->use_xi2 = FALSE;
|
||||||
|
GST_DEBUG ("xvimagesink is not using XInput extension: "
|
||||||
|
"XInput is not present");
|
||||||
|
}
|
||||||
|
|
||||||
xv_attr = XvQueryPortAttributes (context->disp, context->xv_port_id, &N_attr);
|
xv_attr = XvQueryPortAttributes (context->disp, context->xv_port_id, &N_attr);
|
||||||
|
|
||||||
/* Generate the channels list */
|
/* Generate the channels list */
|
||||||
|
@ -943,6 +969,14 @@ gst_xvcontext_set_colorimetry (GstXvContext * context,
|
||||||
g_mutex_unlock (&context->lock);
|
g_mutex_unlock (&context->lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_XI2
|
||||||
|
static void
|
||||||
|
gst_xv_touchdevice_free (GstXvTouchDevice * device)
|
||||||
|
{
|
||||||
|
g_free (device->name);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
GstXWindow *
|
GstXWindow *
|
||||||
gst_xvcontext_create_xwindow (GstXvContext * context, gint width, gint height)
|
gst_xvcontext_create_xwindow (GstXvContext * context, gint width, gint height)
|
||||||
{
|
{
|
||||||
|
@ -964,6 +998,13 @@ gst_xvcontext_create_xwindow (GstXvContext * context, gint width, gint height)
|
||||||
window->height = height;
|
window->height = height;
|
||||||
window->internal = TRUE;
|
window->internal = TRUE;
|
||||||
|
|
||||||
|
#ifdef HAVE_XI2
|
||||||
|
window->last_touch = 0;
|
||||||
|
window->touch_devices = g_array_new (FALSE, FALSE, sizeof (GstXvTouchDevice));
|
||||||
|
g_array_set_clear_func (window->touch_devices,
|
||||||
|
(GDestroyNotify) gst_xv_touchdevice_free);
|
||||||
|
#endif
|
||||||
|
|
||||||
g_mutex_lock (&context->lock);
|
g_mutex_lock (&context->lock);
|
||||||
|
|
||||||
window->win = XCreateSimpleWindow (context->disp,
|
window->win = XCreateSimpleWindow (context->disp,
|
||||||
|
@ -1033,6 +1074,13 @@ gst_xvcontext_create_xwindow_from_xid (GstXvContext * context, XID xid)
|
||||||
window->render_rect.w = attr.width;
|
window->render_rect.w = attr.width;
|
||||||
window->render_rect.h = attr.height;
|
window->render_rect.h = attr.height;
|
||||||
|
|
||||||
|
#ifdef HAVE_XI2
|
||||||
|
window->last_touch = 0;
|
||||||
|
window->touch_devices = g_array_new (FALSE, FALSE, sizeof (GstXvTouchDevice));
|
||||||
|
g_array_set_clear_func (window->touch_devices,
|
||||||
|
(GDestroyNotify) gst_xv_touchdevice_free);
|
||||||
|
#endif
|
||||||
|
|
||||||
window->gc = XCreateGC (context->disp, window->win, 0, NULL);
|
window->gc = XCreateGC (context->disp, window->win, 0, NULL);
|
||||||
g_mutex_unlock (&context->lock);
|
g_mutex_unlock (&context->lock);
|
||||||
|
|
||||||
|
@ -1050,6 +1098,10 @@ gst_xwindow_destroy (GstXWindow * window)
|
||||||
|
|
||||||
g_mutex_lock (&context->lock);
|
g_mutex_lock (&context->lock);
|
||||||
|
|
||||||
|
#ifdef HAVE_XI2
|
||||||
|
g_array_free (window->touch_devices, TRUE);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* If we did not create that window we just free the GC and let it live */
|
/* If we did not create that window we just free the GC and let it live */
|
||||||
if (window->internal)
|
if (window->internal)
|
||||||
XDestroyWindow (context->disp, window->win);
|
XDestroyWindow (context->disp, window->win);
|
||||||
|
@ -1067,6 +1119,91 @@ gst_xwindow_destroy (GstXWindow * window)
|
||||||
g_slice_free1 (sizeof (GstXWindow), window);
|
g_slice_free1 (sizeof (GstXWindow), window);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_XI2
|
||||||
|
void
|
||||||
|
gst_xwindow_select_touch_events (GstXvContext * context, GstXWindow * window)
|
||||||
|
{
|
||||||
|
XIDeviceInfo *devices;
|
||||||
|
int ndevices, i, j, mask_len;
|
||||||
|
unsigned char *mask;
|
||||||
|
|
||||||
|
window->touch_devices = g_array_remove_range (window->touch_devices,
|
||||||
|
0, window->touch_devices->len);
|
||||||
|
|
||||||
|
mask_len = (XI_LASTEVENT + 7) << 3;
|
||||||
|
mask = g_new0 (unsigned char, mask_len);
|
||||||
|
XISetMask (mask, XI_TouchBegin);
|
||||||
|
XISetMask (mask, XI_TouchUpdate);
|
||||||
|
XISetMask (mask, XI_TouchEnd);
|
||||||
|
|
||||||
|
devices = XIQueryDevice (window->context->disp, XIAllDevices, &ndevices);
|
||||||
|
|
||||||
|
/* Find suitable touch screen devices, and select touch events for each */
|
||||||
|
for (i = 0; i < ndevices; i++) {
|
||||||
|
XIEventMask mask_data;
|
||||||
|
GstXvTouchDevice temp, *device;
|
||||||
|
gboolean has_touch = FALSE;
|
||||||
|
|
||||||
|
if (devices[i].use != XISlavePointer)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
temp.pressure_valuator = -1;
|
||||||
|
temp.id = devices[i].deviceid;
|
||||||
|
temp.name = devices[i].name;
|
||||||
|
|
||||||
|
for (j = 0; j < devices[i].num_classes; j++) {
|
||||||
|
XIAnyClassInfo *class = devices[i].classes[j];
|
||||||
|
|
||||||
|
/* only pick devices with direct touch, to avoid touchpads and similar */
|
||||||
|
if (class->type == XITouchClass &&
|
||||||
|
((XITouchClassInfo *) class)->mode == XIDirectTouch) {
|
||||||
|
has_touch = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Find the valuator representing pressure, if present */
|
||||||
|
if (class->type == XIValuatorClass) {
|
||||||
|
XIValuatorClassInfo *val_info = (XIValuatorClassInfo *) class;
|
||||||
|
|
||||||
|
if (val_info->label == XInternAtom (context->disp,
|
||||||
|
"Abs Pressure", TRUE))
|
||||||
|
temp.abs_pressure = TRUE;
|
||||||
|
else if (val_info->label == XInternAtom (context->disp,
|
||||||
|
"Rel Pressure", TRUE))
|
||||||
|
temp.abs_pressure = FALSE;
|
||||||
|
else
|
||||||
|
continue;
|
||||||
|
|
||||||
|
temp.pressure_valuator = i;
|
||||||
|
temp.pressure_min = val_info->min;
|
||||||
|
temp.pressure_max = val_info->max;
|
||||||
|
temp.current_pressure = temp.pressure_min;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (has_touch) {
|
||||||
|
GST_DEBUG ("found%s touch screen with id %d: %s",
|
||||||
|
temp.pressure_valuator < 0 ? "" : (temp.abs_pressure ?
|
||||||
|
"pressure-sensitive (abs)" : "pressure-sensitive (rel)"),
|
||||||
|
temp.id, temp.name);
|
||||||
|
|
||||||
|
device = g_new (GstXvTouchDevice, 1);
|
||||||
|
*device = temp;
|
||||||
|
device->name = g_strdup (device->name);
|
||||||
|
window->touch_devices =
|
||||||
|
g_array_append_vals (window->touch_devices, device, 1);
|
||||||
|
|
||||||
|
mask_data.deviceid = temp.id;
|
||||||
|
mask_data.mask_len = mask_len;
|
||||||
|
mask_data.mask = mask;
|
||||||
|
XISelectEvents (context->disp, window->win, &mask_data, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
g_free (mask);
|
||||||
|
XIFreeDeviceInfo (devices);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void
|
void
|
||||||
gst_xwindow_set_event_handling (GstXWindow * window, gboolean handle_events)
|
gst_xwindow_set_event_handling (GstXWindow * window, gboolean handle_events)
|
||||||
{
|
{
|
||||||
|
@ -1087,6 +1224,23 @@ gst_xwindow_set_event_handling (GstXWindow * window, gboolean handle_events)
|
||||||
ExposureMask | StructureNotifyMask | PointerMotionMask |
|
ExposureMask | StructureNotifyMask | PointerMotionMask |
|
||||||
KeyPressMask | KeyReleaseMask);
|
KeyPressMask | KeyReleaseMask);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_XI2
|
||||||
|
if (context->use_xi2) {
|
||||||
|
XIEventMask mask_data;
|
||||||
|
unsigned char mask[2];
|
||||||
|
|
||||||
|
gst_xwindow_select_touch_events (context, window);
|
||||||
|
|
||||||
|
XISetMask (mask, XI_HierarchyChanged);
|
||||||
|
mask_data.deviceid = XIAllDevices;
|
||||||
|
mask_data.mask_len = sizeof (mask);
|
||||||
|
mask_data.mask = mask;
|
||||||
|
|
||||||
|
/* register for HierarchyChanged events to see device changes */
|
||||||
|
XISelectEvents (context->disp, window->win, &mask_data, 1);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
} else {
|
} else {
|
||||||
XSelectInput (context->disp, window->win, 0);
|
XSelectInput (context->disp, window->win, 0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,6 +47,7 @@ G_BEGIN_DECLS
|
||||||
typedef struct _GstXvContextConfig GstXvContextConfig;
|
typedef struct _GstXvContextConfig GstXvContextConfig;
|
||||||
typedef struct _GstXvImageFormat GstXvImageFormat;
|
typedef struct _GstXvImageFormat GstXvImageFormat;
|
||||||
typedef struct _GstXvContext GstXvContext;
|
typedef struct _GstXvContext GstXvContext;
|
||||||
|
typedef struct _GstXvTouchDevice GstXvTouchDevice;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GstXvContextConfig:
|
* GstXvContextConfig:
|
||||||
|
@ -112,6 +113,9 @@ struct _GstXvImageFormat
|
||||||
* if the Extension is present
|
* if the Extension is present
|
||||||
* @use_xkb: used to known wether of not Xkb extension is usable or not even
|
* @use_xkb: used to known wether of not Xkb extension is usable or not even
|
||||||
* if the Extension is present
|
* if the Extension is present
|
||||||
|
* @use_xi2: used to known wether of not XInput extension is usable or not even
|
||||||
|
* if the Extension is present
|
||||||
|
* @xi_opcode: XInput opcode
|
||||||
* @xv_port_id: the XVideo port ID
|
* @xv_port_id: the XVideo port ID
|
||||||
* @im_format: used to store at least a valid format for XShm calls checks
|
* @im_format: used to store at least a valid format for XShm calls checks
|
||||||
* @formats_list: list of supported image formats on @xv_port_id
|
* @formats_list: list of supported image formats on @xv_port_id
|
||||||
|
@ -148,6 +152,8 @@ struct _GstXvContext
|
||||||
|
|
||||||
gboolean use_xshm;
|
gboolean use_xshm;
|
||||||
gboolean use_xkb;
|
gboolean use_xkb;
|
||||||
|
gboolean use_xi2;
|
||||||
|
int xi_opcode;
|
||||||
|
|
||||||
XvPortID xv_port_id;
|
XvPortID xv_port_id;
|
||||||
guint nb_adaptors;
|
guint nb_adaptors;
|
||||||
|
@ -217,6 +223,8 @@ typedef struct _GstXWindow GstXWindow;
|
||||||
* @internal: used to remember if Window @win was created internally or passed
|
* @internal: used to remember if Window @win was created internally or passed
|
||||||
* through the #GstVideoOverlay interface
|
* through the #GstVideoOverlay interface
|
||||||
* @gc: the Graphical Context of Window @win
|
* @gc: the Graphical Context of Window @win
|
||||||
|
* @last_touch: timestamp of the last received touch event
|
||||||
|
* @touch_devices: list of known touchscreen devices
|
||||||
*
|
*
|
||||||
* Structure used to store information about a Window.
|
* Structure used to store information about a Window.
|
||||||
*/
|
*/
|
||||||
|
@ -230,6 +238,30 @@ struct _GstXWindow
|
||||||
GstVideoRectangle render_rect;
|
GstVideoRectangle render_rect;
|
||||||
gboolean internal;
|
gboolean internal;
|
||||||
GC gc;
|
GC gc;
|
||||||
|
|
||||||
|
#ifdef HAVE_XI2
|
||||||
|
Time last_touch;
|
||||||
|
GArray *touch_devices;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* GstXvTouchDevice:
|
||||||
|
* @name: the name of this decive
|
||||||
|
* @id: the device ID of this device
|
||||||
|
* @pressure_valuator: index of the valuator that encodes pressure data, if present
|
||||||
|
* @abs_pressure: if pressure is reported in absolute or relative values
|
||||||
|
* @current_pressure: stores the most recent pressure value for this device
|
||||||
|
* @pressure_min: lowest possible pressure value
|
||||||
|
* @pressure_max: highest possible pressure value
|
||||||
|
*
|
||||||
|
* Structure used to store information about a touchscreen device.
|
||||||
|
*/
|
||||||
|
struct _GstXvTouchDevice {
|
||||||
|
gchar *name;
|
||||||
|
gint id, pressure_valuator;
|
||||||
|
gboolean abs_pressure;
|
||||||
|
gdouble current_pressure, pressure_min, pressure_max;
|
||||||
};
|
};
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
@ -240,6 +272,10 @@ GstXWindow * gst_xvcontext_create_xwindow_from_xid (GstXvContext * context, XI
|
||||||
|
|
||||||
void gst_xwindow_destroy (GstXWindow * window);
|
void gst_xwindow_destroy (GstXWindow * window);
|
||||||
|
|
||||||
|
#ifdef HAVE_XI2
|
||||||
|
void gst_xwindow_select_touch_events (GstXvContext * context, GstXWindow * window);
|
||||||
|
#endif
|
||||||
|
|
||||||
void gst_xwindow_set_event_handling (GstXWindow * window, gboolean handle_events);
|
void gst_xwindow_set_event_handling (GstXWindow * window, gboolean handle_events);
|
||||||
void gst_xwindow_set_title (GstXWindow * window, const gchar * title);
|
void gst_xwindow_set_title (GstXWindow * window, const gchar * title);
|
||||||
|
|
||||||
|
|
|
@ -132,6 +132,11 @@
|
||||||
/* for XkbKeycodeToKeysym */
|
/* for XkbKeycodeToKeysym */
|
||||||
#include <X11/XKBlib.h>
|
#include <X11/XKBlib.h>
|
||||||
|
|
||||||
|
/* for touchscreen events */
|
||||||
|
#ifdef HAVE_XI2
|
||||||
|
#include <X11/extensions/XInput2.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
GST_DEBUG_CATEGORY_EXTERN (gst_debug_xv_context);
|
GST_DEBUG_CATEGORY_EXTERN (gst_debug_xv_context);
|
||||||
GST_DEBUG_CATEGORY_EXTERN (gst_debug_xv_image_pool);
|
GST_DEBUG_CATEGORY_EXTERN (gst_debug_xv_image_pool);
|
||||||
GST_DEBUG_CATEGORY (gst_debug_xv_image_sink);
|
GST_DEBUG_CATEGORY (gst_debug_xv_image_sink);
|
||||||
|
@ -418,7 +423,7 @@ gst_xv_image_sink_handle_xevents (GstXvImageSink * xvimagesink)
|
||||||
{
|
{
|
||||||
XEvent e;
|
XEvent e;
|
||||||
gint pointer_x = 0, pointer_y = 0;
|
gint pointer_x = 0, pointer_y = 0;
|
||||||
gboolean pointer_moved = FALSE;
|
gboolean pointer_moved = FALSE, touch_frame_open = FALSE;
|
||||||
gboolean exposed = FALSE, configured = FALSE;
|
gboolean exposed = FALSE, configured = FALSE;
|
||||||
|
|
||||||
g_return_if_fail (GST_IS_XV_IMAGE_SINK (xvimagesink));
|
g_return_if_fail (GST_IS_XV_IMAGE_SINK (xvimagesink));
|
||||||
|
@ -557,11 +562,11 @@ gst_xv_image_sink_handle_xevents (GstXvImageSink * xvimagesink)
|
||||||
g_mutex_lock (&xvimagesink->context->lock);
|
g_mutex_lock (&xvimagesink->context->lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Handle Display events */
|
|
||||||
while (XPending (xvimagesink->context->disp)) {
|
while (XPending (xvimagesink->context->disp)) {
|
||||||
XNextEvent (xvimagesink->context->disp, &e);
|
XNextEvent (xvimagesink->context->disp, &e);
|
||||||
|
|
||||||
switch (e.type) {
|
switch (e.type) {
|
||||||
|
/* Handle Display events */
|
||||||
case ClientMessage:{
|
case ClientMessage:{
|
||||||
Atom wm_delete;
|
Atom wm_delete;
|
||||||
|
|
||||||
|
@ -579,13 +584,139 @@ gst_xv_image_sink_handle_xevents (GstXvImageSink * xvimagesink)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
default:{
|
||||||
|
#ifdef HAVE_XI2
|
||||||
|
/* Handle XInput2 touch screen events */
|
||||||
|
if (xvimagesink->context->use_xi2
|
||||||
|
&& XGetEventData (xvimagesink->context->disp,
|
||||||
|
(XGenericEventCookie *) & e)
|
||||||
|
&& e.xcookie.extension == xvimagesink->context->xi_opcode) {
|
||||||
|
XGenericEventCookie *cookie;
|
||||||
|
XIDeviceEvent *touch;
|
||||||
|
GstXvTouchDevice device;
|
||||||
|
GstXWindow *xwindow;
|
||||||
|
GstEvent *nav;
|
||||||
|
gdouble pressure;
|
||||||
|
gboolean device_found;
|
||||||
|
unsigned int ev_id, i;
|
||||||
|
|
||||||
|
cookie = &e.xcookie;
|
||||||
|
xwindow = xvimagesink->xwindow;
|
||||||
|
nav = NULL;
|
||||||
|
|
||||||
|
if (cookie->evtype == XI_HierarchyChanged) {
|
||||||
|
GST_DEBUG ("ximagesink devices changed, searching for "
|
||||||
|
"touch devices again");
|
||||||
|
gst_xwindow_select_touch_events (xvimagesink->context, xwindow);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cookie->evtype != XI_TouchBegin
|
||||||
|
&& cookie->evtype != XI_TouchUpdate
|
||||||
|
&& cookie->evtype != XI_TouchEnd)
|
||||||
|
break;
|
||||||
|
|
||||||
|
touch = cookie->data;
|
||||||
|
ev_id = ((unsigned int) touch->deviceid) << 16 |
|
||||||
|
(((unsigned int) touch->detail) & 0x00ff);
|
||||||
|
|
||||||
|
/* find device that the event belongs to */
|
||||||
|
device_found = FALSE;
|
||||||
|
for (i = 0; i < xwindow->touch_devices->len; i++) {
|
||||||
|
device = g_array_index (xwindow->touch_devices,
|
||||||
|
GstXvTouchDevice, i);
|
||||||
|
if (device.id == touch->deviceid) {
|
||||||
|
device_found = TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!device_found)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (device.pressure_valuator >= 0) {
|
||||||
|
pressure = touch->valuators.values[device.pressure_valuator];
|
||||||
|
pressure -= device.pressure_min;
|
||||||
|
pressure /= device.pressure_max - device.pressure_min;
|
||||||
|
if (!device.abs_pressure)
|
||||||
|
pressure += device.current_pressure;
|
||||||
|
} else
|
||||||
|
pressure = NAN;
|
||||||
|
|
||||||
|
device.current_pressure = pressure;
|
||||||
|
|
||||||
|
g_mutex_unlock (&xvimagesink->context->lock);
|
||||||
|
g_mutex_unlock (&xvimagesink->flow_lock);
|
||||||
|
|
||||||
|
/* assume the event queue is ordered chronologically, and end */
|
||||||
|
/* the previous touch event frame when the timestamp increases */
|
||||||
|
if (touch->time != xwindow->last_touch && touch_frame_open) {
|
||||||
|
if (touch->time < xwindow->last_touch) {
|
||||||
|
GST_WARNING ("ximagesink out of order touch event "
|
||||||
|
"with timestamp %lu, not ending touch frame", touch->time);
|
||||||
|
} else {
|
||||||
|
GST_DEBUG ("ximagesink ending touch frame for %lu",
|
||||||
|
xwindow->last_touch);
|
||||||
|
gst_navigation_send_event_simple (GST_NAVIGATION (xvimagesink),
|
||||||
|
gst_navigation_event_new_touch_frame ());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (cookie->evtype) {
|
||||||
|
case XI_TouchBegin:{
|
||||||
|
GST_DEBUG ("xvimagesink new touch point %d on device %d "
|
||||||
|
"at %.0f,%.0f", touch->detail, touch->deviceid,
|
||||||
|
touch->event_x, touch->event_y);
|
||||||
|
nav = gst_navigation_event_new_touch_down (ev_id,
|
||||||
|
touch->event_x, touch->event_y, pressure);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case XI_TouchEnd:{
|
||||||
|
GST_DEBUG ("xvimagesink removed touch point %d from device %d "
|
||||||
|
"at %.0f,%.0f", touch->detail, touch->deviceid,
|
||||||
|
touch->event_x, touch->event_y);
|
||||||
|
nav = gst_navigation_event_new_touch_up (ev_id,
|
||||||
|
touch->event_x, touch->event_y);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case XI_TouchUpdate:{
|
||||||
|
GST_DEBUG ("xvimagesink touch point %d on device %d moved "
|
||||||
|
"to %.0f,%.0f", touch->detail, touch->deviceid,
|
||||||
|
touch->event_x, touch->event_y);
|
||||||
|
nav = gst_navigation_event_new_touch_motion (ev_id,
|
||||||
|
touch->event_x, touch->event_y, pressure);
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gst_navigation_send_event_simple (GST_NAVIGATION (xvimagesink), nav);
|
||||||
|
xvimagesink->xwindow->last_touch = touch->time;
|
||||||
|
touch_frame_open = TRUE;
|
||||||
|
|
||||||
|
g_mutex_lock (&xvimagesink->flow_lock);
|
||||||
|
g_mutex_lock (&xvimagesink->context->lock);
|
||||||
|
XFreeEventData (xvimagesink->context->disp, cookie);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
g_mutex_unlock (&xvimagesink->context->lock);
|
g_mutex_unlock (&xvimagesink->context->lock);
|
||||||
g_mutex_unlock (&xvimagesink->flow_lock);
|
g_mutex_unlock (&xvimagesink->flow_lock);
|
||||||
|
|
||||||
|
#ifdef HAVE_XI2
|
||||||
|
/* send a touch-frame event now to avoid delay from having to wait for the */
|
||||||
|
/* next invocation */
|
||||||
|
if (touch_frame_open) {
|
||||||
|
GST_DEBUG ("xvimagesink ending touch frame for %lu",
|
||||||
|
xvimagesink->xwindow->last_touch);
|
||||||
|
gst_navigation_send_event_simple (GST_NAVIGATION (xvimagesink),
|
||||||
|
gst_navigation_event_new_touch_frame ());
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static gpointer
|
static gpointer
|
||||||
|
|
Loading…
Reference in a new issue