perf: async fprintd initialization for instant window display
Move all fprintd D-Bus calls (init, availability check, claim, verify) from synchronous to async using gio futures. Windows now appear immediately without waiting for D-Bus — fingerprint label fades in once fprintd is ready. Single shared FingerprintListener across all monitors instead of one per monitor.
This commit is contained in:
+54
-6
@@ -13,9 +13,12 @@ use gdk4 as gdk;
|
||||
use gtk4::prelude::*;
|
||||
use gtk4::{self as gtk, gio};
|
||||
use gtk4_session_lock;
|
||||
use std::cell::RefCell;
|
||||
use std::path::PathBuf;
|
||||
use std::rc::Rc;
|
||||
|
||||
use crate::fingerprint::FingerprintListener;
|
||||
|
||||
fn load_css(display: &gdk::Display) {
|
||||
let css_provider = gtk::CssProvider::new();
|
||||
css_provider.load_from_resource("/dev/moonarch/moonlock/style.css");
|
||||
@@ -75,27 +78,67 @@ fn activate_with_session_lock(
|
||||
app_clone.quit();
|
||||
});
|
||||
|
||||
// Create all monitor windows immediately — no D-Bus calls here
|
||||
let mut all_handles = Vec::new();
|
||||
let mut created_any = false;
|
||||
for i in 0..monitors.n_items() {
|
||||
if let Some(monitor) = monitors
|
||||
.item(i)
|
||||
.and_then(|obj| obj.downcast::<gdk::Monitor>().ok())
|
||||
{
|
||||
let window = lockscreen::create_lockscreen_window(
|
||||
let handles = lockscreen::create_lockscreen_window(
|
||||
bg_path,
|
||||
config,
|
||||
app,
|
||||
unlock_callback.clone(),
|
||||
);
|
||||
lock.assign_window_to_monitor(&window, &monitor);
|
||||
window.present();
|
||||
lock.assign_window_to_monitor(&handles.window, &monitor);
|
||||
handles.window.present();
|
||||
all_handles.push(handles);
|
||||
created_any = true;
|
||||
}
|
||||
}
|
||||
|
||||
if !created_any {
|
||||
log::error!("No lockscreen windows created — screen stays locked (compositor policy)");
|
||||
return;
|
||||
}
|
||||
|
||||
// Async fprintd initialization — runs after windows are visible
|
||||
if config.fingerprint_enabled {
|
||||
init_fingerprint_async(all_handles);
|
||||
}
|
||||
}
|
||||
|
||||
/// Initialize fprintd asynchronously after windows are visible.
|
||||
/// Uses a single FingerprintListener shared across all monitors —
|
||||
/// only the first monitor's handles get the fingerprint UI wired up.
|
||||
fn init_fingerprint_async(all_handles: Vec<lockscreen::LockscreenHandles>) {
|
||||
glib::spawn_future_local(async move {
|
||||
let mut listener = FingerprintListener::new();
|
||||
listener.init_async().await;
|
||||
|
||||
// Use the first monitor's username to check enrollment
|
||||
let username = &all_handles[0].username;
|
||||
if username.is_empty() {
|
||||
return;
|
||||
}
|
||||
|
||||
if !listener.is_available_async(username).await {
|
||||
log::debug!("fprintd not available or no enrolled fingers");
|
||||
return;
|
||||
}
|
||||
|
||||
let fp_rc = Rc::new(RefCell::new(listener));
|
||||
|
||||
// Show fingerprint label on all monitors
|
||||
for handles in &all_handles {
|
||||
lockscreen::show_fingerprint_label(handles, &fp_rc);
|
||||
}
|
||||
|
||||
// Start verification listener on the first monitor only
|
||||
lockscreen::start_fingerprint(&all_handles[0], &fp_rc);
|
||||
});
|
||||
}
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
@@ -109,14 +152,19 @@ fn activate_without_lock(
|
||||
app_clone.quit();
|
||||
});
|
||||
|
||||
let window = lockscreen::create_lockscreen_window(
|
||||
let handles = lockscreen::create_lockscreen_window(
|
||||
bg_path,
|
||||
config,
|
||||
app,
|
||||
unlock_callback,
|
||||
);
|
||||
window.set_default_size(800, 600);
|
||||
window.present();
|
||||
handles.window.set_default_size(800, 600);
|
||||
handles.window.present();
|
||||
|
||||
// Async fprintd initialization for development mode
|
||||
if config.fingerprint_enabled {
|
||||
init_fingerprint_async(vec![handles]);
|
||||
}
|
||||
}
|
||||
|
||||
fn setup_logging() {
|
||||
|
||||
Reference in New Issue
Block a user