fix: panel on all monitors with keyboard exclusive
Instead of guessing the primary monitor (unreliable on Niri), show the panel with action buttons on every monitor. All get keyboard exclusive so the focused monitor captures input. Also set exclusive_zone -1 to overlay Waybar, and delay initial focus grab via GLib.idle_add for layer shell readiness.
This commit is contained in:
parent
2e359f358d
commit
467c022525
@ -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
|
||||
|
||||
@ -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,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user