summaryrefslogtreecommitdiffstats
path: root/video/out
diff options
context:
space:
mode:
authorDudemanguy <random342@airmail.cc>2021-06-26 16:12:03 -0500
committerDudemanguy <random342@airmail.cc>2021-06-26 17:24:44 -0500
commit488581912d01a982f226162eef19ad8aec0c8ead (patch)
tree3b5aa34fe9afa52b9573b10c5f20448952712b73 /video/out
parent76a53f9de3592c435def1d020fab4a05f88a14e0 (diff)
downloadmpv-488581912d01a982f226162eef19ad8aec0c8ead.tar.bz2
mpv-488581912d01a982f226162eef19ad8aec0c8ead.tar.xz
wayland: reorganize wayland common code
Mostly a cosmetic change that (hopefully) makes things look better. Some functions and structs that were previously being exported in the wayland header were made static to the wayland_common.c file (these shouldn't be accessed by anyone else).
Diffstat (limited to 'video/out')
-rw-r--r--video/out/opengl/context_wayland.c2
-rw-r--r--video/out/vo_wlshm.c2
-rw-r--r--video/out/vulkan/context_wayland.c2
-rw-r--r--video/out/wayland_common.c1773
-rw-r--r--video/out/wayland_common.h131
5 files changed, 962 insertions, 948 deletions
diff --git a/video/out/opengl/context_wayland.c b/video/out/opengl/context_wayland.c
index eeaeb11cc1..b899e6fca9 100644
--- a/video/out/opengl/context_wayland.c
+++ b/video/out/opengl/context_wayland.c
@@ -81,7 +81,7 @@ static void wayland_egl_swap_buffers(struct ra_swapchain *sw)
vo_wayland_wait_frame(wl);
if (wl->presentation)
- wayland_sync_swap(wl);
+ vo_wayland_sync_swap(wl);
}
static const struct ra_swapchain_fns wayland_egl_swapchain = {
diff --git a/video/out/vo_wlshm.c b/video/out/vo_wlshm.c
index 69cfdd9dcc..e6ba0875f0 100644
--- a/video/out/vo_wlshm.c
+++ b/video/out/vo_wlshm.c
@@ -278,7 +278,7 @@ static void flip_page(struct vo *vo)
vo_wayland_wait_frame(wl);
if (wl->presentation)
- wayland_sync_swap(wl);
+ vo_wayland_sync_swap(wl);
}
static void get_vsync(struct vo *vo, struct vo_vsync_info *info)
diff --git a/video/out/vulkan/context_wayland.c b/video/out/vulkan/context_wayland.c
index d711a855c4..df2d1abd55 100644
--- a/video/out/vulkan/context_wayland.c
+++ b/video/out/vulkan/context_wayland.c
@@ -46,7 +46,7 @@ static void wayland_vk_swap_buffers(struct ra_ctx *ctx)
vo_wayland_wait_frame(wl);
if (wl->presentation)
- wayland_sync_swap(wl);
+ vo_wayland_sync_swap(wl);
}
static void wayland_vk_get_vsync(struct ra_ctx *ctx, struct vo_vsync_info *info)
diff --git a/video/out/wayland_common.c b/video/out/wayland_common.c
index 850c8d362d..1b7eb5246b 100644
--- a/video/out/wayland_common.c
+++ b/video/out/wayland_common.c
@@ -17,30 +17,89 @@
#include <errno.h>
#include <limits.h>
-#include <poll.h>
-#include <unistd.h>
#include <linux/input-event-codes.h>
+#include <poll.h>
#include <time.h>
+#include <unistd.h>
+#include <wayland-cursor.h>
+#include <xkbcommon/xkbcommon.h>
+
#include "common/msg.h"
-#include "options/m_config.h"
#include "input/input.h"
#include "input/keycodes.h"
+#include "options/m_config.h"
#include "osdep/io.h"
#include "osdep/timer.h"
-#include "win_state.h"
#include "wayland_common.h"
+#include "win_state.h"
-// Generated from xdg-shell.xml
+// Generated from wayland-protocols
+#include "generated/wayland/idle-inhibit-unstable-v1.h"
+#include "generated/wayland/presentation-time.h"
+#include "generated/wayland/xdg-decoration-unstable-v1.h"
#include "generated/wayland/xdg-shell.h"
-// Generated from idle-inhibit-unstable-v1.xml
-#include "generated/wayland/idle-inhibit-unstable-v1.h"
+static const struct mp_keymap keymap[] = {
+ /* Special keys */
+ {XKB_KEY_Pause, MP_KEY_PAUSE}, {XKB_KEY_Escape, MP_KEY_ESC},
+ {XKB_KEY_BackSpace, MP_KEY_BS}, {XKB_KEY_Tab, MP_KEY_TAB},
+ {XKB_KEY_Return, MP_KEY_ENTER}, {XKB_KEY_Menu, MP_KEY_MENU},
+ {XKB_KEY_Print, MP_KEY_PRINT},
-// Generated from xdg-decoration-unstable-v1.xml
-#include "generated/wayland/xdg-decoration-unstable-v1.h"
+ /* Cursor keys */
+ {XKB_KEY_Left, MP_KEY_LEFT}, {XKB_KEY_Right, MP_KEY_RIGHT},
+ {XKB_KEY_Up, MP_KEY_UP}, {XKB_KEY_Down, MP_KEY_DOWN},
-// Generated from presentation-time.xml
-#include "generated/wayland/presentation-time.h"
+ /* Navigation keys */
+ {XKB_KEY_Insert, MP_KEY_INSERT}, {XKB_KEY_Delete, MP_KEY_DELETE},
+ {XKB_KEY_Home, MP_KEY_HOME}, {XKB_KEY_End, MP_KEY_END},
+ {XKB_KEY_Page_Up, MP_KEY_PAGE_UP}, {XKB_KEY_Page_Down, MP_KEY_PAGE_DOWN},
+
+ /* F-keys */
+ {XKB_KEY_F1, MP_KEY_F + 1}, {XKB_KEY_F2, MP_KEY_F + 2},
+ {XKB_KEY_F3, MP_KEY_F + 3}, {XKB_KEY_F4, MP_KEY_F + 4},
+ {XKB_KEY_F5, MP_KEY_F + 5}, {XKB_KEY_F6, MP_KEY_F + 6},
+ {XKB_KEY_F7, MP_KEY_F + 7}, {XKB_KEY_F8, MP_KEY_F + 8},
+ {XKB_KEY_F9, MP_KEY_F + 9}, {XKB_KEY_F10, MP_KEY_F +10},
+ {XKB_KEY_F11, MP_KEY_F +11}, {XKB_KEY_F12, MP_KEY_F +12},
+
+ /* Numpad independent of numlock */
+ {XKB_KEY_KP_Subtract, '-'}, {XKB_KEY_KP_Add, '+'},
+ {XKB_KEY_KP_Multiply, '*'}, {XKB_KEY_KP_Divide, '/'},
+ {XKB_KEY_KP_Enter, MP_KEY_KPENTER},
+
+ /* Numpad with numlock */
+ {XKB_KEY_KP_0, MP_KEY_KP0}, {XKB_KEY_KP_1, MP_KEY_KP1},
+ {XKB_KEY_KP_2, MP_KEY_KP2}, {XKB_KEY_KP_3, MP_KEY_KP3},
+ {XKB_KEY_KP_4, MP_KEY_KP4}, {XKB_KEY_KP_5, MP_KEY_KP5},
+ {XKB_KEY_KP_6, MP_KEY_KP6}, {XKB_KEY_KP_7, MP_KEY_KP7},
+ {XKB_KEY_KP_8, MP_KEY_KP8}, {XKB_KEY_KP_9, MP_KEY_KP9},
+ {XKB_KEY_KP_Decimal, MP_KEY_KPDEC}, {XKB_KEY_KP_Separator, MP_KEY_KPDEC},
+
+ /* Numpad without numlock */
+ {XKB_KEY_KP_Insert, MP_KEY_KPINS}, {XKB_KEY_KP_End, MP_KEY_KP1},
+ {XKB_KEY_KP_Down, MP_KEY_KP2}, {XKB_KEY_KP_Page_Down, MP_KEY_KP3},
+ {XKB_KEY_KP_Left, MP_KEY_KP4}, {XKB_KEY_KP_Begin, MP_KEY_KP5},
+ {XKB_KEY_KP_Right, MP_KEY_KP6}, {XKB_KEY_KP_Home, MP_KEY_KP7},
+ {XKB_KEY_KP_Up, MP_KEY_KP8}, {XKB_KEY_KP_Page_Up, MP_KEY_KP9},
+ {XKB_KEY_KP_Delete, MP_KEY_KPDEL},
+
+ /* Multimedia keys */
+ {XKB_KEY_XF86MenuKB, MP_KEY_MENU},
+ {XKB_KEY_XF86AudioPlay, MP_KEY_PLAY}, {XKB_KEY_XF86AudioPause, MP_KEY_PAUSE},
+ {XKB_KEY_XF86AudioStop, MP_KEY_STOP},
+ {XKB_KEY_XF86AudioPrev, MP_KEY_PREV}, {XKB_KEY_XF86AudioNext, MP_KEY_NEXT},
+ {XKB_KEY_XF86AudioRewind, MP_KEY_REWIND},
+ {XKB_KEY_XF86AudioForward, MP_KEY_FORWARD},
+ {XKB_KEY_XF86AudioMute, MP_KEY_MUTE},
+ {XKB_KEY_XF86AudioLowerVolume, MP_KEY_VOLUME_DOWN},
+ {XKB_KEY_XF86AudioRaiseVolume, MP_KEY_VOLUME_UP},
+ {XKB_KEY_XF86HomePage, MP_KEY_HOMEPAGE}, {XKB_KEY_XF86WWW, MP_KEY_WWW},
+ {XKB_KEY_XF86Mail, MP_KEY_MAIL}, {XKB_KEY_XF86Favorites, MP_KEY_FAVORITES},
+ {XKB_KEY_XF86Search, MP_KEY_SEARCH}, {XKB_KEY_XF86Sleep, MP_KEY_SLEEP},
+
+ {0, 0}
+};
#define OPT_BASE_STRUCT struct wayland_opts
const struct m_sub_options wayland_conf = {
@@ -60,100 +119,46 @@ const struct m_sub_options wayland_conf = {
},
};
-static void xdg_wm_base_ping(void *data, struct xdg_wm_base *wm_base, uint32_t serial)
-{
- xdg_wm_base_pong(wm_base, serial);
-}
-
-static const struct xdg_wm_base_listener xdg_wm_base_listener = {
- xdg_wm_base_ping,
+struct vo_wayland_output {
+ struct vo_wayland_state *wl;
+ struct wl_output *output;
+ struct mp_rect geometry;
+ bool has_surface;
+ uint32_t id;
+ uint32_t flags;
+ int phys_width;
+ int phys_height;
+ int scale;
+ double refresh_rate;
+ char *make;
+ char *model;
+ struct wl_list link;
};
-static int spawn_cursor(struct vo_wayland_state *wl)
-{
- /* Reuse if size is identical */
- if (!wl->pointer || wl->allocated_cursor_scale == wl->scaling)
- return 0;
- else if (wl->cursor_theme)
- wl_cursor_theme_destroy(wl->cursor_theme);
-
- const char *size_str = getenv("XCURSOR_SIZE");
- int size = 32;
- if (size_str != NULL) {
- errno = 0;
- char *end;
- long size_long = strtol(size_str, &end, 10);
- if (!*end && !errno && size_long > 0 && size_long <= INT_MAX)
- size = (int)size_long;
- }
-
- wl->cursor_theme = wl_cursor_theme_load(NULL, size*wl->scaling, wl->shm);
- if (!wl->cursor_theme) {
- MP_ERR(wl, "Unable to load cursor theme!\n");
- return 1;
- }
-
- wl->default_cursor = wl_cursor_theme_get_cursor(wl->cursor_theme, "left_ptr");
- if (!wl->default_cursor) {
- MP_ERR(wl, "Unable to load cursor theme!\n");
- return 1;
- }
-
- wl->allocated_cursor_scale = wl->scaling;
-
- return 0;
-}
-
-static int set_cursor_visibility(struct vo_wayland_state *wl, bool on)
-{
- wl->cursor_visible = on;
- if (on) {
- if (spawn_cursor(wl))
- return VO_FALSE;
- struct wl_cursor_image *img = wl->default_cursor->images[0];
- struct wl_buffer *buffer = wl_cursor_image_get_buffer(img);
- if (!buffer)
- return VO_FALSE;
- wl_pointer_set_cursor(wl->pointer, wl->pointer_id, wl->cursor_surface,
- img->hotspot_x/wl->scaling, img->hotspot_y/wl->scaling);
- wl_surface_set_buffer_scale(wl->cursor_surface, wl->scaling);
- wl_surface_attach(wl->cursor_surface, buffer, 0, 0);
- wl_surface_damage(wl->cursor_surface, 0, 0, img->width, img->height);
- wl_surface_commit(wl->cursor_surface);
- } else {
- wl_pointer_set_cursor(wl->pointer, wl->pointer_id, NULL, 0, 0);
- }
- return VO_TRUE;
-}
-
-static int get_mods(struct vo_wayland_state *wl)
-{
- static char* const mod_names[] = {
- XKB_MOD_NAME_SHIFT,
- XKB_MOD_NAME_CTRL,
- XKB_MOD_NAME_ALT,
- XKB_MOD_NAME_LOGO,
- };
-
- static const int mods[] = {
- MP_KEY_MODIFIER_SHIFT,
- MP_KEY_MODIFIER_CTRL,
- MP_KEY_MODIFIER_ALT,
- MP_KEY_MODIFIER_META,
- };
-
- int modifiers = 0;
-
- for (int n = 0; n < MP_ARRAY_SIZE(mods); n++) {
- xkb_mod_index_t index = xkb_keymap_mod_get_index(wl->xkb_keymap, mod_names[n]);
- if (!xkb_state_mod_index_is_consumed(wl->xkb_state, wl->keyboard_code, index)
- && xkb_state_mod_index_is_active(wl->xkb_state, index,
- XKB_STATE_MODS_DEPRESSED))
- modifiers |= mods[n];
- }
- return modifiers;
-}
+struct vo_wayland_sync {
+ int64_t ust;
+ int64_t msc;
+ int64_t sbc;
+ bool filled;
+};
+static int check_for_resize(struct vo_wayland_state *wl, wl_fixed_t x_w, wl_fixed_t y_w,
+ int edge_pixels, enum xdg_toplevel_resize_edge *edge);
+static int get_mods(struct vo_wayland_state *wl);
+static int last_available_sync(struct vo_wayland_state *wl);
+static int lookupkey(int key);
+static int set_cursor_visibility(struct vo_wayland_state *wl, bool on);
+static int spawn_cursor(struct vo_wayland_state *wl);
+
+static void greatest_common_divisor(struct vo_wayland_state *wl, int a, int b);
+static void queue_new_sync(struct vo_wayland_state *wl);
+static void remove_output(struct vo_wayland_output *out);
+static void rescale_geometry_dimensions(struct vo_wayland_state *wl, double factor);
+static void set_geometry(struct vo_wayland_state *wl);
+static void sync_shift(struct vo_wayland_state *wl);
+static void window_move(struct vo_wayland_state *wl, uint32_t serial);
+
+/* Wayland listener boilerplate */
static void pointer_handle_enter(void *data, struct wl_pointer *pointer,
uint32_t serial, struct wl_surface *surface,
wl_fixed_t sx, wl_fixed_t sy)
@@ -189,48 +194,6 @@ static void pointer_handle_motion(void *data, struct wl_pointer *pointer,
wl->toplevel_configured = false;
}
-static void window_move(struct vo_wayland_state *wl, uint32_t serial)
-{
- if (wl->xdg_toplevel)
- xdg_toplevel_move(wl->xdg_toplevel, wl->seat, serial);
-}
-
-static int check_for_resize(struct vo_wayland_state *wl, wl_fixed_t x_w, wl_fixed_t y_w,
- int edge_pixels, enum xdg_toplevel_resize_edge *edge)
-{
- if (wl->touch_entries || wl->vo_opts->fullscreen || wl->vo_opts->window_maximized)
- return 0;
-
- int pos[2] = { wl_fixed_to_double(x_w), wl_fixed_to_double(y_w) };
- int left_edge = pos[0] < edge_pixels;
- int top_edge = pos[1] < edge_pixels;
- int right_edge = pos[0] > (mp_rect_w(wl->geometry) - edge_pixels);
- int bottom_edge = pos[1] > (mp_rect_h(wl->geometry) - edge_pixels);
-
- if (left_edge) {
- *edge = XDG_TOPLEVEL_RESIZE_EDGE_LEFT;
- if (top_edge)
- *edge = XDG_TOPLEVEL_RESIZE_EDGE_TOP_LEFT;
- else if (bottom_edge)
- *edge = XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM_LEFT;
- } else if (right_edge) {
- *edge = XDG_TOPLEVEL_RESIZE_EDGE_RIGHT;
- if (top_edge)
- *edge = XDG_TOPLEVEL_RESIZE_EDGE_TOP_RIGHT;
- else if (bottom_edge)
- *edge = XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM_RIGHT;
- } else if (top_edge) {
- *edge = XDG_TOPLEVEL_RESIZE_EDGE_TOP;
- } else if (bottom_edge) {
- *edge = XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM;
- } else {
- *edge = 0;
- return 0;
- }
-
- return 1;
-}
-
static void pointer_handle_button(void *data, struct wl_pointer *wl_pointer,
uint32_t serial, uint32_t time, uint32_t button,
uint32_t state)
@@ -377,68 +340,6 @@ static const struct wl_touch_listener touch_listener = {
touch_handle_cancel,
};
-static const struct mp_keymap keymap[] = {
- /* Special keys */
- {XKB_KEY_Pause, MP_KEY_PAUSE}, {XKB_KEY_Escape, MP_KEY_ESC},
- {XKB_KEY_BackSpace, MP_KEY_BS}, {XKB_KEY_Tab, MP_KEY_TAB},
- {XKB_KEY_Return, MP_KEY_ENTER}, {XKB_KEY_Menu, MP_KEY_MENU},
- {XKB_KEY_Print, MP_KEY_PRINT},
-
- /* Cursor keys */
- {XKB_KEY_Left, MP_KEY_LEFT}, {XKB_KEY_Right, MP_KEY_RIGHT},
- {XKB_KEY_Up, MP_KEY_UP}, {XKB_KEY_Down, MP_KEY_DOWN},
-
- /* Navigation keys */
- {XKB_KEY_Insert, MP_KEY_INSERT}, {XKB_KEY_Delete, MP_KEY_DELETE},
- {XKB_KEY_Home, MP_KEY_HOME}, {XKB_KEY_End, MP_KEY_END},
- {XKB_KEY_Page_Up, MP_KEY_PAGE_UP}, {XKB_KEY_Page_Down, MP_KEY_PAGE_DOWN},
-
- /* F-keys */
- {XKB_KEY_F1, MP_KEY_F + 1}, {XKB_KEY_F2, MP_KEY_F + 2},
- {XKB_KEY_F3, MP_KEY_F + 3}, {XKB_KEY_F4, MP_KEY_F + 4},
- {XKB_KEY_F5, MP_KEY_F + 5}, {XKB_KEY_F6, MP_KEY_F + 6},
- {XKB_KEY_F7, MP_KEY_F + 7}, {XKB_KEY_F8, MP_KEY_F + 8},
- {XKB_KEY_F9, MP_KEY_F + 9}, {XKB_KEY_F10, MP_KEY_F +10},
- {XKB_KEY_F11, MP_KEY_F +11}, {XKB_KEY_F12, MP_KEY_F +12},
-
- /* Numpad independent of numlock */
- {XKB_KEY_KP_Subtract, '-'}, {XKB_KEY_KP_Add, '+'},
- {XKB_KEY_KP_Multiply, '*'}, {XKB_KEY_KP_Divide, '/'},
- {XKB_KEY_KP_Enter, MP_KEY_KPENTER},
-
- /* Numpad with numlock */
- {XKB_KEY_KP_0, MP_KEY_KP0}, {XKB_KEY_KP_1, MP_KEY_KP1},
- {XKB_KEY_KP_2, MP_KEY_KP2}, {XKB_KEY_KP_3, MP_KEY_KP3},
- {XKB_KEY_KP_4, MP_KEY_KP4}, {XKB_KEY_KP_5, MP_KEY_KP5},
- {XKB_KEY_KP_6, MP_KEY_KP6}, {XKB_KEY_KP_7, MP_KEY_KP7},
- {XKB_KEY_KP_8, MP_KEY_KP8}, {XKB_KEY_KP_9, MP_KEY_KP9},
- {XKB_KEY_KP_Decimal, MP_KEY_KPDEC}, {XKB_KEY_KP_Separator, MP_KEY_KPDEC},
-
- /* Numpad without numlock */
- {XKB_KEY_KP_Insert, MP_KEY_KPINS}, {XKB_KEY_KP_End, MP_KEY_KP1},
- {XKB_KEY_KP_Down, MP_KEY_KP2}, {XKB_KEY_KP_Page_Down, MP_KEY_KP3},
- {XKB_KEY_KP_Left, MP_KEY_KP4}, {XKB_KEY_KP_Begin, MP_KEY_KP5},
- {XKB_KEY_KP_Right, MP_KEY_KP6}, {XKB_KEY_KP_Home, MP_KEY_KP7},
- {XKB_KEY_KP_Up, MP_KEY_KP8}, {XKB_KEY_KP_Page_Up, MP_KEY_KP9},
- {XKB_KEY_KP_Delete, MP_KEY_KPDEL},
-
- /* Multimedia keys */
- {XKB_KEY_XF86MenuKB, MP_KEY_MENU},
- {XKB_KEY_XF86AudioPlay, MP_KEY_PLAY}, {XKB_KEY_XF86AudioPause, MP_KEY_PAUSE},
- {XKB_KEY_XF86AudioStop, MP_KEY_STOP},
- {XKB_KEY_XF86AudioPrev, MP_KEY_PREV}, {XKB_KEY_XF86AudioNext, MP_KEY_NEXT},
- {XKB_KEY_XF86AudioRewind, MP_KEY_REWIND},
- {XKB_KEY_XF86AudioForward, MP_KEY_FORWARD},
- {XKB_KEY_XF86AudioMute, MP_KEY_MUTE},
- {XKB_KEY_XF86AudioLowerVolume, MP_KEY_VOLUME_DOWN},
- {XKB_KEY_XF86AudioRaiseVolume, MP_KEY_VOLUME_UP},
- {XKB_KEY_XF86HomePage, MP_KEY_HOMEPAGE}, {XKB_KEY_XF86WWW, MP_KEY_WWW},
- {XKB_KEY_XF86Mail, MP_KEY_MAIL}, {XKB_KEY_XF86Favorites, MP_KEY_FAVORITES},
- {XKB_KEY_XF86Search, MP_KEY_SEARCH}, {XKB_KEY_XF86Sleep, MP_KEY_SLEEP},
-
- {0, 0}
-};
-
static void keyboard_handle_keymap(void *data, struct wl_keyboard *wl_keyboard,
uint32_t format, int32_t fd, uint32_t size)
{
@@ -491,34 +392,6 @@ static void keyboard_handle_leave(void *data, struct wl_keyboard *wl_keyboard,
wl->has_keyboard_input = false;
}
-static bool create_input(struct vo_wayland_state *wl)
-{
- wl->xkb_context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
-
- if (!wl->xkb_context) {
- MP_ERR(wl, "failed to initialize input: check xkbcommon\n");
- return 1;
- }
-
- return 0;
-}
-
-static int lookupkey(int key)
-{
- const char *passthrough_keys = " -+*/<>`~!@#$%^&()_{}:;\"\',.?\\|=[]";
-
- int mpkey = 0;
- if ((key >= 'a' && key <= 'z') || (key >= 'A' && key <= 'Z') ||
- (key >= '0' && key <= '9') ||
- (key > 0 && key < 256 && strchr(passthrough_keys, key)))
- mpkey = key;
-
- if (!mpkey)
- mpkey = lookup_keymap_table(keymap, key);
-
- return mpkey;
-}
-
static void keyboard_handle_key(void *data, struct wl_keyboard *wl_keyboard,
uint32_t serial, uint32_t time, uint32_t key,
uint32_t state)
@@ -605,126 +478,6 @@ static const struct wl_seat_listener seat_listener = {
seat_handle_caps,
};
-static void greatest_common_divisor(struct vo_wayland_state *wl, int a, int b) {
- // euclidean algorithm
- int larger;
- int smaller;
- if (a > b) {
- larger = a;
- smaller = b;
- } else {
- larger = b;
- smaller = a;
- }
- int remainder = larger - smaller * floor(larger/smaller);
- if (remainder == 0) {
- wl->gcd = smaller;
- } else {
- greatest_common_divisor(wl, smaller, remainder);
- }
-}
-
-static void set_geometry(struct vo_wayland_state *wl)
-{
- struct vo *vo = wl->vo;
-
- struct vo_win_geometry geo;
- struct mp_rect screenrc = wl->current_output->geometry;
- vo_calc_window_geometry(vo, &screenrc, &geo);
- vo_apply_window_geometry(vo, &geo);
-
- greatest_common_divisor(wl, vo->dwidth, vo->dheight);
- wl->reduced_width = vo->dwidth / wl->gcd;
- wl->reduced_height = vo->dheight / wl->gcd;
-
- wl->vdparams.x0 = 0;
- wl->vdparams.y0 = 0;
- wl->vdparams.x1 = vo->dwidth / wl->scaling;
- wl->vdparams.y1 = vo->dheight / wl->scaling;
-}
-
-static void output_handle_geometry(void *data, struct wl_output *wl_output,
- int32_t x, int32_t y, int32_t phys_width,
- int32_t phys_height, int32_t subpixel,
- const char *make, const char *model,
- int32_t transform)
-{
- struct vo_wayland_output *output = data;
- output->make = talloc_strdup(output->wl, make);
- output->model = talloc_strdup(output->wl, model);
- output->geometry.x0 = x;
- output->geometry.y0 = y;
- output->phys_width = phys_width;
- output->phys_height = phys_height;
-}
-
-static void output_handle_mode(void *data, struct wl_output *wl_output,
- uint32_t flags, int32_t width,
- int32_t height, int32_t refresh)
-{
- struct vo_wayland_output *output = data;
-
- /* Only save current mode */
- if (!(flags & WL_OUTPUT_MODE_CURRENT))
- return;
-
- output->geometry.x1 = width;
- output->geometry.y1 = height;
- output->flags = flags;
- output->refresh_rate = (double)refresh * 0.001;
-}
-
-static void output_handle_done(void* data, struct wl_output *wl_output)
-{
- struct vo_wayland_output *o = data;
- struct vo_wayland_state *wl = o->wl;
-
- o->geometry.x1 += o->geometry.x0;
- o->geometry.y1 += o->geometry.y0;
-
- MP_VERBOSE(o->wl, "Registered output %s %s (0x%x):\n"
- "\tx: %dpx, y: %dpx\n"
- "\tw: %dpx (%dmm), h: %dpx (%dmm)\n"
- "\tscale: %d\n"
- "\tHz: %f\n", o->make, o->model, o->id, o->geometry.x0,
- o->geometry.y0, mp_rect_w(o->geometry), o->phys_width,
- mp_rect_h(o->geometry), o->phys_height, o->scale, o->refresh_rate);
-
- /* If we satisfy this conditional, something about the current
- * output must have changed (resolution, scale, etc). All window
- * geometry and scaling should be recalculated. */
- if (wl->current_output && wl->current_output->output == wl_output) {
- wl->scaling = wl->current_output->scale;
- spawn_cursor(wl);
- set_geometry(wl);
- wl->window_size = wl->vdparams;
- if (!wl->vo_opts->fullscreen && !wl->vo_opts->window_maximized)
- wl->geometry = wl->window_size;
- wl->pending_vo_events |= VO_EVENT_DPI;
- wl->pending_vo_events |= VO_EVENT_RESIZE;
- }
-
- wl->pending_vo_events |= VO_EVENT_WIN_STATE;
-}
-
-static void output_handle_scale(void* data, struct wl_output *wl_output,
- int32_t factor)
-{
- struct vo_wayland_output *output = data;
- if (!factor) {
- MP_ERR(output->wl, "Invalid output scale given by the compositor!\n");
- return;
- }
- output->scale = factor;
-}
-
-static const struct wl_output_listener output_listener = {
- output_handle_geometry,
- output_handle_mode,
- output_handle_done,
- output_handle_scale,
-};
-
static void data_offer_handle_offer(void *data, struct wl_data_offer *offer,
const char *mime_type)
{
@@ -848,18 +601,88 @@ static const struct wl_data_device_listener data_device_listener = {
data_device_handle_selection,
};
-static void rescale_geometry_dimensions(struct vo_wayland_state *wl, double factor)
+static void output_handle_geometry(void *data, struct wl_output *wl_output,
+ int32_t x, int32_t y, int32_t phys_width,
+ int32_t phys_height, int32_t subpixel,
+ const char *make, const char *model,
+ int32_t transform)
{
- wl->vdparams.x1 *= factor;
- wl->vdparams.y1 *= factor;
- wl->window_size.x1 *= factor;
- wl->window_size.y1 *= factor;
- if (!wl->vo_opts->fullscreen && !wl->vo_opts->window_maximized) {
- wl->geometry.x1 *= factor;
- wl->geometry.y1 *= factor;
+ struct vo_wayland_output *output = data;
+ output->make = talloc_strdup(output->wl, make);
+ output->model = talloc_strdup(output->wl, model);
+ output->geometry.x0 = x;
+ output->geometry.y0 = y;
+ output->phys_width = phys_width;
+ output->phys_height = phys_height;
+}
+
+static void output_handle_mode(void *data, struct wl_output *wl_output,
+ uint32_t flags, int32_t width,
+ int32_t height, int32_t refresh)
+{
+ struct vo_wayland_output *output = data;
+
+ /* Only save current mode */
+ if (!(flags & WL_OUTPUT_MODE_CURRENT))
+ return;
+
+ output->geometry.x1 = width;
+ output->geometry.y1 = height;
+ output->flags = flags;
+ output->refresh_rate = (double)refresh * 0.001;
+}
+
+static void output_handle_done(void* data, struct wl_output *wl_output)
+{
+ struct vo_wayland_output *o = data;
+ struct vo_wayland_state *wl = o->wl;
+
+ o->geometry.x1 += o->geometry.x0;
+ o->geometry.y1 += o->geometry.y0;
+
+ MP_VERBOSE(o->wl, "Registered output %s %s (0x%x):\n"
+ "\tx: %dpx, y: %dpx\n"
+ "\tw: %dpx (%dmm), h: %dpx (%dmm)\n"
+ "\tscale: %d\n"
+ "\tHz: %f\n", o->make, o->model, o->id, o->geometry.x0,
+ o->geometry.y0, mp_rect_w(o->geometry), o->phys_width,
+ mp_rect_h(o->geometry), o->phys_height, o->scale, o->refresh_rate);
+
+ /* If we satisfy this conditional, something about the current
+ * output must have changed (resolution, scale, etc). All window
+ * geometry and scaling should be recalculated. */
+ if (wl->current_output && wl->current_output->output == wl_output) {
+ wl->scaling = wl->current_output->scale;
+ spawn_cursor(wl);
+ set_geometry(wl);
+ wl->window_size = wl->vdparams;
+ if (!wl->vo_opts->fullscreen && !wl->vo_opts->window_maximized)
+ wl->geometry = wl->window_size;
+ wl->pending_vo_events |= VO_EVENT_DPI;
+ wl->pending_vo_events |= VO_EVENT_RESIZE;
+ }
+
+ wl->pending_vo_events |= VO_EVENT_WIN_STATE;
+}
+
+static void output_handle_scale(void* data, struct wl_output *wl_output,
+ int32_t factor)
+{
+ struct vo_wayland_output *output = data;
+ if (!factor) {
+ MP_ERR(output->wl, "Invalid output scale given by the compositor!\n");
+ return;
}
+ output->scale = factor;
}
+static const struct wl_output_listener output_listener = {
+ output_handle_geometry,
+ output_handle_mode,
+ output_handle_done,
+ output_handle_scale,
+};
+
static void surface_handle_enter(void *data, struct wl_surface *wl_surface,
struct wl_output *output)
{
@@ -925,184 +748,13 @@ static const struct wl_surface_listener surface_listener = {
surface_handle_leave,
};
-static void pres_set_clockid(void *data, struct wp_presentation *pres,
- uint32_t clockid)
-{
- struct vo_wayland_state *wl = data;
-
- if (clockid == CLOCK_MONOTONIC)
- wl->presentation = pres;
-}
-
-static const struct wp_presentation_listener pres_listener = {
- pres_set_clockid,
-};
-
-static const struct wp_presentation_feedback_listener feedback_listener;
-
-static void feedback_sync_output(void *data, struct wp_presentation_feedback *fback,
- struct wl_output *output)
-{
-}
-
-static void feedback_presented(void *data, struct wp_presentation_feedback *fback,
- uint32_t tv_sec_hi, uint32_t tv_sec_lo,
- uint32_t tv_nsec, uint32_t refresh_nsec,
- uint32_t seq_hi, uint32_t seq_lo,
- uint32_t flags)
-{
- struct vo_wayland_state *wl = data;
- vo_wayland_sync_shift(wl);
-
- if (fback)
- wp_presentation_feedback_destroy(fback);
-
- wl->refresh_interval = (int64_t)refresh_nsec / 1000;
-
- // Very similar to oml_sync_control, in this case we assume that every
- // time the compositor receives feedback, a buffer swap has been already
- // been performed.
- //
- // Notes:
- // - tv_sec_lo + tv_sec_hi is the equivalent of oml's ust
- // - seq_lo + seq_hi is the equivalent of oml's msc
- // - these values are updated everytime the compositor receives feedback.
-
- int index = last_available_sync(wl);
- if (index < 0) {
- queue_new_sync(wl);
- index = 0;
- }
- int64_t sec = (uint64_t) tv_sec_lo + ((uint64_t) tv_sec_hi << 32);
- wl->sync[index].ust = sec * 1000000LL + (uint64_t) tv_nsec / 1000;
- wl->sync[index].msc = (uint64_t) seq_lo + ((uint64_t) seq_hi << 32);
- wl->sync[index].filled = true;
-}
-
-static void feedback_discarded(void *data, struct wp_presentation_feedback *fback)
-{
-}
-
-static const struct wp_presentation_feedback_listener feedback_listener = {
- feedback_sync_output,
- feedback_presented,
- feedback_discarded,
-};
-
-static const struct wl_callback_listener frame_listener;
-
-static void frame_callback(void *data, struct wl_callback *callback, uint32_t time)
-{
- struct vo_wayland_state *wl = data;
-
- if (callback)
- wl_callback_destroy(callback);
-
- wl->frame_callback = wl_surface_frame(wl->surface);
- wl_callback_add_listener(wl->frame_callback, &frame_listener, wl);
-
- if (wl->presentation) {
- wl->feedback = wp_presentation_feedback(wl->presentation, wl->surface);
- wp_presentation_feedback_add_listener(wl->feedback, &feedback_listener, wl);
- }
-
- wl->frame_wait = false;
-}
-
-static const struct wl_callback_listener frame_listener = {
- frame_callback,
-};
-
-static void registry_handle_add(void *data, struct wl_registry *reg, uint32_t id,
- const char *interface, uint32_t ver)
-{
- int found = 1;
- struct vo_wayland_state *wl = data;
-
- if (!strcmp(interface, wl_compositor_interface.name) && (ver >= 3) && found++) {
- wl->compositor = wl_registry_bind(reg, id, &wl_compositor_interface, 3);
- wl->surface = wl_compositor_create_surface(wl->compositor);
- wl->cursor_surface = wl_compositor_create_surface(wl->compositor);
- wl_surface_add_listener(wl->surface, &surface_listener, wl);
- }
-
- if (!strcmp(interface, wl_output_interface.name) && (ver >= 2) && found++) {
- struct vo_wayland_output *output = talloc_zero(wl, struct vo_wayland_output);
-
- output->wl = wl;
- output->id = id;
- output->scale = 1;
- output->output = wl_registry_bind(reg, id, &wl_output_interface, 2);
-
- wl_output_add_listener(output->output, &output_listener, output);
- wl_list_insert(&wl->output_list, &output->link);
- }
-
- if (!strcmp(interface, xdg_wm_base_interface.name) && found++) {
- ver = MPMIN(ver, 2); /* We can use either 1 or 2 */
- wl->wm_base = wl_registry_bind(reg, id, &xdg_wm_base_interface, ver);
- xdg_wm_base_add_listener(wl->wm_base, &xdg_wm_base_listener, wl);
- }
-
- if (!strcmp(interface, wl_seat_interface.name) && found++) {
- wl->seat = wl_registry_bind(reg, id, &wl_seat_interface, 1);
- wl_seat_add_listener(wl->seat, &seat_listener, wl);
- }
-
- if (!strcmp(interface, wl_shm_interface.name) && found++) {
- wl->shm = wl_registry_bind(reg, id, &wl_shm_interface, 1);
- }
-
- if (!strcmp(interface, wl_data_device_manager_interface.name) && (ver >= 3) && found++) {
- wl->dnd_devman = wl_registry_bind(reg, id, &wl_data_device_manager_interface, 3);
- }
-
- if (!strcmp(interface, zxdg_decoration_manager_v1_interface.name) && found++) {
- wl->xdg_decoration_manager = wl_registry_bind(reg, id, &zxdg_decoration_manager_v1_interface, 1);
- }
-
- if (!strcmp(interface, wp_presentation_interface.name) && found++) {
- wl->presentation = wl_registry_bind(reg, id, &wp_presentation_interface, 1);
- wp_presentation_add_listener(wl->presentation, &pres_listener, wl);
- }
-
- if (!strcmp(interface, zwp_idle_inhibit_manager_v1_interface.name) && found++) {
- wl->idle_inhibit_manager = wl_registry_bind(reg, id, &zwp_idle_inhibit_manager_v1_interface, 1);
- }
-
- if (found > 1)
- MP_VERBOSE(wl, "Registered for protocol %s\n", interface);
-}
-
-static void remove_output(struct vo_wayland_output *out)
-{
- if (!out)
- return;
-
- MP_VERBOSE(out->wl, "Deregistering output %s %s (0x%x)\n", out->make,
- out->model, out->id);
- wl_list_remove(&out->link);
- talloc_free(out->make);
- talloc_free(out->model);
- talloc_free(out);
- return;
-}
-
-static void registry_handle_remove(void *data, struct wl_registry *reg, uint32_t id)
+static void xdg_wm_base_ping(void *data, struct xdg_wm_base *wm_base, uint32_t serial)
{
- struct vo_wayland_state *wl = data;
- struct vo_wayland_output *output, *tmp;
- wl_list_for_each_safe(output, tmp, &wl->output_list, link) {
- if (output->id == id) {
- remove_output(output);
- return;
- }
- }
+ xdg_wm_base_pong(wm_base, serial);
}
-static const struct wl_registry_listener registry_listener = {
- registry_handle_add,
- registry_handle_remove,
+static const struct xdg_wm_base_listener xdg_wm_base_listener = {
+ xdg_wm_base_ping,
};
static void handle_surface_config(void *data, struct xdg_surface *surface,
@@ -1249,246 +901,342 @@ static const struct xdg_toplevel_listener xdg_toplevel_listener = {
handle_toplevel_close,
};
-static int create_xdg_surface(struct vo_wayland_state *wl)
+static void pres_set_clockid(void *data, struct wp_presentation *pres,
+ uint32_t clockid)
{
- wl->xdg_surface = xdg_wm_base_get_xdg_surface(wl->wm_base, wl->surface);
- xdg_surface_add_listener(wl->xdg_surface, &xdg_surface_listener, wl);
-
- wl->xdg_toplevel = xdg_surface_get_toplevel(wl->xdg_surface);
- xdg_toplevel_add_listener(wl->xdg_toplevel, &xdg_toplevel_listener, wl);
+ struct vo_wayland_state *wl = data;
- if (!wl->xdg_surface || !wl->xdg_toplevel)
- return 1;
- return 0;
+ if (clockid == CLOCK_MONOTONIC)
+ wl->presentation = pres;
}
-static void update_app_id(struct vo_wayland_state *wl)
+static const struct wp_presentation_listener pres_listener = {
+ pres_set_clockid,
+};
+
+static void feedback_sync_output(void *data, struct wp_presentation_feedback *fback,
+ struct wl_output *output)
{
- if (!wl->xdg_toplevel)
- return;
- if (!wl->vo_opts->appid) {
- wl->vo_opts->appid = talloc_strdup(wl->vo_opts, "mpv");
- m_config_cache_write_opt(wl->vo_opts_cache, &wl->vo_opts->appid);
- }
- xdg_toplevel_set_app_id(wl->xdg_toplevel, wl->vo_opts->appid);
}
-static void set_border_decorations(struct vo_wayland_state *wl, int state)
+static void feedback_presented(void *data, struct wp_presentation_feedback *fback,
+ uint32_t tv_sec_hi, uint32_t tv_sec_lo,
+ uint32_t tv_nsec, uint32_t refresh_nsec,
+ uint32_t seq_hi, uint32_t seq_lo,
+ uint32_t flags)
{
- if (!wl->xdg_toplevel_decoration) {
- wl->vo_opts->border = false;
- m_config_cache_write_opt(wl->vo_opts_cache,
- &wl->vo_opts->border);
- return;
- }
+ struct vo_wayland_state *wl = data;
+ sync_shift(wl);
- enum zxdg_toplevel_decoration_v1_mode mode;
- if (state) {
- MP_VERBOSE(wl, "Enabling server decorations\n");