[RFC weston] compositor: Implement runtime output transform changes

Derek Foreman derekf at osg.samsung.com
Wed Jan 17 20:25:26 UTC 2018


On 2017-06-26 06:23 AM, Ilia Bozhinov wrote:
> From: Ilia Bozhinov <iliyabo at hotmail.com>
> 
> Up to now we could set the transform only on output initialization.
> However, on certain situations(like tablets and convertible laptops),
> screen orientation can change while the compositor is running and thus
> the need for change of the output transform arises.
> 
> When the transform changes, we must update the output geometry,
> output->region and output->previous_damage, as well as send this change
> to clients. We also have to check whether any of the pointers are inside
> the output which is being rotated. If this is the case, they are moved
> to the new center, because otherwise the pointer is stuck outside of the
> screen ans "lost" to the user.
> 
> What is more, after calling this function compositors should check if
> any view is now outside of the screen and move it according to their
> wish.
> 
> Signed-off-by: Ilia Bozhinov <iliyabo at hotmail.com>
> ---
>   libweston/compositor.c | 65 +++++++++++++++++++++++++++++++++++++++++++-------
>   1 file changed, 57 insertions(+), 8 deletions(-)
> 
> diff --git a/libweston/compositor.c b/libweston/compositor.c
> index 2a3074db..ca77bdfc 100644
> --- a/libweston/compositor.c
> +++ b/libweston/compositor.c
> @@ -4587,9 +4587,6 @@ weston_output_set_scale(struct weston_output *output,
>    * \param output    The weston_output object that the transform is set for.
>    * \param transform Transform value for the given output.
>    *
> - * It only supports setting transform for an output that is
> - * not enabled and it can only be ran once.
> - *
>    * Refer to wl_output::transform section located at
>    * https://wayland.freedesktop.org/docs/html/apa.html#protocol-spec-wl_output
>    * for list of values that can be passed to this function.
> @@ -4598,13 +4595,65 @@ WL_EXPORT void
>   weston_output_set_transform(struct weston_output *output,
>   			    uint32_t transform)
>   {
> -	/* We can only set transform on a disabled output */
> -	assert(!output->enabled);
> +	struct weston_pointer_motion_event ev;
> +	struct wl_resource *resource;
> +	struct weston_seat *seat;
> +	pixman_region32_t old_region;
> +	int mid_x, mid_y;
> +
> +	if (!output->enabled && output->transform == UINT32_MAX) {
> +		output->transform = transform;
> +		return;
> +	}
>   
> -	/* We only want to set transform once */
> -	assert(output->transform == UINT32_MAX);
> +	if (transform == output->transform)
> +		return;
>   
> -	output->transform = transform;
> +	weston_output_transform_scale_init(output, transform, output->scale);
> +
> +	pixman_region32_init(&old_region);
> +	pixman_region32_copy(&old_region, &output->region);
> +
> +	pixman_region32_fini(&output->region);
> +	pixman_region32_fini(&output->previous_damage);
> +
> +	weston_output_init_geometry(output, output->x, output->y);
> +
> +	output->dirty = 1;
> +
> +	/* Notify clients of the change for output transform. */
> +	wl_resource_for_each(resource, &output->resource_list) {
> +		wl_output_send_geometry(resource,
> +					output->x,
> +					output->y,
> +					output->mm_width,
> +					output->mm_height,
> +					output->subpixel,
> +					output->make,
> +					output->model,
> +					output->transform);
> +
> +		if (wl_resource_get_version(resource) >= WL_OUTPUT_DONE_SINCE_VERSION)
> +			wl_output_send_done(resource);
> +	}

Some of the above looks like it could maybe be refactored and shared 
with weston_output_move?

Otherwise this looks fine to me:

Reviewed-by: Derek Foreman <derekf at osg.samsung.com>

Daniel, you singled this out for review - does that count as an Ack?

Thanks,
Derek

> +
> +	/* we must ensure that pointers are inside output, otherwise they disappear */
> +	mid_x = output->x + output->width / 2;
> +	mid_y = output->y + output->height / 2;
> +
> +	ev.mask = WESTON_POINTER_MOTION_ABS;
> +	ev.x = wl_fixed_to_double(wl_fixed_from_int(mid_x));
> +	ev.y = wl_fixed_to_double(wl_fixed_from_int(mid_y));
> +
> +	wl_list_for_each(seat, &output->compositor->seat_list, link) {
> +		struct weston_pointer *pointer = weston_seat_get_pointer(seat);
> +
> +		if (pointer && pixman_region32_contains_point(&old_region,
> +							      wl_fixed_to_int(pointer->x),
> +							      wl_fixed_to_int(pointer->y),
> +							      NULL))
> +			weston_pointer_move(pointer, &ev);
> +	}
>   }
>   
>   /** Initializes a weston_output object with enough data so
> 



More information about the wayland-devel mailing list