[vlc-commits] [Git][videolan/vlc][master] 10 commits: qt: add FlickableScrollHandler

Jean-Baptiste Kempf (@jbk) gitlab at videolan.org
Fri Dec 24 17:33:41 UTC 2021



Jean-Baptiste Kempf pushed to branch master at VideoLAN / VLC


Commits:
4d9a386f by Fatih Uzunoglu at 2021-12-24T17:20:25+00:00
qt: add FlickableScrollHandler

- - - - -
8813b048 by Fatih Uzunoglu at 2021-12-24T17:20:25+00:00
qt: register type FlickableScrollHandler

- - - - -
1a562615 by Fatih Uzunoglu at 2021-12-24T17:20:25+00:00
qt: add option 'qt-smooth-scrolling'

- - - - -
290351b5 by Fatih Uzunoglu at 2021-12-24T17:20:25+00:00
qml: add MultipleBinding

- - - - -
6a5cbc9d by Fatih Uzunoglu at 2021-12-24T17:20:25+00:00
qml: add FlickableScrollHandler

- - - - -
c920b335 by Fatih Uzunoglu at 2021-12-24T17:20:25+00:00
Revert "qml: toolbar view to stop at bounds"

This reverts commit ddb5082ed2b6515b519c2b19fdf888457991db61.

- - - - -
b43612bf by Fatih Uzunoglu at 2021-12-24T17:20:25+00:00
Revert "qml: stop at bound when scrolling in KeyNavigableListView"

This reverts commit 2226849992b43e97e4bf77e307285fe61d7e3c0a.

- - - - -
6287a435 by Fatih Uzunoglu at 2021-12-24T17:20:25+00:00
Revert "qml: stop at bounds when scrolling in ExpandGridView"

This reverts commit 7a0719ce6bab29ce8c20aa3b208dd7f889779f50.

- - - - -
b172b099 by Fatih Uzunoglu at 2021-12-24T17:20:25+00:00
Revert "qml: disable overshoot in toolbar editor grid view"

This reverts commit 4e8133f471caed9f77d7ef79a2bc2e4257e7ef2f.

- - - - -
4f7e6a49 by Fatih Uzunoglu at 2021-12-24T17:20:25+00:00
qml: use FlickableScrollHandler in various Flickables

- - - - -


15 changed files:

- modules/gui/qt/Makefile.am
- modules/gui/qt/dialogs/toolbar/qml/EditorDNDView.qml
- modules/gui/qt/dialogs/toolbar/qml/ToolbarEditorButtonList.qml
- modules/gui/qt/maininterface/mainctx.cpp
- modules/gui/qt/maininterface/mainctx.hpp
- modules/gui/qt/maininterface/mainui.cpp
- modules/gui/qt/qt.cpp
- + modules/gui/qt/util/flickable_scroll_handler.cpp
- + modules/gui/qt/util/flickable_scroll_handler.hpp
- + modules/gui/qt/util/qml/FlickableScrollHandler.qml
- + modules/gui/qt/util/qml/MultipleBinding.qml
- modules/gui/qt/vlc.qrc
- modules/gui/qt/widgets/qml/ExpandGridView.qml
- modules/gui/qt/widgets/qml/KeyNavigableGridView.qml
- modules/gui/qt/widgets/qml/KeyNavigableListView.qml


Changes:

=====================================
modules/gui/qt/Makefile.am
=====================================
@@ -243,6 +243,8 @@ libqt_plugin_la_SOURCES = \
 	gui/qt/util/navigation_history.cpp gui/qt/util/navigation_history.hpp \
 	gui/qt/util/item_key_event_filter.cpp \
 	gui/qt/util/item_key_event_filter.hpp \
+	gui/qt/util/flickable_scroll_handler.cpp \
+	gui/qt/util/flickable_scroll_handler.hpp \
 	gui/qt/util/qt_dirs.cpp gui/qt/util/qt_dirs.hpp \
 	gui/qt/util/qvlcapp.hpp \
 	gui/qt/util/proxycolumnmodel.hpp \
