[PATCH 8/9] compositor: Handle background and panel surface in clone mode

Xiong Zhang xiong.y.zhang at intel.com
Thu Feb 13 23:17:43 PST 2014


The background and panel view of slave output can't exist on
layer_list and view_list, otherwise panel is mess.

When unplugging a master, one slave may become master, the slave's
background and panel view should be moved to view_list.

When plugging a master, one old master may become slave, the old
master's background and panel view should be removed from view_list

Signed-off-by: Xiong Zhang <xiong.y.zhang at intel.com>
---
 desktop-shell/shell.c | 70 +++++++++++++++++++++++++++++++++++++++++----------
 1 file changed, 57 insertions(+), 13 deletions(-)

diff --git a/desktop-shell/shell.c b/desktop-shell/shell.c
index 096d618..2bc1856 100644
--- a/desktop-shell/shell.c
+++ b/desktop-shell/shell.c
@@ -60,6 +60,8 @@ struct shell_output {
 	struct desktop_shell  *shell;
 	struct weston_output  *output;
 	uint32_t mark_dirty;
+	struct weston_view    *panel_view;
+	struct weston_view    *background_view;
 	struct wl_listener    role_change_listener;
 	struct wl_listener    destroy_listener;
 	struct wl_list        link;
@@ -2066,15 +2068,16 @@ static int
 get_output_panel_height(struct desktop_shell *shell,
 			struct weston_output *output)
 {
-	struct weston_view *view;
+	struct shell_output *shell_output;
 	int panel_height = 0;
 
 	if (!output)
 		return 0;
 
-	wl_list_for_each(view, &shell->panel_layer.view_list, layer_link) {
-		if (view->surface->output == output) {
-			panel_height = view->surface->height;
+	wl_list_for_each(shell_output, &shell->output_list, link) {
+		if (shell_output->output == output) {
+			panel_height =
+				shell_output->panel_view->surface->height;
 			break;
 		}
 	}
@@ -3654,7 +3657,8 @@ configure_static_view(struct weston_view *ev, struct weston_layer *layer)
 
 	weston_view_set_position(ev, ev->output->x, ev->output->y);
 
-	if (wl_list_empty(&ev->layer_link)) {
+	if (wl_list_empty(&ev->layer_link) &&
+	    !ev->output->is_slave) {
 		wl_list_insert(&layer->view_list, &ev->layer_link);
 		weston_compositor_schedule_repaint(ev->surface->compositor);
 	}
@@ -3681,6 +3685,7 @@ desktop_shell_set_background(struct wl_client *client,
 	struct weston_surface *surface =
 		wl_resource_get_user_data(surface_resource);
 	struct weston_view *view, *next;
+	struct shell_output *shell_output;
 
 	if (surface->configure) {
 		wl_resource_post_error(surface_resource,
@@ -3697,6 +3702,12 @@ desktop_shell_set_background(struct wl_client *client,
 	surface->configure_private = shell;
 	surface->output = wl_resource_get_user_data(output_resource);
 	view->output = surface->output;
+
+	wl_list_for_each(shell_output, &shell->output_list, link) {
+		if (shell_output->output == view->output)
+			shell_output->background_view = view;
+	}
+
 	desktop_shell_send_configure(resource, 0,
 				     surface_resource,
 				     surface->output->width,
@@ -3724,6 +3735,7 @@ desktop_shell_set_panel(struct wl_client *client,
 	struct weston_surface *surface =
 		wl_resource_get_user_data(surface_resource);
 	struct weston_view *view, *next;
+	struct shell_output *shell_output;
 
 	if (surface->configure) {
 		wl_resource_post_error(surface_resource,
@@ -3740,6 +3752,12 @@ desktop_shell_set_panel(struct wl_client *client,
 	surface->configure_private = shell;
 	surface->output = wl_resource_get_user_data(output_resource);
 	view->output = surface->output;
+
+	wl_list_for_each(shell_output, &shell->output_list, link) {
+		if (shell_output->output == view->output)
+			shell_output->panel_view = view;
+	}
+
 	desktop_shell_send_configure(resource, 0,
 				     surface_resource,
 				     surface->output->width,
@@ -5625,15 +5643,30 @@ handle_output_role_change(struct wl_listener *listener, void *data)
 		container_of(listener, struct shell_output,
 			     role_change_listener);
 	struct weston_output *output = (struct weston_output *)data;
+	struct desktop_shell *shell = shell_output->shell;
 
 	/* Output change from master to slave. */
-	if (output->is_slave)
+	if (output->is_slave) {
+		wl_list_remove(&shell_output->background_view->layer_link);
+		wl_list_init(&shell_output->background_view->layer_link);
+		wl_list_remove(&shell_output->panel_view->layer_link);
+		wl_list_init(&shell_output->panel_view->layer_link);
+
 		/* Mark views on this old master as dirty.
 		 * But we will use new master as target output,
 		 * At this point, new master doesn't have panel view
 		 * and background view. So the desktop shell doesn't ready.
 		 * So we delay the mark dirty work until desktop shell ready. */
 		shell_output->mark_dirty = 1;
+	} else {
+		/* Output change from slave to master. */
+		wl_list_insert(&shell->background_layer.view_list,
+			       &shell_output->background_view->layer_link);
+		wl_list_insert(&shell->panel_layer.view_list,
+			       &shell_output->panel_view->layer_link);
+
+		output->repaint_scheduled = 0;
+	}
 }
 
 static void
@@ -5734,6 +5767,24 @@ shell_destroy(struct wl_listener *listener, void *data)
 	struct workspace **ws;
 	struct shell_output *shell_output, *tmp;
 
+	wl_list_for_each_safe(shell_output, tmp, &shell->output_list, link) {
+		/* Restore slave output's panel view and background view to
+		 * correct layer, otherwise when client destroy slave output's
+		 * panel surface and background surface, segment failure will
+		 * happen in weston_view_destroy(). */
+		if (wl_list_empty(&shell_output->background_view->layer_link))
+			wl_list_insert(&shell->background_layer.view_list,
+				&shell_output->background_view->layer_link);
+		if (wl_list_empty(&shell_output->panel_view->layer_link))
+			wl_list_insert(&shell->panel_layer.view_list,
+				       &shell_output->panel_view->layer_link);
+
+		wl_list_remove(&shell_output->destroy_listener.link);
+		wl_list_remove(&shell_output->role_change_listener.link);
+		wl_list_remove(&shell_output->link);
+		free(shell_output);
+	}
+
 	/* Force state to unlocked so we don't try to fade */
 	shell->locked = false;
 	if (shell->child.client)
@@ -5744,13 +5795,6 @@ shell_destroy(struct wl_listener *listener, void *data)
 
 	input_panel_destroy(shell);
 
-	wl_list_for_each_safe(shell_output, tmp, &shell->output_list, link) {
-		wl_list_remove(&shell_output->destroy_listener.link);
-		wl_list_remove(&shell_output->role_change_listener.link);
-		wl_list_remove(&shell_output->link);
-		free(shell_output);
-	}
-
 	wl_list_remove(&shell->output_create_listener.link);
 
 	wl_array_for_each(ws, &shell->workspaces.array)
-- 
1.8.3.2



More information about the wayland-devel mailing list