From 94b20da3cecbcfbf36797bc781308eeb18542a75 Mon Sep 17 00:00:00 2001 From: emersion Date: Tue, 14 Nov 2017 10:20:20 +0100 Subject: Fix popups position for rotated views --- rootston/output.c | 91 ++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 64 insertions(+), 27 deletions(-) diff --git a/rootston/output.c b/rootston/output.c index 145016b3..294047d7 100644 --- a/rootston/output.c +++ b/rootston/output.c @@ -17,13 +17,40 @@ static inline int64_t timespec_to_msec(const struct timespec *a) { return (int64_t)a->tv_sec * 1000 + a->tv_nsec / 1000000; } +/** + * Computes the surface size homogeneous to the global compositor coordinates. + */ +static void get_surface_size(struct wlr_surface *surface, double *width, + double *height) { + double surface_scale = surface->current->scale; + *width = (double)surface->current->buffer_width / surface_scale; + *height = (double)surface->current->buffer_height / surface_scale; +} + +/** + * Rotate a child's position relative to a parent. The parent size is (pw, ph), + * the child position is (*sx, *sy) and its size is (sw, sh). + */ +static void rotate_child_position(double *sx, double *sy, double sw, double sh, + double pw, double ph, float rotation) { + if (rotation != 0.0) { + // Coordinates relative to the center of the subsurface + double ox = *sx - pw/2 + sw/2, + oy = *sy - ph/2 + sh/2; + // Rotated coordinates + double rx = cos(-rotation)*ox - sin(-rotation)*oy, + ry = cos(-rotation)*oy + sin(-rotation)*ox; + *sx = rx + pw/2 - sw/2; + *sy = ry + ph/2 - sh/2; + } +} + static void render_surface(struct wlr_surface *surface, struct roots_desktop *desktop, struct wlr_output *wlr_output, struct timespec *when, double lx, double ly, float rotation) { if (surface->texture->valid) { - double surface_scale = surface->current->scale; - double width = (double)surface->current->buffer_width / surface_scale; - double height = (double)surface->current->buffer_height / surface_scale; + double width, height; + get_surface_size(surface, &width, &height); int render_width = width * wlr_output->scale; int render_height = height * wlr_output->scale; double ox = lx, oy = ly; @@ -73,16 +100,7 @@ static void render_surface(struct wlr_surface *surface, double sy = state->subsurface_position.y; double sw = state->buffer_width / state->scale; double sh = state->buffer_height / state->scale; - if (rotation != 0.0) { - // Coordinates relative to the center of the subsurface - double ox = sx - width/2 + sw/2, - oy = sy - height/2 + sh/2; - // Rotated coordinates - double rx = cos(-rotation)*ox - sin(-rotation)*oy, - ry = cos(-rotation)*oy + sin(-rotation)*ox; - sx = rx + width/2 - sw/2; - sy = ry + height/2 - sh/2; - } + rotate_child_position(&sx, &sy, sw, sh, width, height, rotation); render_surface(subsurface->surface, desktop, wlr_output, when, lx + sx, @@ -95,36 +113,55 @@ static void render_surface(struct wlr_surface *surface, static void render_xdg_v6_popups(struct wlr_xdg_surface_v6 *surface, struct roots_desktop *desktop, struct wlr_output *wlr_output, struct timespec *when, double base_x, double base_y, float rotation) { - // TODO: make sure this works with view rotation + double width, height; + get_surface_size(surface->surface, &width, &height); + struct wlr_xdg_surface_v6 *popup; wl_list_for_each(popup, &surface->popups, popup_link) { if (!popup->configured) { continue; } - double popup_x = base_x + surface->geometry->x + - popup->popup_state->geometry.x - popup->geometry->x; - double popup_y = base_y + surface->geometry->y + - popup->popup_state->geometry.y - popup->geometry->y; - render_surface(popup->surface, desktop, wlr_output, when, popup_x, - popup_y, rotation); - render_xdg_v6_popups(popup, desktop, wlr_output, when, popup_x, popup_y, + double sw, sh; + get_surface_size(popup->surface, &sw, &sh); + + double popup_x = surface->geometry->x + popup->popup_state->geometry.x - + popup->geometry->x; + double popup_y = surface->geometry->y + popup->popup_state->geometry.y - + popup->geometry->y; + rotate_child_position(&popup_x, &popup_y, sw, sh, width, height, rotation); + + render_surface(popup->surface, desktop, wlr_output, when, + base_x + popup_x, base_y + popup_y, rotation); + render_xdg_v6_popups(popup, desktop, wlr_output, when, base_x + popup_x, + base_y + popup_y, rotation); } } -static void render_wl_shell_surface(struct wlr_wl_shell_surface *surface, struct roots_desktop *desktop, - struct wlr_output *wlr_output, struct timespec *when, double lx, - double ly, float rotation, bool is_child) { +static void render_wl_shell_surface(struct wlr_wl_shell_surface *surface, + struct roots_desktop *desktop, struct wlr_output *wlr_output, + struct timespec *when, double lx, double ly, float rotation, + bool is_child) { if (is_child || surface->state != WLR_WL_SHELL_SURFACE_STATE_POPUP) { render_surface(surface->surface, desktop, wlr_output, when, lx, ly, rotation); + + double width, height; + get_surface_size(surface->surface, &width, &height); + struct wlr_wl_shell_surface *popup; wl_list_for_each(popup, &surface->popups, popup_link) { + double sw, sh; + get_surface_size(popup->surface, &sw, &sh); + + double popup_x = popup->transient_state->x; + double popup_y = popup->transient_state->y; + rotate_child_position(&popup_x, &popup_y, sw, sh, width, height, + rotation); + render_wl_shell_surface(popup, desktop, wlr_output, when, - lx + popup->transient_state->x, - ly + popup->transient_state->y, - rotation, true); + lx + popup_x, ly + popup_y, rotation, true); } } } -- cgit v1.2.3 From 2f44140f4afdab3231d215b913393e3d6a5e36d9 Mon Sep 17 00:00:00 2001 From: emersion Date: Tue, 14 Nov 2017 15:33:29 +0100 Subject: Don't use buffer size --- rootston/output.c | 39 +++++++++++++++------------------------ 1 file changed, 15 insertions(+), 24 deletions(-) diff --git a/rootston/output.c b/rootston/output.c index 294047d7..2a39510b 100644 --- a/rootston/output.c +++ b/rootston/output.c @@ -17,16 +17,6 @@ static inline int64_t timespec_to_msec(const struct timespec *a) { return (int64_t)a->tv_sec * 1000 + a->tv_nsec / 1000000; } -/** - * Computes the surface size homogeneous to the global compositor coordinates. - */ -static void get_surface_size(struct wlr_surface *surface, double *width, - double *height) { - double surface_scale = surface->current->scale; - *width = (double)surface->current->buffer_width / surface_scale; - *height = (double)surface->current->buffer_height / surface_scale; -} - /** * Rotate a child's position relative to a parent. The parent size is (pw, ph), * the child position is (*sx, *sy) and its size is (sw, sh). @@ -49,8 +39,9 @@ static void render_surface(struct wlr_surface *surface, struct roots_desktop *desktop, struct wlr_output *wlr_output, struct timespec *when, double lx, double ly, float rotation) { if (surface->texture->valid) { - double width, height; - get_surface_size(surface, &width, &height); + double surface_scale = surface->current->scale; + double width = (double)surface->current->buffer_width / surface_scale; + double height = (double)surface->current->buffer_height / surface_scale; int render_width = width * wlr_output->scale; int render_height = height * wlr_output->scale; double ox = lx, oy = ly; @@ -113,8 +104,8 @@ static void render_surface(struct wlr_surface *surface, static void render_xdg_v6_popups(struct wlr_xdg_surface_v6 *surface, struct roots_desktop *desktop, struct wlr_output *wlr_output, struct timespec *when, double base_x, double base_y, float rotation) { - double width, height; - get_surface_size(surface->surface, &width, &height); + double width = surface->surface->current->width; + double height = surface->surface->current->height; struct wlr_xdg_surface_v6 *popup; wl_list_for_each(popup, &surface->popups, popup_link) { @@ -122,15 +113,15 @@ static void render_xdg_v6_popups(struct wlr_xdg_surface_v6 *surface, continue; } - double sw, sh; - get_surface_size(popup->surface, &sw, &sh); + double popup_width = popup->surface->current->width; + double popup_height = popup->surface->current->height; double popup_x = surface->geometry->x + popup->popup_state->geometry.x - popup->geometry->x; double popup_y = surface->geometry->y + popup->popup_state->geometry.y - popup->geometry->y; - rotate_child_position(&popup_x, &popup_y, sw, sh, width, height, - rotation); + rotate_child_position(&popup_x, &popup_y, popup_width, popup_height, + width, height, rotation); render_surface(popup->surface, desktop, wlr_output, when, base_x + popup_x, base_y + popup_y, rotation); @@ -147,18 +138,18 @@ static void render_wl_shell_surface(struct wlr_wl_shell_surface *surface, render_surface(surface->surface, desktop, wlr_output, when, lx, ly, rotation); - double width, height; - get_surface_size(surface->surface, &width, &height); + double width = surface->surface->current->width; + double height = surface->surface->current->height; struct wlr_wl_shell_surface *popup; wl_list_for_each(popup, &surface->popups, popup_link) { - double sw, sh; - get_surface_size(popup->surface, &sw, &sh); + double popup_width = popup->surface->current->width; + double popup_height = popup->surface->current->height; double popup_x = popup->transient_state->x; double popup_y = popup->transient_state->y; - rotate_child_position(&popup_x, &popup_y, sw, sh, width, height, - rotation); + rotate_child_position(&popup_x, &popup_y, popup_width, popup_height, + width, height, rotation); render_wl_shell_surface(popup, desktop, wlr_output, when, lx + popup_x, ly + popup_y, rotation, true); -- cgit v1.2.3 From bb973ff27d5b735d2eb8ec620d7ea74e43eab301 Mon Sep 17 00:00:00 2001 From: emersion Date: Tue, 14 Nov 2017 21:18:34 +0100 Subject: Remove remaining buffer_{width,height} usage --- rootston/output.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/rootston/output.c b/rootston/output.c index 2a39510b..cfab3756 100644 --- a/rootston/output.c +++ b/rootston/output.c @@ -39,9 +39,8 @@ static void render_surface(struct wlr_surface *surface, struct roots_desktop *desktop, struct wlr_output *wlr_output, struct timespec *when, double lx, double ly, float rotation) { if (surface->texture->valid) { - double surface_scale = surface->current->scale; - double width = (double)surface->current->buffer_width / surface_scale; - double height = (double)surface->current->buffer_height / surface_scale; + int width = surface->current->width; + int height = surface->current->height; int render_width = width * wlr_output->scale; int render_height = height * wlr_output->scale; double ox = lx, oy = ly; -- cgit v1.2.3 From 3f6cf517b9b8d5efa0c6001db5ed0871e5d8d2b4 Mon Sep 17 00:00:00 2001 From: emersion Date: Wed, 15 Nov 2017 14:03:13 +0100 Subject: Add wlr_xdg_surface_v6_popup_get_position --- include/wlr/types/wlr_xdg_shell_v6.h | 6 ++++++ rootston/output.c | 14 ++++++-------- types/wlr_xdg_shell_v6.c | 10 ++++++++++ 3 files changed, 22 insertions(+), 8 deletions(-) diff --git a/include/wlr/types/wlr_xdg_shell_v6.h b/include/wlr/types/wlr_xdg_shell_v6.h index 07911ffa..e3982003 100644 --- a/include/wlr/types/wlr_xdg_shell_v6.h +++ b/include/wlr/types/wlr_xdg_shell_v6.h @@ -209,6 +209,12 @@ void wlr_xdg_toplevel_v6_set_resizing(struct wlr_xdg_surface_v6 *surface, */ void wlr_xdg_toplevel_v6_send_close(struct wlr_xdg_surface_v6 *surface); +/** + * Compute the popup position in surface-local coordinates. + */ +void wlr_xdg_surface_v6_popup_get_position(struct wlr_xdg_surface_v6 *surface, + double *popup_sx, double *popup_sy); + /** * Find a popup within this surface at the surface-local coordinates. Returns * the popup and coordinates in the topmost surface coordinate system or NULL if diff --git a/rootston/output.c b/rootston/output.c index cfab3756..28312c2c 100644 --- a/rootston/output.c +++ b/rootston/output.c @@ -115,17 +115,15 @@ static void render_xdg_v6_popups(struct wlr_xdg_surface_v6 *surface, double popup_width = popup->surface->current->width; double popup_height = popup->surface->current->height; - double popup_x = surface->geometry->x + popup->popup_state->geometry.x - - popup->geometry->x; - double popup_y = surface->geometry->y + popup->popup_state->geometry.y - - popup->geometry->y; - rotate_child_position(&popup_x, &popup_y, popup_width, popup_height, + double popup_sx, popup_sy; + wlr_xdg_surface_v6_popup_get_position(popup, &popup_sx, &popup_sy); + rotate_child_position(&popup_sx, &popup_sy, popup_width, popup_height, width, height, rotation); render_surface(popup->surface, desktop, wlr_output, when, - base_x + popup_x, base_y + popup_y, rotation); - render_xdg_v6_popups(popup, desktop, wlr_output, when, base_x + popup_x, - base_y + popup_y, rotation); + base_x + popup_sx, base_y + popup_sy, rotation); + render_xdg_v6_popups(popup, desktop, wlr_output, when, + base_x + popup_sx, base_y + popup_sy, rotation); } } diff --git a/types/wlr_xdg_shell_v6.c b/types/wlr_xdg_shell_v6.c index 05ca2b76..429baa70 100644 --- a/types/wlr_xdg_shell_v6.c +++ b/types/wlr_xdg_shell_v6.c @@ -1350,6 +1350,16 @@ void wlr_xdg_toplevel_v6_send_close(struct wlr_xdg_surface_v6 *surface) { zxdg_toplevel_v6_send_close(surface->toplevel_state->resource); } +void wlr_xdg_surface_v6_popup_get_position(struct wlr_xdg_surface_v6 *surface, + double *popup_sx, double *popup_sy) { + assert(surface->role == WLR_XDG_SURFACE_V6_ROLE_POPUP); + struct wlr_xdg_surface_v6 *parent = surface->popup_state->parent; + *popup_sx = parent->geometry->x + surface->popup_state->geometry.x - + surface->geometry->x; + *popup_sy = parent->geometry->y + surface->popup_state->geometry.y - + surface->geometry->y; +} + struct wlr_xdg_surface_v6 *wlr_xdg_surface_v6_popup_at( struct wlr_xdg_surface_v6 *surface, double sx, double sy, double *popup_sx, double *popup_sy) { -- cgit v1.2.3