[prev in list] [next in list] [prev in thread] [next in thread] 

List:       gtk-devel
Subject:    Re: gtk 3 stuck menu bug on Mac
From:       Christian Schoenebeck <schoenebeck () linuxsampler ! org>
Date:       2017-11-20 14:43:37
Message-ID: 2214024.oBDIDm6JzE () silver
[Download RAW message or body]

On Montag, 20. November 2017 08:04:20 CET you wrote:
> >> Since this issue only seems to happen on Mac, and since it worked
> >> flawlessly on
> >> Mac before, and since I see the Quartz implementation hasn't really
> >> changed
> >> (significantly) in the last couple years, was there some kind of
> >> important
> >> change in gtk 3 that still would need to be applied to the Quartz driver?
> > 
> > No-one's really maintaining the Quartz backend at the moment, so if you
> > felt like investigating this it would be really appreciated. You could try
> > a 'git bisect' to see what change in GTK3 might have caused the regression
> > and that would probably make it easy to see what would need to be changed
> > in the Quartz backend.
> 
> As Philip, a git bisect might be helpful. But keep in mind that OS X builds
> of GTK+ tend to include quite a few non-upstream patches, so keep any eye
> out for those.

Actually I have no idea where I would find those "OS X build patches".

Anyway, I decided to be pragmatic and I am now using the attached patch to 
address this Quartz driver bug on Mac. The actual root cause seems to be that 
the Quartz driver does not generate crossing events correctly under all 
situations (i.e when menus or tooltips appear or disappear), which in turn 
causes the pointer info to reflect often an old, wrong top level window, 
sometimes even NULL, which finally leads to the described symptoms with hanging 
menus. Because when the current toplevel window info is already wrong, then it 
is impossible for Gtk to resolve the correct child widget that should receive 
pointer events.

So the patch does not fix the Quartz driver, instead it forces to update the 
pointer info very frequently instead (asking the native driver callback always 
about the latest top level window). It is a suboptimal approach to handle this 
issue, I know, but to be honest; in practice the user won't feel a performance 
penalty, and thus I decided for myself that it does not make sense for me to 
invest more days (or even weeks?) to restructure the Quartz driver's event 
generation code in a way expected by Gtk3 now, just to fix this bug in a more 
"clean" way from a pure theoretical point of view.

The rest is up to you to decide whether or whether not you might want to apply 
this or a similar workaround patch to upstream Gtk. All I can say from my side 
is that without addressing this issue at all, Gtk3 IMHO is not usable on Mac, 
because you end up with frozen menus in a matter of few seconds.

CU
Christian
["gtk3-quartz-menu-bug.patch" (gtk3-quartz-menu-bug.patch)]

diff -ruN gtk+-3.22.26.old/gdk/gdkwindow.c gtk+-3.22.26.new/gdk/gdkwindow.c
--- gtk+-3.22.26.old/gdk/gdkwindow.c	2017-10-26 12:23:40.000000000 +0200
+++ gtk+-3.22.26.new/gdk/gdkwindow.c	2017-11-20 01:46:52.000000000 +0100
@@ -8531,6 +8531,26 @@
 
   pointer_info = _gdk_display_get_pointer_info (display, device);
 
+  //HACK: workaround for a bug in the Quartz driver which causes i.e. menus to hang
+#if defined(__APPLE__)
+  /* It seems the Quartz driver is sometimes not handling crossing events
+     correctly (i.e. after menu popups, tooltips appeared), which causes
+     toplevel_under_pointer to point to an old toplevel window or even NULL,
+     and finally the respective relevent child widget under the mouse pointer
+     could not be resolved due to this, which caused i.e. menus to ignore all
+     mouse events. The following is a harsh way to ensure toplevel_under_pointer
+     is always pointing to the window under the current pointer location by
+     updating this whenever pointer info is accessed.
+  */
+  if (pointer_info) {
+    if (pointer_info->toplevel_under_pointer)
+      g_object_unref (pointer_info->toplevel_under_pointer);
+    GdkWindow* w =
+      _gdk_device_window_at_position (device, NULL, NULL, NULL, TRUE);
+    pointer_info->toplevel_under_pointer = w ? g_object_ref (w) : NULL;
+  }
+#endif
+
   if (event_window == pointer_info->toplevel_under_pointer)
     pointer_window =
       _gdk_window_find_descendant_at (event_window,


_______________________________________________
gtk-devel-list mailing list
gtk-devel-list@gnome.org
https://mail.gnome.org/mailman/listinfo/gtk-devel-list


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic