After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 750568 - Add support for windows that are transparent wrt input
Add support for windows that are transparent wrt input
Status: RESOLVED FIXED
Product: gtk+
Classification: Platform
Component: .General
unspecified
Other Linux
: Normal enhancement
: ---
Assigned To: gtk-bugs
gtk-bugs
Depends on:
Blocks:
 
 
Reported: 2015-06-08 14:35 UTC by Alexander Larsson
Modified: 2015-06-17 18:49 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
testoverlay: Add new input stacking test (2.56 KB, patch)
2015-06-08 14:35 UTC, Alexander Larsson
none Details | Review
gdk: Add support for GDK_OUTPUT_ONLY windows (6.36 KB, patch)
2015-06-08 14:36 UTC, Alexander Larsson
none Details | Review
GtkOverlay: Add support for transparent (for input) overlays (7.89 KB, patch)
2015-06-08 14:36 UTC, Alexander Larsson
none Details | Review
testoverlay: Fix test by usint add_transparent_overlay (842 bytes, patch)
2015-06-08 14:36 UTC, Alexander Larsson
none Details | Review
testoverlay: Add new input stacking test (2.56 KB, patch)
2015-06-08 19:56 UTC, Alexander Larsson
none Details | Review
gdk: Add gdk_window_set_pass_through (6.76 KB, patch)
2015-06-08 19:56 UTC, Alexander Larsson
none Details | Review
GtkOverlay: Add support for input pass-through overlays (6.55 KB, patch)
2015-06-08 19:56 UTC, Alexander Larsson
none Details | Review
testoverlay: Fix test by usint add_pass_through_overlay (844 bytes, patch)
2015-06-08 19:56 UTC, Alexander Larsson
none Details | Review
testoverlay: Add new input stacking test (2.56 KB, patch)
2015-06-09 09:13 UTC, Alexander Larsson
accepted-commit_now Details | Review
gdk: Add gdk_window_set_pass_through (6.76 KB, patch)
2015-06-09 09:13 UTC, Alexander Larsson
accepted-commit_now Details | Review
overlay: Add reorder_overlay() (6.87 KB, patch)
2015-06-09 09:13 UTC, Alexander Larsson
reviewed Details | Review
GtkOverlay: Add support for input pass-through overlays (4.71 KB, patch)
2015-06-09 09:14 UTC, Alexander Larsson
reviewed Details | Review
testoverlay: Fix test by using add_pass_through_overlay (844 bytes, patch)
2015-06-09 09:14 UTC, Alexander Larsson
accepted-commit_now Details | Review
testoverlay: Add test for overlay z ordering (2.92 KB, patch)
2015-06-09 09:14 UTC, Alexander Larsson
accepted-commit_now Details | Review
docs: add new GtkOverlay methods to gtk3-sections.txt (760 bytes, patch)
2015-06-16 19:06 UTC, Cosimo Cecchi
accepted-commit_now Details | Review
overlay: add setters and getters for pass-through child property (3.26 KB, patch)
2015-06-16 19:06 UTC, Cosimo Cecchi
accepted-commit_now Details | Review
overlay: remove gtk_overlay_add_pass_through_overlay() (3.59 KB, patch)
2015-06-16 19:06 UTC, Cosimo Cecchi
accepted-commit_now Details | Review

Description Alexander Larsson 2015-06-08 14:35:24 UTC
Currently, when a window does not select for input events we propagate that event to the parent window. This is the X semantics an makes a lot of sense for opaque windows. However, if a window is transparent it makes more sense to propagate the event to whatever is below the window (which is likely a sibling window).

Jasper had issues with this trying to set up a grid of thumbnails that had hover and click with and overlayed semitransparent logo and entry. The entry worked, but in the whole rectangle for the logo vbox all events where stolen from the widgets below.
Comment 1 Alexander Larsson 2015-06-08 14:35:59 UTC
Created attachment 304773 [details] [review]
testoverlay: Add new input stacking test

In this case we have a bunch of interactive main children
of the overlay, and then a centered overlay that contains both
non-interactive (labels) and interactive (entry) widgets.

This shows off a problem where the non-interactive parts (the labels)
steals input from the overlay main children (breaks button click and
hover effects).
Comment 2 Alexander Larsson 2015-06-08 14:36:05 UTC
Created attachment 304774 [details] [review]
gdk: Add support for GDK_OUTPUT_ONLY windows

