summaryrefslogtreecommitdiffstats
path: root/video/out/wayland_common.c
diff options
context:
space:
mode:
Diffstat (limited to 'video/out/wayland_common.c')
-rw-r--r--video/out/wayland_common.c205
1 files changed, 137 insertions, 68 deletions
diff --git a/video/out/wayland_common.c b/video/out/wayland_common.c
index 4a86c21c7e..dea3d0300a 100644
--- a/video/out/wayland_common.c
+++ b/video/out/wayland_common.c
@@ -119,7 +119,7 @@ static const struct mp_keymap keymap[] = {
/* Numpad without numlock */
{XKB_KEY_KP_Insert, MP_KEY_KPINS}, {XKB_KEY_KP_End, MP_KEY_KPEND},
{XKB_KEY_KP_Down, MP_KEY_KPDOWN}, {XKB_KEY_KP_Page_Down, MP_KEY_KPPGDOWN},
- {XKB_KEY_KP_Left, MP_KEY_KPLEFT}, {XKB_KEY_KP_Begin, MP_KEY_KP5},
+ {XKB_KEY_KP_Left, MP_KEY_KPLEFT}, {XKB_KEY_KP_Begin, MP_KEY_KPBEGIN},
{XKB_KEY_KP_Right, MP_KEY_KPRIGHT}, {XKB_KEY_KP_Home, MP_KEY_KPHOME},
{XKB_KEY_KP_Up, MP_KEY_KPUP}, {XKB_KEY_KP_Page_Up, MP_KEY_KPPGUP},
{XKB_KEY_KP_Delete, MP_KEY_KPDEL},
@@ -211,6 +211,9 @@ struct vo_wayland_seat {
bool axis_value120_scroll;
bool has_keyboard_input;
struct wl_list link;
+ bool keyboard_entering;
+ uint32_t *keyboard_entering_keys;
+ int num_keyboard_entering_keys;
};
static bool single_output_spanned(struct vo_wayland_state *wl);
@@ -219,7 +222,7 @@ static int check_for_resize(struct vo_wayland_state *wl, int edge_pixels,
enum xdg_toplevel_resize_edge *edge);
static int get_mods(struct vo_wayland_seat *seat);
static int greatest_common_divisor(int a, int b);
-static int lookupkey(int key);
+static void handle_key_input(struct vo_wayland_seat *s, uint32_t key, uint32_t state);
static int set_cursor_visibility(struct vo_wayland_seat *s, bool on);
static int spawn_cursor(struct vo_wayland_state *wl);
@@ -440,19 +443,17 @@ static void touch_handle_down(void *data, struct wl_touch *wl_touch,
{
struct vo_wayland_seat *s = data;
struct vo_wayland_state *wl = s->wl;
+ // Note: the position should still be saved here for VO dragging handling.
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);
+ mp_input_add_touch_point(wl->vo->input_ctx, id, wl->mouse_x, wl->mouse_y);
enum xdg_toplevel_resize_edge edge;
if (!mp_input_test_dragging(wl->vo->input_ctx, wl->mouse_x, wl->mouse_y) &&
!wl->locked_size && check_for_resize(wl, wl->opts->edge_pixels_touch, &edge))
{
xdg_toplevel_resize(wl->xdg_toplevel, s->seat, serial, edge);
- // Explicitly send an UP event after the client finishes a resize
- mp_input_put_key(wl->vo->input_ctx, MP_MBTN_LEFT | MP_KEY_STATE_UP);
} else {
// Save the serial and seat for voctrl-initialized dragging requests.
s->pointer_button_serial = serial;
@@ -465,7 +466,7 @@ static void touch_handle_up(void *data, struct wl_touch *wl_touch,
{
struct vo_wayland_seat *s = data;
struct vo_wayland_state *wl = s->wl;
- mp_input_put_key(wl->vo->input_ctx, MP_MBTN_LEFT | MP_KEY_STATE_UP);
+ mp_input_remove_touch_point(wl->vo->input_ctx, id);
wl->last_button_seat = NULL;
}
@@ -478,7 +479,7 @@ static void touch_handle_motion(void *data, struct wl_touch *wl_touch,
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_update_touch_point(wl->vo->input_ctx, id, wl->mouse_x, wl->mouse_y);
}
static void touch_handle_frame(void *data, struct wl_touch *wl_touch)
@@ -487,6 +488,9 @@ static void touch_handle_frame(void *data, struct wl_touch *wl_touch)
static void touch_handle_cancel(void *data, struct wl_touch *wl_touch)
{
+ struct vo_wayland_seat *s = data;
+ struct vo_wayland_state *wl = s->wl;
+ mp_input_put_key(wl->vo->input_ctx, MP_TOUCH_RELEASE_ALL);
}
static void touch_handle_shape(void *data, struct wl_touch *wl_touch,
@@ -557,7 +561,12 @@ static void keyboard_handle_enter(void *data, struct wl_keyboard *wl_keyboard,
struct vo_wayland_seat *s = data;
struct vo_wayland_state *wl = s->wl;
s->has_keyboard_input = true;
+ s->keyboard_entering = true;
guess_focus(wl);
+
+ uint32_t *key;
+ wl_array_for_each(key, keys)
+ MP_TARRAY_APPEND(s, s->keyboard_entering_keys, s->num_keyboard_entering_keys, *key);
}
static void keyboard_handle_leave(void *data, struct wl_keyboard *wl_keyboard,
@@ -578,36 +587,7 @@ static void keyboard_handle_key(void *data, struct wl_keyboard *wl_keyboard,
uint32_t state)
{
struct vo_wayland_seat *s = data;
- struct vo_wayland_state *wl = s->wl;
-
- s->keyboard_code = key + 8;
- xkb_keysym_t sym = xkb_state_key_get_one_sym(s->xkb_state, s->keyboard_code);
- int mpkey = lookupkey(sym);
-
- state = state == WL_KEYBOARD_KEY_STATE_PRESSED ? MP_KEY_STATE_DOWN
- : MP_KEY_STATE_UP;
-
- if (mpkey) {
- mp_input_put_key(wl->vo->input_ctx, mpkey | state | s->mpmod);
- } else {
- char str[128];
- if (xkb_keysym_to_utf8(sym, str, sizeof(str)) > 0) {
- mp_input_put_key_utf8(wl->vo->input_ctx, state | s->mpmod, bstr0(str));
- } else {
- // Assume a modifier was pressed and handle it in the mod event instead.
- // If a modifier is released before a regular key, also release that
- // key to not activate it again by accident.
- if (state == MP_KEY_STATE_UP) {
- s->mpkey = 0;
- mp_input_put_key(wl->vo->input_ctx, MP_INPUT_RELEASE_ALL);
- }
- return;
- }
- }
- if (state == MP_KEY_STATE_DOWN)
- s->mpkey = mpkey;
- if (mpkey && state == MP_KEY_STATE_UP)
- s->mpkey = 0;
+ handle_key_input(s, key, state);
}
static void keyboard_handle_modifiers(void *data, struct wl_keyboard *wl_keyboard,
@@ -622,8 +602,15 @@ static void keyboard_handle_modifiers(void *data, struct wl_keyboard *wl_keyboar
xkb_state_update_mask(s->xkb_state, mods_depressed, mods_latched,
mods_locked, 0, 0, group);
s->mpmod = get_mods(s);
- if (s->mpkey)
- mp_input_put_key(wl->vo->input_ctx, s->mpkey | MP_KEY_STATE_DOWN | s->mpmod);
+ }
+ // Handle keys pressed during the enter event.
+ if (s->keyboard_entering) {
+ s->keyboard_entering = false;
+ for (int n = 0; n < s->num_keyboard_entering_keys; n++)
+ handle_key_input(s, s->keyboard_entering_keys[n], WL_KEYBOARD_KEY_STATE_PRESSED);
+ s->num_keyboard_entering_keys = 0;
+ } else if (s->xkb_state && s->mpkey) {
+ mp_input_put_key(wl->vo->input_ctx, s->mpkey | MP_KEY_STATE_DOWN | s->mpmod);
}
}
@@ -1010,6 +997,9 @@ static void surface_handle_preferred_buffer_scale(void *data,
// Update scaling now.
if (single_output_spanned(wl))
update_output_scaling(wl);
+
+ if (!wl->current_output)
+ wl->scaling = wl->pending_scaling;
}
static void surface_handle_preferred_buffer_transform(void *data,
@@ -1235,6 +1225,9 @@ static void preferred_scale(void *data,
// Update scaling now.
if (single_output_spanned(wl))
update_output_scaling(wl);
+
+ if (!wl->current_output)
+ wl->scaling = wl->pending_scaling;
}
static const struct wp_fractional_scale_v1_listener fractional_scale_listener = {
@@ -1457,20 +1450,27 @@ static void registry_handle_add(void *data, struct wl_registry *reg, uint32_t id
wl_surface_add_listener(wl->surface, &surface_listener, wl);
}
- if (!strcmp(interface, wl_subcompositor_interface.name) && (ver >= 1) && found++)
- wl->subcompositor = wl_registry_bind(reg, id, &wl_subcompositor_interface, 1);
+ if (!strcmp(interface, wl_subcompositor_interface.name) && found++) {
+ ver = 1;
+ wl->subcompositor = wl_registry_bind(reg, id, &wl_subcompositor_interface, ver);
+ }
if (!strcmp (interface, zwp_linux_dmabuf_v1_interface.name) && (ver >= 4) && found++) {
- wl->dmabuf = wl_registry_bind(reg, id, &zwp_linux_dmabuf_v1_interface, 4);
+ ver = 4;
+ wl->dmabuf = wl_registry_bind(reg, id, &zwp_linux_dmabuf_v1_interface, ver);
wl->dmabuf_feedback = zwp_linux_dmabuf_v1_get_default_feedback(wl->dmabuf);
zwp_linux_dmabuf_feedback_v1_add_listener(wl->dmabuf_feedback, &dmabuf_feedback_listener, wl);
}
- if (!strcmp (interface, wp_viewporter_interface.name) && (ver >= 1) && found++)
- wl->viewporter = wl_registry_bind (reg, id, &wp_viewporter_interface, 1);
+ if (!strcmp (interface, wp_viewporter_interface.name) && found++) {
+ ver = 1;
+ wl->viewporter = wl_registry_bind (reg, id, &wp_viewporter_interface, ver);
+ }
- 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, wl_data_device_manager_interface.name) && (ver >= 3) && found++) {
+ ver = 3;
+ wl->dnd_devman = wl_registry_bind(reg, id, &wl_data_device_manager_interface, ver);
+ }
if (!strcmp(interface, wl_output_interface.name) && (ver >= 2) && found++) {
struct vo_wayland_output *output = talloc_zero(wl, struct vo_wayland_output);
@@ -1503,46 +1503,65 @@ static void registry_handle_add(void *data, struct wl_registry *reg, uint32_t id
wl_list_insert(&wl->seat_list, &seat->link);
}
- if (!strcmp(interface, wl_shm_interface.name) && found++)
- wl->shm = wl_registry_bind(reg, id, &wl_shm_interface, 1);
+ if (!strcmp(interface, wl_shm_interface.name) && found++) {
+ ver = 1;
+ wl->shm = wl_registry_bind(reg, id, &wl_shm_interface, ver);
+ }
#if HAVE_WAYLAND_PROTOCOLS_1_27
- if (!strcmp(interface, wp_content_type_manager_v1_interface.name) && found++)
- wl->content_type_manager = wl_registry_bind(reg, id, &wp_content_type_manager_v1_interface, 1);
+ if (!strcmp(interface, wp_content_type_manager_v1_interface.name) && found++) {
+ ver = 1;
+ wl->content_type_manager = wl_registry_bind(reg, id, &wp_content_type_manager_v1_interface, ver);
+ }
- if (!strcmp(interface, wp_single_pixel_buffer_manager_v1_interface.name) && found++)
- wl->single_pixel_manager = wl_registry_bind(reg, id, &wp_single_pixel_buffer_manager_v1_interface, 1);
+ if (!strcmp(interface, wp_single_pixel_buffer_manager_v1_interface.name) && found++) {
+ ver = 1;
+ wl->single_pixel_manager = wl_registry_bind(reg, id, &wp_single_pixel_buffer_manager_v1_interface, ver);
+ }
#endif
#if HAVE_WAYLAND_PROTOCOLS_1_31
- if (!strcmp(interface, wp_fractional_scale_manager_v1_interface.name) && found++)
- wl->fractional_scale_manager = wl_registry_bind(reg, id, &wp_fractional_scale_manager_v1_interface, 1);
+ if (!strcmp(interface, wp_fractional_scale_manager_v1_interface.name) && found++) {
+ ver = 1;
+ wl->fractional_scale_manager = wl_registry_bind(reg, id, &wp_fractional_scale_manager_v1_interface, ver);
+ }
#endif
#if HAVE_WAYLAND_PROTOCOLS_1_32
- if (!strcmp(interface, wp_cursor_shape_manager_v1_interface.name) && found++)
- wl->cursor_shape_manager = wl_registry_bind(reg, id, &wp_cursor_shape_manager_v1_interface, 1);
+ if (!strcmp(interface, wp_cursor_shape_manager_v1_interface.name) && found++) {
+ ver = 1;
+ wl->cursor_shape_manager = wl_registry_bind(reg, id, &wp_cursor_shape_manager_v1_interface, ver);
+ }
#endif
if (!strcmp(interface, wp_presentation_interface.name) && found++) {
- wl->presentation = wl_registry_bind(reg, id, &wp_presentation_interface, 1);
+ ver = 1;
+ wl->presentation = wl_registry_bind(reg, id, &wp_presentation_interface, ver);
wp_presentation_add_listener(wl->presentation, &pres_listener, wl);
}
if (!strcmp(interface, xdg_wm_base_interface.name) && found++) {
+#ifdef XDG_TOPLEVEL_WM_CAPABILITIES_SINCE_VERSION
ver = MPMIN(ver, 6); /* Cap at 6 in case new events are added later. */
+#else
+ ver = MPMIN(ver, 4);
+#endif
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, 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, zxdg_decoration_manager_v1_interface.name) && found++) {
+ ver = 1;
+ wl->xdg_decoration_manager = wl_registry_bind(reg, id, &zxdg_decoration_manager_v1_interface, ver);
+ }
- 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 (!strcmp(interface, zwp_idle_inhibit_manager_v1_interface.name) && found++) {
+ ver = 1;
+ wl->idle_inhibit_manager = wl_registry_bind(reg, id, &zwp_idle_inhibit_manager_v1_interface, ver);
+ }
if (found > 1)
- MP_VERBOSE(wl, "Registered for protocol %s\n", interface);
+ MP_VERBOSE(wl, "Registered interface %s at version %d\n", interface, ver);
}
static void registry_handle_remove(void *data, struct wl_registry *reg, uint32_t id)
@@ -1820,10 +1839,10 @@ static void guess_focus(struct vo_wayland_state *wl)
if ((!wl->focused && wl->activated && has_keyboard_input) ||
(wl->focused && !wl->activated))
- {
- wl->focused = !wl->focused;
- wl->pending_vo_events |= VO_EVENT_FOCUS;
- }
+ {
+ wl->focused = !wl->focused;
+ wl->pending_vo_events |= VO_EVENT_FOCUS;
+ }
}
static struct vo_wayland_output *find_output(struct vo_wayland_state *wl)
@@ -1873,6 +1892,49 @@ static int lookupkey(int key)
return mpkey;
}
+static void handle_key_input(struct vo_wayland_seat *s, uint32_t key,
+ uint32_t state)
+{
+ struct vo_wayland_state *wl = s->wl;
+
+ switch (state) {
+ case WL_KEYBOARD_KEY_STATE_RELEASED:
+ state = MP_KEY_STATE_UP;
+ break;
+ case WL_KEYBOARD_KEY_STATE_PRESSED:
+ state = MP_KEY_STATE_DOWN;
+ break;
+ default:
+ return;
+ }
+
+ s->keyboard_code = key + 8;
+ xkb_keysym_t sym = xkb_state_key_get_one_sym(s->xkb_state, s->keyboard_code);
+ int mpkey = lookupkey(sym);
+
+ if (mpkey) {
+ mp_input_put_key(wl->vo->input_ctx, mpkey | state | s->mpmod);
+ } else {
+ char str[128];
+ if (xkb_keysym_to_utf8(sym, str, sizeof(str)) > 0) {
+ mp_input_put_key_utf8(wl->vo->input_ctx, state | s->mpmod, bstr0(str));
+ } else {
+ // Assume a modifier was pressed and handle it in the mod event instead.
+ // If a modifier is released before a regular key, also release that
+ // key to not activate it again by accident.
+ if (state == MP_KEY_STATE_UP) {
+ s->mpkey = 0;
+ mp_input_put_key(wl->vo->input_ctx, MP_INPUT_RELEASE_ALL);
+ }
+ return;
+ }
+ }
+ if (state == MP_KEY_STATE_DOWN)
+ s->mpkey = mpkey;
+ if (mpkey && state == MP_KEY_STATE_UP)
+ s->mpkey = 0;
+}
+
static void prepare_resize(struct vo_wayland_state *wl)
{
int32_t width = mp_rect_w(wl->geometry) / wl->scaling;
@@ -2087,7 +2149,7 @@ static int set_screensaver_inhibitor(struct vo_wayland_state *wl, int state)
if (state) {
MP_VERBOSE(wl, "Enabling idle inhibitor\n");
struct zwp_idle_inhibit_manager_v1 *mgr = wl->idle_inhibit_manager;
- wl->idle_inhibitor = zwp_idle_inhibit_manager_v1_create_inhibitor(mgr, wl->surface);
+ wl->idle_inhibitor = zwp_idle_inhibit_manager_v1_create_inhibitor(mgr, wl->callback_surface);
} else {
MP_VERBOSE(wl, "Disabling the idle inhibitor\n");
zwp_idle_inhibitor_v1_destroy(wl->idle_inhibitor);
@@ -2599,6 +2661,13 @@ bool vo_wayland_init(struct vo *vo)
}
#endif
+#if HAVE_WAYLAND_PROTOCOLS_1_32
+ if (!wl->cursor_shape_manager) {
+ MP_VERBOSE(wl, "Compositor doesn't support the %s protocol!\n",
+ wp_cursor_shape_manager_v1_interface.name);
+ }
+#endif
+
if (wl->dnd_devman) {
struct vo_wayland_seat *seat;
wl_list_for_each(seat, &wl->seat_list, link) {