diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index c71cac32dc..fb4597904a 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -21,7 +21,7 @@ stages: # Common variables variables: - COMMON_MESON_FLAGS: "-Dwerror=true -Dglib:werror=false -Dpango:werror=false -Dgtk-doc:werror=false -Dwayland-protocols:werror=false -Dsysprof:werror=false" + COMMON_MESON_FLAGS: "-Dwerror=true -Dglib:werror=false -Dpango:werror=false -Dgtk-doc:werror=false -Dwayland-protocols:werror=false -Dsysprof:werror=false -Dwayland:werror=false" BACKEND_FLAGS: "-Dx11-backend=true -Dwayland-backend=true -Dbroadway-backend=true" FEATURE_FLAGS: "-Dvulkan=enabled -Dcloudproviders=enabled" MESON_TEST_TIMEOUT_MULTIPLIER: 3 diff --git a/gdk/gdkevents.c b/gdk/gdkevents.c index ba185c2ffb..4b61715575 100644 --- a/gdk/gdkevents.c +++ b/gdk/gdkevents.c @@ -2368,10 +2368,75 @@ gdk_scroll_event_new_discrete (GdkSurface *surface, GdkScrollDirection direction) { GdkScrollEvent *self = gdk_event_alloc (GDK_SCROLL, surface, device, time); + double delta_x = 0, delta_y = 0; + + switch (direction) + { + case GDK_SCROLL_UP: + delta_y = -1; + break; + case GDK_SCROLL_DOWN: + delta_y = 1; + break; + case GDK_SCROLL_LEFT: + delta_x = -1; + break; + case GDK_SCROLL_RIGHT: + delta_x = 1; + break; + case GDK_SCROLL_SMOOTH: + default: + g_assert_not_reached (); + break; + } self->tool = tool != NULL ? g_object_ref (tool) : NULL; self->state = state; self->direction = direction; + self->delta_x = delta_x; + self->delta_y = delta_y; + self->unit = GDK_SCROLL_UNIT_WHEEL; + + return (GdkEvent *) self; +} + +/*< private > + * gtk_scroll_event_new_value120: + * @surface: the `GdkSurface` of the event + * @device: the `GdkDevice` of the event + * @tool: (nullable): the tool that generated to event + * @time: the event serial + * @state: Flags to indicate the state of modifier keys and mouse buttons + * in events. + * @direction: scroll direction. + * @delta_x: delta on the X axis in the 120.0 scale + * @delta_x: delta on the Y axis in the 120.0 scale + * + * Creates a new discrete GdkScrollEvent for high resolution mouse wheels. + * + * Both axes send data in fractions of 120 where each multiple of 120 + * amounts to one logical scroll event. Fractions of 120 indicate a wheel + * movement less than one detent. + * + * Returns: the newly created scroll event + */ +GdkEvent * +gdk_scroll_event_new_value120 (GdkSurface *surface, + GdkDevice *device, + GdkDeviceTool *tool, + guint32 time, + GdkModifierType state, + GdkScrollDirection direction, + double delta_x, + double delta_y) +{ + GdkScrollEvent *self = gdk_event_alloc (GDK_SCROLL, surface, device, time); + + self->tool = tool != NULL ? g_object_ref (tool) : NULL; + self->state = state; + self->direction = direction; + self->delta_x = delta_x / 120.0; + self->delta_y = delta_y / 120.0; self->unit = GDK_SCROLL_UNIT_WHEEL; return (GdkEvent *) self; diff --git a/gdk/gdkeventsprivate.h b/gdk/gdkeventsprivate.h index 661de6baa8..a36c5d100b 100644 --- a/gdk/gdkeventsprivate.h +++ b/gdk/gdkeventsprivate.h @@ -495,6 +495,15 @@ GdkEvent * gdk_scroll_event_new_discrete (GdkSurface *surface, GdkModifierType state, GdkScrollDirection direction); +GdkEvent * gdk_scroll_event_new_value120 (GdkSurface *surface, + GdkDevice *device, + GdkDeviceTool *tool, + guint32 time, + GdkModifierType state, + GdkScrollDirection direction, + double delta_x, + double delta_y); + GdkEvent * gdk_touch_event_new (GdkEventType type, GdkEventSequence *sequence, GdkSurface *surface, diff --git a/gdk/wayland/gdkdevice-wayland.c b/gdk/wayland/gdkdevice-wayland.c index 38d18ec588..1cea5ab1ea 100644 --- a/gdk/wayland/gdkdevice-wayland.c +++ b/gdk/wayland/gdkdevice-wayland.c @@ -112,7 +112,7 @@ struct _GdkWaylandPointerFrameData /* Specific to the scroll event */ double delta_x, delta_y; - int32_t discrete_x, discrete_y; + int32_t value120_x, value120_y; gint8 is_scroll_stop; enum wl_pointer_axis_source source; }; @@ -1383,20 +1383,54 @@ static GdkDevice * get_scroll_device (GdkWaylandSeat *seat, static void flush_discrete_scroll_event (GdkWaylandSeat *seat, - GdkScrollDirection direction) + gint value120_x, + gint value120_y) { - GdkEvent *event; + GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (seat->display); + GdkEvent *event = NULL; GdkDevice *source; + GdkScrollDirection direction; + + if (value120_x > 0) + direction = GDK_SCROLL_LEFT; + else if (value120_x < 0) + direction = GDK_SCROLL_RIGHT; + else if (value120_y > 0) + direction = GDK_SCROLL_DOWN; + else + direction = GDK_SCROLL_UP; source = get_scroll_device (seat, seat->pointer_info.frame.source); - event = gdk_scroll_event_new_discrete (seat->pointer_info.focus, - source, - NULL, - seat->pointer_info.time, - device_get_modifiers (seat->logical_pointer), - direction); - _gdk_wayland_display_deliver_event (seat->display, event); + if (display_wayland->seat_version >= WL_POINTER_AXIS_VALUE120_SINCE_VERSION) + { + event = gdk_scroll_event_new_value120 (seat->pointer_info.focus, + source, + NULL, + seat->pointer_info.time, + device_get_modifiers (seat->logical_pointer), + direction, + value120_x, + value120_y); + } + else + { + gint discrete_x = value120_x / 120; + gint discrete_y = value120_y / 120; + + if (discrete_x != 0 || discrete_y != 0) + { + event = gdk_scroll_event_new_discrete (seat->pointer_info.focus, + source, + NULL, + seat->pointer_info.time, + device_get_modifiers (seat->logical_pointer), + direction); + } + } + + if (event) + _gdk_wayland_display_deliver_event (seat->display, event); } static void @@ -1427,22 +1461,13 @@ flush_scroll_event (GdkWaylandSeat *seat, { gboolean is_stop = FALSE; - if (pointer_frame->discrete_x || pointer_frame->discrete_y) + if (pointer_frame->value120_x || pointer_frame->value120_y) { - GdkScrollDirection direction; - - if (pointer_frame->discrete_x > 0) - direction = GDK_SCROLL_LEFT; - else if (pointer_frame->discrete_x < 0) - direction = GDK_SCROLL_RIGHT; - else if (pointer_frame->discrete_y > 0) - direction = GDK_SCROLL_DOWN; - else - direction = GDK_SCROLL_UP; - - flush_discrete_scroll_event (seat, direction); - pointer_frame->discrete_x = 0; - pointer_frame->discrete_y = 0; + flush_discrete_scroll_event (seat, + pointer_frame->value120_x, + pointer_frame->value120_y); + pointer_frame->value120_x = 0; + pointer_frame->value120_y = 0; } else if (pointer_frame->is_scroll_stop || pointer_frame->delta_x != 0 || @@ -1462,8 +1487,8 @@ flush_scroll_event (GdkWaylandSeat *seat, is_stop); } - pointer_frame->discrete_x = 0; - pointer_frame->discrete_y = 0; + pointer_frame->value120_x = 0; + pointer_frame->value120_y = 0; pointer_frame->delta_x = 0; pointer_frame->delta_y = 0; pointer_frame->is_scroll_stop = FALSE; @@ -1862,10 +1887,10 @@ pointer_handle_axis_discrete (void *data, switch (axis) { case WL_POINTER_AXIS_VERTICAL_SCROLL: - pointer_frame->discrete_y = value; + pointer_frame->value120_y = value * 120; break; case WL_POINTER_AXIS_HORIZONTAL_SCROLL: - pointer_frame->discrete_x = value; + pointer_frame->value120_x = value * 120; break; default: g_return_if_reached (); @@ -1876,6 +1901,35 @@ pointer_handle_axis_discrete (void *data, get_axis_name (axis), value, seat)); } +static void +pointer_handle_axis_value120 (void *data, + struct wl_pointer *pointer, + uint32_t axis, + int32_t value) +{ + GdkWaylandSeat *seat = data; + GdkWaylandPointerFrameData *pointer_frame = &seat->pointer_info.frame; + + if (!seat->pointer_info.focus) + return; + + switch (axis) + { + case WL_POINTER_AXIS_VERTICAL_SCROLL: + pointer_frame->value120_y = value; + break; + case WL_POINTER_AXIS_HORIZONTAL_SCROLL: + pointer_frame->value120_x = value; + break; + default: + g_return_if_reached (); + } + + GDK_SEAT_NOTE (seat, EVENTS, + g_message ("value120 scroll, axis %s, value %d, seat %p", + get_axis_name (axis), value, seat)); +} + static int get_active_layout (GdkKeymap *keymap) { @@ -3070,6 +3124,7 @@ static const struct wl_pointer_listener pointer_listener = { pointer_handle_axis_source, pointer_handle_axis_stop, pointer_handle_axis_discrete, + pointer_handle_axis_value120, }; static const struct wl_keyboard_listener keyboard_listener = { diff --git a/gdk/wayland/gdkdisplay-wayland.c b/gdk/wayland/gdkdisplay-wayland.c index fd2aeee12d..142c971730 100644 --- a/gdk/wayland/gdkdisplay-wayland.c +++ b/gdk/wayland/gdkdisplay-wayland.c @@ -232,7 +232,7 @@ _gdk_wayland_display_add_seat (GdkWaylandDisplay *display_wayland, { struct wl_seat *seat; - display_wayland->seat_version = MIN (version, 7); + display_wayland->seat_version = MIN (version, 8); seat = wl_registry_bind (display_wayland->wl_registry, id, &wl_seat_interface, display_wayland->seat_version); diff --git a/gdk/x11/gdkdevicemanager-xi2.c b/gdk/x11/gdkdevicemanager-xi2.c index a146333b5d..44e3342338 100644 --- a/gdk/x11/gdkdevicemanager-xi2.c +++ b/gdk/x11/gdkdevicemanager-xi2.c @@ -1729,6 +1729,7 @@ gdk_x11_device_manager_xi2_translate_event (GdkEventTranslator *translator, &xev->valuators, &delta_x, &delta_y)) { GdkModifierType state; + GdkScrollDirection direction; GDK_DISPLAY_NOTE (display, EVENTS, g_message ("smooth scroll: \n\tdevice: %u\n\tsource device: %u\n\twindow %ld\n\tdeltas: %f %f", @@ -1737,21 +1738,19 @@ gdk_x11_device_manager_xi2_translate_event (GdkEventTranslator *translator, state = _gdk_x11_device_xi2_translate_state (&xev->mods, &xev->buttons, &xev->group); + if (delta_x > 0) + direction = GDK_SCROLL_RIGHT; + else if (delta_x < 0) + direction = GDK_SCROLL_LEFT; + else if (delta_y > 0) + direction = GDK_SCROLL_DOWN; + else + direction = GDK_SCROLL_UP; + if (gdk_device_get_source (source_device) != GDK_SOURCE_TOUCHPAD && ((delta_x == 0.0 && ABS (delta_y) == 1.0) || (ABS (delta_x) == 1.0 && delta_y == 0.0))) { - GdkScrollDirection direction; - - if (delta_x > 0) - direction = GDK_SCROLL_RIGHT; - else if (delta_x < 0) - direction = GDK_SCROLL_LEFT; - else if (delta_y > 0) - direction = GDK_SCROLL_DOWN; - else - direction = GDK_SCROLL_UP; - event = gdk_scroll_event_new_discrete (surface, device, NULL, @@ -1759,6 +1758,17 @@ gdk_x11_device_manager_xi2_translate_event (GdkEventTranslator *translator, state, direction); } + else if (gdk_device_get_source (source_device) == GDK_SOURCE_MOUSE) + { + event = gdk_scroll_event_new_value120 (surface, + device, + NULL, + xev->time, + state, + direction, + delta_x * 120.0, + delta_y * 120.0); + } else { event = gdk_scroll_event_new (surface, diff --git a/gtk/gtkeventcontrollerscroll.c b/gtk/gtkeventcontrollerscroll.c index d78cc01770..197574dca8 100644 --- a/gtk/gtkeventcontrollerscroll.c +++ b/gtk/gtkeventcontrollerscroll.c @@ -85,6 +85,8 @@ struct _GtkEventControllerScroll /* For discrete event coalescing */ double cur_dx; double cur_dy; + double last_cur_dx; + double last_cur_dy; GdkScrollUnit cur_unit; @@ -337,6 +339,17 @@ gtk_event_controller_scroll_handle_hold_event (GtkEventController *controller, return GDK_EVENT_PROPAGATE; } +static gboolean +should_reset_discrete_acc (double current_delta, + double last_delta) +{ + if (last_delta == 0) + return TRUE; + + return (current_delta < 0 && last_delta > 0) || + (current_delta > 0 && last_delta < 0); +} + static gboolean gtk_event_controller_scroll_handle_event (GtkEventController *controller, GdkEvent *event, @@ -416,30 +429,51 @@ gtk_event_controller_scroll_handle_event (GtkEventController *controller, } else { - switch (direction) - { - case GDK_SCROLL_UP: - dy -= 1; - break; - case GDK_SCROLL_DOWN: - dy += 1; - break; - case GDK_SCROLL_LEFT: - dx -= 1; - break; - case GDK_SCROLL_RIGHT: - dx += 1; - break; - case GDK_SCROLL_SMOOTH: - default: - g_assert_not_reached (); - break; - } + gdk_scroll_event_get_deltas (event, &dx, &dy); if ((scroll->flags & GTK_EVENT_CONTROLLER_SCROLL_VERTICAL) == 0) dy = 0; if ((scroll->flags & GTK_EVENT_CONTROLLER_SCROLL_HORIZONTAL) == 0) dx = 0; + + if (scroll->flags & GTK_EVENT_CONTROLLER_SCROLL_DISCRETE) + { + int steps; + + if (dx != 0) + { + if (should_reset_discrete_acc (dx, scroll->last_cur_dx)) + scroll->cur_dx = 0; + + scroll->last_cur_dx = dx; + } + + if (dy != 0) + { + if (should_reset_discrete_acc (dy, scroll->last_cur_dy)) + scroll->cur_dy = 0; + + scroll->last_cur_dy = dy; + } + + scroll->cur_dx += dx; + scroll->cur_dy += dy; + dx = dy = 0; + + if (ABS (scroll->cur_dx) >= 1) + { + steps = trunc (scroll->cur_dx); + scroll->cur_dx -= steps; + dx = steps; + } + + if (ABS (scroll->cur_dy) >= 1) + { + steps = trunc (scroll->cur_dy); + scroll->cur_dy -= steps; + dy = steps; + } + } } scroll->cur_unit = scroll_unit; diff --git a/meson.build b/meson.build index 2ab7290628..2fb35f393a 100644 --- a/meson.build +++ b/meson.build @@ -18,7 +18,7 @@ cairo_req = '>= 1.14.0' gdk_pixbuf_req = '>= 2.30.0' introspection_req = '>= 1.39.0' wayland_proto_req = '>= 1.25' -wayland_req = '>= 1.20.0' +wayland_req = '>= 1.21.0' graphene_req = '>= 1.9.1' epoxy_req = '>= 1.4' cloudproviders_req = '>= 0.3.1'