diff --git a/src/wayland/session_lock/lock.rs b/src/wayland/session_lock/lock.rs index 9f4492a7e00b..9a561090c0ae 100644 --- a/src/wayland/session_lock/lock.rs +++ b/src/wayland/session_lock/lock.rs @@ -75,8 +75,13 @@ where return; } + // Add pre-commit hook for updating surface state (before creating user data). + let commit_hook_id = + compositor::add_pre_commit_hook::(&surface, LockSurface::pre_commit_hook); + let data = ExtLockSurfaceUserData { surface: surface.downgrade(), + commit_hook_id, }; let lock_surface = data_init.init(id, data); @@ -97,9 +102,6 @@ where } }); - // Add pre-commit hook for updating surface state. - compositor::add_pre_commit_hook::(&surface, LockSurface::pre_commit_hook); - // Call compositor handler. let lock_surface = LockSurface::new(surface, lock_surface); state.new_surface(lock_surface.clone(), output); @@ -111,6 +113,7 @@ where // Ensure session is locked. if !data.lock_status.load(Ordering::Relaxed) { lock.post_error(Error::InvalidUnlock, "Session is not locked."); + return; } state.lock_state().locked_outputs.clear(); @@ -120,6 +123,7 @@ where // Ensure session is not locked. if data.lock_status.load(Ordering::Relaxed) { lock.post_error(Error::InvalidDestroy, "Cannot destroy session lock while locked."); + return; } } _ => unreachable!(), diff --git a/src/wayland/session_lock/surface.rs b/src/wayland/session_lock/surface.rs index 56e507cfb6cd..04d01cb1e426 100644 --- a/src/wayland/session_lock/surface.rs +++ b/src/wayland/session_lock/surface.rs @@ -3,7 +3,7 @@ use std::sync::Mutex; use crate::backend::renderer::buffer_dimensions; -use crate::utils::{IsAlive, Logical, SERIAL_COUNTER, Serial, Size}; +use crate::utils::{IsAlive, Logical, SERIAL_COUNTER, Serial, Size, hook::HookId}; use crate::wayland::compositor::{self, BufferAssignment, Cacheable, SurfaceAttributes}; use crate::wayland::viewporter::{ViewportCachedState, ViewporterSurfaceState}; use _session_lock::ext_session_lock_surface_v1::{Error, ExtSessionLockSurfaceV1, Request}; @@ -21,6 +21,7 @@ pub struct ExtLockSurfaceUserData { // `ExtSessionLockSurfaceV1`. So this reference needs to be weak to avoid a // cycle. pub(crate) surface: Weak, + pub(crate) commit_hook_id: HookId, } impl Dispatch for SessionLockManagerState @@ -71,6 +72,9 @@ where data: &ExtLockSurfaceUserData, ) { if let Ok(surface) = data.surface.upgrade() { + // Remove the pre-commit hook so orphaned commits don't trigger post_error + compositor::remove_pre_commit_hook(&surface, &data.commit_hook_id); + compositor::with_states(&surface, |states| { let mut attributes = states .data_map