From 099bf06e1a432690ca34ebc961e29caf7a8e698a Mon Sep 17 00:00:00 2001
From: Fatih Uzunoglu <fuzun54@outlook.com>
Date: Fri, 28 Mar 2025 21:56:52 +0200
Subject: [PATCH 1/5] qml: create the scroll bar depending on the orientation
 in `ListViewExt`

By default we expect the viewport to cover the content width or height
depending on the orientation, so in normal cases we only need one scroll
bar. This behavior can obviously be overridden where the list view is
reused.

This fixes multiple things:
- Not being able to interact with the bottom part of the list view even
if the orientation is vertical and the viewport covers the whole content
width, because the scroll bar may still be technically visible and consume
events even though it does not display anything visually.
- Flashing scroll bar upon creation of the view until the content and
viewport sizes are determined (regarding the orientation where scroll bar
is not wanted).
---
 modules/gui/qt/widgets/qml/ListViewExt.qml | 18 ++++++++++++++++--
 1 file changed, 16 insertions(+), 2 deletions(-)

diff --git a/modules/gui/qt/widgets/qml/ListViewExt.qml b/modules/gui/qt/widgets/qml/ListViewExt.qml
index ab4bbce99d61..26760c1c3735 100644
--- a/modules/gui/qt/widgets/qml/ListViewExt.qml
+++ b/modules/gui/qt/widgets/qml/ListViewExt.qml
@@ -44,6 +44,10 @@ ListView {
     property var isDropAcceptableFunc
     property var acceptDropFunc
 
+    property Component defaultScrollBar: Component {
+        ScrollBarExt { }
+    }
+
     // Private
 
     property bool _keyPressed: false
@@ -81,8 +85,18 @@ ListView {
     keyNavigationEnabled: false
     keyNavigationWraps: false
 
-    ScrollBar.vertical: ScrollBarExt { }
-    ScrollBar.horizontal: ScrollBarExt { }
+    ScrollBar.vertical: {
+        // By default vertical scroll bar is only used when the orientation is vertical.
+        if (root.defaultScrollBar && (root.orientation === ListView.Vertical))
+            return root.defaultScrollBar.createObject() // rely on JS/QML engine's garbage collection
+        return null
+    }
+    ScrollBar.horizontal: {
+        // By default horizontal scroll bar is only used when the orientation is horizontal.
+        if (root.defaultScrollBar && (root.orientation === ListView.Horizontal))
+            return root.defaultScrollBar.createObject() // rely on JS/QML engine's garbage collection
+        return null
+    }
 
     flickableDirection: Flickable.AutoFlickIfNeeded
 
-- 
GitLab


From a4fee8f72f4fc03a0c6462c1c14ffcdeb876a4e1 Mon Sep 17 00:00:00 2001
From: Fatih Uzunoglu <fuzun54@outlook.com>
Date: Sat, 29 Mar 2025 19:25:09 +0200
Subject: [PATCH 2/5] qml: use 1.0 for `size` by default in `ScrollBarExt`

Using 0.0 (default) is not a good idea and it causes
the scroll bar to be shown with the full size until
the size becomes meaningful when it is attached to
a flickable.

It is not clear why Qt uses 0.0 for the size by
default.
---
 modules/gui/qt/widgets/qml/ScrollBarExt.qml | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/modules/gui/qt/widgets/qml/ScrollBarExt.qml b/modules/gui/qt/widgets/qml/ScrollBarExt.qml
index 92fd86c1a1ae..d30db00d903d 100644
--- a/modules/gui/qt/widgets/qml/ScrollBarExt.qml
+++ b/modules/gui/qt/widgets/qml/ScrollBarExt.qml
@@ -53,6 +53,13 @@ T.ScrollBar {
         hovered: true
     }
 
+    // NOTE: Before the scroll bar size is set when it is attached to a flickable,
+    //       there is an indeterminate period where the size remains 0.0. QQuickScrollBar
+    //       using 0.0 for the size by default does not help with this situation.
+    //       We can set the size to 1.0 by default, so that we don't show the handle
+    //       (content item) before the size is determined:
+    size: 1.0
+
     component DefaultBehavior : Behavior {
         // WARNING: Qt bug: OpacityAnimator is bugged
         NumberAnimation {
-- 
GitLab


From 0cd86d358c993ff8b052bdb0e024453bd85ca424 Mon Sep 17 00:00:00 2001
From: Fatih Uzunoglu <fuzun54@outlook.com>
Date: Sat, 29 Mar 2025 19:29:05 +0200
Subject: [PATCH 3/5] qml: instantiate the scroll bar when content is ready in
 `BannerSources`

Both the viewport and content sizes depend on the readiness of the content.
---
 .../gui/qt/maininterface/qml/BannerSources.qml | 18 ++++++++++++++----
 1 file changed, 14 insertions(+), 4 deletions(-)

diff --git a/modules/gui/qt/maininterface/qml/BannerSources.qml b/modules/gui/qt/maininterface/qml/BannerSources.qml
index 03549a70b071..22052b445e17 100644
--- a/modules/gui/qt/maininterface/qml/BannerSources.qml
+++ b/modules/gui/qt/maininterface/qml/BannerSources.qml
@@ -348,10 +348,20 @@ T.ToolBar {
                             contentWidth: localMenuGroup.width
                             contentHeight: VLCStyle.localToolbar_height // don't allow vertical flickering
 
-                            ScrollBar.horizontal: Widgets.ScrollBarExt {
-                                y: localMenuView.height - height
-                                width: localMenuView.availableWidth
-                                policy: ScrollBar.AsNeeded
+                            ScrollBar.horizontal: {
+                                // The content and viewport sizes are not available in here as soon as the
+                                // scroll bar is attached. This causes the scroll bar `size` to be briefly
+                                // set to 0.0, making its handle be displayed only to be hidden afterwards.
+                                if (localMenuGroup.status === Loader.Ready)
+                                    return scrollBarComponent.createObject() // rely on JS/QML engine's garbage collection
+                                else
+                                    return null
+                            }
+
+                            Component {
+                                id: scrollBarComponent
+
+                                Widgets.ScrollBarExt { orientation: Qt.Horizontal }
                             }
 
                             Loader {
-- 
GitLab


From 73822592b1683c58275b26a93c9b80f1f866b1eb Mon Sep 17 00:00:00 2001
From: Fatih Uzunoglu <fuzun54@outlook.com>
Date: Sat, 29 Mar 2025 19:48:26 +0200
Subject: [PATCH 4/5] qml: allow overriding the scroll bar in `ExpandGridView`

This also makes it respect the default `size` (if set in
the scroll bar).
---
 modules/gui/qt/widgets/qml/ExpandGridView.qml | 13 ++++++++++---
 1 file changed, 10 insertions(+), 3 deletions(-)

diff --git a/modules/gui/qt/widgets/qml/ExpandGridView.qml b/modules/gui/qt/widgets/qml/ExpandGridView.qml
index 61fc52f56e65..9b34345f0bd9 100644
--- a/modules/gui/qt/widgets/qml/ExpandGridView.qml
+++ b/modules/gui/qt/widgets/qml/ExpandGridView.qml
@@ -19,6 +19,7 @@
 import QtQuick
 import QtQuick.Window
 import QtQuick.Controls
+import QtQuick.Templates as T
 
 import QtQml.Models
 
@@ -115,6 +116,10 @@ FocusScope {
         property bool selected: false
     }
 
+    property Component defaultScrollBar: Component {
+        ScrollBarExt { }
+    }
+
     // extra margin taken in account for positionViewAtIndex
     //
     // this is required since delegates selection rect may occupy area outside of
@@ -135,7 +140,7 @@ FocusScope {
     property alias contentHeight: flickable.contentHeight
     property alias contentWidth: flickable.contentWidth
     property alias contentX: flickable.contentX
-    property alias gridScrollBar: flickableScrollBar
+    readonly property T.ScrollBar gridScrollBar: flickable.ScrollBar.vertical
 
     property alias expandDelegate: expandItemLoader.sourceComponent
     property alias expandItem: expandItemLoader.item
@@ -784,8 +789,10 @@ FocusScope {
 
         boundsBehavior: Flickable.StopAtBounds
 
-        ScrollBar.vertical: ScrollBarExt {
-            id: flickableScrollBar
+        ScrollBar.vertical: {
+            if (root.defaultScrollBar)
+                return root.defaultScrollBar.createObject() // rely on JS/QML engine's garbage collector
+            return null
         }
 
         Component.onCompleted: {
-- 
GitLab


From 0791c68e656ddf28cc4af70000785356109d2fbe Mon Sep 17 00:00:00 2001
From: Fatih Uzunoglu <fuzun54@outlook.com>
Date: Sat, 29 Mar 2025 19:48:39 +0200
Subject: [PATCH 5/5] qml: allow overriding the scroll bar in
 `BrowseHomeDisplay`

This also makes it respect the default `size` (if set in
the scroll bar).
---
 modules/gui/qt/network/qml/BrowseHomeDisplay.qml | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/modules/gui/qt/network/qml/BrowseHomeDisplay.qml b/modules/gui/qt/network/qml/BrowseHomeDisplay.qml
index 14f0e41a7ed8..37a2f3bfa261 100644
--- a/modules/gui/qt/network/qml/BrowseHomeDisplay.qml
+++ b/modules/gui/qt/network/qml/BrowseHomeDisplay.qml
@@ -50,6 +50,10 @@ FocusScope {
         { text: qsTr("Url"),        criteria: "mrl" }
     ]
 
+    property Component defaultScrollBar: Component {
+        Widgets.ScrollBarExt { }
+    }
+
     readonly property bool hasGridListMode: true
     readonly property bool isSearchable: true
 
@@ -135,7 +139,11 @@ FocusScope {
         anchors.leftMargin: root.leftPadding
         anchors.rightMargin: root.rightPadding
 
-        ScrollBar.vertical: Widgets.ScrollBarExt { }
+        ScrollBar.vertical: {
+            if (root.defaultScrollBar)
+                return root.defaultScrollBar.createObject() // rely on JS/QML engine's garbage collector
+            return null
+        }
 
         flickableDirection: Flickable.AutoFlickIfNeeded
         boundsBehavior: Flickable.StopAtBounds
-- 
GitLab