diff options
Diffstat (limited to 'video/out/wayland_common.c')
-rw-r--r-- | video/out/wayland_common.c | 231 |
1 files changed, 104 insertions, 127 deletions
diff --git a/video/out/wayland_common.c b/video/out/wayland_common.c index 480f29638b..e64c046327 100644 --- a/video/out/wayland_common.c +++ b/video/out/wayland_common.c @@ -3,6 +3,7 @@ * Copyright © 2008 Kristian Høgsberg * Copyright © 2012-2013 Collabora, Ltd. * Copyright © 2013 Alexander Preisinger <alexander.preisinger@gmail.com> + * Copyright © 2016 Rostislav Pehlivanov <atomnuker@gmail.com> * * mpv is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -46,6 +47,7 @@ #include "input/input.h" #include "input/event.h" #include "input/keycodes.h" +#include "sub/osd.h" static int lookupkey(int key); @@ -54,11 +56,7 @@ static void show_cursor(struct vo_wayland_state * wl); static void window_move(struct vo_wayland_state * wl, uint32_t serial); static void window_set_title(struct vo_wayland_state * wl, const char *title); static void schedule_resize(struct vo_wayland_state *wl, - uint32_t edges, - int32_t width, - int32_t height); - -static void vo_wayland_fullscreen(struct vo *vo); + int32_t width, int32_t height); static const struct wl_callback_listener frame_listener; @@ -127,37 +125,77 @@ static const struct mp_keymap keymap[] = { /** Wayland listeners **/ -static void ssurface_handle_ping(void *data, - struct wl_shell_surface *shell_surface, +static void xdg_handle_ping(void *data, struct zxdg_shell_v6 *shell, uint32_t serial) +{ + zxdg_shell_v6_pong(shell, serial); +} + +static const struct zxdg_shell_v6_listener xdg_shell_listener = { + xdg_handle_ping, +}; + +static void xdg_handle_configure(void *data, struct zxdg_surface_v6 *surface, uint32_t serial) { - wl_shell_surface_pong(shell_surface, serial); + zxdg_surface_v6_ack_configure(surface, serial); } -static void ssurface_handle_configure(void *data, - struct wl_shell_surface *shell_surface, - uint32_t edges, - int32_t width, - int32_t height) +const struct zxdg_surface_v6_listener xdg_surface_listener = { + xdg_handle_configure, +}; + +static void handle_toplevel_configure(void *data, struct zxdg_toplevel_v6 *toplevel, + int32_t width, int32_t height, + struct wl_array *states) { struct vo_wayland_state *wl = data; - float win_aspect = wl->window.aspect; - if (!width || !height) - return; - if (!wl->window.is_fullscreen) - width = win_aspect * height; - schedule_resize(wl, edges, width, height); + uint32_t *state; + + if (!width) { + width = wl->window.p_width; + } + + if (!height) { + height = wl->window.p_height; + } + + if (wl->display.current_output) { + int scale = wl->display.current_output->scale; + width = MPMIN(width, wl->display.current_output->width/scale); + height = MPMIN(height, wl->display.current_output->height/scale); + } + + wl->window.state.fullscreen = false; + + wl_array_for_each(state, states) { + switch (*state) { + case ZXDG_TOPLEVEL_V6_STATE_FULLSCREEN: + wl->window.state.fullscreen = true; + break; + case ZXDG_TOPLEVEL_V6_STATE_MAXIMIZED: + break; + case ZXDG_TOPLEVEL_V6_STATE_ACTIVATED: /* Window is focused */ + break; + case ZXDG_TOPLEVEL_V6_STATE_RESIZING: + break; + default: + /* Undefined state */ + break; + } + } + + schedule_resize(wl, width, height); } -static void ssurface_handle_popup_done(void *data, - struct wl_shell_surface *shell_surface) +static void handle_toplevel_close(void *data, struct zxdg_toplevel_v6 *xdg_toplevel) { + struct vo_wayland_state *wl = data; + mp_input_put_key(wl->vo->input_ctx, MP_KEY_CLOSE_WIN); } -static const struct wl_shell_surface_listener shell_surface_listener = { - ssurface_handle_ping, - ssurface_handle_configure, - ssurface_handle_popup_done +static const struct zxdg_toplevel_v6_listener xdg_toplevel_listener = { + handle_toplevel_configure, + handle_toplevel_close, }; static void output_handle_geometry(void *data, @@ -540,9 +578,9 @@ static void registry_handle_global(void *data, struct wl_registry *reg, MPMIN(3, version)); } - else if (strcmp(interface, "wl_shell") == 0) { - - wl->display.shell = wl_registry_bind(reg, id, &wl_shell_interface, 1); + else if (strcmp(interface, "zxdg_shell_v6") == 0) { + wl->display.shell = wl_registry_bind(reg, id, &zxdg_shell_v6_interface, 1); + zxdg_shell_v6_add_listener(wl->display.shell, &xdg_shell_listener, wl); } else if (strcmp(interface, "wl_shm") == 0) { @@ -638,77 +676,29 @@ static void show_cursor (struct vo_wayland_state *wl) static void window_move(struct vo_wayland_state *wl, uint32_t serial) { - if (wl->display.shell) - wl_shell_surface_move(wl->window.shell_surface, wl->input.seat, serial); -} - -static void window_set_toplevel(struct vo_wayland_state *wl) -{ - if (wl->display.shell) - wl_shell_surface_set_toplevel(wl->window.shell_surface); + zxdg_toplevel_v6_move(wl->window.xdg_toplevel, wl->input.seat, serial); } static void window_set_title(struct vo_wayland_state *wl, const char *title) { if (wl->display.shell) - wl_shell_surface_set_title(wl->window.shell_surface, title); + zxdg_toplevel_v6_set_title(wl->window.xdg_toplevel, title); } static void schedule_resize(struct vo_wayland_state *wl, - uint32_t edges, int32_t width, int32_t height) { - int32_t minimum_size = 150; - int32_t x, y; - float win_aspect = wl->window.aspect; - if (win_aspect <= 0) - win_aspect = 1; - - MP_DBG(wl, "schedule resize: %dx%d\n", width, height); - - width = MPMAX(minimum_size, width); - height = MPMAX(minimum_size, height); - if (wl->display.current_output) { - int scale = wl->display.current_output->scale; - width = MPMIN(width, wl->display.current_output->width /scale); - height = MPMIN(height, wl->display.current_output->height/scale); - } - - // don't keep the aspect ration in fullscreen mode, because the compositor - // shows the desktop in the border regions if the video has not the same - // aspect ration as the screen - /* if only the height is changed we have to calculate the width - * in any other case we calculate the height */ - switch (edges) { - case WL_SHELL_SURFACE_RESIZE_TOP: - case WL_SHELL_SURFACE_RESIZE_BOTTOM: - width = win_aspect * height; - break; - case WL_SHELL_SURFACE_RESIZE_LEFT: - case WL_SHELL_SURFACE_RESIZE_RIGHT: - case WL_SHELL_SURFACE_RESIZE_TOP_LEFT: // just a preference - case WL_SHELL_SURFACE_RESIZE_TOP_RIGHT: - case WL_SHELL_SURFACE_RESIZE_BOTTOM_LEFT: - case WL_SHELL_SURFACE_RESIZE_BOTTOM_RIGHT: - height = (1 / win_aspect) * width; - break; - } - - if (edges & WL_SHELL_SURFACE_RESIZE_LEFT) - x = wl->window.width - width; - else - x = 0; + MP_DBG(wl, "shedule resize: %dx%d\n", width, height); + wl->vo->dwidth = width; + wl->vo->dheight = height; - if (edges & WL_SHELL_SURFACE_RESIZE_TOP) - y = wl->window.height - height; - else - y = 0; + struct mp_rect src, dst; + struct mp_osd_res osd; + vo_get_src_dst_rects(wl->vo, &src, &dst, &osd); - wl->window.sh_width = width; - wl->window.sh_height = height; - wl->window.sh_x = x; - wl->window.sh_y = y; + wl->window.sh_width = dst.x1 - dst.x0; + wl->window.sh_height = dst.y1 - dst.y0; wl->window.events |= VO_EVENT_RESIZE; } @@ -781,7 +771,7 @@ static void destroy_display(struct vo_wayland_state *wl) wl_shm_destroy(wl->display.shm); if (wl->display.shell) - wl_shell_destroy(wl->display.shell); + zxdg_shell_v6_destroy(wl->display.shell); if (wl->display.subcomp) wl_subcompositor_destroy(wl->display.subcomp); @@ -807,19 +797,22 @@ static bool create_window(struct vo_wayland_state *wl) &surface_listener, wl); if (wl->display.shell) { - wl->window.shell_surface = wl_shell_get_shell_surface(wl->display.shell, - wl->window.video_surface); + wl->window.xdg_surface = zxdg_shell_v6_get_xdg_surface(wl->display.shell, + wl->window.video_surface); - if (!wl->window.shell_surface) { - MP_ERR(wl, "creating shell surface failed\n"); + if (!wl->window.xdg_surface) { + MP_ERR(wl, "creating xdg surface failed\n"); return false; } - wl_shell_surface_add_listener(wl->window.shell_surface, - &shell_surface_listener, wl); + zxdg_surface_v6_add_listener(wl->window.xdg_surface, + &xdg_surface_listener, wl); - wl_shell_surface_set_toplevel(wl->window.shell_surface); - wl_shell_surface_set_class(wl->window.shell_surface, "mpv"); + wl->window.xdg_toplevel = zxdg_surface_v6_get_toplevel(wl->window.xdg_surface); + + zxdg_toplevel_v6_add_listener(wl->window.xdg_toplevel, + &xdg_toplevel_listener, wl); + zxdg_toplevel_v6_set_app_id(wl->window.xdg_toplevel, "mpv"); } return true; @@ -827,8 +820,8 @@ static bool create_window(struct vo_wayland_state *wl) static void destroy_window(struct vo_wayland_state *wl) { - if (wl->window.shell_surface) - wl_shell_surface_destroy(wl->window.shell_surface); + if (wl->window.xdg_surface) + zxdg_surface_v6_destroy(wl->window.xdg_surface); if (wl->window.video_surface) wl_surface_destroy(wl->window.video_surface); @@ -954,42 +947,26 @@ void vo_wayland_uninit(struct vo *vo) vo->wayland = NULL; } -static void vo_wayland_ontop(struct vo *vo) -{ - struct vo_wayland_state *wl = vo->wayland; - if (!vo->opts->ontop) - return; - MP_DBG(wl, "going ontop\n"); - window_set_toplevel(wl); - schedule_resize(wl, 0, wl->window.width, wl->window.height); -} - -static void vo_wayland_fullscreen(struct vo *vo) +static void window_set_fullscreen(struct vo *vo) { struct vo_wayland_state *wl = vo->wayland; if (!wl->display.shell) return; - struct wl_output *fs_output = wl->display.fs_output; - if (vo->opts->fullscreen) { MP_DBG(wl, "going fullscreen\n"); - wl->window.is_fullscreen = true; wl->window.p_width = wl->window.width; wl->window.p_height = wl->window.height; - if (wl->display.current_output) - schedule_resize(wl, 0, wl->display.current_output->width, - wl->display.current_output->height); - wl_shell_surface_set_fullscreen(wl->window.shell_surface, - WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT, - 0, fs_output); + zxdg_toplevel_v6_set_fullscreen(wl->window.xdg_toplevel, NULL); + //if (wl->display.current_output) + //schedule_resize(wl, wl->display.current_output->width, + // wl->display.current_output->height); } else { MP_DBG(wl, "leaving fullscreen\n"); - wl->window.is_fullscreen = false; - window_set_toplevel(wl); - schedule_resize(wl, 0, wl->window.p_width, wl->window.p_height); + zxdg_toplevel_v6_unset_fullscreen(wl->window.xdg_toplevel); + //schedule_resize(wl, wl->window.p_width, wl->window.p_height); } } @@ -1047,10 +1024,7 @@ int vo_wayland_control(struct vo *vo, int *events, int request, void *arg) wl->window.events = 0; return VO_TRUE; case VOCTRL_FULLSCREEN: - vo_wayland_fullscreen(vo); - return VO_TRUE; - case VOCTRL_ONTOP: - vo_wayland_ontop(vo); + window_set_fullscreen(vo); return VO_TRUE; case VOCTRL_GET_UNFS_WINDOW_SIZE: { int *s = arg, scale = 1; @@ -1062,8 +1036,8 @@ int vo_wayland_control(struct vo *vo, int *events, int request, void *arg) } case VOCTRL_SET_UNFS_WINDOW_SIZE: { int *s = arg; - if (!wl->window.is_fullscreen) - schedule_resize(wl, 0, s[0], s[1]); + if (!wl->window.state.fullscreen) + schedule_resize(wl, s[0], s[1]); return VO_TRUE; } case VOCTRL_SET_CURSOR_VISIBILITY: @@ -1097,6 +1071,9 @@ bool vo_wayland_config(struct vo *vo) { struct vo_wayland_state *wl = vo->wayland; + // reset states + wl->window.state.fullscreen = false; + struct mp_rect screenrc; vo_wayland_update_screeninfo(vo, &screenrc); @@ -1110,7 +1087,7 @@ bool vo_wayland_config(struct vo *vo) wl->window.width = vo->dwidth; wl->window.height = vo->dheight; - vo_wayland_fullscreen(vo); + window_set_fullscreen(vo); return true; } |