From 04fd894400325fc26af739ff289c3f457acdb41d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= Date: Thu, 18 Mar 2021 15:14:45 +0100 Subject: [PATCH] High-dpi configuration change testing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Export configuration() and setConfiguration() from the offscreen platform plugin using QPlatformNativeInterface. tst_qighdpi can then resolve and make use of them since it always uses the offscreen platform plugin. Add screenDpiChange() auto test. Change-Id: I459b4df5d94ec4991234a346e3a94618cb3485e9 Reviewed-by: Tor Arne Vestbø --- .../platforms/offscreen/qoffscreencommon.cpp | 32 +++++ .../platforms/offscreen/qoffscreencommon.h | 9 ++ .../offscreen/qoffscreenintegration.cpp | 2 +- .../auto/gui/kernel/qhighdpi/tst_qhighdpi.cpp | 111 ++++++++++++++++++ 4 files changed, 153 insertions(+), 1 deletion(-) diff --git a/src/plugins/platforms/offscreen/qoffscreencommon.cpp b/src/plugins/platforms/offscreen/qoffscreencommon.cpp index 29e2cc417d..f485b4eed8 100644 --- a/src/plugins/platforms/offscreen/qoffscreencommon.cpp +++ b/src/plugins/platforms/offscreen/qoffscreencommon.cpp @@ -236,6 +236,38 @@ void QOffscreenBackingStore::clearHash() QHash QOffscreenBackingStore::m_backingStoreForWinIdHash; +QOffscreenPlatformNativeInterface::QOffscreenPlatformNativeInterface(QOffscreenIntegration *integration) + : m_integration(integration) +{ + +} + QOffscreenPlatformNativeInterface::~QOffscreenPlatformNativeInterface() = default; +/* + Set platform configuration, e.g. screen configuration +*/ +void QOffscreenPlatformNativeInterface::setConfiguration(const QJsonObject &configuration, QOffscreenPlatformNativeInterface *iface) +{ + iface->m_integration->setConfiguration(configuration); +} + +/* + Get the current platform configuration +*/ +QJsonObject QOffscreenPlatformNativeInterface::configuration(QOffscreenPlatformNativeInterface *iface) +{ + return iface->m_integration->configuration(); +} + +void *QOffscreenPlatformNativeInterface::nativeResourceForIntegration(const QByteArray &resource) +{ + if (resource == "setConfiguration") + return reinterpret_cast(&QOffscreenPlatformNativeInterface::setConfiguration); + else if (resource == "configuration") + return reinterpret_cast(&QOffscreenPlatformNativeInterface::configuration); + else + return nullptr; +} + QT_END_NAMESPACE diff --git a/src/plugins/platforms/offscreen/qoffscreencommon.h b/src/plugins/platforms/offscreen/qoffscreencommon.h index 7f92c5b4d9..d0edfcc48b 100644 --- a/src/plugins/platforms/offscreen/qoffscreencommon.h +++ b/src/plugins/platforms/offscreen/qoffscreencommon.h @@ -51,6 +51,7 @@ #include #include +#include #include QT_BEGIN_NAMESPACE @@ -120,7 +121,15 @@ private: class QOffscreenPlatformNativeInterface : public QPlatformNativeInterface { public: + QOffscreenPlatformNativeInterface(QOffscreenIntegration *integration); ~QOffscreenPlatformNativeInterface(); + + static void setConfiguration(const QJsonObject &configuration, QOffscreenPlatformNativeInterface *iface); + static QJsonObject configuration(QOffscreenPlatformNativeInterface *iface); + + void *nativeResourceForIntegration(const QByteArray &resource) override; +private: + QOffscreenIntegration *m_integration; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/offscreen/qoffscreenintegration.cpp b/src/plugins/platforms/offscreen/qoffscreenintegration.cpp index a8504316d8..2613a42755 100644 --- a/src/plugins/platforms/offscreen/qoffscreenintegration.cpp +++ b/src/plugins/platforms/offscreen/qoffscreenintegration.cpp @@ -388,7 +388,7 @@ QAbstractEventDispatcher *QOffscreenIntegration::createEventDispatcher() const QPlatformNativeInterface *QOffscreenIntegration::nativeInterface() const { if (!m_nativeInterface) - m_nativeInterface.reset(new QOffscreenPlatformNativeInterface); + m_nativeInterface.reset(new QOffscreenPlatformNativeInterface(const_cast(this))); return m_nativeInterface.get(); } diff --git a/tests/auto/gui/kernel/qhighdpi/tst_qhighdpi.cpp b/tests/auto/gui/kernel/qhighdpi/tst_qhighdpi.cpp index f0b1cab41a..b732954230 100644 --- a/tests/auto/gui/kernel/qhighdpi/tst_qhighdpi.cpp +++ b/tests/auto/gui/kernel/qhighdpi/tst_qhighdpi.cpp @@ -28,11 +28,13 @@ #include #include +#include #include #include #include #include +#include Q_LOGGING_CATEGORY(lcTests, "qt.gui.tests") @@ -45,6 +47,10 @@ private: // helpers QGuiApplication *createStandardOffscreenApp(const QList &dpiValues); QGuiApplication *createStandardOffscreenApp(const QJsonArray &screens); static void standardScreenDpiTestData(); + + static void setOffscreenConfiguration(const QJsonObject &configuration); + static QJsonObject offscreenConfiguration(); + private slots: void cleanup(); void qhighdpiscaling_data(); @@ -53,6 +59,7 @@ private slots: void noscreens(); void screenDpiAndDpr_data(); void screenDpiAndDpr(); + void screenDpiChange(); void environment_QT_SCALE_FACTOR(); void environment_QT_SCREEN_SCALE_FACTORS_data(); void environment_QT_SCREEN_SCALE_FACTORS(); @@ -178,6 +185,83 @@ void tst_QHighDpi::standardScreenDpiTestData() QTest::newRow("240-252-360") << QList { 400./160 * 96, 420./160 * 96, 600./160 * 96 }; } +void tst_QHighDpi::setOffscreenConfiguration(const QJsonObject &configuration) +{ + Q_ASSERT(qApp->platformName() == QLatin1String("offscreen")); + QPlatformNativeInterface *platformNativeInterface = qApp->platformNativeInterface(); + auto setConfiguration = reinterpret_cast( + platformNativeInterface->nativeResourceForIntegration("setConfiguration")); + setConfiguration(configuration, platformNativeInterface); +} + +QJsonObject tst_QHighDpi::offscreenConfiguration() +{ + Q_ASSERT(qApp->platformName() == QLatin1String("offscreen")); + QPlatformNativeInterface *platformNativeInterface = qApp->platformNativeInterface(); + auto getConfiguration = reinterpret_cast( + platformNativeInterface->nativeResourceForIntegration("configuration")); + return getConfiguration(platformNativeInterface); +} + +// JsonValueRef implements support for mutating nested JSON structures, e.g. +// +// JsonValueRef::get(&config)["screens"][0]["logicalDpi"] = 192 +// +class JsonValueRef { +public: + static JsonValueRef get(QJsonValue *value) { + return JsonValueRef(value); + } + + JsonValueRef(QJsonValue *value) + : m_value(value) { } + + JsonValueRef(QJsonValue *value, JsonValueRef *parent, QString key) + : m_value(value), m_parent(parent), m_key(key) { } + + JsonValueRef(QJsonValue *value, JsonValueRef *parent, int index) + : m_value(value), m_parent(parent), m_index(index) { } + + ~JsonValueRef() { + if (m_parent) { + if (!m_key.isNull()) { + QJsonObject parentObject = m_parent->m_value->toObject(); + parentObject[m_key] = *m_value; + *m_parent->m_value = parentObject; + } else if (m_index > -1) { + QJsonArray parentArray = m_parent->m_value->toArray(); + parentArray[m_index] = *m_value; + *m_parent->m_value = parentArray; + } + delete m_value; // owned if we have a parent, see operator[] + } + } + + JsonValueRef operator[](const char *str) { + QString key = QString::fromUtf8(str); + return JsonValueRef(new QJsonValue((*m_value)[key]), this, key); + } + + JsonValueRef operator[](int index) { + return JsonValueRef(new QJsonValue((*m_value)[index]), this, index); + } + + void operator=(int value) { + *m_value = QJsonValue(value); + } + + void operator=(const char *str) { + *m_value = QJsonValue(QString(str)); + } + +private: + Q_DISABLE_COPY(JsonValueRef); + QJsonValue *m_value = nullptr; + JsonValueRef *m_parent = nullptr; + QString m_key; + int m_index = -1; +}; + void tst_QHighDpi::cleanup() { // Some test functions set environment variables. Unset them here, @@ -233,6 +317,33 @@ void tst_QHighDpi::screenDpiAndDpr() } } +void tst_QHighDpi::screenDpiChange() +{ + QList dpiValues = { 96, 96, 96}; + std::unique_ptr app(createStandardOffscreenApp(dpiValues)); + + QCOMPARE(app->devicePixelRatio(), 1); + + // Set new DPI + int newDpi = 192; + QJsonValue config = offscreenConfiguration(); + JsonValueRef::get(&config)["screens"][0]["logicalDpi"] = newDpi; + JsonValueRef::get(&config)["screens"][1]["logicalDpi"] = newDpi; + JsonValueRef::get(&config)["screens"][2]["logicalDpi"] = newDpi; + setOffscreenConfiguration(config.toObject()); + + // TODO check events + + // Verify that the new DPI is in use + for (QScreen *screen : app->screens()) { + QCOMPARE(screen->devicePixelRatio(), newDpi / standardBaseDpi); + QCOMPARE(screen->logicalDotsPerInch(), newDpi / screen->devicePixelRatio()); + QWindow window(screen); + QCOMPARE(window.devicePixelRatio(), screen->devicePixelRatio()); + } + QCOMPARE(app->devicePixelRatio(), newDpi / standardBaseDpi); +} + void tst_QHighDpi::environment_QT_SCALE_FACTOR() { qreal factor = 3.1415;