
I'm having a problem where sometimes my OverrideRedirect window is not visible on the screen after XMapRaised, even though XQueryTree reports that it is on top.
The compositor may be implicated, as apparently it involves a magic window that is on top of all others that is intentionally omitted from the XQueryTree list, because the world is insane.
I have read the documentation, such as it is, and tried a few things, but there seem to be several mutually exclusive paths through the compositor, not all of which involve that magic window, so my question is:
Given the set of window managers that I am likely to encounter in the real world, what is my best bet for making my OverrideRedirect window actually appear on top of all other visible windows? (Which is literally the one and only thing that "OverrideRedirect" was supposed to mean.)
(I assume that any answer involving _NET_WM properties or ClientMessages is incorrect, as those only apply to non-OverrideRedirect windows that are managed by the window manager.)
Relatedly: which window manager in reasonably common use does the most pessimally fucked up compositor-related things, that I should test against?
Update: Interestingly, and in case this should ring any bells, when I am in this state where XMapRaised on my window does not cause it to become visible on the screen (despite XQueryTree saying that it is on top) destroying and re-creating the window does work.
That could be KWin (or whatever it's now called) with all its values for 'prevent window stealing'.
/me goes check...
SystemSettings -> Workspace -> Window Management -> Window Behaviour -> Focus -> Focus Stealing Prevention
* pant * * pant *
I would suggest using XRaiseWindow() followed by XFlush() to force a window to the top - and don't go down the path of _NET_WM. You should also be listening for Expose and VisibilityNotify events for the redraw, which you should likely call it again. The small caveat there is that if you have more than one window doing this, they will fight to the death.
Do you ever create your OverrideRedirect window before the WM has selected SubstructureRedirectMask? I think I vaguely remember encountering bugs around how various WMs use XQueryTree to learn about existing windows at startup. If this is happening, creating the window just before you map it or otherwise deferring its creation so the WM receives a CreateNotify event (and hopefully starts tracking the window for compositing) may help.
Wilder speculation: XMapRaised looks like it sends ConfigureWindow first and then MapWindow. Do you still see the problem if you instead call XMapWindow followed by XRaiseWindow? I think I remember seeing creative approaches taken by different WMs with regard to whether they start tracking windows on CreateNotify vs. on MapRequest/MapNotify. If the WM only pays attention to the window after it's mapped, it may be ignoring earlier ConfigureNotify events and screwing up the stacking order as a result.
No, this is reproducible with an app started long after WM startup.
My workaround of re-creating the window rather than raising it seems to be working, but it's just bizarre. One especially strange thing is that, though my window is not visible on the screen, the mouse cursor behaves as if it is. That is: a screen saver is running, rendering on the full screen, but the mouse cursor changes when its in the rectangle where my dialog box ought to be but is not. Which is what makes me think this is some kind of crazy compositor-extension fuckup.
That, and when I launch Xorg with the composite extension disabled, the bug doesn't happen.
Yeah, that's consistent with the compositing manager screwing up and either being completely oblivious to the override-redirect window or not stacking it correctly when compositing.
So you see this sometimes when you create the window, then wait a while and call XMapRaised, but never when you follow that by creating a new window and immediately calling XMapRaised on it? There are uncountable ways for WMs to implement ICCCM/EWMH and nobody bothers with testing anything beyond GTK+ and QT, but I'm confused about why recreating the window is helping in this case -- it sounds like the sequence of requests (create, configure, map) is the same in both cases.
Is this with a particular compositing WM or are you using xcompmgr or something similar?
Yeah, pretty much. XMapRaised causes the results from XQueryTree to change, but the bits on the screen are full of lies. Adding an XDestroyWindow / XCreateWindow before my XMapRaised call works around the bug. So something got fixated on the old window ID, or it being a new ID short-circuits the restacking bug, or something.
I was able to reproduce this with mutter 3.30.2-9~deb10u1, xcompmgr 1.1.7-1+rpt1, Raspbian 10.6.
Mutter will never fix the bug now that you've worked around it :)
Hmm. xcompmgr was mostly just a proof-of-concept for XCOMPOSITE; it's buggy and I wouldn't read much into problems that show up when using it. compton is a fork that's probably the least-buggy standalone compositing manager. Seeing the same issue in mutter is suspicious, though, since I don't think its compositing code has any overlap with xcompmgr.
I was going to suggest setting EWMH's _NET_WM_BYPASS_COMPOSITOR property to 1 on the window, since mutter appears to honor it for override-redirect windows and it may sidestep compositor bugs while saving some copies. However, mutter 3.30.2 is already trying to unredirect (in the XCompositeUnredirectWindow sense) fullscreen override-redirect windows, so now I'm confused about why your window is even being messed with there. It looks like the override-redirect part of this code was rewritten since 3.30.2, so it may still be worthwhile to set the property explicitly.
Just to mention it, xsecurelock looks like it does lots of junk (including setting _NET_WM_BYPASS_COMPOSITOR) to work around compositor issues.
You say this as if xcompmgr is some goofball thing I decided to install on my own, and not something that was installed and is running by default on this vanilla and up-to-date Raspbian system.
Also, I tried _NET_WM_BYPASS_COMPOSITOR = 1 and _NET_WM_STATE = _NET_WM_STATE_FULLSCREEN and that didn't affect anything.
Are you saying that WMs that do compositing are able to notice and fuck with override redirect windows? Does override redirect mean nothing now?
XCOMPOSITE makes the compositing manager responsible for drawing all mapped windows into the composite overlay window with their correct positions and stacking, so yeah, it'll fuck with override-redirect windows to the extent that it fails to do that properly.
Override redirect (OR) still means what it meant but composite proto adding the Composite Overlay Window (COW) means that OR windows don't necessarily show up unless the compositor decides to show them. You can call it breaking the original X proto intent ¯_(ツ)_/¯
If the compositor decides that a window (OR or not) shoulnd't be composited (maybe you want here) it can tell the X server to clip the COW in order for the window to "show through".
This sounds like a compositor bug WRT stacking order of your OR window.
Have you tried XLowerWindow() followed by XRaiseWindow() on your OR window after it's been mapped, instead of the create+destroy dance? I wonder if that alone would get the compositor's drawing order synchronized with reality...