From cd42df109569e0f9814e715c85481e46f21339b2 Mon Sep 17 00:00:00 2001 From: nevaforget Date: Thu, 9 Apr 2026 15:04:29 +0200 Subject: [PATCH] fix: handle monitor hotplug for greeter windows (v0.8.2) Greeter windows were only created at startup. Hotplugged monitors (e.g. HDMI reconnect) would show no UI. Connect to the monitor ListModel's items-changed signal to create greeter windows for newly added monitors. Aligned with moonlock's hotplug fix using the same pattern adapted for gtk4-layer-shell (ListModel) instead of session-lock (connect_monitor). --- CLAUDE.md | 2 +- Cargo.lock | 2 +- Cargo.toml | 2 +- DECISIONS.md | 7 +++++++ README.md | 2 +- src/main.rs | 29 +++++++++++++++++++++++++++++ 6 files changed, 40 insertions(+), 4 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 8ddcf52..8021910 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -47,7 +47,7 @@ cd pkg && makepkg -sf && sudo pacman -U moongreet-git--x86_64.pkg.tar.z - `fingerprint.rs` — fprintd D-Bus Probe (gio::DBusProxy) — Geräteerkennung und Enrollment-Check für UI-Feedback - `config.rs` — TOML-Config ([appearance] background, gtk-theme, fingerprint-enabled) + Wallpaper-Fallback + Blur-Validierung (finite, clamp 0–200) - `greeter.rs` — GTK4 UI (Overlay-Layout), Login-Flow via greetd IPC (Multi-Stage-Auth für fprintd), Faillock-Warnung, Avatar-Cache, Last-User/Last-Session Persistence (0o700 Dirs, 0o600 Files) -- `main.rs` — Entry Point, GTK App, Layer Shell Setup, Multi-Monitor (one greeter window per monitor, first gets keyboard), systemd-journal-logger +- `main.rs` — Entry Point, GTK App, Layer Shell Setup, Multi-Monitor mit Hotplug via `items-changed` auf Monitor-ListModel (one greeter window per monitor, first gets keyboard), systemd-journal-logger - `resources/style.css` — Catppuccin-inspiriertes Theme ## Design Decisions diff --git a/Cargo.lock b/Cargo.lock index 4e1770f..0eb89d9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -575,7 +575,7 @@ dependencies = [ [[package]] name = "moongreet" -version = "0.7.4" +version = "0.8.0" dependencies = [ "gdk-pixbuf", "gdk4", diff --git a/Cargo.toml b/Cargo.toml index 50758a4..f525d7d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "moongreet" -version = "0.8.0" +version = "0.8.2" edition = "2024" description = "A greetd greeter for Wayland with GTK4 and Layer Shell" license = "MIT" diff --git a/DECISIONS.md b/DECISIONS.md index cc05e4b..5137a9f 100644 --- a/DECISIONS.md +++ b/DECISIONS.md @@ -1,5 +1,12 @@ # Decisions +## 2026-04-09 – Monitor hotplug via ListModel items-changed + +- **Who**: ClaudeCode, Dom +- **Why**: Greeter windows were only created at startup. If a monitor was hotplugged (e.g. HDMI reconnect), it would show no greeter UI. Aligned with moonlock's hotplug fix (same day). +- **Tradeoffs**: Hotplugged monitors get greeter windows without keyboard input (keyboard stays on the primary monitor). Acceptable — user can still interact on the primary screen. +- **How**: Connect to `display.monitors().connect_items_changed()` and create new greeter windows for added monitors. Shared state (config, texture, blur_cache) moved to Rc for the closure. + ## 2026-04-08 – Show greeter UI on all monitors instead of just one - **Who**: ClaudeCode, Dom diff --git a/README.md b/README.md index 4fb9e09..11d229e 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ Part of the Moonarch ecosystem. - **Last user/session** — Remembered in `/var/cache/moongreet/` - **Power actions** — Reboot / Shutdown via `loginctl` - **Layer Shell** — Fullscreen via gtk4-layer-shell (TOP layer) -- **Multi-monitor** — Full greeter UI on all monitors (keyboard input on first) +- **Multi-monitor + hotplug** — Full greeter UI on all monitors (keyboard input on first), hotplugged monitors get windows automatically - **GPU blur** — Background blur via GskBlurNode (shared cache across monitors) - **i18n** — German and English (auto-detected from system locale) - **Faillock warning** — Warns after 2 failed attempts, locked message after 3 diff --git a/src/main.rs b/src/main.rs index 72276a8..d225afd 100644 --- a/src/main.rs +++ b/src/main.rs @@ -11,9 +11,11 @@ mod sessions; mod users; use gdk4 as gdk; +use glib::clone; use gtk4::prelude::*; use gtk4::{self as gtk, gio}; use gtk4_layer_shell::LayerShell; +use std::rc::Rc; fn load_css(display: &gdk::Display) { let css_provider = gtk::CssProvider::new(); css_provider.load_from_resource("/dev/moonarch/moongreet/style.css"); @@ -80,6 +82,33 @@ fn activate(app: >k::Application) { first = false; } } + + // Handle monitor hotplug — create greeter windows for newly added monitors + // (without keyboard, since the primary monitor already has it) + let bg_texture = Rc::new(bg_texture); + let config = Rc::new(config); + monitors.connect_items_changed(clone!( + #[weak] + app, + #[strong] + blur_cache, + move |list, position, _removed, added| { + for i in position..position + added { + if let Some(monitor) = list + .item(i) + .and_then(|obj| obj.downcast::().ok()) + { + log::debug!("Monitor hotplug: creating greeter window"); + let window = greeter::create_greeter_window( + bg_texture.as_ref().as_ref(), &config, &blur_cache, &app, + ); + setup_layer_shell(&window, false, gtk4_layer_shell::Layer::Top); + window.set_monitor(Some(&monitor)); + window.present(); + } + } + } + )); } else { // No layer shell — single window for development let greeter_window = greeter::create_greeter_window(bg_texture.as_ref(), &config, &blur_cache, app);