Show login UI on all monitors for compositor-agnostic focus

Wayland does not expose absolute pointer coordinates to clients,
so we cannot reliably detect which monitor has focus. Instead,
show the full lockscreen UI on every monitor — the compositor
assigns keyboard focus to the surface under the pointer via
ext-session-lock-v1.

Share a single FingerprintListener across all windows to avoid
multiple device claims. Also add makepkg build artifacts to
gitignore.
This commit is contained in:
nevaforget 2026-03-26 13:58:45 +01:00
parent 0eefe76a3a
commit b365572033
4 changed files with 24 additions and 26 deletions

6
.gitignore vendored
View File

@ -5,3 +5,9 @@ __pycache__/
dist/ dist/
build/ build/
.pytest_cache/ .pytest_cache/
# makepkg build artifacts
pkg/src/
pkg/pkg/
pkg/moonlock/
pkg/*.pkg.tar.*

View File

@ -4,7 +4,7 @@
# Maintainer: Dominik Kressler # Maintainer: Dominik Kressler
pkgname=moonlock-git pkgname=moonlock-git
pkgver=0.1.0 pkgver=0.0.0.r8.0eefe76
pkgrel=1 pkgrel=1
pkgdesc="A secure Wayland lockscreen with GTK4, PAM and fingerprint support" pkgdesc="A secure Wayland lockscreen with GTK4, PAM and fingerprint support"
arch=('any') arch=('any')

View File

@ -23,7 +23,8 @@ class LockscreenWindow(Gtk.ApplicationWindow):
"""Fullscreen lockscreen window with password and fingerprint auth.""" """Fullscreen lockscreen window with password and fingerprint auth."""
def __init__(self, application: Gtk.Application, unlock_callback: callable | None = None, def __init__(self, application: Gtk.Application, unlock_callback: callable | None = None,
config: Config | None = None) -> None: config: Config | None = None,
fingerprint_listener: FingerprintListener | None = None) -> None:
super().__init__(application=application) super().__init__(application=application)
self.add_css_class("lockscreen") self.add_css_class("lockscreen")
@ -33,8 +34,8 @@ class LockscreenWindow(Gtk.ApplicationWindow):
self._failed_attempts = 0 self._failed_attempts = 0
self._unlock_callback = unlock_callback self._unlock_callback = unlock_callback
# Fingerprint listener # Fingerprint listener (shared across windows to avoid multiple device claims)
self._fp_listener = FingerprintListener() self._fp_listener = fingerprint_listener or FingerprintListener()
self._fp_available = ( self._fp_available = (
self._config.fingerprint_enabled self._config.fingerprint_enabled
and self._fp_listener.is_available(self._user.username) and self._fp_listener.is_available(self._user.username)
@ -44,8 +45,8 @@ class LockscreenWindow(Gtk.ApplicationWindow):
self._setup_keyboard() self._setup_keyboard()
self._password_entry.grab_focus() self._password_entry.grab_focus()
# Start fingerprint listener if available # Start fingerprint listener if available (only once across shared instances)
if self._fp_available: if self._fp_available and not self._fp_listener._running:
self._fp_listener.start( self._fp_listener.start(
self._user.username, self._user.username,
on_success=self._on_fingerprint_success, on_success=self._on_fingerprint_success,

View File

@ -17,7 +17,8 @@ gi.require_version("Gtk", "4.0")
gi.require_version("Gdk", "4.0") gi.require_version("Gdk", "4.0")
from gi.repository import Gtk, Gdk from gi.repository import Gtk, Gdk
from moonlock.config import load_config, resolve_background_path from moonlock.config import load_config
from moonlock.fingerprint import FingerprintListener
from moonlock.lockscreen import LockscreenWindow from moonlock.lockscreen import LockscreenWindow
# ext-session-lock-v1 via gtk4-layer-shell # ext-session-lock-v1 via gtk4-layer-shell
@ -56,27 +57,17 @@ class MoonlockApp(Gtk.Application):
display = Gdk.Display.get_default() display = Gdk.Display.get_default()
monitors = display.get_monitors() monitors = display.get_monitors()
# Shared fingerprint listener across all windows (only one can claim the device)
fp_listener = FingerprintListener()
for i in range(monitors.get_n_items()): for i in range(monitors.get_n_items()):
monitor = monitors.get_item(i) monitor = monitors.get_item(i)
# Primary monitor gets the full UI window = LockscreenWindow(
if i == 0: application=self,
window = LockscreenWindow( unlock_callback=self._unlock,
application=self, config=self._config,
unlock_callback=self._unlock, fingerprint_listener=fp_listener,
config=self._config, )
)
else:
# Secondary monitors get the wallpaper without login UI
window = Gtk.ApplicationWindow(application=self)
window.add_css_class("lockscreen")
wallpaper = Gtk.Picture.new_for_filename(
str(resolve_background_path(self._config))
)
wallpaper.set_content_fit(Gtk.ContentFit.COVER)
wallpaper.set_hexpand(True)
wallpaper.set_vexpand(True)
window.set_child(wallpaper)
self._lock_instance.assign_window_to_monitor(window, monitor) self._lock_instance.assign_window_to_monitor(window, monitor)
window.present() window.present()
self._windows.append(window) self._windows.append(window)