GNOME Bugzilla – Bug 673125
windows draw as unfocused/backdrop on window managers that do not set _NET_WM_STATE initially
Last modified: 2012-04-04 16:03:32 UTC
When running a gtk-3 application in the "awesome" window manager, or in fluxbox, the window is drawn as unfocused (or "backdrop" as it is called in the theme, I think). It stays this way until I toggle its state (maximize it in fluxbox, or minimize and restore it in awesome). I've been looking at the code and comparing GDK_DEBUG=events output in an attempt to figure out what breaks, and I think the problem is gdk only checks if the WM supports _NET_WM_STATE_FOCUSED in gdk_check_wm_state_changed, called when the WM updates _NET_WM_STATE, but these WMs do not update that property when the window is mapped. Minimizing/maximizing trigger gdk_check_wm_state_changed, which sees there is no WM support and set toplevel->have_focused. Comparing GDK_DEBUG output confirms there is no _NET_WM_STATE property notify for the problematic WMs, while it looks like there is in gnome-shell. If this analysis is correct then perhaps a variation of the fix for bug 667045 will help here: force a _NET_WM_STATE check when the window is mapped (or at some similarly early time). Or perhaps have_focused should initially be true instead of false.
Created attachment 210988 [details] [review] display-x11: Don't try to set window states that weren't just checked Since the order in which _NET_WM_STATE and _NET_WM_DESKTOP are set, or even *if* they are set, isn't defined we could end up toggling GDK_WINDOW_STATE_FOCUSED needlessly when calling do_net_wm_state_changes() from gdk_check_wm_desktop_changed(). Toggling GDK_WINDOW_STATE_STICKY directly in gdk_check_wm_desktop_changed() allows us to just call do_net_wm_state_changes() when _NET_WM_STATE actually changes. -- This patch should fix it. Actually I had noticed another byproduct of the same fundamental issue before: GDK_WINDOW_STATE_FOCUSED was being toggled on map creating 2 needless transitions. But then I forgot about it before digging further. Thanks for the analysis!
That fixed it (tested gedit in awesome), thanks!
Thanks for testing. The bug report must stay open until the patch is reviewed and commited though.
Review of attachment 210988 [details] [review]: ::: gdk/x11/gdkdisplay-x11.c @@ -208,1 @@ if (old_state & GDK_WINDOW_STATE_FULLSCREEN) Are you sure that we don't have to still need this code in d_net_wm_state_changes ? In the case where we go from stick to non-sticky, we don't call gdk_check_wm_desktop_changed, so we don't synthesize the sticky->!sticky transition. Or am I missing something ? @@ +268,3 @@ + if (GDK_WINDOW_DESTROYED (window) || + gdk_window_get_window_type (window) != GDK_WINDOW_TOPLEVEL) + return; Why is this added check necessary ? That should be explained
Created attachment 211031 [details] [review] x11: Set GdkToplevelX11.have_focused on creation Since the order in which _NET_WM_STATE and _NET_WM_DESKTOP are set, or even *if* they are set, isn't defined, we could end up unsetting GDK_WINDOW_STATE_FOCUSED given that both handlers for these two X properties end up doing window state changes for all states. As we want GDK_WINDOW_STATE_FOCUSED to be set by default we need to set its master flag by default as well.
(In reply to comment #4) Yeah, I think the approach on this new patch is better and safer actually.
Review of attachment 211031 [details] [review]: ok
Attachment 211031 [details] pushed as 987baab - x11: Set GdkToplevelX11.have_focused on creation