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 desired_width, desired_height;
uint32_t actual_width, actual_height; uint32_t actual_width, actual_height;
enum zwlr_layer_shell_v1_layer layer; enum zwlr_layer_shell_v1_layer layer;
uint32_t configure_serial;
}; };
struct wlr_layer_surface_v1_configure { struct wlr_layer_surface_v1_configure {
struct wl_list link; // wlr_layer_surface_v1::configure_list struct wl_list link; // wlr_layer_surface_v1::configure_list
uint32_t serial; uint32_t serial;
struct wlr_layer_surface_v1_state state;
uint32_t width, height;
}; };
struct wlr_layer_surface_v1 { struct wlr_layer_surface_v1 {
@ -71,15 +73,9 @@ struct wlr_layer_surface_v1 {
char *namespace; char *namespace;
bool added, configured, mapped; bool added, configured, mapped;
uint32_t configure_serial;
uint32_t configure_next_serial;
struct wl_list configure_list; struct wl_list configure_list;
struct wlr_layer_surface_v1_configure *acked_configure; struct wlr_layer_surface_v1_state current, pending;
struct wlr_layer_surface_v1_state client_pending;
struct wlr_layer_surface_v1_state server_pending;
struct wlr_layer_surface_v1_state current;
struct wl_listener surface_destroy; 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 * 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 * 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); 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); layer_surface_configure_destroy(configure);
} }
if (surface->acked_configure) { surface->pending.configure_serial = configure->serial;
layer_surface_configure_destroy(surface->acked_configure); surface->pending.actual_width = configure->width;
} surface->pending.actual_height = configure->height;
surface->acked_configure = configure;
wl_list_remove(&configure->link); surface->configured = true;
wl_list_init(&configure->link);
layer_surface_configure_destroy(configure);
} }
static void layer_surface_handle_set_size(struct wl_client *client, 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) { if (!surface) {
return; return;
} }
surface->client_pending.desired_width = width; surface->pending.desired_width = width;
surface->client_pending.desired_height = height; surface->pending.desired_height = height;
} }
static void layer_surface_handle_set_anchor(struct wl_client *client, 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) { if (!surface) {
return; return;
} }
surface->client_pending.anchor = anchor; surface->pending.anchor = anchor;
} }
static void layer_surface_handle_set_exclusive_zone(struct wl_client *client, 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) { if (!surface) {
return; return;
} }
surface->client_pending.exclusive_zone = zone; surface->pending.exclusive_zone = zone;
} }
static void layer_surface_handle_set_margin( static void layer_surface_handle_set_margin(
@ -144,10 +145,10 @@ static void layer_surface_handle_set_margin(
if (!surface) { if (!surface) {
return; return;
} }
surface->client_pending.margin.top = top; surface->pending.margin.top = top;
surface->client_pending.margin.right = right; surface->pending.margin.right = right;
surface->client_pending.margin.bottom = bottom; surface->pending.margin.bottom = bottom;
surface->client_pending.margin.left = left; surface->pending.margin.left = left;
} }
static void layer_surface_handle_set_keyboard_interactivity( 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) { 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 { } else {
if (interactive > ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_ON_DEMAND) { if (interactive > ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_ON_DEMAND) {
wl_resource_post_error(resource, wl_resource_post_error(resource,
ZWLR_LAYER_SURFACE_V1_ERROR_INVALID_KEYBOARD_INTERACTIVITY, ZWLR_LAYER_SURFACE_V1_ERROR_INVALID_KEYBOARD_INTERACTIVITY,
"wrong keyboard interactivity value: %" PRIu32, interactive); "wrong keyboard interactivity value: %" PRIu32, interactive);
} else { } 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); "Invalid layer %" PRIu32, layer);
return; return;
} }
surface->client_pending.layer = layer; surface->pending.layer = layer;
} }
static const struct zwlr_layer_surface_v1_interface layer_surface_implementation = { 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->configured = surface->mapped = false;
surface->configure_serial = 0;
surface->configure_next_serial = 0;
} }
static void layer_surface_destroy(struct wlr_layer_surface_v1 *surface) { 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) { uint32_t wlr_layer_surface_v1_configure(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 width, uint32_t height) { uint32_t width, uint32_t height) {
surface->server_pending.actual_width = width; struct wl_display *display =
surface->server_pending.actual_height = height; wl_client_get_display(wl_resource_get_client(surface->resource));
if (layer_surface_state_changed(surface)) { struct wlr_layer_surface_v1_configure *configure =
struct wl_display *display = calloc(1, sizeof(struct wlr_layer_surface_v1_configure));
wl_client_get_display(wl_resource_get_client(surface->resource)); if (configure == NULL) {
struct wlr_layer_surface_v1_configure *configure = wl_client_post_no_memory(wl_resource_get_client(surface->resource));
calloc(1, sizeof(struct wlr_layer_surface_v1_configure)); return surface->pending.configure_serial;
if (configure == NULL) {
wl_client_post_no_memory(wl_resource_get_client(surface->resource));
return;
}
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;
zwlr_layer_surface_v1_send_configure(surface->resource,
configure->serial, configure->state.actual_width,
configure->state.actual_height);
} }
wl_list_insert(surface->configure_list.prev, &configure->link);
configure->width = width;
configure->height = height;
configure->serial = wl_display_next_serial(display);
zwlr_layer_surface_v1_send_configure(surface->resource,
configure->serial, configure->width,
configure->height);
return configure->serial;
} }
void wlr_layer_surface_v1_destroy(struct wlr_layer_surface_v1 *surface) { 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 | const uint32_t horiz = ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT |
ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT; ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT;
if (surface->client_pending.desired_width == 0 && if (surface->pending.desired_width == 0 &&
(surface->client_pending.anchor & horiz) != horiz) { (surface->pending.anchor & horiz) != horiz) {
wl_resource_post_error(surface->resource, wl_resource_post_error(surface->resource,
ZWLR_LAYER_SURFACE_V1_ERROR_INVALID_SIZE, ZWLR_LAYER_SURFACE_V1_ERROR_INVALID_SIZE,
"width 0 requested without setting left and right anchors"); "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 | const uint32_t vert = ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP |
ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM; ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM;
if (surface->client_pending.desired_height == 0 && if (surface->pending.desired_height == 0 &&
(surface->client_pending.anchor & vert) != vert) { (surface->pending.anchor & vert) != vert) {
wl_resource_post_error(surface->resource, wl_resource_post_error(surface->resource,
ZWLR_LAYER_SURFACE_V1_ERROR_INVALID_SIZE, ZWLR_LAYER_SURFACE_V1_ERROR_INVALID_SIZE,
"height 0 requested without setting top and bottom anchors"); "height 0 requested without setting top and bottom anchors");
return; return;
} }
if (surface->acked_configure) { surface->current = surface->pending;
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;
}
if (wlr_surface_has_buffer(surface->surface) && !surface->configured) { if (wlr_surface_has_buffer(surface->surface) && !surface->configured) {
wl_resource_post_error(surface->resource, wl_resource_post_error(surface->resource,
@ -352,15 +317,6 @@ static void layer_surface_role_commit(struct wlr_surface *wlr_surface) {
return; 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) { if (!surface->added) {
surface->added = true; surface->added = true;
assert(!surface->configured); assert(!surface->configured);
@ -422,7 +378,7 @@ static void layer_shell_handle_get_layer_surface(struct wl_client *wl_client,
if (output_resource) { if (output_resource) {
surface->output = wlr_output_from_resource(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) { if (layer > ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY) {
free(surface); free(surface);
wl_resource_post_error(client_resource, wl_resource_post_error(client_resource,