[RFC weston] xwayland: Implement support for programmatically maximizing views

Iliya Bozhinov iliyabo at hotmail.com
Sun Jun 25 11:21:51 UTC 2017


Currently the xwayland implementation of desktop surfaces doesn't do
anything when weston_desktop_surface_set_maximized/fullscreen() is called.
In order to support this, we have to add xwayland internal interfaces
for sending those requests to the xwayland window. Also, a xwayland desktop
surface states need to be handled better - the current way of assigning a
single state to each surface doesn't work - for example, if a view was
maximized, then fullscreen and then unfullscreened, we would lose the
maximized state. That's why this code handles states as bit masks of the
states.

Signed-off-by: Ilia Bozhinov <iliyabo at hotmail.com>
---
 libweston-desktop/xwayland.c           | 74 +++++++++++++++++++++++-----------
 xwayland/window-manager.c              | 24 +++++++++++
 xwayland/xwayland-internal-interface.h |  2 +
 3 files changed, 77 insertions(+), 23 deletions(-)

diff --git a/libweston-desktop/xwayland.c b/libweston-desktop/xwayland.c
index 4f4b453f..8a105537 100644
--- a/libweston-desktop/xwayland.c
+++ b/libweston-desktop/xwayland.c
@@ -38,12 +38,12 @@
 #include "xwayland/xwayland-internal-interface.h"
 
 enum weston_desktop_xwayland_surface_state {
-	NONE,
-	TOPLEVEL,
-	MAXIMIZED,
-	FULLSCREEN,
-	TRANSIENT,
-	XWAYLAND,
+	NONE = 0,
+	TOPLEVEL = 1 << 0,
+	MAXIMIZED = 1 << 1,
+	FULLSCREEN = 1 << 2,
+	TRANSIENT = 1 << 3,
+	XWAYLAND = 1 << 4,
 };
 
 struct weston_desktop_xwayland {
@@ -178,7 +178,7 @@ weston_desktop_xwayland_surface_destroy(struct weston_desktop_surface *dsurface,
 	if (surface->added)
 		weston_desktop_api_surface_removed(surface->desktop,
 						   surface->surface);
-	else if (surface->state == XWAYLAND)
+	else if (surface->state & XWAYLAND)
 		weston_desktop_surface_unlink_view(surface->view);
 
 	free(surface);
@@ -190,7 +190,25 @@ weston_desktop_xwayland_surface_get_maximized(struct weston_desktop_surface *dsu
 {
 	struct weston_desktop_xwayland_surface *surface = user_data;
 
-	return surface->state == MAXIMIZED;
+	return surface->state & MAXIMIZED;
+}
+
+static void
+weston_desktop_xwayland_surface_set_maximized(struct weston_desktop_surface *dsurface,
+		void *user_data, bool maximized)
+{
+	struct weston_desktop_xwayland_surface *surface = user_data;
+	struct weston_surface *wsurface =
+		weston_desktop_surface_get_surface(surface->surface);
+
+	if (surface->state & FULLSCREEN)
+		return;
+
+	surface->client_interface->send_maximized(wsurface, maximized);
+	if (maximized)
+		surface->state |= MAXIMIZED;
+	else
+		surface->state &= ~MAXIMIZED;
 }
 
 static bool
@@ -199,7 +217,22 @@ weston_desktop_xwayland_surface_get_fullscreen(struct weston_desktop_surface *ds
 {
 	struct weston_desktop_xwayland_surface *surface = user_data;
 
-	return surface->state == FULLSCREEN;
+	return surface->state & FULLSCREEN;
+}
+
+static void
+weston_desktop_xwayland_surface_set_fullscreen(struct weston_desktop_surface *dsurface,
+		void *user_data, bool fullscreen)
+{
+	struct weston_desktop_xwayland_surface *surface = user_data;
+	struct weston_surface *wsurface =
+		weston_desktop_surface_get_surface(surface->surface);
+
+	surface->client_interface->send_maximized(wsurface, fullscreen);
+	if (fullscreen)
+		surface->state |= FULLSCREEN;
+	else
+		surface->state &= ~FULLSCREEN;
 }
 
 static const struct weston_desktop_surface_implementation weston_desktop_xwayland_surface_internal_implementation = {
@@ -207,7 +240,9 @@ static const struct weston_desktop_surface_implementation weston_desktop_xwaylan
 	.set_size = weston_desktop_xwayland_surface_set_size,
 
 	.get_maximized = weston_desktop_xwayland_surface_get_maximized,
+	.set_maximized = weston_desktop_xwayland_surface_set_maximized,
 	.get_fullscreen = weston_desktop_xwayland_surface_get_fullscreen,
+	.set_fullscreen = weston_desktop_xwayland_surface_set_fullscreen,
 
 	.destroy = weston_desktop_xwayland_surface_destroy,
 };
@@ -260,16 +295,15 @@ create_surface(struct weston_desktop_xwayland *xwayland,
 static void
 set_toplevel(struct weston_desktop_xwayland_surface *surface)
 {
-	weston_desktop_xwayland_surface_change_state(surface, TOPLEVEL, NULL,
-						     0, 0);
+	surface->state |= TOPLEVEL;
+	surface->state &= ~(MAXIMIZED | FULLSCREEN);
 }
 
 static void
 set_toplevel_with_position(struct weston_desktop_xwayland_surface *surface,
 			   int32_t x, int32_t y)
 {
-	weston_desktop_xwayland_surface_change_state(surface, TOPLEVEL, NULL,
-						     0, 0);
+	set_toplevel(surface);
 	weston_desktop_api_set_xwayland_position(surface->desktop,
 						 surface->surface, x, y);
 }
@@ -305,8 +339,7 @@ static void
 set_fullscreen(struct weston_desktop_xwayland_surface *surface,
 	       struct weston_output *output)
 {
-	weston_desktop_xwayland_surface_change_state(surface, FULLSCREEN, NULL,
-						     0, 0);
+	surface->state |= FULLSCREEN;
 	weston_desktop_api_fullscreen_requested(surface->desktop,
 						surface->surface, true, output);
 }
@@ -322,9 +355,7 @@ static int
 move(struct weston_desktop_xwayland_surface *surface,
      struct weston_pointer *pointer)
 {
-	if (surface->state == TOPLEVEL ||
-	    surface->state == MAXIMIZED ||
-	    surface->state == FULLSCREEN)
+	if (surface->state & (TOPLEVEL | MAXIMIZED | FULLSCREEN))
 		weston_desktop_api_move(surface->desktop, surface->surface,
 					pointer->seat, pointer->grab_serial);
 	return 0;
@@ -334,9 +365,7 @@ static int
 resize(struct weston_desktop_xwayland_surface *surface,
        struct weston_pointer *pointer, uint32_t edges)
 {
-	if (surface->state == TOPLEVEL ||
-	    surface->state == MAXIMIZED ||
-	    surface->state == FULLSCREEN)
+	if (surface->state & (TOPLEVEL | MAXIMIZED | FULLSCREEN))
 		weston_desktop_api_resize(surface->desktop, surface->surface,
 					  pointer->seat, pointer->grab_serial,
 					  edges);
@@ -363,8 +392,7 @@ set_window_geometry(struct weston_desktop_xwayland_surface *surface,
 static void
 set_maximized(struct weston_desktop_xwayland_surface *surface)
 {
-	weston_desktop_xwayland_surface_change_state(surface, MAXIMIZED, NULL,
-						     0, 0);
+	surface->state |= MAXIMIZED;
 	weston_desktop_api_maximized_requested(surface->desktop,
 					       surface->surface, true);
 }
diff --git a/xwayland/window-manager.c b/xwayland/window-manager.c
index 13acc84e..ef07a7cd 100644
--- a/xwayland/window-manager.c
+++ b/xwayland/window-manager.c
@@ -2617,8 +2617,32 @@ send_position(struct weston_surface *surface, int32_t x, int32_t y)
 	}
 }
 
+static void send_maximized(struct weston_surface *surface, bool maximized)
+{
+	struct weston_wm_window *window = get_wm_window(surface);
+
+	if (window->maximized_horz == maximized &&
+	    window->maximized_vert == maximized)
+		return;
+
+	window->maximized_horz = window->maximized_vert = maximized;
+	weston_wm_window_set_net_wm_state(window);
+}
+
+static void send_fullscreen(struct weston_surface *surface, bool fullscreen)
+{
+	struct weston_wm_window *window = get_wm_window(surface);
+	if (window->fullscreen == fullscreen)
+		return;
+
+	window->fullscreen = fullscreen;
+	weston_wm_window_set_net_wm_state(window);
+}
+
 static const struct weston_xwayland_client_interface shell_client = {
 	send_configure,
+	send_maximized,
+	send_fullscreen
 };
 
 static int
diff --git a/xwayland/xwayland-internal-interface.h b/xwayland/xwayland-internal-interface.h
index 10964440..48716b14 100644
--- a/xwayland/xwayland-internal-interface.h
+++ b/xwayland/xwayland-internal-interface.h
@@ -31,6 +31,8 @@ struct weston_desktop_xwayland_surface;
 
 struct weston_xwayland_client_interface {
 	void (*send_configure)(struct weston_surface *surface, int32_t width, int32_t height);
+	void (*send_maximized)(struct weston_surface *surface, bool maximized);
+	void (*send_fullscreen)(struct weston_surface *surface, bool fullscreen);
 };
 
 struct weston_desktop_xwayland_interface {
-- 
2.13.0



More information about the wayland-devel mailing list