diff --git a/include/wlr/types/wlr_pointer_constraints_v1.h b/include/wlr/types/wlr_pointer_constraints_v1.h index 4c541d879..a1fa88633 100644 --- a/include/wlr/types/wlr_pointer_constraints_v1.h +++ b/include/wlr/types/wlr_pointer_constraints_v1.h @@ -70,6 +70,8 @@ struct wlr_pointer_constraint_v1 { struct wl_listener seat_destroy; struct wlr_surface_synced synced; + + bool destroying; } WLR_PRIVATE; }; diff --git a/types/wlr_pointer_constraints_v1.c b/types/wlr_pointer_constraints_v1.c index 94cb48f24..7bc62311b 100644 --- a/types/wlr_pointer_constraints_v1.c +++ b/types/wlr_pointer_constraints_v1.c @@ -39,10 +39,15 @@ static void resource_destroy(struct wl_client *client, } static void pointer_constraint_destroy(struct wlr_pointer_constraint_v1 *constraint) { - if (constraint == NULL) { + if (constraint == NULL || constraint->destroying) { return; } + // Calling wlr_pointer_constraint_v1_send_deactivated() for a oneshot constraint + // that is being destroyed results in another pointer_constraint_destroy() call. + // Avoid finalizing the state twice by setting a flag. + constraint->destroying = true; + wlr_log(WLR_DEBUG, "destroying constraint %p", constraint); wl_signal_emit_mutable(&constraint->events.destroy, constraint);