[RFC weston] libweston-desktop: Add size_requested API

Quentin Glidic sardemff7+wayland at sardemff7.net
Tue Mar 21 11:53:10 UTC 2017


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

Some shells (wl_shell) does not let the compositor control the surface
state and instead force one. Therefore, they cannot call
{maximized,fullscreen}_requested as these imply the compositor can still
opt-out.
This new callback is called whenever a state change requests a new size,
be it triggered by the client or the compositor.

Signed-off-by: Quentin Glidic <sardemff7+git at sardemff7.net>
---
This patch works correctly as-is, but is RFC because I have yet to add
some API to support output choice in wl_shell.

 libweston-desktop/internal.h          | 12 +++++++
 libweston-desktop/libweston-desktop.c |  8 +++++
 libweston-desktop/libweston-desktop.h | 11 ++++++
 libweston-desktop/surface.c           | 36 ++++++++++++++++++++
 libweston-desktop/wl-shell.c          | 14 +++++---
 libweston-desktop/xdg-shell-v5.c      | 64 +++++++++++++++++++++++++++++------
 libweston-desktop/xdg-shell-v6.c      | 64 +++++++++++++++++++++++++++++------
 libweston-desktop/xwayland.c          | 11 ++++--
 8 files changed, 194 insertions(+), 26 deletions(-)

