[PATCH] xwayland: Implement support for programmatically maximizing views

Ilia Bozhinov ammen99 at gmail.com
Mon Jun 26 10:03:09 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. We should also be careful when mapping surfaces in MAXIMIZED
state(v2)

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

diff --git a/libweston-desktop/xwayland.c b/libweston-desktop/xwayland.c
index 4f4b453f..f0e91ab9 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 {
@@ -62,7 +62,7 @@ struct weston_desktop_xwayland_surface {
 	struct weston_geometry next_geometry;
 	bool has_next_geometry;
 	bool added;
-	enum weston_desktop_xwayland_surface_state state;
+	uint32_t state;
 };
 
 static void
@@ -78,7 +78,7 @@ weston_desktop_xwayland_surface_change_state(struct weston_desktop_xwayland_surf
 	assert(!parent || state == TRANSIENT);
 
 	if (to_add && surface->added) {
-		surface->state = state;
+		surface->state |= state;
 		return;
 	}
 
@@ -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,30 @@ 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) {
+		weston_desktop_xwayland_surface_change_state(surface, MAXIMIZED, NULL,
+							     0, 0);
+	} else {
+		surface->state &= ~MAXIMIZED;
+		if (surface->state == NONE)
+			weston_desktop_xwayland_surface_change_state(surface, TOPLEVEL,
+								     NULL, 0, 0);
+	}
 }
 
 static bool
@@ -199,7 +222,27 @@ 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_fullscreen(wsurface, fullscreen);
+	if (fullscreen) {
+		weston_desktop_xwayland_surface_change_state(surface, FULLSCREEN,
+				                             NULL, 0, 0);
+	} else {
+		surface->state &= ~FULLSCREEN;
+		if (surface->state == NONE)
+			weston_desktop_xwayland_surface_change_state(surface, TOPLEVEL,
+								     NULL, 0, 0);
+	}
 }
 
 static const struct weston_desktop_surface_implementation weston_desktop_xwayland_surface_internal_implementation = {
@@ -207,7 +250,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,
 };
@@ -262,14 +307,14 @@ set_toplevel(struct weston_desktop_xwayland_surface *surface)
 {
 	weston_desktop_xwayland_surface_change_state(surface, TOPLEVEL, NULL,
 						     0, 0);
+	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);
 }
@@ -322,9 +367,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 +377,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);
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