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>
This commit is contained in:
parent
0ab89881c5
commit
f4a66e5c4c
@ -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;
|
||||
}
|
||||
|
@ -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)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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 ¶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<QPlatformScreen *> QOffscreenIntegration::screens() const
|
||||
{
|
||||
return m_screens;
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user