High-dpi configuration change testing

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ø <tor.arne.vestbo@qt.io>
bb10
Morten Johan Sørvig 2021-03-18 15:14:45 +01:00
parent 95d5710d7b
commit 04fd894400
4 changed files with 153 additions and 1 deletions

View File

@ -236,6 +236,38 @@ void QOffscreenBackingStore::clearHash()
QHash<WId, QOffscreenBackingStore *> 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<void*>(&QOffscreenPlatformNativeInterface::setConfiguration);
else if (resource == "configuration")
return reinterpret_cast<void*>(&QOffscreenPlatformNativeInterface::configuration);
else
return nullptr;
}
QT_END_NAMESPACE

View File

@ -51,6 +51,7 @@
#include <qscopedpointer.h>
#include <qimage.h>
#include <qjsonobject.h>
#include <qhash.h>
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

View File

@ -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<QOffscreenIntegration*>(this)));
return m_nativeInterface.get();
}

View File

@ -28,11 +28,13 @@
#include <private/qhighdpiscaling_p.h>
#include <qpa/qplatformscreen.h>
#include <qpa/qplatformnativeinterface.h>
#include <QTest>
#include <QJsonArray>
#include <QJsonObject>
#include <QJsonDocument>
#include <QStringView>
Q_LOGGING_CATEGORY(lcTests, "qt.gui.tests")
@ -45,6 +47,10 @@ private: // helpers
QGuiApplication *createStandardOffscreenApp(const QList<qreal> &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<qreal> { 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<void (*)(QJsonObject, QPlatformNativeInterface *)>(
platformNativeInterface->nativeResourceForIntegration("setConfiguration"));
setConfiguration(configuration, platformNativeInterface);
}
QJsonObject tst_QHighDpi::offscreenConfiguration()
{
Q_ASSERT(qApp->platformName() == QLatin1String("offscreen"));
QPlatformNativeInterface *platformNativeInterface = qApp->platformNativeInterface();
auto getConfiguration = reinterpret_cast<QJsonObject (*)(QPlatformNativeInterface *)>(
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<qreal> dpiValues = { 96, 96, 96};
std::unique_ptr<QGuiApplication> 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;