diff options
author | Ivan Tkachenko <me@ratijas.tk> | 2023-09-02 14:16:41 +0300 |
---|---|---|
committer | Qt Cherry-pick Bot <cherrypick_bot@qt-project.org> | 2023-09-05 17:03:29 +0000 |
commit | 51277900f3de7a3b9faaa9223f23cdaac935490b (patch) | |
tree | 12f8a8cadf64cba7245e7c56daa6699d8c590884 /src | |
parent | f02735d4514149b0c297e1e2c2f7060c2fdd4e96 (diff) |
ScrollBar: Fix visualSize being stuck without change signal
Fixes a bug that visualSizeChanged signal won't be emitted when needed,
causing listeners such as binding expression being stuck with an old
value without updates. This has caused a visual glitch with scrollbars
in KDE: they appear incorrectly sized initially, but fix themselves as
soon as scrolling starts. Needless to say, we don't use overshoot on
desktops, but that feature is also plagued by this bug.
Solution is to (1) don't assign new d->size before measuring visualArea,
and (2) don't reassign oldVisualArea, because it would override visual
size with an updated data, losing information needed for
visualAreaChange to determine whether to emit signal or not.
To optimize and avoid double-signals for visual position, existing
setPosition() method was factored out into a new private method with
an optional signal suppression flag.
See also: https://bugs.kde.org/show_bug.cgi?id=473241
Change-Id: Id0482e5b90e08e1bb31367efe86f4a9cc046c4f6
Reviewed-by: Oliver Eftevaag <oliver.eftevaag@qt.io>
(cherry picked from commit 470cc1a600ef5364fd7bee0f3f0b822ba95bab35)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
Diffstat (limited to 'src')
-rw-r--r-- | src/quicktemplates/qquickscrollbar.cpp | 29 | ||||
-rw-r--r-- | src/quicktemplates/qquickscrollbar_p_p.h | 1 |
2 files changed, 18 insertions, 12 deletions
diff --git a/src/quicktemplates/qquickscrollbar.cpp b/src/quicktemplates/qquickscrollbar.cpp index e99887f940..6e167a9314 100644 --- a/src/quicktemplates/qquickscrollbar.cpp +++ b/src/quicktemplates/qquickscrollbar.cpp @@ -409,13 +409,11 @@ void QQuickScrollBar::setSize(qreal size) size = qBound(0.0, size, 1.0); if (qFuzzyCompare(d->size, size)) return; - d->size = size; - auto oldVisualArea = d->visualArea(); - d->size = qBound(0.0, size, 1.0); + const auto oldVisualArea = d->visualArea(); + d->size = size; if (d->size + d->position > 1.0) { - setPosition(1.0 - d->size); - oldVisualArea = d->visualArea(); + d->setPosition(1.0 - d->size, false); } if (isComponentComplete()) @@ -450,15 +448,22 @@ qreal QQuickScrollBar::position() const void QQuickScrollBar::setPosition(qreal position) { Q_D(QQuickScrollBar); - if (!qt_is_finite(position) || qFuzzyCompare(d->position, position)) + d->setPosition(position); +} + +void QQuickScrollBarPrivate::setPosition(qreal newPosition, bool notifyVisualChange) +{ + Q_Q(QQuickScrollBar); + if (!qt_is_finite(newPosition) || qFuzzyCompare(position, newPosition)) return; - auto oldVisualArea = d->visualArea(); - d->position = position; - if (isComponentComplete()) - d->resizeContent(); - emit positionChanged(); - d->visualAreaChange(d->visualArea(), oldVisualArea); + auto oldVisualArea = visualArea(); + position = newPosition; + if (q->isComponentComplete()) + resizeContent(); + emit q->positionChanged(); + if (notifyVisualChange) + visualAreaChange(visualArea(), oldVisualArea); } /*! diff --git a/src/quicktemplates/qquickscrollbar_p_p.h b/src/quicktemplates/qquickscrollbar_p_p.h index cad54882d2..2a834ce71e 100644 --- a/src/quicktemplates/qquickscrollbar_p_p.h +++ b/src/quicktemplates/qquickscrollbar_p_p.h @@ -45,6 +45,7 @@ public: qreal logicalPosition(qreal position) const; + void setPosition(qreal position, bool notifyVisualChange = true); qreal snapPosition(qreal position) const; qreal positionAt(const QPointF &point) const; void setInteractive(bool interactive); |