fix(overlay): keep the Actions Ring above panels on Linux/Wayland - #1211
Open
4ni1ak wants to merge 2 commits into
Open
fix(overlay): keep the Actions Ring above panels on Linux/Wayland#12114ni1ak wants to merge 2 commits into
4ni1ak wants to merge 2 commits into
Conversation
A plain WindowKind::PopUp is just another toplevel to a Wayland compositor — nothing stops it being drawn under a panel/dock's own always-on-top surface, so the ring could open hidden behind one. Anchor it as an AnchoredPopup off an invisible full-screen Layer::Overlay host instead: that layer is guaranteed above everything else, including panels. The host also fixes cursor placement as a side effect. openlogi_hook's Linux cursor_position() falls back to XWayland's X11 query_pointer under a Wayland session — not a real Wayland pointer, and it doesn't track one, so it reports a stale, display-ambiguous coordinate on a Wayland-native desktop. The host surface gets the compositor's own first pointer-motion delivery instead (with a bounded fallback to the old X11-based guess if none arrives), which is accurate regardless of which monitor the cursor is on. Every dismissal path (slot/cancel/root click, click-away, the display-lifetime timeout) now closes the host alongside the ring, and clicking the host itself dismisses the ring — click-away-to-dismiss Linux never had, since the existing native monitor is macOS-only. Falls back to the previous plain-PopUp behavior on macOS, Windows, Linux/X11, and Wayland compositors without zwlr_layer_shell_v1. Fixes AprilNEA#1210
Greptile SummaryThe PR places the Actions Ring above Wayland panels by anchoring it to a full-screen layer-shell host and obtains its position from compositor-delivered pointer motion.
Confidence Score: 5/5The PR appears safe to merge. No blocking failure remains.
|
| Filename | Overview |
|---|---|
| crates/openlogi-overlay/src/main.rs | Delegates ring creation to the asynchronous host-aware path and closes the optional host on display timeout. |
| crates/openlogi-overlay/src/ring.rs | Implements the Wayland layer-shell host, compositor-derived cursor anchoring, corrected fallback conversion, and cleanup after popup creation failure. |
| crates/openlogi-overlay/src/session.rs | Extends session-checked click-away dismissal to remove the ring’s associated Wayland host. |
Flowchart
%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[Ring invocation] --> B{Linux Wayland with layer shell?}
B -->|No| C[Open plain popup]
B -->|Yes| D[Open full-screen overlay host]
D --> E{Pointer motion within 250 ms?}
E -->|Yes| F[Use compositor cursor position]
E -->|No| G[Convert fallback placement to host-local anchor]
F --> H[Open anchored popup]
G --> H
H --> I{Dismissal or timeout}
I --> J[Close ring and host]
H -->|Popup open fails| K[Close host and return error]
Reviews (2): Last reviewed commit: "fix(overlay): cross-platform build + fal..." | Re-trigger Greptile
- Gate the oneshot import and silence the non-Linux stub's unused_async Linux-only — cargo clippy/test --workspace only ran the Linux cfg branch locally, so the non-Linux stub's unused import/async broke the macOS and Windows CI jobs. - The 250ms no-pointer-motion fallback in linux_wayland_ring_host was reusing ring_placement()'s global-coordinate origin as a host-local anchor — exactly the coordinate-space bug the host exists to avoid, reintroduced on a secondary display. Convert it the same way the main PopUp fallback does. - open_ring leaked the host window when the anchored popup itself failed to open: no RingView exists yet for any dismissal path to find, so the invisible full-screen host would sit there blocking clicks until the next ring invocation. Close it explicitly on that error path. Both anchor/leak issues via Greptile review on AprilNEA#1211.
Contributor
Author
|
Fixed everything, pushed
Re-ran the local gate (fmt/clippy/test) green on the final tree. Still no macOS/Windows toolchain here to verify those two CI lanes directly, but the fix is mechanical (cfg-gate the import, document the async-signature mismatch) — will watch CI. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
On Linux under a Wayland compositor (reproduced live on KDE Plasma/KWin), the Actions Ring could open hidden behind a panel/dock, and its position was unreliable on a multi-monitor setup.
Fixes #1210
Root cause
WindowKind::PopUp, which on Wayland is just anotherxdg_toplevelsurface — nothing guarantees it draws above a panel/dock's own always-on-topzwlr_layer_shell_v1overlay-layer surface.openlogi_hook::cursor_position()on Linux falls back to XWayland's X11query_pointerunder a Wayland session. That isn't a real Wayland pointer query and doesn't track one — confirmed live, it returned the exact same coordinate across multiple cursor moves and clicks on two different monitors.Changes
crates/openlogi-overlay/src/ring.rs:open_ringnow opens an invisible full-screenLayer::Overlayhost window first, then anchors the ring to it as aWindowKind::AnchoredPopup(center anchor + center gravity on the real cursor point). The overlay layer is guaranteed above everything else, including panels. Falls back to the previous plainWindowKind::PopUpat the old best-effort position guess on macOS, Windows, Linux/X11, or a Wayland compositor withoutzwlr_layer_shell_v1.gpui::Window::mouse_position, fed by native platform pointer events) rather than the X11 query — accurate regardless of which monitor the cursor is on. Bounded at 250ms, falling back to the old best-effort guess if the compositor never delivers one, so a ring still opens rather than hanging.crates/openlogi-overlay/src/session.rs:dismiss_click_away(previously reachable only via the macOS-only native click-away monitor) now also closes the ring's host window when it fires.Side effect worth calling out: clicking the invisible host — i.e. anywhere outside the ring — now dismisses it on Linux too. Linux never had click-away-to-dismiss before this; the existing mechanism (a native OS click monitor) is macOS-only.
Testing
Linux, x86_64, Rust 1.98.0:
Runtime-verified live on this machine: KDE Plasma (KWin) Wayland session, dual monitor (primary + a secondary at a nonzero global X offset). Iterated through several rounds against the real compositor — confirmed the ring now stays above the panel and opens correctly centered on the cursor on both monitors, including the timeout fallback path (observed firing once when the compositor was slow to deliver the first pointer event).
Not tested: macOS, Windows, Linux/X11, or another Wayland compositor (GNOME/Mutter, Hyprland, Sway) — the fallback path is unchanged from the pre-existing behavior on all of those, but I don't have hardware/sessions for any of them to confirm.