GNOME Bugzilla – Bug 567528
Cannot raise windows from applications in Tcl/Tk and Java [meta_window_same_application() too simplistic]
Last modified: 2011-01-24 11:59:53 UTC
Please describe the problem: Applications in Tcl/Tk and Java are unable to raise toplevel windows they create and in some situations it is impossible to make these windows visible to the user. Changing Gnome preferences did not solve the problem in any way. As the main author of GPSMan I am quite worried by this because some of the functionality of the program is broken and Gnome+Metacity is the environment most Linux machines have. Any urgent help will be appreciated. Steps to reproduce: 1. download this small Tcl/Tk test: wget http://www.ncc.up.pt/gpsman/tmp/testraise.tcl 2. run it from a xterm: testraise.tcl 3. three windows are created, each with 2 buttons that are expected to raise the other two windows; move the windows so that they overlap partially and then try the buttons Actual results: clicking the buttons do not raise the corresponding window; a similar test in Java makes the focus change but the windows are not raised Expected results: clicking a button should raise one of the other windows Does this happen every time? yes Other information: I made a search in the Web and came across some advice on changing the Gnome/Metacity configuration. This was tried without success.
In step 2 above you may have to do: chmod 755 testraise.tcl ./testraise.tcl as you most probably know...
Is GPSMan the toplevel application when it attempts to raise the window, or is some other application toplevel?
Yes, GPSMan is the toplevel application that attempts to raise the window, as in the test I provided.
See also #445447 If you're just trying to focus a window, though, then these toolkits need to use _NET_ACTIVE_WINDOW messages rather than XRaiseWindow()
No, I really want to raise the window to make sure it becomes visible to the user and the user is aware of it, In Tcl/Tk I am using the "raise" command and it is strange there is something wrong with its implementation as it works with all the other window managers I used in the last 10 years (kwin, sawfish, wmaker, fvwm2).
in the default config, metacity doesn't allow a window to exist that's raised but not focused; it just does not have that "state" in its "state machine", it can't make sense out of it since it's a broken situation from a user standpoint. So it won't honor requests that result in that. If you use _NET_ACTIVE_WINDOW it will also focus the window. If metacity was going to honor a plain raise, it would have to interpret that as raising up to just below the focus window, perhaps; or raising just above the topmost unfocused window from the same app as the raised window.
Thanks for your explanation but I don't see how as a developer I can cope with this. As stated in my bug report both Tcl/Tk and Java applications cannot raise windows by using the normal commands for doing that when the window manager is metacity. Do you mean I should report the bug to the maintainers of Tcl/Tk and Java?
If I may make a suggestion, I think you would solve the bug by raising and giving focus to the window in answer to the XRaiseWindow() call (if it is what the Tk "raise" command is translated to). This would mean much less damage to existing applications than just doing nothing, while keeping your state machine. I would like to add that of course python applications using Tkinter can also be broken by this bug. A python version of my test can be retrieved from: http://www.ncc.up.pt/gpsman/tmp/testraise.py
Surely this has come up before... it's not like metacity is some newfangled obscure thing, it's been in wide use for 7-8 years at least, and probably worked this way for at least 4 or 5. I don't remember any of the history though. Some relevant looking bugs are: bug 166395 bug 164675 bug 445447 bug 305882 > Do you mean I should report the bug to the maintainers of Tcl/Tk and > Java? If they have an API meaning "bring this window to user's attention" and they use XRaiseWindow() to mean that, then yes, you should file a bug with them. They need to provide a way to send _NET_ACTIVE_WINDOW (and with a correct timestamp!) Note: I don't know for sure what X calls Java or Tk might be making, this is speculation. You can use "xtrace" to look and see, perhaps.
So, XRaiseWindow() requests are broken as Havoc points out...but metacity does honor some for various backward compatibility reasons. The logic (from the final patch in bug 166395, which is still in use today) is that metacity will honor XRaiseWindow() requests *if* there's some window that has focus, that window is in the same application as the one being raised, and the potential raisee has a user time before that of the active window's. This logic was basically taken from KWin so the two should be the same. However, as noted in bug 166395, our logic for determining if two windows are part of the same application (meta_window_same_application()) is pretty simple -- it's based on group leader windows only. KWin has much more rigorous logic in this area when I last looked at it years ago. So it sounds like metacity is not treating these two windows reported in this bug as being part of the same application, and I'm betting adding some of KWin's are-windows-from-the-same-application logic to metacity would fix this bug. Granted, tcl/tk or python/tk should still be fixed, but I think there's a sane workaround for us to deal with these broken clients without introducing other major breakage.
Many thanks for this constructive comment that I hope will help solving the issue. As a sequel to the last comment from Havoc Pennington (#9) I submitted a general bug to Debian http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=512401
Just for the sake of fellow developers whose applications may suffer for this as yet unconfirmed bug: in answer to a bug I submitted to Debian for the tk and tkinter packages Sergei Golovan gave a workaround that really works. The details can be found at http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=514115
Created attachment 136149 [details] [review] Proposed Patch Patch against current trunk to check in meta_window_same_application() if the client leader matches. Even if not all applications use the same group for all their windows, many use the same client leader. The attached patch improves the meta_window_same_application() function to also check for the xclient_leader. Note: The tcl application attached in the BZ does not set neither the group nor the client leader property, so this patch will not help for that particular example, but it improves the behavior for many real life applications, such as Java applications.
(In reply to comment #13) > Created an attachment (id=136149) [details] > Proposed Patch > > Patch against current trunk to check in meta_window_same_application() if the > client leader matches. > > Even if not all applications use the same group for all their windows, many use > the same client leader. I don't think this patch is quite right - checking for the same leader is probably appropriate in the case being discussed in window.c - "could this application know what it's doing when it's asking to be stacked above" - you could even check for the same X client and catch the Tk case for this bug report. But the other two callers to meta_window_same_application() clearly want "same group" - one is checking whether focus clicks should be eaten, the other is about multiple modal dialogs and placement - and modal dialogs are modal to the group. So, I think there needs to be a separate meta_window_same_client() or something that we use here.
Created attachment 145814 [details] [review] Allow explicit raises from same client, not just same app Here's a patch that takes the approach I proposed. As compared to Olivier's patch: - It works even for clients that don't set WM_CLIENT_LEADER (WM_CLIENT_LEADER will only be set for apps that support session management.) - It affects only this particular check and not all use of meta_window_same_application(); this means that it won't cause regressions for applications that have intentionally split themselves into mutliple separate window groups. (For this particular case, we can assume that an application sophisticated enough to intentionally use multiple window groups is either not going to XRaiseWindow(), or is only going to XRaiseWindow() when appropriate; there's no point in trying to keep such an application from stepping on its *own* toes.) The main thing I don't like about it is the need to include Xlibint.h for dpy->resource_mask. It's ugly. But practically speaking, that field isn't going to change any time soon.
Review of attachment 145814 [details] [review]: Looks sensible to me. Committed.