layer-shell: refactor configure/state flow
Same logic as xdg-toplevel.
This commit is contained in:
parent
3c26244340
commit
59fa3637c3
|
@ -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);
|
||||
|
||||
/**
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
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);
|
||||
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 surface->pending.configure_serial;
|
||||
}
|
||||
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) {
|
||||
|
@ -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,
|
||||
|
|
Loading…
Reference in New Issue