From 76d739188d80e1390245f76cb98e4a17f59456fb Mon Sep 17 00:00:00 2001 From: ookami <110040049+OkamiW@users.noreply.github.com> Date: Wed, 30 Jul 2025 14:31:26 +0800 Subject: [PATCH 1/2] Fix cursor events on screen lock/unlock Inspired by https://github.com/swaywm/sway/pull/8343 cursor_rebase_all calls node_at_coords, and node_at_coords only returns the lock surface after the surface has been committed(not mapped). Also add the missing cursor_rebase_all in handle_unlock. --- sway/lock.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/sway/lock.c b/sway/lock.c index c8975c74..573ee5d4 100644 --- a/sway/lock.c +++ b/sway/lock.c @@ -25,7 +25,8 @@ struct sway_session_lock_output { // invalid if surface is NULL struct wl_listener surface_destroy; - struct wl_listener surface_map; + struct wl_listener surface_commit; + bool surface_committed; }; static void focus_surface(struct sway_session_lock *lock, @@ -59,12 +60,16 @@ static void refocus_output(struct sway_session_lock_output *output) { } } -static void handle_surface_map(struct wl_listener *listener, void *data) { - struct sway_session_lock_output *surf = wl_container_of(listener, surf, surface_map); +static void handle_surface_commit(struct wl_listener *listener, void *data) { + struct sway_session_lock_output *surf = wl_container_of(listener, surf, surface_commit); + if (surf->surface_committed) { + return; + } if (surf->lock->focused == NULL) { focus_surface(surf->lock, surf->surface->surface); } cursor_rebase_all(); + surf->surface_committed = true; } static void handle_surface_destroy(struct wl_listener *listener, void *data) { @@ -75,7 +80,7 @@ static void handle_surface_destroy(struct wl_listener *listener, void *data) { sway_assert(output->surface, "Trying to destroy a surface that the lock doesn't think exists"); output->surface = NULL; wl_list_remove(&output->surface_destroy.link); - wl_list_remove(&output->surface_map.link); + wl_list_remove(&output->surface_commit.link); } static void lock_output_reconfigure(struct sway_session_lock_output *output) { @@ -123,8 +128,8 @@ static void handle_new_surface(struct wl_listener *listener, void *data) { lock_output->surface_destroy.notify = handle_surface_destroy; wl_signal_add(&lock_surface->events.destroy, &lock_output->surface_destroy); - lock_output->surface_map.notify = handle_surface_map; - wl_signal_add(&lock_surface->surface->events.map, &lock_output->surface_map); + lock_output->surface_commit.notify = handle_surface_commit; + wl_signal_add(&lock_surface->surface->events.commit, &lock_output->surface_commit); lock_output_reconfigure(lock_output); } @@ -133,7 +138,7 @@ static void sway_session_lock_output_destroy(struct sway_session_lock_output *ou if (output->surface) { refocus_output(output); wl_list_remove(&output->surface_destroy.link); - wl_list_remove(&output->surface_map.link); + wl_list_remove(&output->surface_commit.link); } wl_list_remove(&output->destroy.link); @@ -237,6 +242,8 @@ static void handle_unlock(struct wl_listener *listener, void *data) { // Views are now visible, so check if we need to activate inhibition again. sway_idle_inhibit_v1_check_active(); + + cursor_rebase_all(); } static void handle_abandon(struct wl_listener *listener, void *data) { From 9d9566d187afe74e32c15eecc9cf02ece2af1103 Mon Sep 17 00:00:00 2001 From: ookami <110040049+OkamiW@users.noreply.github.com> Date: Wed, 30 Jul 2025 16:11:41 +0800 Subject: [PATCH 2/2] Fix sway_session_lock_has_surface Before this commit, if the cursor is at screen center, and the lock is swaylock, the cursor would be at swaylock's subsurface(the indicator). Since it's not the lock surface, `handle_rebase` would refuse to rebase the cursor to there. Thereby the cursor enter event won't be sent to swaylock. This commit fix the issue. --- sway/lock.c | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/sway/lock.c b/sway/lock.c index 573ee5d4..fe2f8636 100644 --- a/sway/lock.c +++ b/sway/lock.c @@ -339,11 +339,31 @@ void sway_session_lock_add_output(struct sway_session_lock *lock, } } +struct is_lock_surface_data { + struct wlr_surface *surface; + bool is_lock_surface; +}; + +static void is_lock_surface(struct wlr_surface *surface, int sx, int sy, void *data) { + struct is_lock_surface_data *is_lock_surface_data = data; + if (is_lock_surface_data->surface == surface) { + is_lock_surface_data->is_lock_surface = true; + } +} + bool sway_session_lock_has_surface(struct sway_session_lock *lock, struct wlr_surface *surface) { struct sway_session_lock_output *lock_output; wl_list_for_each(lock_output, &lock->outputs, link) { - if (lock_output->surface && lock_output->surface->surface == surface) { + if (!lock_output->surface) { + continue; + } + struct is_lock_surface_data data = { + .surface = surface, + .is_lock_surface = false, + }; + wlr_surface_for_each_surface(lock_output->surface->surface, is_lock_surface, &data); + if (data.is_lock_surface) { return true; } }