max / alloy_tui
- Co-Authored-By
- Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 file changed,
+9 insertions,
-1 deletion
| @@ -44,12 +44,20 @@ | |||
| 44 | 44 | - This is the first place Departure Mono renders in a real Alloy surface. Verify the font registration in `alloy_ui::theme` before relying on it here, and document the fallback chain if Departure's unicode coverage misses anything in the user's locale-formatted date. | |
| 45 | 45 | - The focus ring is `border-strong`, never accent. Failed-auth state may *temporarily* color the status text in `accent-error`, per the accent-on-text rule in [TOKENS.md](../../docs/TOKENS.md#accent-on-surface-text-rule). The password field's border does **not** flip to accent. | |
| 46 | 46 | - The lockscreen runs at `surface` tier. The password field sits on `surface-raised`. No popovers, no overlays — there is nowhere for an overlay to go on a lockscreen. | |
| 47 | + | - **Visual reference: the bar.** The lockscreen and the bar are both persistent chrome surfaces and should share visual language — same Departure Mono treatment for time and date, same case and tracking, same density. Alloy doesn't ship an authored bar yet (Ironbar is the curated v0 pick, an egui bar is v3+), so the lockscreen *sets* the precedent: whatever the time/date readout looks like on the lockscreen is what the bar's clock module mirrors when it gets authored. When the Ironbar Alloy theme is written for v0, port the lockscreen's time/date treatment to it as the canonical reference. | |
| 48 | + | ||
| 49 | + | ## Resilience contract | |
| 50 | + | ||
| 51 | + | The lockscreen has a sharper failure profile than any other Alloy surface: when it breaks, the user is locked out of their session with no fallback UI to debug from. Two non-negotiable rules: | |
| 52 | + | ||
| 53 | + | - **Services launch async.** PAM context init, clock ticker, Wayland event pump, and output enumeration all start concurrently at process boot. The render loop draws the first frame as soon as the Wayland surface is up — it does not wait for PAM. PAM submit calls run on a worker task; the UI thread never blocks on auth. Default runtime: a single current-thread async executor (likely tokio with `rt` only — no IO/net features needed). Each service feeds its state into a snapshot struct the render pass reads each frame. | |
| 54 | + | - **The login option never crashes.** Every error on the auth path (PAM context init failure, PAM auth error, worker-task panic, locale lookup failure) is caught and rendered as status text in the surface. The password field stays present and focused regardless of upstream failure. No `.unwrap()`, no `.expect()`, no panic on any code path reachable from a keystroke. If PAM cannot be initialized at startup, the surface shows the failure mode explicitly and offers a retry — it does not exit the process. This rule is stricter than open question #4 (whole-process crash recovery): the auth path is the user's only way out, so it cannot be allowed to fail loudly. | |
| 47 | 55 | ||
| 48 | 56 | ## Architecture | |
| 49 | 57 | ||
| 50 | 58 | The lockscreen does **not** use `eframe`. eframe drives Wayland through winit, which opens its own `wl_display` connection — that connection can't share state with whatever owns the session lock, and the session lock has to be owned by the same client that owns the surfaces it draws into. So alloy_lockscreen owns its Wayland connection directly via `smithay-client-toolkit` and drives egui via `egui_glow` on raw GL contexts (one per output). | |
| 51 | 59 | ||
| 52 | - | Practically: a small render loop pulls Wayland events from SCTK's `calloop` source, feeds keyboard/pointer events into an `egui::Context`, runs the egui pass, and submits the painted output through `egui_glow` to the GL context bound to each `ExtSessionLockSurfaceV1`. The alloy_ui crate is consumed exactly as in the showcase example — `apply_alloy_visuals` + primitives — only the host loop differs. | |
| 60 | + | Practically: a small async render loop pulls Wayland events from SCTK's `calloop` source, feeds keyboard/pointer events into an `egui::Context`, runs the egui pass, and submits the painted output through `egui_glow` to the GL context bound to each `ExtSessionLockSurfaceV1`. PAM, the clock ticker, and Wayland I/O each run as their own async task feeding a snapshot the render pass reads each frame — per the resilience contract below. The alloy_ui crate is consumed exactly as in the showcase example — `apply_alloy_visuals` + primitives — only the host loop differs. | |
| 53 | 61 | ||
| 54 | 62 | ## Stack picks | |
| 55 | 63 |