From f4a66e5c4c4be97a7511b372930e20f330ea0813 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= Date: Mon, 3 Feb 2020 23:03:29 +0100 Subject: QPA offscreen: make platform plugin configurable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add ability to load a json config file containing screen configuration at startup. The config file location is specified using platform options: -platform offscfreen:configfile=/path/to/file Config file format example: { “screens”: [ { "name", "screen-1", "x", 0, "y", 0, "width", 640, "height", 480, "dpi", 96, "dpr", 1, }, … ] } Change-Id: Iac21aaafa6d0f361bdd6f6e9168b7e68db6ae011 Reviewed-by: Paul Olav Tvete Reviewed-by: Friedemann Kleint --- src/plugins/platforms/offscreen/main.cpp | 3 +- .../platforms/offscreen/qoffscreencommon.cpp | 11 +- src/plugins/platforms/offscreen/qoffscreencommon.h | 13 ++- .../platforms/offscreen/qoffscreenintegration.cpp | 112 +++++++++++++++++++-- .../platforms/offscreen/qoffscreenintegration.h | 6 +- .../platforms/offscreen/qoffscreenwindow.cpp | 16 +-- src/plugins/platforms/offscreen/qoffscreenwindow.h | 3 +- 7 files changed, 144 insertions(+), 20 deletions(-) (limited to 'src/plugins/platforms') diff --git a/src/plugins/platforms/offscreen/main.cpp b/src/plugins/platforms/offscreen/main.cpp index f364d9f004..6b696ed073 100644 --- a/src/plugins/platforms/offscreen/main.cpp +++ b/src/plugins/platforms/offscreen/main.cpp @@ -53,9 +53,8 @@ public: QPlatformIntegration *QOffscreenIntegrationPlugin::create(const QString& system, const QStringList& paramList) { - Q_UNUSED(paramList); if (!system.compare(QLatin1String("offscreen"), Qt::CaseInsensitive)) - return QOffscreenIntegration::createOffscreenIntegration(); + return QOffscreenIntegration::createOffscreenIntegration(paramList); return nullptr; } diff --git a/src/plugins/platforms/offscreen/qoffscreencommon.cpp b/src/plugins/platforms/offscreen/qoffscreencommon.cpp index de75a3e012..3d02721869 100644 --- a/src/plugins/platforms/offscreen/qoffscreencommon.cpp +++ b/src/plugins/platforms/offscreen/qoffscreencommon.cpp @@ -38,8 +38,10 @@ ****************************************************************************/ #include "qoffscreencommon.h" +#include "qoffscreenintegration.h" #include "qoffscreenwindow.h" + #include #include @@ -50,6 +52,12 @@ QT_BEGIN_NAMESPACE QPlatformWindow *QOffscreenScreen::windowContainingCursor = nullptr; + +QList QOffscreenScreen::virtualSiblings() const +{ + return m_integration->screens(); +} + class QOffscreenCursor : public QPlatformCursor { public: @@ -93,9 +101,10 @@ private: QPoint m_pos; }; -QOffscreenScreen::QOffscreenScreen() +QOffscreenScreen::QOffscreenScreen(const QOffscreenIntegration *integration) : m_geometry(0, 0, 800, 600) , m_cursor(new QOffscreenCursor) + , m_integration(integration) { } diff --git a/src/plugins/platforms/offscreen/qoffscreencommon.h b/src/plugins/platforms/offscreen/qoffscreencommon.h index f4f0142911..abb641fbbc 100644 --- a/src/plugins/platforms/offscreen/qoffscreencommon.h +++ b/src/plugins/platforms/offscreen/qoffscreencommon.h @@ -54,23 +54,34 @@ QT_BEGIN_NAMESPACE +class QOffscreenIntegration; class QOffscreenScreen : public QPlatformScreen { public: - QOffscreenScreen(); + QOffscreenScreen(const QOffscreenIntegration *integration); QRect geometry() const override { return m_geometry; } int depth() const override { return 32; } QImage::Format format() const override { return QImage::Format_RGB32; } + QDpi logicalDpi() const override { return QDpi(m_logicalDpi, m_logicalDpi); } + QDpi logicalBaseDpi() const override { return QDpi(m_logicalBaseDpi, m_logicalBaseDpi); } + qreal devicePixelRatio() const override { return m_dpr; } + QString name() const override { return m_name; } QPlatformCursor *cursor() const override { return m_cursor.data(); } + QList virtualSiblings() const override; QPixmap grabWindow(WId window, int x, int y, int width, int height) const override; static QPlatformWindow *windowContainingCursor; public: + QString m_name; QRect m_geometry; + int m_logicalDpi = 96; + int m_logicalBaseDpi= 96; + qreal m_dpr = 1; QScopedPointer m_cursor; + const QOffscreenIntegration *m_integration; }; #if QT_CONFIG(draganddrop) diff --git a/src/plugins/platforms/offscreen/qoffscreenintegration.cpp b/src/plugins/platforms/offscreen/qoffscreenintegration.cpp index 811e025f62..c9f97ce46a 100644 --- a/src/plugins/platforms/offscreen/qoffscreenintegration.cpp +++ b/src/plugins/platforms/offscreen/qoffscreenintegration.cpp @@ -54,6 +54,11 @@ #include #endif +#include +#include +#include +#include +#include #include #include #include @@ -104,14 +109,98 @@ QOffscreenIntegration::QOffscreenIntegration() m_drag.reset(new QOffscreenDrag); #endif m_services.reset(new QPlatformServices); - - QWindowSystemInterface::handleScreenAdded(new QOffscreenScreen); } QOffscreenIntegration::~QOffscreenIntegration() { } +/* + The offscren platform plugin is configurable with a JSON configuration + file. Write the config to disk and pass the file path as a platform argument: + + ./myapp -platform offscreen:configfile=/path/to/config.json + + The supported top-level config keys are: + { + "synchronousWindowSystemEvents": + "windowFrameMargins": , + "screens": [], + } + + Screen: + { + "name" : string, + "x": int, + "y": int, + "width": int, + "height": int, + "logicalDpi": int, + "logicalBaseDpi": int, + "dpr": double, + } +*/ +void QOffscreenIntegration::configure(const QStringList& paramList) +{ + // Use config file configuring platform plugin, if one was specified + bool hasConfigFile = false; + QString configFilePath; + for (const QString ¶m : paramList) { + // Look for "configfile=/path/to/file/" + QString configPrefix(QLatin1String("configfile=")); + if (param.startsWith(configPrefix)) { + hasConfigFile = true; + configFilePath= param.mid(configPrefix.length()); + } + } + + // Create the default screen if there was no config file + if (!hasConfigFile) { + QOffscreenScreen *offscreenScreen = new QOffscreenScreen(this); + m_screens.append(offscreenScreen); + QWindowSystemInterface::handleScreenAdded(offscreenScreen); + return; + } + + // Read config file + if (configFilePath.isEmpty()) + qFatal("Missing file path for -configfile platform option"); + QFile configFile(configFilePath); + if (!configFile.exists()) + qFatal("Could not find platform config file %s", qPrintable(configFilePath)); + if (!configFile.open(QIODevice::ReadOnly)) + qFatal("Could not open platform config file for reading %s, %s", qPrintable(configFilePath), qPrintable(configFile.errorString())); + + QByteArray json = configFile.readAll(); + QJsonParseError error; + QJsonDocument config = QJsonDocument::fromJson(json, &error); + if (config.isNull()) + qFatal("Platform config file parse error: %s", qPrintable(error.errorString())); + + // Apply configuration (create screens) + bool synchronousWindowSystemEvents = config["synchronousWindowSystemEvents"].toBool(false); + QWindowSystemInterface::setSynchronousWindowSystemEvents(synchronousWindowSystemEvents); + m_windowFrameMarginsEnabled = config["windowFrameMargins"].toBool(true); + QJsonArray screens = config["screens"].toArray(); + for (QJsonValue screenValue : screens) { + QJsonObject screen = screenValue.toObject(); + if (screen.isEmpty()) { + qWarning("QOffscreenIntegration::initializeWithPlatformArguments: empty screen object"); + continue; + } + QOffscreenScreen *offscreenScreen = new QOffscreenScreen(this); + offscreenScreen->m_name = screen["name"].toString(); + offscreenScreen->m_geometry = QRect(screen["x"].toInt(0), screen["y"].toInt(0), + screen["width"].toInt(640), screen["height"].toInt(480)); + offscreenScreen->m_logicalDpi = screen["logicalDpi"].toInt(96); + offscreenScreen->m_logicalBaseDpi = screen["logicalBaseDpi"].toInt(96); + offscreenScreen->m_dpr = screen["dpr"].toDouble(1.0); + + m_screens.append(offscreenScreen); + QWindowSystemInterface::handleScreenAdded(offscreenScreen); + } +} + void QOffscreenIntegration::initialize() { m_inputContext.reset(QPlatformInputContextFactory::create()); @@ -134,7 +223,7 @@ bool QOffscreenIntegration::hasCapability(QPlatformIntegration::Capability cap) QPlatformWindow *QOffscreenIntegration::createPlatformWindow(QWindow *window) const { Q_UNUSED(window); - QPlatformWindow *w = new QOffscreenWindow(window); + QPlatformWindow *w = new QOffscreenWindow(window, m_windowFrameMarginsEnabled); w->requestActivateWindow(); return w; } @@ -203,14 +292,25 @@ QPlatformServices *QOffscreenIntegration::services() const return m_services.data(); } -QOffscreenIntegration *QOffscreenIntegration::createOffscreenIntegration() +QOffscreenIntegration *QOffscreenIntegration::createOffscreenIntegration(const QStringList& paramList) { + QOffscreenIntegration *offscreenIntegration = nullptr; + #if QT_CONFIG(xlib) && QT_CONFIG(opengl) && !QT_CONFIG(opengles2) QByteArray glx = qgetenv("QT_QPA_OFFSCREEN_NO_GLX"); if (glx.isEmpty()) - return new QOffscreenX11Integration; + offscreenIntegration = new QOffscreenX11Integration; +#else + offscreenIntegration = new QOffscreenIntegration; #endif - return new QOffscreenIntegration; + + offscreenIntegration->configure(paramList); + return offscreenIntegration; +} + +QList QOffscreenIntegration::screens() const +{ + return m_screens; } QT_END_NAMESPACE diff --git a/src/plugins/platforms/offscreen/qoffscreenintegration.h b/src/plugins/platforms/offscreen/qoffscreenintegration.h index 098e726550..be47313913 100644 --- a/src/plugins/platforms/offscreen/qoffscreenintegration.h +++ b/src/plugins/platforms/offscreen/qoffscreenintegration.h @@ -55,6 +55,7 @@ public: QOffscreenIntegration(); ~QOffscreenIntegration(); + void configure(const QStringList& paramList); void initialize() override; bool hasCapability(QPlatformIntegration::Capability cap) const override; @@ -73,8 +74,9 @@ public: QStringList themeNames() const override; QPlatformTheme *createPlatformTheme(const QString &name) const override; - static QOffscreenIntegration *createOffscreenIntegration(); + static QOffscreenIntegration *createOffscreenIntegration(const QStringList& paramList); + QList screens() const; private: QScopedPointer m_fontDatabase; #if QT_CONFIG(draganddrop) @@ -82,6 +84,8 @@ private: #endif QScopedPointer m_inputContext; QScopedPointer m_services; + QList m_screens; + bool m_windowFrameMarginsEnabled = true; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/offscreen/qoffscreenwindow.cpp b/src/plugins/platforms/offscreen/qoffscreenwindow.cpp index 53880c877e..a46258a401 100644 --- a/src/plugins/platforms/offscreen/qoffscreenwindow.cpp +++ b/src/plugins/platforms/offscreen/qoffscreenwindow.cpp @@ -47,18 +47,18 @@ QT_BEGIN_NAMESPACE -QOffscreenWindow::QOffscreenWindow(QWindow *window) +QOffscreenWindow::QOffscreenWindow(QWindow *window, bool frameMarginsEnabled) : QPlatformWindow(window) , m_positionIncludesFrame(false) , m_visible(false) , m_pendingGeometryChangeOnShow(true) + , m_frameMarginsRequested(frameMarginsEnabled) { - if (window->windowState() == Qt::WindowNoState) - setGeometry(window->geometry()); - else + if (window->windowState() == Qt::WindowNoState) { + setGeometry(windowGeometry()); + } else { setWindowState(window->windowStates()); - - QWindowSystemInterface::flushWindowSystemEvents(); + } static WId counter = 0; m_winId = ++counter; @@ -80,7 +80,7 @@ void QOffscreenWindow::setGeometry(const QRect &rect) m_positionIncludesFrame = qt_window_private(window())->positionPolicy == QWindowPrivate::WindowFrameInclusive; - setFrameMarginsEnabled(true); + setFrameMarginsEnabled(m_frameMarginsRequested); setGeometryImpl(rect); m_normalGeometry = geometry(); @@ -168,7 +168,7 @@ void QOffscreenWindow::setFrameMarginsEnabled(bool enabled) void QOffscreenWindow::setWindowState(Qt::WindowStates state) { - setFrameMarginsEnabled(!(state & Qt::WindowFullScreen)); + setFrameMarginsEnabled(m_frameMarginsRequested && !(state & Qt::WindowFullScreen)); m_positionIncludesFrame = false; if (state & Qt::WindowMinimized) diff --git a/src/plugins/platforms/offscreen/qoffscreenwindow.h b/src/plugins/platforms/offscreen/qoffscreenwindow.h index e1f37bb034..32b8ca33cb 100644 --- a/src/plugins/platforms/offscreen/qoffscreenwindow.h +++ b/src/plugins/platforms/offscreen/qoffscreenwindow.h @@ -50,7 +50,7 @@ QT_BEGIN_NAMESPACE class QOffscreenWindow : public QPlatformWindow { public: - QOffscreenWindow(QWindow *window); + QOffscreenWindow(QWindow *window, bool frameMarginsEnabled); ~QOffscreenWindow(); void setGeometry(const QRect &rect) override; @@ -74,6 +74,7 @@ private: bool m_positionIncludesFrame; bool m_visible; bool m_pendingGeometryChangeOnShow; + bool m_frameMarginsRequested; WId m_winId; static QHash m_windowForWinIdHash; -- cgit v1.2.3