diff --git a/libweston-desktop/internal.h b/libweston-desktop/internal.h
index 763355bf..38386916 100644
--- a/libweston-desktop/internal.h
+++ b/libweston-desktop/internal.h
@@ -80,6 +80,9 @@ weston_desktop_api_maximized_requested(struct weston_desktop *desktop,
 void
 weston_desktop_api_minimized_requested(struct weston_desktop *desktop,
 				       struct weston_desktop_surface *surface);
+void
+weston_desktop_api_size_requested(struct weston_desktop *desktop,
+				  struct weston_desktop_surface *surface);
 
 void
 weston_desktop_api_set_xwayland_position(struct weston_desktop *desktop,
@@ -123,6 +126,15 @@ struct weston_desktop_surface_implementation {
 	(*get_min_size)(struct weston_desktop_surface *surface,
 			void *user_data);
 
+	bool (*get_pending_activated)(struct weston_desktop_surface *surface,
+					void *user_data);
+	bool (*get_pending_fullscreen)(struct weston_desktop_surface *surface,
+					 void *user_data);
+	bool (*get_pending_maximized)(struct weston_desktop_surface *surface,
+					void *user_data);
+	bool (*get_pending_resizing)(struct weston_desktop_surface *surface,
+				       void *user_data);
+
 	void (*destroy)(struct weston_desktop_surface *surface,
 			void *user_data);
 };
diff --git a/libweston-desktop/libweston-desktop.c b/libweston-desktop/libweston-desktop.c
index 48e90009..a5ae5bd9 100644
--- a/libweston-desktop/libweston-desktop.c
+++ b/libweston-desktop/libweston-desktop.c
@@ -243,6 +243,14 @@ weston_desktop_api_minimized_requested(struct weston_desktop *desktop,
 		desktop->api.minimized_requested(surface, desktop->user_data);
 }
 
+void
+weston_desktop_api_size_requested(struct weston_desktop *desktop,
+				  struct weston_desktop_surface *surface)
+{
+	if (desktop->api.size_requested != NULL)
+		desktop->api.size_requested(surface, desktop->user_data);
+}
+
 void
 weston_desktop_api_set_xwayland_position(struct weston_desktop *desktop,
 					 struct weston_desktop_surface *surface,
diff --git a/libweston-desktop/libweston-desktop.h b/libweston-desktop/libweston-desktop.h
index 03b04c7b..8da10a49 100644
--- a/libweston-desktop/libweston-desktop.h
+++ b/libweston-desktop/libweston-desktop.h
@@ -80,6 +80,8 @@ struct weston_desktop_api {
 				    bool maximized, void *user_data);
 	void (*minimized_requested)(struct weston_desktop_surface *surface,
 				    void *user_data);
+	void (*size_requested)(struct weston_desktop_surface *surface,
+			       void *user_data);
 
 	/** Position suggestion for an Xwayland window
 	 *
@@ -192,6 +194,15 @@ weston_desktop_surface_get_max_size(struct weston_desktop_surface *surface);
 struct weston_size
 weston_desktop_surface_get_min_size(struct weston_desktop_surface *surface);
 
+bool
+weston_desktop_surface_get_pending_activated(struct weston_desktop_surface *surface);
+bool
+weston_desktop_surface_get_pending_maximized(struct weston_desktop_surface *surface);
+bool
+weston_desktop_surface_get_pending_fullscreen(struct weston_desktop_surface *surface);
+bool
+weston_desktop_surface_get_pending_resizing(struct weston_desktop_surface *surface);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/libweston-desktop/surface.c b/libweston-desktop/surface.c
index d3be9364..50aa4f46 100644
--- a/libweston-desktop/surface.c
+++ b/libweston-desktop/surface.c
@@ -675,6 +675,42 @@ weston_desktop_surface_get_min_size(struct weston_desktop_surface *surface)
 						     surface->implementation_data);
 }
 
+WL_EXPORT bool
+weston_desktop_surface_get_pending_activated(struct weston_desktop_surface *surface)
+{
+	if (surface->implementation->get_pending_activated == NULL)
+		return false;
+	return surface->implementation->get_pending_activated(surface,
+								surface->implementation_data);
+}
+
+WL_EXPORT bool
+weston_desktop_surface_get_pending_resizing(struct weston_desktop_surface *surface)
+{
+	if (surface->implementation->get_pending_resizing == NULL)
+		return false;
+	return surface->implementation->get_pending_resizing(surface,
+							       surface->implementation_data);
+}
+
+WL_EXPORT bool
+weston_desktop_surface_get_pending_maximized(struct weston_desktop_surface *surface)
+{
+	if (surface->implementation->get_pending_maximized == NULL)
+		return false;
+	return surface->implementation->get_pending_maximized(surface,
+								surface->implementation_data);
+}
+
+WL_EXPORT bool
+weston_desktop_surface_get_pending_fullscreen(struct weston_desktop_surface *surface)
+{
+	if (surface->implementation->get_pending_fullscreen == NULL)
+		return false;
+	return surface->implementation->get_pending_fullscreen(surface,
+								 surface->implementation_data);
+}
+
 void
 weston_desktop_surface_set_title(struct weston_desktop_surface *surface,
 				 const char *title)
diff --git a/libweston-desktop/wl-shell.c b/libweston-desktop/wl-shell.c
index 399139cf..a48c8ab7 100644
--- a/libweston-desktop/wl-shell.c
+++ b/libweston-desktop/wl-shell.c
@@ -155,6 +155,8 @@ weston_desktop_wl_shell_change_state(struct weston_desktop_wl_shell_surface *sur
 
 	if (to_add && surface->added) {
 		surface->state = state;
+		weston_desktop_api_size_requested(surface->desktop,
+						  surface->surface);
 		return;
 	}
 
@@ -162,16 +164,19 @@ weston_desktop_wl_shell_change_state(struct weston_desktop_wl_shell_surface *sur
 		if (surface->state == POPUP)
 			weston_desktop_wl_shell_surface_maybe_ungrab(surface);
 
+		surface->state = state;
+
 		if (to_add) {
 			weston_desktop_surface_unset_relative_to(surface->surface);
 			weston_desktop_api_surface_added(surface->desktop,
 							 surface->surface);
+			weston_desktop_api_size_requested(surface->desktop,
+							  surface->surface);
 		} else if (surface->added) {
 			weston_desktop_api_surface_removed(surface->desktop,
 							   surface->surface);
 		}
 
-		surface->state = state;
 		surface->added = to_add;
 	}
 
@@ -304,9 +309,8 @@ weston_desktop_wl_shell_surface_protocol_set_fullscreen(struct wl_client *wl_cli
 	if (output_resource != NULL)
 		output = wl_resource_get_user_data(output_resource);
 
+	/* FIXME: add back output usage */
 	weston_desktop_wl_shell_change_state(surface, FULLSCREEN, NULL, 0, 0);
-	weston_desktop_api_fullscreen_requested(surface->desktop, dsurface,
-						true, output);
 }
 
 static void
@@ -355,7 +359,6 @@ weston_desktop_wl_shell_surface_protocol_set_maximized(struct wl_client *wl_clie
 		weston_desktop_surface_get_implementation_data(dsurface);
 
 	weston_desktop_wl_shell_change_state(surface, MAXIMIZED, NULL, 0, 0);
-	weston_desktop_api_maximized_requested(surface->desktop, dsurface, true);
 }
 
 static void
@@ -403,6 +406,9 @@ static const struct weston_desktop_surface_implementation weston_desktop_wl_shel
 	.get_maximized = weston_desktop_wl_shell_surface_get_maximized,
 	.get_fullscreen = weston_desktop_wl_shell_surface_get_fullscreen,
 
+	.get_pending_maximized = weston_desktop_wl_shell_surface_get_maximized,
+	.get_pending_fullscreen = weston_desktop_wl_shell_surface_get_fullscreen,
+
 	.destroy = weston_desktop_wl_shell_surface_destroy,
 };
 
diff --git a/libweston-desktop/xdg-shell-v5.c b/libweston-desktop/xdg-shell-v5.c
index 08cf71ee..b2cb6588 100644
--- a/libweston-desktop/xdg-shell-v5.c
+++ b/libweston-desktop/xdg-shell-v5.c
@@ -53,7 +53,7 @@ struct weston_desktop_xdg_surface {
 		bool fullscreen;
 		bool resizing;
 		bool activated;
-	} requested_state, next_state, state;
+	} pending_state, next_state, state;
 	bool has_next_geometry;
 	struct weston_geometry next_geometry;
 };
