[PATCH 2/3] shell: restore app on default and unplugged output

Xiong Zhang xiong.y.zhang at intel.com
Mon Dec 2 19:25:05 PST 2013


if the unplugged output is the first default output, the second
output will move to the first working as default output. Mark
the surface on unplaugged output as dirty, so on the next output
repaint, these views will reassign output and get the right
output.
when we move output, the views on moved output should be moved also.
Because of the page flip intervention, the weston_output_destroy()
maybe asynchronous with update_outputs(). So we should change
moving following outputs to output_destroy handler.

Signed-off-by: Xiong Zhang <xiong.y.zhang at intel.com>
---
 src/compositor-drm.c |  8 -----
 src/compositor.c     | 18 +++++++++++
 src/shell.c          | 88 ++++++++++++++++++++++++++++++++++++----------------
 3 files changed, 80 insertions(+), 34 deletions(-)

diff --git a/src/compositor-drm.c b/src/compositor-drm.c
index c34fc1c..158a05f 100644
--- a/src/compositor-drm.c
+++ b/src/compositor-drm.c
@@ -2223,7 +2223,6 @@ update_outputs(struct drm_compositor *ec, struct udev_device *drm_device)
 	drmModeRes *resources;
 	struct drm_output *output, *next;
 	int x = 0, y = 0;
-	int x_offset = 0, y_offset = 0;
 	uint32_t connected = 0, disconnects = 0;
 	int i;
 
