xdg-surface: add pending state

struct wlr_xdg_surface_state is introduced to hold the geometry
and configure serial to be applied on next wl_surface.commit.

This commit fixes our handling for ack_configure: instead of making
the request mutate our current state, it mutates the pending state
only.

Co-authored-by: Simon Ser <contact@emersion.fr>
This commit is contained in:
Kirill Primak 2021-07-29 23:03:14 +03:00
parent 3d0848daae
commit db4afc2408
2 changed files with 22 additions and 18 deletions

View file

@ -161,6 +161,11 @@ struct wlr_xdg_surface_configure {
struct wlr_xdg_toplevel_configure *toplevel_configure;
};
struct wlr_xdg_surface_state {
uint32_t configure_serial;
struct wlr_box geometry;
};
/**
* An xdg-surface is a user interface element requiring management by the
* compositor. An xdg-surface alone isn't useful, a role should be assigned to
@ -191,10 +196,10 @@ struct wlr_xdg_surface {
uint32_t configure_next_serial;
struct wl_list configure_list;
bool has_next_geometry;
struct wlr_box next_geometry;
struct wlr_box geometry;
struct wlr_xdg_surface_state pending;
struct wl_listener surface_destroy;
struct wl_listener surface_commit;

View file

@ -88,12 +88,10 @@ void unmap_xdg_surface(struct wlr_xdg_surface *surface) {
}
surface->configure_next_serial = 0;
surface->has_next_geometry = false;
memset(&surface->geometry, 0, sizeof(struct wlr_box));
memset(&surface->next_geometry, 0, sizeof(struct wlr_box));
memset(&surface->pending, 0, sizeof(struct wlr_xdg_surface_state));
}
static void xdg_surface_handle_ack_configure(struct wl_client *client,
struct wl_resource *resource, uint32_t serial) {
struct wlr_xdg_surface *surface = wlr_xdg_surface_from_resource(resource);
@ -144,7 +142,7 @@ static void xdg_surface_handle_ack_configure(struct wl_client *client,
}
surface->configured = true;
surface->configure_serial = serial;
surface->pending.configure_serial = serial;
wlr_signal_emit_safe(&surface->events.ack_configure, configure);
xdg_surface_configure_destroy(configure);
@ -252,11 +250,10 @@ static void xdg_surface_handle_set_window_geometry(struct wl_client *client,
return;
}
surface->has_next_geometry = true;
surface->next_geometry.height = height;
surface->next_geometry.width = width;
surface->next_geometry.x = x;
surface->next_geometry.y = y;
surface->pending.geometry.x = x;
surface->pending.geometry.y = y;
surface->pending.geometry.width = width;
surface->pending.geometry.height = height;
}
static void xdg_surface_handle_destroy(struct wl_client *client,
@ -313,6 +310,14 @@ static void xdg_surface_handle_surface_commit(struct wl_listener *listener,
}
}
static void surface_commit_state(struct wlr_xdg_surface *surface,
struct wlr_xdg_surface_state *state) {
surface->configure_serial = state->configure_serial;
if (!wlr_box_empty(&state->geometry)) {
surface->geometry = state->geometry;
}
}
void handle_xdg_surface_commit(struct wlr_surface *wlr_surface) {
struct wlr_xdg_surface *surface =
wlr_xdg_surface_from_wlr_surface(wlr_surface);
@ -320,13 +325,7 @@ void handle_xdg_surface_commit(struct wlr_surface *wlr_surface) {
return;
}
if (surface->has_next_geometry) {
surface->has_next_geometry = false;
surface->geometry.x = surface->next_geometry.x;
surface->geometry.y = surface->next_geometry.y;
surface->geometry.width = surface->next_geometry.width;
surface->geometry.height = surface->next_geometry.height;
}
surface_commit_state(surface, &surface->pending);
switch (surface->role) {
case WLR_XDG_SURFACE_ROLE_NONE: