linux-packaging-mono/external/bockbuild/packages/patches/gtk/0019-Add-hack-to-lock-flow-of-scroll-events-to-window-whe.patch

145 lines
5.4 KiB
Diff
Raw Normal View History

From 026f9bc1846eae8fa98a307975fedce1f61d9cd5 Mon Sep 17 00:00:00 2001
From: Kristian Rietveld <kris@lanedo.com>
Date: Fri, 28 Sep 2012 08:24:05 +0200
Subject: [PATCH 19/68] Add hack to lock flow of scroll events to window where
scroll started
A bit evil but there is probably no other way, because this is very
different from GDK's usual behavior.
There's one quirk left, if you start a scroll and move to another GTK+
window in the same process and click, the click won't be processed until
the folow of momentum events has ended.
---
gdk/gdkwindow.c | 94 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 94 insertions(+)
diff --git a/gdk/gdkwindow.c b/gdk/gdkwindow.c
index 1843873..1dac543 100644
--- a/gdk/gdkwindow.c
+++ b/gdk/gdkwindow.c
@@ -434,6 +434,10 @@ accumulate_get_window (GSignalInvocationHint *ihint,
}
static GQuark quark_pointer_window = 0;
+#ifdef GDK_WINDOWING_QUARTZ
+static GQuark quark_last_scroll_pointer_window = 0;
+static GQuark quark_last_scroll_event_window = 0;
+#endif /* GDK_WINDOWING_QUARTZ */
static void
gdk_window_class_init (GdkWindowObjectClass *klass)
@@ -478,6 +482,12 @@ gdk_window_class_init (GdkWindowObjectClass *klass)
drawable_class->get_source_drawable = gdk_window_get_source_drawable;
quark_pointer_window = g_quark_from_static_string ("gtk-pointer-window");
+#ifdef GDK_WINDOWING_QUARTZ
+ quark_last_scroll_pointer_window =
+ g_quark_from_static_string ("gtk-last-scroll-pointer-window");
+ quark_last_scroll_event_window =
+ g_quark_from_static_string ("gtk-last-scroll-event-window");
+#endif /* GDK_WINDOWING_QUARTZ */
/* Properties */
@@ -10702,6 +10712,64 @@ proxy_pointer_event (GdkDisplay *display,
GDK_BUTTON4_MASK | \
GDK_BUTTON5_MASK)
+#ifdef GDK_WINDOWING_QUARTZ
+static void
+last_scroll_event_weak_ref_notify (gpointer data,
+ GObject *where_the_object_was)
+{
+ /* If any of pointer_window or event_window is destroyed, we unset
+ * both values in the display's qdata.
+ */
+ GdkDisplay *display = data;
+
+ g_object_set_qdata (G_OBJECT (display), quark_last_scroll_pointer_window,
+ NULL);
+ g_object_set_qdata (G_OBJECT (display), quark_last_scroll_event_window,
+ NULL);
+}
+
+static void
+set_last_scroll_event_windows (GdkDisplay *display,
+ GdkWindow *pointer_window,
+ GdkWindow *event_window)
+{
+ GdkWindow *old_window;
+
+ /* Check whether the values are still set from a previous scroll,
+ * if so we need to release the weak references. (If they are no
+ * longer set, we assume the weak ref notify callback was called).
+ */
+ old_window = g_object_get_qdata (G_OBJECT (display),
+ quark_last_scroll_pointer_window);
+ if (old_window)
+ g_object_weak_unref (G_OBJECT (old_window),
+ last_scroll_event_weak_ref_notify, display);
+
+ old_window = g_object_get_qdata (G_OBJECT (display),
+ quark_last_scroll_event_window);
+ if (old_window)
+ g_object_weak_unref (G_OBJECT (old_window),
+ last_scroll_event_weak_ref_notify, display);
+
+ /* Set new values and setup weak references. Note that pointer_window
+ * and event_window can be NULL, in which case GDK won't proxy the
+ * event. In this case we store NULL into the qdata so that we won't
+ * store the scroll event.
+ */
+ g_object_set_qdata (G_OBJECT (display), quark_last_scroll_pointer_window,
+ pointer_window);
+ if (pointer_window)
+ g_object_weak_ref (G_OBJECT (pointer_window),
+ last_scroll_event_weak_ref_notify, display);
+
+ g_object_set_qdata (G_OBJECT (display), quark_last_scroll_event_window,
+ event_window);
+ if (event_window)
+ g_object_weak_ref (G_OBJECT (event_window),
+ last_scroll_event_weak_ref_notify, display);
+}
+#endif /* GDK_WINDOWING_QUARTZ */
+
static gboolean
proxy_button_event (GdkEvent *source_event,
gulong serial)
@@ -10769,6 +10837,32 @@ proxy_button_event (GdkEvent *source_event,
type, state,
NULL, serial);
+#ifdef GDK_WINDOWING_QUARTZ
+ /* A Quartz-specific hack we cannot handle from within the backend
+ * unfortunately. For scroll events with precise deltas (i.e. these
+ * generated by the Mac touchpad or Magic Mouse, we want to lock the
+ * flow of events belonging to a single gesture to the window the
+ * gesture was started on. The default behavior of GDK, which insists
+ * to send events to the window under the pointer or discard the
+ * events when there's no GDK window under the pointer, makes it
+ * impossible to implement this differently.
+ */
+ if (type == GDK_SCROLL && source_event->scroll.has_deltas)
+ {
+ if (source_event->scroll.phase == GDK_EVENT_SCROLL_PHASE_START)
+ {
+ set_last_scroll_event_windows (display, pointer_window, event_win);
+ }
+ else
+ {
+ pointer_window = g_object_get_qdata (G_OBJECT (display),
+ quark_last_scroll_pointer_window);
+ event_win = g_object_get_qdata (G_OBJECT (display),
+ quark_last_scroll_event_window);
+ }
+ }
+#endif /* GDK_WINDOWING_QUARTZ */
+
if (event_win == NULL || display->ignore_core_events)
return TRUE;
--
1.7.10.2 (Apple Git-33)