[PATCH weston] libweston-desktop/xdg-shell: Consolidate configure event sending

Quentin Glidic sardemff7+wayland at sardemff7.net
Thu Apr 13 19:15:57 UTC 2017


From: Quentin Glidic <sardemff7+git at sardemff7.net>

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 at sardemff7.net>
---
 libweston-desktop/xdg-shell-v5.c | 81 +++++++++++++++++++++------------
 libweston-desktop/xdg-shell-v6.c | 98 ++++++++++++++++++++++++++--------------
 2 files changed, 115 insertions(+), 64 deletions(-)

diff --git a/libweston-desktop/xdg-shell-v5.c b/libweston-desktop/xdg-shell-v5.c
index 08cf71ee..bec314ba 100644
--- a/libweston-desktop/xdg-shell-v5.c
+++ b/libweston-desktop/xdg-shell-v5.c
@@ -118,18 +118,56 @@ weston_desktop_xdg_surface_send_configure(void *data)
 	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 true;
+}
+
 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 @@ weston_desktop_xdg_surface_set_maximized(struct weston_desktop_surface *dsurface
 {
 	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 @@ weston_desktop_xdg_surface_set_fullscreen(struct weston_desktop_surface *dsurfac
 {
 	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 @@ weston_desktop_xdg_surface_set_resizing(struct weston_desktop_surface *dsurface,
 {
 	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 @@ weston_desktop_xdg_surface_set_activated(struct weston_desktop_surface *dsurface
 {
 	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 @@ weston_desktop_xdg_surface_set_size(struct weston_desktop_surface *dsurface,
 				    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 @@ weston_desktop_xdg_surface_committed(struct weston_desktop_surface *dsurface,
 			      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 7d0bd8e4..a5b90980 100644
--- a/libweston-desktop/xdg-shell-v6.c
+++ b/libweston-desktop/xdg-shell-v6.c
@@ -281,7 +281,8 @@ static const struct zxdg_positioner_v6_interface weston_desktop_xdg_positioner_i
 };
 
 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_xdg_toplevel_ensure_added(struct weston_desktop_xdg_toplevel *top
 
 	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 @@ weston_desktop_xdg_toplevel_set_maximized(struct weston_desktop_surface *dsurfac
 {
 	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 @@ weston_desktop_xdg_toplevel_set_fullscreen(struct weston_desktop_surface *dsurfa
 {
 	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 @@ weston_desktop_xdg_toplevel_set_resizing(struct weston_desktop_surface *dsurface
 {
 	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 @@ weston_desktop_xdg_toplevel_set_activated(struct weston_desktop_surface *dsurfac
 {
 	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 @@ weston_desktop_xdg_toplevel_set_size(struct weston_desktop_surface *dsurface,
 				     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
@@ -640,7 +623,8 @@ weston_desktop_xdg_toplevel_committed(struct weston_desktop_xdg_toplevel *toplev
 			  ( toplevel->requested_size.height != wsurface->height ) );
 
 	if (reconfigure) {
-		weston_desktop_xdg_surface_schedule_configure(&toplevel->base);
+		weston_desktop_xdg_surface_schedule_configure(&toplevel->base,
+							      true);
 	} else {
 		toplevel->state = toplevel->next_state;
 		toplevel->min_size = toplevel->next_min_size;
@@ -789,7 +773,7 @@ static void
 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);
@@ -870,18 +854,64 @@ weston_desktop_xdg_surface_send_configure(void *user_data)
 	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 true;
+}
+
 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
-- 
2.12.2



More information about the wayland-devel mailing list