summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms
diff options
context:
space:
mode:
authorMorten Johan Sørvig <morten.sorvig@qt.io>2020-02-03 23:03:29 +0100
committerMorten Johan Sørvig <morten.sorvig@qt.io>2020-10-20 07:26:46 +0200
commitf4a66e5c4c4be97a7511b372930e20f330ea0813 (patch)
tree013880c3a0f5084b017962310208448a761632cf /src/plugins/platforms
parent0ab89881c5aecc31e44fd83b1a63bd4de52ebe4a (diff)
QPA offscreen: make platform plugin configurable
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 <paul.tvete@qt.io> Reviewed-by: Friedemann Kleint <Friedemann.Kleint@qt.io>
Diffstat (limited to 'src/plugins/platforms')
-rw-r--r--src/plugins/platforms/offscreen/main.cpp3
-rw-r--r--src/plugins/platforms/offscreen/qoffscreencommon.cpp11
-rw-r--r--src/plugins/platforms/offscreen/qoffscreencommon.h13
-rw-r--r--src/plugins/platforms/offscreen/qoffscreenintegration.cpp112
-rw-r--r--src/plugins/platforms/offscreen/qoffscreenintegration.h6
-rw-r--r--src/plugins/platforms/offscreen/qoffscreenwindow.cpp16
-rw-r--r--src/plugins/platforms/offscreen/qoffscreenwindow.h3
7 files changed, 144 insertions, 20 deletions
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 <QtGui/private/qpixmap_raster_p.h>
#include <QtGui/private/qguiapplication_p.h>
@@ -50,6 +52,12 @@ QT_BEGIN_NAMESPACE
QPlatformWindow *QOffscreenScreen::windowContainingCursor = nullptr;
+
+QList<QPlatformScreen *> 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<QPlatformScreen *> 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<QPlatformCursor> 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 <QtCore/private/qeventdispatcher_win_p.h>
#endif
+#include <QtCore/qfile.h>
+#include <QtCore/qjsonarray.h>
+#include <QtCore/qjsondocument.h>
+#include <QtCore/qjsonobject.h>
+#include <QtCore/qjsonvalue.h>
#include <QtGui/private/qpixmap_raster_p.h>
#include <QtGui/private/qguiapplication_p.h>
#include <qpa/qplatforminputcontextfactory_p.h>
@@ -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": <bool>
+ "windowFrameMargins": <bool>,
+ "screens": [<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 &param : 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<QPlatformScreen *> 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<QPlatformScreen *> screens() const;
private:
QScopedPointer<QPlatformFontDatabase> m_fontDatabase;
#if QT_CONFIG(draganddrop)
@@ -82,6 +84,8 @@ private:
#endif
QScopedPointer<QPlatformInputContext> m_inputContext;
QScopedPointer<QPlatformServices> m_services;
+ QList<QPlatformScreen *> 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<WId, QOffscreenWindow *> m_windowForWinIdHash;