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 769635 - Using gtk_event_box_set_above_child() can result in spurious grab-broken events
Using gtk_event_box_set_above_child() can result in spurious grab-broken events
Status: RESOLVED NOTABUG
Product: gtk+
Classification: Platform
Component: Widget: Other
3.20.x
Other Linux
: Normal normal
: ---
Assigned To: gtk-bugs
gtk-bugs
Depends on:
Blocks:
 
 
Reported: 2016-08-08 15:07 UTC by Christophe Fergeau
Modified: 2016-08-09 10:04 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
small reproducer (2.49 KB, text/x-csrc)
2016-08-08 15:08 UTC, Christophe Fergeau
Details

Description Christophe Fergeau 2016-08-08 15:07:18 UTC
In spice-gtk, we use a GtkEventBox along with gtk_event_box_set_above_child().
On a button-press-event, we are calling gdk_pointer_grab() on the event box. After doing that, we get a grab-broken event where event->grab_window is the event box we passed to gdk_pointer_grab(). This is unexpected, and is currently causing spice-gtk to fail grabbing the mouse.
Comment 1 Christophe Fergeau 2016-08-08 15:08:52 UTC
Created attachment 332947 [details]
small reproducer

This small test program exhibits the bug described in this bug report.
Comment 2 Carlos Garnacho 2016-08-08 16:07:45 UTC
I think this works as intended... bear in mind that gtk_widget_get_window() won't return the GdkWindow that GtkEventBox places above as per your request.

In this case, GtkEventBox has 2 windows: a I/O window set as the widget window (the one you get and grab on) and a input-only window placed right above. When you click, the latter gets the events, yet you immediately force a grab on the first one. So gdk sends a GdkEventGrabBroken with event->window being the window it's delivered to (the input-only window), and event->grab_window being the window that's taking over the grab (the I/O window below the child widget).

This "works" in the !above_child case, because gtk_widget_get_window() and the "event window" are the same.

I see two options to handle this on your side:
- Check whether event->grab_broken.window and event->grab_broken.grab_window belong to the same widget
- Actually grab on the input-only window, although GtkEventBox doesn't offer getters for it.
Comment 3 Carlos Garnacho 2016-08-08 20:13:43 UTC
An idea to bypass the shortcoming in the second option: grab on event->button.window, that will be the input-only window that's meant to be handling input events here.
Comment 4 Christophe Fergeau 2016-08-09 08:13:53 UTC
(In reply to Carlos Garnacho from comment #2)
> I think this works as intended... 

Oh, could very well be, I'm not familiar with grabs in general, and this was unexpected behaviour for me, so I thought I'd file a bug. At the same time, I was expecting it to end up being closed as NOTABUG or WONTFIX :) Thanks for the detailed explanation!

> bear in mind that gtk_widget_get_window()
> won't return the GdkWindow that GtkEventBox places above as per your request.
> 
> In this case, GtkEventBox has 2 windows: a I/O window set as the widget
> window (the one you get and grab on) and a input-only window placed right
> above. When you click, the latter gets the events, yet you immediately force
> a grab on the first one. So gdk sends a GdkEventGrabBroken with
> event->window being the window it's delivered to (the input-only window),
> and event->grab_window being the window that's taking over the grab (the I/O
> window below the child widget).
> 
> This "works" in the !above_child case, because gtk_widget_get_window() and
> the "event window" are the same.

Hmm, yup, makes sense, this was quite confusing for me as the input-only window is some hidden implementation detail, so it was not very clear what was this window that had the grab. Add to that that GtkEventBox has 2 GdkWindow and we get a grab-broken for the grab moving from one window to the other, and I was not sure which behaviour to expect ;)

> 
> I see two options to handle this on your side:
> - Check whether event->grab_broken.window and event->grab_broken.grab_window
> belong to the same widget

Yup, this is what I've proposed on the mailing list ( https://lists.freedesktop.org/archives/spice-devel/2016-August/031150.html ), but I'll try your other suggestion. Thanks!

> - Actually grab on the input-only window, although GtkEventBox doesn't offer
> getters for it.
Comment 5 Carlos Garnacho 2016-08-09 10:04:45 UTC
(In reply to Christophe Fergeau from comment #4)
> (In reply to Carlos Garnacho from comment #2)
> > I think this works as intended... 
> 
> Oh, could very well be, I'm not familiar with grabs in general, and this was
> unexpected behaviour for me, so I thought I'd file a bug. At the same time,
> I was expecting it to end up being closed as NOTABUG or WONTFIX :) Thanks
> for the detailed explanation!
> 
> > bear in mind that gtk_widget_get_window()
> > won't return the GdkWindow that GtkEventBox places above as per your request.
> > 
> > In this case, GtkEventBox has 2 windows: a I/O window set as the widget
> > window (the one you get and grab on) and a input-only window placed right
> > above. When you click, the latter gets the events, yet you immediately force
> > a grab on the first one. So gdk sends a GdkEventGrabBroken with
> > event->window being the window it's delivered to (the input-only window),
> > and event->grab_window being the window that's taking over the grab (the I/O
> > window below the child widget).
> > 
> > This "works" in the !above_child case, because gtk_widget_get_window() and
> > the "event window" are the same.
> 
> Hmm, yup, makes sense, this was quite confusing for me as the input-only
> window is some hidden implementation detail, so it was not very clear what
> was this window that had the grab. Add to that that GtkEventBox has 2
> GdkWindow and we get a grab-broken for the grab moving from one window to
> the other, and I was not sure which behaviour to expect ;)

I agree this is kinda confusing :), events are coherent at the gdk level, but this one sends a kind of mixed message when both windows belong to the same widget above gdk. I would be at the same time afraid to just silence it at the gtk level because we drop this event coherence.

I expect this to get better in the future when we manage to eliminate/hide non-toplevel GdkWindows from API, and widgets become the surface unit. Till then... this works as designed, thus NOTABUG :)