summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKonstantin Ritt <ritt.ks@gmail.com>2019-09-11 21:54:53 +0300
committerKonstantin Ritt <ritt.ks@gmail.com>2019-09-19 11:36:26 +0000
commit6815f353e5a73c0dcf39fbfc91c6a2c1b0784324 (patch)
tree27681102f10ef27f0cb96ca4e39f026d1a0e6f87
parenta89c3bc67ea6c76bfc89d64f235ebf5cb4b0fca4 (diff)
TextArea: prevent changing size of background recursively
When the x/y position of background depends on the height/width of background and these values are not constant, the if statement in the method resizeBackground() will always pass. And since `resizingBackground` guard wasn't checked, any geometry change will always call resizeBackground() and then call themself recursively (via the change listener), that means the height/width of background will always be reset, no matter what value you set. Another part of the issue was in determining the extra bits too late: in case the background gets parented by the flickable, the new child caused the flickable to re-calculate its metrics and thus resize the background *prior* to remembering if it has w/h set. As a side effect, this fix also brings the possibility to reset previously set w/h to get the default background sizing behavior. Inspired by da06da57002b64cf4bcde0ca708b3275a5f919ae [ChangeLog][QtQuick][QQuickTextArea] prevent changing size of background recursively in construction Fixes: QTBUG-76369 Change-Id: Ide51ec1ebab63605ae3bfcc10a76a28be960ef36 Reviewed-by: Mitch Curtis <mitch.curtis@qt.io>
-rw-r--r--src/quicktemplates2/qquicktextarea.cpp21
-rw-r--r--tests/auto/controls/data/tst_textarea.qml68
2 files changed, 82 insertions, 7 deletions
diff --git a/src/quicktemplates2/qquicktextarea.cpp b/src/quicktemplates2/qquicktextarea.cpp
index 7fdc8f0a..f7b8969c 100644
--- a/src/quicktemplates2/qquicktextarea.cpp
+++ b/src/quicktemplates2/qquicktextarea.cpp
@@ -435,9 +435,16 @@ void QQuickTextAreaPrivate::resizeFlickableContent()
void QQuickTextAreaPrivate::itemGeometryChanged(QQuickItem *item, QQuickGeometryChange change, const QRectF &diff)
{
- Q_UNUSED(item);
- Q_UNUSED(change);
Q_UNUSED(diff);
+ if (!resizingBackground && item == background) {
+ QQuickItemPrivate *p = QQuickItemPrivate::get(item);
+ // Only set hasBackgroundWidth/Height if it was a width/height change,
+ // otherwise we're prevented from setting a width/height in the future.
+ if (change.widthChange())
+ extra.value().hasBackgroundWidth = p->widthValid;
+ if (change.heightChange())
+ extra.value().hasBackgroundHeight = p->heightValid;
+ }
if (flickable)
resizeFlickableControl();
@@ -627,17 +634,17 @@ void QQuickTextArea::setBackground(QQuickItem *background)
d->background = background;
if (background) {
+ QQuickItemPrivate *p = QQuickItemPrivate::get(background);
+ if (p->widthValid || p->heightValid) {
+ d->extra.value().hasBackgroundWidth = p->widthValid;
+ d->extra.value().hasBackgroundHeight = p->heightValid;
+ }
if (d->flickable)
background->setParentItem(d->flickable);
else
background->setParentItem(this);
if (qFuzzyIsNull(background->z()))
background->setZ(-1);
- QQuickItemPrivate *p = QQuickItemPrivate::get(background);
- if (p->widthValid || p->heightValid) {
- d->extra.value().hasBackgroundWidth = p->widthValid;
- d->extra.value().hasBackgroundHeight = p->heightValid;
- }
if (isComponentComplete())
d->resizeBackground();
QQuickControlPrivate::addImplicitSizeListener(background, d, QQuickControlPrivate::ImplicitSizeChanges | QQuickItemPrivate::Geometry);
diff --git a/tests/auto/controls/data/tst_textarea.qml b/tests/auto/controls/data/tst_textarea.qml
index ee40c9b7..1e455ffc 100644
--- a/tests/auto/controls/data/tst_textarea.qml
+++ b/tests/auto/controls/data/tst_textarea.qml
@@ -688,4 +688,72 @@ TestCase {
compare(control.background.width, 100)
compare(control.background.height, 100)
}
+
+ // QTBUG-76369
+ Component {
+ id: testResizeBackground
+ Item {
+ width: 200
+ height: 200
+ property alias textArea: textArea
+ ScrollView {
+ anchors.fill: parent
+ ScrollBar.horizontal.policy: ScrollBar.AlwaysOff
+ TextArea {
+ id: textArea
+ // workaround test failing due to default insets on Imagine
+ topInset: undefined
+ leftInset: undefined
+ rightInset: undefined
+ bottomInset: undefined
+ wrapMode : TextEdit.WordWrap
+ readOnly: false
+ selectByMouse: true
+ focus: true
+ text: "test message"
+
+ background: Rectangle {
+ y: parent.height - height - textArea.bottomPadding / 2
+ implicitWidth: 120
+ height: textArea.activeFocus ? 2 : 1
+ }
+ }
+ }
+ }
+ }
+
+ function test_resize_background() {
+ var control = createTemporaryObject(testResizeBackground, testCase)
+
+ compare(control.textArea.background.width, control.width)
+ compare(control.textArea.background.height, 1)
+ control.width = 400
+ control.height = 400
+ compare(control.textArea.background.width, control.width)
+ compare(control.textArea.background.height, 1)
+ control.width = 200
+ control.height = 200
+ compare(control.textArea.background.width, control.width)
+ compare(control.textArea.background.height, 1)
+
+ // hasBackgroundWidth=true
+ control.textArea.background.width = 1
+ compare(control.textArea.background.width, 1)
+ compare(control.textArea.background.height, 1)
+ control.width = 400
+ control.height = 400
+ compare(control.textArea.background.width, 1)
+ compare(control.textArea.background.height, 1)
+ // hasBackgroundHeight=false
+ control.textArea.background.height = undefined
+ compare(control.textArea.background.width, 1)
+ compare(control.textArea.background.height, 0)
+ control.textArea.background.y = 0
+ compare(control.textArea.background.width, 1)
+ compare(control.textArea.background.height, control.height)
+ control.width = 200
+ control.height = 200
+ compare(control.textArea.background.width, 1)
+ compare(control.textArea.background.height, control.height)
+ }
}