layer-shell: refactor configure/state flow

Same logic as xdg-toplevel.
This commit is contained in:
Kirill Primak 2021-09-18 11:32:23 +03:00 committed by Isaac Freund
parent 3c26244340
commit 59fa3637c3
2 changed files with 46 additions and 94 deletions

View file

@ -53,12 +53,14 @@ struct wlr_layer_surface_v1_state {
uint32_t desired_width, desired_height;
uint32_t actual_width, actual_height;
enum zwlr_layer_shell_v1_layer layer;
uint32_t configure_serial;
};
struct wlr_layer_surface_v1_configure {
struct wl_list link; // wlr_layer_surface_v1::configure_list
uint32_t serial;
struct wlr_layer_surface_v1_state state;
uint32_t width, height;
};
struct wlr_layer_surface_v1 {
@ -71,15 +73,9 @@ struct wlr_layer_surface_v1 {
char *namespace;
bool added, configured, mapped;
uint32_t configure_serial;
uint32_t configure_next_serial;
struct wl_list configure_list;
struct wlr_layer_surface_v1_configure *acked_configure;
struct wlr_layer_surface_v1_state client_pending;
struct wlr_layer_surface_v1_state server_pending;
struct wlr_layer_surface_v1_state current;
struct wlr_layer_surface_v1_state current, pending;
struct wl_listener surface_destroy;
@ -119,9 +115,9 @@ struct wlr_layer_shell_v1 *wlr_layer_shell_v1_create(struct wl_display *display)
/**
* Notifies the layer surface to configure itself with this width/height. The
* layer_surface will signal its map event when the surface is ready to assume
* this size.
* this size. Returns the associated configure serial.
*/
void wlr_layer_surface_v1_configure(struct wlr_layer_surface_v1 *surface,
uint32_t wlr_layer_surface_v1_configure(struct wlr_layer_surface_v1 *surface,
uint32_t width, uint32_t height);
/**

View file

@ -87,12 +87,13 @@ static void layer_surface_handle_ack_configure(struct wl_client *client,
layer_surface_configure_destroy(configure);
}
if (surface->acked_configure) {
layer_surface_configure_destroy(surface->acked_configure);
}
surface->acked_configure = configure;
wl_list_remove(&configure->link);
wl_list_init(&configure->link);
surface->pending.configure_serial = configure->serial;
surface->pending.actual_width = configure->width;
surface->pending.actual_height = configure->height;
surface->configured = true;
layer_surface_configure_destroy(configure);
}
static void layer_surface_handle_set_size(struct wl_client *client,
@ -102,8 +103,8 @@ static void layer_surface_handle_set_size(struct wl_client *client,
if (!surface) {
return;
}
surface->client_pending.desired_width = width;
surface->client_pending.desired_height = height;
surface->pending.desired_width = width;
surface->pending.desired_height = height;
}
static void layer_surface_handle_set_anchor(struct wl_client *client,
@ -123,7 +124,7 @@ static void layer_surface_handle_set_anchor(struct wl_client *client,
if (!surface) {
return;
}
surface->client_pending.anchor = anchor;
surface->pending.anchor = anchor;
}
static void layer_surface_handle_set_exclusive_zone(struct wl_client *client,
@ -133,7 +134,7 @@ static void layer_surface_handle_set_exclusive_zone(struct wl_client *client,
if (!surface) {
return;
}
surface->client_pending.exclusive_zone = zone;
surface->pending.exclusive_zone = zone;
}
static void layer_surface_handle_set_margin(
@ -144,10 +145,10 @@ static void layer_surface_handle_set_margin(
if (!surface) {
return;
}
surface->client_pending.margin.top = top;
surface->client_pending.margin.right = right;
surface->client_pending.margin.bottom = bottom;
surface->client_pending.margin.left = left;
surface->pending.margin.top = top;
surface->pending.margin.right = right;
surface->pending.margin.bottom = bottom;
surface->pending.margin.left = left;
}
static void layer_surface_handle_set_keyboard_interactivity(
@ -160,14 +161,14 @@ static void layer_surface_handle_set_keyboard_interactivity(
}
if (wl_resource_get_version(resource) < ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_ON_DEMAND_SINCE_VERSION) {
surface->client_pending.keyboard_interactive = !!interactive;
surface->pending.keyboard_interactive = !!interactive;
} else {
if (interactive > ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_ON_DEMAND) {
wl_resource_post_error(resource,
ZWLR_LAYER_SURFACE_V1_ERROR_INVALID_KEYBOARD_INTERACTIVITY,
"wrong keyboard interactivity value: %" PRIu32, interactive);
} else {
surface->client_pending.keyboard_interactive = interactive;
surface->pending.keyboard_interactive = interactive;
}
}
}
@ -203,7 +204,7 @@ static void layer_surface_set_layer(struct wl_client *client,
"Invalid layer %" PRIu32, layer);
return;
}
surface->client_pending.layer = layer;
surface->pending.layer = layer;
}
static const struct zwlr_layer_surface_v1_interface layer_surface_implementation = {
@ -233,8 +234,6 @@ static void layer_surface_unmap(struct wlr_layer_surface_v1 *surface) {
}
surface->configured = surface->mapped = false;
surface->configure_serial = 0;
surface->configure_next_serial = 0;
}
static void layer_surface_destroy(struct wlr_layer_surface_v1 *surface) {
@ -257,49 +256,24 @@ static void layer_surface_resource_destroy(struct wl_resource *resource) {
}
}
static bool layer_surface_state_changed(struct wlr_layer_surface_v1 *surface) {
struct wlr_layer_surface_v1_state *state;
if (wl_list_empty(&surface->configure_list)) {
if (surface->acked_configure) {
state = &surface->acked_configure->state;
} else if (!surface->configured) {
return true;
} else {
state = &surface->current;
}
} else {
struct wlr_layer_surface_v1_configure *configure =
wl_container_of(surface->configure_list.prev, configure, link);
state = &configure->state;
}
bool changed = state->actual_width != surface->server_pending.actual_width
|| state->actual_height != surface->server_pending.actual_height;
return changed;
}
void wlr_layer_surface_v1_configure(struct wlr_layer_surface_v1 *surface,
uint32_t wlr_layer_surface_v1_configure(struct wlr_layer_surface_v1 *surface,
uint32_t width, uint32_t height) {
surface->server_pending.actual_width = width;
surface->server_pending.actual_height = height;
if (layer_surface_state_changed(surface)) {
struct wl_display *display =
wl_client_get_display(wl_resource_get_client(surface->resource));
struct wlr_layer_surface_v1_configure *configure =
calloc(1, sizeof(struct wlr_layer_surface_v1_configure));
if (configure == NULL) {
wl_client_post_no_memory(wl_resource_get_client(surface->resource));
return;
return surface->pending.configure_serial;
}
surface->configure_next_serial = wl_display_next_serial(display);
wl_list_insert(surface->configure_list.prev, &configure->link);
configure->state.actual_width = width;
configure->state.actual_height = height;
configure->serial = surface->configure_next_serial;
configure->width = width;
configure->height = height;
configure->serial = wl_display_next_serial(display);
zwlr_layer_surface_v1_send_configure(surface->resource,
configure->serial, configure->state.actual_width,
configure->state.actual_height);
}
configure->serial, configure->width,
configure->height);
return configure->serial;
}
void wlr_layer_surface_v1_destroy(struct wlr_layer_surface_v1 *surface) {
@ -316,8 +290,8 @@ static void layer_surface_role_commit(struct wlr_surface *wlr_surface) {
const uint32_t horiz = ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT |
ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT;
if (surface->client_pending.desired_width == 0 &&
(surface->client_pending.anchor & horiz) != horiz) {
if (surface->pending.desired_width == 0 &&
(surface->pending.anchor & horiz) != horiz) {
wl_resource_post_error(surface->resource,
ZWLR_LAYER_SURFACE_V1_ERROR_INVALID_SIZE,
"width 0 requested without setting left and right anchors");
@ -326,24 +300,15 @@ static void layer_surface_role_commit(struct wlr_surface *wlr_surface) {
const uint32_t vert = ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP |
ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM;
if (surface->client_pending.desired_height == 0 &&
(surface->client_pending.anchor & vert) != vert) {
if (surface->pending.desired_height == 0 &&
(surface->pending.anchor & vert) != vert) {
wl_resource_post_error(surface->resource,
ZWLR_LAYER_SURFACE_V1_ERROR_INVALID_SIZE,
"height 0 requested without setting top and bottom anchors");
return;
}
if (surface->acked_configure) {
struct wlr_layer_surface_v1_configure *configure =
surface->acked_configure;
surface->configured = true;
surface->configure_serial = configure->serial;
surface->current.actual_width = configure->state.actual_width;
surface->current.actual_height = configure->state.actual_height;
layer_surface_configure_destroy(configure);
surface->acked_configure = NULL;
}
surface->current = surface->pending;
if (wlr_surface_has_buffer(surface->surface) && !surface->configured) {
wl_resource_post_error(surface->resource,
@ -352,15 +317,6 @@ static void layer_surface_role_commit(struct wlr_surface *wlr_surface) {
return;
}
surface->current.anchor = surface->client_pending.anchor;
surface->current.exclusive_zone = surface->client_pending.exclusive_zone;
surface->current.margin = surface->client_pending.margin;
surface->current.keyboard_interactive =
surface->client_pending.keyboard_interactive;
surface->current.desired_width = surface->client_pending.desired_width;
surface->current.desired_height = surface->client_pending.desired_height;
surface->current.layer = surface->client_pending.layer;
if (!surface->added) {
surface->added = true;
assert(!surface->configured);
@ -422,7 +378,7 @@ static void layer_shell_handle_get_layer_surface(struct wl_client *wl_client,
if (output_resource) {
surface->output = wlr_output_from_resource(output_resource);
}
surface->current.layer = surface->client_pending.layer = layer;
surface->current.layer = surface->pending.layer = layer;
if (layer > ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY) {
free(surface);
wl_resource_post_error(client_resource,