Merge branch 'better-initialized' into 'master'

Draft: xdg-shell,layer-shell: improve init state tracking

Closes #3780

See merge request wlroots/wlroots!4766
This commit is contained in:
Kirill Primak 2026-02-04 04:50:12 +03:00
commit 79c8a4dc57
6 changed files with 44 additions and 26 deletions

View file

@ -250,8 +250,6 @@ struct wlr_surface {
int buffer_width, buffer_height;
} previous;
bool unmap_commit;
bool opaque;
bool handling_commit;

View file

@ -70,6 +70,10 @@ struct wlr_layer_surface_v1_state {
uint32_t configure_serial;
uint32_t actual_width, actual_height;
struct {
bool initial_commit;
} WLR_PRIVATE;
};
struct wlr_layer_surface_v1_configure {
@ -118,6 +122,8 @@ struct wlr_layer_surface_v1 {
struct {
struct wlr_surface_synced synced;
bool client_mapped;
} WLR_PRIVATE;
};

View file

@ -258,6 +258,10 @@ struct wlr_xdg_surface_state {
struct wlr_box geometry;
uint32_t configure_serial;
struct {
bool initial_commit;
} WLR_PRIVATE;
};
/**
@ -319,6 +323,8 @@ struct wlr_xdg_surface {
struct wlr_surface_synced synced;
struct wl_listener role_resource_destroy;
bool client_mapped;
} WLR_PRIVATE;
};

View file

@ -515,10 +515,7 @@ static void surface_commit_state(struct wlr_surface *surface,
bool invalid_buffer = next->committed & WLR_SURFACE_STATE_BUFFER;
if (invalid_buffer && next->buffer == NULL) {
surface->unmap_commit = surface->mapped;
wlr_surface_unmap(surface);
} else {
surface->unmap_commit = false;
}
surface_update_damage(&surface->buffer_damage, &surface->current, next);

View file

@ -33,6 +33,7 @@ static void layer_surface_configure_destroy(
static void layer_surface_reset(struct wlr_layer_surface_v1 *surface) {
surface->configured = false;
surface->initialized = false;
surface->client_mapped = false;
struct wlr_xdg_popup *popup, *popup_tmp;
wl_list_for_each_safe(popup, popup_tmp, &surface->popups, link) {
@ -349,7 +350,9 @@ static void layer_surface_role_client_commit(struct wlr_surface *wlr_surface) {
return;
}
if (wlr_surface_state_has_buffer(&wlr_surface->pending) && !surface->configured) {
bool has_pending_buffer = wlr_surface_state_has_buffer(&wlr_surface->pending);
if (has_pending_buffer && !surface->configured) {
wlr_surface_reject_pending(wlr_surface, surface->resource,
ZWLR_LAYER_SHELL_V1_ERROR_ALREADY_CONSTRUCTED,
"layer_surface has never been configured");
@ -380,7 +383,18 @@ static void layer_surface_role_client_commit(struct wlr_surface *wlr_surface) {
wlr_surface_reject_pending(wlr_surface, surface->resource,
ZWLR_LAYER_SURFACE_V1_ERROR_INVALID_EXCLUSIVE_EDGE,
"exclusive edge is invalid given the surface anchors");
return;
}
if (surface->client_mapped && !has_pending_buffer) {
layer_surface_reset(surface);
surface->pending.initial_commit = false;
} else {
surface->pending.initial_commit = !surface->initialized;
surface->initialized = true;
}
surface->client_mapped = has_pending_buffer;
}
static void layer_surface_role_commit(struct wlr_surface *wlr_surface) {
@ -390,15 +404,7 @@ static void layer_surface_role_commit(struct wlr_surface *wlr_surface) {
return;
}
if (surface->surface->unmap_commit) {
layer_surface_reset(surface);
assert(!surface->initialized);
surface->initial_commit = false;
} else {
surface->initial_commit = !surface->initialized;
surface->initialized = true;
}
surface->initial_commit = surface->current.initial_commit && surface->initialized;
if (wlr_surface_has_buffer(wlr_surface)) {
wlr_surface_map(wlr_surface);

View file

@ -26,6 +26,7 @@ static void xdg_surface_configure_destroy(
static void reset_xdg_surface(struct wlr_xdg_surface *surface) {
surface->configured = false;
surface->initialized = false;
surface->client_mapped = false;
struct wlr_xdg_popup *popup, *popup_tmp;
wl_list_for_each_safe(popup, popup_tmp, &surface->popups, link) {
@ -283,7 +284,9 @@ static void xdg_surface_role_client_commit(struct wlr_surface *wlr_surface) {
struct wlr_xdg_surface *surface = wlr_xdg_surface_try_from_wlr_surface(wlr_surface);
assert(surface != NULL);
if (wlr_surface_state_has_buffer(&wlr_surface->pending) && !surface->configured) {
bool has_pending_buffer = wlr_surface_state_has_buffer(&wlr_surface->pending);
if (has_pending_buffer && !surface->configured) {
wlr_surface_reject_pending(wlr_surface, surface->resource,
XDG_SURFACE_ERROR_UNCONFIGURED_BUFFER, "xdg_surface has never been configured");
return;
@ -310,22 +313,24 @@ static void xdg_surface_role_client_commit(struct wlr_surface *wlr_surface) {
}
break;
}
if (surface->client_mapped && !has_pending_buffer) {
reset_xdg_surface_role_object(surface);
reset_xdg_surface(surface);
surface->pending.initial_commit = false;
} else {
surface->pending.initial_commit = !surface->initialized;
surface->initialized = true;
}
surface->client_mapped = has_pending_buffer;
}
static void xdg_surface_role_commit(struct wlr_surface *wlr_surface) {
struct wlr_xdg_surface *surface = wlr_xdg_surface_try_from_wlr_surface(wlr_surface);
assert(surface != NULL);
if (surface->surface->unmap_commit) {
reset_xdg_surface_role_object(surface);
reset_xdg_surface(surface);
assert(!surface->initial_commit);
surface->initial_commit = false;
} else {
surface->initial_commit = !surface->initialized;
surface->initialized = true;
}
surface->initial_commit = surface->current.initial_commit && surface->initialized;
switch (surface->role) {
case WLR_XDG_SURFACE_ROLE_NONE: