summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Larsson <alexl@redhat.com>2015-06-08 15:36:43 +0200
committerAlexander Larsson <alexl@redhat.com>2015-06-15 10:56:45 +0200
commit4c3eece6638aa36fbcd8379109dcb4e27323a306 (patch)
treec84c9e853bef2325b9402253423f9960bab88610
parentccc4b192ec994ee06817fbf19ff8c662be8d995a (diff)
downloadgtk+-4c3eece6638aa36fbcd8379109dcb4e27323a306.tar.gz
gdk: Add gdk_window_set_pass_through
An pass_through window is something you can draw in but does not affect event handling. Normally if a window has with no event mask set for a particular event then input events in it go to its parent window (X11 semantics), whereas if pass_through is enabled the window below the window will get the event. The later mode is useful when the window is partially transparent. Note that an pass-through windows can have child windows that are not pass-through so they can still get events on some parts. Semantically, this behaves the same as an regular window with gdk_window_set_child_input_shapes() called on it (and re-called any time a child is changed), but its far more efficient and easy to use. This allows us to fix the testoverlay input stacking test. https://bugzilla.gnome.org/show_bug.cgi?id=750568 https://bugs.freedesktop.org/show_bug.cgi?id=90917
-rw-r--r--gdk/gdkinternals.h1
-rw-r--r--gdk/gdkwindow.c125
-rw-r--r--gdk/gdkwindow.h6
3 files changed, 128 insertions, 4 deletions
diff --git a/gdk/gdkinternals.h b/gdk/gdkinternals.h
index d1d1e4d167..e5ec4b204d 100644
--- a/gdk/gdkinternals.h
+++ b/gdk/gdkinternals.h
@@ -314,6 +314,7 @@ struct _GdkWindow
guint8 fullscreen_mode;
guint input_only : 1;
+ guint pass_through : 1;
guint modal_hint : 1;
guint composited : 1;
guint has_alpha_background : 1;
diff --git a/gdk/gdkwindow.c b/gdk/gdkwindow.c
index 612d796a2f..faa848c243 100644
--- a/gdk/gdkwindow.c
+++ b/gdk/gdkwindow.c
@@ -6785,6 +6785,64 @@ gdk_window_set_child_input_shapes (GdkWindow *window)
}
/**
+ * gdk_window_set_pass_through:
+ * @window: a #GdkWindow
+ * @pass_through: a boolean
+ *
+ * Sets whether input to the window is passed through to the window
+ * below.
+ *
+ * The default value of this is %FALSE, which means that pointer
+ * events that happen inside the window are send first to the window,
+ * but if the event is not selected by the event mask then the event
+ * is sent to the parent window, and so on up the hierarchy.
+ *
+ * If @pass_through is %TRUE then such pointer events happen as if the
+ * window wasn't there at all, and thus will be sent first to any
+ * windows below @window. This is useful if the window is used in a
+ * transparent fashion. In the terminology of the web this would be called
+ * "pointer-events: none".
+ *
+ * Note that a window with @pass_through %TRUE can still have a subwindow
+ * without pass through, so you can get events on a subset of a window. And in
+ * that cases you would get the in-between related events such as the pointer
+ * enter/leave events on its way to the destination window.
+ *
+ * Since: 3.18
+ **/
+void
+gdk_window_set_pass_through (GdkWindow *window,
+ gboolean pass_through)
+{
+ g_return_if_fail (GDK_IS_WINDOW (window));
+
+ window->pass_through = !!pass_through;
+
+ /* Pointer may have e.g. moved outside window due to the input region change */
+ _gdk_synthesize_crossing_events_for_geometry_change (window);
+}
+
+/**
+ * gdk_window_get_pass_through:
+ * @window: a #GdkWindow
+ * @pass_through: a boolean
+ *
+ * Returns whether input to the window is passed through to the window
+ * below.
+ *
+ * See gdk_window_set_pass_through() for details
+ *
+ * Since: 3.18
+ **/
+gboolean
+gdk_window_get_pass_through (GdkWindow *window)
+{
+ g_return_if_fail (GDK_IS_WINDOW (window));
+
+ return window->pass_through;
+}
+
+/**
* gdk_window_merge_child_input_shapes:
* @window: a #GdkWindow
*
@@ -7133,6 +7191,63 @@ point_in_window (GdkWindow *window,
x, y));
}
+/* Same as point_in_window, except it also takes pass_through and its
+ interaction with child windows into account */
+static gboolean
+point_in_input_window (GdkWindow *window,
+ gdouble x,
+ gdouble y,
+ GdkWindow **input_window,
+ gdouble *input_window_x,
+ gdouble *input_window_y)
+{
+ GdkWindow *sub;
+ double child_x, child_y;
+ GList *l;
+
+ if (!point_in_window (window, x, y))
+ return FALSE;
+
+ if (!window->pass_through)
+ {
+ if (input_window)
+ {
+ *input_window = window;
+ *input_window_x = x;
+ *input_window_y = y;
+ }
+ return TRUE;
+ }
+
+ /* For pass-through, must be over a child input window */
+
+ /* Children is ordered in reverse stack order, i.e. first is topmost */
+ for (l = window->children; l != NULL; l = l->next)
+ {
+ sub = l->data;
+
+ if (!GDK_WINDOW_IS_MAPPED (sub))
+ continue;
+
+ gdk_window_coords_from_parent ((GdkWindow *)sub,
+ x, y,
+ &child_x, &child_y);
+ if (point_in_input_window (sub, child_x, child_y,
+ input_window, input_window_x, input_window_y))
+ {
+ if (input_window)
+ gdk_window_coords_to_parent (sub,
+ *input_window_x,
+ *input_window_y,
+ input_window_x,
+ input_window_y);
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
static GdkWindow *
convert_native_coords_to_toplevel (GdkWindow *window,
gdouble child_x,
@@ -7226,7 +7341,8 @@ _gdk_window_find_child_at (GdkWindow *window,
gdk_window_coords_from_parent ((GdkWindow *)sub,
x, y,
&child_x, &child_y);
- if (point_in_window (sub, child_x, child_y))
+ if (point_in_input_window (sub, child_x, child_y,
+ NULL, NULL, NULL))
return (GdkWindow *)sub;
}
@@ -7249,7 +7365,7 @@ _gdk_window_find_descendant_at (GdkWindow *window,
gdouble *found_x,
gdouble *found_y)
{
- GdkWindow *sub;
+ GdkWindow *sub, *input_window;
gdouble child_x, child_y;
GList *l;
gboolean found;
@@ -7270,11 +7386,12 @@ _gdk_window_find_descendant_at (GdkWindow *window,
gdk_window_coords_from_parent ((GdkWindow *)sub,
x, y,
&child_x, &child_y);
- if (point_in_window (sub, child_x, child_y))
+ if (point_in_input_window (sub, child_x, child_y,
+ &input_window, &child_x, &child_y))
{
x = child_x;
y = child_y;
- window = sub;
+ window = input_window;
found = TRUE;
break;
}
diff --git a/gdk/gdkwindow.h b/gdk/gdkwindow.h
index ad5e88cc14..b42f9dfe93 100644
--- a/gdk/gdkwindow.h
+++ b/gdk/gdkwindow.h
@@ -654,6 +654,12 @@ GDK_AVAILABLE_IN_ALL
void gdk_window_merge_child_input_shapes (GdkWindow *window);
+GDK_AVAILABLE_IN_3_18
+void gdk_window_set_pass_through (GdkWindow *window,
+ gboolean pass_through);
+GDK_AVAILABLE_IN_3_18
+gboolean gdk_window_get_pass_through (GdkWindow *window);
+
/*
* Check if a window has been shown, and whether all its
* parents up to a toplevel have been shown, respectively.