Make tst_qwidget pass on High-DPI screens (Windows)
- Move the fuzz check introduced by 63090627220a6209652d236cf991305fbeb188b8 to a shared header for reuse. Use it in in more places to account for rounding errors introduced by odd window frame sizes when scaling is active. - Use the test widget size to ensure windows do not violate the minimum decorated window size on Windows when scaling is inactive on large monitors. Task-number: QTBUG-46615 Change-Id: Icf803a4bc2c275eadb8f98e60b08e39b2ebebedd Reviewed-by: Oliver Wolff <oliver.wolff@qt.io>
This commit is contained in:
parent
085d1335d1
commit
67c569add0
109
tests/auto/shared/highdpi.h
Normal file
109
tests/auto/shared/highdpi.h
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2019 The Qt Company Ltd.
|
||||||
|
** Contact: https://www.qt.io/licensing/
|
||||||
|
**
|
||||||
|
** This file is part of the test suite of the Qt Toolkit.
|
||||||
|
**
|
||||||
|
** $QT_BEGIN_LICENSE:GPL-EXCEPT$
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and The Qt Company. For licensing terms
|
||||||
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||||
|
** information use the contact form at https://www.qt.io/contact-us.
|
||||||
|
**
|
||||||
|
** GNU General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU
|
||||||
|
** General Public License version 3 as published by the Free Software
|
||||||
|
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||||
|
** included in the packaging of this file. Please review the following
|
||||||
|
** information to ensure the GNU General Public License requirements will
|
||||||
|
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||||
|
**
|
||||||
|
** $QT_END_LICENSE$
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef HIGHDPI_H
|
||||||
|
#define HIGHDPI_H
|
||||||
|
|
||||||
|
#include <QtCore/qbytearray.h>
|
||||||
|
#include <QtCore/qpoint.h>
|
||||||
|
#include <QtCore/qrect.h>
|
||||||
|
#include <QtCore/qsize.h>
|
||||||
|
|
||||||
|
// Helpers for comparing geometries a that may go through scaling in the
|
||||||
|
// platform plugin with fuzz (pass rounded-down device pixel ratios or
|
||||||
|
// scaling factors). Error message for use with QVERIFY2() are also provided.
|
||||||
|
|
||||||
|
class HighDpi
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
HighDpi() = delete;
|
||||||
|
HighDpi(const HighDpi &) = delete;
|
||||||
|
HighDpi &operator=(const HighDpi &) = delete;
|
||||||
|
HighDpi(HighDpi &&) = delete;
|
||||||
|
HighDpi &operator=(HighDpi &&) = delete;
|
||||||
|
~HighDpi() = delete;
|
||||||
|
|
||||||
|
static int manhattanDelta(const QPoint &p1, const QPoint p2)
|
||||||
|
{
|
||||||
|
return (p1 - p2).manhattanLength();
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool fuzzyCompare(const QPoint &p1, const QPoint p2, int fuzz)
|
||||||
|
{
|
||||||
|
return manhattanDelta(p1, p2) <= fuzz;
|
||||||
|
}
|
||||||
|
|
||||||
|
static QByteArray msgPointMismatch(const QPoint &p1, const QPoint p2)
|
||||||
|
{
|
||||||
|
return QByteArray::number(p1.x()) + ',' + QByteArray::number(p1.y())
|
||||||
|
+ " != " + QByteArray::number(p2.x()) + ',' + QByteArray::number(p2.y())
|
||||||
|
+ ", manhattanLength=" + QByteArray::number(manhattanDelta(p1, p2));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compare a size that may go through scaling in the platform plugin with fuzz.
|
||||||
|
|
||||||
|
static inline int manhattanDelta(const QSize &s1, const QSize &s2)
|
||||||
|
{
|
||||||
|
return qAbs(s1.width() - s2.width()) + qAbs(s1.height() - s2.height());
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool fuzzyCompare(const QSize &s1, const QSize &s2, int fuzz)
|
||||||
|
{
|
||||||
|
return manhattanDelta(s1, s2) <= fuzz;
|
||||||
|
}
|
||||||
|
|
||||||
|
static QByteArray msgSizeMismatch(const QSize &s1, const QSize &s2)
|
||||||
|
{
|
||||||
|
return QByteArray::number(s1.width()) + 'x' + QByteArray::number(s1.height())
|
||||||
|
+ " != " + QByteArray::number(s2.width()) + 'x' + QByteArray::number(s2.height())
|
||||||
|
+ ", manhattanLength=" + QByteArray::number(manhattanDelta(s1, s2));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compare a geometry that may go through scaling in the platform plugin with fuzz.
|
||||||
|
|
||||||
|
static inline bool fuzzyCompare(const QRect &r1, const QRect &r2, int fuzz)
|
||||||
|
{
|
||||||
|
return manhattanDelta(r1.topLeft(), r2.topLeft()) <= fuzz
|
||||||
|
&& manhattanDelta(r1.size(), r2.size()) <= fuzz;
|
||||||
|
}
|
||||||
|
|
||||||
|
static QByteArray msgRectMismatch(const QRect &r1, const QRect &r2)
|
||||||
|
{
|
||||||
|
return formatRect(r1) + " != " + formatRect(r2);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
static QByteArray formatRect(const QRect &r)
|
||||||
|
{
|
||||||
|
return QByteArray::number(r.width()) + 'x' + QByteArray::number(r.height())
|
||||||
|
+ (r.left() < 0 ? '-' : '+') + QByteArray::number(r.left())
|
||||||
|
+ (r.top() < 0 ? '-' : '+') + QByteArray::number(r.top());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // HIGHDPI_H
|
@ -26,6 +26,7 @@
|
|||||||
**
|
**
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include "../../../shared/highdpi.h"
|
||||||
|
|
||||||
#include <qboxlayout.h>
|
#include <qboxlayout.h>
|
||||||
#include <qapplication.h>
|
#include <qapplication.h>
|
||||||
@ -140,19 +141,6 @@ static QByteArray msgComparisonFailed(T v1, const char *op, T v2)
|
|||||||
return s.toLocal8Bit();
|
return s.toLocal8Bit();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compare a window position that may go through scaling in the platform plugin with fuzz.
|
|
||||||
static inline bool qFuzzyCompareWindowPosition(const QPoint &p1, const QPoint p2, int fuzz)
|
|
||||||
{
|
|
||||||
return (p1 - p2).manhattanLength() <= fuzz;
|
|
||||||
}
|
|
||||||
|
|
||||||
static QString msgPointMismatch(const QPoint &p1, const QPoint p2)
|
|
||||||
{
|
|
||||||
QString result;
|
|
||||||
QDebug(&result) << p1 << "!=" << p2 << ", manhattanLength=" << (p1 - p2).manhattanLength();
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
class tst_QWidget : public QObject
|
class tst_QWidget : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
@ -416,6 +404,7 @@ private:
|
|||||||
QPoint m_safeCursorPos;
|
QPoint m_safeCursorPos;
|
||||||
const bool m_windowsAnimationsEnabled;
|
const bool m_windowsAnimationsEnabled;
|
||||||
QTouchDevice *m_touchScreen;
|
QTouchDevice *m_touchScreen;
|
||||||
|
const int m_fuzz;
|
||||||
};
|
};
|
||||||
|
|
||||||
bool tst_QWidget::ensureScreenSize(int width, int height)
|
bool tst_QWidget::ensureScreenSize(int width, int height)
|
||||||
@ -574,6 +563,7 @@ tst_QWidget::tst_QWidget()
|
|||||||
, m_safeCursorPos(0, 0)
|
, m_safeCursorPos(0, 0)
|
||||||
, m_windowsAnimationsEnabled(windowsAnimationsEnabled())
|
, m_windowsAnimationsEnabled(windowsAnimationsEnabled())
|
||||||
, m_touchScreen(QTest::createTouchDevice())
|
, m_touchScreen(QTest::createTouchDevice())
|
||||||
|
, m_fuzz(int(QGuiApplication::primaryScreen()->devicePixelRatio()))
|
||||||
{
|
{
|
||||||
if (m_windowsAnimationsEnabled) // Disable animations which can interfere with screen grabbing in moveChild(), showAndMoveChild()
|
if (m_windowsAnimationsEnabled) // Disable animations which can interfere with screen grabbing in moveChild(), showAndMoveChild()
|
||||||
setWindowsAnimationsEnabled(false);
|
setWindowsAnimationsEnabled(false);
|
||||||
@ -2047,10 +2037,9 @@ void tst_QWidget::windowState()
|
|||||||
|
|
||||||
widget1.setWindowState(widget1.windowState() ^ Qt::WindowMaximized);
|
widget1.setWindowState(widget1.windowState() ^ Qt::WindowMaximized);
|
||||||
QTest::qWait(100);
|
QTest::qWait(100);
|
||||||
const int fuzz = int(QHighDpiScaling::factor(widget1.windowHandle()));
|
|
||||||
QVERIFY(!(widget1.windowState() & Qt::WindowMaximized));
|
QVERIFY(!(widget1.windowState() & Qt::WindowMaximized));
|
||||||
QTRY_VERIFY2(qFuzzyCompareWindowPosition(widget1.pos(), pos, fuzz),
|
QTRY_VERIFY2(HighDpi::fuzzyCompare(widget1.pos(), pos, m_fuzz),
|
||||||
qPrintable(msgPointMismatch(widget1.pos(), pos)));
|
qPrintable(HighDpi::msgPointMismatch(widget1.pos(), pos)));
|
||||||
QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowNoState);
|
QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowNoState);
|
||||||
|
|
||||||
widget1.setWindowState(Qt::WindowMinimized);
|
widget1.setWindowState(Qt::WindowMinimized);
|
||||||
@ -2071,8 +2060,8 @@ void tst_QWidget::windowState()
|
|||||||
widget1.setWindowState(widget1.windowState() ^ Qt::WindowMaximized);
|
widget1.setWindowState(widget1.windowState() ^ Qt::WindowMaximized);
|
||||||
QTest::qWait(100);
|
QTest::qWait(100);
|
||||||
QVERIFY(!(widget1.windowState() & (Qt::WindowMinimized|Qt::WindowMaximized)));
|
QVERIFY(!(widget1.windowState() & (Qt::WindowMinimized|Qt::WindowMaximized)));
|
||||||
QTRY_VERIFY2(qFuzzyCompareWindowPosition(widget1.pos(), pos, fuzz),
|
QTRY_VERIFY2(HighDpi::fuzzyCompare(widget1.pos(), pos, m_fuzz),
|
||||||
qPrintable(msgPointMismatch(widget1.pos(), pos)));
|
qPrintable(HighDpi::msgPointMismatch(widget1.pos(), pos)));
|
||||||
QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowNoState);
|
QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowNoState);
|
||||||
|
|
||||||
widget1.setWindowState(Qt::WindowFullScreen);
|
widget1.setWindowState(Qt::WindowFullScreen);
|
||||||
@ -2093,8 +2082,8 @@ void tst_QWidget::windowState()
|
|||||||
widget1.setWindowState(Qt::WindowNoState);
|
widget1.setWindowState(Qt::WindowNoState);
|
||||||
QTest::qWait(100);
|
QTest::qWait(100);
|
||||||
VERIFY_STATE(Qt::WindowNoState);
|
VERIFY_STATE(Qt::WindowNoState);
|
||||||
QTRY_VERIFY2(qFuzzyCompareWindowPosition(widget1.pos(), pos, fuzz),
|
QTRY_VERIFY2(HighDpi::fuzzyCompare(widget1.pos(), pos, m_fuzz),
|
||||||
qPrintable(msgPointMismatch(widget1.pos(), pos)));
|
qPrintable(HighDpi::msgPointMismatch(widget1.pos(), pos)));
|
||||||
QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowNoState);
|
QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowNoState);
|
||||||
|
|
||||||
widget1.setWindowState(Qt::WindowFullScreen);
|
widget1.setWindowState(Qt::WindowFullScreen);
|
||||||
@ -2127,8 +2116,8 @@ void tst_QWidget::windowState()
|
|||||||
QVERIFY(!(widget1.windowState() & stateMask));
|
QVERIFY(!(widget1.windowState() & stateMask));
|
||||||
QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowNoState);
|
QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowNoState);
|
||||||
|
|
||||||
QTRY_VERIFY2(qFuzzyCompareWindowPosition(widget1.pos(), pos, fuzz),
|
QTRY_VERIFY2(HighDpi::fuzzyCompare(widget1.pos(), pos, m_fuzz),
|
||||||
qPrintable(msgPointMismatch(widget1.pos(), pos)));
|
qPrintable(HighDpi::msgPointMismatch(widget1.pos(), pos)));
|
||||||
QTRY_COMPARE(widget1.size(), size);
|
QTRY_COMPARE(widget1.size(), size);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2321,7 +2310,7 @@ void tst_QWidget::resizeEvent()
|
|||||||
{
|
{
|
||||||
QWidget wParent;
|
QWidget wParent;
|
||||||
wParent.setWindowTitle(QLatin1String(QTest::currentTestFunction()));
|
wParent.setWindowTitle(QLatin1String(QTest::currentTestFunction()));
|
||||||
wParent.resize(200, 200);
|
wParent.resize(m_testWidgetSize);
|
||||||
ResizeWidget wChild(&wParent);
|
ResizeWidget wChild(&wParent);
|
||||||
wParent.show();
|
wParent.show();
|
||||||
QVERIFY(QTest::qWaitForWindowExposed(&wParent));
|
QVERIFY(QTest::qWaitForWindowExposed(&wParent));
|
||||||
@ -2339,7 +2328,7 @@ void tst_QWidget::resizeEvent()
|
|||||||
{
|
{
|
||||||
ResizeWidget wTopLevel;
|
ResizeWidget wTopLevel;
|
||||||
wTopLevel.setWindowTitle(QLatin1String(QTest::currentTestFunction()));
|
wTopLevel.setWindowTitle(QLatin1String(QTest::currentTestFunction()));
|
||||||
wTopLevel.resize(200, 200);
|
wTopLevel.resize(m_testWidgetSize);
|
||||||
wTopLevel.show();
|
wTopLevel.show();
|
||||||
QVERIFY(QTest::qWaitForWindowExposed(&wTopLevel));
|
QVERIFY(QTest::qWaitForWindowExposed(&wTopLevel));
|
||||||
if (m_platform == QStringLiteral("winrt"))
|
if (m_platform == QStringLiteral("winrt"))
|
||||||
@ -2377,17 +2366,20 @@ void tst_QWidget::showMinimized()
|
|||||||
#ifdef Q_OS_WINRT
|
#ifdef Q_OS_WINRT
|
||||||
QEXPECT_FAIL("", "Winrt does not support move and resize", Abort);
|
QEXPECT_FAIL("", "Winrt does not support move and resize", Abort);
|
||||||
#endif
|
#endif
|
||||||
QCOMPARE(plain.pos(), pos);
|
QVERIFY2(HighDpi::fuzzyCompare(plain.pos(), pos, m_fuzz),
|
||||||
|
qPrintable(HighDpi::msgPointMismatch(plain.pos(), pos)));
|
||||||
|
|
||||||
plain.showNormal();
|
plain.showNormal();
|
||||||
QVERIFY(!plain.isMinimized());
|
QVERIFY(!plain.isMinimized());
|
||||||
QVERIFY(plain.isVisible());
|
QVERIFY(plain.isVisible());
|
||||||
QCOMPARE(plain.pos(), pos);
|
QVERIFY2(HighDpi::fuzzyCompare(plain.pos(), pos, m_fuzz),
|
||||||
|
qPrintable(HighDpi::msgPointMismatch(plain.pos(), pos)));
|
||||||
|
|
||||||
plain.showMinimized();
|
plain.showMinimized();
|
||||||
QVERIFY(plain.isMinimized());
|
QVERIFY(plain.isMinimized());
|
||||||
QVERIFY(plain.isVisible());
|
QVERIFY(plain.isVisible());
|
||||||
QCOMPARE(plain.pos(), pos);
|
QVERIFY2(HighDpi::fuzzyCompare(plain.pos(), pos, m_fuzz),
|
||||||
|
qPrintable(HighDpi::msgPointMismatch(plain.pos(), pos)));
|
||||||
|
|
||||||
plain.hide();
|
plain.hide();
|
||||||
QVERIFY(plain.isMinimized());
|
QVERIFY(plain.isMinimized());
|
||||||
@ -2779,7 +2771,9 @@ void tst_QWidget::setGeometry()
|
|||||||
tlw.setWindowTitle(QLatin1String(QTest::currentTestFunction()));
|
tlw.setWindowTitle(QLatin1String(QTest::currentTestFunction()));
|
||||||
QWidget child(&tlw);
|
QWidget child(&tlw);
|
||||||
|
|
||||||
QRect tr(100,100,200,200);
|
const QPoint topLeft = QGuiApplication::primaryScreen()->availableGeometry().topLeft();
|
||||||
|
const QSize initialSize = 2 * m_testWidgetSize;
|
||||||
|
QRect tr(topLeft + QPoint(100,100), initialSize);
|
||||||
QRect cr(50,50,50,50);
|
QRect cr(50,50,50,50);
|
||||||
tlw.setGeometry(tr);
|
tlw.setGeometry(tr);
|
||||||
child.setGeometry(cr);
|
child.setGeometry(cr);
|
||||||
@ -2790,8 +2784,7 @@ void tst_QWidget::setGeometry()
|
|||||||
QCOMPARE(child.geometry(), cr);
|
QCOMPARE(child.geometry(), cr);
|
||||||
|
|
||||||
tlw.setParent(nullptr, Qt::Window|Qt::FramelessWindowHint);
|
tlw.setParent(nullptr, Qt::Window|Qt::FramelessWindowHint);
|
||||||
tr = QRect(0,0,100,100);
|
tr = QRect(topLeft, initialSize / 2);
|
||||||
tr.moveTopLeft(QGuiApplication::primaryScreen()->availableGeometry().topLeft());
|
|
||||||
tlw.setGeometry(tr);
|
tlw.setGeometry(tr);
|
||||||
QCOMPARE(tlw.geometry(), tr);
|
QCOMPARE(tlw.geometry(), tr);
|
||||||
tlw.showNormal();
|
tlw.showNormal();
|
||||||
@ -3263,7 +3256,8 @@ void tst_QWidget::saveRestoreGeometry()
|
|||||||
|
|
||||||
if (m_platform == QStringLiteral("winrt"))
|
if (m_platform == QStringLiteral("winrt"))
|
||||||
QEXPECT_FAIL("", "WinRT does not support move/resize", Abort);
|
QEXPECT_FAIL("", "WinRT does not support move/resize", Abort);
|
||||||
QTRY_COMPARE(widget.pos(), position);
|
QTRY_VERIFY2(HighDpi::fuzzyCompare(widget.pos(), position, m_fuzz),
|
||||||
|
qPrintable(HighDpi::msgPointMismatch(widget.pos(), position)));
|
||||||
QCOMPARE(widget.size(), size);
|
QCOMPARE(widget.size(), size);
|
||||||
savedGeometry = widget.saveGeometry();
|
savedGeometry = widget.saveGeometry();
|
||||||
}
|
}
|
||||||
@ -3291,10 +3285,12 @@ void tst_QWidget::saveRestoreGeometry()
|
|||||||
QVERIFY(QTest::qWaitForWindowExposed(&widget));
|
QVERIFY(QTest::qWaitForWindowExposed(&widget));
|
||||||
QApplication::processEvents();
|
QApplication::processEvents();
|
||||||
|
|
||||||
QTRY_COMPARE(widget.pos(), position);
|
QVERIFY2(HighDpi::fuzzyCompare(widget.pos(), position, m_fuzz),
|
||||||
|
qPrintable(HighDpi::msgPointMismatch(widget.pos(), position)));
|
||||||
QCOMPARE(widget.size(), size);
|
QCOMPARE(widget.size(), size);
|
||||||
widget.show();
|
widget.show();
|
||||||
QCOMPARE(widget.pos(), position);
|
QVERIFY2(HighDpi::fuzzyCompare(widget.pos(), position, m_fuzz),
|
||||||
|
qPrintable(HighDpi::msgPointMismatch(widget.pos(), position)));
|
||||||
QCOMPARE(widget.size(), size);
|
QCOMPARE(widget.size(), size);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3408,6 +3404,9 @@ void tst_QWidget::restoreVersion1Geometry()
|
|||||||
QFETCH(QSize, expectedSize);
|
QFETCH(QSize, expectedSize);
|
||||||
QFETCH(QRect, expectedNormalGeometry);
|
QFETCH(QRect, expectedNormalGeometry);
|
||||||
|
|
||||||
|
if (m_platform == QLatin1String("windows") && QGuiApplication::primaryScreen()->geometry().width() > 2000)
|
||||||
|
QSKIP("Skipping due to minimum decorated window size on Windows");
|
||||||
|
|
||||||
// WindowActive is uninteresting for this test
|
// WindowActive is uninteresting for this test
|
||||||
const Qt::WindowStates WindowStateMask = Qt::WindowFullScreen | Qt::WindowMaximized | Qt::WindowMinimized;
|
const Qt::WindowStates WindowStateMask = Qt::WindowFullScreen | Qt::WindowMaximized | Qt::WindowMinimized;
|
||||||
|
|
||||||
@ -4988,7 +4987,8 @@ void tst_QWidget::windowMoveResize()
|
|||||||
widget.showNormal();
|
widget.showNormal();
|
||||||
|
|
||||||
QTest::qWait(10);
|
QTest::qWait(10);
|
||||||
QTRY_COMPARE(widget.pos(), rect.topLeft());
|
QTRY_VERIFY2(HighDpi::fuzzyCompare(widget.pos(), rect.topLeft(), m_fuzz),
|
||||||
|
qPrintable(HighDpi::msgPointMismatch(widget.pos(), rect.topLeft())));
|
||||||
// Windows: Minimum size of decorated windows.
|
// Windows: Minimum size of decorated windows.
|
||||||
const bool expectResizeFail = (!windowFlags && (rect.width() < 160 || rect.height() < 40))
|
const bool expectResizeFail = (!windowFlags && (rect.width() < 160 || rect.height() < 40))
|
||||||
&& m_platform == QStringLiteral("windows");
|
&& m_platform == QStringLiteral("windows");
|
||||||
|
Loading…
x
Reference in New Issue
Block a user