@@ -2273,17 +2272,10 @@ update_outputs(struct drm_compositor *ec, struct udev_device *drm_device)
 	if (disconnects) {
 		wl_list_for_each_safe(output, next, &ec->base.output_list,
 				      base.link) {
-			if (x_offset != 0 || y_offset != 0) {
-				weston_output_move(&output->base,
-						 output->base.x - x_offset,
-						 output->base.y - y_offset);
-			}
-
 			if (disconnects & (1 << output->connector_id)) {
 				disconnects &= ~(1 << output->connector_id);
 				weston_log("connector %d disconnected\n",
 				       output->connector_id);
-				x_offset += output->base.width;
 				drm_output_destroy(&output->base);
 			}
 		}
diff --git a/src/compositor.c b/src/compositor.c
index 32e72b1..246b02b 100644
--- a/src/compositor.c
+++ b/src/compositor.c
@@ -3128,6 +3128,13 @@ weston_output_transform_scale_init(struct weston_output *output, uint32_t transf
 WL_EXPORT void
 weston_output_move(struct weston_output *output, int x, int y)
 {
+	struct weston_view *view;
+	struct weston_layer *layer;
+	int offset_x, offset_y;
+
+	offset_x = x - output->x;
+	offset_y = y - output->y;
+
 	output->x = x;
 	output->y = y;
 
@@ -3135,6 +3142,17 @@ weston_output_move(struct weston_output *output, int x, int y)
 	pixman_region32_init_rect(&output->region, x, y,
 				  output->width,
 				  output->height);
+	output->dirty = 1;
+
+	wl_list_for_each(layer, &output->compositor->layer_list, link) {
+		wl_list_for_each(view, &layer->view_list, layer_link) {
+			if (view->output == output &&
+				view->geometry.parent == NULL)
+				weston_view_set_position(view,
+						view->geometry.x + offset_x,
+						view->geometry.y + offset_y);
+		}
+	}
 }
 
 WL_EXPORT void
diff --git a/src/shell.c b/src/shell.c
index 16d22f1..3cf87fd 100644
--- a/src/shell.c
+++ b/src/shell.c
@@ -6084,11 +6084,17 @@ clamp_coordinate(struct weston_output *target_output,
 	return result;
 }
 
+/* if destroyed output is default output, marking views on this output */
+/* are dirty, so the next repaint will assign a new output to these views */
+/* if destroyed output isn't default output, move views on this output */
+/* to default output */
 static void
 handle_view_on_destroyed_output(struct weston_view *view,
-					struct weston_output *target_output)
+					struct weston_output *target_output,
+					unsigned int move)
 {
 	float new_x, new_y, original_x, original_y;
+	int result;
 
 	/* the child window's view->geometry is a relative coordinate to */
 	/* parent view, no need to move child_view */
@@ -6098,17 +6104,23 @@ handle_view_on_destroyed_output(struct weston_view *view,
 	original_x = view->geometry.x;
 	original_y = view->geometry.y;
 
-	clamp_coordinate(target_output, view->output,
-			&original_x, &original_y);
+	result = clamp_coordinate(target_output, view->output,
+				&original_x, &original_y);
 
-	new_x = target_output->x + original_x - view->output->x;
-	new_y = target_output->y + original_y - view->output->y;
-	weston_view_set_position(view, new_x, new_y);
+	if (move) {
+		new_x = target_output->x + original_x - view->output->x;
+		new_y = target_output->y + original_y - view->output->y;
+		weston_view_set_position(view, new_x, new_y);
+	} else if (result)
+		weston_view_set_position(view, original_x, original_y);
+	else
+		weston_view_geometry_dirty(view);
 }
 
 static void
 normal_view_on_destroyed_output(struct shell_output *shell_output,
-						struct weston_output *target_output)
+						struct weston_output *target_output,
+						unsigned int move)
 {
 	struct weston_output *del_output = shell_output->output;
 	struct desktop_shell *shell = shell_output->shell;
@@ -6142,7 +6154,8 @@ normal_view_on_destroyed_output(struct shell_output *shell_output,
 
 static void
 full_screen_view_on_destroyed_output(struct shell_output *shell_output,
-						struct weston_output *target_output)
+						struct weston_output *target_output,
+						unsigned int move)
 {
 	struct weston_output *del_output = shell_output->output;
 	struct desktop_shell *shell = shell_output->shell;
@@ -6155,7 +6168,7 @@ full_screen_view_on_destroyed_output(struct shell_output *shell_output,
 	wl_list_for_each(view, &shell->fullscreen_layer.view_list, layer_link) {
 		/* fullscreen.black_view followed fullscreen.view */
 		if (shsurf && shsurf->fullscreen.black_view == view) {
-			handle_view_on_destroyed_output(view, target_output);
+			handle_view_on_destroyed_output(view, target_output, move);
 			weston_view_configure(view, target_output->x, target_output->y,
 								target_output->width, target_output->height);
 			pixman_region32_fini(&view->surface->opaque);
@@ -6168,7 +6181,7 @@ full_screen_view_on_destroyed_output(struct shell_output *shell_output,
 		}
 		shsurf = get_shell_surface(view->surface);
 		if (shsurf->fullscreen_output == del_output) {
-			handle_view_on_destroyed_output(view, target_output);
+			handle_view_on_destroyed_output(view, target_output, move);
 			shsurf->type = SHELL_SURFACE_NONE;
 			set_fullscreen(shsurf,
 						   shsurf->fullscreen.type,
@@ -6180,7 +6193,8 @@ full_screen_view_on_destroyed_output(struct shell_output *shell_output,
 
 static void
 pointer_on_destroyed_output(struct shell_output *shell_output,
-					struct weston_output *target_output)
+					struct weston_output *target_output,
+					unsigned int move)
 {
 	struct weston_output *del_output = shell_output->output;
 	struct weston_compositor *wc = del_output->compositor;
@@ -6205,12 +6219,15 @@ pointer_on_destroyed_output(struct shell_output *shell_output,
 			pointer->x = wl_fixed_from_double(pointer_x);
 			pointer->y = wl_fixed_from_double(pointer_y);
 		}
-		dx = wl_fixed_from_int(target_output->x - del_output->x);
-		dy = wl_fixed_from_int(target_output->y - del_output->y);
-		pointer->x += dx;
-		pointer->y += dy;
+		if (move) {
+			dx = wl_fixed_from_int(target_output->x - del_output->x);
+			dy = wl_fixed_from_int(target_output->y - del_output->y);
+			pointer->x += dx;
+			pointer->y += dy;
+		}
 		if (pointer->sprite)
-			handle_view_on_destroyed_output(pointer->sprite, target_output);
+			handle_view_on_destroyed_output(pointer->sprite,
+							target_output, move);
 		pointer->grab->interface->focus(pointer->grab);
 		resource_list = &pointer->focus_resource_list;
 		wl_resource_for_each(resource, resource_list) {
@@ -6231,22 +6248,41 @@ handle_output_destroy(struct wl_listener *listener, void *data)
 		container_of(listener, struct shell_output, destroy_listener);
 	struct weston_output *output = (struct weston_output *)data;
 	struct weston_compositor *wc = output->compositor;
-	struct weston_output *default_output, *target_output = NULL;
+	struct weston_output *default_output, *target_output = NULL, *tmp;
+	unsigned int move;
+	int x_offset = 0, y_offset = 0;
 
 	default_output = get_default_output(wc);
-	/* if default output is the only output in output_list, or destroyed
-	   output is default output, return*/
-	if ((default_output->link.prev == default_output->link.next) ||
-		(default_output == output))
+	/* if default output is the only output in output_list, return*/
+	if (default_output->link.prev == default_output->link.next)
 		goto exit_handler;
 
-	target_output = default_output;
+	if (default_output != output) {
+		target_output = default_output;
+		move = 1;
+	} else {
+		target_output = container_of(output->link.next,
+					struct weston_output, link);
+		move = 0;
+	}
+
+	normal_view_on_destroyed_output(shell_output, target_output, move);
+	full_screen_view_on_destroyed_output(shell_output, target_output, move);
+	pointer_on_destroyed_output(shell_output, target_output, move);
 
-	normal_view_on_destroyed_output(shell_output, target_output);
-	full_screen_view_on_destroyed_output(shell_output, target_output);
-	pointer_on_destroyed_output(shell_output, target_output);
+	if (move)
+		weston_output_schedule_repaint(target_output);
 
-	weston_output_schedule_repaint(target_output);
+	/* move the following output */
+	wl_list_for_each(tmp, &wc->output_list, link) {
+		if (x_offset != 0 || y_offset != 0) {
+			weston_output_move(tmp,
+				tmp->x - x_offset, tmp->y - y_offset);
+			weston_output_damage(tmp);
+		}
+		if (tmp == output)
+			x_offset = output->width;
+	}
 
 exit_handler:
 	wl_list_remove(&shell_output->destroy_listener.link);
-- 
1.8.3.2



More information about the wayland-devel mailing list