mirror of
https://gitlab.freedesktop.org/wlroots/wlroots.git
synced 2025-11-23 06:59:44 -05:00
xdg-shell: add support for cached xdg_surface state
When the pending surface state becomes cached, also cache the pending xdg_surface state. When a cached surface state becomes current, also make the matching cached xdg_surface state current. References: https://github.com/swaywm/wlroots/issues/2957
This commit is contained in:
parent
0f9ecac3cb
commit
9c3163df7a
2 changed files with 84 additions and 15 deletions
|
|
@ -149,6 +149,14 @@ struct wlr_xdg_surface_configure {
|
||||||
struct wlr_xdg_toplevel_state *toplevel_state;
|
struct wlr_xdg_toplevel_state *toplevel_state;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct wlr_xdg_surface_state {
|
||||||
|
bool has_geometry;
|
||||||
|
struct wlr_box geometry;
|
||||||
|
|
||||||
|
uint32_t seq;
|
||||||
|
struct wl_list cached_state_link;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An xdg-surface is a user interface element requiring management by the
|
* 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
|
* compositor. An xdg-surface alone isn't useful, a role should be assigned to
|
||||||
|
|
@ -179,12 +187,14 @@ struct wlr_xdg_surface {
|
||||||
uint32_t configure_next_serial;
|
uint32_t configure_next_serial;
|
||||||
struct wl_list configure_list;
|
struct wl_list configure_list;
|
||||||
|
|
||||||
bool has_next_geometry;
|
|
||||||
struct wlr_box next_geometry;
|
|
||||||
struct wlr_box geometry;
|
struct wlr_box geometry;
|
||||||
|
|
||||||
|
struct wlr_xdg_surface_state pending;
|
||||||
|
struct wl_list cached;
|
||||||
|
|
||||||
struct wl_listener surface_destroy;
|
struct wl_listener surface_destroy;
|
||||||
struct wl_listener surface_commit;
|
struct wl_listener surface_commit;
|
||||||
|
struct wl_listener surface_cache;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
struct wl_signal destroy;
|
struct wl_signal destroy;
|
||||||
|
|
|
||||||
|
|
@ -87,9 +87,8 @@ void unmap_xdg_surface(struct wlr_xdg_surface *surface) {
|
||||||
}
|
}
|
||||||
surface->configure_next_serial = 0;
|
surface->configure_next_serial = 0;
|
||||||
|
|
||||||
surface->has_next_geometry = false;
|
surface->pending.has_geometry = false;
|
||||||
memset(&surface->geometry, 0, sizeof(struct wlr_box));
|
memset(&surface->geometry, 0, sizeof(struct wlr_box));
|
||||||
memset(&surface->next_geometry, 0, sizeof(struct wlr_box));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -285,11 +284,11 @@ static void xdg_surface_handle_set_window_geometry(struct wl_client *client,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
surface->has_next_geometry = true;
|
surface->pending.has_geometry = true;
|
||||||
surface->next_geometry.height = height;
|
surface->pending.geometry.x = x;
|
||||||
surface->next_geometry.width = width;
|
surface->pending.geometry.y = y;
|
||||||
surface->next_geometry.x = x;
|
surface->pending.geometry.width = width;
|
||||||
surface->next_geometry.y = y;
|
surface->pending.geometry.height = height;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void xdg_surface_handle_destroy(struct wl_client *client,
|
static void xdg_surface_handle_destroy(struct wl_client *client,
|
||||||
|
|
@ -346,6 +345,47 @@ static void xdg_surface_handle_surface_commit(struct wl_listener *listener,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void xdg_surface_handle_surface_cache(struct wl_listener *listener,
|
||||||
|
void *data) {
|
||||||
|
struct wlr_xdg_surface *surface =
|
||||||
|
wl_container_of(listener, surface, surface_cache);
|
||||||
|
|
||||||
|
if (!surface->pending.has_geometry) {
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct wlr_xdg_surface_state *cached = calloc(1, sizeof(*cached));
|
||||||
|
if (cached == NULL) {
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
*cached = surface->pending;
|
||||||
|
wl_list_insert(&surface->cached, &cached->cached_state_link);
|
||||||
|
|
||||||
|
out:
|
||||||
|
surface->pending.seq = surface->surface->pending.seq;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool xdg_surface_pop_state(struct wlr_xdg_surface *surface,
|
||||||
|
uint32_t seq, struct wlr_xdg_surface_state *out) {
|
||||||
|
if (surface->pending.seq == seq) {
|
||||||
|
*out = surface->pending;
|
||||||
|
memset(&surface->pending, 0, sizeof(surface->pending));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct wlr_xdg_surface_state *cached;
|
||||||
|
wl_list_for_each(cached, &surface->cached, cached_state_link) {
|
||||||
|
if (cached->seq == seq) {
|
||||||
|
wl_list_remove(&cached->cached_state_link);
|
||||||
|
*out = *cached;
|
||||||
|
free(cached);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void handle_xdg_surface_commit(struct wlr_surface *wlr_surface) {
|
void handle_xdg_surface_commit(struct wlr_surface *wlr_surface) {
|
||||||
struct wlr_xdg_surface *surface =
|
struct wlr_xdg_surface *surface =
|
||||||
wlr_xdg_surface_from_wlr_surface(wlr_surface);
|
wlr_xdg_surface_from_wlr_surface(wlr_surface);
|
||||||
|
|
@ -353,12 +393,16 @@ void handle_xdg_surface_commit(struct wlr_surface *wlr_surface) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (surface->has_next_geometry) {
|
struct wlr_xdg_surface_state next;
|
||||||
surface->has_next_geometry = false;
|
bool has_next =
|
||||||
surface->geometry.x = surface->next_geometry.x;
|
xdg_surface_pop_state(surface, wlr_surface->current.seq, &next);
|
||||||
surface->geometry.y = surface->next_geometry.y;
|
surface->pending.seq = wlr_surface->pending.seq;
|
||||||
surface->geometry.width = surface->next_geometry.width;
|
if (!has_next) {
|
||||||
surface->geometry.height = surface->next_geometry.height;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (next.has_geometry) {
|
||||||
|
surface->geometry = next.geometry;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (surface->role) {
|
switch (surface->role) {
|
||||||
|
|
@ -445,6 +489,7 @@ struct wlr_xdg_surface *create_xdg_surface(
|
||||||
|
|
||||||
wl_list_init(&xdg_surface->configure_list);
|
wl_list_init(&xdg_surface->configure_list);
|
||||||
wl_list_init(&xdg_surface->popups);
|
wl_list_init(&xdg_surface->popups);
|
||||||
|
wl_list_init(&xdg_surface->cached);
|
||||||
|
|
||||||
wl_signal_init(&xdg_surface->events.destroy);
|
wl_signal_init(&xdg_surface->events.destroy);
|
||||||
wl_signal_init(&xdg_surface->events.ping_timeout);
|
wl_signal_init(&xdg_surface->events.ping_timeout);
|
||||||
|
|
@ -462,6 +507,10 @@ struct wlr_xdg_surface *create_xdg_surface(
|
||||||
&xdg_surface->surface_commit);
|
&xdg_surface->surface_commit);
|
||||||
xdg_surface->surface_commit.notify = xdg_surface_handle_surface_commit;
|
xdg_surface->surface_commit.notify = xdg_surface_handle_surface_commit;
|
||||||
|
|
||||||
|
wl_signal_add(&xdg_surface->surface->events.cache,
|
||||||
|
&xdg_surface->surface_cache);
|
||||||
|
xdg_surface->surface_cache.notify = xdg_surface_handle_surface_cache;
|
||||||
|
|
||||||
wlr_log(WLR_DEBUG, "new xdg_surface %p (res %p)", xdg_surface,
|
wlr_log(WLR_DEBUG, "new xdg_surface %p (res %p)", xdg_surface,
|
||||||
xdg_surface->resource);
|
xdg_surface->resource);
|
||||||
wl_resource_set_implementation(xdg_surface->resource,
|
wl_resource_set_implementation(xdg_surface->resource,
|
||||||
|
|
@ -469,6 +518,8 @@ struct wlr_xdg_surface *create_xdg_surface(
|
||||||
xdg_surface_handle_resource_destroy);
|
xdg_surface_handle_resource_destroy);
|
||||||
wl_list_insert(&client->surfaces, &xdg_surface->link);
|
wl_list_insert(&client->surfaces, &xdg_surface->link);
|
||||||
|
|
||||||
|
xdg_surface->pending.seq = surface->pending.seq;
|
||||||
|
|
||||||
return xdg_surface;
|
return xdg_surface;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -518,9 +569,17 @@ void destroy_xdg_surface(struct wlr_xdg_surface *surface) {
|
||||||
wl_resource_set_user_data(surface->resource, NULL);
|
wl_resource_set_user_data(surface->resource, NULL);
|
||||||
surface->surface->role_data = NULL;
|
surface->surface->role_data = NULL;
|
||||||
|
|
||||||
|
struct wlr_xdg_surface_state *cached, *cached_tmp;
|
||||||
|
wl_list_for_each_safe(cached, cached_tmp, &surface->cached,
|
||||||
|
cached_state_link) {
|
||||||
|
wl_list_remove(&cached->cached_state_link);
|
||||||
|
free(cached);
|
||||||
|
}
|
||||||
|
|
||||||
wl_list_remove(&surface->link);
|
wl_list_remove(&surface->link);
|
||||||
wl_list_remove(&surface->surface_destroy.link);
|
wl_list_remove(&surface->surface_destroy.link);
|
||||||
wl_list_remove(&surface->surface_commit.link);
|
wl_list_remove(&surface->surface_commit.link);
|
||||||
|
wl_list_remove(&surface->surface_cache.link);
|
||||||
free(surface);
|
free(surface);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue