summaryrefslogtreecommitdiffstats
path: root/video/out/wayland_common.c
diff options
context:
space:
mode:
authorRostislav Pehlivanov <atomnuker@gmail.com>2017-10-01 21:16:49 +0100
committerRostislav Pehlivanov <atomnuker@gmail.com>2017-10-03 19:36:02 +0100
commit68f9ee7e0b3fdddfa42fa11a15d9ae84460d5e19 (patch)
tree91b3c4dd976c54a241dc17d04ccdd15e1cf70ff8 /video/out/wayland_common.c
parent980116360b0f393e16064ec3b7a4ef9efb14372e (diff)
downloadmpv-68f9ee7e0b3fdddfa42fa11a15d9ae84460d5e19.tar.bz2
mpv-68f9ee7e0b3fdddfa42fa11a15d9ae84460d5e19.tar.xz
wayland_common: rewrite from scratch
The wayland code was written more than 4 years ago when wayland wasn't even at version 1.0. This commit rewrites everything in a more modern way, switches to using the new xdg v6 shell interface which solves a lot of bugs and makes mpv tiling-friedly, adds support for drag and drop, adds support for touchscreens, adds support for KDE's server decorations protocol, and finally adds support for the new idle-inhibitor protocol. It does not yet use the frame callback as a main rendering loop driver, this will happen with a later commit.
Diffstat (limited to 'video/out/wayland_common.c')
-rw-r--r--video/out/wayland_common.c1720
1 files changed, 927 insertions, 793 deletions
diff --git a/video/out/wayland_common.c b/video/out/wayland_common.c
index fedebb3f8d..fb98308de2 100644
--- a/video/out/wayland_common.c
+++ b/video/out/wayland_common.c
@@ -1,8 +1,5 @@
/*
* This file is part of mpv video player.
- * Copyright © 2008 Kristian Høgsberg
- * Copyright © 2012-2013 Collabora, Ltd.
- * Copyright © 2013 Alexander Preisinger <alexander.preisinger@gmail.com>
*
* mpv is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -18,80 +15,269 @@
* License along with mpv. If not, see <http://www.gnu.org/licenses/>.
*/
-#include <stdio.h>
-#include <stdlib.h>
-#include <math.h>
-#include <inttypes.h>
-#include <limits.h>
-#include <assert.h>
#include <poll.h>
#include <unistd.h>
-
-#include <sys/mman.h>
#include <linux/input.h>
-
-#include "config.h"
-#include "misc/bstr.h"
-#include "options/options.h"
#include "common/msg.h"
-#include "mpv_talloc.h"
-
-#include "wayland_common.h"
-
-#include "vo.h"
-#include "win_state.h"
+#include "input/input.h"
+#include "input/keycodes.h"
#include "osdep/io.h"
#include "osdep/timer.h"
+#include "win_state.h"
+#include "wayland_common.h"
-#include "input/input.h"
-#include "input/event.h"
-#include "input/keycodes.h"
+// Generated from xdg-shell-unstable-v6.xml
+#include "video/out/wayland/xdg-shell-v6.h"
-static int lookupkey(int key);
+// Generated from idle-inhibit-unstable-v1.xml
+#include "video/out/wayland/idle-inhibit-v1.h"
-static void hide_cursor(struct vo_wayland_state * wl);
-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);
+// Generated from server-decoration.xml
+#include "video/out/wayland/srv-decor.h"
-static void vo_wayland_fullscreen(struct vo *vo);
+static void xdg_shell_ping(void *data, struct zxdg_shell_v6 *shell, uint32_t serial)
+{
+ zxdg_shell_v6_pong(shell, serial);
+}
-static const struct wl_callback_listener frame_listener;
+static const struct zxdg_shell_v6_listener xdg_shell_listener = {
+ xdg_shell_ping,
+};
+
+static void set_cursor_visibility(struct vo_wayland_state *wl, int on)
+{
+ if (!wl->pointer)
+ return;
+ if (on) {
+ struct wl_cursor_image *image = wl->default_cursor->images[0];
+ struct wl_buffer *buffer = wl_cursor_image_get_buffer(image);
+ if (!buffer)
+ return;
+ wl_pointer_set_cursor(wl->pointer, wl->pointer_id, wl->cursor_surface,
+ image->hotspot_x, image->hotspot_y);
+ wl_surface_attach(wl->cursor_surface, buffer, 0, 0);
+ wl_surface_damage(wl->cursor_surface, 0, 0, image->width, image->height);
+ wl_surface_commit(wl->cursor_surface);
+ } else {
+ wl_pointer_set_cursor(wl->pointer, wl->pointer_id, NULL, 0, 0);
+ }
+}
+
+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)
+{
+ struct vo_wayland_state *wl = data;
+
+ wl->pointer = pointer;
+ wl->pointer_id = serial;
+
+ set_cursor_visibility(wl, 1);
+ mp_input_put_key(wl->vo->input_ctx, MP_KEY_MOUSE_ENTER);
+}
+
+static void pointer_handle_leave(void *data, struct wl_pointer *pointer,
+ uint32_t serial, struct wl_surface *surface)
+{
+ struct vo_wayland_state *wl = data;
+ mp_input_put_key(wl->vo->input_ctx, MP_KEY_MOUSE_LEAVE);
+}
+
+static void pointer_handle_motion(void *data, struct wl_pointer *pointer,
+ uint32_t time, wl_fixed_t sx, wl_fixed_t sy)
+{
+ struct vo_wayland_state *wl = data;
+
+ wl->mouse_x = wl_fixed_to_int(sx) * wl->scaling;
+ wl->mouse_y = wl_fixed_to_int(sy) * wl->scaling;
+
+ mp_input_set_mouse_pos(wl->vo->input_ctx, wl->mouse_x, wl->mouse_y);
+}
+
+static void window_move(struct vo_wayland_state *wl, uint32_t serial)
+{
+ if (wl->xdg_toplevel)
+ zxdg_toplevel_v6_move(wl->xdg_toplevel, wl->seat, serial);
+}
+
+static void pointer_handle_button(void *data, struct wl_pointer *wl_pointer,
+ uint32_t serial, uint32_t time, uint32_t button,
+ uint32_t state)
+{
+ struct vo_wayland_state *wl = data;
+
+ state = state == WL_POINTER_BUTTON_STATE_PRESSED ? MP_KEY_STATE_DOWN
+ : MP_KEY_STATE_UP;
+
+ button = button == BTN_LEFT ? MP_MBTN_LEFT :
+ button == BTN_MIDDLE ? MP_MBTN_MID : MP_MBTN_RIGHT;
+
+ mp_input_put_key(wl->vo->input_ctx, button | state);
+
+ if (!mp_input_test_dragging(wl->vo->input_ctx, wl->mouse_x, wl->mouse_y) &&
+ (button == MP_MBTN_LEFT) && (state == MP_KEY_STATE_DOWN))
+ window_move(wl, serial);
+}
+
+static void pointer_handle_axis(void *data, struct wl_pointer *wl_pointer,
+ uint32_t time, uint32_t axis, wl_fixed_t value)
+{
+ struct vo_wayland_state *wl = data;
+ double val = wl_fixed_to_double(value)*0.1;
+ switch (axis) {
+ case WL_POINTER_AXIS_VERTICAL_SCROLL:
+ if (value > 0)
+ mp_input_put_wheel(wl->vo->input_ctx, MP_WHEEL_DOWN, +val);
+ if (value < 0)
+ mp_input_put_wheel(wl->vo->input_ctx, MP_WHEEL_UP, -val);
+ break;
+ case WL_POINTER_AXIS_HORIZONTAL_SCROLL:
+ if (value > 0)
+ mp_input_put_wheel(wl->vo->input_ctx, MP_WHEEL_RIGHT, +val);
+ if (value < 0)
+ mp_input_put_wheel(wl->vo->input_ctx, MP_WHEEL_LEFT, -val);
+ break;
+ }
+}
+
+static const struct wl_pointer_listener pointer_listener = {
+ pointer_handle_enter,
+ pointer_handle_leave,
+ pointer_handle_motion,
+ pointer_handle_button,
+ pointer_handle_axis,
+};
+
+static int check_for_resize(struct vo_wayland_state *wl, wl_fixed_t x_w, wl_fixed_t y_w,
+ enum zxdg_toplevel_v6_resize_edge *edge)
+{
+ if (wl->touch_entries || wl->fullscreen)
+ return 0;
+
+ const int edge_pixels = 64;
+ 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 = ZXDG_TOPLEVEL_V6_RESIZE_EDGE_LEFT;
+ if (top_edge)
+ *edge = ZXDG_TOPLEVEL_V6_RESIZE_EDGE_TOP_LEFT;
+ else if (bottom_edge)
+ *edge = ZXDG_TOPLEVEL_V6_RESIZE_EDGE_BOTTOM_LEFT;
+ } else if (right_edge) {
+ *edge = ZXDG_TOPLEVEL_V6_RESIZE_EDGE_RIGHT;
+ if (top_edge)
+ *edge = ZXDG_TOPLEVEL_V6_RESIZE_EDGE_TOP_RIGHT;
+ else if (bottom_edge)
+ *edge = ZXDG_TOPLEVEL_V6_RESIZE_EDGE_BOTTOM_RIGHT;
+ } else if (top_edge) {
+ *edge = ZXDG_TOPLEVEL_V6_RESIZE_EDGE_TOP;
+ } else if (bottom_edge) {
+ *edge = ZXDG_TOPLEVEL_V6_RESIZE_EDGE_BOTTOM;
+ } else {
+ *edge = 0;
+ return 0;
+ }
+
+ return 1;
+}
+
+static void touch_handle_down(void *data, struct wl_touch *wl_touch,
+ uint32_t serial, uint32_t time, struct wl_surface *surface,
+ int32_t id, wl_fixed_t x_w, wl_fixed_t y_w)
+{
+ struct vo_wayland_state *wl = data;
+
+ enum zxdg_toplevel_v6_resize_edge edge;
+ if (check_for_resize(wl, x_w, y_w, &edge)) {
+ wl->touch_entries = 0;
+ zxdg_toplevel_v6_resize(wl->xdg_toplevel, wl->seat, serial, edge);
+ return;
+ } else if (wl->touch_entries) {
+ wl->touch_entries = 0;
+ zxdg_toplevel_v6_move(wl->xdg_toplevel, wl->seat, serial);
+ return;
+ }
+
+ wl->touch_entries = 1;
+
+ wl->mouse_x = wl_fixed_to_int(x_w) * wl->scaling;
+ wl->mouse_y = wl_fixed_to_int(y_w) * wl->scaling;
+
+ mp_input_set_mouse_pos(wl->vo->input_ctx, wl->mouse_x, wl->mouse_y);
+ mp_input_put_key(wl->vo->input_ctx, MP_MBTN_LEFT | MP_KEY_STATE_DOWN);
+}
+
+static void touch_handle_up(void *data, struct wl_touch *wl_touch,
+ uint32_t serial, uint32_t time, int32_t id)
+{
+ struct vo_wayland_state *wl = data;
+
+ wl->touch_entries = 0;
+
+ mp_input_put_key(wl->vo->input_ctx, MP_MBTN_LEFT | MP_KEY_STATE_UP);
+}
+
+static void touch_handle_motion(void *data, struct wl_touch *wl_touch,
+ uint32_t time, int32_t id, wl_fixed_t x_w, wl_fixed_t y_w)
+{
+ struct vo_wayland_state *wl = data;
+
+ wl->mouse_x = wl_fixed_to_int(x_w) * wl->scaling;
+ wl->mouse_y = wl_fixed_to_int(y_w) * wl->scaling;
+
+ mp_input_set_mouse_pos(wl->vo->input_ctx, wl->mouse_x, wl->mouse_y);
+}
+
+static void touch_handle_frame(void *data, struct wl_touch *wl_touch)
+{
+}
+
+static void touch_handle_cancel(void *data, struct wl_touch *wl_touch)
+{
+}
+
+static const struct wl_touch_listener touch_listener = {
+ touch_handle_down,
+ touch_handle_up,
+ touch_handle_motion,
+ touch_handle_frame,
+ touch_handle_cancel,
+};
static const struct mp_keymap keymap[] = {
- // special keys
+ /* 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
+ /* 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 block
+ /* 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},
+ /* 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, '+'},
+ /* 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
+ /* 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},
@@ -99,7 +285,7 @@ static const struct mp_keymap keymap[] = {
{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
+ /* 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},
@@ -107,7 +293,7 @@ static const struct mp_keymap keymap[] = {
{XKB_KEY_KP_Up, MP_KEY_KP8}, {XKB_KEY_KP_Page_Up, MP_KEY_KP9},
{XKB_KEY_KP_Delete, MP_KEY_KPDEL},
- // "Multimedia keyboard" keys
+ /* 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},
@@ -124,137 +310,8 @@ static const struct mp_keymap keymap[] = {
{0, 0}
};
-
-/** Wayland listeners **/
-
-static void ssurface_handle_ping(void *data,
- struct wl_shell_surface *shell_surface,
- uint32_t serial)
-{
- wl_shell_surface_pong(shell_surface, serial);
-}
-
-static void ssurface_handle_configure(void *data,
- struct wl_shell_surface *shell_surface,
- uint32_t edges,
- int32_t width,
- int32_t height)
-{
- 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);
-}
-
-static void ssurface_handle_popup_done(void *data,
- struct wl_shell_surface *shell_surface)
-{
-}
-
-static const struct wl_shell_surface_listener shell_surface_listener = {
- ssurface_handle_ping,
- ssurface_handle_configure,
- ssurface_handle_popup_done
-};
-
-static void output_handle_geometry(void *data,
- struct wl_output *wl_output,
- int32_t x,
- int32_t y,
- int32_t physical_width,
- int32_t physical_height,
- int32_t subpixel,
- const char *make,
- const char *model,
- int32_t transform)
-{
- struct vo_wayland_output *output = data;
- output->make = make;
- output->model = model;
-}
-
-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 (!output || !(flags & WL_OUTPUT_MODE_CURRENT))
- return;
-
- output->width = width;
- output->height = height;
- output->flags = flags;
- output->refresh_rate = refresh;
-}
-
-static void output_handle_done(void* data, struct wl_output *wl_output)
-{
-}
-
-static void output_handle_scale(void* data, struct wl_output *wl_output,
- int32_t factor)
-{
- struct vo_wayland_output *output = data;
- output->scale = factor;
-}
-
-static const struct wl_output_listener output_listener = {
- output_handle_geometry,
- output_handle_mode,
- output_handle_done,
- output_handle_scale
-};
-
-
-/* SURFACE LISTENER */
-
-static void surface_handle_enter(void *data,
- struct wl_surface *wl_surface,
- struct wl_output *output)
-{
- struct vo_wayland_state *wl = data;
- wl->display.current_output = NULL;
-
- struct vo_wayland_output *o;
- wl_list_for_each(o, &wl->display.output_list, link) {
- if (o->output == output) {
- wl->display.current_output = o;
- break;
- }
- }
-
- wl->window.events |= VO_EVENT_WIN_STATE | VO_EVENT_RESIZE;
-}
-
-static void surface_handle_leave(void *data,
- struct wl_surface *wl_surface,
- struct wl_output *output)
-{
- // window can be displayed at 2 output, but we only use the most recently
- // entered and discard the previous one even if a part of the window is
- // still visible on the previous entered output.
- // Don't bother with a "leave" logic
-}
-
-static const struct wl_surface_listener surface_listener = {
- surface_handle_enter,
- surface_handle_leave
-};
-
-/* KEYBOARD LISTENER */
-static void keyboard_handle_keymap(void *data,
- struct wl_keyboard *wl_keyboard,
- uint32_t format,
- int32_t fd,
- uint32_t size)
+static void keyboard_handle_keymap(void *data, struct wl_keyboard *wl_keyboard,
+ uint32_t format, int32_t fd, uint32_t size)
{
struct vo_wayland_state *wl = data;
char *map_str;
@@ -270,68 +327,97 @@ static void keyboard_handle_keymap(void *data,
return;
}
- wl->input.xkb.keymap = xkb_keymap_new_from_string(wl->input.xkb.context,
- map_str,
- XKB_KEYMAP_FORMAT_TEXT_V1,
- 0);
+ wl->xkb_keymap = xkb_keymap_new_from_string(wl->xkb_context, map_str,
+ XKB_KEYMAP_FORMAT_TEXT_V1, 0);
munmap(map_str, size);
close(fd);
- if (!wl->input.xkb.keymap) {
+ if (!wl->xkb_keymap) {
MP_ERR(wl, "failed to compile keymap\n");
return;
}
- wl->input.xkb.state = xkb_state_new(wl->input.xkb.keymap);
- if (!wl->input.xkb.state) {
+ wl->xkb_state = xkb_state_new(wl->xkb_keymap);
+ if (!wl->xkb_state) {
MP_ERR(wl, "failed to create XKB state\n");
- xkb_keymap_unref(wl->input.xkb.keymap);
- wl->input.xkb.keymap = NULL;
+ xkb_keymap_unref(wl->xkb_keymap);
+ wl->xkb_keymap = NULL;
return;
}
}
-static void keyboard_handle_enter(void *data,
- struct wl_keyboard *wl_keyboard,
- uint32_t serial,
- struct wl_surface *surface,
+static void keyboard_handle_enter(void *data, struct wl_keyboard *wl_keyboard,
+ uint32_t serial, struct wl_surface *surface,
struct wl_array *keys)
{
}
-static void keyboard_handle_leave(void *data,
- struct wl_keyboard *wl_keyboard,
- uint32_t serial,
- struct wl_surface *surface)
+static void keyboard_handle_leave(void *data, struct wl_keyboard *wl_keyboard,
+ uint32_t serial, struct wl_surface *surface)
{
}
-static void keyboard_handle_key(void *data,
- struct wl_keyboard *wl_keyboard,
- uint32_t serial,
- uint32_t time,
- uint32_t key,
+static bool create_input(struct vo_wayland_state *wl)
+{
+ wl->xkb_context = xkb_context_new(0);
+
+ 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)
{
struct vo_wayland_state *wl = data;
uint32_t code = code = key + 8;
- xkb_keysym_t sym = xkb_state_key_get_one_sym(wl->input.xkb.state, code);
+ xkb_keysym_t sym = xkb_state_key_get_one_sym(wl->xkb_state, code);
int mpmod = state == WL_KEYBOARD_KEY_STATE_PRESSED ? MP_KEY_STATE_DOWN
: MP_KEY_STATE_UP;
- static const char *mod_names[] = {XKB_MOD_NAME_SHIFT, XKB_MOD_NAME_CTRL,
- XKB_MOD_NAME_ALT, XKB_MOD_NAME_LOGO, 0};
- static int mods[] = {MP_KEY_MODIFIER_SHIFT, MP_KEY_MODIFIER_CTRL,
- MP_KEY_MODIFIER_ALT, MP_KEY_MODIFIER_META, 0};
+ static const char *mod_names[] = {
+ XKB_MOD_NAME_SHIFT,
+ XKB_MOD_NAME_CTRL,
+ XKB_MOD_NAME_ALT,
+ XKB_MOD_NAME_LOGO,
+ 0,
+ };
+
+ static int mods[] = {
+ MP_KEY_MODIFIER_SHIFT,
+ MP_KEY_MODIFIER_CTRL,
+ MP_KEY_MODIFIER_ALT,
+ MP_KEY_MODIFIER_META,
+ 0,
+ };
for (int n = 0; mods[n]; n++) {
- xkb_mod_index_t index =
- xkb_keymap_mod_get_index(wl->input.xkb.keymap, mod_names[n]);
- if (!xkb_state_mod_index_is_consumed(wl->input.xkb.state, code, index)
- && xkb_state_mod_index_is_active(wl->input.xkb.state, index,
+ 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, code, index)
+ && xkb_state_mod_index_is_active(wl->xkb_state, index,
XKB_STATE_MODS_DEPRESSED))
mpmod |= mods[n];
}
@@ -340,42 +426,29 @@ static void keyboard_handle_key(void *data,
if (mpkey) {
mp_input_put_key(wl->vo->input_ctx, mpkey | mpmod);
} else {
- char s[80];
+ char s[128];
if (xkb_keysym_to_utf8(sym, s, sizeof(s)) > 0)
mp_input_put_key_utf8(wl->vo->input_ctx, mpmod, bstr0(s));
}
}
-static void keyboard_handle_modifiers(void *data,
- struct wl_keyboard *wl_keyboard,
- uint32_t serial,
- uint32_t mods_depressed,
- uint32_t mods_latched,
- uint32_t mods_locked,
+static void keyboard_handle_modifiers(void *data, struct wl_keyboard *wl_keyboard,
+ uint32_t serial, uint32_t mods_depressed,
+ uint32_t mods_latched, uint32_t mods_locked,
uint32_t group)
{
struct vo_wayland_state *wl = data;
- xkb_state_update_mask(wl->input.xkb.state,
- mods_depressed,
- mods_latched,
- mods_locked,
- 0, 0, group);
+ xkb_state_update_mask(wl->xkb_state, mods_depressed, mods_latched,
+ mods_locked, 0, 0, group);
}
-static void keyboard_handle_repeat_info(void *data,
- struct wl_keyboard *wl_keyboard,
- int32_t rate,
- int32_t delay)
+static void keyboard_handle_repeat_info(void *data, struct wl_keyboard *wl_keyboard,
+ int32_t rate, int32_t delay)
{
struct vo_wayland_state *wl = data;
- if (wl->vo->opts->native_keyrepeat) {
- if (rate < 0 || delay < 0) {
- MP_WARN(wl, "Invalid rate or delay values sent by compositor\n");
- return;
- }
+ if (wl->vo->opts->native_keyrepeat)
mp_input_set_repeat_info(wl->vo->input_ctx, rate, delay);
- }
}
static const struct wl_keyboard_listener keyboard_listener = {
@@ -384,786 +457,847 @@ static const struct wl_keyboard_listener keyboard_listener = {
keyboard_handle_leave,
keyboard_handle_key,
keyboard_handle_modifiers,
- keyboard_handle_repeat_info
+ keyboard_handle_repeat_info,
};
-/* POINTER LISTENER */
-static void pointer_handle_enter(void *data,
- struct wl_pointer *pointer,
- uint32_t serial,
- struct wl_surface *surface,
- wl_fixed_t sx_w,
- wl_fixed_t sy_w)
+static void seat_handle_caps(void *data, struct wl_seat *seat,
+ enum wl_seat_capability caps)
{
struct vo_wayland_state *wl = data;
- wl->cursor.serial = serial;
- wl->cursor.pointer = pointer;
+ if ((caps & WL_SEAT_CAPABILITY_POINTER) && !wl->pointer) {
+ wl->pointer = wl_seat_get_pointer(seat);
+ wl_pointer_add_listener(wl->pointer, &pointer_listener, wl);
+ } else if (!(caps & WL_SEAT_CAPABILITY_POINTER) && wl->pointer) {
+ wl_pointer_destroy(wl->pointer);
+ wl->pointer = NULL;
+ }
- /* Release the left button on pointer enter again
- * because after moving the shell surface no release event is sent */
- mp_input_put_key(wl->vo->input_ctx, MP_KEY_MOUSE_ENTER);
- mp_input_put_key(wl->vo->input_ctx, MP_MBTN_LEFT | MP_KEY_STATE_UP);
- show_cursor(wl);
+ if ((caps & WL_SEAT_CAPABILITY_KEYBOARD) && !wl->keyboard) {
+ wl->keyboard = wl_seat_get_keyboard(seat);
+ wl_keyboard_add_listener(wl->keyboard, &keyboard_listener, wl);
+ } else if (!(caps & WL_SEAT_CAPABILITY_KEYBOARD) && wl->keyboard) {
+ wl_keyboard_destroy(wl->keyboard);
+ wl->keyboard = NULL;
+ }
+
+ if ((caps & WL_SEAT_CAPABILITY_TOUCH) && !wl->touch) {
+ wl->touch = wl_seat_get_touch(seat);
+ wl_touch_set_user_data(wl->touch, wl);
+ wl_touch_add_listener(wl->touch, &touch_listener, wl);
+ } else if (!(caps & WL_SEAT_CAPABILITY_TOUCH) && wl->touch) {
+ wl_touch_destroy(wl->touch);
+ wl->touch = NULL;
+ }
}
-static void pointer_handle_leave(void *data,
- struct wl_pointer *pointer,
- uint32_t serial,
- struct wl_surface *surface)
+static const struct wl_seat_listener seat_listener = {
+ seat_handle_caps,
+};
+
+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_state *wl = data;
- mp_input_put_key(wl->vo->input_ctx, MP_KEY_MOUSE_LEAVE);
+ struct vo_wayland_output *output = data;
+ output->make = make;
+ output->model = model;
+ output->geometry.x0 = x;
+ output->geometry.y0 = y;
}
-static void pointer_handle_motion(void *data,
- struct wl_pointer *pointer,
- uint32_t time,
- wl_fixed_t sx_w,
- wl_fixed_t sy_w)
+static void output_handle_mode(void *data, struct wl_output *wl_output,
+ uint32_t flags, int32_t width,
+ int32_t height, int32_t refresh)
{
- int32_t scale = 1;
- struct vo_wayland_state *wl = data;
+ struct vo_wayland_output *output = data;
- if (wl->display.current_output)
- scale = wl->display.current_output->scale;
+ /* Only save current mode */
+ if (!output || !(flags & WL_OUTPUT_MODE_CURRENT))
+ return;
- wl->cursor.pointer = pointer;
- wl->window.mouse_x = scale*wl_fixed_to_int(sx_w);
- wl->window.mouse_y = scale*wl_fixed_to_int(sy_w);
+ output->width = width;
+ output->height = height;
+ output->geometry.x1 = width + output->geometry.x0;
+ output->geometry.y1 = height + output->geometry.y0;
+ output->flags = flags;
+ output->refresh_rate = (double)refresh * 0.001;
+}
- mp_input_set_mouse_pos(wl->vo->input_ctx, wl->window.mouse_x,
- wl->window.mouse_y);
+static void output_handle_done(void* data, struct wl_output *wl_output)
+{
}
-static void pointer_handle_button(void *data,
- struct wl_pointer *pointer,
- uint32_t serial,
- uint32_t time,
- uint32_t button,
- uint32_t state)
+static void output_handle_scale(void* data, struct wl_output *wl_output,
+ int32_t factor)
{
- struct vo_wayland_state *wl = data;
+ struct vo_wayland_output *output = data;
+ output->scale = factor;
+}
- state = state == WL_POINTER_BUTTON_STATE_PRESSED ? MP_KEY_STATE_DOWN
- : MP_KEY_STATE_UP;
+static const struct wl_output_listener output_listener = {
+ output_handle_geometry,
+ output_handle_mode,
+ output_handle_done,
+ output_handle_scale,
+};
- button = button == BTN_LEFT ? MP_MBTN_LEFT :
- button == BTN_MIDDLE ? MP_MBTN_MID : MP_MBTN_RIGHT;
+static void data_offer_handle_offer(void *data, struct wl_data_offer *offer,
+ const char *mime_type)
+{
+ struct vo_wayland_state *wl = data;
+ int score = mp_event_get_mime_type_score(wl->vo->input_ctx, mime_type);
+ if (score > wl->dnd_mime_score) {
+ wl->dnd_mime_score = score;
+ talloc_free(wl->dnd_mime_type);
+ wl->dnd_mime_type = talloc_strdup(wl, mime_type);
+ MP_VERBOSE(wl, "Given DND offer with mime type %s\n", wl->dnd_mime_type);
+ }
+}
- mp_input_put_key(wl->vo->input_ctx, button | state);
+static void data_offer_source_actions(void *data, struct wl_data_offer *offer, uint32_t source_actions)
+{
- if (!mp_input_test_dragging(wl->vo->input_ctx, wl->window.mouse_x, wl->window.mouse_y) &&
- (button == MP_MBTN_LEFT) && (state == MP_KEY_STATE_DOWN))
- window_move(wl, serial);
}
-static void pointer_handle_axis(void *data,
- struct wl_pointer *pointer,
- uint32_t time,
- uint32_t axis,
- wl_fixed_t value)
+static void data_offer_action(void *data, struct wl_data_offer *wl_data_offer, uint32_t dnd_action)
{
struct vo_wayland_state *wl = data;
-
- // value is 10.00 on a normal mouse wheel
- // scale it down to 1.00 for multipliying it with the commands
- if (axis == WL_POINTER_AXIS_VERTICAL_SCROLL) {
- if (value > 0)
- mp_input_put_wheel(wl->vo->input_ctx, MP_WHEEL_DOWN,
- wl_fixed_to_double(value)*0.1);
- if (value < 0)
- mp_input_put_wheel(wl->vo->input_ctx, MP_WHEEL_UP,
- wl_fixed_to_double(value)*-0.1);
- }
- else if (axis == WL_POINTER_AXIS_HORIZONTAL_SCROLL) {
- if (value > 0)
- mp_input_put_wheel(wl->vo->input_ctx, MP_WHEEL_RIGHT,
- wl_fixed_to_double(value)*0.1);
- if (value < 0)
- mp_input_put_wheel(wl->vo->input_ctx, MP_WHEEL_LEFT,
- wl_fixed_to_double(value)*-0.1);
- }
+ wl->dnd_action = dnd_action & WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY ?
+ DND_REPLACE : DND_APPEND;
+ MP_VERBOSE(wl, "DND action is %s\n",
+ wl->dnd_action == DND_REPLACE ? "DND_REPLACE" : "DND_APPEND");
}
-static const struct wl_pointer_listener pointer_listener = {
- pointer_handle_enter,
- pointer_handle_leave,
- pointer_handle_motion,
- pointer_handle_button,
- pointer_handle_axis,
+static const struct wl_data_offer_listener data_offer_listener = {
+ data_offer_handle_offer,
+ data_offer_source_actions,
+ data_offer_action,
};
-static void seat_handle_capabilities(void *data,
- struct wl_seat *seat,
- enum wl_seat_capability caps)
+static void data_device_handle_data_offer(void *data, struct wl_data_device *wl_ddev,
+ struct wl_data_offer *id)
{
struct vo_wayland_state *wl = data;
+ if (wl->dnd_offer)
+ wl_data_offer_destroy(wl->dnd_offer);
- if ((caps & WL_SEAT_CAPABILITY_KEYBOARD) && !wl->input.keyboard) {
- wl->input.keyboard = wl_seat_get_keyboard(seat);
- wl_keyboard_add_listener(wl->input.keyboard, &keyboard_listener, wl);
- }
- else if (!(caps & WL_SEAT_CAPABILITY_KEYBOARD) && wl->input.keyboard) {
- wl_keyboard_destroy(wl->input.keyboard);
- wl->input.keyboard = NULL;
- }
- if ((caps & WL_SEAT_CAPABILITY_POINTER) && !wl->input.pointer) {
- wl->input.pointer = wl_seat_get_pointer(seat);
- wl_pointer_add_listener(wl->input.pointer, &pointer_listener, wl);
- }
- else if (!(caps & WL_SEAT_CAPABILITY_POINTER) && wl->input.pointer) {
- wl_pointer_destroy(wl->input.pointer);
- wl->input.pointer = NULL;
+ wl->dnd_offer = id;
+ wl_data_offer_add_listener(id, &data_offer_listener, wl);
+}
+
+static void data_device_handle_enter(void *data, struct wl_data_device *wl_ddev,
+ uint32_t serial, struct wl_surface *surface,
+ wl_fixed_t x, wl_fixed_t y,
+ struct wl_data_offer *id)
+{
+ struct vo_wayland_state *wl = data;
+ if (wl->dnd_offer != id) {
+ MP_FATAL(wl, "DND offer ID mismatch!\n");
+ return;
}
+
+ wl_data_offer_set_actions(id, WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY |
+ WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE,
+ WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY);
+
+ wl_data_offer_accept(id, serial, wl->dnd_mime_type);
+
+ MP_VERBOSE(wl, "Accepting DND offer with mime type %s\n", wl->dnd_mime_type);
}
-static void seat_handle_name(void *data,
- struct wl_seat *seat,
- const char *name)
+static void data_device_handle_leave(void *data, struct wl_data_device *wl_ddev)
{
struct vo_wayland_state *wl = data;
- MP_VERBOSE(wl, "Seat \"%s\" connected\n", name);</