Wayland layer-shell overlay (always-on-top over fullscreen games) - #6
Wayland layer-shell overlay (always-on-top over fullscreen games)#6raman78 wants to merge 3 commits into
Conversation
|
Pushed a revision addressing the feedback:
One thing I deliberately left out: proper HiDPI/fractional-scale handling for the overlay surface (it still renders at Let me know what else you'd like changed. |
Render the always-on-top metrics overlay through a wlr-layer-shell surface on Linux (the winit/eframe always-on-top hint is ignored on Wayland, so the overlay could never stay above a full-screen game). The overlay is draggable with a click-through body, remembers its position, and adopts the main window's egui style. It shares a single wgpu instance/adapter/device/queue with eframe (created at startup and handed to eframe via WgpuSetup::Existing), so the app runs one Vulkan stack rather than two. The Linux backend lives under app::overlay::layer_shell; the approach is documented in docs/OVERLAY.md. Also remember the main window's size and maximized state across restarts and fix a couple of Wayland-specific window issues (a 0x0 initial-size crash and jittery resizing).
Remembering the main window size, raising its minimum size and the redraw-while-resizing tweak have nothing to do with the overlay, and carrying them here made this branch touch main.rs and the settings struct for unrelated reasons. The window size persistence is proposed separately. The minimum size and the resize redraw stay on the development branches for now. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
Narrowed this down to the overlay. The main-window geometry work that was bundled in here (remembering the window size, redrawing while resizing, and the larger minimum size) was unrelated to it and made this branch touch |
The overlay chose its back end with #[cfg(target_os = "linux")], so every Linux build used wlr-layer-shell. That is a Wayland protocol, and in an X11 session there is nothing to connect to: the layer thread failed at Connection::connect_to_env, logged an error and exited, leaving the Overlay button doing nothing at all. Before this branch those users had a working always-on-top overlay window. Both back ends are now compiled on Linux and the choice is made while the app runs. App::new only injects the shared wgpu handles when eframe's CreationContext reports a RawDisplayHandle::Wayland, which is the back end winit actually picked rather than a guess, and having those handles is what OverlayInner::uses_layer_shell asks about. A session without them falls back to the viewport instead of failing, so the two can never disagree. main.rs makes the same call one step earlier, before any window exists, the way winit does it (WAYLAND_DISPLAY / WAYLAND_SOCKET), so an X11 session no longer builds a shared wgpu stack it will not use — and no longer runs the two expects inside create_shared_gpu for a back end it cannot reach. The chosen back end is logged once at startup. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
Follow-up: the back end is now picked per session rather than per target OS. As it stood, every Linux build went to wlr-layer-shell, which meant that in an X11 session the layer thread failed at |
What & why
On Wayland the winit/eframe path cannot keep the metrics overlay above a full-screen game — the compositor simply won't honor always-on-top for a regular top-level. This PR renders the overlay through wlr-layer-shell on the dedicated overlay layer in a Wayland session, which is the reliable way to sit above fullscreen.
X11, Windows and macOS keep the existing always-on-top viewport, unchanged.
Note that on X11 this is only as good as the window manager's handling of
_NET_WM_STATE_ABOVE: testing on KWin (via XWayland) the overlay window does appear, but it does not stay above a full-screen game. That is the pre-existing behaviour of this path and the reason the Wayland back end exists — the point of the runtime choice below is that an X11 session gets the same overlay it has today, rather than a button that silently does nothing.Overlay
docs/OVERLAY.md.Choosing the back end
Which back end is used is decided at runtime, not with
#[cfg(target_os = "linux")]. A single Linux build has to serve both session types, and wlr-layer-shell is a Wayland protocol: in an X11 session there is nothing to connect to, and picking it there would leave the Overlay button doing nothing.App::newonly injects the shared wgpu handles when eframe'sCreationContextreports aRawDisplayHandle::Wayland— the back endwinitactually picked, rather than a guess — and having those handles is whatOverlayInner::uses_layer_shell()asks about, so the two cannot disagree. A session without them falls back to the viewport.main.rsmakes the same call one step earlier, before any window exists, the way winit does it, so an X11 session does not build a shared wgpu stack it will not use.The selected back end is logged once at startup (
overlay backend: ...).Not included
The main-window geometry changes that used to be part of this PR (remembering the size, the redraw while resizing, the larger minimum size) had nothing to do with the overlay and are proposed separately in #8.
Notes
The Wayland/wgpu dependencies are Linux-only (
[target.'cfg(target_os = "linux")'.dependencies]).Verified on KDE: the layer-shell back end in a Wayland session, and the viewport back end in an X11 session (via
env -u WAYLAND_DISPLAY).Overlap with #8
Both this PR and #8 change the same lines of
src/app/mod.rsandsrc/main.rs— this branch removes the window-geometry code that used to sit there, #8 adds its own version in the same place — so whichever of the two you merge first, the other will report a conflict.Nothing for you to resolve: merge either one in any order and I will rebase the other branch and push, which updates its PR automatically. The two changes are independent in substance; only the text overlaps.