After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 166395 - Window raised without taking focus (after gdk_window_show/gdk_window_focus)
Window raised without taking focus (after gdk_window_show/gdk_window_focus)
Status: RESOLVED FIXED
Product: metacity
Classification: Other
Component: general
2.9.x
Other Linux
: High normal
: 2.10.x
Assigned To: Metacity maintainers list
Metacity maintainers list
Depends on:
Blocks: 149028
 
 
Reported: 2005-02-05 21:58 UTC by Crispin Flowerday (not receiving bugmail)
Modified: 2005-02-06 17:02 UTC
See Also:
GNOME target: ---
GNOME version: 2.9/2.10


Attachments
Testcase (1.16 KB, text/plain)
2005-02-05 21:59 UTC, Crispin Flowerday (not receiving bugmail)
  Details
Be smart about handling the _NET_ACTIVE_WINDOW (gdk_window_focus) request; pay attention to timestamps (884 bytes, patch)
2005-02-05 22:09 UTC, Elijah Newren
none Details | Review
Ignore inherently buggy xconfigurerequest's (1.03 KB, patch)
2005-02-05 22:26 UTC, Elijah Newren
rejected Details | Review
Fix it up for clients using an old version of the EWMH spec (oops) (1006 bytes, patch)
2005-02-05 23:12 UTC, Elijah Newren
none Details | Review
Be smart about when to listen to xconfigurerequest events (2.17 KB, patch)
2005-02-06 06:58 UTC, Elijah Newren
accepted-commit_now Details | Review

Description Crispin Flowerday (not receiving bugmail) 2005-02-05 21:58:32 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.
Comment 1 Crispin Flowerday (not receiving bugmail) 2005-02-05 21:59:55 UTC
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.
Comment 2 Elijah Newren 2005-02-05 22:08:56 UTC
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...
Comment 3 Elijah Newren 2005-02-05 22:09:56 UTC
Created attachment 37040 [details] [review]
Be smart about handling the _NET_ACTIVE_WINDOW (gdk_window_focus) request; pay attention to timestamps
Comment 4 Elijah Newren 2005-02-05 22:26:03 UTC
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 5 Havoc Pennington 2005-02-05 22:55:43 UTC
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 6 Havoc Pennington 2005-02-05 22:58:57 UTC
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.
Comment 7 Elijah Newren 2005-02-05 23:12:53 UTC
Created attachment 37043 [details] [review]
Fix it up for clients using an old version of the EWMH spec  (oops)
Comment 8 Elijah Newren 2005-02-05 23:46:32 UTC
> 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?
Comment 9 Havoc Pennington 2005-02-06 05:16:22 UTC
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?)
Comment 10 Elijah Newren 2005-02-06 06:57:39 UTC
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.
Comment 11 Elijah Newren 2005-02-06 06:58:43 UTC
Created attachment 37051 [details] [review]
Be smart about when to listen to xconfigurerequest events
Comment 12 Havoc Pennington 2005-02-06 15:45:55 UTC
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 ;-)
Comment 13 Elijah Newren 2005-02-06 17:02:44 UTC
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.