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)
|
QPlatformIntegration *QOffscreenIntegrationPlugin::create(const QString& system, const QStringList& paramList)
|
||||||
{
|
{
|
||||||
Q_UNUSED(paramList);
|
|
||||||
if (!system.compare(QLatin1String("offscreen"), Qt::CaseInsensitive))
|
if (!system.compare(QLatin1String("offscreen"), Qt::CaseInsensitive))
|
||||||
return QOffscreenIntegration::createOffscreenIntegration();
|
return QOffscreenIntegration::createOffscreenIntegration(paramList);
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
@ -38,8 +38,10 @@
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#include "qoffscreencommon.h"
|
#include "qoffscreencommon.h"
|
||||||
|
#include "qoffscreenintegration.h"
|
||||||
#include "qoffscreenwindow.h"
|
#include "qoffscreenwindow.h"
|
||||||
|
|
||||||
|
|
||||||
#include <QtGui/private/qpixmap_raster_p.h>
|
#include <QtGui/private/qpixmap_raster_p.h>
|
||||||
#include <QtGui/private/qguiapplication_p.h>
|
#include <QtGui/private/qguiapplication_p.h>
|
||||||
|
|
||||||
@ -50,6 +52,12 @@ QT_BEGIN_NAMESPACE
|
|||||||
|
|
||||||
QPlatformWindow *QOffscreenScreen::windowContainingCursor = nullptr;
|
QPlatformWindow *QOffscreenScreen::windowContainingCursor = nullptr;
|
||||||
|
|
||||||
|
|
||||||
|
QList<QPlatformScreen *> QOffscreenScreen::virtualSiblings() const
|
||||||
|
{
|
||||||
|
return m_integration->screens();
|
||||||
|
}
|
||||||
|
|
||||||
class QOffscreenCursor : public QPlatformCursor
|
class QOffscreenCursor : public QPlatformCursor
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -93,9 +101,10 @@ private:
|
|||||||
QPoint m_pos;
|
QPoint m_pos;
|
||||||
};
|
};
|
||||||
|
|
||||||
QOffscreenScreen::QOffscreenScreen()
|
QOffscreenScreen::QOffscreenScreen(const QOffscreenIntegration *integration)
|
||||||
: m_geometry(0, 0, 800, 600)
|
: m_geometry(0, 0, 800, 600)
|
||||||
, m_cursor(new QOffscreenCursor)
|
, m_cursor(new QOffscreenCursor)
|
||||||
|
, m_integration(integration)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,23 +54,34 @@
|
|||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
|
class QOffscreenIntegration;
|
||||||
class QOffscreenScreen : public QPlatformScreen
|
class QOffscreenScreen : public QPlatformScreen
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
QOffscreenScreen();
|
QOffscreenScreen(const QOffscreenIntegration *integration);
|
||||||
|
|
||||||
QRect geometry() const override { return m_geometry; }
|
QRect geometry() const override { return m_geometry; }
|
||||||
int depth() const override { return 32; }
|
int depth() const override { return 32; }
|
||||||
QImage::Format format() const override { return QImage::Format_RGB32; }
|
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(); }
|
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;
|
QPixmap grabWindow(WId window, int x, int y, int width, int height) const override;
|
||||||
|
|
||||||
static QPlatformWindow *windowContainingCursor;
|
static QPlatformWindow *windowContainingCursor;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
QString m_name;
|
||||||
QRect m_geometry;
|
QRect m_geometry;
|
||||||
|
int m_logicalDpi = 96;
|
||||||
|
int m_logicalBaseDpi= 96;
|
||||||
|
qreal m_dpr = 1;
|
||||||
QScopedPointer<QPlatformCursor> m_cursor;
|
QScopedPointer<QPlatformCursor> m_cursor;
|
||||||
|
const QOffscreenIntegration *m_integration;
|
||||||
};
|
};
|
||||||
|
|
||||||
#if QT_CONFIG(draganddrop)
|
#if QT_CONFIG(draganddrop)
|
||||||
|
@ -54,6 +54,11 @@
|
|||||||
#include <QtCore/private/qeventdispatcher_win_p.h>
|
#include <QtCore/private/qeventdispatcher_win_p.h>
|
||||||
#endif
|
#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/qpixmap_raster_p.h>
|
||||||
#include <QtGui/private/qguiapplication_p.h>
|
#include <QtGui/private/qguiapplication_p.h>
|
||||||
#include <qpa/qplatforminputcontextfactory_p.h>
|
#include <qpa/qplatforminputcontextfactory_p.h>
|
||||||
@ -104,14 +109,98 @@ QOffscreenIntegration::QOffscreenIntegration()
|
|||||||
m_drag.reset(new QOffscreenDrag);
|
m_drag.reset(new QOffscreenDrag);
|
||||||
#endif
|
#endif
|
||||||
m_services.reset(new QPlatformServices);
|
m_services.reset(new QPlatformServices);
|
||||||
|
|
||||||
QWindowSystemInterface::handleScreenAdded(new QOffscreenScreen);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QOffscreenIntegration::~QOffscreenIntegration()
|
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()
|
void QOffscreenIntegration::initialize()
|
||||||
{
|
{
|
||||||
m_inputContext.reset(QPlatformInputContextFactory::create());
|
m_inputContext.reset(QPlatformInputContextFactory::create());
|
||||||
@ -134,7 +223,7 @@ bool QOffscreenIntegration::hasCapability(QPlatformIntegration::Capability cap)
|
|||||||
QPlatformWindow *QOffscreenIntegration::createPlatformWindow(QWindow *window) const
|
QPlatformWindow *QOffscreenIntegration::createPlatformWindow(QWindow *window) const
|
||||||
{
|
{
|
||||||
Q_UNUSED(window);
|
Q_UNUSED(window);
|
||||||
QPlatformWindow *w = new QOffscreenWindow(window);
|
QPlatformWindow *w = new QOffscreenWindow(window, m_windowFrameMarginsEnabled);
|
||||||
w->requestActivateWindow();
|
w->requestActivateWindow();
|
||||||
return w;
|
return w;
|
||||||
}
|
}
|
||||||
@ -203,14 +292,25 @@ QPlatformServices *QOffscreenIntegration::services() const
|
|||||||
return m_services.data();
|
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)
|
#if QT_CONFIG(xlib) && QT_CONFIG(opengl) && !QT_CONFIG(opengles2)
|
||||||
QByteArray glx = qgetenv("QT_QPA_OFFSCREEN_NO_GLX");
|
QByteArray glx = qgetenv("QT_QPA_OFFSCREEN_NO_GLX");
|
||||||
if (glx.isEmpty())
|
if (glx.isEmpty())
|
||||||
return new QOffscreenX11Integration;
|
offscreenIntegration = new QOffscreenX11Integration;
|
||||||
|
#else
|
||||||
|
offscreenIntegration = new QOffscreenIntegration;
|
||||||
#endif
|
#endif
|
||||||
return new QOffscreenIntegration;
|
|
||||||
|
offscreenIntegration->configure(paramList);
|
||||||
|
return offscreenIntegration;
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<QPlatformScreen *> QOffscreenIntegration::screens() const
|
||||||
|
{
|
||||||
|
return m_screens;
|
||||||
}
|
}
|
||||||
|
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
@ -55,6 +55,7 @@ public:
|
|||||||
QOffscreenIntegration();
|
QOffscreenIntegration();
|
||||||
~QOffscreenIntegration();
|
~QOffscreenIntegration();
|
||||||
|
|
||||||
|
void configure(const QStringList& paramList);
|
||||||
void initialize() override;
|
void initialize() override;
|
||||||
bool hasCapability(QPlatformIntegration::Capability cap) const override;
|
bool hasCapability(QPlatformIntegration::Capability cap) const override;
|
||||||
|
|
||||||
@ -73,8 +74,9 @@ public:
|
|||||||
QStringList themeNames() const override;
|
QStringList themeNames() const override;
|
||||||
QPlatformTheme *createPlatformTheme(const QString &name) const override;
|
QPlatformTheme *createPlatformTheme(const QString &name) const override;
|
||||||
|
|
||||||
static QOffscreenIntegration *createOffscreenIntegration();
|
static QOffscreenIntegration *createOffscreenIntegration(const QStringList& paramList);
|
||||||
|
|
||||||
|
QList<QPlatformScreen *> screens() const;
|
||||||
private:
|
private:
|
||||||
QScopedPointer<QPlatformFontDatabase> m_fontDatabase;
|
QScopedPointer<QPlatformFontDatabase> m_fontDatabase;
|
||||||
#if QT_CONFIG(draganddrop)
|
#if QT_CONFIG(draganddrop)
|
||||||
@ -82,6 +84,8 @@ private:
|
|||||||
#endif
|
#endif
|
||||||
QScopedPointer<QPlatformInputContext> m_inputContext;
|
QScopedPointer<QPlatformInputContext> m_inputContext;
|
||||||
QScopedPointer<QPlatformServices> m_services;
|
QScopedPointer<QPlatformServices> m_services;
|
||||||
|
QList<QPlatformScreen *> m_screens;
|
||||||
|
bool m_windowFrameMarginsEnabled = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
@ -47,18 +47,18 @@
|
|||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
QOffscreenWindow::QOffscreenWindow(QWindow *window)
|
QOffscreenWindow::QOffscreenWindow(QWindow *window, bool frameMarginsEnabled)
|
||||||
: QPlatformWindow(window)
|
: QPlatformWindow(window)
|
||||||
, m_positionIncludesFrame(false)
|
, m_positionIncludesFrame(false)
|
||||||
, m_visible(false)
|
, m_visible(false)
|
||||||
, m_pendingGeometryChangeOnShow(true)
|
, m_pendingGeometryChangeOnShow(true)
|
||||||
|
, m_frameMarginsRequested(frameMarginsEnabled)
|
||||||
{
|
{
|
||||||
if (window->windowState() == Qt::WindowNoState)
|
if (window->windowState() == Qt::WindowNoState) {
|
||||||
setGeometry(window->geometry());
|
setGeometry(windowGeometry());
|
||||||
else
|
} else {
|
||||||
setWindowState(window->windowStates());
|
setWindowState(window->windowStates());
|
||||||
|
}
|
||||||
QWindowSystemInterface::flushWindowSystemEvents();
|
|
||||||
|
|
||||||
static WId counter = 0;
|
static WId counter = 0;
|
||||||
m_winId = ++counter;
|
m_winId = ++counter;
|
||||||
@ -80,7 +80,7 @@ void QOffscreenWindow::setGeometry(const QRect &rect)
|
|||||||
|
|
||||||
m_positionIncludesFrame = qt_window_private(window())->positionPolicy == QWindowPrivate::WindowFrameInclusive;
|
m_positionIncludesFrame = qt_window_private(window())->positionPolicy == QWindowPrivate::WindowFrameInclusive;
|
||||||
|
|
||||||
setFrameMarginsEnabled(true);
|
setFrameMarginsEnabled(m_frameMarginsRequested);
|
||||||
setGeometryImpl(rect);
|
setGeometryImpl(rect);
|
||||||
|
|
||||||
m_normalGeometry = geometry();
|
m_normalGeometry = geometry();
|
||||||
@ -168,7 +168,7 @@ void QOffscreenWindow::setFrameMarginsEnabled(bool enabled)
|
|||||||
|
|
||||||
void QOffscreenWindow::setWindowState(Qt::WindowStates state)
|
void QOffscreenWindow::setWindowState(Qt::WindowStates state)
|
||||||
{
|
{
|
||||||
setFrameMarginsEnabled(!(state & Qt::WindowFullScreen));
|
setFrameMarginsEnabled(m_frameMarginsRequested && !(state & Qt::WindowFullScreen));
|
||||||
m_positionIncludesFrame = false;
|
m_positionIncludesFrame = false;
|
||||||
|
|
||||||
if (state & Qt::WindowMinimized)
|
if (state & Qt::WindowMinimized)
|
||||||
|
@ -50,7 +50,7 @@ QT_BEGIN_NAMESPACE
|
|||||||
class QOffscreenWindow : public QPlatformWindow
|
class QOffscreenWindow : public QPlatformWindow
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
QOffscreenWindow(QWindow *window);
|
QOffscreenWindow(QWindow *window, bool frameMarginsEnabled);
|
||||||
~QOffscreenWindow();
|
~QOffscreenWindow();
|
||||||
|
|
||||||
void setGeometry(const QRect &rect) override;
|
void setGeometry(const QRect &rect) override;
|
||||||
@ -74,6 +74,7 @@ private:
|
|||||||
bool m_positionIncludesFrame;
|
bool m_positionIncludesFrame;
|
||||||
bool m_visible;
|
bool m_visible;
|
||||||
bool m_pendingGeometryChangeOnShow;
|
bool m_pendingGeometryChangeOnShow;
|
||||||
|
bool m_frameMarginsRequested;
|
||||||
WId m_winId;
|
WId m_winId;
|
||||||
|
|
||||||
static QHash<WId, QOffscreenWindow *> m_windowForWinIdHash;
|
static QHash<WId, QOffscreenWindow *> m_windowForWinIdHash;
|
||||||
|
Loading…
Reference in New Issue
Block a user