An output-only window is something you can draw in but does not affect
event handling. This is different from an input-output window with no
event mask in that such a window would send input events over it to
its parent window (X11 semantics), whereas an output-only window would
send it to whatever window is below it. The later mode is useful when
the window is partially transparent. Note that an output-only window
can have input-output and input-only children.

Semantically, these windows behave the same as an input-output 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.
Comment 3 Alexander Larsson 2015-06-08 14:36:13 UTC
Created attachment 304775 [details] [review]
GtkOverlay: Add support for transparent (for input) overlays

For these widgets we allocate an output-only window so that input
over these widgets (that are not on a child input window) goes to
the window below the overlay.
Comment 4 Alexander Larsson 2015-06-08 14:36:21 UTC
Created attachment 304776 [details] [review]
testoverlay: Fix test by usint add_transparent_overlay
Comment 5 Alexander Larsson 2015-06-08 14:37:46 UTC
This adds a test showing jaspers issue, then it implements GDK_OUTPUT_ONLY windows and uses these to fix the issue. I'm not super-fond of the word "transparent" used in the overlay part as it doesn't really talk about the visual side, but i can't think of a better name.
Comment 6 Alexander Larsson 2015-06-08 15:07:56 UTC
DOM calls this mode "pointer-events: none"
Comment 7 Benjamin Otte (Company) 2015-06-08 16:05:24 UTC
Comment on attachment 304775 [details] [review]
GtkOverlay: Add support for transparent (for input) overlays

I think this API is unfortunate. I think input acceptance should be a mutable boolean property on the window instead of a constuct-only property.

I would imagine that toggling input acceptance on widgets might be a runtime decision (ie when toggling widget sensitivity) and that should not require recreation of the GDK window.

Also technically, I don't see it requiring a lot more code to make it mutable.
Comment 8 Benjamin Otte (Company) 2015-06-08 16:07:41 UTC
Comment on attachment 304774 [details] [review]
gdk: Add support for GDK_OUTPUT_ONLY windows

That was the wrong patch I commented on, I meant to comment on this one.

Also, for a name, I'd suggest gdk_window_set_pass_through(GdkWindow *, gboolean);

It'd make not much sense to call that on input-only windows, so we might forbid it on those.
Comment 9 Alexander Larsson 2015-06-08 16:15:57 UTC
Yeah, making it a boolean is super easy, its in fact treated that way in the code already. And it would make the GtkOverlay property code much easier too.
Comment 10 Alexander Larsson 2015-06-08 19:56:23 UTC
Created attachment 304807 [details] [review]
testoverlay: Add new input stacking test

In this case we have a bunch of interactive main children
of the overlay, and then a centered overlay that contains both
non-interactive (labels) and interactive (entry) widgets.

This shows off a problem where the non-interactive parts (the labels)
steals input from the overlay main children (breaks button click and
hover effects).
Comment 11 Alexander Larsson 2015-06-08 19:56:31 UTC
Created attachment 304808 [details] [review]
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.
Comment 12 Alexander Larsson 2015-06-08 19:56:39 UTC
Created attachment 304809 [details] [review]
GtkOverlay: Add support for input pass-through overlays

For these widgets we set pass-through on the child window so that
input over these widgets (that are not on a child input window) goes
to the window below the overlay.
Comment 13 Alexander Larsson 2015-06-08 19:56:48 UTC
Created attachment 304810 [details] [review]
testoverlay: Fix test by usint add_pass_through_overlay
Comment 14 Alexander Larsson 2015-06-08 19:58:14 UTC
New version uses set_pass_through()
Comment 15 Christian Hergert 2015-06-08 20:05:53 UTC
Review of attachment 304775 [details] [review]:

Very nice. Just think we should add a bit more to the docs on hit-target propagation.

::: gtk/gtkoverlay.c
@@ -538,0 +556,50 @@
+static GtkOverlayChild *
+gtk_overlay_get_overlay_child (GtkOverlay *overlay,
+			       GtkWidget *child)
... 47 more ...

Generally prefer the !! style, but I think with gvalue we can depend on 0 or 1 for gboolean.

