GNOME Bugzilla – Bug 166395
Window raised without taking focus (after gdk_window_show/gdk_window_focus)
Last modified: 2005-02-06 17:02:44 UTC
If in gtk code you call (with an old time): gdk_window_show (window->window); gdk_window_focus (window->window, time); The window is raised (it doesn't have the focus), possibly obscuring the current window. I am using this code as a replacement for gtk_window_present() which doesn't allow specifying the time. I'll attach a simple test case.
Created attachment 37039 [details] Testcase To work the testcase: 1) Compile it :-) 2) run it, and click the button in the window 3) Now interact with another window 4) After 5 seconds, the window will be raised, over the top of the window you just interacted with.
There's two problems: 1) meta_window_activate doesn't pay attention to timestamp to decide whether to honor the request or whether to set the demands_attention hint. 2) gdk_window_focus calls XRaiseWindow which sends an xconfigurerequest event which we unconditionally honor. Patches incoming...
Created attachment 37040 [details] [review] Be smart about handling the _NET_ACTIVE_WINDOW (gdk_window_focus) request; pay attention to timestamps
Created attachment 37041 [details] [review] Ignore inherently buggy xconfigurerequest's Okay, so this one's kind of debatable, but remember Havoc's comment in the relevant section of code: ...all client attempts to deal with stacking order are essentially broken, since they have no idea what other clients are involved or how the stack looks... There was also the recent firefox bug about this. Of course, the whole problem is that "Havoc once upon a time knew of a legacy app that this seemed to break," though we don't know if that was another bug in Metacity or if any such app still exists that still has such a problem. So, two other possible solutions (and a third would be to use both...): 1) Fix gtk+ (and firefox, as pointed out in another bug...) to not use XRaiseWindow--at least not with respectable WMs. 2) Only ignore xconfigurerequest raise/lower's from clients that support certain wm_protocols (e.g. if the client supports _NET_WM_PING or _NET_WM_SYNC_REQUEST it ought to be safe to know that the app had knowledge of the EWMH and thus could use more intelligent ways to do whatever it wanted).
Comment on attachment 37040 [details] [review] Be smart about handling the _NET_ACTIVE_WINDOW (gdk_window_focus) request; pay attention to timestamps If timestamp is 0 that means it's an old _NET_ACTIVE_WINDOW before it supported timestamps, right? There have to be tons of these in various apps...
Comment on attachment 37041 [details] [review] Ignore inherently buggy xconfigurerequest's I still think this is just not compatible. No WM does this. You could have it do this with "disable workarounds" setting, and give it some more testing maybe. My take on gdk_window_focus() is that it does not call XRaiseWindow(), just sends _NET_ACTIVE_WINDOW.
Created attachment 37043 [details] [review] Fix it up for clients using an old version of the EWMH spec (oops)
> My take on gdk_window_focus() is that it does not call XRaiseWindow(), just > sends _NET_ACTIVE_WINDOW. Oops, I meant gdk_window_show() not gdk_window_focus(). gdk_window_show(), via show_window_internal() calls XRaiseWindow. However, how about smarter behavior: We currently keep track of the user_time for each window. We could keep track of a global user_time as well (which is the maximum of the user_time values across all windows). Then, when we receive such an event, ignore it if that window's user_time is less than the global user time. I stole this idea by googling on xconfigurerequest and taking a brief look at KWin code (which maybe I should try again sometime, it was surprisingly useful, unlike the only other time I tried it). I'm not sure if this is exactly what they do as I only looked at two relevant lines of code: if ( e->value_mask & CWStackMode ) restackWindow(e->above,e->detail,NET::FromApplication,userTime(),false); But that does make me think that's the idea they have. Anyway, does it sound sane to you to try?
Sounds like it might work. We might have to say this only applies to windows that have a user time though. (We aren't tracking a user time for legacy apps, right? Or did you add that?)
All windows have a user_time; Metacity has a fallback where it tracks button presses for the client. (This effectively means that keypresses aren't counted as user interaction for such legacy apps. This is is suboptimal, but I didn't want to go through the trouble of grabbing every keystroke for every app). Since users typically launch applications using the mouse (and switch applications that way as well), this tends to work pretty well in practice. And, well, users making use of legacy applications can't really expect _perfect_ integration... ;-) Okay, so I thought about the when-to-ignore-xconfigurerequest stuff a lot more. The only possible failing of my proposal I could think of was if the xconfigurerequest was sent while another window of the same application was active and it was interaction with that active window that somehow required the other window to be raised. Then I went and read a lot of KWin code and KWin bug reports. They like to configure stuff to death, but basically, their default behavior (the only one I'm interested in as it's the widest tested...and hopefully also fairly sane), does the timestamp stuff proposed above plus a same application check. So, I think this is the right path. The only major difference I could see is that KWin has a much more comprehensive routine for checking whether two windows are from the same application than our meta_window_same_application(); they include checking whether one window is an ancestor/transient of the other, checking whether the windows have different PIDs (assuming _NET_WM_PID is defined), and even attempting to use wm_client_machine, wm_window_role, and res_class/res_name as backups... It may be worth using some of the same things to make meta_window_same_application() more robust in general. Anyway, I'll attach a patch in a moment, but without any additions to meta_window_same_application() for now.
Created attachment 37051 [details] [review] Be smart about when to listen to xconfigurerequest events
Comment on attachment 37051 [details] [review] Be smart about when to listen to xconfigurerequest events This looks worth a try. I can't really predict what will happen, but we can give it a shot ;-)
Okay, I went ahead and committed (with a small fix for an accidental logic inversion). I'm assuming from your previous comments that the other fixed-up patch for meta_window_activate is also okay to commit so I went ahead and did that too.