GNOME Bugzilla – Bug 166379
Problems with gtk_window_present()
Last modified: 2011-02-04 16:18:41 UTC
There are a couple problems with gtk_window_present(): 1) It uses gtk_get_current_event_time(). This can return a timestamp from an event that was not user interaction. Since this function is used to focus windows, this usage of gtk_get_current_event_time() is wrong. (See bug 165939 for an example of where this is causing problems right now) Further, the user interaction that caused the window to be activated may not be current and thus even using the most recent user time could be wrong. 2) It depends on a bug in Metacity to work (and I intend to fix the Metacity bug soon). _NET_ACTIVE_WINDOW should not do all the things that gtk_window_present claims that it will do. (See bug 128380) Suggestions: 1) Deprecate the current version of gtk_window_present() and add a new version with a timestamp parameter. In the deprecated version, replace use of gtk_get_current_event_time with display_x11->user_time since that will at least be closer to correct. 2) Either change the documentation for gtk_window_present() so that it states that it results in moving to the workspace where the window already is, or make use of _NET_WM_DESKTOP to ensure that gtk_window_present() will do what it currently says it does (this would basically be copy & paste from gdk_window_unstick() with just a few changes). We may want to consult usability people to help decide which would be better; while we could provide additional API so that both behaviors can be accessed by apps, I think it would result in annoying and inconsistent behavior. 3) Provide an API for just switching a window to the current workspace (that's really what gedit wants in bug 165939; it doesn't want to activate the windows but there wasn't another gtk+ function that only did this)
Oh crap, is this affecting you too Christian?
I think this certainly affects galeon, but I'm going to work around it by writing an alternative gtk_window_present function that you can pass the time to. gdk_window_show (widget->window); gdk_window_focus (widget->window, user_time);
Sorry for the stupid question... how do you get "user_time"?
Paolo: From a ButtonPress or KeyPress event. Hook up a handler to the button_press_event or key_press_event, and just grab the event->time field. In gtk+-2.8 there will also be a gdk_x11_display_get_last_user_time() to retrieve the most recent user interaction event.
In case anyone is confused about the milestones (since gtk+-2.8 won't be out until long after gnome-2.10): I put this on the gnome-2.10 milestone so that we could do the replacing of gtk_get_current_event_time() with display_x11->user_time thing in gtk_window_present(). This would fix problems for gedit, for example. The remaind of the issues would be something that would be punted for gtk+-2.8 & gnome-2.12.
Created attachment 37370 [details] [review] Use display_x11->user_time instead of gtk_get_current_event_time() on X
Comment on attachment 37370 [details] [review] Use display_x11->user_time instead of gtk_get_current_event_time() on X Those includes aren't legal.. you can add .._libgtk_only() API to GDK if you need to.
Created attachment 37379 [details] [review] add some libgtk_only API to gdkx.h Is this what you mean?
ping?
Comment on attachment 37379 [details] [review] add some libgtk_only API to gdkx.h I'm pretty sure owen meant not to include gdkx.h, i.e. add libgtk_only to gdk.h
Created attachment 37689 [details] [review] Make the chage Havoc suggested Third time's a charm?
We'll have official api for getting the user time in 2.8, so I don't quite see the logic of adding libgtk_only api in the middle of the stable 2.6 series
Would you like to suggest an alternative way of getting display_x11->user_time from within gtk_window_present() without waiting for the gtk-2.8 release? I tried one way and Owen suggested doing the libgtk_only API. Also, not doing so means shipping with fairly major problems for Gnome 2.10. Of course, I guess we can tell gedit and Epiphany to remove all occurences of gtk_window_present and replace them with a home-grown function (which Galeon has done because of this problem), as well as hope that these two modules are the only ones that this bug causes problems for (or that we can find the others and change them in time)...
Re-reading, I don't think that came out very well; sorry about that. Still, is this something we can expect to get in for Gnome 2.10 in some form? If so, what do I need to modify to get it right if anything? (it'd be great if someone tookover as it seems it ought to be a simple patch but I don't know the right way to do it...)
Ok, I guess it makes sense to add this as an interim solution. 2005-02-20 Matthias Clasen <mclasen@redhat.com> * gdk/x11/gdkx.h: * gdk/x11/gdkdisplay-x11.c (gdk_x11_display_get_user_time_libgtk_only): Add libgtk_only api to obtain the user_time of the display. This function will become generally available api in 2.8. * gtk/gtkwindow.c (gtk_window_present): Use the timestamp of the last user interaction when focusing the window. (#166379, Elijah Newren)
Thanks Matthias! I'm kicking this off the Gnome 2.10 milestone since the portion relevant for that milestone has been fixed. :-)
Hi, I'm not steeped in all the technicalities of this so I'll just say it in normal terms to not screw it up. The windows should come to you, not the other way around. :-)
You have to be a bit careful about that though. One question is: which windows? Say you call gtk_window_present on a dialog box. That box may not make sense out of the context of its parent windows, so do you bring over all the parent windows also, recursively? Did not the user specifically take an action to place that window on that workspace?
Rob, why would the application present a dialog when the main window is on a different workspace, thus the user didn't have a chance to press a button or interact in some other way with the app.
I have been thinking about this in terms of an analogy on the way to work, and I thought I'd share it: If a minion comes to the palace with an important message for the king, what will the guard do ? Will he run into the kings chamber, where the king is listening to a concert, lift up the throne and carry the king to the entrance where the minion is waiting ? No, he will have the minion wait, investigate if its a matter of war and peace, and if its not, he will make the minion appear before the king at the next occasion for an audience. I hope we treat our users as kings, not as minons... The analogy also sheds some light on a misnomer in the EWMH (_NET_DEMANDS_ATTENTION). Minions don't demand attention, they ask for an audience.
And what happen when the king asks for something? At the moment when you click to open a nautilus folder already open on an another workspace you are moved to this workspace by example.
If the analogy wasn't clear: I think changing workspaces should happen almost exclusively in response to a direct user request for it, not as a side effect of some other action. To me, the semantics of the desktop icons is "open the folder here" rather than "warp me to whereever I opened this folder last"
right, I agree with that :)
*** Bug 171543 has been marked as a duplicate of this bug. ***
So I had to work around the workspace switching change in Tomboy using some pretty hairy code... check out the end of http://cvs.gnome.org/viewcvs/tomboy/libtomboy/tomboyutil.c?view=markup I think gedit also uses some of this code to accomplish the same thing.
Do I understand correctly that gtk_window_present() cannot be used by an application to focus one of its windows when the user is interacting with another application (since the user_time of the first application will likely be lower than user_time of the second one, making Metacity ignore the request)? Moreover, is it possible for the first application to request focus using NET_ACTIVE_WINDOW? IMHO again no, because the only time snapshot it could send is its own, and that may be lower than the _NET_WM_USER_TIME property of the window currently having the focus.
Andrei: Yes, that's part of the point of focus stealing prevention. Apps shouldn't dictate policy--that should be up to the WM. (Apps should say "I'm important, please let the user know", not "I'm important, raise me" or "I'm important, focus me" or "I'm important, please minimize all other apps so that the user can give me my due attention".) In response to your second question, yes it is totally possible for an application to request focus using _NET_ACTIVE_WINDOW. Granted, Metacity will deny the request in the cases you talked about, but that's because it matches the policy it chose. Note that in these cases, though, Metacity will set the DEMANDS_ATTENTION hint on windows that have an out-of-date _NET_ACTIVE_WINDOW request; if you feel that policy is insufficient (note that our implementation of DEMANDS_ATTENTION is very suboptimal currently) or that there needs to be an additional important/urgent type that is handled differently from most apps, please file a Metacity bug with the details about any such problems.
Created attachment 48030 [details] [review] a patch to add gtk_window_present_time() Here is a patch which adds a gtk_window_present() variant which takes a timestamp. I would be happy for better naming proposals.
2005-06-20 Matthias Clasen <mclasen@redhat.com> * gtk/gtk.symbols: * gtk/gtkwindow.h: * gtk/gtkwindow.c (gtk_window_present_with_time): Variant of gtk_window_present which takes a timestamp. (#166379, Elijah Newren)
*** Bug 171541 has been marked as a duplicate of this bug. ***
The "users is moved to an another workspace issue is still here". Elijah, do you think that's a window manager or a gtk issue (that's not clear if gtk_window_present () should use _NET_WM_DESKTOP, or if the window manager should "just do the right thing" (ie: moving the window and not changing the desktop))?
As mentioned in bug 128380, the whole reason the workspace switch issue exists is because the intent of the EWMH is that _NET_ACTIVE_WINDOW does NOT switch what workspace a window is on, yet Metacity did so for a long time. That has been fixed. Bryan says that gtk_window_present() SHOULD switch what workspace a window is on. Given that requirement, gtk_window_present() can not just use _NET_ACTIVE_WINDOW; it must also make use of _NET_WM_DESKTOP. I'll attach a patch in a minute that does so. I wasn't sure whether we should make a separate function for the _NET_WM_DESKTOP stuff and have gtk_window_present() also call that, or whether to just add it to gdk_window_focus(). For now, I just did the latter. Also, the version of gtk_window_present_with_time() in the last patch didn't handle GDK_CURRENT_TIME being passed. So the patch I will attach will account for that too.
Created attachment 48884 [details] [review] Add use of _NET_WM_DESKTOP to gdk_window_focus(), fix GDK_CURRENT_TIME issue with gtk_window_present()
Could you maybe instead add a new function that both focuses and switches desktops? I am very worried that this would break Eclipse as we use gdk_window_focus (and already have bugs about metacity causing our windows to inadvertently switch desktops).
Yay! Finally everything will work again, and I can remove my gross hacks to get the old gtk_window_present behavior! Hope this patch goes in in time for the next release.
Elijah, I'd like to contest the notion that the EWMH mandates that activation does not move a window to a different workspace. I wrote the introductory section of the EWMH which introduces the notion of activation, and it says: In the X world, activating a window means to give it the input focus. This may not be possible if the window is unmapped, because it is on a different desktop. Thus, activating a window may involve additional steps like moving it to the current desktop (or changing to the desktop the window is on), deiconifying it or raising it.
Billy: I'm guessing that a separate function shouldn't be any problem. Of course, we have to get Matthias' concerns addressed first, so if we forget later for any reason, make sure to whack us hard (or at least remind us). ;-) Matthias: Well, you're much more knowledgeable than I about all things X related, but I'm really not the person to argue with. I was merely doing what others had agreed on. Well before I had even joined the wm-spec list, they had a thread on the list which discussed this issue and which was followed up in bug 128380. Lubos, Havoc, and apparently others came to the conclusion that _NET_ACTIVE_WINDOW should not move a window to another desktop. (See bug 128380 for all details and a link to the wm-spec archives.) I was just trying to improve our standards conformance so that hopefully apps would work better (in the long run, of course). If you convince them, I'll happily change. I could try to argue the case, but I think you'd do better at it. (Also, if you do convince them to change, we may need to work out some special stuff for Billy and others as he claims there our cases where Metacity's old behavior breaks stuff)
Created attachment 48890 [details] [review] alternative patch I'm not going to fight over this issue any longer. Maybe window managers will become smarter about activation in the future, but then it will be too late, because toolkits will hardwire the "move the window to the current desktop" behaviour, as the following alternative patch does. It does not modify gdk_window_focus() and instead makes the move-to-current-desktop explicit in gtk_window_present. Does that look better to you, Billy ?
2005-07-11 Matthias Clasen <mclasen@redhat.com> Make gdk_window_present() move the window to the current desktop, instead of letting the WM change the current desktop to where the window is. (#166379, Elijah Newren) * gdk/gdk.symbols: * gdk/x11/gdkx.h: * gdk/x11/gdkwindow-x11.c (gdk_x11_window_move_to_current_desktop): New function to move a window to the current desktop. * gtk/gtkwindow.c (gtk_window_present_with_time): Move the window to the current desktop before giving it focus.
*** Bug 304404 has been marked as a duplicate of this bug. ***
The metacity _NET_ACTIVE_WINDOW change was reverted on both the gnome-2-10 branch and on HEAD; a 2.10.3 release was made with the reversion, and a 2.11.something release will be made tomorrow. The portion of the patch you objected to Matthias can be reverted. (See bug 128380 comment 17 for details)
*** Bug 313178 has been marked as a duplicate of this bug. ***
I am completely confused about this bug and what I should understand from it. Here's what's happened to me: - I run FC4 - I use a tasklist, showing all windows from all workspaces - I use this to navigate around a lot (which I didn't realize before the bug I ran into) - I recently pulled in a metacity update from 2.10.0 to 2.10.3 - After that, every time I clicked on an app in the tasklist, instead of switching me to that app on its desktop, it moves the app to my *current* desktop. End result - all my windows end up on the same desktop. It took me an hour to figure out what was going on in the first place :) I was doing stuff, and at some point I noticed all these windows were all together and my nice separation was gone. - I tried pushing some knobs here and there, made another user, asked around, ... After two days of wasting a lot of time being annoyed while trying to get work done, I downgraded metacity and it works again. If I follow this whole discussion a little, it would seem that gtk_present_window is being used by the task applet, and maybe that's the wrong function to use, since Bryan claims that gtk_present_window should "bring the window to you" ? My biggest gripe atm is that this is an annoying chance to have come over you during a stable series. Can someone break down the results of this whole bug report for me so I know what I should do with my problem ? Thanks, Thomas
Thomas: libwnck (the library that controls the tasklist stuff) doesn't use gtk_window_present() to activate windows (it can't--it doesn't own the windows and thus doesn't have a GtkWindow) so you don't need to understanding anything from this bug other than that it is only tangentially related to your problem. I believe your problem is that you upgraded Metacity without upgrading libwnck (yeah it sucks that we needed both to be updated in a stable release for people using two certain non-default options, but it was what we were stuck with); feel free to email me off list if upgrading libwnck along with Metacity doesn't solve your issues.