[PATCH weston v3 06/13] shell: account for the subsurfaces when going fullscreen or maximizing

Jonas Ådahl jadahl at gmail.com
Sun Apr 28 11:14:50 PDT 2013


On Thu, Apr 25, 2013 at 12:57 PM, Pekka Paalanen <ppaalanen at gmail.com> wrote:
> From: Giulio Camuffo <giuliocamuffo at gmail.com>
>
> We must calculate the bounding box of the surface + subsurfaces set and use
> that when maximizing the window or going fullscreen.
>
> Signed-off-by: Pekka Paalanen <ppaalanen at gmail.com>
> ---
>  src/shell.c | 89 ++++++++++++++++++++++++++++++++++++++++++++++---------------
>  1 file changed, 68 insertions(+), 21 deletions(-)
>
> diff --git a/src/shell.c b/src/shell.c
> index 86bdd84..39df27a 100644
> --- a/src/shell.c
> +++ b/src/shell.c
> @@ -1203,6 +1203,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) {

Wouldn't it be better if we left sub-compositor details to the
compositor and instead use a generic "weston_surface_get_bounds()"
function to get the collective bounding box of the given surface and
associated sub-surfaces?

> +       pixman_region32_t region;
> +       pixman_box32_t *box;
> +       struct weston_subsurface *subsurface;
> +
> +       pixman_region32_init_rect(&region, 0, 0,
> +                                 surface->geometry.width,
> +                                 surface->geometry.height);
> +
> +       wl_list_for_each(subsurface, &surface->subsurface_list, parent_link) {
> +               pixman_region32_union_rect(&region, &region,
> +                                          subsurface->position.x,
> +                                          subsurface->position.y,
> +                                          subsurface->surface->geometry.width,
> +                                          subsurface->surface->geometry.height);
> +       }
> +
> +       box = pixman_region32_extents(&region);
> +       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(&region);
> +}
> +
>  static int
>  surface_resize(struct shell_surface *shsurf,
>                struct weston_seat *ws, uint32_t edges)
> @@ -1222,8 +1257,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);
> @@ -1726,6 +1761,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 =
> @@ -1740,6 +1776,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)
> @@ -1747,9 +1786,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;
>                 }
>
> @@ -1762,33 +1802,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.link);
>                 wl_list_insert(&surface->geometry.transformation_list,
>                                &shsurf->fullscreen.transform.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;
>                         }
>                 }
> @@ -3122,12 +3162,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);
>  }
> @@ -3205,6 +3246,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;
> @@ -3222,8 +3264,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);
> @@ -3297,6 +3341,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)
> @@ -3311,9 +3356,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;
> --
> 1.8.1.5
>

Jonas


More information about the wayland-devel mailing list