1
0
mirror of https://github.com/mpv-player/mpv synced 2024-12-23 15:22:09 +00:00

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.
This commit is contained in:
Alexander Preisinger 2013-05-07 20:51:09 +02:00
parent c653697610
commit 2c6c842719
3 changed files with 72 additions and 65 deletions

View File

@ -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)

View File

@ -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;

View File

@ -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 {