diff --git a/video/out/wayland_common.c b/video/out/wayland_common.c index 03e9e40ab1..3e031d1449 100644 --- a/video/out/wayland_common.c +++ b/video/out/wayland_common.c @@ -56,6 +56,10 @@ #include "cursor-shape-v1.h" #endif +#if WAYLAND_VERSION_MAJOR > 1 || WAYLAND_VERSION_MINOR >= 21 +#define HAVE_WAYLAND_1_21 +#endif + #if WAYLAND_VERSION_MAJOR > 1 || WAYLAND_VERSION_MINOR >= 22 #define HAVE_WAYLAND_1_22 #endif @@ -294,35 +298,95 @@ 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; - - // The axis value is specified in logical coordinates, but the exact value emitted - // by one mouse wheel click is unspecified. In practice, most compositors use either - // 10 (GNOME, Weston) or 15 (wlroots, same as libinput) as the value. - // Divide the value by 10 and clamp it between -1 and 1 so that mouse wheel clicks - // work as intended on all compositors while still allowing high resolution trackpads. - double val = MPCLAMP(wl_fixed_to_double(value) / 10.0, -1, 1); switch (axis) { case WL_POINTER_AXIS_VERTICAL_SCROLL: - if (value > 0) - mp_input_put_wheel(wl->vo->input_ctx, MP_WHEEL_DOWN | wl->mpmod, +val); - if (value < 0) - mp_input_put_wheel(wl->vo->input_ctx, MP_WHEEL_UP | wl->mpmod, -val); + wl->axis_value_vertical += wl_fixed_to_double(value); break; case WL_POINTER_AXIS_HORIZONTAL_SCROLL: - if (value > 0) - mp_input_put_wheel(wl->vo->input_ctx, MP_WHEEL_RIGHT | wl->mpmod, +val); - if (value < 0) - mp_input_put_wheel(wl->vo->input_ctx, MP_WHEEL_LEFT | wl->mpmod, -val); + wl->axis_value_horizontal += wl_fixed_to_double(value); break; } } +static void pointer_handle_frame(void *data, struct wl_pointer *wl_pointer) +{ + struct vo_wayland_state *wl = data; + double value_vertical, value_horizontal; + if (wl->axis_value120_scroll) { + // Prefer axis_value120 if supported and the axis event is from mouse wheel. + value_vertical = wl->axis_value120_vertical / 120.0; + value_horizontal = wl->axis_value120_horizontal / 120.0; + } else { + // The axis value is specified in logical coordinates, but the exact value emitted + // by one mouse wheel click is unspecified. In practice, most compositors use either + // 10 (GNOME, Weston) or 15 (wlroots, same as libinput) as the value. + // Divide the value by 10 and clamp it between -1 and 1 so that mouse wheel clicks + // work as intended on all compositors while still allowing high resolution trackpads. + value_vertical = MPCLAMP(wl->axis_value_vertical / 10.0, -1, 1); + value_horizontal = MPCLAMP(wl->axis_value_horizontal / 10.0, -1, 1); + } + + if (value_vertical > 0) + mp_input_put_wheel(wl->vo->input_ctx, MP_WHEEL_DOWN | wl->mpmod, +value_vertical); + if (value_vertical < 0) + mp_input_put_wheel(wl->vo->input_ctx, MP_WHEEL_UP | wl->mpmod, -value_vertical); + if (value_horizontal > 0) + mp_input_put_wheel(wl->vo->input_ctx, MP_WHEEL_RIGHT | wl->mpmod, +value_horizontal); + if (value_horizontal < 0) + mp_input_put_wheel(wl->vo->input_ctx, MP_WHEEL_LEFT | wl->mpmod, -value_horizontal); + + wl->axis_value120_scroll = false; + wl->axis_value_vertical = 0; + wl->axis_value_horizontal = 0; + wl->axis_value120_vertical = 0; + wl->axis_value120_horizontal = 0; +} + +static void pointer_handle_axis_source(void *data, struct wl_pointer *wl_pointer, + uint32_t axis_source) +{ +} + +static void pointer_handle_axis_stop(void *data, struct wl_pointer *wl_pointer, + uint32_t time, uint32_t axis) +{ +} + +static void pointer_handle_axis_discrete(void *data, struct wl_pointer *wl_pointer, + uint32_t axis, int32_t discrete) +{ +} + +#ifdef HAVE_WAYLAND_1_21 +static void pointer_handle_axis_value120(void *data, struct wl_pointer *wl_pointer, + uint32_t axis, int32_t value120) +{ + struct vo_wayland_state *wl = data; + wl->axis_value120_scroll = true; + switch (axis) { + case WL_POINTER_AXIS_VERTICAL_SCROLL: + wl->axis_value120_vertical += value120; + break; + case WL_POINTER_AXIS_HORIZONTAL_SCROLL: + wl->axis_value120_horizontal += value120; + break; + } +} +#endif + static const struct wl_pointer_listener pointer_listener = { pointer_handle_enter, pointer_handle_leave, pointer_handle_motion, pointer_handle_button, pointer_handle_axis, + pointer_handle_frame, + pointer_handle_axis_source, + pointer_handle_axis_stop, + pointer_handle_axis_discrete, +#ifdef HAVE_WAYLAND_1_21 + pointer_handle_axis_value120, +#endif }; static void touch_handle_down(void *data, struct wl_touch *wl_touch, @@ -534,8 +598,14 @@ static void seat_handle_caps(void *data, struct wl_seat *seat, } } +static void seat_handle_name(void *data, struct wl_seat *seat, + const char *name) +{ +} + static const struct wl_seat_listener seat_listener = { seat_handle_caps, + seat_handle_name, }; static void data_offer_handle_offer(void *data, struct wl_data_offer *offer, @@ -1338,7 +1408,12 @@ static void registry_handle_add(void *data, struct wl_registry *reg, uint32_t id } if (!strcmp(interface, wl_seat_interface.name) && found++) { - wl->seat = wl_registry_bind(reg, id, &wl_seat_interface, 1); +#ifdef HAVE_WAYLAND_1_21 + ver = MPMIN(ver, 8); /* Cap at 8 in case new events are added later. */ +#else + ver = MPMIN(ver, 7); +#endif + wl->seat = wl_registry_bind(reg, id, &wl_seat_interface, ver); wl_seat_add_listener(wl->seat, &seat_listener, wl); } diff --git a/video/out/wayland_common.h b/video/out/wayland_common.h index 25e973dcfd..9928cc83cc 100644 --- a/video/out/wayland_common.h +++ b/video/out/wayland_common.h @@ -151,6 +151,11 @@ struct vo_wayland_state { uint32_t keyboard_code; int mpkey; int mpmod; + double axis_value_vertical; + int32_t axis_value120_vertical; + double axis_value_horizontal; + int32_t axis_value120_horizontal; + bool axis_value120_scroll; /* DND */ struct wl_data_device *dnd_ddev;