@@ -673,0 +818,11 @@
+
+/**
+ * gtk_overlay_add_transparent_overlay:
... 8 more ...

What if the overlay child is placed in an overlapping location with a second overlay child? Does the event dispatch based on implicit stacking, or always fall through to the GtkBin child?
Comment 16 Christian Hergert 2015-06-08 20:12:50 UTC
Review of attachment 304774 [details] [review]:

Does anything special need to happen if gdk_window_ensure_native() gets called on a GDK_OUTPUT_ONLY window?
Comment 17 Alexander Larsson 2015-06-08 20:20:55 UTC
Review of attachment 304775 [details] [review]:

::: gtk/gtkoverlay.c
@@ -673,0 +818,11 @@
+
+/**
+ * gtk_overlay_add_transparent_overlay:
... 8 more ...

It will dispatch based on the gdkwindow stacking order, which i guess is somewhat related to the order you add overlays.
Comment 18 Alexander Larsson 2015-06-09 07:08:55 UTC
Review of attachment 304774 [details] [review]:

No, the code works fine with native (child) windows (i tried). They are not especially useful for those, as they can't be transparent so you can't really see what you're delivering the events to, but it works.

For toplevel windows it will stop delivery of events, but not actually propagate them to whatever window is below you. I guess technically we could auto-set the input region on the toplevels to achieve this, but i'm not sure how useful that will be.
Comment 19 Alexander Larsson 2015-06-09 09:13:40 UTC
Created attachment 304833 [details] [review]
testoverlay: Add new input stacking test

In this case we have a bunch of interactive main children
of the overlay, and then a centered overlay that contains both
non-interactive (labels) and interactive (entry) widgets.

This shows off a problem where the non-interactive parts (the labels)
steals input from the overlay main children (breaks button click and
hover effects).
Comment 20 Alexander Larsson 2015-06-09 09:13:48 UTC
Created attachment 304834 [details] [review]
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.
Comment 21 Alexander Larsson 2015-06-09 09:13:56 UTC
Created attachment 304835 [details] [review]
overlay: Add reorder_overlay()

This allows you to control the z-ordering of overlay children
Comment 22 Alexander Larsson 2015-06-09 09:14:04 UTC
Created attachment 304836 [details] [review]
GtkOverlay: Add support for input pass-through overlays

For these widgets we set pass-through on the child window so that
input over these widgets (that are not on a child input window) goes
to the window below the overlay.
Comment 23 Alexander Larsson 2015-06-09 09:14:12 UTC
Created attachment 304837 [details] [review]
testoverlay: Fix test by using add_pass_through_overlay
Comment 24 Alexander Larsson 2015-06-09 09:14:22 UTC
Created attachment 304839 [details] [review]
testoverlay: Add test for overlay z ordering
Comment 25 Alexander Larsson 2015-06-09 09:25:34 UTC
New set of patches which also includes z-ordering of overlay children.

I also looked at trying to make this a more generic pass-through property on GtkWidget, but that was a bit iffy. Its hard to make it work generically as lots of widgets have extra windows, and its only useful for z-stacked overlapping widgets which really only happens for overlays, so i'm not sure how useful it is.
Comment 26 Matthias Clasen 2015-06-09 10:29:08 UTC
Review of attachment 304835 [details] [review]:

::: gtk/gtkoverlay.c
@@ +534,3 @@
+ * A widget’s position in the @overlay children list determines which order
+ * the children are drawn if they overlap. The first child is drawn at
+ * the bottom.

It also determines the default focus chain, right ?
Comment 27 Alexander Larsson 2015-06-09 14:20:51 UTC
Review of attachment 304835 [details] [review]:

::: gtk/gtkoverlay.c
@@ +534,3 @@
+ * A widget’s position in the @overlay children list determines which order
+ * the children are drawn if they overlap. The first child is drawn at
+ * the bottom.

I guess so.
Comment 28 Matthias Clasen 2015-06-14 23:53:18 UTC
Review of attachment 304833 [details] [review]:

ok
Comment 29 Matthias Clasen 2015-06-15 00:01:23 UTC
Review of attachment 304834 [details] [review]:

Looks good to me.
Comment 30 Matthias Clasen 2015-06-15 00:08:42 UTC
Review of attachment 304835 [details] [review]:

::: gtk/gtkoverlay.c
@@ +578,3 @@
+  priv->children = g_slist_insert_before (priv->children, new_link, child_info);
+
+  gtk_widget_child_notify (child, "index");

If we're going to take this seriously, we need to notify the position of other children here too, I guess
Comment 31 Matthias Clasen 2015-06-15 00:15:09 UTC
Review of attachment 304836 [details] [review]:

::: gtk/gtkoverlay.c
@@ +661,3 @@
     {
+    case CHILD_PROP_PASS_THROUGH:
+      /* Ignore value on main child */

This should probably go into a doc comment for the child property.
Comment 32 Matthias Clasen 2015-06-15 00:15:31 UTC
Review of attachment 304837 [details] [review]:

