1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
//! Wayland `wlr-layer-shell` styled-popup presenter — **SCAFFOLD ONLY** (0.11.0).
//!
//! This is the third [`LinuxMenuPresenter`](super::LinuxMenuPresenter) impl: the
//! self-drawn, pixel-identical styled popup on the compositors that expose
//! `zwlr_layer_shell_v1` — every wlroots compositor (sway, Hyprland, river,
//! Wayfire, labwc, cosmic-comp) **and** KWin/Plasma. GNOME/Mutter refuses
//! layer-shell as an architectural stance (research doc §6, mutter#973), so it
//! stays on the native dbusmenu presenter — see [`super::detect_linux_presenter`].
//!
//! ## Why this module carries no code yet
//!
//! The real implementation needs the Wayland client stack
//! (`smithay-client-toolkit` + `wayland-client`), which is **Linux-only** and
//! does not build on the macOS host this crate is currently gated against (the
//! `cargo build --all-features` gate must stay green on macOS). So the whole
//! module is gated behind BOTH `all(unix, not(target_os = "macos"))` (via its
//! parent [`super`]) **and** the off-by-default `wayland-styled` cargo feature,
//! and every function that would touch a live Wayland connection has a
//! `todo!("DEVICE-VERIFY: …")` body describing the exact device-side step. The
//! signatures + lifecycle are fixed here so the seam is real; the bytes are added
//! on a Linux session (ADR-0003, first device task).
//!
//! ## The recipe this module will implement (research doc §3, §12)
//!
//! 1. Bind `wl_compositor`, `wl_shm`, `wl_seat`, and `zwlr_layer_shell_v1` from
//! the registry. If `zwlr_layer_shell_v1` is absent → not our path (the caller
//! already fell back to the dbusmenu presenter via detection).
//! 2. Create a **full-output overlay** layer surface: anchor to all four edges,
//! `exclusive_zone(-1)`, `KeyboardInteractivity::OnDemand`, an empty input
//! region except under the menu. Because it covers the output, `wl_pointer`
//! motion coordinates *are* output coordinates (the only pointer-position
//! channel Wayland gives a client).
//! 3. `get_popup` a child `xdg_popup` positioned by an `xdg_positioner` with a
//! 1×1 anchor rect at the pointer (for `ContextMenu::open_at`) or at the
//! SNI-reported coordinate (Plasma/Waybar tray-anchored). The positioner's
//! constraint-adjustment gives on-screen flip/slide for free.
//! 4. Blit muri's premultiplied-RGBA [`RasterDrawer`](crate::render::RasterDrawer)
//! framebuffer into a `wl_shm` `Argb8888` buffer. `Argb8888` is BGRA in memory
//! (little-endian), premultiplied — so the per-pixel work is a single **R↔B
//! swap**; alpha is already premultiplied (see [`blit_argb8888`]). Unlike the
//! X11 path (`super::x11::encode_framebuffer`, which composites over an opaque
//! background), layer-shell keeps true alpha so rounded corners / shadow
//! survive — the compositor composites the ARGB surface.
//! 5. Drive pointer/keyboard from the `wl_seat` handlers, reusing the shared,
//! display-server-agnostic `flyout` + `keynav` state machines exactly as the
//! X11 backend does; only the transport (`wl_shm` attach/damage/commit) and
//! positioning (layer-surface + xdg-popup) differ.
// Scaffold: the seam is defined here; the bodies are the
// first device-side task (ADR-0003). Every item below is
// referenced by the real implementation added on Linux.
use crate;
use crate;
use crate;
use crateMenuOptions;
/// Whether the current Wayland compositor advertises `zwlr_layer_shell_v1` — the
/// authoritative test for whether the styled layer-shell presenter is usable
/// (research doc §10, detection step 2). A live answer must bind the registry on
/// a real `wl_display`, which cannot be done on the macOS gate host, so the body
/// is deferred; [`super::detect_linux_presenter`] uses a cheap env heuristic
/// ([`super::wayland_env_suggests_layer_shell`]) to select the presenter and this
/// function is the device-side confirmation before a surface is actually created.
///
/// DEVICE-VERIFY(0.11.0): connect to `$WAYLAND_DISPLAY`, `wl_registry.global`
/// enumerate, return whether `zwlr_layer_shell_v1` appears. Add
/// `wayland-client`/`smithay-client-toolkit` first (see ADR-0003).
pub
/// Open a styled, self-drawn popup on a layer-shell compositor and block until it
/// dismisses — the Wayland analogue of [`super::x11::open_popup_session`].
///
/// `anchor` is the pointer (or SNI-reported) point the popup grows from relative
/// to `edge`; `on_click` receives the activated row's id. Reuses the shared
/// `render_menu` layout + `flyout`/`keynav` machinery; only transport +
/// positioning are Wayland-specific.
///
/// DEVICE-VERIFY(0.11.0): the full lifecycle — bind globals, create the
/// full-output overlay layer surface, `get_popup` at `anchor`, blit via
/// [`blit_argb8888`], run the seat event loop, tear down on dismiss.
pub ,
anchor: LogicalRect,
edge: Edge,
dark: bool,
)
/// The global pointer position via the full-output overlay surface's own
/// `wl_pointer` motion — the *only* pointer channel a Wayland client has
/// (research doc §5). Meaningful only while an overlay surface is mapped and the
/// pointer is over it; `None` otherwise. The tray-anchored case instead uses the
/// out-of-band SNI `ContextMenu`/`Activate` coordinate (Plasma/Waybar).
///
/// DEVICE-VERIFY(0.11.0): map the overlay, cache the last `wl_pointer` motion
/// coordinate, return it here.
pub
/// Blit muri's premultiplied-RGBA framebuffer into a `wl_shm` `Argb8888`
/// (BGRA-in-memory, premultiplied) destination buffer: a per-pixel R↔B swap,
/// alpha copied through unchanged (already premultiplied). Pure byte-shuffling —
/// no Wayland handle — so it is implemented **now** and unit-testable on the host
/// once the transport lands; only the destination `canvas` (a mapped `wl_shm`
/// slot) is device-side.
///
/// `src` is muri's framebuffer (`RasterDrawer::framebuffer().pixels()`, RGBA
/// premultiplied); `dst` is the mapped `wl_shm` `Argb8888` canvas. Both are
/// `4 * width * height` bytes.
pub