Client attempts to deal with stacking order considered harmful

I was asked on IRC to explain why it is that programs mostly cannot raise their own windows.

The mechanism:
gtk_window_show() indirectly calls XRaiseWindow. This causes a ConfigureRequest X event. Metacity will only honour this if:

  • the window belongs to the active application (but if there is no active application, any application can raise its windows), or
  • there has been user activity in the new window more recently than in the active window

In all other cases it will ignore the request. If the request is to raise a window (rather than to lower it), it will set the attention hint on the window which was trying to raise itself.

The policy:

  • Havoc noted in r460 that:
    …in fact 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.

    although that changeset did allow clients to raise themselves.

  • After a discussion based partly on this , GNOME bug 166395 in February 2005 established a consensus that client attempts to deal with stacking order should be ignored; this was implemented in r1936.
  • However, this left the program believing that it had alerted the user but with no change in the display, which was unhelpful. Therefore, in GNOME bug 305882 it was decided that when client attempts to deal with stacking order were ignored, the attention flag should be set instead; this was implemented in r2045.

This is not just GNOME being weird: here’s Lubos Lunak (the kwin maintainer) saying the same thing last year.

If you think this is a bad idea, figure out which part of it you think is a bad idea and then complain on that bug, or on wm-spec-list.

10 Comments

  1. Xavier Claessens
    Posted December 24, 2007 at 9:08 am | Permalink

    AH! Now I understand why I have that empathy bug:

    http://bugzilla.gnome.org/show_bug.cgi?id=502930

    What do you suggest to workaround that?

    I always considered that behaviour a metacity bug. In my opinion metacity should always raise windows if it’s asked. It’s up to GNOME programs to not popup windows when it’s not needed, we have a notification area to notify user of new event and we can set urgency hint to avoid poping it directly. Seriously in all cases I saw a window with the urgency hint on it because metacity refused to raise, I *always* considered that a metacity bug and I directly clicked on the window to raise it.

    In my opinion it’s not up to metacity to make the decision of not raising a window, but it’s up to programs to NOT ask raising windows if not needed.

    With modern desktop we have more and more separated processes that communicates through DBus, metacity can’t assumes that if it’s a different process it means it’s not directly requested by the user.

    At least that’s my opinion…

  2. Posted December 24, 2007 at 12:31 pm | Permalink

    I don’t suggest anything to work around that: gtk_window_present() says “This may mean raising the window in the stacking order, deiconifying it, moving it to the current desktop, and/or giving it the keyboard focus”. Clearly messing with the stacking order is optional.

    Note that I said that it belongs to the same application, or to be more precise the same group (in the ICCCM sense), not the same process (which is ultimately not really our business).

  3. Posted December 24, 2007 at 12:49 pm | Permalink

    (It seems to me that the idea of raising a window because of an action in another window, when the windows are as closely related as these are, is exactly why there is the exemption for members of the same ICCCM group. Are these two windows *not* members of the same group? If not, why not?)

  4. Brent Goodrick
    Posted December 27, 2007 at 4:32 pm | Permalink

    Thanks very much for your writeup, Thomas.

    You stated “the window belongs to the active application”. How does Metacity determine what the active application is?

    Brent

  5. Posted December 27, 2007 at 4:46 pm | Permalink

    When I said “the active application” I meant the application which owns the active window; the active window is pretty much equivalent in Metacity to the window which has the keyboard input focus. I can give you function and field names if you like.

  6. Brent Goodrick
    Posted December 27, 2007 at 5:17 pm | Permalink

    Thanks. Sure, I would like to consider using your suggested API if necessary, provided they are window-manager-independent and whose use is not discouraged for interoperability reasons.

    Does your “user activity” comment mean that that Metacity only numerically compares the _NET_WM_USER_TIME X property value of that requesting window to the _NET_WM_USER_TIME X property value of the currently active window, to determine whether to allow the raise request to go through, based on which value is greater?

    Brent

  7. Posted December 27, 2007 at 5:32 pm | Permalink

    I’m not sure which API you’re referring to.

    Does your “user activity” comment mean that that Metacity only numerically compares the _NET_WM_USER_TIME X property value of that requesting window to the _NET_WM_USER_TIME X property value of the currently active window, to determine whether to allow the raise request to go through, based on which value is greater?

    It uses the XSERVER_TIME_IS_BEFORE macro defined in display.h. In practical terms this means that:

    if the raising window’s _NET_WM_USER_TIME is zero it will always fail; and

    if the active window’s _NET_WM_USER_TIME is more recent than the raising window’s _NET_WM_USER_TIME it will always fail, provided that

    the active window has a non-zero _NET_WM_USER_TIME; and

    “more recent” is more complicated than a numerical comparison because X timestamps wrap after a month or two and, as much as it’s possible, we take account of that.

  8. Brent Goodrick
    Posted December 27, 2007 at 10:55 pm | Permalink

    I’ll take a look at that macro, as that gives me hints as to the API I could use for my case.

    Thanks for your help!

  9. Brent Goodrick
    Posted December 31, 2007 at 7:54 pm | Permalink

    This might be useful for others who need to programmatically raise top-level X windows:

    I tried setting the _NET_WM_USER_TIME X window property on the target window (in this case, the X window corresponding to Firefox), and metacity raised it. However, the focus did not change away from the currently active window.

    I read through the standard for _NET_WM_USER_TIME (http://standards.freedesktop.org/wm-spec/wm-spec-1.3.html#id2506353), and so tried it out on a small X application running under Metacity and it worked: Metacity raised the target window to the top of the stack and gave it input focus.

    Thanks,
    Brent

  10. Brent Goodrick
    Posted December 31, 2007 at 7:57 pm | Permalink

    Correction: “_NET_ACTIVE_WINDOW” is the type of ClientMessage I used, and not “_NET_WM_USER_TIME” in the link to http://standards.freedesktop.org/wm-spec/wm-spec-1.3.html#id2506353. To bad this page has no edit capability.

    Brent