File fix_scrolling.patch of Package nheko

From c9f1a449d825d5879735f95ebfb0c7acec101226 Mon Sep 17 00:00:00 2001
From: Reilly Brogan <reilly@reillybrogan.com>
Date: Wed, 12 Jun 2024 15:24:53 -0500
Subject: [PATCH] linux: Use kirigami mouse handling if available

Qt6 changed the mouse scroll wheel handling for QtQuick to a type that mimics how touch pads/screens work, which most people find feels very poor. KDE fixes this by creating a custom type which re-implements the QtWidgets handling (see https://invent.kde.org/frameworks/kirigami/-/merge_requests/415).

On Matrix Nico has expressed a desire not to have to deal with compiling Kirigami for Windows and Mac, which is understandable. Linux users on the other hand almost always have kirigami available in their package repos which sidesteps that particular issue. We can search for Kirigami at build time and if present define a QML context property to allow it to be used, which should fix this issue for Linux users at least.

Helps with nheko-reborn/nheko#1819 (which won't be completely resolved until this is working for Windows and Mac as well).

Signed-off-by: Reilly Brogan <reilly@reillybrogan.com>
---
 CMakeLists.txt                                | 24 ++++++++++++++++++-
 resources/qml/CommunitiesList.qml             |  4 ++++
 resources/qml/Completer.qml                   |  4 ++++
 resources/qml/MessageView.qml                 |  4 ++++
 resources/qml/RoomList.qml                    |  4 ++++
 resources/qml/UploadBox.qml                   |  4 ++++
 resources/qml/components/AdaptiveLayout.qml   |  4 ++++
 .../qml/components/KirigamiWheelHandler.qml   | 12 ++++++++++
 .../qml/components/ReorderableListview.qml    |  4 ++++
 resources/qml/dialogs/AliasEditor.qml         |  3 +++
 .../dialogs/AllowedRoomsSettingsDialog.qml    |  3 +++
 resources/qml/dialogs/IgnoredUsers.qml        |  4 ++++
 .../qml/dialogs/ImagePackEditorDialog.qml     |  3 +++
 .../qml/dialogs/ImagePackSettingsDialog.qml   |  4 +++-
 resources/qml/dialogs/InviteDialog.qml        |  7 ++++++
 .../dialogs/PowerLevelSpacesApplyDialog.qml   |  4 ++++
 resources/qml/dialogs/ReadReceipts.qml        |  4 ++++
 resources/qml/dialogs/RoomDirectory.qml       |  4 ++++
 resources/qml/dialogs/RoomMembers.qml         |  3 +++
 resources/qml/dialogs/UserProfile.qml         |  4 ++++
 resources/qml/emoji/StickerPicker.qml         |  4 ++++
 src/MainWindow.cpp                            |  7 ++++++
 22 files changed, 116 insertions(+), 2 deletions(-)
 create mode 100644 resources/qml/components/KirigamiWheelHandler.qml

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 1832968ea..2016a4ff2 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -277,6 +277,20 @@ else()
     find_package(KDSingleApplication-qt6 REQUIRED)
 endif()
 
+if(UNIX)
+    set(KF_MIN_VERSION "6.0.0")
+    find_package(ECM ${KF_MIN_VERSION})
+    if(ECM_FOUND)
+        list(APPEND CMAKE_MODULE_PATH ${ECM_MODULE_PATH})
+        find_package(KF6 COMPONENTS
+            Kirigami
+        )
+        if(KF6_FOUND)
+            add_compile_definitions(NHEKO_USE_KIRIGAMI)
+        endif()
+    endif()
+endif()
+
 if(Qt6Widgets_FOUND)
     if(Qt6Widgets_VERSION VERSION_LESS 6.5.0)
         message(STATUS "Qt version ${Qt6Widgets_VERSION}")
@@ -821,12 +835,20 @@ set(QML_SOURCES
     resources/qml/delegates/EncryptionEnabled.qml
     resources/qml/ui/TimelineEffects.qml
 )
+set(QML_DEPENDENCIES
+    QtQuick
+    QtQml.Models
+)
+if(KF6_FOUND)
+    list(APPEND QML_SOURCES "resources/qml/components/KirigamiWheelHandler.qml")
+    list(APPEND QML_DEPENDENCIES "org.kde.kirigami")
+endif()
 qt_add_qml_module(nheko
     URI im.nheko
     NO_RESOURCE_TARGET_PATH
     RESOURCE_PREFIX "/"
     VERSION 1.1
-    DEPENDENCIES QtQuick QtQml.Models
+    DEPENDENCIES ${QML_DEPENDENCIES}
     QML_FILES
     ${QML_SOURCES}
     SOURCES
diff --git a/resources/qml/CommunitiesList.qml b/resources/qml/CommunitiesList.qml
index 2b0be72c0..c4a5a9837 100644
--- a/resources/qml/CommunitiesList.qml
+++ b/resources/qml/CommunitiesList.qml
@@ -38,6 +38,10 @@ Page {
         model: Communities.filtered()
         boundsBehavior: Flickable.StopAtBounds
 
+        Loader {
+            source: NHEKO_USE_KIRIGAMI ? "components/KirigamiWheelHandler.qml" : ""
+        }
+
         ScrollBar.vertical: ScrollBar {
             id: scrollbar
 
diff --git a/resources/qml/Completer.qml b/resources/qml/Completer.qml
index c6fea98ea..890ba2036 100644
--- a/resources/qml/Completer.qml
+++ b/resources/qml/Completer.qml
@@ -93,6 +93,10 @@ Control {
     contentItem: ListView {
         id: listView
 
+        Loader {
+            source: NHEKO_USE_KIRIGAMI ? "components/KirigamiWheelHandler.qml" : ""
+        }
+
         clip: true
         displayMarginBeginning: height / 2
         displayMarginEnd: height / 2
diff --git a/resources/qml/MessageView.qml b/resources/qml/MessageView.qml
index a49761b23..9e83f2b7d 100644
--- a/resources/qml/MessageView.qml
+++ b/resources/qml/MessageView.qml
@@ -65,6 +65,10 @@ Item {
         spacing: 2
         verticalLayoutDirection: ListView.BottomToTop
 
+        Loader {
+            source: NHEKO_USE_KIRIGAMI ? "components/KirigamiWheelHandler.qml" : ""
+        }
+
         property int lastScrollPos: 0
 
         // Fixup the scroll position when the height changes. Without this, the view is kept around the center of the currently visible content, while we usually want to stick to the bottom.
diff --git a/resources/qml/RoomList.qml b/resources/qml/RoomList.qml
index 44a3e333d..f3c4ecca4 100644
--- a/resources/qml/RoomList.qml
+++ b/resources/qml/RoomList.qml
@@ -446,6 +446,10 @@ Page {
         model: Rooms
         boundsBehavior: Flickable.StopAtBounds
 
+        Loader {
+            source: NHEKO_USE_KIRIGAMI ? "components/KirigamiWheelHandler.qml" : ""
+        }
+
         //reuseItems: true
         ScrollBar.vertical: ScrollBar {
             id: scrollbar
diff --git a/resources/qml/UploadBox.qml b/resources/qml/UploadBox.qml
index 1d9415e5c..dd3d2188e 100644
--- a/resources/qml/UploadBox.qml
+++ b/resources/qml/UploadBox.qml
@@ -22,6 +22,10 @@ Page {
     contentItem: ListView {
         id: uploadsList
 
+        Loader {
+            source: NHEKO_USE_KIRIGAMI ? "components/KirigamiWheelHandler.qml" : ""
+        }
+
         anchors.horizontalCenter: parent.horizontalCenter
         boundsBehavior: Flickable.StopAtBounds
         model: room ? room.input.uploads : undefined
diff --git a/resources/qml/components/AdaptiveLayout.qml b/resources/qml/components/AdaptiveLayout.qml
index eb8ec341d..3fda3fb81 100644
--- a/resources/qml/components/AdaptiveLayout.qml
+++ b/resources/qml/components/AdaptiveLayout.qml
@@ -122,6 +122,10 @@ Container {
     contentItem: ListView {
         id: view
 
+        Loader {
+            source: NHEKO_USE_KIRIGAMI ? "KirigamiWheelHandler.qml" : ""
+        }
+
         model: container.contentModel
         snapMode: ListView.SnapOneItem
         orientation: ListView.Horizontal
diff --git a/resources/qml/components/KirigamiWheelHandler.qml b/resources/qml/components/KirigamiWheelHandler.qml
new file mode 100644
index 000000000..d1d444360
--- /dev/null
+++ b/resources/qml/components/KirigamiWheelHandler.qml
@@ -0,0 +1,12 @@
+// SPDX-FileCopyrightText: Nheko Contributors
+//
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+import org.kde.kirigami as Kirigami
+
+Kirigami.WheelHandler {
+    id: wheelHandler
+    target: parent
+    filterMouseEvents: true
+    keyNavigationEnabled: true
+}
diff --git a/resources/qml/components/ReorderableListview.qml b/resources/qml/components/ReorderableListview.qml
index b5d5f5e58..4ed604b2c 100644
--- a/resources/qml/components/ReorderableListview.qml
+++ b/resources/qml/components/ReorderableListview.qml
@@ -100,6 +100,10 @@ Item {
         ListView {
             id: view
 
+            Loader {
+                source: NHEKO_USE_KIRIGAMI ? "KirigamiWheelHandler.qml" : ""
+            }
+
             clip: true
 
             anchors { fill: parent; margins: 2 }
diff --git a/resources/qml/dialogs/AliasEditor.qml b/resources/qml/dialogs/AliasEditor.qml
index 82f127505..619fce4f4 100644
--- a/resources/qml/dialogs/AliasEditor.qml
+++ b/resources/qml/dialogs/AliasEditor.qml
@@ -52,6 +52,9 @@ ApplicationWindow {
 
             clip: true
 
+            Loader {
+                source: NHEKO_USE_KIRIGAMI ? "../components/KirigamiWheelHandler.qml" : ""
+            }
 
             model: editingModel
             spacing: 4
diff --git a/resources/qml/dialogs/AllowedRoomsSettingsDialog.qml b/resources/qml/dialogs/AllowedRoomsSettingsDialog.qml
index 82b5506e4..a689a1c20 100644
--- a/resources/qml/dialogs/AllowedRoomsSettingsDialog.qml
+++ b/resources/qml/dialogs/AllowedRoomsSettingsDialog.qml
@@ -51,6 +51,9 @@ ApplicationWindow {
 
             clip: true
 
+            Loader {
+                source: NHEKO_USE_KIRIGAMI ? "../components/KirigamiWheelHandler.qml" : ""
+            }
 
             model: roomSettings.allowedRoomsModel
             spacing: 4
diff --git a/resources/qml/dialogs/IgnoredUsers.qml b/resources/qml/dialogs/IgnoredUsers.qml
index 6d6585f0b..ac45de352 100644
--- a/resources/qml/dialogs/IgnoredUsers.qml
+++ b/resources/qml/dialogs/IgnoredUsers.qml
@@ -26,6 +26,10 @@ Window {
         spacing: Nheko.paddingMedium
         footerPositioning: ListView.OverlayFooter
 
+        Loader {
+            source: NHEKO_USE_KIRIGAMI ? "../components/KirigamiWheelHandler.qml" : ""
+        }
+
         model: TimelineManager.ignoredUsers
         header: ColumnLayout {
             Text {
diff --git a/resources/qml/dialogs/ImagePackEditorDialog.qml b/resources/qml/dialogs/ImagePackEditorDialog.qml
index 9416ec971..be8a58425 100644
--- a/resources/qml/dialogs/ImagePackEditorDialog.qml
+++ b/resources/qml/dialogs/ImagePackEditorDialog.qml
@@ -49,6 +49,9 @@ ApplicationWindow {
 
                 model: imagePack
 
+                Loader {
+                    source: NHEKO_USE_KIRIGAMI ? "../components/KirigamiWheelHandler.qml" : ""
+                }
 
                 header: AvatarListTile {
                     title: imagePack.packname
diff --git a/resources/qml/dialogs/ImagePackSettingsDialog.qml b/resources/qml/dialogs/ImagePackSettingsDialog.qml
index 690684054..c4496f49c 100644
--- a/resources/qml/dialogs/ImagePackSettingsDialog.qml
+++ b/resources/qml/dialogs/ImagePackSettingsDialog.qml
@@ -59,7 +59,9 @@ ApplicationWindow {
                 model: packlist
                 clip: true
 
-                
+                Loader {
+                    source: NHEKO_USE_KIRIGAMI ? "../components/KirigamiWheelHandler.qml" : ""
+                }
 
                 footer: ColumnLayout {
                     Button {
diff --git a/resources/qml/dialogs/InviteDialog.qml b/resources/qml/dialogs/InviteDialog.qml
index 9fc165c7b..a45099390 100644
--- a/resources/qml/dialogs/InviteDialog.qml
+++ b/resources/qml/dialogs/InviteDialog.qml
@@ -166,6 +166,9 @@ ApplicationWindow {
                 Layout.fillWidth: true
                 Layout.fillHeight: true
                 clip: true
+                Loader {
+                    source: NHEKO_USE_KIRIGAMI ? "../components/KirigamiWheelHandler.qml" : ""
+                }
                 delegate: UserListRow {
                     id: del2
                     width: ListView.view.width
@@ -192,6 +195,10 @@ ApplicationWindow {
                 clip: true
                 visible: inviteDialogRoot.width >= 500
 
+                Loader {
+                    source: NHEKO_USE_KIRIGAMI ? "../components/KirigamiWheelHandler.qml" : ""
+                }
+
                 delegate: UserListRow {
                     id: del
                     hoverEnabled: true
diff --git a/resources/qml/dialogs/PowerLevelSpacesApplyDialog.qml b/resources/qml/dialogs/PowerLevelSpacesApplyDialog.qml
index 6a2e74b2b..946332f5b 100644
--- a/resources/qml/dialogs/PowerLevelSpacesApplyDialog.qml
+++ b/resources/qml/dialogs/PowerLevelSpacesApplyDialog.qml
@@ -86,6 +86,10 @@ ApplicationWindow {
             spacing: 4
             cacheBuffer: 50
 
+            Loader {
+                source: NHEKO_USE_KIRIGAMI ? "../components/KirigamiWheelHandler.qml" : ""
+            }
+
             delegate: RowLayout {
                 anchors.left: parent.left
                 anchors.right: parent.right
diff --git a/resources/qml/dialogs/ReadReceipts.qml b/resources/qml/dialogs/ReadReceipts.qml
index 74a4d1d8e..e93a2a947 100644
--- a/resources/qml/dialogs/ReadReceipts.qml
+++ b/resources/qml/dialogs/ReadReceipts.qml
@@ -54,6 +54,10 @@ ApplicationWindow {
                 boundsBehavior: Flickable.StopAtBounds
                 model: readReceipts
 
+                Loader {
+                    source: NHEKO_USE_KIRIGAMI ? "../components/KirigamiWheelHandler.qml" : ""
+                }
+
                 delegate: ItemDelegate {
                     id: del
 
diff --git a/resources/qml/dialogs/RoomDirectory.qml b/resources/qml/dialogs/RoomDirectory.qml
index dbf3b4591..9de3dfa3e 100644
--- a/resources/qml/dialogs/RoomDirectory.qml
+++ b/resources/qml/dialogs/RoomDirectory.qml
@@ -34,6 +34,10 @@ ApplicationWindow {
         anchors.fill: parent
         model: publicRooms
 
+        Loader {
+            source: NHEKO_USE_KIRIGAMI ? "../components/KirigamiWheelHandler.qml" : ""
+        }
+
         delegate: Rectangle {
             id: roomDirDelegate
 
diff --git a/resources/qml/dialogs/RoomMembers.qml b/resources/qml/dialogs/RoomMembers.qml
index 95dc9fc34..f843fc9e0 100644
--- a/resources/qml/dialogs/RoomMembers.qml
+++ b/resources/qml/dialogs/RoomMembers.qml
@@ -108,6 +108,9 @@ ApplicationWindow {
                 boundsBehavior: Flickable.StopAtBounds
                 model: members
 
+                Loader {
+                    source: NHEKO_USE_KIRIGAMI ? "../components/KirigamiWheelHandler.qml" : ""
+                }
 
                 delegate: ItemDelegate {
                     id: del
diff --git a/resources/qml/dialogs/UserProfile.qml b/resources/qml/dialogs/UserProfile.qml
index 6798bc791..735b55269 100644
--- a/resources/qml/dialogs/UserProfile.qml
+++ b/resources/qml/dialogs/UserProfile.qml
@@ -45,6 +45,10 @@ ApplicationWindow {
         anchors.margins: 10
         footerPositioning: ListView.OverlayFooter
 
+        Loader {
+            source: NHEKO_USE_KIRIGAMI ? "../components/KirigamiWheelHandler.qml" : ""
+        }
+
         header: ColumnLayout {
             id: contentL
 
diff --git a/resources/qml/emoji/StickerPicker.qml b/resources/qml/emoji/StickerPicker.qml
index b7721db64..aea169887 100644
--- a/resources/qml/emoji/StickerPicker.qml
+++ b/resources/qml/emoji/StickerPicker.qml
@@ -116,6 +116,10 @@ Menu {
                 clip: true
                 currentIndex: -1 // prevent sorting from stealing focus
 
+                Loader {
+                    source: NHEKO_USE_KIRIGAMI ? "../components/KirigamiWheelHandler.qml" : ""
+                }
+
                 section.property: "packname"
                 section.criteria: ViewSection.FullString
                 section.delegate: Rectangle {
diff --git a/src/MainWindow.cpp b/src/MainWindow.cpp
index 42a1521d8..bb4ff3f61 100644
--- a/src/MainWindow.cpp
+++ b/src/MainWindow.cpp
@@ -4,6 +4,7 @@
 
 #include <QApplication>
 #include <QMessageBox>
+#include <QQmlContext>
 
 #include <mtx/events/collections.hpp>
 #include <mtx/requests.hpp>
@@ -123,6 +124,12 @@ MainWindow::registerQmlTypes()
             nhlog::ui()->warn("Could not connect to D-Bus!");
     }
 #endif
+
+#ifdef NHEKO_USE_KIRIGAMI
+    engine()->rootContext()->setContextProperty("NHEKO_USE_KIRIGAMI", QVariant(true));
+#else
+    engine()->rootContext()->setContextProperty("NHEKO_USE_KIRIGAMI", QVariant(false));
+#endif
 }
 
 void
openSUSE Build Service is sponsored by