Add WheelHandler to the Search result list too
authorCarl Schwan <carl@carlschwan.eu>
Fri, 12 Nov 2021 20:02:58 +0000 (21:02 +0100)
committerMatthieu Gallien (Rebase PR Action) <matthieu_gallien@yahoo.fr>
Mon, 22 Nov 2021 11:18:18 +0000 (11:18 +0000)
Signed-off-by: Carl Schwan <carl@carlschwan.eu>
src/3rdparty/kirigami/wheelhandler.cpp [new file with mode: 0644]
src/3rdparty/kirigami/wheelhandler.h [new file with mode: 0644]
src/gui/CMakeLists.txt
src/gui/systray.cpp
src/gui/tray/ActivityList.qml
src/gui/tray/Window.qml
src/gui/tray/wheelhandler.cpp [deleted file]
src/gui/tray/wheelhandler.h [deleted file]

diff --git a/src/3rdparty/kirigami/wheelhandler.cpp b/src/3rdparty/kirigami/wheelhandler.cpp
new file mode 100644 (file)
index 0000000..ce21e51
--- /dev/null
@@ -0,0 +1,280 @@
+/*
+ *  SPDX-FileCopyrightText: 2019 Marco Martin <mart@kde.org>
+ *
+ *  SPDX-License-Identifier: LGPL-2.0-or-later
+ */
+
+#include "wheelhandler.h"
+#include <QWheelEvent>
+#include <QQuickItem>
+#include <QDebug>
+
+class GlobalWheelFilterSingleton
+{
+public:
+    GlobalWheelFilter self;
+};
+
+Q_GLOBAL_STATIC(GlobalWheelFilterSingleton, privateGlobalWheelFilterSelf)
+
+GlobalWheelFilter::GlobalWheelFilter(QObject *parent)
+    : QObject(parent)
+{
+}
+
+GlobalWheelFilter::~GlobalWheelFilter() = default;
+
+GlobalWheelFilter *GlobalWheelFilter::self()
+{
+    return &privateGlobalWheelFilterSelf()->self;
+}
+
+void GlobalWheelFilter::setItemHandlerAssociation(QQuickItem *item, WheelHandler *handler)
+{
+    if (!m_handlersForItem.contains(handler->target())) {
+        handler->target()->installEventFilter(this);
+    }
+    m_handlersForItem.insert(item, handler);
+
+    connect(item, &QObject::destroyed, this, [this](QObject *obj) {
+        auto item = static_cast<QQuickItem *>(obj);
+        m_handlersForItem.remove(item);
+    });
+
+    connect(handler, &QObject::destroyed, this, [this](QObject *obj) {
+        auto handler = static_cast<WheelHandler *>(obj);
+        removeItemHandlerAssociation(handler->target(), handler);
+    });
+}
+
+void GlobalWheelFilter::removeItemHandlerAssociation(QQuickItem *item, WheelHandler *handler)
+{
+    if (!item || !handler) {
+        return;
+    }
+    m_handlersForItem.remove(item, handler);
+    if (!m_handlersForItem.contains(item)) {
+        item->removeEventFilter(this);
+    }
+}
+
+bool GlobalWheelFilter::eventFilter(QObject *watched, QEvent *event)
+{
+    if (event->type() == QEvent::Wheel) {
+        auto item = qobject_cast<QQuickItem *>(watched);
+        if (!item || !item->isEnabled()) {
+            return QObject::eventFilter(watched, event);
+        }
+        auto we = static_cast<QWheelEvent *>(event);
+        m_wheelEvent.initializeFromEvent(we);
+
+        bool shouldBlock = false;
+        bool shouldScrollFlickable = false;
+
+        for (auto *handler : m_handlersForItem.values(item)) {
+            if (handler->m_blockTargetWheel) {
+                shouldBlock = true;
+            }
+            if (handler->m_scrollFlickableTarget) {
+                shouldScrollFlickable = true;
+            }
+            emit handler->wheel(&m_wheelEvent);
+        }
+
+        if (shouldScrollFlickable && !m_wheelEvent.isAccepted()) {
+            manageWheel(item, we);
+        }
+
+        if (shouldBlock) {
+            return true;
+        }
+    }
+    return QObject::eventFilter(watched, event);
+}
+
+void GlobalWheelFilter::manageWheel(QQuickItem *target, QWheelEvent *event)
+{
+    // Duck typing: accept everyhint that has all the properties we need
+    if (target->metaObject()->indexOfProperty("contentX") == -1
+        || target->metaObject()->indexOfProperty("contentY") == -1
+        || target->metaObject()->indexOfProperty("contentWidth") == -1
+        || target->metaObject()->indexOfProperty("contentHeight") == -1
+        || target->metaObject()->indexOfProperty("topMargin") == -1
+        || target->metaObject()->indexOfProperty("bottomMargin") == -1
+        || target->metaObject()->indexOfProperty("leftMargin") == -1
+        || target->metaObject()->indexOfProperty("rightMargin") == -1
+        || target->metaObject()->indexOfProperty("originX") == -1
+        || target->metaObject()->indexOfProperty("originY") == -1) {
+        return;
+    }
+
+    qreal contentWidth = target->property("contentWidth").toReal();
+    qreal contentHeight = target->property("contentHeight").toReal();
+    qreal contentX = target->property("contentX").toReal();
+    qreal contentY = target->property("contentY").toReal();
+    qreal topMargin = target->property("topMargin").toReal();
+    qreal bottomMargin = target->property("bottomMargin").toReal();
+    qreal leftMargin = target->property("leftMaring").toReal();
+    qreal rightMargin = target->property("rightMargin").toReal();
+    qreal originX = target->property("originX").toReal();
+    qreal originY = target->property("originY").toReal();
+
+    // Scroll Y
+    if (contentHeight > target->height()) {
+
+        int y = event->pixelDelta().y() != 0 ? event->pixelDelta().y() : event->angleDelta().y() / 8;
+
+        //if we don't have a pixeldelta, apply the configured mouse wheel lines
+        if (!event->pixelDelta().y()) {
+            y *= 3; // Magic copied value from Kirigami::Settings
+        }
+
+        // Scroll one page regardless of delta:
+        if ((event->modifiers() & Qt::ControlModifier) || (event->modifiers() & Qt::ShiftModifier)) {
+            if (y > 0) {
+                y = target->height();
+            } else if (y < 0) {
+                y = -target->height();
+            }
+        }
+
+        qreal minYExtent = topMargin - originY;
+        qreal maxYExtent = target->height() - (contentHeight + bottomMargin + originY);
+
+        target->setProperty("contentY", qMin(-maxYExtent, qMax(-minYExtent, contentY - y)));
+    }
+
+    //Scroll X
+    if (contentWidth > target->width()) {
+
+        int x = event->pixelDelta().x() != 0 ? event->pixelDelta().x() : event->angleDelta().x() / 8;
+
+        // Special case: when can't scroll vertically, scroll horizontally with vertical wheel as well
+        if (x == 0 && contentHeight <= target->height()) {
+            x = event->pixelDelta().y() != 0 ? event->pixelDelta().y() : event->angleDelta().y() / 8;
+        }
+
+        //if we don't have a pixeldelta, apply the configured mouse wheel lines
+        if (!event->pixelDelta().x()) {
+            x *= 3; // Magic copied value from Kirigami::Settings
+        }
+
+        // Scroll one page regardless of delta:
+        if ((event->modifiers() & Qt::ControlModifier) || (event->modifiers() & Qt::ShiftModifier)) {
+            if (x > 0) {
+                x = target->width();
+            } else if (x < 0) {
+                x = -target->width();
+            }
+        }
+
+        qreal minXExtent = leftMargin - originX;
+        qreal maxXExtent = target->width() - (contentWidth + rightMargin + originX);
+
+        target->setProperty("contentX", qMin(-maxXExtent, qMax(-minXExtent, contentX - x)));
+    }
+
+    //this is just for making the scrollbar
+    target->metaObject()->invokeMethod(target, "flick", Q_ARG(double, 0), Q_ARG(double, 1));
+    target->metaObject()->invokeMethod(target, "cancelFlick");
+}
+
+
+////////////////////////////
+KirigamiWheelEvent::KirigamiWheelEvent(QObject *parent)
+    : QObject(parent)
+{}
+
+KirigamiWheelEvent::~KirigamiWheelEvent() = default;
+
+void KirigamiWheelEvent::initializeFromEvent(QWheelEvent *event)
+{
+    m_x = event->position().x();
+    m_y = event->position().y();
+    m_angleDelta = event->angleDelta();
+    m_pixelDelta = event->pixelDelta();
+    m_buttons = event->buttons();
+    m_modifiers = event->modifiers();
+    m_accepted = false;
+    m_inverted = event->inverted();
+}
+
+qreal KirigamiWheelEvent::x() const
+{
+    return m_x;
+}
+
+qreal KirigamiWheelEvent::y() const
+{
+    return m_y;
+}
+
+QPointF KirigamiWheelEvent::angleDelta() const
+{
+    return m_angleDelta;
+}
+
+QPointF KirigamiWheelEvent::pixelDelta() const
+{
+    return m_pixelDelta;
+}
+
+int KirigamiWheelEvent::buttons() const
+{
+    return m_buttons;
+}
+
+int KirigamiWheelEvent::modifiers() const
+{
+    return m_modifiers;
+}
+
+bool KirigamiWheelEvent::inverted() const
+{
+    return m_inverted;
+}
+
+bool KirigamiWheelEvent::isAccepted()
+{
+    return m_accepted;
+}
+
+void KirigamiWheelEvent::setAccepted(bool accepted)
+{
+    m_accepted = accepted;
+}
+
+
+///////////////////////////////
+
+WheelHandler::WheelHandler(QObject *parent)
+    : QObject(parent)
+{
+}
+
+WheelHandler::~WheelHandler() = default;
+
+QQuickItem *WheelHandler::target() const
+{
+    return m_target;
+}
+
+void WheelHandler::setTarget(QQuickItem *target)
+{
+    if (m_target == target) {
+        return;
+    }
+
+    if (m_target) {
+        GlobalWheelFilter::self()->removeItemHandlerAssociation(m_target, this);
+    }
+
+    m_target = target;
+
+    GlobalWheelFilter::self()->setItemHandlerAssociation(target, this);
+
+    emit targetChanged();
+}
+
+
+#include "moc_wheelhandler.cpp"
diff --git a/src/3rdparty/kirigami/wheelhandler.h b/src/3rdparty/kirigami/wheelhandler.h
new file mode 100644 (file)
index 0000000..1148694
--- /dev/null
@@ -0,0 +1,213 @@
+/*
+ *  SPDX-FileCopyrightText: 2019 Marco Martin <mart@kde.org>
+ *
+ *  SPDX-License-Identifier: LGPL-2.0-or-later
+ */
+
+#pragma once
+
+#include <QtQml>
+#include <QPoint>
+#include <QQuickItem>
+#include <QObject>
+
+class QWheelEvent;
+
+class WheelHandler;
+
+/**
+ * Describes the mouse wheel event
+ */
+class KirigamiWheelEvent : public QObject
+{
+    Q_OBJECT
+
+    /**
+     * x: real
+     *
+     * X coordinate of the mouse pointer
+     */
+    Q_PROPERTY(qreal x READ x CONSTANT)
+
+    /**
+     * y: real
+     *
+     * Y coordinate of the mouse pointer
+     */
+    Q_PROPERTY(qreal y READ y CONSTANT)
+
+    /**
+     * angleDelta: point
+     *
+     * The distance the wheel is rotated in degrees.
+     * The x and y coordinates indicate the horizontal and vertical wheels respectively.
+     * A positive value indicates it was rotated up/right, negative, bottom/left
+     * This value is more likely to be set in traditional mice.
+     */
+    Q_PROPERTY(QPointF angleDelta READ angleDelta CONSTANT)
+
+    /**
+     * pixelDelta: point
+     *
+     * provides the delta in screen pixels available on high resolution trackpads
+     */
+    Q_PROPERTY(QPointF pixelDelta READ pixelDelta CONSTANT)
+
+    /**
+     * buttons: int
+     *
+     * it contains an OR combination of the buttons that were pressed during the wheel, they can be:
+     * Qt.LeftButton, Qt.MiddleButton, Qt.RightButton
+     */
+    Q_PROPERTY(int buttons READ buttons CONSTANT)
+
+    /**
+     * modifiers: int
+     *
+     * Keyboard mobifiers that were pressed during the wheel event, such as:
+     * Qt.NoModifier (default, no modifiers)
+     * Qt.ControlModifier
+     * Qt.ShiftModifier
+     * ...
+     */
+    Q_PROPERTY(int modifiers READ modifiers CONSTANT)
+
+    /**
+     * inverted: bool
+     *
+     * Whether the delta values are inverted
+     * On some platformsthe returned delta are inverted, so positive values would mean bottom/left
+     */
+    Q_PROPERTY(bool inverted READ inverted CONSTANT)
+
+    /**
+     * accepted: bool
+     *
+     * If set, the event shouldn't be managed anymore,
+     * for instance it can be used to block the handler to manage the scroll of a view on some scenarios
+     * @code
+     * // This handler handles automatically the scroll of
+     * // flickableItem, unless Ctrl is pressed, in this case the
+     * // app has custom code to handle Ctrl+wheel zooming
+     * Kirigami.WheelHandler {
+     *   target: flickableItem
+     *   blockTargetWheel: true
+     *   scrollFlickableTarget: true
+     *   onWheel: {
+     *        if (wheel.modifiers & Qt.ControlModifier) {
+     *            wheel.accepted = true;
+     *            // Handle scaling of the view
+     *       }
+     *   }
+     * }
+     * @endcode
+     *
+     */
+    Q_PROPERTY(bool accepted READ isAccepted WRITE setAccepted)
+
+public:
+    KirigamiWheelEvent(QObject *parent = nullptr);
+    ~KirigamiWheelEvent() override;
+
+    void initializeFromEvent(QWheelEvent *event);
+
+    qreal x() const;
+    qreal y() const;
+    QPointF angleDelta() const;
+    QPointF pixelDelta() const;
+    int buttons() const;
+    int modifiers() const;
+    bool inverted() const;
+    bool isAccepted();
+    void setAccepted(bool accepted);
+
+private:
+    qreal m_x = 0;
+    qreal m_y = 0;
+    QPointF m_angleDelta;
+    QPointF m_pixelDelta;
+    Qt::MouseButtons m_buttons = Qt::NoButton;
+    Qt::KeyboardModifiers m_modifiers = Qt::NoModifier;
+    bool m_inverted = false;
+    bool m_accepted = false;
+};
+
+class GlobalWheelFilter : public QObject
+{
+    Q_OBJECT
+
+public:
+    GlobalWheelFilter(QObject *parent = nullptr);
+    ~GlobalWheelFilter() override;
+
+    static GlobalWheelFilter *self();
+
+    void setItemHandlerAssociation(QQuickItem *item, WheelHandler *handler);
+    void removeItemHandlerAssociation(QQuickItem *item, WheelHandler *handler);
+
+protected:
+    bool eventFilter(QObject *watched, QEvent *event) override;
+
+private:
+    void manageWheel(QQuickItem *target, QWheelEvent *wheel);
+
+    QMultiHash<QQuickItem *, WheelHandler *> m_handlersForItem;
+    KirigamiWheelEvent m_wheelEvent;
+};
+
+
+
+/**
+ * This class intercepts the mouse wheel events of its target, and gives them to the user code as a signal, which can be used for custom mouse wheel management code.
+ * The handler can block completely the wheel events from its target, and if it's a Flickable, it can automatically handle scrolling on it
+ */
+class WheelHandler : public QObject
+{
+    Q_OBJECT
+
+    /**
+     * target: Item
+     *
+     * The target we want to manage wheel events.
+     * We will receive wheel() signals every time the user moves
+     * the mouse wheel (or scrolls with the touchpad) on top
+     * of that item.
+     */
+    Q_PROPERTY(QQuickItem *target READ target WRITE setTarget NOTIFY targetChanged)
+
+    /**
+     * blockTargetWheel: bool
+     *
+     * If true, the target won't receive any wheel event at all (default true)
+     */
+    Q_PROPERTY(bool blockTargetWheel MEMBER m_blockTargetWheel NOTIFY blockTargetWheelChanged)
+
+    /**
+     * scrollFlickableTarget: bool
+     * If this property is true and the target is a Flickable, wheel events will cause the Flickable to scroll (default true)
+     */
+    Q_PROPERTY(bool scrollFlickableTarget MEMBER m_scrollFlickableTarget NOTIFY scrollFlickableTargetChanged)
+
+public:
+    explicit WheelHandler(QObject *parent = nullptr);
+    ~WheelHandler() override;
+
+    QQuickItem *target() const;
+    void setTarget(QQuickItem *target);
+
+Q_SIGNALS:
+    void targetChanged();
+    void blockTargetWheelChanged();
+    void scrollFlickableTargetChanged();
+    void wheel(KirigamiWheelEvent *wheel);
+
+private:
+    QPointer<QQuickItem> m_target;
+    bool m_blockTargetWheel = true;
+    bool m_scrollFlickableTarget = true;
+    KirigamiWheelEvent m_wheelEvent;
+
+    friend class GlobalWheelFilter;
+};
+
+
index cc65cd6ffe2ba39fa51010849bece04ff212bdd1..794f44f275bfa553789d904d2691c2d956433a65 100644 (file)
@@ -134,7 +134,6 @@ set(client_SRCS
     tray/usermodel.cpp
     tray/notificationhandler.cpp
     tray/notificationcache.cpp
-    tray/wheelhandler.cpp
     creds/credentialsfactory.cpp
     creds/httpcredentialsgui.cpp
     creds/oauth.cpp
@@ -207,6 +206,7 @@ set(3rdparty_SRC
     ../3rdparty/qtsingleapplication/qtsingleapplication.cpp
     ../3rdparty/qtsingleapplication/qtsinglecoreapplication.cpp
     ../3rdparty/kmessagewidget/kmessagewidget.cpp
+    ../3rdparty/kirigami/wheelhandler.cpp
    )
 
 if(NOT WIN32)
@@ -376,6 +376,7 @@ target_include_directories(nextcloudCore
   PUBLIC
   ${CMAKE_SOURCE_DIR}/src/3rdparty/QProgressIndicator
   ${CMAKE_SOURCE_DIR}/src/3rdparty/qtlockedfile
+  ${CMAKE_SOURCE_DIR}/src/3rdparty/kirigami
   ${CMAKE_SOURCE_DIR}/src/3rdparty/qtsingleapplication
   ${CMAKE_SOURCE_DIR}/src/3rdparty/kmessagewidget
   ${CMAKE_CURRENT_BINARY_DIR}
index 4158809de9cd26a3278b562c08e05b2d2c33b669..47536748694824398e065e0d95e2860c8625e6f3 100644 (file)
@@ -19,7 +19,7 @@
 #include "common/utility.h"
 #include "tray/svgimageprovider.h"
 #include "tray/usermodel.h"
-#include "tray/wheelhandler.h"
+#include "wheelhandler.h"
 #include "tray/unifiedsearchresultimageprovider.h"
 #include "configfile.h"
 
index 795b3dc7786736d19f9f4c7c0451fb04dd236990..e1ab4f81832238f9c7795a0576dd9524fed1c461 100644 (file)
@@ -13,6 +13,7 @@ ScrollView {
     signal activityItemClicked(int index)
 
     contentWidth: availableWidth
+    padding: 1
 
     ScrollBar.horizontal.policy: ScrollBar.AlwaysOff
 
index 96528a61f0d4ba8510c69e87152374c362b9642e..631097879721d39f8c94a9ad94fd47353512b7aa 100644 (file)
@@ -651,51 +651,61 @@ Window {
             iconColor: "#afafaf"\r
         }\r
 \r
-        ListView {\r
-            id: unifiedSearchResultsListView\r
+        ScrollView {\r
+            id: controlRoot\r
+            padding: 1\r
+            contentWidth: availableWidth\r
+\r
+            ScrollBar.horizontal.policy: ScrollBar.AlwaysOff\r
+\r
+            data: WheelHandler {\r
+                target: controlRoot.contentItem\r
+            }\r
+            visible: unifiedSearchResultsListView.count > 0\r
+\r
             anchors.top: trayWindowUnifiedSearchInputContainer.bottom\r
             anchors.left: trayWindowBackground.left\r
             anchors.right: trayWindowBackground.right\r
             anchors.bottom: trayWindowBackground.bottom\r
-            spacing: 4\r
-            visible: count > 0\r
-            clip: true\r
-            ScrollBar.vertical: ScrollBar {\r
-                id: unifiedSearchResultsListViewScrollbar\r
-            }\r
 \r
-            keyNavigationEnabled: true\r
-\r
-            reuseItems: true\r
-\r
-            Accessible.role: Accessible.List\r
-            Accessible.name: qsTr("Unified search results list")\r
-\r
-            model: UserModel.currentUser.unifiedSearchResultsListModel\r
-\r
-            delegate: UnifiedSearchResultListItem {\r
-                width: unifiedSearchResultsListView.width\r
-                height: trayWindowBackground.Style.unifiedSearchItemHeight\r
-                isSearchInProgress:  unifiedSearchResultsListView.model.isSearchInProgress\r
-                textLeftMargin: trayWindowBackground.Style.unifiedSearchResultTextLeftMargin\r
-                textRightMargin: trayWindowBackground.Style.unifiedSearchResultTextRightMargin\r
-                iconWidth: trayWindowBackground.Style.unifiedSearchResulIconWidth\r
-                iconLeftMargin: trayWindowBackground.Style.unifiedSearchResulIconLeftMargin\r
-                titleFontSize: trayWindowBackground.Style.unifiedSearchResulTitleFontSize\r
-                sublineFontSize: trayWindowBackground.Style.unifiedSearchResulSublineFontSize\r
-                titleColor: trayWindowBackground.Style.unifiedSearchResulTitleColor\r
-                sublineColor: trayWindowBackground.Style.unifiedSearchResulSublineColor\r
-                currentFetchMoreInProgressProviderId: unifiedSearchResultsListView.model.currentFetchMoreInProgressProviderId\r
-                fetchMoreTriggerClicked: unifiedSearchResultsListView.model.fetchMoreTriggerClicked\r
-                resultClicked: unifiedSearchResultsListView.model.resultClicked\r
-                ListView.onPooled: isPooled = true\r
-                ListView.onReused: isPooled = false\r
-            }\r
+            ListView {\r
+                id: unifiedSearchResultsListView\r
+                spacing: 4\r
+                clip: true\r
+\r
+                keyNavigationEnabled: true\r
+\r
+                reuseItems: true\r
+\r
+                Accessible.role: Accessible.List\r
+                Accessible.name: qsTr("Unified search results list")\r
+\r
+                model: UserModel.currentUser.unifiedSearchResultsListModel\r
+\r
+                delegate: UnifiedSearchResultListItem {\r
+                    width: unifiedSearchResultsListView.width\r
+                    height: trayWindowBackground.Style.unifiedSearchItemHeight\r
+                    isSearchInProgress:  unifiedSearchResultsListView.model.isSearchInProgress\r
+                    textLeftMargin: trayWindowBackground.Style.unifiedSearchResultTextLeftMargin\r
+                    textRightMargin: trayWindowBackground.Style.unifiedSearchResultTextRightMargin\r
+                    iconWidth: trayWindowBackground.Style.unifiedSearchResulIconWidth\r
+                    iconLeftMargin: trayWindowBackground.Style.unifiedSearchResulIconLeftMargin\r
+                    titleFontSize: trayWindowBackground.Style.unifiedSearchResulTitleFontSize\r
+                    sublineFontSize: trayWindowBackground.Style.unifiedSearchResulSublineFontSize\r
+                    titleColor: trayWindowBackground.Style.unifiedSearchResulTitleColor\r
+                    sublineColor: trayWindowBackground.Style.unifiedSearchResulSublineColor\r
+                    currentFetchMoreInProgressProviderId: unifiedSearchResultsListView.model.currentFetchMoreInProgressProviderId\r
+                    fetchMoreTriggerClicked: unifiedSearchResultsListView.model.fetchMoreTriggerClicked\r
+                    resultClicked: unifiedSearchResultsListView.model.resultClicked\r
+                    ListView.onPooled: isPooled = true\r
+                    ListView.onReused: isPooled = false\r
+                }\r
 \r
-            section.property: "providerName"\r
-            section.criteria: ViewSection.FullString\r
-            section.delegate: UnifiedSearchResultSectionItem {\r
-                width: unifiedSearchResultsListView.width\r
+                section.property: "providerName"\r
+                section.criteria: ViewSection.FullString\r
+                section.delegate: UnifiedSearchResultSectionItem {\r
+                    width: unifiedSearchResultsListView.width\r
+                }\r
             }\r
         }\r
 \r
diff --git a/src/gui/tray/wheelhandler.cpp b/src/gui/tray/wheelhandler.cpp
deleted file mode 100644 (file)
index 1e60e5f..0000000
+++ /dev/null
@@ -1,289 +0,0 @@
-/*
- *  SPDX-FileCopyrightText: 2019 Marco Martin <mart@kde.org>
- *
- *  SPDX-License-Identifier: LGPL-2.0-or-later
- */
-
-#include "wheelhandler.h"
-#include <QWheelEvent>
-#include <QQuickItem>
-#include <QDebug>
-
-class GlobalWheelFilterSingleton
-{
-public:
-    GlobalWheelFilter self;
-};
-
-Q_GLOBAL_STATIC(GlobalWheelFilterSingleton, privateGlobalWheelFilterSelf)
-
-GlobalWheelFilter::GlobalWheelFilter(QObject *parent)
-    : QObject(parent)
-{
-}
-
-GlobalWheelFilter::~GlobalWheelFilter()
-{}
-
-GlobalWheelFilter *GlobalWheelFilter::self()
-{
-    return &privateGlobalWheelFilterSelf()->self;
-}
-
-void GlobalWheelFilter::setItemHandlerAssociation(QQuickItem *item, WheelHandler *handler)
-{
-    if (!m_handlersForItem.contains(handler->target())) {
-        handler->target()->installEventFilter(this);
-    }
-    m_handlersForItem.insert(item, handler);
-
-    connect(item, &QObject::destroyed, this, [this](QObject *obj) {
-        QQuickItem *item = static_cast<QQuickItem *>(obj);
-        m_handlersForItem.remove(item);
-    });
-
-    connect(handler, &QObject::destroyed, this, [this](QObject *obj) {
-        WheelHandler *handler = static_cast<WheelHandler *>(obj);
-        removeItemHandlerAssociation(handler->target(), handler);
-    });
-}
-
-void GlobalWheelFilter::removeItemHandlerAssociation(QQuickItem *item, WheelHandler *handler)
-{
-    if (!item || !handler) {
-        return;
-    }
-    m_handlersForItem.remove(item, handler);
-    if (!m_handlersForItem.contains(item)) {
-        item->removeEventFilter(this);
-    }
-}
-
-bool GlobalWheelFilter::eventFilter(QObject *watched, QEvent *event)
-{
-    if (event->type() == QEvent::Wheel) {
-        QQuickItem *item = qobject_cast<QQuickItem *>(watched);
-        if (!item || !item->isEnabled()) {
-            return QObject::eventFilter(watched, event);
-        }
-        QWheelEvent *we = static_cast<QWheelEvent *>(event);
-        m_wheelEvent.initializeFromEvent(we);
-
-        bool shouldBlock = false;
-        bool shouldScrollFlickable = false;
-
-        for (auto *handler : m_handlersForItem.values(item)) {
-            if (handler->m_blockTargetWheel) {
-                shouldBlock = true;
-            }
-            if (handler->m_scrollFlickableTarget) {
-                shouldScrollFlickable = true;
-            }
-            emit handler->wheel(&m_wheelEvent);
-        }
-
-        if (shouldScrollFlickable && !m_wheelEvent.isAccepted()) {
-            manageWheel(item, we);
-        }
-
-        if (shouldBlock) {
-            return true;
-        }
-    }
-    return QObject::eventFilter(watched, event);
-}
-
-void GlobalWheelFilter::manageWheel(QQuickItem *target, QWheelEvent *event)
-{
-    // Duck typing: accept everyhint that has all the properties we need
-    if (target->metaObject()->indexOfProperty("contentX") == -1
-        || target->metaObject()->indexOfProperty("contentY") == -1
-        || target->metaObject()->indexOfProperty("contentWidth") == -1
-        || target->metaObject()->indexOfProperty("contentHeight") == -1
-        || target->metaObject()->indexOfProperty("topMargin") == -1
-        || target->metaObject()->indexOfProperty("bottomMargin") == -1
-        || target->metaObject()->indexOfProperty("leftMargin") == -1
-        || target->metaObject()->indexOfProperty("rightMargin") == -1
-        || target->metaObject()->indexOfProperty("originX") == -1
-        || target->metaObject()->indexOfProperty("originY") == -1) {
-        return;
-    }
-
-    qreal contentWidth = target->property("contentWidth").toReal();
-    qreal contentHeight = target->property("contentHeight").toReal();
-    qreal contentX = target->property("contentX").toReal();
-    qreal contentY = target->property("contentY").toReal();
-    qreal topMargin = target->property("topMargin").toReal();
-    qreal bottomMargin = target->property("bottomMargin").toReal();
-    qreal leftMargin = target->property("leftMaring").toReal();
-    qreal rightMargin = target->property("rightMargin").toReal();
-    qreal originX = target->property("originX").toReal();
-    qreal originY = target->property("originY").toReal();
-
-    // Scroll Y
-    if (contentHeight > target->height()) {
-
-        int y = event->pixelDelta().y() != 0 ? event->pixelDelta().y() : event->angleDelta().y() / 8;
-
-        //if we don't have a pixeldelta, apply the configured mouse wheel lines
-        if (!event->pixelDelta().y()) {
-            y *= 3; // Magic copied value from Kirigami::Settings
-        }
-
-        // Scroll one page regardless of delta:
-        if ((event->modifiers() & Qt::ControlModifier) || (event->modifiers() & Qt::ShiftModifier)) {
-            if (y > 0) {
-                y = target->height();
-            } else if (y < 0) {
-                y = -target->height();
-            }
-        }
-
-        qreal minYExtent = topMargin - originY;
-        qreal maxYExtent = target->height() - (contentHeight + bottomMargin + originY);
-
-        target->setProperty("contentY", qMin(-maxYExtent, qMax(-minYExtent, contentY - y)));
-    }
-
-    //Scroll X
-    if (contentWidth > target->width()) {
-
-        int x = event->pixelDelta().x() != 0 ? event->pixelDelta().x() : event->angleDelta().x() / 8;
-
-        // Special case: when can't scroll vertically, scroll horizontally with vertical wheel as well
-        if (x == 0 && contentHeight <= target->height()) {
-            x = event->pixelDelta().y() != 0 ? event->pixelDelta().y() : event->angleDelta().y() / 8;
-        }
-
-        //if we don't have a pixeldelta, apply the configured mouse wheel lines
-        if (!event->pixelDelta().x()) {
-            x *= 3; // Magic copied value from Kirigami::Settings
-        }
-
-        // Scroll one page regardless of delta:
-        if ((event->modifiers() & Qt::ControlModifier) || (event->modifiers() & Qt::ShiftModifier)) {
-            if (x > 0) {
-                x = target->width();
-            } else if (x < 0) {
-                x = -target->width();
-            }
-        }
-
-        qreal minXExtent = leftMargin - originX;
-        qreal maxXExtent = target->width() - (contentWidth + rightMargin + originX);
-
-        target->setProperty("contentX", qMin(-maxXExtent, qMax(-minXExtent, contentX - x)));
-    }
-
-    //this is just for making the scrollbar
-    target->metaObject()->invokeMethod(target, "flick", Q_ARG(double, 0), Q_ARG(double, 1));
-    target->metaObject()->invokeMethod(target, "cancelFlick");
-}
-
-
-////////////////////////////
-KirigamiWheelEvent::KirigamiWheelEvent(QObject *parent)
-    : QObject(parent)
-{}
-
-KirigamiWheelEvent::~KirigamiWheelEvent()
-{}
-
-void KirigamiWheelEvent::initializeFromEvent(QWheelEvent *event)
-{
-#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
-    m_x = event->position().x();
-    m_y = event->position().y();
-#else
-    m_x = event->x();
-    m_y = event->y();
-#endif
-    m_angleDelta = event->angleDelta();
-    m_pixelDelta = event->pixelDelta();
-    m_buttons = event->buttons();
-    m_modifiers = event->modifiers();
-    m_accepted = false;
-    m_inverted = event->inverted();
-}
-
-qreal KirigamiWheelEvent::x() const
-{
-    return m_x;
-}
-
-qreal KirigamiWheelEvent::y() const
-{
-    return m_y;
-}
-
-QPointF KirigamiWheelEvent::angleDelta() const
-{
-    return m_angleDelta;
-}
-
-QPointF KirigamiWheelEvent::pixelDelta() const
-{
-    return m_pixelDelta;
-}
-
-int KirigamiWheelEvent::buttons() const
-{
-    return m_buttons;
-}
-
-int KirigamiWheelEvent::modifiers() const
-{
-    return m_modifiers;
-}
-
-bool KirigamiWheelEvent::inverted() const
-{
-    return m_inverted;
-}
-
-bool KirigamiWheelEvent::isAccepted()
-{
-    return m_accepted;
-}
-
-void KirigamiWheelEvent::setAccepted(bool accepted)
-{
-    m_accepted = accepted;
-}
-
-
-///////////////////////////////
-
-WheelHandler::WheelHandler(QObject *parent)
-    : QObject(parent)
-{
-}
-
-WheelHandler::~WheelHandler()
-{
-}
-
-QQuickItem *WheelHandler::target() const
-{
-    return m_target;
-}
-
-void WheelHandler::setTarget(QQuickItem *target)
-{
-    if (m_target == target) {
-        return;
-    }
-
-    if (m_target) {
-        GlobalWheelFilter::self()->removeItemHandlerAssociation(m_target, this);
-    }
-
-    m_target = target;
-
-    GlobalWheelFilter::self()->setItemHandlerAssociation(target, this);
-
-    emit targetChanged();
-}
-
-
-#include "moc_wheelhandler.cpp"
diff --git a/src/gui/tray/wheelhandler.h b/src/gui/tray/wheelhandler.h
deleted file mode 100644 (file)
index 8e81f51..0000000
+++ /dev/null
@@ -1,213 +0,0 @@
-/*
- *  SPDX-FileCopyrightText: 2019 Marco Martin <mart@kde.org>
- *
- *  SPDX-License-Identifier: LGPL-2.0-or-later
- */
-
-#pragma once
-
-#include <QtQml>
-#include <QPoint>
-#include <QQuickItem>
-#include <QObject>
-
-class QWheelEvent;
-
-class WheelHandler;
-
-/**
- * Describes the mouse wheel event
- */
-class KirigamiWheelEvent : public QObject
-{
-    Q_OBJECT
-
-    /**
-     * x: real
-     *
-     * X coordinate of the mouse pointer
-     */
-    Q_PROPERTY(qreal x READ x CONSTANT)
-
-    /**
-     * y: real
-     *
-     * Y coordinate of the mouse pointer
-     */
-    Q_PROPERTY(qreal y READ y CONSTANT)
-
-    /**
-     * angleDelta: point
-     *
-     * The distance the wheel is rotated in degrees.
-     * The x and y coordinates indicate the horizontal and vertical wheels respectively.
-     * A positive value indicates it was rotated up/right, negative, bottom/left
-     * This value is more likely to be set in traditional mice.
-     */
-    Q_PROPERTY(QPointF angleDelta READ angleDelta CONSTANT)
-
-    /**
-     * pixelDelta: point
-     *
-     * provides the delta in screen pixels available on high resolution trackpads
-     */
-    Q_PROPERTY(QPointF pixelDelta READ pixelDelta CONSTANT)
-
-    /**
-     * buttons: int
-     *
-     * it contains an OR combination of the buttons that were pressed during the wheel, they can be:
-     * Qt.LeftButton, Qt.MiddleButton, Qt.RightButton
-     */
-    Q_PROPERTY(int buttons READ buttons CONSTANT)
-
-    /**
-     * modifiers: int
-     *
-     * Keyboard mobifiers that were pressed during the wheel event, such as:
-     * Qt.NoModifier (default, no modifiers)
-     * Qt.ControlModifier
-     * Qt.ShiftModifier
-     * ...
-     */
-    Q_PROPERTY(int modifiers READ modifiers CONSTANT)
-
-    /**
-     * inverted: bool
-     *
-     * Whether the delta values are inverted
-     * On some platformsthe returned delta are inverted, so positive values would mean bottom/left
-     */
-    Q_PROPERTY(bool inverted READ inverted CONSTANT)
-
-    /**
-     * accepted: bool
-     *
-     * If set, the event shouldn't be managed anymore,
-     * for instance it can be used to block the handler to manage the scroll of a view on some scenarions
-     * @code
-     * // This handler handles automatically the scroll of
-     * // flickableItem, unless Ctrl is pressed, in this case the
-     * // app has custom code to handle Ctrl+wheel zooming
-     * Kirigami.WheelHandler {
-     *   target: flickableItem
-     *   blockTargetWheel: true
-     *   scrollFlickableTarget: true
-     *   onWheel: {
-     *        if (wheel.modifiers & Qt.ControlModifier) {
-     *            wheel.accepted = true;
-     *            // Handle scaling of the view
-     *       }
-     *   }
-     * }
-     * @endcode
-     *
-     */
-    Q_PROPERTY(bool accepted READ isAccepted WRITE setAccepted)
-
-public:
-    KirigamiWheelEvent(QObject *parent = nullptr);
-    ~KirigamiWheelEvent();
-
-    void initializeFromEvent(QWheelEvent *event);
-
-    qreal x() const;
-    qreal y() const;
-    QPointF angleDelta() const;
-    QPointF pixelDelta() const;
-    int buttons() const;
-    int modifiers() const;
-    bool inverted() const;
-    bool isAccepted();
-    void setAccepted(bool accepted);
-
-private:
-    qreal m_x = 0;
-    qreal m_y = 0;
-    QPointF m_angleDelta;
-    QPointF m_pixelDelta;
-    Qt::MouseButtons m_buttons = Qt::NoButton;
-    Qt::KeyboardModifiers m_modifiers = Qt::NoModifier;
-    bool m_inverted = false;
-    bool m_accepted = false;
-};
-
-class GlobalWheelFilter : public QObject
-{
-    Q_OBJECT
-
-public:
-    GlobalWheelFilter(QObject *parent = nullptr);
-    ~GlobalWheelFilter();
-
-    static GlobalWheelFilter *self();
-
-    void setItemHandlerAssociation(QQuickItem *item, WheelHandler *handler);
-    void removeItemHandlerAssociation(QQuickItem *item, WheelHandler *handler);
-
-protected:
-    bool eventFilter(QObject *watched, QEvent *event) override;
-
-private:
-    void manageWheel(QQuickItem *target, QWheelEvent *wheel);
-
-    QMultiHash<QQuickItem *, WheelHandler *> m_handlersForItem;
-    KirigamiWheelEvent m_wheelEvent;
-};
-
-
-
-/**
- * This class intercepts the mouse wheel events of its target, and gives them to the user code as a signal, which can be used for custom mouse wheel management code.
- * The handler can block completely the wheel events from its target, and if it's a Flickable, it can automatically handle scrolling on it
- */
-class WheelHandler : public QObject
-{
-    Q_OBJECT
-
-    /**
-     * target: Item
-     *
-     * The target we want to manage wheel events.
-     * We will receive wheel() signals every time the user moves
-     * the mouse wheel (or scrolls with the touchpad) on top
-     * of that item.
-     */
-    Q_PROPERTY(QQuickItem *target READ target WRITE setTarget NOTIFY targetChanged)
-
-    /**
-     * blockTargetWheel: bool
-     *
-     * If true, the target won't receive any wheel event at all (default true)
-     */
-    Q_PROPERTY(bool blockTargetWheel MEMBER m_blockTargetWheel NOTIFY blockTargetWheelChanged)
-
-    /**
-     * scrollFlickableTarget: bool
-     * If this property is true and the target is a Flickable, wheel events will cause the Flickable to scroll (default true)
-     */
-    Q_PROPERTY(bool scrollFlickableTarget MEMBER m_scrollFlickableTarget NOTIFY scrollFlickableTargetChanged)
-
-public:
-    explicit WheelHandler(QObject *parent = nullptr);
-    ~WheelHandler() override;
-
-    QQuickItem *target() const;
-    void setTarget(QQuickItem *target);
-
-Q_SIGNALS:
-    void targetChanged();
-    void blockTargetWheelChanged();
-    void scrollFlickableTargetChanged();
-    void wheel(KirigamiWheelEvent *wheel);
-
-private:
-    QPointer<QQuickItem> m_target;
-    bool m_blockTargetWheel = true;
-    bool m_scrollFlickableTarget = true;
-    KirigamiWheelEvent m_wheelEvent;
-
-    friend class GlobalWheelFilter;
-};
-
-