@@ -86,25 +86,28 @@ weston_desktop_xdg_surface_send_configure(void *data)
 	uint32_t *s;
 	struct wl_array states;
 
+	/* User is expected to call _set_size(), so we trigger it now so it
+	 * doesn’t schedule another configure event */
+	weston_desktop_api_size_requested(surface->desktop, surface->surface);
 	surface->configure_idle = NULL;
 
 	surface->configure_serial =
 		wl_display_next_serial(weston_desktop_get_display(surface->desktop));
 
 	wl_array_init(&states);
-	if (surface->requested_state.maximized) {
+	if (surface->pending_state.maximized) {
 		s = wl_array_add(&states, sizeof(uint32_t));
 		*s = XDG_SURFACE_STATE_MAXIMIZED;
 	}
-	if (surface->requested_state.fullscreen) {
+	if (surface->pending_state.fullscreen) {
 		s = wl_array_add(&states, sizeof(uint32_t));
 		*s = XDG_SURFACE_STATE_FULLSCREEN;
 	}
-	if (surface->requested_state.resizing) {
+	if (surface->pending_state.resizing) {
 		s = wl_array_add(&states, sizeof(uint32_t));
 		*s = XDG_SURFACE_STATE_RESIZING;
 	}
-	if (surface->requested_state.activated) {
+	if (surface->pending_state.activated) {
 		s = wl_array_add(&states, sizeof(uint32_t));
 		*s = XDG_SURFACE_STATE_ACTIVATED;
 	}
@@ -141,7 +144,7 @@ weston_desktop_xdg_surface_set_maximized(struct weston_desktop_surface *dsurface
 	if (surface->state.maximized == maximized)
 		return;
 
-	surface->requested_state.maximized = maximized;
+	surface->pending_state.maximized = maximized;
 	weston_desktop_xdg_surface_schedule_configure(surface);
 }
 
@@ -154,7 +157,7 @@ weston_desktop_xdg_surface_set_fullscreen(struct weston_desktop_surface *dsurfac
 	if (surface->state.fullscreen == fullscreen)
 		return;
 
-	surface->requested_state.fullscreen = fullscreen;
+	surface->pending_state.fullscreen = fullscreen;
 	weston_desktop_xdg_surface_schedule_configure(surface);
 }
 
@@ -167,7 +170,7 @@ weston_desktop_xdg_surface_set_resizing(struct weston_desktop_surface *dsurface,
 	if (surface->state.resizing == resizing)
 		return;
 
-	surface->requested_state.resizing = resizing;
+	surface->pending_state.resizing = resizing;
 	weston_desktop_xdg_surface_schedule_configure(surface);
 }
 
@@ -180,7 +183,7 @@ weston_desktop_xdg_surface_set_activated(struct weston_desktop_surface *dsurface
 	if (surface->state.activated == activated)
 		return;
 
-	surface->requested_state.activated = activated;
+	surface->pending_state.activated = activated;
 	weston_desktop_xdg_surface_schedule_configure(surface);
 }
 
@@ -288,6 +291,42 @@ weston_desktop_xdg_surface_get_activated(struct weston_desktop_surface *dsurface
 	return surface->state.activated;
 }
 
+static bool
+weston_desktop_xdg_surface_get_pending_maximized(struct weston_desktop_surface *dsurface,
+						 void *user_data)
+{
+	struct weston_desktop_xdg_surface *surface = user_data;
+
+	return surface->pending_state.maximized;
+}
+
+static bool
+weston_desktop_xdg_surface_get_pending_fullscreen(struct weston_desktop_surface *dsurface,
+						  void *user_data)
+{
+	struct weston_desktop_xdg_surface *surface = user_data;
+
+	return surface->pending_state.fullscreen;
+}
+
+static bool
+weston_desktop_xdg_surface_get_pending_resizing(struct weston_desktop_surface *dsurface,
+						void *user_data)
+{
+	struct weston_desktop_xdg_surface *surface = user_data;
+
+	return surface->pending_state.resizing;
+}
+
+static bool
+weston_desktop_xdg_surface_get_pending_activated(struct weston_desktop_surface *dsurface,
+						 void *user_data)
+{
+	struct weston_desktop_xdg_surface *surface = user_data;
+
+	return surface->pending_state.activated;
+}
+
 static void
 weston_desktop_xdg_surface_destroy(struct weston_desktop_surface *dsurface,
 				   void *user_data)
@@ -415,7 +454,7 @@ weston_desktop_xdg_surface_protocol_ack_configure(struct wl_client *wl_client,
 	if (surface->configure_serial != serial)
 		return;
 
-	surface->next_state = surface->requested_state;
+	surface->next_state = surface->pending_state;
 }
 
 static void
@@ -540,6 +579,11 @@ static const struct weston_desktop_surface_implementation weston_desktop_xdg_sur
 	.get_resizing = weston_desktop_xdg_surface_get_resizing,
 	.get_activated = weston_desktop_xdg_surface_get_activated,
 
+	.get_pending_maximized = weston_desktop_xdg_surface_get_pending_maximized,
+	.get_pending_fullscreen = weston_desktop_xdg_surface_get_pending_fullscreen,
+	.get_pending_resizing = weston_desktop_xdg_surface_get_pending_resizing,
+	.get_pending_activated = weston_desktop_xdg_surface_get_pending_activated,
+
 	.destroy = weston_desktop_xdg_surface_destroy,
 };
 
diff --git a/libweston-desktop/xdg-shell-v6.c b/libweston-desktop/xdg-shell-v6.c
index 7d0bd8e4..df838170 100644
--- a/libweston-desktop/xdg-shell-v6.c
+++ b/libweston-desktop/xdg-shell-v6.c
@@ -88,7 +88,7 @@ struct weston_desktop_xdg_toplevel {
 		bool fullscreen;
 		bool resizing;
 		bool activated;
-	} requested_state, next_state, state;
+	} pending_state, next_state, state;
 	struct weston_size
 		next_max_size, max_size,
 		next_min_size, min_size;
@@ -413,7 +413,7 @@ weston_desktop_xdg_toplevel_protocol_resize(struct wl_client *wl_client,
 static void
 weston_desktop_xdg_toplevel_ack_configure(struct weston_desktop_xdg_toplevel *toplevel)
 {
-	toplevel->next_state = toplevel->requested_state;
+	toplevel->next_state = toplevel->pending_state;
 }
 
 static void
@@ -523,19 +523,19 @@ weston_desktop_xdg_toplevel_send_configure(struct weston_desktop_xdg_toplevel *t
 	struct wl_array states;
 
 	wl_array_init(&states);
-	if (toplevel->requested_state.maximized) {
+	if (toplevel->pending_state.maximized) {
 		s = wl_array_add(&states, sizeof(uint32_t));
 		*s = ZXDG_TOPLEVEL_V6_STATE_MAXIMIZED;
 	}
-	if (toplevel->requested_state.fullscreen) {
+	if (toplevel->pending_state.fullscreen) {
 		s = wl_array_add(&states, sizeof(uint32_t));
 		*s = ZXDG_TOPLEVEL_V6_STATE_FULLSCREEN;
 	}
-	if (toplevel->requested_state.resizing) {
+	if (toplevel->pending_state.resizing) {
 		s = wl_array_add(&states, sizeof(uint32_t));
 		*s = ZXDG_TOPLEVEL_V6_STATE_RESIZING;
 	}
-	if (toplevel->requested_state.activated) {
+	if (toplevel->pending_state.activated) {
 		s = wl_array_add(&states, sizeof(uint32_t));
 		*s = ZXDG_TOPLEVEL_V6_STATE_ACTIVATED;
 	}
@@ -557,7 +557,7 @@ weston_desktop_xdg_toplevel_set_maximized(struct weston_desktop_surface *dsurfac
 	if (toplevel->state.maximized == maximized)
 		return;
 
-	toplevel->requested_state.maximized = maximized;
+	toplevel->pending_state.maximized = maximized;
 	weston_desktop_xdg_surface_schedule_configure(&toplevel->base);
 }
 
@@ -570,7 +570,7 @@ weston_desktop_xdg_toplevel_set_fullscreen(struct weston_desktop_surface *dsurfa
 	if (toplevel->state.fullscreen == fullscreen)
 		return;
 
-	toplevel->requested_state.fullscreen = fullscreen;
+	toplevel->pending_state.fullscreen = fullscreen;
 	weston_desktop_xdg_surface_schedule_configure(&toplevel->base);
 }
 
@@ -583,7 +583,7 @@ weston_desktop_xdg_toplevel_set_resizing(struct weston_desktop_surface *dsurface
 	if (toplevel->state.resizing == resizing)
 		return;
 
-	toplevel->requested_state.resizing = resizing;
+	toplevel->pending_state.resizing = resizing;
 	weston_desktop_xdg_surface_schedule_configure(&toplevel->base);
 }
 
@@ -596,7 +596,7 @@ weston_desktop_xdg_toplevel_set_activated(struct weston_desktop_surface *dsurfac
 	if (toplevel->state.activated == activated)
 		return;
 
-	toplevel->requested_state.activated = activated;
+	toplevel->pending_state.activated = activated;
 	weston_desktop_xdg_surface_schedule_configure(&toplevel->base);
 }
 
@@ -694,6 +694,42 @@ weston_desktop_xdg_toplevel_get_activated(struct weston_desktop_surface *dsurfac
 	return toplevel->state.activated;
 }
 
+static bool
+weston_desktop_xdg_toplevel_get_pending_maximized(struct weston_desktop_surface *dsurface,
+						  void *user_data)
+{
+	struct weston_desktop_xdg_toplevel *toplevel = user_data;
+
+	return toplevel->pending_state.maximized;
+}
+
+static bool
+weston_desktop_xdg_toplevel_get_pending_fullscreen(struct weston_desktop_surface *dsurface,
+						   void *user_data)
+{
+	struct weston_desktop_xdg_toplevel *toplevel = user_data;
+
+	return toplevel->pending_state.fullscreen;
+}
+
+static bool
+weston_desktop_xdg_toplevel_get_pending_resizing(struct weston_desktop_surface *dsurface,
+						 void *user_data)
+{
+	struct weston_desktop_xdg_toplevel *toplevel = user_data;
+
+	return toplevel->pending_state.resizing;
+}
+
+static bool
+weston_desktop_xdg_toplevel_get_pending_activated(struct weston_desktop_surface *dsurface,
+						  void *user_data)
+{
+	struct weston_desktop_xdg_toplevel *toplevel = user_data;
+
+	return toplevel->pending_state.activated;
+}
+
 static void
 weston_desktop_xdg_toplevel_destroy(struct weston_desktop_xdg_toplevel *toplevel)
 {
@@ -851,6 +887,9 @@ weston_desktop_xdg_surface_send_configure(void *user_data)
 {
 	struct weston_desktop_xdg_surface *surface = user_data;
 
+	/* User is expected to call _set_size(), so we trigger it now so it
+	 * doesn’t schedule another configure event */
+	weston_desktop_api_size_requested(surface->desktop, surface->desktop_surface);
 	surface->configure_idle = NULL;
 	surface->configure_serial =
 		wl_display_next_serial(weston_desktop_get_display(surface->desktop));
@@ -1148,6 +1187,11 @@ static const struct weston_desktop_surface_implementation weston_desktop_xdg_sur
 	.get_resizing = weston_desktop_xdg_toplevel_get_resizing,
 	.get_activated = weston_desktop_xdg_toplevel_get_activated,
 
+	.get_pending_maximized = weston_desktop_xdg_toplevel_get_pending_maximized,
+	.get_pending_fullscreen = weston_desktop_xdg_toplevel_get_pending_fullscreen,
+	.get_pending_resizing = weston_desktop_xdg_toplevel_get_pending_resizing,
+	.get_pending_activated = weston_desktop_xdg_toplevel_get_pending_activated,
+
 	/* These are used for popup only */
 	.update_position = weston_desktop_xdg_popup_update_position,
 
diff --git a/libweston-desktop/xwayland.c b/libweston-desktop/xwayland.c
index b9843853..d2670e37 100644
--- a/libweston-desktop/xwayland.c
+++ b/libweston-desktop/xwayland.c
@@ -79,6 +79,8 @@ weston_desktop_xwayland_surface_change_state(struct weston_desktop_xwayland_surf
 
 	if (to_add && surface->added) {
 		surface->state = state;
+		weston_desktop_api_size_requested(surface->desktop,
+						  surface->surface);
 		return;
 	}
 
@@ -94,10 +96,14 @@ weston_desktop_xwayland_surface_change_state(struct weston_desktop_xwayland_surf
 			weston_surface_unmap(wsurface);
 		}
 
+		surface->state = state;
+
 		if (to_add) {
 			weston_desktop_surface_unset_relative_to(surface->surface);
 			weston_desktop_api_surface_added(surface->desktop,
 							 surface->surface);
+			weston_desktop_api_size_requested(surface->desktop,
+							  surface->surface);
 			surface->added = true;
 		} else if (surface->added) {
 			weston_desktop_api_surface_removed(surface->desktop,
@@ -116,8 +122,6 @@ weston_desktop_xwayland_surface_change_state(struct weston_desktop_xwayland_surf
 			surface->view->is_mapped = true;
 			wsurface->is_mapped = true;
 		}
-
-		surface->state = state;
 	}
 
 	if (parent != NULL)
@@ -202,6 +206,9 @@ static const struct weston_desktop_surface_implementation weston_desktop_xwaylan
 	.get_maximized = weston_desktop_xwayland_surface_get_maximized,
 	.get_fullscreen = weston_desktop_xwayland_surface_get_fullscreen,
 
+	.get_pending_maximized = weston_desktop_xwayland_surface_get_maximized,
+	.get_pending_fullscreen = weston_desktop_xwayland_surface_get_fullscreen,
+
 	.destroy = weston_desktop_xwayland_surface_destroy,
 };
 
-- 
2.11.1



More information about the wayland-devel mailing list