GNOME Bugzilla – Bug 371036
Win32: Raise modal children dialogs when clicking parent in window list
Last modified: 2007-10-18 00:34:16 UTC
Steps to reproduce: * execute gtk-demo.exe * choose Dialog and Message Boxes * click Message Dialog * raise some other windows by alt-tab or the window list * raise the parent window (Dialogs) This window ist not responsive, because there is still a modal dialog you cannot see unless you minimize/move_out_of_the_way all windows that got stacked above it. But the user will not expect that and assume the application crashed somehow.
Created attachment 76029 [details] raise modals, smaller example Here is a smaller example code.
Thanks for the excellent small test program. The problem is fixed by a patch that has been circulating (slowly) between me and some gnumeric people for quite some time without any clear consensus (I think) whether it's good enough or entirely correct. I don't think the patch introduces any new problems, though, and your example shows how easy it is to get the problem, so I think I will commit the patch.
Sorry, I meant Inkscape, not gnumeric. I'll include here a couple of mail messages exchanged with Inkscape people to show the kind of complexities involved: Message 1: In summary, our use of transients breaks into two parts, the trivial part and the hacky part: The trivial part: each dialog window is attached to the main editing window by gtk_window_set_transient_for. Both belong to the same application, of course. The hackish part: Inkscape may have _several_ editing windows, if you load several documents. All they are still the same application, and the floating dialogs are _shared_ between them and are switching to display the information pertaining to the document window which currently has focus. With regard to transient behavior, of course the ideal approach would be something like "make this dialog window transient to this GROUP of windows, so that no matter which one has focus, the dialog will be on top of it". But there's no such API as far as I know. So we achieve the same by a hack: whenever a document window gets focus, it sends a signal to all active dialogs, and these dialogs "re-transientize" themselves, i.e. use gtk_window_set_transient_for to attach to the document window which is currently on top. If anyone has a better idea of how to achieve the same effect, we'd like to hear. Additional bits: - Each dialog also is hidden from the task bar by default, using gtk_window_set_skip_taskbar_hint. - On some window managers, re-transientizing a dialog does not pull it on top unless you click on the document window to which this dialog is transientized. To work around this we have the "aggressive" mode where, after each gtk_window_set_transient_for, a gtk_window_present call is used on the dialog. - Each dialog stores the pointer to the editing window to which it is currently transient and uses it to pass focus to that window, e.g. when you press Esc or in some other situations. Message 2, by he author of the patch I talk about in comment #2: I've just had a go with Inkscape on Linux (Ubuntu) and it also seems to have problems with transient windows. For example: Create two new documents each containing a simple shape. Right-click on a shape and select "Fill and Stroke". Minimize the active document window. The "Fill and Stroke" window is also minimized. Restore the document. Note that "Fill and Stroke" doesn't return. Right-click on a shape and select "Fill and Stroke". It still doesn't return. Select the menu command "View|Show/Hide dialogs". It still doesn't return. Open another dialog (e.g. "Swatches") and "Fill and Stroke" reappears. (But it wouldn't have without the preceding step.) It's also very unfriendly if you have two inkscape documents open in different workspaces. The Windows patch was fairly complicated to avoid the problems on minimization, but it looks like I was putting the fix in the wrong place. I think it would be sensible to fix Inkscape's problems before trying to take the win32 patch any further. Message 3: As you might guess, all this weirdness is NOT coded into Inkscape in any shape or form. It's just the reality of how window managers support transient windows. I agree it's a mess, but it's not Inkscape's mess. Inkscape just tries to adapt and work around this mess as best it can. Needless to say, this very much depends on your window manager. For example, on my KDE 3.3 the sequence differs from yours in this item: > Right-click on a shape and select "Fill and Stroke". It still doesn't > return. For me, it does. I have explained exactly how Inkscape uses transiency (see my last mail). If you spot something wrong with it, please share your suggestions. Please also understand that I'm not a specialist in window interface at all, and never claimed to be one. It's not an area that interests me as such. I was forced to code this hack simply because without it, Inkscape was unusable. With it, it's far from ideal but at least tolerable. If you can help me make it work better or reimplement it in a more correct way, your help will be GREATLY appreciated. Briefly, the ideal behavior of Inkscape dialogs is this: they always stay on top of the topmost (active) document window; they minimize and restore together with the LAST document window; and they are hidden from the taskbar. That's all I'm asking for. The current Linux implementation does not fully conform to this, but this is the best I could do with the current window managers. If you can help me fix the Linux side of things (there may be some things I overlooked, of course), I will be very grateful. If you can make the Windows port work the same or even better than the Linux (i.e. closer to the above ideal), it would be simply great and much much appreciated. Just don't look at the actual Linux behavior as a reference, because it is not. I look forward to hearing your thoughts on this. Please do help me out. I've been fighting with this stuff basically alone for 3 years.
May you attach the patch you have? OT: The docs for gtk_window_set_transient_for miss a word, exactly in the sentence describing the behavior on Windows. May you fix that too or should I file a new bug?
Hmm, I wonder what the documentation is supposed to say. Most probably just that the function (or the underlying GDK functionality) will only do its best to try doing what the window manager would/should do on X11. Attaching the patch, originally by Charles Reilly. It most probably needs more thorough testing, for instance for what happens in the case of chained transient-for. Also, I guess the code (regardless whether the patch is applied or not) should start checking, and explicitly disregard, attempts to se transient-for-ness across process boundaries, as that can cause hangs.
Created attachment 76051 [details] [review] Charles Reilly's patch
I have this problem with GtkMessageDialog, and a workaround which seems to work for me is to simply run this after creating the dialog with gtk_message_dialog_new(): gtk_window_set_skip_taskbar_hint( GTK_WINDOW( dialog ), FALSE ); I have no idea why this works. And the dialog still doesn't show up in the taskbar, probably because it is transient to the parent window. Also, with the risk of falling off topic and while confessing that I don't really understand anything of the GTK+ internals, I can't help but wonder why this hint is set in gtk_message_dialog_init() where it will affect all dialogs, even those without a parent window. If a dialog doesn't have a parent window, wouldn't you then want it to show up in the task bar?
I posted a patch to bug #164537 that also addresses this bug.
2007-10-17 Cody Russell <cody@jhu.edu> * gdk/win32/gdkevents-win32.c * gdk/win32/gdkwindow-win32.[ch]: Force non-modal transient dialogs to iconify with their parents on Win32. Maintain a list of transient children, and whenever a window is hidden or restored we now do the same thing to all connected transient windows above and below the current window in the chain. See comment under WM_ACTIVATE for the reasons why. (#164537, #371036, #405178)