[PATCH 2/2 v3] shell: account for the subsurfaces when going fullscreen or maximizing
Pekka Paalanen
ppaalanen at gmail.com
Tue Feb 26 23:45:52 PST 2013
On Tue, 26 Feb 2013 16:24:32 +0100
Giulio Camuffo <giuliocamuffo at gmail.com> wrote:
> We must calculate the bounding box of the surface + subsurfaces set and use
> that when maximizing the window or going fullscreen.
> ---
> src/shell.c | 89 ++++++++++++++++++++++++++++++++++++++++++++++---------------
> 1 file changed, 68 insertions(+), 21 deletions(-)
>
> diff --git a/src/shell.c b/src/shell.c
> index da41efa..d9ebfd4 100644
> --- a/src/shell.c
> +++ b/src/shell.c
> @@ -1183,6 +1183,41 @@ static const struct wl_pointer_grab_interface resize_grab_interface = {
> resize_grab_button,
> };
>
> +/*
> + * Returns the bounding box of a surface and all its sub-surfaces,
> + * in the surface coordinates system. */
> +static void
> +surface_subsurfaces_boundingbox(struct weston_surface *surface, int32_t *x,
> + int32_t *y, int32_t *w, int32_t *h) {
> + pixman_region32_t region;
> + pixman_box32_t *box;
> + struct weston_subsurface *subsurface;
> +
> + pixman_region32_init_rect(®ion, 0, 0,
> + surface->geometry.width,
> + surface->geometry.height);
> +
> + wl_list_for_each(subsurface, &surface->subsurface_list, parent_link) {
> + pixman_region32_union_rect(®ion, ®ion,
> + subsurface->position.x,
> + subsurface->position.y,
> + subsurface->surface->geometry.width,
> + subsurface->surface->geometry.height);
> + }
> +
> + box = pixman_region32_extents(®ion);
> + if (x)
> + *x = box->x1;
> + if (y)
> + *y = box->y1;
> + if (w)
> + *w = box->x2 - box->x1;
> + if (h)
> + *h = box->y2 - box->y1;
> +
> + pixman_region32_fini(®ion);
> +}
> +
> static int
> surface_resize(struct shell_surface *shsurf,
> struct weston_seat *ws, uint32_t edges)
> @@ -1201,8 +1236,8 @@ surface_resize(struct shell_surface *shsurf,
> return -1;
>
> resize->edges = edges;
> - resize->width = shsurf->surface->geometry.width;
> - resize->height = shsurf->surface->geometry.height;
> + surface_subsurfaces_boundingbox(shsurf->surface, NULL, NULL,
> + &resize->width, &resize->height);
>
> shell_grab_start(&resize->base, &resize_grab_interface, shsurf,
> ws->seat.pointer, edges);
> @@ -1688,6 +1723,7 @@ shell_configure_fullscreen(struct shell_surface *shsurf)
> struct weston_surface *surface = shsurf->surface;
> struct weston_matrix *matrix;
> float scale, output_aspect, surface_aspect, x, y;
> + int32_t surf_x, surf_y, surf_width, surf_height;
>
> if (!shsurf->fullscreen.black_surface)
> shsurf->fullscreen.black_surface =
> @@ -1702,6 +1738,9 @@ shell_configure_fullscreen(struct shell_surface *shsurf)
> &shsurf->fullscreen.black_surface->layer_link);
> shsurf->fullscreen.black_surface->output = output;
>
> + surface_subsurfaces_boundingbox(surface, &surf_x, &surf_y,
> + &surf_width, &surf_height);
> +
> switch (shsurf->fullscreen.type) {
> case WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT:
> if (surface->buffer_ref.buffer)
> @@ -1709,9 +1748,10 @@ shell_configure_fullscreen(struct shell_surface *shsurf)
> break;
> case WL_SHELL_SURFACE_FULLSCREEN_METHOD_SCALE:
> /* 1:1 mapping between surface and output dimensions */
> - if (output->width == surface->geometry.width &&
> - output->height == surface->geometry.height) {
> - weston_surface_set_position(surface, output->x, output->y);
> + if (output->width == surf_width &&
> + output->height == surf_height) {
> + weston_surface_set_position(surface, output->x - surf_x,
> + output->y - surf_y);
> break;
> }
>
> @@ -1724,33 +1764,33 @@ shell_configure_fullscreen(struct shell_surface *shsurf)
> (float) surface->geometry.height;
> if (output_aspect < surface_aspect)
> scale = (float) output->width /
> - (float) surface->geometry.width;
> + (float) surf_width;
> else
> scale = (float) output->height /
> - (float) surface->geometry.height;
> + (float) surf_height;
>
> weston_matrix_scale(matrix, scale, scale, 1);
> wl_list_remove(&shsurf->fullscreen.transform.ptr.link);
> wl_list_insert(&surface->geometry.transformation_list,
> &shsurf->fullscreen.transform.ptr.link);
> - x = output->x + (output->width - surface->geometry.width * scale) / 2;
> - y = output->y + (output->height - surface->geometry.height * scale) / 2;
> + x = output->x + (output->width - surf_width * scale) / 2 - surf_x;
> + y = output->y + (output->height - surf_height * scale) / 2 - surf_y;
> weston_surface_set_position(surface, x, y);
>
> break;
> case WL_SHELL_SURFACE_FULLSCREEN_METHOD_DRIVER:
> if (shell_surface_is_top_fullscreen(shsurf)) {
> struct weston_mode mode = {0,
> - surface->geometry.width,
> - surface->geometry.height,
> + surf_width,
> + surf_height,
> shsurf->fullscreen.framerate};
>
> if (weston_output_switch_mode(output, &mode) == 0) {
> weston_surface_configure(shsurf->fullscreen.black_surface,
> - output->x, output->y,
> + output->x - surf_x,
> + output->y - surf_y,
> output->width,
> output->height);
> - weston_surface_set_position(surface, output->x, output->y);
> break;
> }
> }
> @@ -3001,12 +3041,13 @@ hide_input_panels(struct wl_listener *listener, void *data)
> static void
> center_on_output(struct weston_surface *surface, struct weston_output *output)
> {
> - int32_t width = weston_surface_buffer_width(surface);
> - int32_t height = weston_surface_buffer_height(surface);
> + int32_t surf_x, surf_y, width, height;
> float x, y;
>
> - x = output->x + (output->width - width) / 2;
> - y = output->y + (output->height - height) / 2;
> + surface_subsurfaces_boundingbox(surface, &surf_x, &surf_y, &width, &height);
> +
> + x = output->x + (output->width - width) / 2 - surf_x / 2;
> + y = output->y + (output->height - height) / 2 - surf_y / 2;
>
> weston_surface_configure(surface, x, y, width, height);
> }
> @@ -3084,6 +3125,7 @@ map(struct desktop_shell *shell, struct weston_surface *surface,
> struct weston_seat *seat;
> struct workspace *ws;
> int panel_height = 0;
> + int32_t surf_x, surf_y;
>
> surface->geometry.width = width;
> surface->geometry.height = height;
> @@ -3101,8 +3143,10 @@ map(struct desktop_shell *shell, struct weston_surface *surface,
> case SHELL_SURFACE_MAXIMIZED:
> /* use surface configure to set the geometry */
> panel_height = get_output_panel_height(shell,surface->output);
> - weston_surface_set_position(surface, shsurf->output->x,
> - shsurf->output->y + panel_height);
> + surface_subsurfaces_boundingbox(shsurf->surface, &surf_x, &surf_y,
> + NULL, NULL);
> + weston_surface_set_position(surface, shsurf->output->x - surf_x,
> + shsurf->output->y + panel_height - surf_y);
> break;
> case SHELL_SURFACE_POPUP:
> shell_map_popup(shsurf);
> @@ -3176,6 +3220,7 @@ configure(struct desktop_shell *shell, struct weston_surface *surface,
> {
> enum shell_surface_type surface_type = SHELL_SURFACE_NONE;
> struct shell_surface *shsurf;
> + int32_t surf_x, surf_y;
>
> shsurf = get_shell_surface(surface);
> if (shsurf)
> @@ -3190,9 +3235,11 @@ configure(struct desktop_shell *shell, struct weston_surface *surface,
> break;
> case SHELL_SURFACE_MAXIMIZED:
> /* setting x, y and using configure to change that geometry */
> - surface->geometry.x = surface->output->x;
> + surface_subsurfaces_boundingbox(shsurf->surface, &surf_x, &surf_y,
> + NULL, NULL);
> + surface->geometry.x = surface->output->x - surf_x;
> surface->geometry.y = surface->output->y +
> - get_output_panel_height(shell,surface->output);
> + get_output_panel_height(shell,surface->output) - surf_y;
> break;
> case SHELL_SURFACE_TOPLEVEL:
> break;
You read my mind, the patch is in my subsurface-wip branch now. :-)
Thanks!
- pq
More information about the wayland-devel
mailing list