diff --git a/CMakeLists.txt b/CMakeLists.txt index 8798a4a88b..69dae13eec 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -204,7 +204,7 @@ if (Wayland_Egl_FOUND) set(HAVE_WAYLAND_EGL TRUE) endif() -find_package(Wayland 1.20 REQUIRED COMPONENTS +find_package(Wayland 1.21 REQUIRED COMPONENTS Server ) diff --git a/autotests/libinput/input_event_test.cpp b/autotests/libinput/input_event_test.cpp index 897eec816c..16ea450ca6 100644 --- a/autotests/libinput/input_event_test.cpp +++ b/autotests/libinput/input_event_test.cpp @@ -111,7 +111,7 @@ void InputEventsTest::testInitWheelEvent_data() { QTest::addColumn("orientation"); QTest::addColumn("delta"); - QTest::addColumn("discreteDelta"); + QTest::addColumn("deltaV120"); QTest::addColumn("expectedAngleDelta"); QTest::newRow("horiz") << Qt::Horizontal << 3.3 << 1 << QPoint(3, 0); @@ -129,8 +129,8 @@ void InputEventsTest::testInitWheelEvent() // setup event QFETCH(Qt::Orientation, orientation); QFETCH(qreal, delta); - QFETCH(qint32, discreteDelta); - WheelEvent event(QPointF(100, 200), delta, discreteDelta, orientation, Qt::LeftButton | Qt::RightButton, + QFETCH(qint32, deltaV120); + WheelEvent event(QPointF(100, 200), delta, deltaV120, orientation, Qt::LeftButton | Qt::RightButton, Qt::ShiftModifier | Qt::ControlModifier, InputRedirection::PointerAxisSourceWheel, 300, &d); // compare QWheelEvent contract QCOMPARE(event.type(), QEvent::Wheel); @@ -142,7 +142,7 @@ void InputEventsTest::testInitWheelEvent() QTEST(event.angleDelta(), "expectedAngleDelta"); QTEST(event.orientation(), "orientation"); QTEST(event.delta(), "delta"); - QTEST(event.discreteDelta(), "discreteDelta"); + QTEST(event.deltaV120(), "deltaV120"); QCOMPARE(event.axisSource(), InputRedirection::PointerAxisSourceWheel); // and our custom argument QCOMPARE(event.device(), &d); diff --git a/autotests/libinput/mock_libinput.cpp b/autotests/libinput/mock_libinput.cpp index 84e13e5956..89a3413b0a 100644 --- a/autotests/libinput/mock_libinput.cpp +++ b/autotests/libinput/mock_libinput.cpp @@ -414,7 +414,9 @@ struct libinput_event_pointer *libinput_event_get_pointer_event(struct libinput_ case LIBINPUT_EVENT_POINTER_MOTION: case LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE: case LIBINPUT_EVENT_POINTER_BUTTON: - case LIBINPUT_EVENT_POINTER_AXIS: + case LIBINPUT_EVENT_POINTER_SCROLL_WHEEL: + case LIBINPUT_EVENT_POINTER_SCROLL_FINGER: + case LIBINPUT_EVENT_POINTER_SCROLL_CONTINUOUS: return reinterpret_cast(event); default: return nullptr; @@ -595,29 +597,24 @@ int libinput_event_pointer_has_axis(struct libinput_event_pointer *event, enum l } } -double libinput_event_pointer_get_axis_value(struct libinput_event_pointer *event, enum libinput_pointer_axis axis) +double libinput_event_pointer_get_scroll_value(struct libinput_event_pointer *event, enum libinput_pointer_axis axis) { if (axis == LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL) { - return event->verticalAxisValue; + return event->verticalScrollValue; } else { - return event->horizontalAxisValue; + return event->horizontalScrollValue; } } -double libinput_event_pointer_get_axis_value_discrete(struct libinput_event_pointer *event, enum libinput_pointer_axis axis) +double libinput_event_pointer_get_scroll_value_v120(struct libinput_event_pointer *event, enum libinput_pointer_axis axis) { if (axis == LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL) { - return event->verticalDiscreteAxisValue; + return event->verticalScrollValueV120; } else { - return event->horizontalDiscreteAxisValue; + return event->horizontalScrollValueV120; } } -enum libinput_pointer_axis_source libinput_event_pointer_get_axis_source(struct libinput_event_pointer *event) -{ - return event->axisSource; -} - uint32_t libinput_event_touch_get_time(struct libinput_event_touch *event) { return event->time; diff --git a/autotests/libinput/mock_libinput.h b/autotests/libinput/mock_libinput.h index 23e23d00e1..0511b80f17 100644 --- a/autotests/libinput/mock_libinput.h +++ b/autotests/libinput/mock_libinput.h @@ -128,11 +128,10 @@ struct libinput_event_pointer : libinput_event quint32 button = 0; bool verticalAxis = false; bool horizontalAxis = false; - qreal horizontalAxisValue = 0.0; - qreal verticalAxisValue = 0.0; - qreal horizontalDiscreteAxisValue = 0.0; - qreal verticalDiscreteAxisValue = 0.0; - libinput_pointer_axis_source axisSource = {}; + qreal horizontalScrollValue = 0.0; + qreal verticalScrollValue = 0.0; + qreal horizontalScrollValueV120 = 0.0; + qreal verticalScrollValueV120 = 0.0; QSizeF delta; QPointF absolutePos; }; diff --git a/autotests/libinput/pointer_event_test.cpp b/autotests/libinput/pointer_event_test.cpp index bbc73d0dca..4126e61ba1 100644 --- a/autotests/libinput/pointer_event_test.cpp +++ b/autotests/libinput/pointer_event_test.cpp @@ -17,7 +17,6 @@ Q_DECLARE_METATYPE(libinput_event_type) Q_DECLARE_METATYPE(libinput_button_state) -Q_DECLARE_METATYPE(libinput_pointer_axis_source) using namespace KWin::LibInput; @@ -32,8 +31,12 @@ private Q_SLOTS: void testType(); void testButton_data(); void testButton(); - void testAxis_data(); - void testAxis(); + void testScrollWheel_data(); + void testScrollWheel(); + void testScrollFinger_data(); + void testScrollFinger(); + void testScrollContinuous_data(); + void testScrollContinuous(); void testMotion(); void testAbsoluteMotion(); @@ -66,7 +69,9 @@ void TestLibinputPointerEvent::testType_data() QTest::newRow("motion") << LIBINPUT_EVENT_POINTER_MOTION; QTest::newRow("absolute motion") << LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE; QTest::newRow("button") << LIBINPUT_EVENT_POINTER_BUTTON; - QTest::newRow("axis") << LIBINPUT_EVENT_POINTER_AXIS; + QTest::newRow("scroll wheel") << LIBINPUT_EVENT_POINTER_SCROLL_WHEEL; + QTest::newRow("scroll finger") << LIBINPUT_EVENT_POINTER_SCROLL_FINGER; + QTest::newRow("scroll continuous") << LIBINPUT_EVENT_POINTER_SCROLL_CONTINUOUS; } void TestLibinputPointerEvent::testType() @@ -122,64 +127,129 @@ void TestLibinputPointerEvent::testButton() QCOMPARE(pe->timeMicroseconds(), quint64(time * 1000)); } -void TestLibinputPointerEvent::testAxis_data() +void TestLibinputPointerEvent::testScrollWheel_data() { QTest::addColumn("horizontal"); QTest::addColumn("vertical"); QTest::addColumn("value"); - QTest::addColumn("discreteValue"); - QTest::addColumn("axisSource"); - QTest::addColumn("expectedAxisSource"); + QTest::addColumn("valueV120"); QTest::addColumn("time"); - QTest::newRow("wheel/horizontal") << true << false << QPointF(3.0, 0.0) << QPoint(1, 0) << LIBINPUT_POINTER_AXIS_SOURCE_WHEEL << KWin::InputRedirection::PointerAxisSourceWheel << 100u; - QTest::newRow("wheel/vertical") << false << true << QPointF(0.0, 2.5) << QPoint(0, 1) << LIBINPUT_POINTER_AXIS_SOURCE_WHEEL << KWin::InputRedirection::PointerAxisSourceWheel << 200u; - QTest::newRow("wheel/both") << true << true << QPointF(1.1, 4.2) << QPoint(1, 1) << LIBINPUT_POINTER_AXIS_SOURCE_WHEEL << KWin::InputRedirection::PointerAxisSourceWheel << 300u; - - QTest::newRow("finger/horizontal") << true << false << QPointF(3.0, 0.0) << QPoint(0, 0) << LIBINPUT_POINTER_AXIS_SOURCE_FINGER << KWin::InputRedirection::PointerAxisSourceFinger << 400u; - QTest::newRow("stop finger/horizontal") << true << false << QPointF(0.0, 0.0) << QPoint(0, 0) << LIBINPUT_POINTER_AXIS_SOURCE_FINGER << KWin::InputRedirection::PointerAxisSourceFinger << 500u; - QTest::newRow("finger/vertical") << false << true << QPointF(0.0, 2.5) << QPoint(0, 0) << LIBINPUT_POINTER_AXIS_SOURCE_FINGER << KWin::InputRedirection::PointerAxisSourceFinger << 600u; - QTest::newRow("stop finger/vertical") << false << true << QPointF(0.0, 0.0) << QPoint(0, 0) << LIBINPUT_POINTER_AXIS_SOURCE_FINGER << KWin::InputRedirection::PointerAxisSourceFinger << 700u; - QTest::newRow("finger/both") << true << true << QPointF(1.1, 4.2) << QPoint(0, 0) << LIBINPUT_POINTER_AXIS_SOURCE_FINGER << KWin::InputRedirection::PointerAxisSourceFinger << 800u; - QTest::newRow("stop finger/both") << true << true << QPointF(0.0, 0.0) << QPoint(0, 0) << LIBINPUT_POINTER_AXIS_SOURCE_FINGER << KWin::InputRedirection::PointerAxisSourceFinger << 900u; - - QTest::newRow("continuous/horizontal") << true << false << QPointF(3.0, 0.0) << QPoint(0, 0) << LIBINPUT_POINTER_AXIS_SOURCE_CONTINUOUS << KWin::InputRedirection::PointerAxisSourceContinuous << 1000u; - QTest::newRow("continuous/vertical") << false << true << QPointF(0.0, 2.5) << QPoint(0, 0) << LIBINPUT_POINTER_AXIS_SOURCE_CONTINUOUS << KWin::InputRedirection::PointerAxisSourceContinuous << 1100u; - QTest::newRow("continuous/both") << true << true << QPointF(1.1, 4.2) << QPoint(0, 0) << LIBINPUT_POINTER_AXIS_SOURCE_CONTINUOUS << KWin::InputRedirection::PointerAxisSourceContinuous << 1200u; + QTest::newRow("wheel/horizontal") << true << false << QPointF(3.0, 0.0) << QPoint(120, 0) << 100u; + QTest::newRow("wheel/vertical") << false << true << QPointF(0.0, 2.5) << QPoint(0, 120) << 200u; + QTest::newRow("wheel/both") << true << true << QPointF(1.1, 4.2) << QPoint(120, 120) << 300u; } -void TestLibinputPointerEvent::testAxis() +void TestLibinputPointerEvent::testScrollWheel() { // this test verifies pointer axis functionality libinput_event_pointer *pointerEvent = new libinput_event_pointer; pointerEvent->device = m_nativeDevice; - pointerEvent->type = LIBINPUT_EVENT_POINTER_AXIS; + pointerEvent->type = LIBINPUT_EVENT_POINTER_SCROLL_WHEEL; QFETCH(bool, horizontal); QFETCH(bool, vertical); QFETCH(QPointF, value); - QFETCH(QPoint, discreteValue); - QFETCH(libinput_pointer_axis_source, axisSource); + QFETCH(QPoint, valueV120); QFETCH(quint32, time); pointerEvent->horizontalAxis = horizontal; pointerEvent->verticalAxis = vertical; - pointerEvent->horizontalAxisValue = value.x(); - pointerEvent->verticalAxisValue = value.y(); - pointerEvent->horizontalDiscreteAxisValue = discreteValue.x(); - pointerEvent->verticalDiscreteAxisValue = discreteValue.y(); - pointerEvent->axisSource = axisSource; + pointerEvent->horizontalScrollValue = value.x(); + pointerEvent->verticalScrollValue = value.y(); + pointerEvent->horizontalScrollValueV120 = valueV120.x(); + pointerEvent->verticalScrollValueV120 = valueV120.y(); pointerEvent->time = time; std::unique_ptr event(Event::create(pointerEvent)); auto pe = dynamic_cast(event.get()); QVERIFY(pe); - QCOMPARE(pe->type(), LIBINPUT_EVENT_POINTER_AXIS); + QCOMPARE(pe->type(), LIBINPUT_EVENT_POINTER_SCROLL_WHEEL); QCOMPARE(pe->axis().contains(KWin::InputRedirection::PointerAxisHorizontal), horizontal); QCOMPARE(pe->axis().contains(KWin::InputRedirection::PointerAxisVertical), vertical); - QCOMPARE(pe->axisValue(KWin::InputRedirection::PointerAxisHorizontal), value.x()); - QCOMPARE(pe->axisValue(KWin::InputRedirection::PointerAxisVertical), value.y()); - QCOMPARE(pe->discreteAxisValue(KWin::InputRedirection::PointerAxisHorizontal), discreteValue.x()); - QCOMPARE(pe->discreteAxisValue(KWin::InputRedirection::PointerAxisVertical), discreteValue.y()); - QTEST(pe->axisSource(), "expectedAxisSource"); + QCOMPARE(pe->scrollValue(KWin::InputRedirection::PointerAxisHorizontal), value.x()); + QCOMPARE(pe->scrollValue(KWin::InputRedirection::PointerAxisVertical), value.y()); + QCOMPARE(pe->scrollValueV120(KWin::InputRedirection::PointerAxisHorizontal), valueV120.x()); + QCOMPARE(pe->scrollValueV120(KWin::InputRedirection::PointerAxisVertical), valueV120.y()); + QCOMPARE(pe->time(), time); +} + +void TestLibinputPointerEvent::testScrollFinger_data() +{ + QTest::addColumn("horizontal"); + QTest::addColumn("vertical"); + QTest::addColumn("value"); + QTest::addColumn("time"); + + QTest::newRow("finger/horizontal") << true << false << QPointF(3.0, 0.0) << 400u; + QTest::newRow("stop finger/horizontal") << true << false << QPointF(0.0, 0.0) << 500u; + QTest::newRow("finger/vertical") << false << true << QPointF(0.0, 2.5) << 600u; + QTest::newRow("stop finger/vertical") << false << true << QPointF(0.0, 0.0) << 700u; + QTest::newRow("finger/both") << true << true << QPointF(1.1, 4.2) << 800u; + QTest::newRow("stop finger/both") << true << true << QPointF(0.0, 0.0) << 900u; +} + +void TestLibinputPointerEvent::testScrollFinger() +{ + // this test verifies pointer axis functionality + libinput_event_pointer *pointerEvent = new libinput_event_pointer; + pointerEvent->device = m_nativeDevice; + pointerEvent->type = LIBINPUT_EVENT_POINTER_SCROLL_FINGER; + QFETCH(bool, horizontal); + QFETCH(bool, vertical); + QFETCH(QPointF, value); + QFETCH(quint32, time); + pointerEvent->horizontalAxis = horizontal; + pointerEvent->verticalAxis = vertical; + pointerEvent->horizontalScrollValue = value.x(); + pointerEvent->verticalScrollValue = value.y(); + pointerEvent->time = time; + + std::unique_ptr event(Event::create(pointerEvent)); + auto pe = dynamic_cast(event.get()); + QVERIFY(pe); + QCOMPARE(pe->type(), LIBINPUT_EVENT_POINTER_SCROLL_FINGER); + QCOMPARE(pe->axis().contains(KWin::InputRedirection::PointerAxisHorizontal), horizontal); + QCOMPARE(pe->axis().contains(KWin::InputRedirection::PointerAxisVertical), vertical); + QCOMPARE(pe->scrollValue(KWin::InputRedirection::PointerAxisHorizontal), value.x()); + QCOMPARE(pe->scrollValue(KWin::InputRedirection::PointerAxisVertical), value.y()); + QCOMPARE(pe->time(), time); +} + +void TestLibinputPointerEvent::testScrollContinuous_data() +{ + QTest::addColumn("horizontal"); + QTest::addColumn("vertical"); + QTest::addColumn("value"); + QTest::addColumn("time"); + + QTest::newRow("continuous/horizontal") << true << false << QPointF(3.0, 0.0) << 1000u; + QTest::newRow("continuous/vertical") << false << true << QPointF(0.0, 2.5) << 1100u; + QTest::newRow("continuous/both") << true << true << QPointF(1.1, 4.2) << 1200u; +} + +void TestLibinputPointerEvent::testScrollContinuous() +{ + // this test verifies pointer axis functionality + libinput_event_pointer *pointerEvent = new libinput_event_pointer; + pointerEvent->device = m_nativeDevice; + pointerEvent->type = LIBINPUT_EVENT_POINTER_SCROLL_CONTINUOUS; + QFETCH(bool, horizontal); + QFETCH(bool, vertical); + QFETCH(QPointF, value); + QFETCH(quint32, time); + pointerEvent->horizontalAxis = horizontal; + pointerEvent->verticalAxis = vertical; + pointerEvent->horizontalScrollValue = value.x(); + pointerEvent->verticalScrollValue = value.y(); + pointerEvent->time = time; + + std::unique_ptr event(Event::create(pointerEvent)); + auto pe = dynamic_cast(event.get()); + QVERIFY(pe); + QCOMPARE(pe->type(), LIBINPUT_EVENT_POINTER_SCROLL_CONTINUOUS); + QCOMPARE(pe->axis().contains(KWin::InputRedirection::PointerAxisHorizontal), horizontal); + QCOMPARE(pe->axis().contains(KWin::InputRedirection::PointerAxisVertical), vertical); + QCOMPARE(pe->scrollValue(KWin::InputRedirection::PointerAxisHorizontal), value.x()); + QCOMPARE(pe->scrollValue(KWin::InputRedirection::PointerAxisVertical), value.y()); QCOMPARE(pe->time(), time); } diff --git a/src/backends/libinput/connection.cpp b/src/backends/libinput/connection.cpp index edb321e9cb..2f234c600d 100644 --- a/src/backends/libinput/connection.cpp +++ b/src/backends/libinput/connection.cpp @@ -300,12 +300,42 @@ void Connection::processEvents() Q_EMIT ke->device()->keyChanged(ke->key(), ke->state(), ke->time(), ke->device()); break; } - case LIBINPUT_EVENT_POINTER_AXIS: { - PointerEvent *pe = static_cast(event.get()); - const auto axes = pe->axis(); + case LIBINPUT_EVENT_POINTER_SCROLL_WHEEL: { + const PointerEvent *pointerEvent = static_cast(event.get()); + const auto axes = pointerEvent->axis(); for (const InputRedirection::PointerAxis &axis : axes) { - Q_EMIT pe->device()->pointerAxisChanged(axis, pe->axisValue(axis), pe->discreteAxisValue(axis), - pe->axisSource(), pe->time(), pe->device()); + Q_EMIT pointerEvent->device()->pointerAxisChanged(axis, + pointerEvent->scrollValue(axis), + pointerEvent->scrollValueV120(axis), + InputRedirection::PointerAxisSourceWheel, + pointerEvent->time(), + pointerEvent->device()); + } + break; + } + case LIBINPUT_EVENT_POINTER_SCROLL_FINGER: { + const PointerEvent *pointerEvent = static_cast(event.get()); + const auto axes = pointerEvent->axis(); + for (const InputRedirection::PointerAxis &axis : axes) { + Q_EMIT pointerEvent->device()->pointerAxisChanged(axis, + pointerEvent->scrollValue(axis), + 0, + InputRedirection::PointerAxisSourceFinger, + pointerEvent->time(), + pointerEvent->device()); + } + break; + } + case LIBINPUT_EVENT_POINTER_SCROLL_CONTINUOUS: { + const PointerEvent *pointerEvent = static_cast(event.get()); + const auto axes = pointerEvent->axis(); + for (const InputRedirection::PointerAxis &axis : axes) { + Q_EMIT pointerEvent->device()->pointerAxisChanged(axis, + pointerEvent->scrollValue(axis), + 0, + InputRedirection::PointerAxisSourceContinuous, + pointerEvent->time(), + pointerEvent->device()); } break; } diff --git a/src/backends/libinput/events.cpp b/src/backends/libinput/events.cpp index d47432542f..f9ce18d3cf 100644 --- a/src/backends/libinput/events.cpp +++ b/src/backends/libinput/events.cpp @@ -27,7 +27,9 @@ std::unique_ptr Event::create(libinput_event *event) switch (t) { case LIBINPUT_EVENT_KEYBOARD_KEY: return std::make_unique(event); - case LIBINPUT_EVENT_POINTER_AXIS: + case LIBINPUT_EVENT_POINTER_SCROLL_WHEEL: + case LIBINPUT_EVENT_POINTER_SCROLL_FINGER: + case LIBINPUT_EVENT_POINTER_SCROLL_CONTINUOUS: case LIBINPUT_EVENT_POINTER_BUTTON: case LIBINPUT_EVENT_POINTER_MOTION: case LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE: @@ -191,7 +193,6 @@ InputRedirection::PointerButtonState PointerEvent::buttonState() const QVector PointerEvent::axis() const { - Q_ASSERT(type() == LIBINPUT_EVENT_POINTER_AXIS); QVector a; if (libinput_event_pointer_has_axis(m_pointerEvent, LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL)) { a << InputRedirection::PointerAxisHorizontal; @@ -202,39 +203,20 @@ QVector PointerEvent::axis() const return a; } -qreal PointerEvent::axisValue(InputRedirection::PointerAxis axis) const +qreal PointerEvent::scrollValue(InputRedirection::PointerAxis axis) const { - Q_ASSERT(type() == LIBINPUT_EVENT_POINTER_AXIS); const libinput_pointer_axis a = axis == InputRedirection::PointerAxisHorizontal ? LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL : LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL; - return libinput_event_pointer_get_axis_value(m_pointerEvent, a) * device()->scrollFactor(); + return libinput_event_pointer_get_scroll_value(m_pointerEvent, a) * device()->scrollFactor(); } -qint32 PointerEvent::discreteAxisValue(InputRedirection::PointerAxis axis) const +qint32 PointerEvent::scrollValueV120(InputRedirection::PointerAxis axis) const { - Q_ASSERT(type() == LIBINPUT_EVENT_POINTER_AXIS); const libinput_pointer_axis a = (axis == InputRedirection::PointerAxisHorizontal) ? LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL : LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL; - return libinput_event_pointer_get_axis_value_discrete(m_pointerEvent, a) * device()->scrollFactor(); -} - -InputRedirection::PointerAxisSource PointerEvent::axisSource() const -{ - Q_ASSERT(type() == LIBINPUT_EVENT_POINTER_AXIS); - switch (libinput_event_pointer_get_axis_source(m_pointerEvent)) { - case LIBINPUT_POINTER_AXIS_SOURCE_WHEEL: - return InputRedirection::PointerAxisSourceWheel; - case LIBINPUT_POINTER_AXIS_SOURCE_FINGER: - return InputRedirection::PointerAxisSourceFinger; - case LIBINPUT_POINTER_AXIS_SOURCE_CONTINUOUS: - return InputRedirection::PointerAxisSourceContinuous; - case LIBINPUT_POINTER_AXIS_SOURCE_WHEEL_TILT: - return InputRedirection::PointerAxisSourceWheelTilt; - default: - return InputRedirection::PointerAxisSourceUnknown; - } + return libinput_event_pointer_get_scroll_value_v120(m_pointerEvent, a) * device()->scrollFactor(); } TouchEvent::TouchEvent(libinput_event *event, libinput_event_type type) diff --git a/src/backends/libinput/events.h b/src/backends/libinput/events.h index 0b6ee8ab11..322f01b1c8 100644 --- a/src/backends/libinput/events.h +++ b/src/backends/libinput/events.h @@ -87,9 +87,8 @@ public: uint32_t time() const; quint64 timeMicroseconds() const; QVector axis() const; - qreal axisValue(InputRedirection::PointerAxis a) const; - qint32 discreteAxisValue(InputRedirection::PointerAxis axis) const; - InputRedirection::PointerAxisSource axisSource() const; + qreal scrollValue(InputRedirection::PointerAxis a) const; + qint32 scrollValueV120(InputRedirection::PointerAxis axis) const; operator libinput_event_pointer *() { diff --git a/src/backends/x11/windowed/x11_windowed_backend.cpp b/src/backends/x11/windowed/x11_windowed_backend.cpp index c6c7ff253e..59309900a1 100644 --- a/src/backends/x11/windowed/x11_windowed_backend.cpp +++ b/src/backends/x11/windowed/x11_windowed_backend.cpp @@ -511,7 +511,7 @@ void X11WindowedBackend::handleButtonPress(xcb_button_press_event_t *event) if (!pressed) { return; } - const int delta = (event->detail == XCB_BUTTON_INDEX_4 || event->detail == 6) ? -1 : 1; + const int delta = (event->detail == XCB_BUTTON_INDEX_4 || event->detail == 6) ? -120 : 120; static const qreal s_defaultAxisStepDistance = 10.0; InputRedirection::PointerAxis axis; if (event->detail > 5) { diff --git a/src/core/inputdevice.h b/src/core/inputdevice.h index cfe151eb2e..b6c450d3c3 100644 --- a/src/core/inputdevice.h +++ b/src/core/inputdevice.h @@ -49,7 +49,7 @@ Q_SIGNALS: void pointerButtonChanged(quint32 button, InputRedirection::PointerButtonState state, quint32 time, InputDevice *device); void pointerMotionAbsolute(const QPointF &position, quint32 time, InputDevice *device); void pointerMotion(const QSizeF &delta, const QSizeF &deltaNonAccelerated, quint32 time, quint64 timeMicroseconds, InputDevice *device); - void pointerAxisChanged(InputRedirection::PointerAxis axis, qreal delta, qint32 discreteDelta, + void pointerAxisChanged(InputRedirection::PointerAxis axis, qreal delta, qint32 deltaV120, InputRedirection::PointerAxisSource source, quint32 time, InputDevice *device); void touchFrame(InputDevice *device); void touchCanceled(InputDevice *device); diff --git a/src/input.cpp b/src/input.cpp index 4963c9386e..1488d2e8a8 100644 --- a/src/input.cpp +++ b/src/input.cpp @@ -392,7 +392,7 @@ public: const WheelEvent *wheelEvent = static_cast(event); seat->setTimestamp(wheelEvent->timestamp()); seat->notifyPointerAxis(wheelEvent->orientation(), wheelEvent->delta(), - wheelEvent->discreteDelta(), + wheelEvent->deltaV120(), kwinAxisSourceToKWaylandAxisSource(wheelEvent->axisSource())); seat->notifyPointerFrame(); } @@ -1866,7 +1866,7 @@ public: auto seat = waylandServer()->seat(); seat->setTimestamp(event->timestamp()); auto _event = static_cast(event); - seat->notifyPointerAxis(_event->orientation(), _event->delta(), _event->discreteDelta(), + seat->notifyPointerAxis(_event->orientation(), _event->delta(), _event->deltaV120(), kwinAxisSourceToKWaylandAxisSource(_event->axisSource())); seat->notifyPointerFrame(); return true; diff --git a/src/input_event.cpp b/src/input_event.cpp index 4fac01c638..85184bf9c3 100644 --- a/src/input_event.cpp +++ b/src/input_event.cpp @@ -24,14 +24,14 @@ MouseEvent::MouseEvent(QEvent::Type type, const QPointF &pos, Qt::MouseButton bu setTimestamp(timestamp); } -WheelEvent::WheelEvent(const QPointF &pos, qreal delta, qint32 discreteDelta, Qt::Orientation orientation, +WheelEvent::WheelEvent(const QPointF &pos, qreal delta, qint32 deltaV120, Qt::Orientation orientation, Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers, InputRedirection::PointerAxisSource source, quint32 timestamp, InputDevice *device) : QWheelEvent(pos, pos, QPoint(), (orientation == Qt::Horizontal) ? QPoint(delta, 0) : QPoint(0, delta), buttons, modifiers, Qt::NoScrollPhase, false) , m_device(device) , m_orientation(orientation) , m_delta(delta) - , m_discreteDelta(discreteDelta) + , m_deltaV120(deltaV120) , m_source(source) { setTimestamp(timestamp); diff --git a/src/input_event.h b/src/input_event.h index 84f6ea3cbf..7bbaf0bdfc 100644 --- a/src/input_event.h +++ b/src/input_event.h @@ -79,7 +79,7 @@ private: class WheelEvent : public QWheelEvent { public: - explicit WheelEvent(const QPointF &pos, qreal delta, qint32 discreteDelta, Qt::Orientation orientation, + explicit WheelEvent(const QPointF &pos, qreal delta, qint32 deltaV120, Qt::Orientation orientation, Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers, InputRedirection::PointerAxisSource source, quint32 timestamp, InputDevice *device); @@ -93,9 +93,9 @@ public: return m_delta; } - qint32 discreteDelta() const + qint32 deltaV120() const { - return m_discreteDelta; + return m_deltaV120; } InputRedirection::PointerAxisSource axisSource() const @@ -122,7 +122,7 @@ private: InputDevice *m_device; Qt::Orientation m_orientation; qreal m_delta; - qint32 m_discreteDelta; + qint32 m_deltaV120; InputRedirection::PointerAxisSource m_source; Qt::KeyboardModifiers m_modifiersRelevantForShortcuts = Qt::KeyboardModifiers(); }; diff --git a/src/pointer_input.cpp b/src/pointer_input.cpp index 6632524e97..652e8212c9 100644 --- a/src/pointer_input.cpp +++ b/src/pointer_input.cpp @@ -290,7 +290,7 @@ void PointerInputRedirection::processButton(uint32_t button, InputRedirection::P } } -void PointerInputRedirection::processAxis(InputRedirection::PointerAxis axis, qreal delta, qint32 discreteDelta, +void PointerInputRedirection::processAxis(InputRedirection::PointerAxis axis, qreal delta, qint32 deltaV120, InputRedirection::PointerAxisSource source, uint32_t time, InputDevice *device) { input()->setLastInputHandler(this); @@ -298,7 +298,7 @@ void PointerInputRedirection::processAxis(InputRedirection::PointerAxis axis, qr Q_EMIT input()->pointerAxisChanged(axis, delta); - WheelEvent wheelEvent(m_pos, delta, discreteDelta, + WheelEvent wheelEvent(m_pos, delta, deltaV120, (axis == InputRedirection::PointerAxisHorizontal) ? Qt::Horizontal : Qt::Vertical, m_qtButtons, input()->keyboardModifiers(), source, time, device); wheelEvent.setModifiersRelevantForGlobalShortcuts(input()->modifiersRelevantForGlobalShortcuts()); diff --git a/src/pointer_input.h b/src/pointer_input.h index bf562d89d4..1180c465dd 100644 --- a/src/pointer_input.h +++ b/src/pointer_input.h @@ -96,7 +96,7 @@ public: /** * @internal */ - void processAxis(InputRedirection::PointerAxis axis, qreal delta, qint32 discreteDelta, InputRedirection::PointerAxisSource source, uint32_t time, InputDevice *device = nullptr); + void processAxis(InputRedirection::PointerAxis axis, qreal delta, qint32 deltaV120, InputRedirection::PointerAxisSource source, uint32_t time, InputDevice *device = nullptr); /** * @internal */ diff --git a/src/wayland/autotests/client/test_wayland_seat.cpp b/src/wayland/autotests/client/test_wayland_seat.cpp index 250c06aee2..cc1f52a9c0 100644 --- a/src/wayland/autotests/client/test_wayland_seat.cpp +++ b/src/wayland/autotests/client/test_wayland_seat.cpp @@ -407,12 +407,12 @@ void TestWaylandSeat::testPointer() // test axis m_seatInterface->setTimestamp(2); - m_seatInterface->notifyPointerAxis(Qt::Horizontal, 10, 1, PointerAxisSource::Wheel); + m_seatInterface->notifyPointerAxis(Qt::Horizontal, 10, 120, PointerAxisSource::Wheel); m_seatInterface->notifyPointerFrame(); QVERIFY(axisSpy.wait()); QCOMPARE(frameSpy.count(), 6); m_seatInterface->setTimestamp(3); - m_seatInterface->notifyPointerAxis(Qt::Vertical, 20, 2, PointerAxisSource::Wheel); + m_seatInterface->notifyPointerAxis(Qt::Vertical, 20, 240, PointerAxisSource::Wheel); m_seatInterface->notifyPointerFrame(); QVERIFY(axisSpy.wait()); QCOMPARE(frameSpy.count(), 7); @@ -1196,7 +1196,7 @@ void TestWaylandSeat::testPointerAxis() quint32 timestamp = 1; m_seatInterface->setTimestamp(timestamp++); - m_seatInterface->notifyPointerAxis(Qt::Vertical, 10, 1, PointerAxisSource::Wheel); + m_seatInterface->notifyPointerAxis(Qt::Vertical, 10, 120, PointerAxisSource::Wheel); m_seatInterface->notifyPointerFrame(); QVERIFY(frameSpy.wait()); QCOMPARE(frameSpy.count(), 2); @@ -1242,7 +1242,7 @@ void TestWaylandSeat::testPointerAxis() // if the device is unknown, no axis_source event should be sent m_seatInterface->setTimestamp(timestamp++); - m_seatInterface->notifyPointerAxis(Qt::Horizontal, 42, 1, PointerAxisSource::Unknown); + m_seatInterface->notifyPointerAxis(Qt::Horizontal, 42, 120, PointerAxisSource::Unknown); m_seatInterface->notifyPointerFrame(); QVERIFY(frameSpy.wait()); QCOMPARE(frameSpy.count(), 5); diff --git a/src/wayland/pointer_interface.cpp b/src/wayland/pointer_interface.cpp index 516c31f349..f7c64433f3 100644 --- a/src/wayland/pointer_interface.cpp +++ b/src/wayland/pointer_interface.cpp @@ -208,12 +208,35 @@ void PointerInterface::sendButton(quint32 button, PointerButtonState state, quin } } -void PointerInterface::sendAxis(Qt::Orientation orientation, qreal delta, qint32 discreteDelta, PointerAxisSource source) +static bool shouldResetAccumulator(int accumulator, int delta) +{ + // Reset the accumulator if the delta has opposite sign. + return accumulator && (accumulator < 0 != delta < 0); +} + +void PointerInterface::sendAxis(Qt::Orientation orientation, qreal delta, qint32 deltaV120, PointerAxisSource source) { if (!d->focusedSurface) { return; } + qint32 deltaDiscrete; + if (orientation == Qt::Horizontal) { + if (shouldResetAccumulator(d->accumulatorV120.x(), deltaV120)) { + d->accumulatorV120.setX(0); + } + d->accumulatorV120.rx() += deltaV120; + deltaDiscrete = d->accumulatorV120.x() / 120; + d->accumulatorV120.rx() -= deltaDiscrete * 120; + } else { + if (shouldResetAccumulator(d->accumulatorV120.y(), deltaV120)) { + d->accumulatorV120.setY(0); + } + d->accumulatorV120.ry() += deltaV120; + deltaDiscrete = d->accumulatorV120.y() / 120; + d->accumulatorV120.ry() -= deltaDiscrete * 120; + } + const auto pointerResources = d->pointersForClient(d->focusedSurface->client()); for (PointerInterfacePrivate::Resource *resource : pointerResources) { const quint32 version = resource->version(); @@ -244,8 +267,14 @@ void PointerInterface::sendAxis(Qt::Orientation orientation, qreal delta, qint32 } if (delta != 0.0) { - if (discreteDelta && version >= WL_POINTER_AXIS_DISCRETE_SINCE_VERSION) { - d->send_axis_discrete(resource->handle, wlOrientation, discreteDelta); + if (version >= WL_POINTER_AXIS_VALUE120_SINCE_VERSION) { + if (deltaV120) { + d->send_axis_value120(resource->handle, wlOrientation, deltaV120); + } + } else if (version >= WL_POINTER_AXIS_DISCRETE_SINCE_VERSION) { + if (deltaDiscrete) { + d->send_axis_discrete(resource->handle, wlOrientation, deltaDiscrete); + } } d->send_axis(resource->handle, d->seat->timestamp(), wlOrientation, wl_fixed_from_double(delta)); } else if (version >= WL_POINTER_AXIS_STOP_SINCE_VERSION) { diff --git a/src/wayland/pointer_interface.h b/src/wayland/pointer_interface.h index c7e314c972..a68336172e 100644 --- a/src/wayland/pointer_interface.h +++ b/src/wayland/pointer_interface.h @@ -58,7 +58,7 @@ public: void sendEnter(SurfaceInterface *surface, const QPointF &position, quint32 serial); void sendLeave(quint32 serial); void sendButton(quint32 button, PointerButtonState state, quint32 serial); - void sendAxis(Qt::Orientation orientation, qreal delta, qint32 discreteDelta, PointerAxisSource source); + void sendAxis(Qt::Orientation orientation, qreal delta, qint32 deltaV120, PointerAxisSource source); void sendMotion(const QPointF &position); void sendFrame(); diff --git a/src/wayland/pointer_interface_p.h b/src/wayland/pointer_interface_p.h index de4f1a1ea3..b0989a1645 100644 --- a/src/wayland/pointer_interface_p.h +++ b/src/wayland/pointer_interface_p.h @@ -43,6 +43,7 @@ public: std::unique_ptr pinchGesturesV1; std::unique_ptr holdGesturesV1; QPointF lastPosition; + QPoint accumulatorV120; void sendLeave(quint32 serial); void sendEnter(const QPointF &parentSurfacePosition, quint32 serial); diff --git a/src/wayland/seat_interface.cpp b/src/wayland/seat_interface.cpp index 8d7d43ebdd..2aa6a6e504 100644 --- a/src/wayland/seat_interface.cpp +++ b/src/wayland/seat_interface.cpp @@ -37,7 +37,7 @@ namespace KWaylandServer { -static const int s_version = 7; +static const int s_version = 8; SeatInterfacePrivate *SeatInterfacePrivate::get(SeatInterface *seat) { @@ -690,7 +690,7 @@ bool SeatInterface::isPointerButtonPressed(quint32 button) const return it.value() == SeatInterfacePrivate::Pointer::State::Pressed; } -void SeatInterface::notifyPointerAxis(Qt::Orientation orientation, qreal delta, qint32 discreteDelta, PointerAxisSource source) +void SeatInterface::notifyPointerAxis(Qt::Orientation orientation, qreal delta, qint32 deltaV120, PointerAxisSource source) { if (!d->pointer) { return; @@ -699,7 +699,7 @@ void SeatInterface::notifyPointerAxis(Qt::Orientation orientation, qreal delta, // ignore return; } - d->pointer->sendAxis(orientation, delta, discreteDelta, source); + d->pointer->sendAxis(orientation, delta, deltaV120, source); } void SeatInterface::notifyPointerButton(Qt::MouseButton button, PointerButtonState state) diff --git a/src/wayland/seat_interface.h b/src/wayland/seat_interface.h index 57d8e245cd..a2a9d13869 100644 --- a/src/wayland/seat_interface.h +++ b/src/wayland/seat_interface.h @@ -374,10 +374,10 @@ public: * * @param orientation The scroll axis. * @param delta The length of a vector along the specified axis @p orientation. - * @param discreteDelta The number of discrete steps, e.g. mouse wheel clicks. + * @param deltaV120 The high-resolution scrolling axis value. * @param source Describes how the axis event was physically generated. */ - void notifyPointerAxis(Qt::Orientation orientation, qreal delta, qint32 discreteDelta, PointerAxisSource source); + void notifyPointerAxis(Qt::Orientation orientation, qreal delta, qint32 deltaV120, PointerAxisSource source); /** * @returns true if there is a pressed button with the given @p serial */