@@ -420,6 +422,7 @@ nodist_libqt_plugin_la_SOURCES = \
 	gui/qt/util/navigation_history.moc.cpp \
 	gui/qt/util/item_key_event_filter.moc.cpp \
 	gui/qt/util/mouse_event_filter.moc.cpp \
+	gui/qt/util/flickable_scroll_handler.moc.cpp \
 	gui/qt/util/qvlcapp.moc.cpp \
 	gui/qt/util/renderer_manager.moc.cpp \
 	gui/qt/util/selectable_list_model.moc.cpp \
@@ -843,6 +846,8 @@ libqt_plugin_la_QML = \
 	gui/qt/style/qmldir \
 	gui/qt/util/qml/Helpers.js \
 	gui/qt/util/qml/SelectableDelegateModel.qml \
+	gui/qt/util/qml/MultipleBinding.qml \
+	gui/qt/util/qml/FlickableScrollHandler.qml \
 	gui/qt/widgets/qml/ActionButtonOverlay.qml \
 	gui/qt/widgets/qml/ActionButtonPrimary.qml \
 	gui/qt/widgets/qml/BannerTabButton.qml \


=====================================
modules/gui/qt/dialogs/toolbar/qml/EditorDNDView.qml
=====================================
@@ -22,6 +22,7 @@ import QtQml.Models 2.11
 import org.videolan.vlc 0.1
 
 import "qrc:///style/"
