fix: properly unlock on niri by flushing Wayland connection before exit
The ext-session-lock-v1 protocol does not guarantee a `finished` event after the client calls `unlock_and_destroy` — that event is only sent when the compositor independently terminates the lock. Waiting for it caused rustlock to hang forever on niri (and any spec-compliant compositor). The previous attempt to fix this by setting exit=true immediately broke unlocking because the while loop stopped calling event_loop.dispatch, leaving the unlock_and_destroy bytes unflushed in the client-side Wayland send buffer and never reaching the compositor. Store the Connection in WaylandLock and explicitly call conn.flush() after session_lock.unlock(), ensuring the unlock request is sent before we exit. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
+5
-7
@@ -104,6 +104,7 @@ impl log::Log for DualLogger {
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct WaylandLock {
|
struct WaylandLock {
|
||||||
|
conn: Connection,
|
||||||
loop_handle: LoopHandle<'static, Self>,
|
loop_handle: LoopHandle<'static, Self>,
|
||||||
lock_manager: Arc<Mutex<LockManager>>,
|
lock_manager: Arc<Mutex<LockManager>>,
|
||||||
config: Config,
|
config: Config,
|
||||||
@@ -123,7 +124,6 @@ struct WaylandLock {
|
|||||||
captured_backgrounds: Vec<Option<cairo::ImageSurface>>,
|
captured_backgrounds: Vec<Option<cairo::ImageSurface>>,
|
||||||
pending_screenshots: usize,
|
pending_screenshots: usize,
|
||||||
exit: bool,
|
exit: bool,
|
||||||
unlocking: bool,
|
|
||||||
screenshot_manager: Option<ScreenshotManager>,
|
screenshot_manager: Option<ScreenshotManager>,
|
||||||
grace_until: Option<Instant>,
|
grace_until: Option<Instant>,
|
||||||
system_manager: Arc<SystemManager>,
|
system_manager: Arc<SystemManager>,
|
||||||
@@ -140,8 +140,9 @@ impl WaylandLock {
|
|||||||
log::info!("✅ Authentication successful - unlocking session");
|
log::info!("✅ Authentication successful - unlocking session");
|
||||||
if let Some(session_lock) = &self.session_lock {
|
if let Some(session_lock) = &self.session_lock {
|
||||||
session_lock.unlock();
|
session_lock.unlock();
|
||||||
self.unlocking = true;
|
let _ = self.conn.flush();
|
||||||
log::debug!("Unlock requested - waiting for compositor finished event");
|
self.exit = true;
|
||||||
|
log::debug!("Unlock requested - exiting");
|
||||||
} else {
|
} else {
|
||||||
log::error!("No session_lock available to unlock!");
|
log::error!("No session_lock available to unlock!");
|
||||||
self.exit = true;
|
self.exit = true;
|
||||||
@@ -617,6 +618,7 @@ fn main() -> Result<(), Box<dyn Error>> {
|
|||||||
let pool = SlotPool::new(1, &shm_state)?;
|
let pool = SlotPool::new(1, &shm_state)?;
|
||||||
|
|
||||||
let mut state = WaylandLock {
|
let mut state = WaylandLock {
|
||||||
|
conn: conn.clone(),
|
||||||
loop_handle: event_loop.handle(),
|
loop_handle: event_loop.handle(),
|
||||||
lock_manager: lock_manager.clone(),
|
lock_manager: lock_manager.clone(),
|
||||||
config: config.clone(),
|
config: config.clone(),
|
||||||
@@ -636,7 +638,6 @@ fn main() -> Result<(), Box<dyn Error>> {
|
|||||||
captured_backgrounds: Vec::new(),
|
captured_backgrounds: Vec::new(),
|
||||||
pending_screenshots: 0,
|
pending_screenshots: 0,
|
||||||
exit: false,
|
exit: false,
|
||||||
unlocking: false,
|
|
||||||
screenshot_manager: ScreenshotManager::new(&globals, &qh).ok(),
|
screenshot_manager: ScreenshotManager::new(&globals, &qh).ok(),
|
||||||
grace_until: None,
|
grace_until: None,
|
||||||
system_manager: system_manager.clone(),
|
system_manager: system_manager.clone(),
|
||||||
@@ -727,9 +728,6 @@ fn main() -> Result<(), Box<dyn Error>> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if state.unlocking {
|
|
||||||
return calloop::timer::TimeoutAction::ToDuration(Duration::from_millis(100));
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut status = state.system_manager.get_status();
|
let mut status = state.system_manager.get_status();
|
||||||
status.keyboard_layout = Some(state.current_layout.to_string());
|
status.keyboard_layout = Some(state.current_layout.to_string());
|
||||||
|
|||||||
Reference in New Issue
Block a user