GNOME Bugzilla – Bug 564648
when switching to/from compositing enabled, windows appear as new
Last modified: 2010-07-01 07:47:24 UTC
Continued from 563561: We now correctly apply real transparency when the compositing window manager is started after g-t, and switch back to non-transparency when it terminates. One problem with re-realizing the window however is that the window manager and wnck think this is a new window, so it's highlighted in the window list applet.
Along with this issue, the realize/unrealize is also losing: - Size - Position - Desktop I'll attach patches to deal with these. I haven't investigated the user-time issue yet. I think the fix might be to set the user time on the window to 0 on map rather than to the saved user time.
Created attachment 136949 [details] [review] Avoid changing the size during realize At the point when the the TerminalScreen is mapped, we are at a funny state: - The terminal window is mapped - GTK+ hasn't yet applied the default size Since the terminal window is mapped, we call gtk_window_resize() instead of gtk_window_set_default_size() and end up mapping with the wrong default size. (The observed effect is that depending on timing, the terminal will be reset to 80x24 when switching to a compositing window manager.) The simple fix is to not resize the window when the TerminalScreen is realized - changing sizing during realize is a poor idea in all cases - but rather at the start of show().
Created attachment 136950 [details] [review] Save position of window when unrealizing/realizing When we unrealize and realize the terminal window, save the position.
Created attachment 136951 [details] [review] Save the desktop when unrealizing/realizing Save the current desktop for a terminal window when unrealizing and realizing it to change the colormap. This is complicated because: a) GDK has no support for_NET_WM_DESKTOP b) GDK however clears _NET_WM_DESKTOP on map (as part of it's support for sticky windows.)
Created attachment 136956 [details] [review] Turn off demands-attention state after unrealizing/realizing Unrealizing and realizing the window is likely to cause the window to be focus-stealing-preventing and start blinking in the taskbar. There's no obvious way to prevent this, so just turn off the _NET_WM_STATE_DEMANDS_ATTENTION after the window is remapped.
I think these patches get things working about as well as can be expected. The position of the terminal-window in the stacking order will likely still get changed, but other than the top window (focus window), the user is unlikely to really care that much about the stacking order.
(In reply to comment #1) > I haven't investigated the user-time > issue yet. I think the fix might be to set the user time on the window to 0 on > map rather than to the saved user time. IIRC when I wrote this code, I tried using 0 instead of the actualy user_time, but that didn't fix it. --- Thanks for the patches! Attachment 136949 [details] looks fine to me. Attachment 136950 [details] look fine to me. One question though: if switching compositing isn't done by starting a replacement window manager but e.g. by changing compositing in metacity, shouldn't metacity be able to preserve the position itself, given that the windows have unique window roles which are the same before and afterwards? (It does not work, currently; I just wonder if that _should_ work.) Attachment 136951 [details] is fine too, but I'd prefer to add the [sg]et_net_wm_desktop functions to terminal-util.[ch] as sth. like terminal_util_x11_[sg]et_.... Attachment 136956 [details]: +static void +wait_for_map (GtkWidget *widget) +{ + int flag = FALSE; + + g_signal_connect (widget, "map-event", + G_CALLBACK (show_map_callback), + &flag); + while (!flag) + gtk_main_iteration (); +} + wait_for_map (widget); + clear_net_wm_demands_attention (widget->window); I really don't like this. Can't we just set a flag in TerminalWindowPrivate, and have the map handler (always connected) do clear_net_wm_demands_attention() if the flag is set, then unset it? (And I'd prefer to move clear_net_wm_demands_attention to terminal-util.[ch] as sth. like terminal_util_x11_clear_....) ---- With all four patches applied, I noticed a very strange behaviour in metacity when switching from non-compositing to compositing enabled, or back, both in metacity 2.24.x, and with 2.27.x master: Place one terminal window on workspace 1, one on workspace 2, both shown. Now switch compositing using e.g. gconf-editor on workspace 3, and watch the workspace switching applet. The terminal on ws 1 vanishes from it; it's becoming iconified! Switch to ws 1, and de-iconify the terminal there using the window list applet. Now the terminal on ws 2 becomes iconified! Switching to ws 2 and deiconifying the terminal, everything's back to normal.
(In reply to comment #7) > (In reply to comment #1) > > I haven't investigated the user-time > > issue yet. I think the fix might be to set the user time on the window to 0 on > > map rather than to the saved user time. > > IIRC when I wrote this code, I tried using 0 instead of the actualy user_time, > but that didn't fix it. Yeah, I figured that out after I tried it - Metacity sets the needs-attention hint whenever a window doesn't get focus. (To let the user know that the window appeared, I guess.) There's no difference in whether a window _asks_ for the focus or not. > Attachment 136950 [details] [edit] look fine to me. One question though: if switching > compositing isn't done by starting a replacement window manager but e.g. by > changing compositing in metacity, shouldn't metacity be able to preserve the > position itself, given that the windows have unique window roles which are the > same before and afterwards? (It does not work, currently; I just wonder if that > _should_ work.) It's conceivable to imagine implementing something like that, but I certainly wouldn't go as far as saying it *should* work. The intent of the role property is for session management - so when gnome-terminal is restarted as part of a session and opens 3 windows, Metacity can figure out which is which. Remembering the position and other attributes outside the scope of session management would frequently be what the user wants, but in other cases could be weird. (Especially remembering the workspace could be confusing) Remember, Metacity doesn't see this as part of the switch. What it sees is that after it switches compositing on, a terminal window is withdrawn, and then another terminal window is mapped. > Attachment 136951 [details] [edit] is fine too, but I'd prefer to add the [sg]et_net_wm_desktop > functions to terminal-util.[ch] as sth. like terminal_util_x11_[sg]et_.... Sure, I can redo it like that if you'd prefer. > Attachment 136956 [details] [edit]: > > +static void > +wait_for_map (GtkWidget *widget) > +{ > + int flag = FALSE; > + > + g_signal_connect (widget, "map-event", > + G_CALLBACK (show_map_callback), > + &flag); > + while (!flag) > + gtk_main_iteration (); > +} > > + wait_for_map (widget); > + clear_net_wm_demands_attention (widget->window); > > I really don't like this. Can't we just set a flag in TerminalWindowPrivate, > and have the map handler (always connected) do clear_net_wm_demands_attention() > if the flag is set, then unset it? (And I'd prefer to move > clear_net_wm_demands_attention to terminal-util.[ch] as sth. like > terminal_util_x11_clear_....) I can certainly do it like that. I thought it was cleaner to keep the hack encapsulated instead of extending the private structure with a clear_demands_attention bit, but no strong preference. > With all four patches applied, I noticed a very strange behaviour in metacity > when switching from non-compositing to compositing enabled, or back, both in > metacity 2.24.x, and with 2.27.x master: > > Place one terminal window on workspace 1, one on workspace 2, both shown. Now > switch compositing using e.g. gconf-editor on workspace 3, and watch the > workspace switching applet. The terminal on ws 1 vanishes from it; it's > becoming iconified! Switch to ws 1, and de-iconify the terminal there using the > window list applet. Now the terminal on ws 2 becomes iconified! Switching to ws > 2 and deiconifying the terminal, everything's back to normal. I can partially reproduce it (see the window that gets remapped the other workspace get minimzed, don't see the other window get minimized when I unminimize it, however.) I'll see if I can figure out what's going on.
Basically, what's going on with windows getting iconified is that - Metacity (but not Mutter) unmaps windows on other desktops. - GDK detects GDK_WINDOW_STATE_ICONIFIED by being unmapped when not withdrawn - GtkWindow, when you unmap a window, does: window->iconify_initially = (state & GDK_WINDOW_STATE_ICONIFIED) != 0; Not all that hard to work around with some more code. - Get the _NET_WM_STATE property from the window before unmapping it - If it doesn't have _NET_WM_STATE_HIDDEN then we're not iconified - If we are not iconified, then before remapping call gtk_window_deiconify() Shading is hard to handle, since Metacity sets: !meta_window_showing_on_its_workspace (window) || window->shaded So there's no way to distinguish, for example: - A shaded window on another workspace - An iconified window on another workspace My tendency is to just ignore shading. If you are switching compositors on and off and funny things happen to your shaded windows, tough. There's only so much code this is worth. [The reason I think it is worth *some* code is that until GNOME 3.0 requires compositing, it is supposed to be easy to switch back and forth. Plus it's annoying for people hacking gnome-shell if their terminals misbehave.]
Created attachment 137185 [details] [review] Save the desktop when unrealizing/realizing Save the current desktop for a terminal window when unrealizing and realizing it to change the colormap. This is complicated because: a) GDK has no support for_NET_WM_DESKTOP b) GDK however clears _NET_WM_DESKTOP on map (as part of it's support for sticky windows.)
Created attachment 137186 [details] [review] Turn off demands-attention state after unrealizing/realizing Unrealizing and realizing the window is likely to cause the window to be focus-stealing-preventing and start blinking in the taskbar. There's no obvious way to prevent this, so just turn off the _NET_WM_STATE_DEMANDS_ATTENTION after the window is remapped.
Created attachment 137187 [details] [review] Get the minimization status by reading _NET_WM_STATE A GDK bug or (arguably) misfeature means that the minimization status of GtkWindow is not properly saved and restored when unmapping and then mapping. Work around this by directly reading the _NET_WM_STATE property and looking for _NET_WM_STATE_HIDDEN.
Created attachment 137189 [details] [review] Get the minimization status by reading _NET_WM_STATE Just fixing a stray newline introduced in the last version
Thanks for the detailed explanations! > My tendency is to just ignore shading. If you are switching compositors on and > off and funny things happen to your shaded windows, tough. There's only so much > code this is worth. [The reason I think it is worth *some* code is that until > GNOME 3.0 requires compositing, it is supposed to be easy to switch back and > forth. Plus it's annoying for people hacking gnome-shell if their terminals > misbehave.] I agree. I was only using compositor switching as mean to test the patches, not to put it forward as a valid use pattern in regular app use :-) Please commit the patches to master.
Patches pushed to master
*** Bug 604536 has been marked as a duplicate of this bug. ***