From b836664c4249d496416f7c8a99dac03d04a3cf77 Mon Sep 17 00:00:00 2001 From: Giulio Camuffo Date: Thu, 25 Apr 2013 13:57:46 +0300 Subject: shell: account for the subsurfaces when going fullscreen or maximizing 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 --- src/shell.c | 89 ++++++++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 68 insertions(+), 21 deletions(-) diff --git a/src/shell.c b/src/shell.c index 55f3dcc..5da649d 100644 --- a/src/shell.c +++ b/src/shell.c @@ -1199,6 +1199,41 @@ static const struct weston_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 *seat, uint32_t edges) @@ -1218,8 +1253,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, seat->pointer, edges); @@ -1707,6 +1742,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 = @@ -1721,6 +1757,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) @@ -1728,9 +1767,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; } @@ -1743,33 +1783,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; } } @@ -3120,12 +3160,13 @@ update_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); } @@ -3203,6 +3244,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; @@ -3220,8 +3262,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); @@ -3295,6 +3339,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) @@ -3309,9 +3354,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; -- cgit v1.2.3