This is to work around "misbehaving" (for lack of a better term)
clients. At the moment, Firefox Nightly and Google Chrome/Chromium are
known to be suchs client:
When XWayland support is enabled, Firefox first creates an XWayland
surface, closes this (before mapping it) and then opens an XDG toplevel
surface. Cage tries to manage the first XWayland surface, but when it
closes, Cage has no surfaces left and hence closes as well.
Hence, Cage terminates before it picks up on Firefox's XDG toplevel, and
Firefox (rightly) prints it cannot read the Wayland pipe.
In Chromium's case, it simply opens an XWayland surface which it
immediately closes, before opening the "real" XWayland surface.
The workaround is to track whether an XWayland surface has been mapped
and, if it hasn't, to not exit when we have no views left.
Firefox's behavior and the workaround are discussed in #18.
This commit fixes#18 and is part of the fix for #19.
This is the path we settled on in #24.
That is: any new toplevel window takes over the Cage display, hiding any
previous toplevels until it is closed. Only when the last toplevel is
closed, does Cage exit as well.
This allows us to check per-view whether is has dialogs open, instead of
diong it on a global basis as we are doing currently. This is necessary
for fully supporting multiple primary clients.
With this, some apps (e.g. mpv) can block the idle tracker from
kicking in. This way, the screen won't blank (or whatever you
configured) when the application doesn't want it to.
With Cage becoming more popular since its mention on Phoronix and
therefore getting more use-cases than just my own project, add XWayland
support. The refactoring of 2cf40f7 makes this much easier. Note that
this is a no-cost addition for those of us not using XWayland as it is a
compile-time option that needs to be explicitly enabled by adding
`-Dxwayland=true` to your meson command.
We shouldn't render a window before it is mapped (obviously), but we
render all windows in the view list. Hence, only insert the window once
it is mapped.
We could run into the case where a window is destroyed without being in
the window list, so we now track unmapping again and remove windows from
the list when they get unmapped.
Since this is inherently output independent, we can move this to here
and avoid the inexistance of an output we ran into in the previous
commit.
Warping the cursor is no problem here either: since we restrict
ourselves to a single output, there won't be any confusing UX by having
the cursor jump from one output to the newly attached one.
This makes Cage much easier to maintain. Not only is it easier where to
look and to maintain a mental model of the code, there is also more
encapsulation, better abstractions and better extendability.