feat(gui): hand-rolled winit loop for true window-hide on Wayland
Replace eframe::run_native with a winit ApplicationHandler + glutin + egui_glow loop so "keep running in the tray" can genuinely hide the window. winit's set_visible(false) is a deliberate no-op on Wayland (xdg-shell has no unmap-but-keep-alive request), so the only way to hide a toplevel is to destroy its surface: hide-to-tray now drops the Window + GL surface (parking the GL context as not-current) and a tray click recreates them and makes the context current again. The GL context, glutin display/config, egui_glow painter (uploaded textures), and egui-winit state (clipboard) all persist across the cycle — only the OS window and its surface churn. Wakeups route through winit's EventLoopProxy (the new Waker, and the tray) instead of egui's repaint callback, so a child event or tray click wakes the loop even while the window is dropped and no frame is running — keeping viewer join/leave notifications and the tray tooltip live while hidden. Removes the old Wayland minimize-to-tray fallback (window stayed in the taskbar); hide is now uniform on Wayland and X11. Deps: winit/glutin/glutin-winit/egui_glow promoted to direct (gui-gated, optional) — all already transitive via eframe, so no new crates. winit's default features minus wayland-csd-adwaita, so sctk-adwaita/tiny-skia/ ttf-parser aren't pulled for a CSD fallback titlebar (KWin draws server-side decorations, and eframe never had CSD either). Verified end-to-end on KWin Wayland: launch->render; close->window AND taskbar entry gone (true hide, process stays alive); tray activate-> window + GL surface recreated and renders; tray quit->clean exit; stderr clean throughout. cargo test --features gui: 15 pass; clippy clean; headless dependency tree unchanged. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
+16
-1
@@ -40,6 +40,21 @@ notify-rust = { version = "4", optional = true }
|
||||
# System-tray icon (StatusNotifierItem over D-Bus). Pure-Rust, riding the same
|
||||
# zbus stack notify-rust already pulls — no GTK, no libappindicator/C libdbus.
|
||||
ksni = { version = "0.3", optional = true }
|
||||
# Hand-rolled windowing stack for the GUI (replaces eframe::run_native) so we
|
||||
# can drop the OS window on "hide to tray" — the only way to truly hide a
|
||||
# toplevel on Wayland — and recreate it on Show. All of these are already pulled
|
||||
# in transitively by eframe; making them direct adds no new crates to vet.
|
||||
# eframe is kept for its egui re-export + icon_data PNG decoder. egui_glow needs
|
||||
# its (non-default) `winit` feature for the `EguiGlow` integration type; eframe
|
||||
# pulls egui_glow but without that feature, so we enable it here.
|
||||
egui_glow = { version = "0.34.2", default-features = false, features = ["winit", "wayland", "x11"], optional = true }
|
||||
# winit's default set minus `wayland-csd-adwaita`: KWin (and most desktop
|
||||
# compositors) draw server-side decorations, and eframe never enabled CSD
|
||||
# either, so dropping it keeps the dependency tree identical to before (no
|
||||
# sctk-adwaita / tiny-skia / ttf-parser pulled in just for a fallback titlebar).
|
||||
winit = { version = "0.30", default-features = false, features = ["rwh_06", "x11", "wayland", "wayland-dlopen"], optional = true }
|
||||
glutin = { version = "0.32", optional = true }
|
||||
glutin-winit = { version = "0.5", optional = true }
|
||||
|
||||
[profile.release]
|
||||
lto = "thin"
|
||||
@@ -49,4 +64,4 @@ strip = "symbols"
|
||||
[features]
|
||||
# Opt-in graphical front-end (pixelpass --gui). Default-off so the headless
|
||||
# build never pulls the GUI toolkit tree.
|
||||
gui = ["dep:eframe", "dep:notify-rust", "dep:ksni"]
|
||||
gui = ["dep:eframe", "dep:notify-rust", "dep:ksni", "dep:egui_glow", "dep:winit", "dep:glutin", "dep:glutin-winit"]
|
||||
|
||||
Reference in New Issue
Block a user