Update window geometry when QWindow::m{in|ax}imumSize is updated

More specifically, if either minimum or maximum size are updated, make
sure that the current window geometry is updated so that it is within
the minimum and maximum sizes.

Previously, these constraints was only respected by the window manager
when the user resized the window.

For widgets this already worked, because a top-level widget will take
care of respecting these constraints if they are changed.

Since QWindow::setMinimumSize and QWindow::setMaximumSize started to
share so many common things, a new function (setMinOrMaxSize_helper())
is added.

Task-number: QTBUG-102771
Change-Id: Ia4b2680dcf865f84a3cf6424187f9a6036b76386
Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
This commit is contained in:
Jan Arve Sæther 2022-05-13 11:01:43 +02:00
parent e57ab1b454
commit e7477e8934
3 changed files with 51 additions and 22 deletions

View File

@ -567,6 +567,36 @@ QRectF QWindowPrivate::closestAcceptableGeometry(const QRectF &rect) const
return QRectF();
}
void QWindowPrivate::setMinOrMaxSize(QSize *oldSizeMember, const QSize &size,
std::function<void()> funcWidthChanged,
std::function<void()> funcHeightChanged)
{
Q_Q(QWindow);
Q_ASSERT(oldSizeMember);
Q_ASSERT(funcWidthChanged && funcHeightChanged);
const QSize adjustedSize =
size.expandedTo(QSize(0, 0)).boundedTo(QSize(QWINDOWSIZE_MAX, QWINDOWSIZE_MAX));
if (*oldSizeMember == adjustedSize)
return;
const bool widthChanged = adjustedSize.width() != oldSizeMember->width();
const bool heightChanged = adjustedSize.height() != oldSizeMember->height();
*oldSizeMember = adjustedSize;
if (platformWindow && q->isTopLevel())
platformWindow->propagateSizeHints();
if (widthChanged)
funcWidthChanged();
if (heightChanged)
funcHeightChanged();
// resize window if current size is outside of min and max limits
if (minimumSize.width() <= maximumSize.width()
|| minimumSize.height() <= maximumSize.height()) {
q->resize(q->geometry().size().expandedTo(minimumSize).boundedTo(maximumSize));
}
}
/*!
Sets the \a surfaceType of the window.
@ -1531,17 +1561,9 @@ QSize QWindow::sizeIncrement() const
void QWindow::setMinimumSize(const QSize &size)
{
Q_D(QWindow);
QSize adjustedSize = QSize(qBound(0, size.width(), QWINDOWSIZE_MAX), qBound(0, size.height(), QWINDOWSIZE_MAX));
if (d->minimumSize == adjustedSize)
return;
QSize oldSize = d->minimumSize;
d->minimumSize = adjustedSize;
if (d->platformWindow && isTopLevel())
d->platformWindow->propagateSizeHints();
if (d->minimumSize.width() != oldSize.width())
emit minimumWidthChanged(d->minimumSize.width());
if (d->minimumSize.height() != oldSize.height())
emit minimumHeightChanged(d->minimumSize.height());
d->setMinOrMaxSize(
&d->minimumSize, size, [=]() { emit minimumWidthChanged(d->minimumSize.width()); },
[=]() { emit minimumHeightChanged(d->minimumSize.height()); });
}
/*!
@ -1618,17 +1640,9 @@ void QWindow::setMinimumHeight(int h)
void QWindow::setMaximumSize(const QSize &size)
{
Q_D(QWindow);
QSize adjustedSize = QSize(qBound(0, size.width(), QWINDOWSIZE_MAX), qBound(0, size.height(), QWINDOWSIZE_MAX));
if (d->maximumSize == adjustedSize)
return;
QSize oldSize = d->maximumSize;
d->maximumSize = adjustedSize;
if (d->platformWindow && isTopLevel())
d->platformWindow->propagateSizeHints();
if (d->maximumSize.width() != oldSize.width())
emit maximumWidthChanged(d->maximumSize.width());
if (d->maximumSize.height() != oldSize.height())
emit maximumHeightChanged(d->maximumSize.height());
d->setMinOrMaxSize(
&d->maximumSize, size, [=]() { emit maximumWidthChanged(d->maximumSize.width()); },
[=]() { emit maximumHeightChanged(d->maximumSize.height()); });
}
/*!

View File

@ -73,6 +73,10 @@ public:
virtual void clearFocusObject();
virtual QRectF closestAcceptableGeometry(const QRectF &rect) const;
void setMinOrMaxSize(QSize *oldSizeMember, const QSize &size,
std::function<void()> funcWidthChanged,
std::function<void()> funcHeightChanged);
virtual void processSafeAreaMarginsChanged() {}
virtual bool participatesInLastWindowClosed() const;

View File

@ -1610,6 +1610,17 @@ void tst_QWindow::sizes()
QCOMPARE(minimumHeightSpy.count(), 1);
QCOMPARE(maximumWidthSpy.count(), 1);
QCOMPARE(maximumHeightSpy.count(), 1);
// test if min and max limits will change the size
QVERIFY(window.minimumWidth() < 50 && window.maximumWidth() > 80);
QVERIFY(window.minimumHeight() < 50 && window.maximumHeight() > 80);
window.resize(50, 50);
QCOMPARE(window.size(), QSize(50, 50));
window.setMinimumSize(QSize(60, 60));
QCOMPARE(window.size(), QSize(60, 60));
window.resize(80, 80);
window.setMaximumSize(QSize(70, 70));
QCOMPARE(window.size(), QSize(70, 70));
}
class CloseOnCloseEventWindow : public QWindow