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

Ander Conselvan de Oliveira conselvan2 at gmail.com
Tue Dec 3 07:26:26 PST 2013


On 12/03/2013 05:25 AM, Xiong Zhang wrote:
> 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.

Building up on the idea on my previous email - were we would have an 
output_destroyed() callback for the view which receives the new output 
the view should be in - I think we could avoid having different logic 
for the case where the first output is removed. Instead, we could move 
the outputs position before calling the callback, so when it calculates 
the new position for the view that would be final.

It sounds like we still need to delay weston_output_move() in the drm 
backend, so that would be split into a separate patch.


Ander


> 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);
>



More information about the wayland-devel mailing list