diff --git a/src/moonset/main.py b/src/moonset/main.py index 8eeb764..8c3931a 100644 --- a/src/moonset/main.py +++ b/src/moonset/main.py @@ -58,7 +58,7 @@ class MoonsetApp(Gtk.Application): def __init__(self) -> None: super().__init__(application_id="dev.moonarch.moonset") - self._secondary_windows: list[WallpaperWindow] = [] + self._windows: list[PanelWindow] = [] def do_activate(self) -> None: """Create and present power menu windows on all monitors.""" @@ -73,37 +73,17 @@ class MoonsetApp(Gtk.Application): config = load_config() bg_path = resolve_background_path(config) + # Panel window on every monitor — keyboard exclusive on all so + # the focused monitor always captures input monitors = display.get_monitors() - primary_monitor = None - - # Find primary monitor — fall back to first available for i in range(monitors.get_n_items()): monitor = monitors.get_item(i) - if hasattr(monitor, "is_primary") and monitor.is_primary(): - primary_monitor = monitor - break - if primary_monitor is None and monitors.get_n_items() > 0: - primary_monitor = monitors.get_item(0) - - # Main power menu window on primary monitor - panel = PanelWindow(bg_path=bg_path, application=self) - if HAS_LAYER_SHELL: - self._setup_layer_shell(panel, keyboard=True) - if primary_monitor is not None: - Gtk4LayerShell.set_monitor(panel, primary_monitor) - panel.present() - - # Wallpaper-only windows on secondary monitors - for i in range(monitors.get_n_items()): - monitor = monitors.get_item(i) - if monitor == primary_monitor: - continue - wallpaper_win = WallpaperWindow(bg_path=bg_path, application=self) + panel = PanelWindow(bg_path=bg_path, application=self) if HAS_LAYER_SHELL: - self._setup_layer_shell(wallpaper_win, keyboard=False) - Gtk4LayerShell.set_monitor(wallpaper_win, monitor) - wallpaper_win.present() - self._secondary_windows.append(wallpaper_win) + self._setup_layer_shell(panel, keyboard=True) + Gtk4LayerShell.set_monitor(panel, monitor) + panel.present() + self._windows.append(panel) def _load_css(self, display: Gdk.Display) -> None: """Load the CSS stylesheet for the power menu.""" @@ -122,6 +102,7 @@ class MoonsetApp(Gtk.Application): """Configure gtk4-layer-shell for fullscreen OVERLAY display.""" Gtk4LayerShell.init_for_window(window) Gtk4LayerShell.set_layer(window, Gtk4LayerShell.Layer.OVERLAY) + Gtk4LayerShell.set_exclusive_zone(window, -1) if keyboard: Gtk4LayerShell.set_keyboard_mode( window, Gtk4LayerShell.KeyboardMode.EXCLUSIVE diff --git a/src/moonset/panel.py b/src/moonset/panel.py index 7ef9505..552e237 100644 --- a/src/moonset/panel.py +++ b/src/moonset/panel.py @@ -119,6 +119,9 @@ class PanelWindow(Gtk.ApplicationWindow): self._build_ui(bg_path) self._setup_keyboard() + # Focus the first action button once the window is mapped + self.connect("map", self._on_map) + def _build_ui(self, bg_path: Path) -> None: """Build the panel layout with wallpaper background and action buttons.""" # Main overlay for background + centered content @@ -196,6 +199,19 @@ class PanelWindow(Gtk.ApplicationWindow): controller.connect("key-pressed", self._on_key_pressed) self.add_controller(controller) + def _on_map(self, widget: Gtk.Widget) -> None: + """Grab focus on the first action button once the window is visible.""" + # Delay focus grab — layer shell keyboard interactivity may not + # be ready at map time + GLib.idle_add(self._grab_initial_focus) + + def _grab_initial_focus(self) -> bool: + """Set focus on the first action button.""" + first_button = self._button_box.get_first_child() + if first_button is not None: + first_button.grab_focus() + return GLib.SOURCE_REMOVE + def _on_key_pressed( self, controller: Gtk.EventControllerKey,