From 2c6c842719b19c0c71c188e7337f15bb60f2585c Mon Sep 17 00:00:00 2001 From: Alexander Preisinger Date: Tue, 7 May 2013 20:51:09 +0200 Subject: [PATCH] wayland: reworked resizing This fixes 2 bugs: * Resizing very fast breaks the aspect of the window and the width and height don't match with the video anymore * Pressing 'f' for fullscreen very fast can overwrite the backup variables for the previous width and height. Also includes a better aspect calculation with fluid resizing. --- video/out/gl_wayland.c | 81 +++++++++++++++++--------------------- video/out/wayland_common.c | 36 ++++++++++------- video/out/wayland_common.h | 20 +++++++--- 3 files changed, 72 insertions(+), 65 deletions(-) diff --git a/video/out/gl_wayland.c b/video/out/gl_wayland.c index d04b17286b..859eab70fd 100644 --- a/video/out/gl_wayland.c +++ b/video/out/gl_wayland.c @@ -39,49 +39,52 @@ struct egl_context { }; static void egl_resize_func(struct vo_wayland_state *wl, - struct egl_context *ctx) + uint32_t edges, + int32_t width, + int32_t height, + void *user_data) { - int32_t x, y, scaled_height; - double ratio; - int minimum_size = 50; + struct vo_wayland_window *w = wl->window; + struct egl_context *ctx = user_data; + int32_t minimum_size = 150; + int32_t x, y; - if (wl->window->pending_width < minimum_size) - wl->window->pending_width = minimum_size; - if (wl->window->pending_height < minimum_size) - wl->window->pending_height = minimum_size; + /* get the real window size of the window */ + wl_egl_window_get_attached_size(ctx->egl_window, + &wl->window->width, + &wl->window->height); - ratio = (double) wl->vo->aspdat.orgw / wl->vo->aspdat.orgh; - scaled_height = wl->window->pending_height * ratio; - if (wl->window->pending_width > scaled_height) { - wl->window->pending_height = wl->window->pending_width / ratio; - } else { - wl->window->pending_width = scaled_height; - } + if (width < minimum_size) + width = minimum_size; + if (height < minimum_size) + height = minimum_size; - if (wl->window->edges & WL_SHELL_SURFACE_RESIZE_LEFT) - x = wl->window->width - wl->window->pending_width; + /* if only the height is changed we have to calculate the width + * in any other case we calculate the height */ + if (edges == WL_SHELL_SURFACE_RESIZE_BOTTOM || + edges == WL_SHELL_SURFACE_RESIZE_TOP) + width = wl->vo->aspdat.asp * height; + else + height = (1 / wl->vo->aspdat.asp) * width; + + if (edges & WL_SHELL_SURFACE_RESIZE_LEFT) + x = w->width - width; else x = 0; - if (wl->window->edges & WL_SHELL_SURFACE_RESIZE_TOP) - y = wl->window->height - wl->window->pending_height; + if (edges & WL_SHELL_SURFACE_RESIZE_TOP) + y = w->height - height; else y = 0; - wl_egl_window_resize(ctx->egl_window, - wl->window->pending_width, - wl->window->pending_height, - x, y); + wl_egl_window_resize(ctx->egl_window, width, height, x, y); - wl->window->width = wl->window->pending_width; - wl->window->height = wl->window->pending_height; + w->width = width; + w->height = height; /* set size for mplayer */ - wl->vo->dwidth = wl->window->pending_width; - wl->vo->dheight = wl->window->pending_height; - wl->window->events |= VO_EVENT_RESIZE; - wl->window->edges = 0; - wl->window->resize_needed = 0; + wl->vo->dwidth = width; + wl->vo->dheight = height; } static bool egl_create_context(struct vo_wayland_state *wl, @@ -166,6 +169,7 @@ static void egl_create_window(struct vo_wayland_state *wl, egl_ctx->egl.ctx); wl_display_dispatch_pending(wl->display->display); + } static bool config_window_wayland(struct MPGLContext *ctx, @@ -178,8 +182,8 @@ static bool config_window_wayland(struct MPGLContext *ctx, bool enable_alpha = !!(flags & VOFLAG_ALPHA); bool ret = false; - wl->window->pending_width = d_width; - wl->window->pending_height = d_height; + wl->window->resize_func = egl_resize_func; + wl->window->resize_func_data = (void*) egl_ctx; wl->window->width = d_width; wl->window->height = d_height; @@ -202,7 +206,7 @@ static bool config_window_wayland(struct MPGLContext *ctx, else { /* If the window exists just resize it */ if (egl_ctx->egl_window) - egl_resize_func(wl, egl_ctx); + egl_resize_func(wl, 0, d_width, d_height, egl_ctx); else { /* If the context exists and the hidden flag is unset then @@ -231,18 +235,7 @@ static void releaseGlContext_wayland(MPGLContext *ctx) static void swapGlBuffers_wayland(MPGLContext *ctx) { struct egl_context * egl_ctx = ctx->priv; - struct vo_wayland_state *wl = ctx->vo->wayland; - eglSwapBuffers(egl_ctx->egl.dpy, egl_ctx->egl_surface); - - /* resize window after the buffers have swapped - * makes resizing more fluid */ - if (wl->window->resize_needed) { - wl_egl_window_get_attached_size(egl_ctx->egl_window, - &wl->window->width, - &wl->window->height); - egl_resize_func(wl, egl_ctx); - } } void mpgl_set_backend_wayland(MPGLContext *ctx) diff --git a/video/out/wayland_common.c b/video/out/wayland_common.c index 054619dc83..9c1d5ffe55 100644 --- a/video/out/wayland_common.c +++ b/video/out/wayland_common.c @@ -59,6 +59,10 @@ static int lookupkey(int key); static void hide_cursor(struct vo_wayland_state * wl); static void show_cursor(struct vo_wayland_state * wl); +static void resize_window(struct vo_wayland_state *wl, + uint32_t edges, + int32_t width, + int32_t height); /*** wayland interface ***/ @@ -71,16 +75,6 @@ static void ssurface_handle_ping(void *data, wl_shell_surface_pong(shell_surface, serial); } -static void ssurface_schedule_resize(struct vo_wayland_window *window, - int32_t width, - int32_t height) -{ - window->pending_width = width; - window->pending_height = height; - window->resize_needed = 1; - window->events |= VO_EVENT_RESIZE; -} - static void ssurface_handle_configure(void *data, struct wl_shell_surface *shell_surface, uint32_t edges, @@ -88,9 +82,7 @@ static void ssurface_handle_configure(void *data, int32_t height) { struct vo_wayland_state *wl = data; - - wl->window->edges = edges; - ssurface_schedule_resize(wl->window, width, height); + resize_window(wl, edges, width, height); } static void ssurface_handle_popup_done(void *data, @@ -560,6 +552,21 @@ static void show_cursor (struct vo_wayland_state *wl) display->cursor.mouse_waiting_hide = true; } +static void resize_window(struct vo_wayland_state *wl, + uint32_t edges, + int32_t width, + int32_t height) +{ + struct vo_wayland_window *w = wl->window; + if (w->resize_func && w->resize_func_data) { + w->resize_func(wl, edges, width, height, w->resize_func_data); + w->events |= VO_EVENT_RESIZE; + } + else + mp_msg(MSGT_VO, MSGL_WARN, "[waylnad] No resizing possible!\n"); +} + + static bool create_display (struct vo_wayland_state *wl) { struct vo_wayland_display *d = wl->display; @@ -742,8 +749,7 @@ void vo_wayland_fullscreen (struct vo *vo) else { wl_shell_surface_set_toplevel(wl->window->shell_surface); - ssurface_schedule_resize(wl->window, wl->window->p_width, - wl->window->p_height); + resize_window(wl, 0, wl->window->p_width, wl->window->p_height); wl->window->type = TYPE_TOPLEVEL; vo->opts->fs = false; diff --git a/video/out/wayland_common.h b/video/out/wayland_common.h index 9c03dca7e5..d5259242bf 100644 --- a/video/out/wayland_common.h +++ b/video/out/wayland_common.h @@ -35,6 +35,8 @@ enum vo_wayland_window_type { }; struct vo; +struct vo_wayland_state; + struct vo_wayland_output { uint32_t id; /* unique name */ @@ -81,17 +83,23 @@ struct vo_wayland_window { int32_t p_width; int32_t p_height; - int32_t pending_width; - int32_t pending_height; - uint32_t edges; - int resize_needed; - struct wl_surface *surface; struct wl_shell_surface *shell_surface; - int events; /* mplayer events */ + int events; /* mplayer events (VO_EVENT_RESIZE) */ enum vo_wayland_window_type type; /* is fullscreen */ + + /* Because the egl windows have a special resize windw function we have to + * register it first before doing any resizing. + * This makes us independet from the output driver */ + void (*resize_func) (struct vo_wayland_state *wl, + uint32_t edges, + int32_t width, + int32_t height, + void *user_data); + + void *resize_func_data; }; struct vo_wayland_input {