[PATCH weston] shell: Fix view repositioning logic for output move and destroy

Ander Conselvan de Oliveira conselvan2 at gmail.com
Fri Apr 11 03:57:15 PDT 2014


From: Ander Conselvan de Oliveira <ander.conselvan.de.oliveira at intel.com>

Previously, the repositioning logic would iterate the compositor's list
of layers and move the views on those layers. However, that failed in
two different ways: it didn't cover hidden workspaces and crashed when
the display was locked.

This patch changes the logic to explicit iterate over all the layers
owned by the shell. The iteration is done through a helper function,
shell_for_each_layer().

https://bugs.freedesktop.org/show_bug.cgi?id=76859
https://bugs.freedesktop.org/show_bug.cgi?id=77290
---
 desktop-shell/shell.c | 84 ++++++++++++++++++++++++++++-----------------------
 desktop-shell/shell.h |  8 +++++
 2 files changed, 54 insertions(+), 38 deletions(-)

diff --git a/desktop-shell/shell.c b/desktop-shell/shell.c
index 63b4d4c..130618c 100644
--- a/desktop-shell/shell.c
+++ b/desktop-shell/shell.c
@@ -5740,27 +5740,35 @@ shell_reposition_view_on_output_destroy(struct weston_view *view)
 	}
 }
 
+void
+shell_for_each_layer(struct desktop_shell *shell,
+		     shell_for_each_layer_func_t func, void *data)
+{
+	struct workspace **ws;
+
+	func(shell, &shell->fullscreen_layer, data);
+	func(shell, &shell->panel_layer, data);
+	func(shell, &shell->background_layer, data);
+	func(shell, &shell->lock_layer, data);
+	func(shell, &shell->input_panel_layer, data);
+
+	wl_array_for_each(ws, &shell->workspaces.array)
+		func(shell, &(*ws)->layer, data);
+}
+
 static void
-shell_reposition_views_on_output_destroy(struct shell_output *shell_output)
+shell_output_destroy_move_layer(struct desktop_shell *shell,
+				struct weston_layer *layer,
+				void *data)
 {
-	struct desktop_shell *shell = shell_output->shell;
-	struct weston_output *output = shell_output->output;
-	struct weston_layer *layer;
+	struct weston_output *output = data;
 	struct weston_view *view;
 
-	/* Move all views in the layers owned by the shell */
-	wl_list_for_each(layer, shell->fullscreen_layer.link.prev, link) {
-		wl_list_for_each(view, &layer->view_list, layer_link) {
-			if (view->output != output)
-				continue;
-
-			shell_reposition_view_on_output_destroy(view);
-		}
+	wl_list_for_each(view, &layer->view_list, layer_link) {
+		if (view->output != output)
+			continue;
 
-		/* We don't start from the beggining of the layer list, so
-		 * make sure we don't wrap around it. */
-		if (layer == &shell->background_layer)
-			break;
+		shell_reposition_view_on_output_destroy(view);
 	}
 }
 
@@ -5769,8 +5777,10 @@ handle_output_destroy(struct wl_listener *listener, void *data)
 {
 	struct shell_output *output_listener =
 		container_of(listener, struct shell_output, destroy_listener);
+	struct weston_output *output = output_listener->output;
+	struct desktop_shell *shell = output_listener->shell;
 
-	shell_reposition_views_on_output_destroy(output_listener);
+	shell_for_each_layer(shell, shell_output_destroy_move_layer, output);
 
 	wl_list_remove(&output_listener->destroy_listener.link);
 	wl_list_remove(&output_listener->link);
@@ -5806,34 +5816,32 @@ handle_output_create(struct wl_listener *listener, void *data)
 }
 
 static void
-handle_output_move(struct wl_listener *listener, void *data)
+handle_output_move_layer(struct desktop_shell *shell,
+			 struct weston_layer *layer, void *data)
 {
-	struct desktop_shell *shell;
-	struct weston_output *output;
-	struct weston_layer *layer;
+	struct weston_output *output = data;
 	struct weston_view *view;
 	float x, y;
 
-	shell = container_of(listener, struct desktop_shell,
-			     output_move_listener);
-	output = data;
+	wl_list_for_each(view, &layer->view_list, layer_link) {
+		if (view->output != output)
+			continue;
 
-	/* Move all views in the layers owned by the shell */
-	wl_list_for_each(layer, shell->fullscreen_layer.link.prev, link) {
-		wl_list_for_each(view, &layer->view_list, layer_link) {
-			if (view->output != output)
-				continue;
+		x = view->geometry.x + output->move_x;
+		y = view->geometry.y + output->move_y;
+		weston_view_set_position(view, x, y);
+	}
+}
 
-			x = view->geometry.x + output->move_x;
-			y = view->geometry.y + output->move_y;
-			weston_view_set_position(view, x, y);
-		}
+static void
+handle_output_move(struct wl_listener *listener, void *data)
+{
+	struct desktop_shell *shell;
 
-		/* We don't start from the beggining of the layer list, so
-		 * make sure we don't wrap around it. */
-		if (layer == &shell->background_layer)
-			break;
-	}
+	shell = container_of(listener, struct desktop_shell,
+			     output_move_listener);
+
+	shell_for_each_layer(shell, handle_output_move_layer, data);
 }
 
 static void
diff --git a/desktop-shell/shell.h b/desktop-shell/shell.h
index 5d127c6..4ed11d5 100644
--- a/desktop-shell/shell.h
+++ b/desktop-shell/shell.h
@@ -236,3 +236,11 @@ int
 input_panel_setup(struct desktop_shell *shell);
 void
 input_panel_destroy(struct desktop_shell *shell);
+
+typedef void (*shell_for_each_layer_func_t)(struct desktop_shell *,
+					    struct weston_layer *, void *);
+
+void
+shell_for_each_layer(struct desktop_shell *shell,
+		     shell_for_each_layer_func_t func,
+		     void *data);
-- 
1.8.3.2



More information about the wayland-devel mailing list