[PATCH weston] xwm: let the shells decide the position of X windows

Giulio Camuffo giuliocamuffo at gmail.com
Sat Apr 11 09:11:34 PDT 2015


The xwm used to automatically send to Xwayland the position of X windows
when that changed, using the x,y of the primary view of the surface.
This works fine for the desktop shell but less so for others.
This patch adds a 'send_position' vfunc to the weston_shell_client that
the shell will call when it wants to let Xwayland know what the position
of a window is.
The logic used by the desktop-shell for that is exactly the same the xwm
used to have.
---
 desktop-shell/shell.c     | 40 ++++++++++++++++++------
 desktop-shell/shell.h     |  1 +
 src/compositor.h          |  4 +--
 xwayland/window-manager.c | 77 +++++++++++++++++++++--------------------------
 xwayland/xwayland.h       |  1 -
 5 files changed, 66 insertions(+), 57 deletions(-)

diff --git a/desktop-shell/shell.c b/desktop-shell/shell.c
index f7c928e..8d0c716 100644
--- a/desktop-shell/shell.c
+++ b/desktop-shell/shell.c
@@ -1859,7 +1859,8 @@ send_configure(struct weston_surface *surface, int32_t width, int32_t height)
 }
 
 static const struct weston_shell_client shell_client = {
-	send_configure
+	send_configure,
+	NULL
 };
 
 static void
@@ -3688,12 +3689,6 @@ create_shell_surface(void *shell, struct weston_surface *surface,
 	return create_common_surface(NULL, shell, surface, client);
 }
 
-static struct weston_view *
-get_primary_view(void *shell, struct shell_surface *shsurf)
-{
-	return shsurf->view;
-}
-
 static void
 shell_get_shell_surface(struct wl_client *client,
 			struct wl_resource *resource,
@@ -3978,7 +3973,8 @@ xdg_send_configure(struct weston_surface *surface,
 }
 
 static const struct weston_shell_client xdg_client = {
-	xdg_send_configure
+	xdg_send_configure,
+	NULL
 };
 
 static void
@@ -4084,7 +4080,8 @@ xdg_popup_send_configure(struct weston_surface *surface,
 }
 
 static const struct weston_shell_client xdg_popup_client = {
-	xdg_popup_send_configure
+	xdg_popup_send_configure,
+	NULL
 };
 
 static struct shell_surface *
@@ -5395,6 +5392,27 @@ wake_handler(struct wl_listener *listener, void *data)
 }
 
 static void
