summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarlos Garnacho <carlosg@gnome.org>2017-09-19 18:14:53 +0200
committerCarlos Garnacho <carlosg@gnome.org>2017-09-19 18:40:51 +0200
commitfb81d7fc8fca701847f614aebc647ce9fd836a4a (patch)
tree7d6e0f12c06450291c63e40268874655987e4911
parent97139e4027c42578cd320a5393dc64fb0dcc7e36 (diff)
downloadgtk+-fb81d7fc8fca701847f614aebc647ce9fd836a4a.tar.gz
gdk/x11: Implement GDK_CROSSING_TOUCH_BEGIN/END/DEVICE_CHANGE events
The behavior where a touchpoint takes over the pointer position is really backend dependent. Since this went away from the generic code, implement it here.
-rw-r--r--gdk/x11/gdkeventsource.c106
1 files changed, 106 insertions, 0 deletions
diff --git a/gdk/x11/gdkeventsource.c b/gdk/x11/gdkeventsource.c
index 774d10c528..ae465db7bb 100644
--- a/gdk/x11/gdkeventsource.c
+++ b/gdk/x11/gdkeventsource.c
@@ -32,6 +32,8 @@ static gboolean gdk_event_source_dispatch (GSource *source,
gpointer user_data);
static void gdk_event_source_finalize (GSource *source);
+static GQuark quark_needs_enter = 0;
+
#define HAS_FOCUS(toplevel) \
((toplevel)->has_focus || (toplevel)->has_pointer_focus)
@@ -167,6 +169,100 @@ handle_focus_change (GdkEventCrossing *event)
}
static GdkEvent *
+create_synth_crossing_event (GdkEventType evtype,
+ GdkCrossingMode mode,
+ const GdkEvent *real_event)
+{
+ GdkEvent *event;
+ gdouble x, y;
+ GdkModifierType state;
+
+ g_assert (evtype == GDK_ENTER_NOTIFY || evtype == GDK_LEAVE_NOTIFY);
+
+ event = gdk_event_new (evtype);
+ event->crossing.send_event = TRUE;
+ event->crossing.window = g_object_ref (real_event->any.window);
+ event->crossing.detail = GDK_NOTIFY_ANCESTOR;
+ event->crossing.mode = mode;
+ event->crossing.time = gdk_event_get_time (real_event);
+ gdk_event_set_device (event, gdk_event_get_device (real_event));
+ gdk_event_set_source_device (event, gdk_event_get_device (real_event));
+
+ if (gdk_event_get_state (real_event, &state))
+ event->crossing.state = state;
+
+ if (gdk_event_get_coords (real_event, &x, &y))
+ gdk_event_set_coords (event, x, y);
+
+ return event;
+}
+
+static void
+handle_touch_synthetic_crossing (GdkEvent *event)
+{
+ GdkEventType evtype = gdk_event_get_event_type (event);
+ GdkDevice *device = gdk_event_get_device (event);
+ GdkEvent *crossing = NULL;
+ GdkSeat *seat = gdk_device_get_seat (device);
+ gboolean needs_enter, set_needs_enter = FALSE;
+
+ if (quark_needs_enter == 0)
+ quark_needs_enter = g_quark_from_static_string ("gdk-x11-needs-enter-after-touch-end");
+
+ needs_enter =
+ GPOINTER_TO_UINT (g_object_get_qdata (G_OBJECT (seat), quark_needs_enter));
+
+ if (evtype == GDK_MOTION_NOTIFY && needs_enter)
+ {
+ set_needs_enter = FALSE;
+ crossing = create_synth_crossing_event (GDK_ENTER_NOTIFY,
+ GDK_CROSSING_DEVICE_SWITCH,
+ event);
+ }
+ else if (evtype == GDK_TOUCH_BEGIN && needs_enter &&
+ gdk_event_get_pointer_emulated (event))
+ {
+ set_needs_enter = FALSE;
+ crossing = create_synth_crossing_event (GDK_ENTER_NOTIFY,
+ GDK_CROSSING_TOUCH_BEGIN,
+ event);
+ }
+ else if (evtype == GDK_TOUCH_END &&
+ gdk_event_get_pointer_emulated (event))
+ {
+ set_needs_enter = TRUE;
+ crossing = create_synth_crossing_event (GDK_LEAVE_NOTIFY,
+ GDK_CROSSING_TOUCH_END,
+ event);
+ }
+ else if (evtype == GDK_ENTER_NOTIFY ||
+ evtype == GDK_LEAVE_NOTIFY)
+ {
+ /* We are receiving or shall receive a real crossing event,
+ * turn this off.
+ */
+ set_needs_enter = FALSE;
+ }
+ else
+ return;
+
+ if (needs_enter != set_needs_enter)
+ {
+ if (!set_needs_enter)
+ g_object_steal_qdata (G_OBJECT (seat), quark_needs_enter);
+ else
+ g_object_set_qdata (G_OBJECT (seat), quark_needs_enter,
+ GUINT_TO_POINTER (TRUE));
+ }
+
+ if (crossing)
+ {
+ gdk_event_put (crossing);
+ gdk_event_free (crossing);
+ }
+}
+
+static GdkEvent *
gdk_event_source_translate_event (GdkEventSource *event_source,
XEvent *xevent)
{
@@ -255,6 +351,16 @@ gdk_event_source_translate_event (GdkEventSource *event_source,
handle_focus_change (&event->crossing);
}
+ if (event &&
+ (event->type == GDK_TOUCH_BEGIN ||
+ event->type == GDK_TOUCH_END ||
+ event->type == GDK_MOTION_NOTIFY ||
+ event->type == GDK_ENTER_NOTIFY ||
+ event->type == GDK_LEAVE_NOTIFY))
+ {
+ handle_touch_synthetic_crossing (event);
+ }
+
#ifdef HAVE_XGENERICEVENTS
if (xevent->type == GenericEvent)
XFreeEventData (dpy, &xevent->xcookie);