libweston-desktop/xdg-shell: Properly handle ack_configure
Now we keep track of serial->state association and we discard the states that the client ignored. Signed-off-by: Quentin Glidic <sardemff7+git@sardemff7.net> Reviewed-by: Jonas Ådahl <jadahl@gmail.com>
This commit is contained in:
@@ -46,6 +46,13 @@ struct weston_desktop_xdg_surface_state {
|
|||||||
bool activated;
|
bool activated;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct weston_desktop_xdg_surface_configure {
|
||||||
|
struct wl_list link; /* weston_desktop_xdg_surface::configure_list */
|
||||||
|
uint32_t serial;
|
||||||
|
struct weston_desktop_xdg_surface_state state;
|
||||||
|
struct weston_size size;
|
||||||
|
};
|
||||||
|
|
||||||
struct weston_desktop_xdg_surface {
|
struct weston_desktop_xdg_surface {
|
||||||
struct wl_resource *resource;
|
struct wl_resource *resource;
|
||||||
struct weston_desktop_surface *surface;
|
struct weston_desktop_surface *surface;
|
||||||
@@ -53,7 +60,7 @@ struct weston_desktop_xdg_surface {
|
|||||||
bool added;
|
bool added;
|
||||||
struct wl_event_source *add_idle;
|
struct wl_event_source *add_idle;
|
||||||
struct wl_event_source *configure_idle;
|
struct wl_event_source *configure_idle;
|
||||||
uint32_t configure_serial;
|
struct wl_list configure_list; /* weston_desktop_xdg_surface_configure::link */
|
||||||
struct {
|
struct {
|
||||||
struct weston_desktop_xdg_surface_state state;
|
struct weston_desktop_xdg_surface_state state;
|
||||||
struct weston_size size;
|
struct weston_size size;
|
||||||
@@ -94,13 +101,26 @@ static void
|
|||||||
weston_desktop_xdg_surface_send_configure(void *data)
|
weston_desktop_xdg_surface_send_configure(void *data)
|
||||||
{
|
{
|
||||||
struct weston_desktop_xdg_surface *surface = data;
|
struct weston_desktop_xdg_surface *surface = data;
|
||||||
|
struct weston_desktop_xdg_surface_configure *configure;
|
||||||
uint32_t *s;
|
uint32_t *s;
|
||||||
struct wl_array states;
|
struct wl_array states;
|
||||||
|
|
||||||
surface->configure_idle = NULL;
|
surface->configure_idle = NULL;
|
||||||
|
|
||||||
surface->configure_serial =
|
configure = zalloc(sizeof(struct weston_desktop_xdg_surface_configure));
|
||||||
|
if (configure == NULL) {
|
||||||
|
struct weston_desktop_client *client =
|
||||||
|
weston_desktop_surface_get_client(surface->surface);
|
||||||
|
struct wl_client *wl_client =
|
||||||
|
weston_desktop_client_get_client(client);
|
||||||
|
wl_client_post_no_memory(wl_client);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
wl_list_insert(surface->configure_list.prev, &configure->link);
|
||||||
|
configure->serial =
|
||||||
wl_display_next_serial(weston_desktop_get_display(surface->desktop));
|
wl_display_next_serial(weston_desktop_get_display(surface->desktop));
|
||||||
|
configure->state = surface->pending.state;
|
||||||
|
configure->size = surface->pending.size;
|
||||||
|
|
||||||
wl_array_init(&states);
|
wl_array_init(&states);
|
||||||
if (surface->pending.state.maximized) {
|
if (surface->pending.state.maximized) {
|
||||||
@@ -124,7 +144,7 @@ weston_desktop_xdg_surface_send_configure(void *data)
|
|||||||
surface->pending.size.width,
|
surface->pending.size.width,
|
||||||
surface->pending.size.height,
|
surface->pending.size.height,
|
||||||
&states,
|
&states,
|
||||||
surface->configure_serial);
|
configure->serial);
|
||||||
|
|
||||||
wl_array_release(&states);
|
wl_array_release(&states);
|
||||||
};
|
};
|
||||||
@@ -325,6 +345,7 @@ weston_desktop_xdg_surface_destroy(struct weston_desktop_surface *dsurface,
|
|||||||
void *user_data)
|
void *user_data)
|
||||||
{
|
{
|
||||||
struct weston_desktop_xdg_surface *surface = user_data;
|
struct weston_desktop_xdg_surface *surface = user_data;
|
||||||
|
struct weston_desktop_xdg_surface_configure *configure, *temp;
|
||||||
|
|
||||||
if (surface->added)
|
if (surface->added)
|
||||||
weston_desktop_api_surface_removed(surface->desktop,
|
weston_desktop_api_surface_removed(surface->desktop,
|
||||||
@@ -336,6 +357,9 @@ weston_desktop_xdg_surface_destroy(struct weston_desktop_surface *dsurface,
|
|||||||
if (surface->configure_idle != NULL)
|
if (surface->configure_idle != NULL)
|
||||||
wl_event_source_remove(surface->configure_idle);
|
wl_event_source_remove(surface->configure_idle);
|
||||||
|
|
||||||
|
wl_list_for_each_safe(configure, temp, &surface->configure_list, link)
|
||||||
|
free(configure);
|
||||||
|
|
||||||
free(surface);
|
free(surface);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -443,12 +467,34 @@ weston_desktop_xdg_surface_protocol_ack_configure(struct wl_client *wl_client,
|
|||||||
wl_resource_get_user_data(resource);
|
wl_resource_get_user_data(resource);
|
||||||
struct weston_desktop_xdg_surface *surface =
|
struct weston_desktop_xdg_surface *surface =
|
||||||
weston_desktop_surface_get_implementation_data(dsurface);
|
weston_desktop_surface_get_implementation_data(dsurface);
|
||||||
|
struct weston_desktop_xdg_surface_configure *configure, *temp;
|
||||||
|
bool found = false;
|
||||||
|
|
||||||
if (surface->configure_serial != serial)
|
wl_list_for_each_safe(configure, temp, &surface->configure_list, link) {
|
||||||
|
if (configure->serial < serial) {
|
||||||
|
wl_list_remove(&configure->link);
|
||||||
|
free(configure);
|
||||||
|
} else if (configure->serial == serial) {
|
||||||
|
wl_list_remove(&configure->link);
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!found) {
|
||||||
|
struct weston_desktop_client *client =
|
||||||
|
weston_desktop_surface_get_client(dsurface);
|
||||||
|
struct wl_resource *client_resource =
|
||||||
|
weston_desktop_client_get_resource(client);
|
||||||
|
wl_resource_post_error(client_resource,
|
||||||
|
XDG_SHELL_ERROR_DEFUNCT_SURFACES,
|
||||||
|
"Wrong configure serial: %u", serial);
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
surface->next.state = surface->pending.state;
|
surface->next.state = configure->state;
|
||||||
surface->next.size = surface->pending.size;
|
surface->next.size = configure->size;
|
||||||
|
|
||||||
|
free(configure);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ struct weston_desktop_xdg_surface {
|
|||||||
struct weston_desktop_surface *desktop_surface;
|
struct weston_desktop_surface *desktop_surface;
|
||||||
bool configured;
|
bool configured;
|
||||||
struct wl_event_source *configure_idle;
|
struct wl_event_source *configure_idle;
|
||||||
uint32_t configure_serial;
|
struct wl_list configure_list; /* weston_desktop_xdg_surface_configure::link */
|
||||||
|
|
||||||
bool has_next_geometry;
|
bool has_next_geometry;
|
||||||
struct weston_geometry next_geometry;
|
struct weston_geometry next_geometry;
|
||||||
@@ -77,6 +77,11 @@ struct weston_desktop_xdg_surface {
|
|||||||
enum weston_desktop_xdg_surface_role role;
|
enum weston_desktop_xdg_surface_role role;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct weston_desktop_xdg_surface_configure {
|
||||||
|
struct wl_list link; /* weston_desktop_xdg_surface::configure_list */
|
||||||
|
uint32_t serial;
|
||||||
|
};
|
||||||
|
|
||||||
struct weston_desktop_xdg_toplevel_state {
|
struct weston_desktop_xdg_toplevel_state {
|
||||||
bool maximized;
|
bool maximized;
|
||||||
bool fullscreen;
|
bool fullscreen;
|
||||||
@@ -84,6 +89,12 @@ struct weston_desktop_xdg_toplevel_state {
|
|||||||
bool activated;
|
bool activated;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct weston_desktop_xdg_toplevel_configure {
|
||||||
|
struct weston_desktop_xdg_surface_configure base;
|
||||||
|
struct weston_desktop_xdg_toplevel_state state;
|
||||||
|
struct weston_size size;
|
||||||
|
};
|
||||||
|
|
||||||
struct weston_desktop_xdg_toplevel {
|
struct weston_desktop_xdg_toplevel {
|
||||||
struct weston_desktop_xdg_surface base;
|
struct weston_desktop_xdg_surface base;
|
||||||
|
|
||||||
@@ -115,6 +126,7 @@ struct weston_desktop_xdg_popup {
|
|||||||
};
|
};
|
||||||
|
|
||||||
#define weston_desktop_surface_role_biggest_size (sizeof(struct weston_desktop_xdg_toplevel))
|
#define weston_desktop_surface_role_biggest_size (sizeof(struct weston_desktop_xdg_toplevel))
|
||||||
|
#define weston_desktop_surface_configure_biggest_size (sizeof(struct weston_desktop_xdg_toplevel))
|
||||||
|
|
||||||
|
|
||||||
static struct weston_geometry
|
static struct weston_geometry
|
||||||
@@ -422,10 +434,11 @@ weston_desktop_xdg_toplevel_protocol_resize(struct wl_client *wl_client,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
weston_desktop_xdg_toplevel_ack_configure(struct weston_desktop_xdg_toplevel *toplevel)
|
weston_desktop_xdg_toplevel_ack_configure(struct weston_desktop_xdg_toplevel *toplevel,
|
||||||
|
struct weston_desktop_xdg_toplevel_configure *configure)
|
||||||
{
|
{
|
||||||
toplevel->next.state = toplevel->pending.state;
|
toplevel->next.state = configure->state;
|
||||||
toplevel->next.size = toplevel->pending.size;
|
toplevel->next.size = configure->size;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -529,11 +542,15 @@ weston_desktop_xdg_toplevel_protocol_set_minimized(struct wl_client *wl_client,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
weston_desktop_xdg_toplevel_send_configure(struct weston_desktop_xdg_toplevel *toplevel)
|
weston_desktop_xdg_toplevel_send_configure(struct weston_desktop_xdg_toplevel *toplevel,
|
||||||
|
struct weston_desktop_xdg_toplevel_configure *configure)
|
||||||
{
|
{
|
||||||
uint32_t *s;
|
uint32_t *s;
|
||||||
struct wl_array states;
|
struct wl_array states;
|
||||||
|
|
||||||
|
configure->state = toplevel->pending.state;
|
||||||
|
configure->size = toplevel->pending.size;
|
||||||
|
|
||||||
wl_array_init(&states);
|
wl_array_init(&states);
|
||||||
if (toplevel->pending.state.maximized) {
|
if (toplevel->pending.state.maximized) {
|
||||||
s = wl_array_add(&states, sizeof(uint32_t));
|
s = wl_array_add(&states, sizeof(uint32_t));
|
||||||
@@ -848,9 +865,21 @@ static void
|
|||||||
weston_desktop_xdg_surface_send_configure(void *user_data)
|
weston_desktop_xdg_surface_send_configure(void *user_data)
|
||||||
{
|
{
|
||||||
struct weston_desktop_xdg_surface *surface = user_data;
|
struct weston_desktop_xdg_surface *surface = user_data;
|
||||||
|
struct weston_desktop_xdg_surface_configure *configure;
|
||||||
|
|
||||||
surface->configure_idle = NULL;
|
surface->configure_idle = NULL;
|
||||||
surface->configure_serial =
|
|
||||||
|
configure = zalloc(weston_desktop_surface_configure_biggest_size);
|
||||||
|
if (configure == NULL) {
|
||||||
|
struct weston_desktop_client *client =
|
||||||
|
weston_desktop_surface_get_client(surface->desktop_surface);
|
||||||
|
struct wl_client *wl_client =
|
||||||
|
weston_desktop_client_get_client(client);
|
||||||
|
wl_client_post_no_memory(wl_client);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
wl_list_insert(surface->configure_list.prev, &configure->link);
|
||||||
|
configure->serial =
|
||||||
wl_display_next_serial(weston_desktop_get_display(surface->desktop));
|
wl_display_next_serial(weston_desktop_get_display(surface->desktop));
|
||||||
|
|
||||||
switch (surface->role) {
|
switch (surface->role) {
|
||||||
@@ -858,14 +887,15 @@ weston_desktop_xdg_surface_send_configure(void *user_data)
|
|||||||
assert(0 && "not reached");
|
assert(0 && "not reached");
|
||||||
break;
|
break;
|
||||||
case WESTON_DESKTOP_XDG_SURFACE_ROLE_TOPLEVEL:
|
case WESTON_DESKTOP_XDG_SURFACE_ROLE_TOPLEVEL:
|
||||||
weston_desktop_xdg_toplevel_send_configure((struct weston_desktop_xdg_toplevel *) surface);
|
weston_desktop_xdg_toplevel_send_configure((struct weston_desktop_xdg_toplevel *) surface,
|
||||||
|
(struct weston_desktop_xdg_toplevel_configure *) configure);
|
||||||
break;
|
break;
|
||||||
case WESTON_DESKTOP_XDG_SURFACE_ROLE_POPUP:
|
case WESTON_DESKTOP_XDG_SURFACE_ROLE_POPUP:
|
||||||
weston_desktop_xdg_popup_send_configure((struct weston_desktop_xdg_popup *) surface);
|
weston_desktop_xdg_popup_send_configure((struct weston_desktop_xdg_popup *) surface);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
zxdg_surface_v6_send_configure(surface->resource, surface->configure_serial);
|
zxdg_surface_v6_send_configure(surface->resource, configure->serial);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
@@ -1060,12 +1090,32 @@ weston_desktop_xdg_surface_protocol_ack_configure(struct wl_client *wl_client,
|
|||||||
wl_resource_get_user_data(resource);
|
wl_resource_get_user_data(resource);
|
||||||
struct weston_desktop_xdg_surface *surface =
|
struct weston_desktop_xdg_surface *surface =
|
||||||
weston_desktop_surface_get_implementation_data(dsurface);
|
weston_desktop_surface_get_implementation_data(dsurface);
|
||||||
|
struct weston_desktop_xdg_surface_configure *configure, *temp;
|
||||||
|
bool found = false;
|
||||||
|
|
||||||
if (!weston_desktop_xdg_surface_check_role(surface))
|
if (!weston_desktop_xdg_surface_check_role(surface))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (surface->configure_serial != serial)
|
wl_list_for_each_safe(configure, temp, &surface->configure_list, link) {
|
||||||
|
if (configure->serial < serial) {
|
||||||
|
wl_list_remove(&configure->link);
|
||||||
|
free(configure);
|
||||||
|
} else if (configure->serial == serial) {
|
||||||
|
wl_list_remove(&configure->link);
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!found) {
|
||||||
|
struct weston_desktop_client *client =
|
||||||
|
weston_desktop_surface_get_client(dsurface);
|
||||||
|
struct wl_resource *client_resource =
|
||||||
|
weston_desktop_client_get_resource(client);
|
||||||
|
wl_resource_post_error(client_resource,
|
||||||
|
ZXDG_SHELL_V6_ERROR_INVALID_SURFACE_STATE,
|
||||||
|
"Wrong configure serial: %u", serial);
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
surface->configured = true;
|
surface->configured = true;
|
||||||
|
|
||||||
@@ -1074,11 +1124,14 @@ weston_desktop_xdg_surface_protocol_ack_configure(struct wl_client *wl_client,
|
|||||||
assert(0 && "not reached");
|
assert(0 && "not reached");
|
||||||
break;
|
break;
|
||||||
case WESTON_DESKTOP_XDG_SURFACE_ROLE_TOPLEVEL:
|
case WESTON_DESKTOP_XDG_SURFACE_ROLE_TOPLEVEL:
|
||||||
weston_desktop_xdg_toplevel_ack_configure((struct weston_desktop_xdg_toplevel *) surface);
|
weston_desktop_xdg_toplevel_ack_configure((struct weston_desktop_xdg_toplevel *) surface,
|
||||||
|
(struct weston_desktop_xdg_toplevel_configure *) configure);
|
||||||
break;
|
break;
|
||||||
case WESTON_DESKTOP_XDG_SURFACE_ROLE_POPUP:
|
case WESTON_DESKTOP_XDG_SURFACE_ROLE_POPUP:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
free(configure);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -1153,6 +1206,7 @@ weston_desktop_xdg_surface_destroy(struct weston_desktop_surface *dsurface,
|
|||||||
void *user_data)
|
void *user_data)
|
||||||
{
|
{
|
||||||
struct weston_desktop_xdg_surface *surface = user_data;
|
struct weston_desktop_xdg_surface *surface = user_data;
|
||||||
|
struct weston_desktop_xdg_surface_configure *configure, *temp;
|
||||||
|
|
||||||
switch (surface->role) {
|
switch (surface->role) {
|
||||||
case WESTON_DESKTOP_XDG_SURFACE_ROLE_NONE:
|
case WESTON_DESKTOP_XDG_SURFACE_ROLE_NONE:
|
||||||
@@ -1168,6 +1222,9 @@ weston_desktop_xdg_surface_destroy(struct weston_desktop_surface *dsurface,
|
|||||||
if (surface->configure_idle != NULL)
|
if (surface->configure_idle != NULL)
|
||||||
wl_event_source_remove(surface->configure_idle);
|
wl_event_source_remove(surface->configure_idle);
|
||||||
|
|
||||||
|
wl_list_for_each_safe(configure, temp, &surface->configure_list, link)
|
||||||
|
free(configure);
|
||||||
|
|
||||||
free(surface);
|
free(surface);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1290,6 +1347,8 @@ weston_desktop_xdg_shell_protocol_get_xdg_surface(struct wl_client *wl_client,
|
|||||||
"xdg_surface must not have a buffer at creation");
|
"xdg_surface must not have a buffer at creation");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wl_list_init(&surface->configure_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|||||||
Reference in New Issue
Block a user