From b25f98d583871173f5586c09e78ddcaa7caf6486 Mon Sep 17 00:00:00 2001 From: Kirill Primak Date: Wed, 8 Jan 2025 12:16:24 +0300 Subject: [PATCH] pointer-constraints: use wlr_surface_synced.commit hook This fixes a problem where an outdated surface input region was used to compute the effective confinement region. Additionally, this commit fixes a bug in pointer_constraint_create() which caused the initial region to not be applied immediately. This is a breaking change: set_region is now emitted before the role commit hook is called, and it's not emitted if the region hasn't actually changed. --- .../wlr/types/wlr_pointer_constraints_v1.h | 1 - types/wlr_pointer_constraints_v1.c | 67 ++++++++++--------- 2 files changed, 34 insertions(+), 34 deletions(-) diff --git a/include/wlr/types/wlr_pointer_constraints_v1.h b/include/wlr/types/wlr_pointer_constraints_v1.h index f97413e22..bccb23090 100644 --- a/include/wlr/types/wlr_pointer_constraints_v1.h +++ b/include/wlr/types/wlr_pointer_constraints_v1.h @@ -64,7 +64,6 @@ struct wlr_pointer_constraint_v1 { void *data; struct { - struct wl_listener surface_commit; struct wl_listener surface_destroy; struct wl_listener seat_destroy; diff --git a/types/wlr_pointer_constraints_v1.c b/types/wlr_pointer_constraints_v1.c index 7bc62311b..42329da82 100644 --- a/types/wlr_pointer_constraints_v1.c +++ b/types/wlr_pointer_constraints_v1.c @@ -58,7 +58,6 @@ static void pointer_constraint_destroy(struct wlr_pointer_constraint_v1 *constra wl_resource_set_user_data(constraint->resource, NULL); wlr_surface_synced_finish(&constraint->synced); wl_list_remove(&constraint->link); - wl_list_remove(&constraint->surface_commit.link); wl_list_remove(&constraint->surface_destroy.link); wl_list_remove(&constraint->seat_destroy.link); pixman_region32_fini(&constraint->region); @@ -72,19 +71,6 @@ static void pointer_constraint_destroy_resource(struct wl_resource *resource) { pointer_constraint_destroy(constraint); } -static void pointer_constraint_set_region( - struct wlr_pointer_constraint_v1 *constraint, - struct wl_resource *region_resource) { - pixman_region32_clear(&constraint->pending.region); - - if (region_resource) { - const pixman_region32_t *region = wlr_region_from_resource(region_resource); - pixman_region32_copy(&constraint->pending.region, region); - } - - constraint->pending.committed |= WLR_POINTER_CONSTRAINT_V1_STATE_REGION; -} - static void pointer_constraint_handle_set_region(struct wl_client *client, struct wl_resource *resource, struct wl_resource *region_resource) { struct wlr_pointer_constraint_v1 *constraint = @@ -93,7 +79,13 @@ static void pointer_constraint_handle_set_region(struct wl_client *client, return; } - pointer_constraint_set_region(constraint, region_resource); + pixman_region32_clear(&constraint->pending.region); + if (region_resource) { + const pixman_region32_t *region = wlr_region_from_resource(region_resource); + pixman_region32_copy(&constraint->pending.region, region); + } + + constraint->pending.committed |= WLR_POINTER_CONSTRAINT_V1_STATE_REGION; } static void pointer_constraint_set_cursor_position_hint(struct wl_client *client, @@ -110,27 +102,27 @@ static void pointer_constraint_set_cursor_position_hint(struct wl_client *client constraint->pending.committed |= WLR_POINTER_CONSTRAINT_V1_STATE_CURSOR_HINT; } -static void pointer_constraint_commit( - struct wlr_pointer_constraint_v1 *constraint) { - pixman_region32_clear(&constraint->region); +// Returns true if the region has changed +static bool update_region(struct wlr_pointer_constraint_v1 *constraint) { + pixman_region32_t region; + pixman_region32_init(®ion); + if (pixman_region32_not_empty(&constraint->current.region)) { - pixman_region32_intersect(&constraint->region, + pixman_region32_intersect(®ion, &constraint->surface->input_region, &constraint->current.region); } else { - pixman_region32_copy(&constraint->region, - &constraint->surface->input_region); + pixman_region32_copy(®ion, &constraint->surface->input_region); } - if (constraint->current.committed & WLR_POINTER_CONSTRAINT_V1_STATE_REGION) { - wl_signal_emit_mutable(&constraint->events.set_region, NULL); + if (pixman_region32_equal(®ion, &constraint->region)) { + pixman_region32_fini(®ion); + return false; } -} -static void handle_surface_commit(struct wl_listener *listener, void *data) { - struct wlr_pointer_constraint_v1 *constraint = - wl_container_of(listener, constraint, surface_commit); + pixman_region32_fini(&constraint->region); + constraint->region = region; - pointer_constraint_commit(constraint); + return true; } static void handle_surface_destroy(struct wl_listener *listener, void *data) { @@ -182,11 +174,20 @@ static void surface_synced_move_state(void *_dst, void *_src) { src->committed = 0; } +static void surface_synced_commit(struct wlr_surface_synced *synced) { + struct wlr_pointer_constraint_v1 *constraint = wl_container_of(synced, constraint, synced); + + if (update_region(constraint)) { + wl_signal_emit_mutable(&constraint->events.set_region, NULL); + } +} + static const struct wlr_surface_synced_impl surface_synced_impl = { .state_size = sizeof(struct wlr_pointer_constraint_v1_state), .init_state = surface_synced_init_state, .finish_state = surface_synced_finish_state, .move_state = surface_synced_move_state, + .commit = surface_synced_commit, }; static void pointer_constraint_create(struct wl_client *client, @@ -264,11 +265,11 @@ static void pointer_constraint_create(struct wl_client *client, pixman_region32_init(&constraint->region); - pointer_constraint_set_region(constraint, region_resource); - pointer_constraint_commit(constraint); - - constraint->surface_commit.notify = handle_surface_commit; - wl_signal_add(&surface->events.commit, &constraint->surface_commit); + if (region_resource) { + pixman_region32_copy(&constraint->current.region, + wlr_region_from_resource(region_resource)); + update_region(constraint); + } constraint->surface_destroy.notify = handle_surface_destroy; wl_signal_add(&surface->events.destroy, &constraint->surface_destroy);