+transform_handler(struct wl_listener *listener, void *data)
+{
+	struct weston_surface *surface = data;
+	struct shell_surface *shsurf = get_shell_surface(surface);
+	struct weston_view *view;;
+	int x, y;
+
+	if (!shsurf || !shsurf->client->send_position)
+		return;
+
+	view = shsurf->view;
+	if (!view || !weston_view_is_mapped(view))
+		return;
+
+	x = view->geometry.x;
+	y = view->geometry.y;
+
+	shsurf->client->send_position(surface, x, y);
+}
+
+static void
 center_on_output(struct weston_view *view, struct weston_output *output)
 {
 	int32_t surf_x, surf_y, width, height;
@@ -6454,6 +6472,7 @@ shell_destroy(struct wl_listener *listener, void *data)
 
 	wl_list_remove(&shell->idle_listener.link);
 	wl_list_remove(&shell->wake_listener.link);
+	wl_list_remove(&shell->transform_listener.link);
 
 	input_panel_destroy(shell);
 
@@ -6595,10 +6614,11 @@ module_init(struct weston_compositor *ec,
 	wl_signal_add(&ec->idle_signal, &shell->idle_listener);
 	shell->wake_listener.notify = wake_handler;
 	wl_signal_add(&ec->wake_signal, &shell->wake_listener);
+	shell->transform_listener.notify = transform_handler;
+	wl_signal_add(&ec->transform_signal, &shell->transform_listener);
 
 	ec->shell_interface.shell = shell;
 	ec->shell_interface.create_shell_surface = create_shell_surface;
-	ec->shell_interface.get_primary_view = get_primary_view;
 	ec->shell_interface.set_toplevel = set_toplevel;
 	ec->shell_interface.set_transient = set_transient;
 	ec->shell_interface.set_fullscreen = shell_interface_set_fullscreen;
diff --git a/desktop-shell/shell.h b/desktop-shell/shell.h
index 2cfd1d6..f4e2e89 100644
--- a/desktop-shell/shell.h
+++ b/desktop-shell/shell.h
@@ -120,6 +120,7 @@ struct desktop_shell {
 
 	struct wl_listener idle_listener;
 	struct wl_listener wake_listener;
+	struct wl_listener transform_listener;
 	struct wl_listener destroy_listener;
 	struct wl_listener show_input_panel_listener;
 	struct wl_listener hide_input_panel_listener;
diff --git a/src/compositor.h b/src/compositor.h
index 5f49237..784ec80 100644
--- a/src/compositor.h
+++ b/src/compositor.h
@@ -91,6 +91,7 @@ struct weston_mode {
 
 struct weston_shell_client {
 	void (*send_configure)(struct weston_surface *surface, int32_t width, int32_t height);
+	void (*send_position)(struct weston_surface *surface, int32_t x, int32_t y);
 };
 
 struct weston_shell_interface {
@@ -99,9 +100,6 @@ struct weston_shell_interface {
 	struct shell_surface *(*create_shell_surface)(void *shell,
 						      struct weston_surface *surface,
 						      const struct weston_shell_client *client);
-	struct weston_view *(*get_primary_view)(void *shell,
-						struct shell_surface *shsurf);
-
 	void (*set_toplevel)(struct shell_surface *shsurf);
 
 	void (*set_transient)(struct shell_surface *shsurf,
diff --git a/xwayland/window-manager.c b/xwayland/window-manager.c
index cab7e20..db32fd7 100644
--- a/xwayland/window-manager.c
+++ b/xwayland/window-manager.c
@@ -124,7 +124,6 @@ struct weston_wm_window {
 	uint32_t surface_id;
 	struct weston_surface *surface;
 	struct shell_surface *shsurf;
-	struct weston_view *view;
 	struct wl_listener surface_destroy_listener;
 	struct wl_event_source *repaint_source;
 	struct wl_event_source *configure_source;
@@ -138,6 +137,7 @@ struct weston_wm_window {
 	xcb_atom_t type;
 	int width, height;
 	int x, y;
+	int pos_dirty;
 	int saved_width, saved_height;
 	int decorate;
 	int override_redirect;
@@ -676,6 +676,8 @@ weston_wm_handle_configure_notify(struct weston_wm *wm, xcb_generic_event_t *eve
 
 	window->x = configure_notify->x;
 	window->y = configure_notify->y;
+	window->pos_dirty = 0;
+
 	if (window->override_redirect) {
 		window->width = configure_notify->width;
 		window->height = configure_notify->height;
@@ -775,32 +777,6 @@ weston_wm_window_activate(struct wl_listener *listener, void *data)
 	}
 }
 
-static void
-weston_wm_window_transform(struct wl_listener *listener, void *data)
-{
-	struct weston_surface *surface = data;
-	struct weston_wm_window *window = get_wm_window(surface);
-	struct weston_wm *wm =
-		container_of(listener, struct weston_wm, transform_listener);
-	uint32_t mask, values[2];
-
-	if (!window || !wm)
-		return;
-
-	if (!window->view || !weston_view_is_mapped(window->view))
-		return;
-
-	if (window->x != window->view->geometry.x ||
-	    window->y != window->view->geometry.y) {
-		values[0] = window->view->geometry.x;
-		values[1] = window->view->geometry.y;
-		mask = XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y;
-
-		xcb_configure_window(wm->conn, window->frame_id, mask, values);
-		xcb_flush(wm->conn);
-	}
-}
-
 #define ICCCM_WITHDRAWN_STATE	0
 #define ICCCM_NORMAL_STATE	1
 #define ICCCM_ICONIC_STATE	3
@@ -1015,7 +991,6 @@ weston_wm_handle_unmap_notify(struct weston_wm *wm, xcb_generic_event_t *event)
 		wl_list_remove(&window->surface_destroy_listener.link);
 	window->surface = NULL;
 	window->shsurf = NULL;
-	window->view = NULL;
 
 	weston_wm_window_set_wm_state(window, ICCCM_WITHDRAWN_STATE);
 	weston_wm_window_set_virtual_desktop(window, -1);
@@ -1035,6 +1010,7 @@ weston_wm_window_draw_decoration(void *data)
 	struct weston_shell_interface *shell_interface =
 		&wm->server->compositor->shell_interface;
 	uint32_t flags = 0;
+	struct weston_view *view;
 
 	weston_wm_window_read_properties(window);
 
@@ -1076,8 +1052,8 @@ weston_wm_window_draw_decoration(void *data)
 						  window->width + 2,
 						  window->height + 2);
 		}
-		if (window->view)
-			weston_view_geometry_dirty(window->view);
+		wl_list_for_each(view, &window->surface->views, surface_link)
+			weston_view_geometry_dirty(view);
 
 		pixman_region32_fini(&window->surface->pending.input);
 
@@ -1103,6 +1079,7 @@ static void
 weston_wm_window_schedule_repaint(struct weston_wm_window *window)
 {
 	struct weston_wm *wm = window->wm;
+	struct weston_view *view;
 	int width, height;
 
 	if (window->frame_id == XCB_WINDOW_NONE) {
@@ -1115,8 +1092,8 @@ weston_wm_window_schedule_repaint(struct weston_wm_window *window)
 				pixman_region32_init_rect(&window->surface->pending.opaque, 0, 0,
 							  width, height);
 			}
-			if (window->view)
-				weston_view_geometry_dirty(window->view);
+			wl_list_for_each(view, &window->surface->views, surface_link)
+				weston_view_geometry_dirty(view);
 		}
 		return;
 	}
@@ -1182,6 +1159,7 @@ weston_wm_window_create(struct weston_wm *wm,
 	window->height = height;
 	window->x = x;
 	window->y = y;
+	window->pos_dirty = 0;
 
 	geometry_reply = xcb_get_geometry_reply(wm->conn, geometry_cookie, NULL);
 	/* technically we should use XRender and check the visual format's
@@ -1477,7 +1455,6 @@ surface_destroy(struct wl_listener *listener, void *data)
 	 * Don't try to use it later. */
 	window->shsurf = NULL;
 	window->surface = NULL;
-	window->view = NULL;
 }
 
 static void
@@ -2242,9 +2219,6 @@ weston_wm_create(struct weston_xserver *wxs, int fd)
 	wm->activate_listener.notify = weston_wm_window_activate;
 	wl_signal_add(&wxs->compositor->activate_signal,
 		      &wm->activate_listener);
-	wm->transform_listener.notify = weston_wm_window_transform;
-	wl_signal_add(&wxs->compositor->transform_signal,
-		      &wm->transform_listener);
 	wm->kill_listener.notify = weston_wm_kill_client;
 	wl_signal_add(&wxs->compositor->kill_signal,
 		      &wm->kill_listener);
@@ -2273,7 +2247,6 @@ weston_wm_destroy(struct weston_wm *wm)
 	wl_list_remove(&wm->selection_listener.link);
 	wl_list_remove(&wm->activate_listener.link);
 	wl_list_remove(&wm->kill_listener.link);
-	wl_list_remove(&wm->transform_listener.link);
 	wl_list_remove(&wm->create_surface_listener.link);
 
 	free(wm);
@@ -2364,8 +2337,31 @@ send_configure(struct weston_surface *surface, int32_t width, int32_t height)
 				       weston_wm_window_configure, window);
 }
 
+static void
+send_position(struct weston_surface *surface, int32_t x, int32_t y)
+{
+	struct weston_wm_window *window = get_wm_window(surface);
+	struct weston_wm *wm = window->wm;
+	uint32_t mask, values[2];
+
+	/* We use pos_dirty to tell whether a configure message is in flight.
+	 * This is needed in case we send two configure events in a very
+	 * short time, since window->x/y is set in after a roundtrip, hence
+	 * we cannot just check if the current x and y are different. */
+	if (window->x != x || window->y != y || window->pos_dirty) {
+		window->pos_dirty = 1;
+		values[0] = x;
+		values[1] = y;
+		mask = XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y;
+
+		xcb_configure_window(wm->conn, window->frame_id, mask, values);
+		xcb_flush(wm->conn);
+	}
+}
+
 static const struct weston_shell_client shell_client = {
-	send_configure
+	send_configure,
+	send_position
 };
 
 static int
@@ -2455,9 +2451,6 @@ xserver_map_shell_surface(struct weston_wm_window *window,
 	if (!shell_interface->create_shell_surface)
 		return;
 
-	if (!shell_interface->get_primary_view)
-		return;
-
 	if (window->surface->configure) {
 		weston_log("warning, unexpected in %s: "
 			   "surface's configure hook is already set.\n",
@@ -2469,8 +2462,6 @@ xserver_map_shell_surface(struct weston_wm_window *window,
 		shell_interface->create_shell_surface(shell_interface->shell,
 						      window->surface,
 						      &shell_client);
-	window->view = shell_interface->get_primary_view(shell_interface->shell,
-							 window->shsurf);
 
 	if (window->name)
 		shell_interface->set_title(window->shsurf, window->name);
diff --git a/xwayland/xwayland.h b/xwayland/xwayland.h
index 54cbf6d..80ba0e1 100644
--- a/xwayland/xwayland.h
+++ b/xwayland/xwayland.h
@@ -67,7 +67,6 @@ struct weston_wm {
 	xcb_colormap_t colormap;
 	struct wl_listener create_surface_listener;
 	struct wl_listener activate_listener;
-	struct wl_listener transform_listener;
 	struct wl_listener kill_listener;
 	struct wl_list unpaired_window_list;
 
-- 
2.3.5



More information about the wayland-devel mailing list