fix(gui): give the window a real icon instead of the Wayland fallback

Set the Wayland app_id to `pixelpass` so the compositor matches the
installed pixelpass.desktop and uses its Icon= in the titlebar/taskbar,
replacing the generic fallback. Also embed a 256px PNG (rendered from
assets/pixelpass.svg) and set it via with_icon for X11 _NET_WM_ICON, and
add StartupWMClass=pixelpass to the desktop entry for robust window↔entry
matching across desktop environments. No new deps — eframe already pulls
the image crate, and icon_data::from_png_bytes decodes the embed.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-05-26 05:24:25 -04:00
parent 6c275faf28
commit ad70ce5ea9
3 changed files with 19 additions and 4 deletions
+18 -4
View File
@@ -18,11 +18,25 @@ use self::child::{ChildEvent, ChildProc};
/// Launch the GUI event loop. Blocks until the window is closed. Runs on the
/// main thread (a winit requirement), which is where `main` calls it from.
pub fn run() -> anyhow::Result<()> {
// `app_id` must match the installed `pixelpass.desktop`: on Wayland the
// compositor sources the titlebar/taskbar icon from that desktop file's
// `Icon=` keyed by app_id — not from any pixels the app sets.
let mut viewport = egui::ViewportBuilder::default()
.with_app_id("pixelpass")
.with_inner_size([520.0, 480.0])
.with_min_inner_size([460.0, 380.0])
.with_title("PixelPass");
// Pixel icon for X11 titlebars (`_NET_WM_ICON`), embedded at compile time
// so the single binary stays self-contained. Non-fatal on failure: Wayland
// already has its icon via app_id, and X11 just keeps the generic fallback.
match eframe::icon_data::from_png_bytes(include_bytes!("../../assets/pixelpass-256.png")) {
Ok(icon) => viewport = viewport.with_icon(icon),
Err(e) => tracing::warn!("could not load embedded window icon: {e}"),
}
let options = eframe::NativeOptions {
viewport: egui::ViewportBuilder::default()
.with_inner_size([520.0, 480.0])
.with_min_inner_size([460.0, 380.0])
.with_title("PixelPass"),
viewport,
..Default::default()
};