[PATCH] shell: moving drag surface refine

Kristian Høgsberg hoegsberg at gmail.com
Fri Jul 27 07:47:41 PDT 2012


On Fri, Jul 27, 2012 at 02:58:50AM -0700, juan.j.zhao at linux.intel.com wrote:
> From: Juan Zhao <juan.j.zhao at linux.intel.com>
> 
> When applications not directly based on toytoolkit, like simple-egl, efl
> applications is grabbed and moved, they may be moved to the place under
> the panel. Then they could not be grabbed again.
> Don't allow the pointer's bounding box move across the desktop's viewport.

This is good, but it doesn't work for multiple monitors.  I think we
need a different strategy for supporting multiple outputs.  The
outputs are rectangles laid out in the global coordinate system
(output->x/y and output->current->width/height).  Here's what I think
should work: we add a new shell->active_region to weston_compositor,
and pixman_region32_union all the outputs into that union and then
subtract all the panel rectangles.  It won't change very often so we
can just keep that in desktop_shell and update it on monitor hotplug
or resolution changes.

To see if we can move a surface, we intersect the bounding box for the
surface with shell->active_region and look at the boxes in the
intersection.  If all boxes are below a minimum width we cancel the
horizontal movement (set dx = es->geometry.x).  If all boxes are below
a certain height we cancel the vertical movement.

It's a slightly different heuristics than the bounding box you
implemented below, but I think it works better.  The bounding box
approach will restrict motion event though there may be plenty of
surface left on the screen to grab later.  The region intersect
approach just makes sure there's always a minimum amount of surface on
the screen.

Kristian

> Signed-off-by: Juan Zhao <juan.j.zhao at linux.intel.com>
> ---
>  src/shell.c | 34 ++++++++++++++++++++++++++++++++++
>  1 file changed, 34 insertions(+)
> 
> diff --git a/src/shell.c b/src/shell.c
> index a9e4d4f..b85f3f6 100644
> --- a/src/shell.c
> +++ b/src/shell.c
> @@ -221,6 +221,13 @@ get_shell_surface(struct weston_surface *surface);
>  static struct desktop_shell *
>  shell_surface_get_shell(struct shell_surface *shsurf);
>  
> +static int
> +get_output_panel_height(struct desktop_shell *shell,
> +                        struct weston_output *output);
> +
> +static struct weston_output *
> +get_default_output(struct weston_compositor *compositor);
> +
>  static bool
>  shell_surface_is_top_fullscreen(struct shell_surface *shsurf)
>  {
> @@ -784,13 +791,40 @@ move_grab_motion(struct wl_pointer_grab *grab,
>  	struct wl_pointer *pointer = grab->pointer;
>  	struct shell_surface *shsurf = move->base.shsurf;
>  	struct weston_surface *es;
> +	struct desktop_shell *shell = NULL;
>  	int dx = wl_fixed_to_int(pointer->x + move->dx);
>  	int dy = wl_fixed_to_int(pointer->y + move->dy);
> +	int bounding_x, bounding_y, view_x, view_y, view_w, view_h, panel_height;
> +	int ncx = 0, ncy = 0;
> +	int boxsize = 10;
>  
>  	if (!shsurf)
>  		return;
>  
>  	es = shsurf->surface;
> +	shsurf->output = shsurf->output ? shsurf->output
> +			     : get_default_output(es->compositor);
> +	shell = shell_surface_get_shell(shsurf);
> +	panel_height = get_output_panel_height(shell, shsurf->output);
> +
> +	weston_surface_from_global(es, wl_fixed_to_int(pointer->x),
> +				   wl_fixed_to_int(pointer->y),
> +				   &ncx, &ncy);
> +	ncx -= boxsize>>1;
> +	ncy -= boxsize>>1;
> +
> +	bounding_x = dx + (ncx>0?ncx:0);
> +	bounding_y = dy + (ncy>0?ncy:0);
> +
> +	view_x = 0;
> +	view_y = panel_height;
> +	view_w = shsurf->output->current->width;
> +	view_h = shsurf->output->current->height - panel_height;
> +
> +	if ( !(bounding_x >= view_x && bounding_y >= view_y &&
> +	       bounding_x + boxsize <= view_x + view_w &&
> +	       bounding_y + boxsize <= view_y + view_h) )
> +	    return;
>  
>  	weston_surface_configure(es, dx, dy,
>  				 es->geometry.width, es->geometry.height);
> -- 
> 1.7.11
> 


More information about the wayland-devel mailing list