+import "qrc:///util/" as Util
 
 ListView {
     id: playerBtnDND
@@ -33,9 +34,6 @@ ListView {
     currentIndex: -1
     highlightFollowsCurrentItem: false
 
-    boundsBehavior: Flickable.StopAtBounds
-    boundsMovement: Flickable.StopAtBounds
-
     property bool containsDrag: footerItem.dropVisible
 
     property alias scrollBar: scrollBar
@@ -94,6 +92,15 @@ ListView {
         }
     }
     
+    MouseEventFilter {
+        target: playerBtnDND
+    }
+
+    Util.FlickableScrollHandler {
+        fallbackScroll: true
+        enabled: true
+    }
+
     MouseArea {
         anchors.fill: parent
 
@@ -101,21 +108,6 @@ ListView {
         z: -1
 
         cursorShape: root.dragActive ? Qt.DragMoveCursor : Qt.ArrowCursor
-
-        onWheel: {
-            // scrolling based on angleDelta.x is handled by the listview itself
-            var y = wheel.angleDelta.y
-
-            if (y > 0) {
-                scrollBar.decrease()
-                wheel.accepted = true
-            } else if (y < 0) {
-                scrollBar.increase()
-                wheel.accepted = true
-            } else {
-                wheel.accepted = false
-            }
-        }
     }
 
     footer: Item {


=====================================
modules/gui/qt/dialogs/toolbar/qml/ToolbarEditorButtonList.qml
=====================================
@@ -25,8 +25,11 @@ import org.videolan.vlc 0.1
 import "qrc:///player/"
 import "qrc:///style/"
 import "qrc:///widgets/" as Widgets
+import "qrc:///util/" as Util
 
 GridView {
+    id: root
+
     clip: true
 
     ScrollBar.vertical: ScrollBar { policy: ScrollBar.AlwaysOn }
@@ -38,11 +41,14 @@ GridView {
     cellWidth: VLCStyle.cover_small
     cellHeight: cellWidth
 
-    boundsBehavior: Flickable.StopAtBounds
-    boundsMovement: Flickable.StopAtBounds
-
     property alias removeInfoRectVisible: removeInfoRect.visible
 
+    MouseEventFilter {
+        target: root
+    }
+
+    Util.FlickableScrollHandler { }
+
     DropArea {
         id: dropArea
         anchors.fill: parent


=====================================
modules/gui/qt/maininterface/mainctx.cpp
=====================================
@@ -294,6 +294,8 @@ void MainCtx::loadPrefs(const bool callSignals)
 #if QT_CLIENT_SIDE_DECORATION_AVAILABLE
     loadFromVLCOption(m_windowTitlebar, "qt-titlebar" , &MainCtx::useClientSideDecorationChanged);
 #endif
+
+    loadFromVLCOption(m_smoothScroll, "qt-smooth-scrolling", &MainCtx::smoothScrollChanged);
 }
 
 void MainCtx::loadFromSettingsImpl(const bool callSignals)


=====================================
modules/gui/qt/maininterface/mainctx.hpp
=====================================
@@ -172,6 +172,7 @@ class MainCtx : public QObject
     Q_PROPERTY(bool hasAcrylicSurface READ hasAcrylicSurface NOTIFY hasAcrylicSurfaceChanged FINAL)
     Q_PROPERTY(PlaylistPtr mainPlaylist READ getMainPlaylist CONSTANT FINAL)
     Q_PROPERTY(vlc::playlist::PlaylistControllerModel* mainPlaylistController READ getMainPlaylistController CONSTANT FINAL)
+    Q_PROPERTY(bool smoothScroll READ smoothScroll NOTIFY smoothScrollChanged FINAL)
 
     // This Property only works if hasAcrylicSurface is set
     Q_PROPERTY(bool acrylicActive READ acrylicActive WRITE setAcrylicActive NOTIFY acrylicActiveChanged FINAL)
@@ -190,6 +191,7 @@ public:
     inline qt_intf_t* getIntf() const { return p_intf; }
     inline PlaylistPtr getMainPlaylist() const { return PlaylistPtr(p_intf->p_playlist); }
     inline vlc::playlist::PlaylistControllerModel* getMainPlaylistController() const { return p_intf->p_mainPlaylistController; }
+    bool smoothScroll() const { return m_smoothScroll; };
 
     QSystemTrayIcon *getSysTray() { return sysTray; }
     QMenu *getSysTrayMenu() { return systrayMenu.get(); }
@@ -314,6 +316,8 @@ protected:
     bool m_hasAcrylicSurface = false;
     bool m_acrylicActive = false;
 
+    bool m_smoothScroll = true;
+
 public slots:
     void toggleUpdateSystrayMenu();
     void showUpdateSystrayMenu();
@@ -385,6 +389,8 @@ signals:
 
     void acrylicActiveChanged();
 
+    void smoothScrollChanged();
+
 private:
     void loadPrefs(bool callSignals);
     void loadFromSettingsImpl(bool callSignals);


=====================================
modules/gui/qt/maininterface/mainui.cpp
=====================================
@@ -37,6 +37,7 @@
 #include "util/navigation_history.hpp"
 #include "util/qmlinputitem.hpp"
 #include "util/mouse_event_filter.hpp"
+#include "util/flickable_scroll_handler.hpp"
 
 #include "dialogs/help/aboutmodel.hpp"
 #include "dialogs/dialogs_provider.hpp"
@@ -272,6 +273,7 @@ void MainUI::registerQMLTypes()
 
         qmlRegisterType<ItemKeyEventFilter>( uri, versionMajor, versionMinor, "KeyEventFilter" );
         qmlRegisterType<MouseEventFilter>( uri, versionMajor, versionMinor, "MouseEventFilter" );
+        qmlRegisterType<FlickableScrollHandler>( uri, versionMajor, versionMinor, "FlickableScrollHandler" );
 
         qmlRegisterUncreatableType<ControlbarProfileModel>(uri, versionMajor, versionMinor, "ControlbarProfileModel", "");
         qmlRegisterUncreatableType<ControlbarProfile>(uri, versionMajor, versionMinor, "ControlbarProfile", "");


=====================================
modules/gui/qt/qt.cpp
=====================================
@@ -246,6 +246,9 @@ static void ShowDialog   ( intf_thread_t *, int, int, intf_dialog_args_t * );
 #define QT_COMPOSITOR_TEXT N_("Select Qt video intergration backend")
 #define QT_COMPOSITOR_LONGTEXT N_("Select Qt video intergration backend. Use with care, the interface may not start if an incompatible compositor is selected")
 
+#define SMOOTH_SCROLLING_TEXT N_( "Use smooth scrolling in Flickable based views" )
+#define SMOOTH_SCROLLING_LONGTEXT N_( "Deactivating this option will disable smooth scrolling in Flickable based views (such as the Playqueue)" )
+
 static const int i_notification_list[] =
     { NOTIFICATION_NEVER, NOTIFICATION_MINIMIZED, NOTIFICATION_ALWAYS };
 
@@ -403,6 +406,8 @@ vlc_module_begin ()
                  AUTORAISE_ON_PLAYBACK_LONGTEXT )
             change_integer_list( i_raise_list, psz_raise_list_text )
 
+    add_bool( "qt-smooth-scrolling", true, SMOOTH_SCROLLING_TEXT, SMOOTH_SCROLLING_LONGTEXT )
+
     cannot_unload_broken_library()
 
     add_submodule ()


=====================================
modules/gui/qt/util/flickable_scroll_handler.cpp
=====================================
@@ -0,0 +1,289 @@
+/*****************************************************************************
+ * Copyright (C) 2021 VLC authors and VideoLAN
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * ( at your option ) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+#include "flickable_scroll_handler.hpp"
+
+#include <QApplication>
+#include <QStyleHints>
+#include <QtQml>
+#include <QQmlProperty>
+
+#define OVERRIDE_SCROLLBAR_STEPSIZE true
+#define PAGE_SCROLL_SHIFT_OR_CTRL true
+
+FlickableScrollHandler::FlickableScrollHandler(QObject *parent)
+    : QObject(parent)
+{
+    connect(this, &FlickableScrollHandler::scaleFactorChanged, this, [this]() {
+        m_effectiveScaleFactor = QApplication::styleHints()->wheelScrollLines() * 20 * m_scaleFactor;
+        emit effectiveScaleFactorChanged();
+    });
+
+    setScaleFactor(1.0);
+
+    QMetaObject::invokeMethod(this, &FlickableScrollHandler::init, Qt::QueuedConnection);
+}
+
+FlickableScrollHandler::~FlickableScrollHandler()
+{
+    detach();
+}
+
+void FlickableScrollHandler::init()
+{
+    assert(parent());
+
+    m_target = qobject_cast<QQuickItem*>(parent());
+    if (!m_target || !m_target->inherits("QQuickFlickable"))
+    {
+        qmlWarning(this) << "Parent is not QQuickFlickable!";
+        return;
+    }
+
+    const auto qCtx = qmlContext(m_target);
+    assert(qCtx);
+
+    m_propertyContentX = QQmlProperty(m_target, "contentX", qCtx);
+    m_propertyContentY = QQmlProperty(m_target, "contentY", qCtx);
+    m_propertyContentHeight = QQmlProperty(m_target, "contentHeight", qCtx);
+    m_propertyContentWidth = QQmlProperty(m_target, "contentWidth", qCtx);
+    m_propertyHeight = QQmlProperty(m_target, "height", qCtx);
+    m_propertyWidth = QQmlProperty(m_target, "width", qCtx);
+
+    m_scrollBarV.scrollBar = QQmlProperty(m_target, "ScrollBar.vertical", qCtx);
+    m_scrollBarH.scrollBar = QQmlProperty(m_target, "ScrollBar.horizontal", qCtx);
+
+    adjustScrollBarV();
+    adjustScrollBarH();
+
+    m_scrollBarV.scrollBar.connectNotifySignal(this, SLOT(adjustScrollBarV()));
+    m_scrollBarH.scrollBar.connectNotifySignal(this, SLOT(adjustScrollBarH()));
+
+    if (enabled())
+        attach();
+
+    emit initialized();
+}
+
+bool FlickableScrollHandler::eventFilter(QObject *watched, QEvent *event)
+{
+    assert (event);
+    assert (watched == m_target);
+
+    if (event->type() != QEvent::Wheel)
+        return QObject::eventFilter(watched, event);
+
+    const auto wheel = static_cast<QWheelEvent *>(event);
+
+    struct {
+        QPoint delta;
+        enum class Type {
+            Pixel,
+            Degree
+        } type;
+    } ev;
+
+    using Type = decltype(ev)::Type;
+
+    if (!wheel->pixelDelta().isNull() && (wheel->pixelDelta().manhattanLength() % 120))
+    {
+        ev.delta = wheel->pixelDelta();
+        ev.type = Type::Pixel;
+    }
+    else if (!wheel->angleDelta().isNull())
+    {
+        ev.delta = wheel->angleDelta() / 8 / 15;
+        ev.type = Type::Degree;
+    }
+    else
+        return false;
+
+    if (wheel->inverted())
+    {
+        ev.delta = -ev.delta;
+    }
+
+    const auto handler = [this, wheel, ev](Qt::Orientation orientation, bool fallback = false) {
+        const auto vertical = (orientation == Qt::Vertical);
+
+        const auto handler = [this, vertical](qreal delta, Type type) {
+            const auto contentSize = vertical ? m_propertyContentHeight.read().toReal()
+                                              : m_propertyContentWidth.read().toReal();
+            const auto pos = vertical ? m_propertyContentY.read().toReal()
+                                      : m_propertyContentX.read().toReal();
+            const auto size = vertical ? m_propertyHeight.read().toReal()
+                                       : m_propertyWidth.read().toReal();
+
+            if (contentSize < size || pos >= contentSize)
+                return false;
+
+            const auto& scrollBar = vertical ? m_scrollBarV : m_scrollBarH;
+            if (scrollBar.valid())
+            {
+                // Attached ScrollBar is available, use it to scroll
+#if !OVERRIDE_SCROLLBAR_STEPSIZE
+                const auto _stepSize = scrollBar.stepSize.read().toReal();
+#endif
+                qreal newStepSize = delta;
+                if (type == Type::Degree)
+                    newStepSize *= (m_effectiveScaleFactor / contentSize);
+                else
+                    newStepSize *= (1.0 / contentSize);
+
+                scrollBar.stepSize.write(qBound<qreal>(0, qAbs(newStepSize), 1));
+
+                if (newStepSize > 0)
+                    scrollBar.decreaseMethod.invoke(scrollBar.item);
+                else
+                    scrollBar.increaseMethod.invoke(scrollBar.item);
+
+#if !OVERRIDE_SCROLLBAR_STEPSIZE
+                scrollBar.stepSize.write(_stepSize);
+#endif
+            }
+            else
+            {
+                qreal newPos = pos;
+                if (type == Type::Degree)
+                    newPos -= (m_effectiveScaleFactor * delta);
+                else
+                    newPos -= delta;
+
+                newPos = qBound<qreal>(0, newPos, contentSize - size);
+
+                if (vertical)
+                    m_propertyContentY.write(newPos);
+                else
+                    m_propertyContentX.write(newPos);
+            }
+
+            return (vertical ? (!qFuzzyCompare(m_propertyContentY.read().toReal(), pos))
+                             : (!qFuzzyCompare(m_propertyContentX.read().toReal(), pos)));
+        };
+
+        const bool _vertical = (fallback ? !vertical : vertical);
+        qreal _delta = _vertical ? ev.delta.y() : ev.delta.x();
+        auto _type = ev.type;
+
+#if PAGE_SCROLL_SHIFT_OR_CTRL
+        if (_delta != 0 && (wheel->modifiers() & (Qt::ControlModifier | Qt::ShiftModifier)))
+        {
+            _type = Type::Pixel;
+            _delta = (_vertical ? m_propertyHeight.read().toReal()
+                                : m_propertyWidth.read().toReal()) * (_delta > 0 ? 1 : -1);
+        }
+#endif
+
+        if (_delta != 0 && handler(_delta, _type))
+        {
+            wheel->accept();
+            return true;
+        }
+
+        return false;
+    };
+
+    bool rV = handler(Qt::Vertical);
+    bool rH = handler(Qt::Horizontal);
+
+    if (m_fallbackScroll && (rV == false && rH == false))
+    {
+        if (ev.delta.y() != 0)
+            rH = handler(Qt::Horizontal, true);
+        else if (ev.delta.x() != 0)
+            rV = handler(Qt::Vertical, true);
+    }
+
+    return (rV || rH) || QObject::eventFilter(watched, event);
+}
+
+void FlickableScrollHandler::attach()
+{
+    if (m_target)
+    {
+        m_target->installEventFilter(this);
+    }
+}
+
+void FlickableScrollHandler::detach()
+{
+    if (m_target)
+    {
+        m_target->removeEventFilter(this);
+    }
+}
+
+void FlickableScrollHandler::adjustScrollBar(ScrollBar& scrollBar)
+{
+    const auto item = scrollBar.scrollBar.read().value<QQuickItem *>();
+
+    scrollBar.item = item;
+
+    if (item)
+    {
+        scrollBar.stepSize = QQmlProperty(item, "stepSize", qmlContext(item));
+        scrollBar.decreaseMethod = item->metaObject()->method(item->metaObject()->indexOfMethod("decrease()"));
+        scrollBar.increaseMethod = item->metaObject()->method(item->metaObject()->indexOfMethod("increase()"));
+    }
+}
+
+qreal FlickableScrollHandler::scaleFactor() const
+{
+    return m_scaleFactor;
+}
+
+void FlickableScrollHandler::setScaleFactor(qreal newScaleFactor)
+{
+    if (qFuzzyCompare(m_scaleFactor, newScaleFactor))
+        return;
+    m_scaleFactor = newScaleFactor;
+    emit scaleFactorChanged();
+}
+
+bool FlickableScrollHandler::enabled() const
+{
+    return m_enabled;
+}
+
+void FlickableScrollHandler::setEnabled(bool newEnabled)
+{
+    if (m_enabled == newEnabled)
+        return;
+
+    if (newEnabled)
+        attach();
+    else
+        detach();
+
+    m_enabled = newEnabled;
+    emit enabledChanged();
+}
+
+void FlickableScrollHandler::adjustScrollBarV()
+{
+    adjustScrollBar(m_scrollBarV);
+}
+
+void FlickableScrollHandler::adjustScrollBarH()
+{
+    adjustScrollBar(m_scrollBarH);
+}
+
+qreal FlickableScrollHandler::effectiveScaleFactor() const
+{
+    return m_effectiveScaleFactor;
+}


=====================================
modules/gui/qt/util/flickable_scroll_handler.hpp
=====================================
@@ -0,0 +1,91 @@
+/*****************************************************************************
+ * Copyright (C) 2021 VLC authors and VideoLAN
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * ( at your option ) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+#ifndef FLICKABLE_SCROLL_HANDLER_HPP
+#define FLICKABLE_SCROLL_HANDLER_HPP
+
+#include <QObject>
+#include <QQmlProperty>
+#include <QPointer>
+#include <QQuickItem>
+
+class FlickableScrollHandler : public QObject
+{
+    Q_OBJECT
+
+    Q_PROPERTY(QObject* parent READ parent NOTIFY initialized FINAL)
+
+    Q_PROPERTY(qreal scaleFactor READ scaleFactor WRITE setScaleFactor NOTIFY scaleFactorChanged FINAL)
+    Q_PROPERTY(qreal effectiveScaleFactor READ effectiveScaleFactor NOTIFY effectiveScaleFactorChanged FINAL)
+    Q_PROPERTY(bool enabled READ enabled WRITE setEnabled NOTIFY enabledChanged FINAL)
+    Q_PROPERTY(bool fallbackScroll MEMBER m_fallbackScroll NOTIFY fallbackScrollChanged FINAL)
+
+public:
+    explicit FlickableScrollHandler(QObject *parent = nullptr);
+    ~FlickableScrollHandler();
+
+    qreal scaleFactor() const;
+    qreal effectiveScaleFactor() const;
+    bool enabled() const;
+
+    void setScaleFactor(qreal newScaleFactor);
+    void setEnabled(bool newEnabled);
+
+signals:
+    void initialized();
+
+    void scaleFactorChanged();
+    void enabledChanged();
+    void effectiveScaleFactorChanged();
+    void fallbackScrollChanged();
+
+private slots:
+    void init();
+
+    void adjustScrollBarV();
+    void adjustScrollBarH();
+
+private:
+    void attach();
+    void detach();
+
+    bool eventFilter(QObject *watched, QEvent *event) override;
+
+private:
+    QPointer<QQuickItem> m_target = nullptr;
+    qreal m_scaleFactor;
+    qreal m_effectiveScaleFactor;
+    bool m_enabled = true;
+    bool m_fallbackScroll = false;
+
+    QQmlProperty m_propertyContentX, m_propertyContentY;
+    QQmlProperty m_propertyContentHeight, m_propertyContentWidth;
+    QQmlProperty m_propertyHeight, m_propertyWidth;
+
+    struct ScrollBar {
+        QQmlProperty scrollBar;
+        QQmlProperty stepSize;
+        QMetaMethod increaseMethod;
+        QMetaMethod decreaseMethod;
+        QQuickItem* item = nullptr;
+        bool valid() const { return item != nullptr; };
+    } m_scrollBarV, m_scrollBarH;
+
+    void adjustScrollBar(ScrollBar& scrollBar);
+};
+
+#endif // FLICKABLE_SCROLL_HANDLER_HPP


=====================================
modules/gui/qt/util/qml/FlickableScrollHandler.qml
=====================================
@@ -0,0 +1,39 @@
+/*****************************************************************************
+ * Copyright (C) 2021 VLC authors and VideoLAN
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * ( at your option ) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+import QtQml 2.11
+
+import org.videolan.vlc 0.1 as VLC
+
+VLC.FlickableScrollHandler {
+    id: handler
+
+    scaleFactor: VLC.MainCtx.intfScaleFactor
+    enabled: !VLC.MainCtx.smoothScroll
+
+    readonly property QtObject _behaviorAdjuster: MultipleBinding {
+        target: handler.parent
+        when: !handler.enabled
+
+        model: [
+            {property: "flickDeceleration", value: 3500} /* TODO: Workaround Qt <6.2 */,
+            {property: "boundsBehavior", value: 0 /* Flickable.StopAtBounds */},
+            {property: "boundsMovement", value: 0 /* Flickable.StopAtBounds */}
+        ]
+    }
+}


=====================================
modules/gui/qt/util/qml/MultipleBinding.qml
=====================================
@@ -0,0 +1,46 @@
+/*****************************************************************************
+ * Copyright (C) 2021 VLC authors and VideoLAN
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * ( at your option ) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+import QtQml 2.11
+
+QtObject {
+    id: root
+
+    property alias model: instantiator.model
+    property alias enabled: instantiator.active
+    property alias asynchronous: instantiator.asynchronous
+
+    property QtObject target: null
+    property bool when
+    property bool delayed: false
+
+    readonly property QtObject _instantiator: Instantiator {
+        id: instantiator
+
+        delegate: Binding {
+            target: modelData.target ? modelData.target
+                                     : root.target
+            when: modelData.when !== undefined ? modelData.when
+                                               : root.when
+            property: modelData.property
+            value: modelData.value
+            delayed: modelData.delayed !== undefined ? modelData.delayed
+                                                     : root.delayed
+        }
+    }
+}


=====================================
modules/gui/qt/vlc.qrc
=====================================
@@ -26,6 +26,8 @@
         <file alias="wait4.svg">pixmaps/util/wait4.svg</file>
         <file alias="SelectableDelegateModel.qml">util/qml/SelectableDelegateModel.qml</file>
         <file alias="Helpers.js">util/qml/Helpers.js</file>
+        <file alias="MultipleBinding.qml">util/qml/MultipleBinding.qml</file>
+        <file alias="FlickableScrollHandler.qml">util/qml/FlickableScrollHandler.qml</file>
     </qresource>
     <qresource prefix="/toolbar">
         <file alias="faster.svg">pixmaps/faster.svg</file>


=====================================
modules/gui/qt/widgets/qml/ExpandGridView.qml
=====================================
@@ -21,6 +21,7 @@ import org.videolan.vlc 0.1
 
 import "qrc:///style/"
 import "qrc:///util/Helpers.js" as Helpers
+import "qrc:///util/" as Util
 
 FocusScope {
     id: root
@@ -562,8 +563,6 @@ FocusScope {
         id: flickable
 
         flickableDirection: Flickable.VerticalFlick
-        boundsBehavior: Flickable.StopAtBounds
-        boundsMovement :Flickable.StopAtBounds
 
         ScrollBar.vertical: ScrollBar {
             id: flickableScrollBar
@@ -589,6 +588,8 @@ FocusScope {
                 }
             }
         }
+        
+        Util.FlickableScrollHandler { }
 
         Loader {
             id: headerItemLoader


=====================================
modules/gui/qt/widgets/qml/KeyNavigableGridView.qml
=====================================
@@ -20,6 +20,8 @@ import QtQuick.Controls 2.4
 
 import org.videolan.vlc 0.1
 
+import "qrc:///util/" as Util
+
 FocusScope {
     id: gridview_id
 
@@ -72,6 +74,8 @@ FocusScope {
 
         property int _colCount: Math.floor(width / cellWidth)
 
+        Util.FlickableScrollHandler { }
+
         Keys.onPressed: {
             var newIndex = -1
             if (KeyHelper.matchRight(event)) {


=====================================
modules/gui/qt/widgets/qml/KeyNavigableListView.qml
=====================================
@@ -21,6 +21,7 @@ import org.videolan.vlc 0.1
 
 import "qrc:///style/"
 import "qrc:///util/Helpers.js" as Helpers
+import "qrc:///util/" as Util
 
 FocusScope {
     id: listview_id
@@ -218,9 +219,6 @@ FocusScope {
         section.criteria: ViewSection.FullString
         section.delegate: sectionHeading
 
-        boundsBehavior: Flickable.StopAtBounds
-        boundsMovement: Flickable.StopAtBounds
-
         MouseEventFilter {
             target: view
 
@@ -244,6 +242,8 @@ FocusScope {
         // NOTE: We always want a valid 'currentIndex' by default.
         onCountChanged: if (count && currentIndex === -1) currentIndex = 0
 
+        Util.FlickableScrollHandler { }
+
         Keys.onPressed: {
             var newIndex = -1
 



View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/c9965e651b85005c2a526fd62f5b236cd620430d...4f7e6a49d82b6376aa251747602eac4881431057

-- 
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/c9965e651b85005c2a526fd62f5b236cd620430d...4f7e6a49d82b6376aa251747602eac4881431057
You're receiving this email because of your account on code.videolan.org.




More information about the vlc-commits mailing list