GNOME Bugzilla – Bug 156511
Fullscreen window on other xinerama monitor doesn't stay on top
Last modified: 2005-01-28 18:42:25 UTC
If you have a fullscreen window on one monitor, and then start working on the other monitor, your fullscreen window gets dropped below the panel because it loses focus. My thought is something like: - fullscreen windows are stacked on top if (they have focus OR the focus window is on another xinerama OR the no-focus window is focused) Will code up the patch here shortly, but please post comments or better suggestions if you have them...
Even off-topic comments? Like "please commit the patch you approved in bug 151245 for me, because I don't have a freedesktop.org cvs account" ? ;-)
Did we ever make the change in the semantics of the expected focus window that Elijah suggested before? Either way, it should involve the expected focus window, and also they should be on top if any transient descendant of the fullscreen window is focused.
Current test is: else if ((window->has_focus || focused_transient || (window == window->display->expected_focus_window)) && (window->fullscreen || window_is_fullscreen_size (window))) layer = META_LAYER_FULLSCREEN; So let's abbreviate "window->has_focus || focused_transient || window == expected_focus_window" as HAS_FOCUS (window) and propose: if ((HAS_FOCUS (window) || on_other_xinerama (expected_focus_window) || expected_focus_window == NULL) && FULLSCREEN (window)) layer = META_LAYER_FULLSCREEN; Is that right?
We should probably make window==window->display->expected_focus_window be more robust. It can be wrong in race-condition like areas because XSetInputFocus calls are ignored if the timestamp is less than the last time that XSetInputFocus was called (and this _will_ happen in Metacity in the cases listed in bug 152000--that's why timestamps fixed those problems). We currently always change the expected_focus_window but it'd be better to wrap XSetInputFocus as we talked about in bug 154598 so that the expected_focus_window is only changed when the focus is changed. Also, a much more minor point is that if you use window->has_focus and window==window->display->expected_focus_window, then you can get multiple windows having focus at the same time (but only for a short duration between the XSetInputFocus call and the FocusIn/FocusOut events). You may want to use only one or the other. I know the current code uses both, but I was planning on fixing that up after doing the XSetInputFocus wrapping.
*** Bug 139930 has been marked as a duplicate of this bug. ***
The wrapping of XSetInputFocus in bug 154598 is done now, so I think this can be applied. I think your proposal is correct. There is the possibility for problems due to the fact that expected_focus_window isn't updated when clients call XSetInputFocus directly, but I don't think that's a real big deal and we already have similar problems anyway (we already have the possibility for the code to think there's multiple focus windows since the value of window->has_focus and expected_focus_window can be different during the time between an XSetInpuFocus call and the corresponding FocusIn/FocusOut events). We could get rid of the multiple perceived focus windows issue by removing expected_focus_window everywhere (would that give correct results?), or else by removing ->has_focus everywhere (see last comment of 154598 for more about this choice), but they don't seem to have caused any problems so far. :-)
Hmm, I seem to have this in RHEL-3 but don't see it in CVS/RHEL-4/FC3 - I don't remember the story here, so maybe there's a reason or maybe I just forgot --- metacity-2.4.55/src/stack.c.fullscreen-xinerama 2003-03-17 01:36:34.000000000 -0500 +++ metacity-2.4.55/src/stack.c 2004-10-28 18:35:13.954512840 -0400 @@ -217,6 +217,17 @@ return FALSE; } +static gboolean +windows_on_different_xinerama (MetaWindow *a, + MetaWindow *b) +{ + if (a->screen != b->screen) + return TRUE; + + return meta_screen_get_xinerama_for_window (a->screen, a) != + meta_screen_get_xinerama_for_window (b->screen, b); +} + /* Get layer ignoring any transient or group relationships */ static MetaStackLayer get_standalone_layer (MetaWindow *window) @@ -249,8 +260,12 @@ layer = META_LAYER_FOCUSED_WINDOW; #endif - if (window->has_focus && - (window->fullscreen || window_is_fullscreen_size (window))) + if ((window->fullscreen || window_is_fullscreen_size (window)) && + (window->has_focus || + window->display->focus_window == NULL || + (window->display->focus_window != NULL && + windows_on_different_xinerama (window, + window->display->focus_window)))) layer = META_LAYER_FULLSCREEN; else if (window->wm_state_above) layer = META_LAYER_DOCK;
I don't see any problems with this RHEL3 patch (but I don't have xinerama and haven't played much with stack.c either...). Rob, are there any special cases you know of where the distinction between expected_focus_window and focus_window is important for this particular chunk of code?
nope; it's only there to prevent the panels from flashing above fullscreen windows when you close a transient descendant of a fullscreen window.
If this looks fine to you guys let's go for it
committed. 2005-01-28 Elijah Newren <newren@gmail.com> Patch from RHEL-3 (Havoc doesn't remember how it got there) that Havoc posted in bug 156511 to fix the problem with fullscreen windows on a different xinerama monitor not staying on top. I updated to HEAD. Should fix #156511. * src/stack.c: (windows_on_different_xinerama): new function, (get_standalone_layer): let windows on a different screen than the one with the focus window stay in the fullscreen layer