sure
Comment 33 Matthias Clasen 2015-06-15 00:17:47 UTC
Review of attachment 304839 [details] [review]:

looks good, otherwise

::: tests/testoverlay.c
@@ +501,3 @@
+      gtk_widget_override_background_color (ebox, 0, &color);
+      G_GNUC_END_IGNORE_DEPRECATIONS
+	gtk_widget_set_halign (ebox, (i == 0 || i == 3) ? GTK_ALIGN_START : GTK_ALIGN_END);

Indentation mishap
Comment 34 Alexander Larsson 2015-06-15 07:01:15 UTC
Review of attachment 304835 [details] [review]:

::: gtk/gtkoverlay.c
@@ +578,3 @@
+  priv->children = g_slist_insert_before (priv->children, new_link, child_info);
+
+  gtk_widget_child_notify (child, "index");

Not only here, also when removing a child.
Comment 35 Alexander Larsson 2015-06-15 09:02:34 UTC
Pushed fixed versions to master.
Comment 36 Cosimo Cecchi 2015-06-15 20:32:48 UTC
Arriving a little late to the party, but I think I would have preferred if there was not another extra gtk_overlay_add_pass_through_overlay() method, because that makes it for three different methods to add children to an overlay.

Could the API be implemented as a simple helper to set the child property instead? So a caller would do something like:

 gtk_overlay_add_overlay (overlay, child);
 gtk_overlay_set_pass_through (overlay, child, TRUE);

Either way thanks for implementing this!
Comment 37 Alexander Larsson 2015-06-16 14:47:32 UTC
Cosimo: There is already a child property, we could easily make a method for that. Then we could either remove the add_pass_through_overlay or make it a helper for the new method. I don't *really* care, as long as it is possible to do this, and possible to figure out how to do it from the API (as in, not too many contortions).
Comment 38 Jasper St. Pierre (not reading bugmail) 2015-06-16 15:14:17 UTC
I prefer Cosimo's API, personally.
Comment 39 Matthias Clasen 2015-06-16 15:21:24 UTC
I leave it up to you to figure out the api, I don't have a strong opinion. We don't generally have non-generic child property setters, but there's nothing wrong in principle with that. You can of course already do:

gtk_overlay_add_overlay (overlay, child);
gtk_container_child_set (GTK_CONTAINER (overlay), child,
                         "passthrough", TRUE,
                         NULL);
Comment 40 Benjamin Otte (Company) 2015-06-16 15:37:37 UTC
We should have setters for child properties where we don't.

The reason why we don't in lots of places is that either those properties are meant more for glade than for actual code or because they were meant to be small knobs that most people shouldn't use. Both of these are not very good excuses IMO.

If you look at GtkNotebook or GtkListBox for example, there is lots of API for accessing child properties. Because there the code needed to be able to fiddle with those.
Comment 41 Cosimo Cecchi 2015-06-16 19:06:35 UTC
Created attachment 305419 [details] [review]
docs: add new GtkOverlay methods to gtk3-sections.txt
Comment 42 Cosimo Cecchi 2015-06-16 19:06:40 UTC
Created attachment 305420 [details] [review]
overlay: add setters and getters for pass-through child property

This will make the API easier to use from bindings too.
Comment 43 Cosimo Cecchi 2015-06-16 19:06:46 UTC
Created attachment 305421 [details] [review]
overlay: remove gtk_overlay_add_pass_through_overlay()

The API to access this functionality will be the setter we just added in
the previous commit.
Comment 44 Cosimo Cecchi 2015-06-16 19:10:49 UTC
I guess this is the API I was thinking about. Feedback welcome.
Comment 45 Alexander Larsson 2015-06-17 07:15:48 UTC
Review of attachment 305419 [details] [review]:

looks good
Comment 46 Alexander Larsson 2015-06-17 07:16:35 UTC
Review of attachment 305420 [details] [review]:

looks good
Comment 47 Alexander Larsson 2015-06-17 07:17:50 UTC
Review of attachment 305421 [details] [review]:

I don't really care deeply, but sure, it is kind of ugly to have multiple add versions, so lets go with this.
Comment 48 Cosimo Cecchi 2015-06-17 18:49:20 UTC
Thanks, I pushed these to master now.

Attachment 305419 [details] pushed as 1e6ccf5 - docs: add new GtkOverlay methods to gtk3-sections.txt
Attachment 305420 [details] pushed as 3b1b171 - overlay: add setters and getters for pass-through child property
Attachment 305421 [details] pushed as 9c7b0f0 - overlay: remove gtk_overlay_add_pass_through_overlay()