[RFC v4] Introduce output zoom.

Kristian Hoegsberg hoegsberg at gmail.com
Thu Feb 23 14:54:25 PST 2012


On Wed, Feb 22, 2012 at 02:21:41PM -0700, Scott Moreau wrote:
> Ideally, we would want to use <modifier>+Scroll binding but that will have
> to wait for axis events. For now we just use keybindings. Zoom in/out with
> Super+Up/Down.

Applied with a minor edit to really fix the code-before-declaration
thing.  With your change we still end up with

weston_output_update_zoom(struct weston_output *output, int x, int y)
{
	if (output->zoom.level <= 0)
  		return;
  
  	float ratio;
	...  

That is, the ratio variable is declared after the if statement.
That's what we don't want.

Anyway, enough nit-picking, it works well where, but we need to fix
the binding issue.  We need to swallow the key press that triggers the
binding and we also need to swallow the corresponding key up.  What
I've been thinking is that we could let the binding handler return a
value to indicate whether or not to swallow the event.  The tricky
part is going to be swallowing the release event, since that may come
many key events later.  We could just maintain a per-device list of
"keys that are down, and we need to swallow the release event", but
that's kinda gross.  I don't really think there's a nicer way though.
And all this applies to pointer buttons as well.

Kristian


> ---
>  src/compositor.c |   68 ++++++++++++++++++++++++++++++++++++++++++++++--------
>  src/compositor.h |   14 +++++++++++
>  src/shell.c      |   48 ++++++++++++++++++++++++++++++++++++++
>  3 files changed, 120 insertions(+), 10 deletions(-)
> 
> diff --git a/src/compositor.c b/src/compositor.c
> index 5a424fa..1566753 100644
> --- a/src/compositor.c
> +++ b/src/compositor.c
> @@ -743,7 +743,7 @@ weston_surface_draw(struct weston_surface *es, struct weston_output *output)
>  	glUniform1f(es->shader->texwidth_uniform,
>  		    (GLfloat)es->geometry.width / es->pitch);
>  
> -	if (es->transform.enabled)
> +	if (es->transform.enabled || output->zoom.active)
>  		filter = GL_LINEAR;
>  	else
>  		filter = GL_NEAREST;
> @@ -979,6 +979,9 @@ weston_output_repaint(struct weston_output *output, int msecs)
>  					 &total_damage, &es->transform.opaque);
>  	}
>  
> +	if (output->dirty)
> +		weston_output_update_matrix(output);
> +
>  	output->repaint(output);
>  
>  	pixman_region32_fini(&total_damage);
> @@ -1341,6 +1344,11 @@ notify_motion(struct wl_input_device *device, uint32_t time, int x, int y)
>  	device->x = x;
>  	device->y = y;
>  
> +	wl_list_for_each(output, &ec->output_list, link)
> +		if (output->zoom.active &&
> +		    pixman_region32_contains_point(&output->region, x, y, NULL))
> +			weston_output_update_zoom(output, x, y);
> +
>  	weston_device_repick(device, time);
>  	interface = device->pointer_grab->interface;
>  	interface->motion(device->pointer_grab, time,
> @@ -1941,17 +1949,29 @@ weston_output_destroy(struct weston_output *output)
>  }
>  
>  WL_EXPORT void
> -weston_output_move(struct weston_output *output, int x, int y)
> +weston_output_update_zoom(struct weston_output *output, int x, int y)
>  {
> -	int flip;
> +	if (output->zoom.level <= 0)
> +		return;
>  
> -	output->x = x;
> -	output->y = y;
> +	float ratio;
>  
> -	pixman_region32_init(&output->previous_damage);
> -	pixman_region32_init_rect(&output->region, x, y, 
> -				  output->current->width,
> -				  output->current->height);
> +	output->zoom.magnification = 1 / output->zoom.level;
> +	ratio = 1 - (1 / output->zoom.magnification);
> +
> +	output->zoom.trans_x = (((float)(x - output->x) / output->current->width) * (ratio * 2)) - ratio;
> +	output->zoom.trans_y = (((float)(y - output->y) / output->current->height) * (ratio * 2)) - ratio;
> +
> +	output->dirty = 1;
> +	weston_output_damage(output);
> +}
> +
> +WL_EXPORT void
> +weston_output_update_matrix(struct weston_output *output)
> +{
> +	int flip;
> +	struct weston_matrix camera;
> +	struct weston_matrix modelview;
>  
>  	weston_matrix_init(&output->matrix);
>  	weston_matrix_translate(&output->matrix,
> @@ -1962,8 +1982,28 @@ weston_output_move(struct weston_output *output, int x, int y)
>  	weston_matrix_scale(&output->matrix,
>  			    2.0 / (output->current->width + output->border.left + output->border.right),
>  			    flip * 2.0 / (output->current->height + output->border.top + output->border.bottom), 1);
> +	if (output->zoom.active) {
> +		weston_matrix_init(&camera);
> +		weston_matrix_init(&modelview);
> +		weston_matrix_translate(&camera, output->zoom.trans_x, flip * output->zoom.trans_y, 0);
> +		weston_matrix_invert(&modelview, &camera);
> +		weston_matrix_scale(&modelview, output->zoom.magnification, output->zoom.magnification, 1.0);
> +		weston_matrix_multiply(&output->matrix, &modelview);
> +	}
>  
> -	weston_output_damage(output);
> +	output->dirty = 0;
> +}
> +
> +WL_EXPORT void
> +weston_output_move(struct weston_output *output, int x, int y)
> +{
> +	output->x = x;
> +	output->y = y;
> +
> +	pixman_region32_init(&output->previous_damage);
> +	pixman_region32_init_rect(&output->region, x, y,
> +				  output->current->width,
> +				  output->current->height);
>  }
>  
>  WL_EXPORT void
> @@ -1979,6 +2019,14 @@ weston_output_init(struct weston_output *output, struct weston_compositor *c,
>  	output->border.right = 0;
>  	output->mm_width = width;
>  	output->mm_height = height;
> +	output->dirty = 1;
> +
> +	output->zoom.active = 0;
> +	output->zoom.increment = 0.05;
> +	output->zoom.level = 1.0;
> +	output->zoom.magnification = 1.0;
> +	output->zoom.trans_x = 0.0;
> +	output->zoom.trans_y = 0.0;
>  
>  	output->flags = flags;
>  	weston_output_move(output, x, y);
> diff --git a/src/compositor.h b/src/compositor.h
> index 4c82e79..a11ca45 100644
> --- a/src/compositor.h
> +++ b/src/compositor.h
> @@ -54,6 +54,14 @@ struct weston_border {
>  	int32_t left, right, top, bottom;
>  };
>  
> +struct weston_output_zoom {
> +	int active;
> +	float increment;
> +	float level;
> +	float magnification;
> +	float trans_x, trans_y;
> +};
> +
>  struct weston_output {
>  	struct wl_list link;
>  	struct weston_compositor *compositor;
> @@ -66,6 +74,8 @@ struct weston_output {
>  	uint32_t flags;
>  	int repaint_needed;
>  	int repaint_scheduled;
> +	struct weston_output_zoom zoom;
> +	int dirty;
>  
>  	char *make, *model;
>  	uint32_t subpixel;
> @@ -414,6 +424,10 @@ weston_compositor_init(struct weston_compositor *ec, struct wl_display *display)
>  void
>  weston_compositor_shutdown(struct weston_compositor *ec);
>  void
> +weston_output_update_zoom(struct weston_output *output, int x, int y);
> +void
> +weston_output_update_matrix(struct weston_output *output);
> +void
>  weston_output_move(struct weston_output *output, int x, int y);
>  void
>  weston_output_init(struct weston_output *output, struct weston_compositor *c,
> diff --git a/src/shell.c b/src/shell.c
> index 3d5dfd9..36b0c9e 100644
> --- a/src/shell.c
> +++ b/src/shell.c
> @@ -1035,6 +1035,50 @@ resize_binding(struct wl_input_device *device, uint32_t time,
>  }
>  
>  static void
> +zoom_in_binding(struct wl_input_device *device, uint32_t time,
> +	       uint32_t key, uint32_t button, uint32_t state, void *data)
> +{
> +	struct weston_input_device *wd = (struct weston_input_device *) device;
> +	struct weston_compositor *compositor = wd->compositor;
> +	struct weston_output *output;
> +
> +	wl_list_for_each(output, &compositor->output_list, link) {
> +		if (pixman_region32_contains_point(&output->region,
> +						device->x, device->y, NULL)) {
> +			output->zoom.active = 1;
> +			output->zoom.level -= output->zoom.increment;
> +
> +			if (output->zoom.level < output->zoom.increment)
> +				output->zoom.level = output->zoom.increment;
> +
> +			weston_output_update_zoom(output, device->x, device->y);
> +		}
> +	}
> +}
> +
> +static void
> +zoom_out_binding(struct wl_input_device *device, uint32_t time,
> +	       uint32_t key, uint32_t button, uint32_t state, void *data)
> +{
> +	struct weston_input_device *wd = (struct weston_input_device *) device;
> +	struct weston_compositor *compositor = wd->compositor;
> +	struct weston_output *output;
> +
> +	wl_list_for_each(output, &compositor->output_list, link) {
> +		if (pixman_region32_contains_point(&output->region,
> +						device->x, device->y, NULL)) {
> +			output->zoom.level += output->zoom.increment;
> +			if (output->zoom.level >= 1.0) {
> +				output->zoom.active = 0;
> +				output->zoom.level = 1.0;
> +			}
> +
> +			weston_output_update_zoom(output, device->x, device->y);
> +		}
> +	}
> +}
> +
> +static void
>  terminate_binding(struct wl_input_device *device, uint32_t time,
>  		  uint32_t key, uint32_t button, uint32_t state, void *data)
>  {
> @@ -1832,6 +1876,10 @@ shell_init(struct weston_compositor *ec)
>  				    terminate_binding, ec);
>  	weston_compositor_add_binding(ec, 0, BTN_LEFT, 0,
>  				    click_to_activate_binding, ec);
> +	weston_compositor_add_binding(ec, KEY_UP, 0, MODIFIER_SUPER,
> +				    zoom_in_binding, shell);
> +	weston_compositor_add_binding(ec, KEY_DOWN, 0, MODIFIER_SUPER,
> +				    zoom_out_binding, shell);
>  	weston_compositor_add_binding(ec, 0, BTN_LEFT,
>  				      MODIFIER_SUPER | MODIFIER_ALT,
>  				      rotate_binding, NULL);
> -- 
> 1.7.4.1
> 
> _______________________________________________
> wayland-devel mailing list
> wayland-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/wayland-devel


More information about the wayland-devel mailing list