diff --git a/autotests/integration/lockscreen.cpp b/autotests/integration/lockscreen.cpp index 8d3b5d1a72..4786617ca6 100644 --- a/autotests/integration/lockscreen.cpp +++ b/autotests/integration/lockscreen.cpp @@ -665,18 +665,18 @@ void LockScreenTest::testAxisShortcut() // try to trigger the shortcut quint32 timestamp = 1; -#define PERFORM(expectedCount) \ - do { \ - Test::keyboardKeyPressed(KEY_LEFTMETA, timestamp++); \ - if (direction == Qt::Vertical) \ - Test::pointerAxisVertical(sign * 5.0, timestamp++); \ - else \ - Test::pointerAxisHorizontal(sign * 5.0, timestamp++); \ - QCoreApplication::instance()->processEvents(); \ - QCOMPARE(actionSpy.count(), expectedCount); \ - Test::keyboardKeyReleased(KEY_LEFTMETA, timestamp++); \ - QCoreApplication::instance()->processEvents(); \ - QCOMPARE(actionSpy.count(), expectedCount); \ +#define PERFORM(expectedCount) \ + do { \ + Test::keyboardKeyPressed(KEY_LEFTMETA, timestamp++); \ + if (direction == Qt::Vertical) \ + Test::pointerAxisVertical(sign * 15.0, timestamp++); \ + else \ + Test::pointerAxisHorizontal(sign * 15.0, timestamp++); \ + QCoreApplication::instance()->processEvents(); \ + QCOMPARE(actionSpy.count(), expectedCount); \ + Test::keyboardKeyReleased(KEY_LEFTMETA, timestamp++); \ + QCoreApplication::instance()->processEvents(); \ + QCOMPARE(actionSpy.count(), expectedCount); \ } while (false) PERFORM(1); diff --git a/src/globalshortcuts.cpp b/src/globalshortcuts.cpp index 5682e2a797..40b99d2018 100644 --- a/src/globalshortcuts.cpp +++ b/src/globalshortcuts.cpp @@ -240,17 +240,16 @@ bool GlobalShortcutsManager::processKeyRelease(Qt::KeyboardModifiers mods, int k } template -bool match(QList &shortcuts, Args... args) +GlobalShortcut *match(QList &shortcuts, Args... args) { for (auto &sc : shortcuts) { if (std::holds_alternative(sc.shortcut())) { if (std::get(sc.shortcut()) == ShortcutKind{args...}) { - sc.invoke(); - return true; + return ≻ } } } - return false; + return nullptr; } // TODO(C++20): use ranges for a nicer way of filtering by shortcut type @@ -266,10 +265,14 @@ bool GlobalShortcutsManager::processPointerPressed(Qt::KeyboardModifiers mods, Q Q_ARG(Qt::MouseButtons, pointerButtons)); } #endif - return match(m_shortcuts, mods, pointerButtons); + GlobalShortcut *shortcut = match(m_shortcuts, mods, pointerButtons); + if (shortcut) { + shortcut->invoke(); + } + return shortcut != nullptr; } -bool GlobalShortcutsManager::processAxis(Qt::KeyboardModifiers mods, PointerAxisDirection axis) +bool GlobalShortcutsManager::processAxis(Qt::KeyboardModifiers mods, PointerAxisDirection axis, qreal delta) { #if KWIN_BUILD_GLOBALSHORTCUTS // currently only used to better support modifier only shortcuts @@ -281,7 +284,11 @@ bool GlobalShortcutsManager::processAxis(Qt::KeyboardModifiers mods, PointerAxis Q_ARG(int, axis)); } #endif - return match(m_shortcuts, mods, axis); + GlobalShortcut *shortcut = match(m_shortcuts, mods, axis); + if (shortcut && std::abs(delta) >= 1.0f) { + shortcut->invoke(); + } + return shortcut != nullptr; } void GlobalShortcutsManager::processSwipeStart(DeviceType device, uint fingerCount) diff --git a/src/globalshortcuts.h b/src/globalshortcuts.h index 13c4239cae..4a2748cf39 100644 --- a/src/globalshortcuts.h +++ b/src/globalshortcuts.h @@ -98,7 +98,7 @@ public: * @param axis The axis direction which has triggered this event * @return @c true if a shortcut triggered, @c false otherwise */ - bool processAxis(Qt::KeyboardModifiers modifiers, PointerAxisDirection axis); + bool processAxis(Qt::KeyboardModifiers modifiers, PointerAxisDirection axis, qreal delta); void processSwipeStart(DeviceType device, uint fingerCount); void processSwipeUpdate(DeviceType device, const QPointF &delta); diff --git a/src/input.cpp b/src/input.cpp index 52dd7be865..4bc5b7f719 100644 --- a/src/input.cpp +++ b/src/input.cpp @@ -976,6 +976,29 @@ private: QMap m_touchPoints; }; +class MouseWheelAccumulator +{ +public: + qreal accumulate(PointerAxisEvent *event) + { + const qreal delta = event->deltaV120 != 0 ? event->deltaV120 / 120.0 : event->delta / 15.0; + if (std::signbit(m_scrollDistance) != std::signbit(delta)) { + m_scrollDistance = 0; + } + m_scrollDistance += delta; + if (std::abs(m_scrollDistance) >= 1.0) { + const qreal ret = m_scrollDistance; + m_scrollDistance = std::fmod(m_scrollDistance, 1.0f); + return ret - m_scrollDistance; + } else { + return 0; + } + } + +private: + qreal m_scrollDistance = 0; +}; + #if KWIN_BUILD_GLOBALSHORTCUTS class GlobalShortcutFilter : public InputEventFilter { @@ -1008,15 +1031,15 @@ public: } else if (event->delta > 0) { direction = PointerAxisLeft; } + return input()->shortcuts()->processAxis(event->modifiers, direction, m_horizontalAccumulator.accumulate(event)); } else { if (event->delta < 0) { direction = PointerAxisDown; } else if (event->delta > 0) { direction = PointerAxisUp; } + return input()->shortcuts()->processAxis(event->modifiers, direction, m_verticalAccumulator.accumulate(event)); } - - return input()->shortcuts()->processAxis(event->modifiers, direction); } bool keyboardKey(KeyboardKeyEvent *event) override { @@ -1229,6 +1252,8 @@ private: QPointF m_lastAverageDistance; QMap m_touchPoints; int m_touchpadGestureFingerCount = 0; + MouseWheelAccumulator m_horizontalAccumulator; + MouseWheelAccumulator m_verticalAccumulator; QTimer m_powerDown; }; @@ -1515,28 +1540,6 @@ private: QList m_touchPoints; }; -class MouseWheelAccumulator -{ -public: - float accumulate(PointerAxisEvent *event) - { - m_scrollV120 += event->deltaV120; - m_scrollDistance += event->delta; - if (std::abs(m_scrollV120) >= 120 || (!event->deltaV120 && std::abs(m_scrollDistance) >= 15)) { - float ret = m_scrollDistance; - m_scrollV120 = 0; - m_scrollDistance = 0; - return ret; - } else { - return 0; - } - } - -private: - float m_scrollDistance = 0; - int m_scrollV120 = 0; -}; - class DecorationEventFilter : public InputEventFilter { public: