libweston-desktop/xdg-shell: Consolidate configure event sending
When switching a state twice in a row, we were overwriting the old value
without setting it back, sending a wrong state to the client.
Now we update our requested state, then check if we need to schedule a
configure event, if we have one scheduled already or even if we can
cancel it.
Signed-off-by: Quentin Glidic <sardemff7+git@sardemff7.net>
Reviewed-by: Daniel Stone <daniels@collabora.com>
diff --git a/libweston-desktop/xdg-shell-v5.c b/libweston-desktop/xdg-shell-v5.c
index 08cf71e..1ec796e 100644
--- a/libweston-desktop/xdg-shell-v5.c
+++ b/libweston-desktop/xdg-shell-v5.c
@@ -118,18 +118,56 @@
wl_array_release(&states);
};
+static bool
+weston_desktop_xdg_surface_state_compare(struct weston_desktop_xdg_surface *surface)
+{
+ struct weston_surface *wsurface =
+ weston_desktop_surface_get_surface(surface->surface);
+
+ if (surface->requested_state.activated != surface->state.activated)
+ return false;
+ if (surface->requested_state.fullscreen != surface->state.fullscreen)
+ return false;
+ if (surface->requested_state.maximized != surface->state.maximized)
+ return false;
+ if (surface->requested_state.resizing != surface->state.resizing)
+ return false;
+
+ if (wsurface->width == surface->requested_size.width &&
+ wsurface->height == surface->requested_size.height)
+ return true;
+
+ if (surface->requested_size.width == 0 &&
+ surface->requested_size.height == 0)
+ return true;
+
+ return false;
+}
+
static void
-weston_desktop_xdg_surface_schedule_configure(struct weston_desktop_xdg_surface *surface)
+weston_desktop_xdg_surface_schedule_configure(struct weston_desktop_xdg_surface *surface,
+ bool force)
{
struct wl_display *display = weston_desktop_get_display(surface->desktop);
struct wl_event_loop *loop = wl_display_get_event_loop(display);
+ bool requested_same =
+ !force && weston_desktop_xdg_surface_state_compare(surface);
- if (surface->configure_idle != NULL)
- return;
- surface->configure_idle =
- wl_event_loop_add_idle(loop,
- weston_desktop_xdg_surface_send_configure,
- surface);
+ if (surface->configure_idle != NULL) {
+ if (!requested_same)
+ return;
+
+ wl_event_source_remove(surface->configure_idle);
+ surface->configure_idle = NULL;
+ } else {
+ if (requested_same)
+ return;
+
+ surface->configure_idle =
+ wl_event_loop_add_idle(loop,
+ weston_desktop_xdg_surface_send_configure,
+ surface);
+ }
}
static void
@@ -138,11 +176,8 @@
{
struct weston_desktop_xdg_surface *surface = user_data;
- if (surface->state.maximized == maximized)
- return;
-
surface->requested_state.maximized = maximized;
- weston_desktop_xdg_surface_schedule_configure(surface);
+ weston_desktop_xdg_surface_schedule_configure(surface, false);
}
static void
@@ -151,11 +186,8 @@
{
struct weston_desktop_xdg_surface *surface = user_data;
- if (surface->state.fullscreen == fullscreen)
- return;
-
surface->requested_state.fullscreen = fullscreen;
- weston_desktop_xdg_surface_schedule_configure(surface);
+ weston_desktop_xdg_surface_schedule_configure(surface, false);
}
static void
@@ -164,11 +196,8 @@
{
struct weston_desktop_xdg_surface *surface = user_data;
- if (surface->state.resizing == resizing)
- return;
-
surface->requested_state.resizing = resizing;
- weston_desktop_xdg_surface_schedule_configure(surface);
+ weston_desktop_xdg_surface_schedule_configure(surface, false);
}
static void
@@ -177,11 +206,8 @@
{
struct weston_desktop_xdg_surface *surface = user_data;
- if (surface->state.activated == activated)
- return;
-
surface->requested_state.activated = activated;
- weston_desktop_xdg_surface_schedule_configure(surface);
+ weston_desktop_xdg_surface_schedule_configure(surface, false);
}
static void
@@ -190,16 +216,11 @@
int32_t width, int32_t height)
{
struct weston_desktop_xdg_surface *surface = user_data;
- struct weston_surface *wsurface = weston_desktop_surface_get_surface(surface->surface);
surface->requested_size.width = width;
surface->requested_size.height = height;
- if ((wsurface->width == width && wsurface->height == height) ||
- (width == 0 && height == 0))
- return;
-
- weston_desktop_xdg_surface_schedule_configure(surface);
+ weston_desktop_xdg_surface_schedule_configure(surface, false);
}
static void
@@ -217,7 +238,7 @@
surface->requested_size.height != wsurface->height;
if (reconfigure) {
- weston_desktop_xdg_surface_schedule_configure(surface);
+ weston_desktop_xdg_surface_schedule_configure(surface, true);
} else {
surface->state = surface->next_state;
if (surface->has_next_geometry) {
diff --git a/libweston-desktop/xdg-shell-v6.c b/libweston-desktop/xdg-shell-v6.c
index 600723e..9dec1fe 100644
--- a/libweston-desktop/xdg-shell-v6.c
+++ b/libweston-desktop/xdg-shell-v6.c
@@ -281,7 +281,8 @@
};
static void
-weston_desktop_xdg_surface_schedule_configure(struct weston_desktop_xdg_surface *surface);
+weston_desktop_xdg_surface_schedule_configure(struct weston_desktop_xdg_surface *surface,
+ bool force);
static void
weston_desktop_xdg_toplevel_ensure_added(struct weston_desktop_xdg_toplevel *toplevel)
@@ -291,7 +292,7 @@
weston_desktop_api_surface_added(toplevel->base.desktop,
toplevel->base.desktop_surface);
- weston_desktop_xdg_surface_schedule_configure(&toplevel->base);
+ weston_desktop_xdg_surface_schedule_configure(&toplevel->base, true);
toplevel->added = true;
}
@@ -554,11 +555,8 @@
{
struct weston_desktop_xdg_toplevel *toplevel = user_data;
- if (toplevel->state.maximized == maximized)
- return;
-
toplevel->requested_state.maximized = maximized;
- weston_desktop_xdg_surface_schedule_configure(&toplevel->base);
+ weston_desktop_xdg_surface_schedule_configure(&toplevel->base, false);
}
static void
@@ -567,11 +565,8 @@
{
struct weston_desktop_xdg_toplevel *toplevel = user_data;
- if (toplevel->state.fullscreen == fullscreen)
- return;
-
toplevel->requested_state.fullscreen = fullscreen;
- weston_desktop_xdg_surface_schedule_configure(&toplevel->base);
+ weston_desktop_xdg_surface_schedule_configure(&toplevel->base, false);
}
static void
@@ -580,11 +575,8 @@
{
struct weston_desktop_xdg_toplevel *toplevel = user_data;
- if (toplevel->state.resizing == resizing)
- return;
-
toplevel->requested_state.resizing = resizing;
- weston_desktop_xdg_surface_schedule_configure(&toplevel->base);
+ weston_desktop_xdg_surface_schedule_configure(&toplevel->base, false);
}
static void
@@ -593,11 +585,8 @@
{
struct weston_desktop_xdg_toplevel *toplevel = user_data;
- if (toplevel->state.activated == activated)
- return;
-
toplevel->requested_state.activated = activated;
- weston_desktop_xdg_surface_schedule_configure(&toplevel->base);
+ weston_desktop_xdg_surface_schedule_configure(&toplevel->base, false);
}
static void
@@ -606,17 +595,11 @@
int32_t width, int32_t height)
{
struct weston_desktop_xdg_toplevel *toplevel = user_data;
- struct weston_surface *wsurface =
- weston_desktop_surface_get_surface(toplevel->base.desktop_surface);
toplevel->requested_size.width = width;
toplevel->requested_size.height = height;
- if ((wsurface->width == width && wsurface->height == height) ||
- (width == 0 && height == 0))
- return;
-
- weston_desktop_xdg_surface_schedule_configure(&toplevel->base);
+ weston_desktop_xdg_surface_schedule_configure(&toplevel->base, false);
}
static void
@@ -793,7 +776,7 @@
weston_desktop_xdg_popup_committed(struct weston_desktop_xdg_popup *popup)
{
if (!popup->committed)
- weston_desktop_xdg_surface_schedule_configure(&popup->base);
+ weston_desktop_xdg_surface_schedule_configure(&popup->base, true);
popup->committed = true;
weston_desktop_xdg_popup_update_position(popup->base.desktop_surface,
popup);
@@ -874,18 +857,64 @@
zxdg_surface_v6_send_configure(surface->resource, surface->configure_serial);
}
+static bool
+weston_desktop_xdg_toplevel_state_compare(struct weston_desktop_xdg_toplevel *toplevel)
+{
+ if (toplevel->requested_state.activated != toplevel->state.activated)
+ return false;
+ if (toplevel->requested_state.fullscreen != toplevel->state.fullscreen)
+ return false;
+ if (toplevel->requested_state.maximized != toplevel->state.maximized)
+ return false;
+ if (toplevel->requested_state.resizing != toplevel->state.resizing)
+ return false;
+
+ if (toplevel->base.surface->width == toplevel->requested_size.width &&
+ toplevel->base.surface->height == toplevel->requested_size.height)
+ return true;
+
+ if (toplevel->requested_size.width == 0 &&
+ toplevel->requested_size.height == 0)
+ return true;
+
+ return false;
+}
+
static void
-weston_desktop_xdg_surface_schedule_configure(struct weston_desktop_xdg_surface *surface)
+weston_desktop_xdg_surface_schedule_configure(struct weston_desktop_xdg_surface *surface,
+ bool force)
{
struct wl_display *display = weston_desktop_get_display(surface->desktop);
struct wl_event_loop *loop = wl_display_get_event_loop(display);
+ bool requested_same = !force;
- if (surface->configure_idle != NULL)
- return;
- surface->configure_idle =
- wl_event_loop_add_idle(loop,
- weston_desktop_xdg_surface_send_configure,
- surface);
+ switch (surface->role) {
+ case WESTON_DESKTOP_XDG_SURFACE_ROLE_NONE:
+ assert(0 && "not reached");
+ break;
+ case WESTON_DESKTOP_XDG_SURFACE_ROLE_TOPLEVEL:
+ requested_same = requested_same &&
+ weston_desktop_xdg_toplevel_state_compare((struct weston_desktop_xdg_toplevel *) surface);
+ break;
+ case WESTON_DESKTOP_XDG_SURFACE_ROLE_POPUP:
+ break;
+ }
+
+ if (surface->configure_idle != NULL) {
+ if (!requested_same)
+ return;
+
+ wl_event_source_remove(surface->configure_idle);
+ surface->configure_idle = NULL;
+ } else {
+ if (requested_same)
+ return;
+
+ surface->configure_idle =
+ wl_event_loop_add_idle(loop,
+ weston_desktop_xdg_surface_send_configure,
+ surface);
+ }
}
static void