summaryrefslogtreecommitdiff
path: root/components/controls/StyledScrollBar.qml
diff options
context:
space:
mode:
author2 * r + 2 * t <61896496+soramanew@users.noreply.github.com>2026-01-03 17:53:06 +1100
committerGitHub <noreply@github.com>2026-01-03 17:53:06 +1100
commitbdcd13222fc6edc77c779a396900ab909e7d5439 (patch)
treef9457f3c91c05ec852f974f239d06aca52a3918e /components/controls/StyledScrollBar.qml
parent[CI] chore: update flake (diff)
parentMerge branch 'caelestia-dots:main' into main (diff)
downloadcaelestia-shell-bdcd13222fc6edc77c779a396900ab909e7d5439.tar.gz
caelestia-shell-bdcd13222fc6edc77c779a396900ab909e7d5439.tar.bz2
caelestia-shell-bdcd13222fc6edc77c779a396900ab909e7d5439.zip
Merge pull request #906 from atdma/main
controlcenter: many setting panes and minor features
Diffstat (limited to 'components/controls/StyledScrollBar.qml')
-rw-r--r--components/controls/StyledScrollBar.qml96
1 files changed, 89 insertions, 7 deletions
diff --git a/components/controls/StyledScrollBar.qml b/components/controls/StyledScrollBar.qml
index fc641b5..de8b679 100644
--- a/components/controls/StyledScrollBar.qml
+++ b/components/controls/StyledScrollBar.qml
@@ -19,14 +19,51 @@ ScrollBar {
shouldBeActive = flickable.moving;
}
+ property bool _updatingFromFlickable: false
+ property bool _updatingFromUser: false
+
+ // Sync nonAnimPosition with Qt's automatic position binding
onPositionChanged: {
- if (position === nonAnimPosition)
+ if (_updatingFromUser) {
+ _updatingFromUser = false;
+ return;
+ }
+ if (position === nonAnimPosition) {
animating = false;
- else if (!animating)
+ return;
+ }
+ if (!animating && !_updatingFromFlickable && !fullMouse.pressed) {
nonAnimPosition = position;
+ }
}
- position: nonAnimPosition
+ // Sync nonAnimPosition with flickable when not animating
+ Connections {
+ target: flickable
+ function onContentYChanged() {
+ if (!animating && !fullMouse.pressed) {
+ _updatingFromFlickable = true;
+ const contentHeight = flickable.contentHeight;
+ const height = flickable.height;
+ if (contentHeight > height) {
+ nonAnimPosition = Math.max(0, Math.min(1, flickable.contentY / (contentHeight - height)));
+ } else {
+ nonAnimPosition = 0;
+ }
+ _updatingFromFlickable = false;
+ }
+ }
+ }
+
+ Component.onCompleted: {
+ if (flickable) {
+ const contentHeight = flickable.contentHeight;
+ const height = flickable.height;
+ if (contentHeight > height) {
+ nonAnimPosition = Math.max(0, Math.min(1, flickable.contentY / (contentHeight - height)));
+ }
+ }
+ }
implicitWidth: Appearance.padding.small
contentItem: StyledRect {
@@ -86,17 +123,62 @@ ScrollBar {
onPressed: event => {
root.animating = true;
- root.nonAnimPosition = Math.max(0, Math.min(1 - root.size, event.y / root.height - root.size / 2));
+ root._updatingFromUser = true;
+ const newPos = Math.max(0, Math.min(1 - root.size, event.y / root.height - root.size / 2));
+ root.nonAnimPosition = newPos;
+ // Update flickable position
+ // Map scrollbar position [0, 1-size] to contentY [0, maxContentY]
+ if (root.flickable) {
+ const contentHeight = root.flickable.contentHeight;
+ const height = root.flickable.height;
+ if (contentHeight > height) {
+ const maxContentY = contentHeight - height;
+ const maxPos = 1 - root.size;
+ const contentY = maxPos > 0 ? (newPos / maxPos) * maxContentY : 0;
+ root.flickable.contentY = Math.max(0, Math.min(maxContentY, contentY));
+ }
+ }
}
- onPositionChanged: event => root.nonAnimPosition = Math.max(0, Math.min(1 - root.size, event.y / root.height - root.size / 2))
+ onPositionChanged: event => {
+ root._updatingFromUser = true;
+ const newPos = Math.max(0, Math.min(1 - root.size, event.y / root.height - root.size / 2));
+ root.nonAnimPosition = newPos;
+ // Update flickable position
+ // Map scrollbar position [0, 1-size] to contentY [0, maxContentY]
+ if (root.flickable) {
+ const contentHeight = root.flickable.contentHeight;
+ const height = root.flickable.height;
+ if (contentHeight > height) {
+ const maxContentY = contentHeight - height;
+ const maxPos = 1 - root.size;
+ const contentY = maxPos > 0 ? (newPos / maxPos) * maxContentY : 0;
+ root.flickable.contentY = Math.max(0, Math.min(maxContentY, contentY));
+ }
+ }
+ }
function onWheel(event: WheelEvent): void {
root.animating = true;
+ root._updatingFromUser = true;
+ let newPos = root.nonAnimPosition;
if (event.angleDelta.y > 0)
- root.nonAnimPosition = Math.max(0, root.nonAnimPosition - 0.1);
+ newPos = Math.max(0, root.nonAnimPosition - 0.1);
else if (event.angleDelta.y < 0)
- root.nonAnimPosition = Math.min(1 - root.size, root.nonAnimPosition + 0.1);
+ newPos = Math.min(1 - root.size, root.nonAnimPosition + 0.1);
+ root.nonAnimPosition = newPos;
+ // Update flickable position
+ // Map scrollbar position [0, 1-size] to contentY [0, maxContentY]
+ if (root.flickable) {
+ const contentHeight = root.flickable.contentHeight;
+ const height = root.flickable.height;
+ if (contentHeight > height) {
+ const maxContentY = contentHeight - height;
+ const maxPos = 1 - root.size;
+ const contentY = maxPos > 0 ? (newPos / maxPos) * maxContentY : 0;
+ root.flickable.contentY = Math.max(0, Math.min(maxContentY, contentY));
+ }
+ }
}
}