pointer-constraints: sync with surface state flow

This commit is contained in:
Kirill Primak 2022-02-04 16:25:01 +03:00
parent d663fb4f63
commit f1fed4d64c
2 changed files with 75 additions and 27 deletions

View file

@ -12,6 +12,7 @@
#include <stdint.h> #include <stdint.h>
#include <wayland-server-core.h> #include <wayland-server-core.h>
#include <pixman.h> #include <pixman.h>
#include <wlr/types/wlr_compositor.h>
#include <wlr/types/wlr_seat.h> #include <wlr/types/wlr_seat.h>
#include "pointer-constraints-unstable-v1-protocol.h" #include "pointer-constraints-unstable-v1-protocol.h"
@ -35,6 +36,8 @@ struct wlr_pointer_constraint_v1_state {
struct { struct {
double x, y; double x, y;
} cursor_hint; } cursor_hint;
struct wlr_surface_synced_state synced_state;
}; };
struct wlr_pointer_constraint_v1 { struct wlr_pointer_constraint_v1 {
@ -50,11 +53,12 @@ struct wlr_pointer_constraint_v1 {
struct wlr_pointer_constraint_v1_state current, pending; struct wlr_pointer_constraint_v1_state current, pending;
struct wl_listener surface_commit; struct wl_listener surface_commit;
struct wl_listener surface_destroy;
struct wl_listener seat_destroy; struct wl_listener seat_destroy;
struct wl_list link; // wlr_pointer_constraints_v1::constraints struct wl_list link; // wlr_pointer_constraints_v1::constraints
struct wlr_surface_synced synced;
struct { struct {
/** /**
* Called when a pointer constraint's region is updated, * Called when a pointer constraint's region is updated,

View file

@ -49,10 +49,10 @@ static void pointer_constraint_destroy(struct wlr_pointer_constraint_v1 *constra
wlr_signal_emit_safe(&constraint->events.destroy, constraint); wlr_signal_emit_safe(&constraint->events.destroy, constraint);
wlr_surface_synced_finish(&constraint->synced);
wl_resource_set_user_data(constraint->resource, NULL); wl_resource_set_user_data(constraint->resource, NULL);
wl_list_remove(&constraint->link); wl_list_remove(&constraint->link);
wl_list_remove(&constraint->surface_commit.link); wl_list_remove(&constraint->surface_commit.link);
wl_list_remove(&constraint->surface_destroy.link);
wl_list_remove(&constraint->seat_destroy.link); wl_list_remove(&constraint->seat_destroy.link);
pixman_region32_fini(&constraint->current.region); pixman_region32_fini(&constraint->current.region);
pixman_region32_fini(&constraint->pending.region); pixman_region32_fini(&constraint->pending.region);
@ -106,20 +106,6 @@ static void pointer_constraint_set_cursor_position_hint(struct wl_client *client
static void pointer_constraint_commit( static void pointer_constraint_commit(
struct wlr_pointer_constraint_v1 *constraint) { struct wlr_pointer_constraint_v1 *constraint) {
if (constraint->pending.committed &
WLR_POINTER_CONSTRAINT_V1_STATE_REGION) {
pixman_region32_copy(&constraint->current.region,
&constraint->pending.region);
}
if (constraint->pending.committed &
WLR_POINTER_CONSTRAINT_V1_STATE_CURSOR_HINT) {
constraint->current.cursor_hint = constraint->pending.cursor_hint;
}
constraint->current.committed |= constraint->pending.committed;
bool updated_region = !!constraint->pending.committed;
constraint->pending.committed = 0;
pixman_region32_clear(&constraint->region); pixman_region32_clear(&constraint->region);
if (pixman_region32_not_empty(&constraint->current.region)) { if (pixman_region32_not_empty(&constraint->current.region)) {
pixman_region32_intersect(&constraint->region, pixman_region32_intersect(&constraint->region,
@ -129,7 +115,7 @@ static void pointer_constraint_commit(
&constraint->surface->input_region); &constraint->surface->input_region);
} }
if (updated_region) { if (constraint->current.committed != 0) {
wlr_signal_emit_safe(&constraint->events.set_region, NULL); wlr_signal_emit_safe(&constraint->events.set_region, NULL);
} }
} }
@ -141,13 +127,6 @@ static void handle_surface_commit(struct wl_listener *listener, void *data) {
pointer_constraint_commit(constraint); pointer_constraint_commit(constraint);
} }
static void handle_surface_destroy(struct wl_listener *listener, void *data) {
struct wlr_pointer_constraint_v1 *constraint =
wl_container_of(listener, constraint, surface_destroy);
pointer_constraint_destroy(constraint);
}
static void handle_seat_destroy(struct wl_listener *listener, void *data) { static void handle_seat_destroy(struct wl_listener *listener, void *data) {
struct wlr_pointer_constraint_v1 *constraint = struct wlr_pointer_constraint_v1 *constraint =
wl_container_of(listener, constraint, seat_destroy); wl_container_of(listener, constraint, seat_destroy);
@ -166,6 +145,64 @@ static const struct zwp_locked_pointer_v1_interface locked_pointer_impl = {
.set_cursor_position_hint = pointer_constraint_set_cursor_position_hint, .set_cursor_position_hint = pointer_constraint_set_cursor_position_hint,
}; };
static void pointer_constraint_synced_destroy(struct wlr_surface_synced *synced) {
struct wlr_pointer_constraint_v1 *constraint =
wl_container_of(synced, constraint, synced);
pointer_constraint_destroy(constraint);
}
static void pointer_constraint_synced_squash_state(
struct wlr_surface_synced_state *synced_dst,
struct wlr_surface_synced_state *synced_src) {
struct wlr_pointer_constraint_v1_state *dst =
wl_container_of(synced_dst, dst, synced_state);
struct wlr_pointer_constraint_v1_state *src =
wl_container_of(synced_src, src, synced_state);
if (src->committed & WLR_POINTER_CONSTRAINT_V1_STATE_REGION) {
pixman_region32_copy(&dst->region, &src->region);
}
if (src->committed & WLR_POINTER_CONSTRAINT_V1_STATE_CURSOR_HINT) {
dst->cursor_hint = src->cursor_hint;
}
dst->committed |= src->committed;
src->committed = 0;
}
static struct wlr_surface_synced_state *pointer_constraint_synced_create_state(void) {
struct wlr_pointer_constraint_v1_state *state = calloc(1, sizeof(*state));
if (!state) {
return NULL;
}
pixman_region32_init(&state->region);
return &state->synced_state;
}
static void pointer_constraint_synced_destroy_state(
struct wlr_surface_synced_state *synced_state) {
struct wlr_pointer_constraint_v1_state *state =
wl_container_of(synced_state, state, synced_state);
pixman_region32_fini(&state->region);
free(state);
}
static void pointer_constraint_synced_precommit(struct wlr_surface_synced *synced,
struct wlr_surface_synced_state *synced_state) {
struct wlr_pointer_constraint_v1 *constraint =
wl_container_of(synced, constraint, synced);
constraint->current.committed = 0;
}
static const struct wlr_surface_synced_interface pointer_constraint_synced_impl = {
.name = "wlr_pointer_constraint_v1",
.destroy = pointer_constraint_synced_destroy,
.squash_state = pointer_constraint_synced_squash_state,
.create_state = pointer_constraint_synced_create_state,
.destroy_state = pointer_constraint_synced_destroy_state,
.precommit = pointer_constraint_synced_precommit,
};
static void pointer_constraint_create(struct wl_client *client, static void pointer_constraint_create(struct wl_client *client,
struct wl_resource *pointer_constraints_resource, uint32_t id, struct wl_resource *pointer_constraints_resource, uint32_t id,
struct wl_resource *surface_resource, struct wl_resource *surface_resource,
@ -208,6 +245,16 @@ static void pointer_constraint_create(struct wl_client *client,
return; return;
} }
if (!wlr_surface_synced_init(&constraint->synced,
&pointer_constraint_synced_impl, surface,
&constraint->current.synced_state,
&constraint->pending.synced_state)) {
free(constraint);
wl_resource_destroy(resource);
wl_client_post_no_memory(client);
return;
}
constraint->resource = resource; constraint->resource = resource;
constraint->surface = surface; constraint->surface = surface;
constraint->seat = seat; constraint->seat = seat;
@ -229,9 +276,6 @@ static void pointer_constraint_create(struct wl_client *client,
constraint->surface_commit.notify = handle_surface_commit; constraint->surface_commit.notify = handle_surface_commit;
wl_signal_add(&surface->events.commit, &constraint->surface_commit); wl_signal_add(&surface->events.commit, &constraint->surface_commit);
constraint->surface_destroy.notify = handle_surface_destroy;
wl_signal_add(&surface->events.destroy, &constraint->surface_destroy);
constraint->seat_destroy.notify = handle_seat_destroy; constraint->seat_destroy.notify = handle_seat_destroy;
wl_signal_add(&seat->events.destroy, &constraint->seat_destroy); wl_signal_add(&seat->events.destroy, &constraint->seat_destroy);