diff options
Diffstat (limited to 'src/plugins/platforms/offscreen')
-rw-r--r-- | src/plugins/platforms/offscreen/.prev_CMakeLists.txt | 38 | ||||
-rw-r--r-- | src/plugins/platforms/offscreen/CMakeLists.txt | 17 | ||||
-rw-r--r-- | src/plugins/platforms/offscreen/main.cpp | 47 | ||||
-rw-r--r-- | src/plugins/platforms/offscreen/offscreen.pro | 28 | ||||
-rw-r--r-- | src/plugins/platforms/offscreen/qoffscreencommon.cpp | 125 | ||||
-rw-r--r-- | src/plugins/platforms/offscreen/qoffscreencommon.h | 70 | ||||
-rw-r--r-- | src/plugins/platforms/offscreen/qoffscreenintegration.cpp | 315 | ||||
-rw-r--r-- | src/plugins/platforms/offscreen/qoffscreenintegration.h | 60 | ||||
-rw-r--r-- | src/plugins/platforms/offscreen/qoffscreenintegration_x11.cpp | 90 | ||||
-rw-r--r-- | src/plugins/platforms/offscreen/qoffscreenintegration_x11.h | 79 | ||||
-rw-r--r-- | src/plugins/platforms/offscreen/qoffscreenwindow.cpp | 80 | ||||
-rw-r--r-- | src/plugins/platforms/offscreen/qoffscreenwindow.h | 45 |
12 files changed, 511 insertions, 483 deletions
diff --git a/src/plugins/platforms/offscreen/.prev_CMakeLists.txt b/src/plugins/platforms/offscreen/.prev_CMakeLists.txt deleted file mode 100644 index 319502ccc6..0000000000 --- a/src/plugins/platforms/offscreen/.prev_CMakeLists.txt +++ /dev/null @@ -1,38 +0,0 @@ -# Generated from offscreen.pro. - -##################################################################### -## QOffscreenIntegrationPlugin Plugin: -##################################################################### - -qt_internal_add_plugin(QOffscreenIntegrationPlugin - OUTPUT_NAME qoffscreen - TYPE platforms - SOURCES - main.cpp - qoffscreencommon.cpp qoffscreencommon.h - qoffscreenintegration.cpp qoffscreenintegration.h - qoffscreenwindow.cpp qoffscreenwindow.h - DEFINES - QT_NO_FOREACH - PUBLIC_LIBRARIES - Qt::Core - Qt::CorePrivate - Qt::Gui - Qt::GuiPrivate -) - -#### Keys ignored in scope 1:.:.:offscreen.pro:<TRUE>: -# OTHER_FILES = "offscreen.json" - -## Scopes: -##################################################################### - -qt_extend_target(QOffscreenIntegrationPlugin CONDITION QT_FEATURE_opengl AND QT_FEATURE_xlib AND NOT QT_FEATURE_opengles2 - SOURCES - qoffscreenintegration_x11.cpp qoffscreenintegration_x11.h - LIBRARIES - X11::X11 -) - -#### Keys ignored in scope 3:.:.:offscreen.pro:NOT TARGET___equals____ss_QT_DEFAULT_QPA_PLUGIN: -# PLUGIN_EXTENDS = "-" diff --git a/src/plugins/platforms/offscreen/CMakeLists.txt b/src/plugins/platforms/offscreen/CMakeLists.txt index 7a312701c6..09ad9a384d 100644 --- a/src/plugins/platforms/offscreen/CMakeLists.txt +++ b/src/plugins/platforms/offscreen/CMakeLists.txt @@ -1,4 +1,5 @@ -# Generated from offscreen.pro. +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## QOffscreenIntegrationPlugin Plugin: @@ -6,8 +7,8 @@ qt_internal_add_plugin(QOffscreenIntegrationPlugin OUTPUT_NAME qoffscreen - TYPE platforms - DEFAULT_IF ${QT_QPA_DEFAULT_PLATFORM} MATCHES offscreen # special case + PLUGIN_TYPE platforms + DEFAULT_IF ${QT_QPA_DEFAULT_PLATFORM} MATCHES offscreen SOURCES main.cpp qoffscreencommon.cpp qoffscreencommon.h @@ -15,25 +16,19 @@ qt_internal_add_plugin(QOffscreenIntegrationPlugin qoffscreenwindow.cpp qoffscreenwindow.h DEFINES QT_NO_FOREACH - PUBLIC_LIBRARIES + LIBRARIES Qt::Core Qt::CorePrivate Qt::Gui Qt::GuiPrivate ) -#### Keys ignored in scope 1:.:.:offscreen.pro:<TRUE>: -# OTHER_FILES = "offscreen.json" - ## Scopes: ##################################################################### -qt_extend_target(QOffscreenIntegrationPlugin CONDITION QT_FEATURE_opengl AND QT_FEATURE_xlib AND NOT QT_FEATURE_opengles2 +qt_internal_extend_target(QOffscreenIntegrationPlugin CONDITION QT_FEATURE_opengl AND QT_FEATURE_xlib AND NOT QT_FEATURE_opengles2 SOURCES qoffscreenintegration_x11.cpp qoffscreenintegration_x11.h LIBRARIES X11::X11 ) - -#### Keys ignored in scope 3:.:.:offscreen.pro:NOT TARGET___equals____ss_QT_DEFAULT_QPA_PLUGIN: -# PLUGIN_EXTENDS = "-" diff --git a/src/plugins/platforms/offscreen/main.cpp b/src/plugins/platforms/offscreen/main.cpp index f364d9f004..4b5527cbde 100644 --- a/src/plugins/platforms/offscreen/main.cpp +++ b/src/plugins/platforms/offscreen/main.cpp @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the plugins of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include <qpa/qplatformintegrationplugin.h> @@ -43,6 +7,8 @@ QT_BEGIN_NAMESPACE +using namespace Qt::StringLiterals; + class QOffscreenIntegrationPlugin : public QPlatformIntegrationPlugin { Q_OBJECT @@ -53,9 +19,8 @@ public: QPlatformIntegration *QOffscreenIntegrationPlugin::create(const QString& system, const QStringList& paramList) { - Q_UNUSED(paramList); - if (!system.compare(QLatin1String("offscreen"), Qt::CaseInsensitive)) - return QOffscreenIntegration::createOffscreenIntegration(); + if (!system.compare("offscreen"_L1, Qt::CaseInsensitive)) + return QOffscreenIntegration::createOffscreenIntegration(paramList); return nullptr; } diff --git a/src/plugins/platforms/offscreen/offscreen.pro b/src/plugins/platforms/offscreen/offscreen.pro deleted file mode 100644 index 6be725af7e..0000000000 --- a/src/plugins/platforms/offscreen/offscreen.pro +++ /dev/null @@ -1,28 +0,0 @@ -TARGET = qoffscreen - -QT += \ - core-private gui-private - -DEFINES += QT_NO_FOREACH - -SOURCES = main.cpp \ - qoffscreenintegration.cpp \ - qoffscreenwindow.cpp \ - qoffscreencommon.cpp - -HEADERS = qoffscreenintegration.h \ - qoffscreenwindow.h \ - qoffscreencommon.h - -OTHER_FILES += offscreen.json - -qtConfig(xlib):qtConfig(opengl):!qtConfig(opengles2) { - SOURCES += qoffscreenintegration_x11.cpp - HEADERS += qoffscreenintegration_x11.h - QMAKE_USE_PRIVATE += xlib -} - -PLUGIN_TYPE = platforms -PLUGIN_CLASS_NAME = QOffscreenIntegrationPlugin -!equals(TARGET, $$QT_DEFAULT_QPA_PLUGIN): PLUGIN_EXTENDS = - -load(qt_plugin) diff --git a/src/plugins/platforms/offscreen/qoffscreencommon.cpp b/src/plugins/platforms/offscreen/qoffscreencommon.cpp index de75a3e012..923fffb29c 100644 --- a/src/plugins/platforms/offscreen/qoffscreencommon.cpp +++ b/src/plugins/platforms/offscreen/qoffscreencommon.cpp @@ -1,45 +1,12 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the plugins of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include "qoffscreencommon.h" +#include "qoffscreenintegration.h" #include "qoffscreenwindow.h" + +#include <QtGui/QPainter> #include <QtGui/private/qpixmap_raster_p.h> #include <QtGui/private/qguiapplication_p.h> @@ -50,6 +17,16 @@ QT_BEGIN_NAMESPACE QPlatformWindow *QOffscreenScreen::windowContainingCursor = nullptr; + +QList<QPlatformScreen *> QOffscreenScreen::virtualSiblings() const +{ + QList<QPlatformScreen *> platformScreens; + for (auto screen : m_integration->screens()) { + platformScreens.append(screen); + } + return platformScreens; +} + class QOffscreenCursor : public QPlatformCursor { public: @@ -93,9 +70,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) { } @@ -103,22 +81,25 @@ QPixmap QOffscreenScreen::grabWindow(WId id, int x, int y, int width, int height { QRect rect(x, y, width, height); - QOffscreenWindow *window = QOffscreenWindow::windowForWinId(id); - if (!window || window->window()->type() == Qt::Desktop) { + // id == 0 -> grab the screen, so all windows intersecting rect + if (!id) { + if (width == -1) + rect.setWidth(m_geometry.width()); + if (height == -1) + rect.setHeight(m_geometry.height()); + QPixmap screenImage(rect.size()); + QPainter painter(&screenImage); + painter.translate(-x, -y); const QWindowList wl = QGuiApplication::topLevelWindows(); - QWindow *containing = nullptr; for (QWindow *w : wl) { - if (w->type() != Qt::Desktop && w->isExposed() && w->geometry().contains(rect)) { - containing = w; - break; + if (w->isExposed() && w->geometry().intersects(rect)) { + QOffscreenBackingStore *store = QOffscreenBackingStore::backingStoreForWinId(w->winId()); + const QImage windowImage = store ? store->toImage() : QImage(); + if (!windowImage.isNull()) + painter.drawImage(w->position(), windowImage); } } - - if (!containing) - return QPixmap(); - - id = containing->winId(); - rect = rect.translated(-containing->geometry().topLeft()); + return screenImage; } QOffscreenBackingStore *store = QOffscreenBackingStore::backingStoreForWinId(id); @@ -180,8 +161,8 @@ bool QOffscreenBackingStore::scroll(const QRegion &area, int dx, int dy) if (m_image.isNull()) return false; - for (const QRect &rect : area) - qt_scrollRectInImage(m_image, rect, QPoint(dx, dy)); + const QRect rect = area.boundingRect(); + qt_scrollRectInImage(m_image, rect, QPoint(dx, dy)); return true; } @@ -208,13 +189,13 @@ QPixmap QOffscreenBackingStore::grabWindow(WId window, const QRect &rect) const QOffscreenBackingStore *QOffscreenBackingStore::backingStoreForWinId(WId id) { - return m_backingStoreForWinIdHash.value(id, 0); + return m_backingStoreForWinIdHash.value(id, nullptr); } void QOffscreenBackingStore::clearHash() { for (auto it = m_windowAreaHash.cbegin(), end = m_windowAreaHash.cend(); it != end; ++it) { - const auto it2 = qAsConst(m_backingStoreForWinIdHash).find(it.key()); + const auto it2 = std::as_const(m_backingStoreForWinIdHash).find(it.key()); if (it2.value() == this) m_backingStoreForWinIdHash.erase(it2); } @@ -223,4 +204,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 diff --git a/src/plugins/platforms/offscreen/qoffscreencommon.h b/src/plugins/platforms/offscreen/qoffscreencommon.h index f4f0142911..a3d6227168 100644 --- a/src/plugins/platforms/offscreen/qoffscreencommon.h +++ b/src/plugins/platforms/offscreen/qoffscreencommon.h @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the plugins of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QOFFSCREENCOMMON_H #define QOFFSCREENCOMMON_H @@ -45,32 +9,45 @@ #include <qpa/qplatformdrag.h> #endif #include <qpa/qplatformintegration.h> +#include <qpa/qplatformnativeinterface.h> #include <qpa/qplatformscreen.h> #include <qpa/qplatformwindow.h> #include <qscopedpointer.h> #include <qimage.h> +#include <qjsonobject.h> #include <qhash.h> 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) @@ -93,6 +70,7 @@ public: bool scroll(const QRegion &area, int dx, int dy) override; QPixmap grabWindow(WId window, const QRect &rect) const; + QImage toImage() const override { return m_image; } static QOffscreenBackingStore *backingStoreForWinId(WId id); @@ -105,6 +83,20 @@ private: static QHash<WId, QOffscreenBackingStore *> m_backingStoreForWinIdHash; }; +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 #endif diff --git a/src/plugins/platforms/offscreen/qoffscreenintegration.cpp b/src/plugins/platforms/offscreen/qoffscreenintegration.cpp index 811e025f62..ea8042928a 100644 --- a/src/plugins/platforms/offscreen/qoffscreenintegration.cpp +++ b/src/plugins/platforms/offscreen/qoffscreenintegration.cpp @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the plugins of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include "qoffscreenintegration.h" #include "qoffscreenwindow.h" @@ -54,6 +18,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> @@ -69,6 +38,8 @@ QT_BEGIN_NAMESPACE +using namespace Qt::StringLiterals; + class QCoreTextFontEngine; template <typename BaseEventDispatcher> @@ -88,7 +59,7 @@ public: } }; -QOffscreenIntegration::QOffscreenIntegration() +QOffscreenIntegration::QOffscreenIntegration(const QStringList& paramList) { #if defined(Q_OS_UNIX) #if defined(Q_OS_MAC) @@ -105,11 +76,235 @@ QOffscreenIntegration::QOffscreenIntegration() #endif m_services.reset(new QPlatformServices); - QWindowSystemInterface::handleScreenAdded(new QOffscreenScreen); + QJsonObject config = resolveConfigFileConfiguration(paramList).value_or(defaultConfiguration()); + setConfiguration(config); } QOffscreenIntegration::~QOffscreenIntegration() { + while (!m_screens.isEmpty()) + QWindowSystemInterface::handleScreenRemoved(m_screens.takeLast()); +} + +/* + The offscren platform plugin is configurable with a JSON configuration. + The confiuration can be provided either from a file on disk on startup, + or at by calling setConfiguration(). + + To provide a configuration on startuip, 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>], + } + + "screens" is an array of: + { + "name": string, + "x": int, + "y": int, + "width": int, + "height": int, + "logicalDpi": int, + "logicalBaseDpi": int, + "dpr": double, + } +*/ + +QJsonObject QOffscreenIntegration::defaultConfiguration() const +{ + const auto defaultScreen = QJsonObject { + {"name", ""}, + {"x", 0}, + {"y", 0}, + {"width", 800}, + {"height", 800}, + {"logicalDpi", 96}, + {"logicalBaseDpi", 96}, + {"dpr", 1.0}, + }; + const auto defaultConfiguration = QJsonObject { + {"synchronousWindowSystemEvents", false}, + {"windowFrameMargins", true}, + {"screens", QJsonArray { defaultScreen } }, + }; + return defaultConfiguration; +} + +std::optional<QJsonObject> QOffscreenIntegration::resolveConfigFileConfiguration(const QStringList& paramList) const +{ + bool hasConfigFile = false; + QString configFilePath; + for (const QString ¶m : paramList) { + // Look for "configfile=/path/to/file/" + QString configPrefix("configfile="_L1); + if (param.startsWith(configPrefix)) { + hasConfigFile = true; + configFilePath = param.mid(configPrefix.size()); + } + } + if (!hasConfigFile) + return std::nullopt; + + // 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())); + + return config.object(); +} + + +void QOffscreenIntegration::setConfiguration(const QJsonObject &configuration) +{ + // Apply the new configuration, diffing against the current m_configuration + + const bool synchronousWindowSystemEvents = configuration["synchronousWindowSystemEvents"].toBool( + m_configuration["synchronousWindowSystemEvents"].toBool(false)); + QWindowSystemInterface::setSynchronousWindowSystemEvents(synchronousWindowSystemEvents); + + m_windowFrameMarginsEnabled = configuration["windowFrameMargins"].toBool( + m_configuration["windowFrameMargins"].toBool(true)); + + // Diff screens array, using the screen name as the screen identity. + QJsonArray currentScreens = m_configuration["screens"].toArray(); + QJsonArray newScreens = configuration["screens"].toArray(); + + auto getScreenNames = [](const QJsonArray &screens) -> QList<QString> { + QList<QString> names; + for (QJsonValue screen : screens) { + names.append(screen["name"].toString()); + }; + std::sort(names.begin(), names.end()); + return names; + }; + + auto currentNames = getScreenNames(currentScreens); + auto newNames = getScreenNames(newScreens); + + QList<QString> present; + std::set_intersection(currentNames.begin(), currentNames.end(), newNames.begin(), newNames.end(), + std::inserter(present, present.begin())); + QList<QString> added; + std::set_difference(newNames.begin(), newNames.end(), currentNames.begin(), currentNames.end(), + std::inserter(added, added.begin())); + QList<QString> removed; + std::set_difference(currentNames.begin(), currentNames.end(), newNames.begin(), newNames.end(), + std::inserter(removed, removed.begin())); + + auto platformScreenByName = [](const QString &name, QList<QOffscreenScreen *> screens) -> QOffscreenScreen * { + for (QOffscreenScreen *screen : screens) { + if (screen->m_name == name) + return screen; + } + Q_UNREACHABLE(); + }; + + auto screenConfigByName = [](const QString &name, QJsonArray screenConfigs) -> QJsonValue { + for (QJsonValue screenConfig : screenConfigs) { + if (screenConfig["name"].toString() == name) + return screenConfig; + } + Q_UNREACHABLE(); + }; + + auto geometryFromConfig = [](const QJsonObject &config) -> QRect { + return QRect(config["x"].toInt(0), config["y"].toInt(0), config["width"].toInt(640), config["height"].toInt(480)); + }; + + // Remove removed screens + for (const QString &remove : removed) { + QOffscreenScreen *screen = platformScreenByName(remove, m_screens); + m_screens.removeAll(screen); + QWindowSystemInterface::handleScreenRemoved(screen); + } + + // Add new screens + for (const QString &add : added) { + QJsonValue configValue = screenConfigByName(add, newScreens); + QJsonObject config = configValue.toObject(); + if (config.isEmpty()) { + qWarning("empty screen object"); + continue; + } + QOffscreenScreen *offscreenScreen = new QOffscreenScreen(this); + offscreenScreen->m_name = config["name"].toString(); + offscreenScreen->m_geometry = geometryFromConfig(config); + offscreenScreen->m_logicalDpi = config["logicalDpi"].toInt(96); + offscreenScreen->m_logicalBaseDpi = config["logicalBaseDpi"].toInt(96); + offscreenScreen->m_dpr = config["dpr"].toDouble(1.0); + m_screens.append(offscreenScreen); + QWindowSystemInterface::handleScreenAdded(offscreenScreen); + } + + // Update present screens + for (const QString &pres : present) { + QOffscreenScreen *screen = platformScreenByName(pres, m_screens); + Q_ASSERT(screen); + QJsonObject currentConfig = screenConfigByName(pres, currentScreens).toObject(); + QJsonObject newConfig = screenConfigByName(pres, newScreens).toObject(); + + // Name can't change, because it'd be a different screen + Q_ASSERT(currentConfig["name"] == newConfig["name"]); + + // Geometry + QRect currentGeomtry = geometryFromConfig(currentConfig); + QRect newGeomtry = geometryFromConfig(newConfig); + if (currentGeomtry != newGeomtry) { + screen->m_geometry = newGeomtry; + QWindowSystemInterface::handleScreenGeometryChange(screen->screen(), newGeomtry, newGeomtry); + } + + // logical DPI + int currentLogicalDpi = currentConfig["logicalDpi"].toInt(96); + int newLogicalDpi = newConfig["logicalDpi"].toInt(96); + if (currentLogicalDpi != newLogicalDpi) { + screen->m_logicalDpi = newLogicalDpi; + QWindowSystemInterface::handleScreenLogicalDotsPerInchChange(screen->screen(), newLogicalDpi, newLogicalDpi); + } + + // The base DPI is more of a platform constant, and should not change, and + // there is no handleChange function for it. Print a warning. + int currentLogicalBaseDpi = currentConfig["logicalBaseDpi"].toInt(96); + int newLogicalBaseDpi = newConfig["logicalBaseDpi"].toInt(96); + if (currentLogicalBaseDpi != newLogicalBaseDpi) { + screen->m_logicalBaseDpi = newLogicalBaseDpi; + qWarning("You ain't supposed to change logicalBaseDpi - its a platform constant. Qt may not react to the change"); + } + + // DPR. There is also no handleChange function in Qt at this point, instead + // the new DPR value will be used during the next repaint. We could repaint + // all windows here, but don't. Print a warning. + double currentDpr = currentConfig["dpr"].toDouble(1); + double newDpr = newConfig["dpr"].toDouble(1); + if (currentDpr != newDpr) { + screen->m_dpr = newDpr; + qWarning("DPR change notifications is not implemented - Qt may not react to the change"); + } + } + + // Now the new configuration is the current configuration + m_configuration = configuration; +} + +QJsonObject QOffscreenIntegration::configuration() const +{ + return m_configuration; } void QOffscreenIntegration::initialize() @@ -127,6 +322,7 @@ bool QOffscreenIntegration::hasCapability(QPlatformIntegration::Capability cap) switch (cap) { case ThreadedPixmaps: return true; case MultipleWindows: return true; + case RhiBasedRendering: return false; default: return QPlatformIntegration::hasCapability(cap); } } @@ -134,7 +330,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; } @@ -155,6 +351,13 @@ QAbstractEventDispatcher *QOffscreenIntegration::createEventDispatcher() const #endif } +QPlatformNativeInterface *QOffscreenIntegration::nativeInterface() const +{ + if (!m_nativeInterface) + m_nativeInterface.reset(new QOffscreenPlatformNativeInterface(const_cast<QOffscreenIntegration*>(this))); + return m_nativeInterface.get(); +} + static QString themeName() { return QStringLiteral("offscreen"); } QStringList QOffscreenIntegration::themeNames() const @@ -179,6 +382,20 @@ public: } return QPlatformTheme::themeHint(h); } + + virtual const QFont *font(Font type = SystemFont) const override + { + static QFont systemFont("Sans Serif"_L1, 9); + static QFont fixedFont("monospace"_L1, 9); + switch (type) { + case QPlatformTheme::SystemFont: + return &systemFont; + case QPlatformTheme::FixedFont: + return &fixedFont; + default: + return nullptr; + } + } }; QPlatformTheme *QOffscreenIntegration::createPlatformTheme(const QString &name) const @@ -203,14 +420,24 @@ 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(paramList); #endif - return new QOffscreenIntegration; + + if (!offscreenIntegration) + offscreenIntegration = new QOffscreenIntegration(paramList); + return offscreenIntegration; +} + +QList<QOffscreenScreen *> 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..aab8d305b4 100644 --- a/src/plugins/platforms/offscreen/qoffscreenintegration.h +++ b/src/plugins/platforms/offscreen/qoffscreenintegration.h @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the plugins of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QOFFSCREENINTEGRATION_H #define QOFFSCREENINTEGRATION_H @@ -44,17 +8,24 @@ #include <qpa/qplatformnativeinterface.h> #include <qscopedpointer.h> +#include <qjsonobject.h> QT_BEGIN_NAMESPACE class QOffscreenBackendData; +class QOffscreenScreen; class QOffscreenIntegration : public QPlatformIntegration { public: - QOffscreenIntegration(); + QOffscreenIntegration(const QStringList& paramList); ~QOffscreenIntegration(); + QJsonObject defaultConfiguration() const; + std::optional<QJsonObject> resolveConfigFileConfiguration(const QStringList& paramList) const; + void setConfiguration(const QJsonObject &configuration); + QJsonObject configuration() const; + void initialize() override; bool hasCapability(QPlatformIntegration::Capability cap) const override; @@ -70,18 +41,25 @@ public: QPlatformFontDatabase *fontDatabase() const override; QAbstractEventDispatcher *createEventDispatcher() const override; + QPlatformNativeInterface *nativeInterface() const override; + QStringList themeNames() const override; QPlatformTheme *createPlatformTheme(const QString &name) const override; - static QOffscreenIntegration *createOffscreenIntegration(); + static QOffscreenIntegration *createOffscreenIntegration(const QStringList& paramList); -private: + QList<QOffscreenScreen *> screens() const; +protected: QScopedPointer<QPlatformFontDatabase> m_fontDatabase; #if QT_CONFIG(draganddrop) QScopedPointer<QPlatformDrag> m_drag; #endif QScopedPointer<QPlatformInputContext> m_inputContext; QScopedPointer<QPlatformServices> m_services; + mutable QScopedPointer<QPlatformNativeInterface> m_nativeInterface; + QList<QOffscreenScreen *> m_screens; + bool m_windowFrameMarginsEnabled = true; + QJsonObject m_configuration; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/offscreen/qoffscreenintegration_x11.cpp b/src/plugins/platforms/offscreen/qoffscreenintegration_x11.cpp index bb4d8aeaa1..fbee6667ea 100644 --- a/src/plugins/platforms/offscreen/qoffscreenintegration_x11.cpp +++ b/src/plugins/platforms/offscreen/qoffscreenintegration_x11.cpp @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the plugins of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include "qoffscreenintegration_x11.h" @@ -76,6 +40,14 @@ private: QOffscreenX11Connection *m_connection; }; +QOffscreenX11Integration::QOffscreenX11Integration(const QStringList& paramList) +: QOffscreenIntegration(paramList) +{ + +} + +QOffscreenX11Integration::~QOffscreenX11Integration() = default; + bool QOffscreenX11Integration::hasCapability(QPlatformIntegration::Capability cap) const { switch (cap) { @@ -86,23 +58,37 @@ bool QOffscreenX11Integration::hasCapability(QPlatformIntegration::Capability ca } } +#if !defined(QT_NO_OPENGL) && QT_CONFIG(xcb_glx_plugin) QPlatformOpenGLContext *QOffscreenX11Integration::createPlatformOpenGLContext(QOpenGLContext *context) const { - if (!m_connection) - m_connection.reset(new QOffscreenX11Connection); + auto &connection = nativeInterface()->m_connection; + + if (!connection) + connection.reset(new QOffscreenX11Connection); - if (!m_connection->display()) + if (!connection->display()) return nullptr; - return new QOffscreenX11GLXContext(m_connection->x11Info(), context); + return new QOffscreenX11GLXContext(connection->x11Info(), context); +} +#endif // !defined(QT_NO_OPENGL) && QT_CONFIG(xcb_glx_plugin) + +QOffscreenX11PlatformNativeInterface *QOffscreenX11Integration::nativeInterface() const +{ + if (!m_nativeInterface) + m_nativeInterface.reset(new QOffscreenX11PlatformNativeInterface(const_cast<QOffscreenX11Integration *>(this))); + return static_cast<QOffscreenX11PlatformNativeInterface *>(m_nativeInterface.data()); } -QPlatformNativeInterface *QOffscreenX11Integration::nativeInterface() const +QOffscreenX11PlatformNativeInterface::QOffscreenX11PlatformNativeInterface(QOffscreenIntegration *integration) +:QOffscreenPlatformNativeInterface(integration) { - return const_cast<QOffscreenX11Integration *>(this); + } -void *QOffscreenX11Integration::nativeResourceForScreen(const QByteArray &resource, QScreen *screen) +QOffscreenX11PlatformNativeInterface::~QOffscreenX11PlatformNativeInterface() = default; + +void *QOffscreenX11PlatformNativeInterface::nativeResourceForScreen(const QByteArray &resource, QScreen *screen) { Q_UNUSED(screen); if (resource.toLower() == QByteArrayLiteral("display") ) { @@ -113,8 +99,8 @@ void *QOffscreenX11Integration::nativeResourceForScreen(const QByteArray &resour return nullptr; } -#ifndef QT_NO_OPENGL -void *QOffscreenX11Integration::nativeResourceForContext(const QByteArray &resource, QOpenGLContext *context) { +#if !defined(QT_NO_OPENGL) && QT_CONFIG(xcb_glx_plugin) +void *QOffscreenX11PlatformNativeInterface::nativeResourceForContext(const QByteArray &resource, QOpenGLContext *context) { if (resource.toLower() == QByteArrayLiteral("glxconfig") ) { if (context) { QOffscreenX11GLXContext *glxPlatformContext = static_cast<QOffscreenX11GLXContext *>(context->handle()); @@ -133,6 +119,13 @@ void *QOffscreenX11Integration::nativeResourceForContext(const QByteArray &resou } #endif +#if QT_CONFIG(xcb) +Display *QOffscreenX11PlatformNativeInterface::display() const +{ + return m_connection ? reinterpret_cast<Display *>(m_connection->display()) : nullptr; +} +#endif + QOffscreenX11Connection::QOffscreenX11Connection() { XInitThreads(); @@ -156,6 +149,7 @@ QOffscreenX11Info *QOffscreenX11Connection::x11Info() return m_x11Info.data(); } +#if QT_CONFIG(xcb_glx_plugin) class QOffscreenX11GLXContextData { public: @@ -303,5 +297,5 @@ void *QOffscreenX11GLXContext::glxConfig() const { return d->config; } - +#endif // QT_CONFIG(xcb_glx_plugin) QT_END_NAMESPACE diff --git a/src/plugins/platforms/offscreen/qoffscreenintegration_x11.h b/src/plugins/platforms/offscreen/qoffscreenintegration_x11.h index 005ac26151..d7b5120332 100644 --- a/src/plugins/platforms/offscreen/qoffscreenintegration_x11.h +++ b/src/plugins/platforms/offscreen/qoffscreenintegration_x11.h @@ -1,73 +1,54 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the plugins of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QOFFSCREENINTEGRATION_X11_H #define QOFFSCREENINTEGRATION_X11_H #include "qoffscreenintegration.h" +#include "qoffscreencommon.h" #include <qglobal.h> #include <qscopedpointer.h> #include <qpa/qplatformopenglcontext.h> +#include <QtGui/qguiapplication.h> QT_BEGIN_NAMESPACE class QOffscreenX11Connection; class QOffscreenX11Info; -class QOffscreenX11Integration : public QOffscreenIntegration, public QPlatformNativeInterface +class QOffscreenX11PlatformNativeInterface : public QOffscreenPlatformNativeInterface +#if QT_CONFIG(xcb) + , public QNativeInterface::QX11Application +#endif { public: - bool hasCapability(QPlatformIntegration::Capability cap) const override; - - QPlatformOpenGLContext *createPlatformOpenGLContext(QOpenGLContext *context) const override; - QPlatformNativeInterface *nativeInterface()const override; + QOffscreenX11PlatformNativeInterface(QOffscreenIntegration *integration); + ~QOffscreenX11PlatformNativeInterface(); - // QPlatformNativeInterface void *nativeResourceForScreen(const QByteArray &resource, QScreen *screen) override; -#ifndef QT_NO_OPENGL +#if !defined(QT_NO_OPENGL) && QT_CONFIG(xcb_glx_plugin) void *nativeResourceForContext(const QByteArray &resource, QOpenGLContext *context) override; #endif +#if QT_CONFIG(xcb) + Display *display() const override; + xcb_connection_t *connection() const override { return nullptr; }; +#endif + QScopedPointer<QOffscreenX11Connection> m_connection; +}; -private: - mutable QScopedPointer<QOffscreenX11Connection> m_connection; +class QOffscreenX11Integration : public QOffscreenIntegration +{ +public: + QOffscreenX11Integration(const QStringList& paramList); + ~QOffscreenX11Integration(); + bool hasCapability(QPlatformIntegration::Capability cap) const override; + +#if !defined(QT_NO_OPENGL) && QT_CONFIG(xcb_glx_plugin) + QPlatformOpenGLContext *createPlatformOpenGLContext(QOpenGLContext *context) const override; +#endif + QOffscreenX11PlatformNativeInterface *nativeInterface() const override; }; class QOffscreenX11Connection { @@ -87,10 +68,11 @@ private: QScopedPointer<QOffscreenX11Info> m_x11Info; }; +#if QT_CONFIG(xcb_glx_plugin) class QOffscreenX11GLXContextData; class QOffscreenX11GLXContext : public QPlatformOpenGLContext - , public QPlatformInterface::QGLXContext + , public QNativeInterface::QGLXContext { public: QOffscreenX11GLXContext(QOffscreenX11Info *x11, QOpenGLContext *context); @@ -113,6 +95,7 @@ public: private: QScopedPointer<QOffscreenX11GLXContextData> d; }; +#endif // QT_CONFIG(xcb_glx_plugin) QT_END_NAMESPACE diff --git a/src/plugins/platforms/offscreen/qoffscreenwindow.cpp b/src/plugins/platforms/offscreen/qoffscreenwindow.cpp index 53880c877e..1a1471c687 100644 --- a/src/plugins/platforms/offscreen/qoffscreenwindow.cpp +++ b/src/plugins/platforms/offscreen/qoffscreenwindow.cpp @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the plugins of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include "qoffscreenwindow.h" #include "qoffscreencommon.h" @@ -44,21 +8,22 @@ #include <qpa/qwindowsysteminterface.h> #include <private/qwindow_p.h> +#include <private/qguiapplication_p.h> 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 +45,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(); @@ -121,7 +86,7 @@ void QOffscreenWindow::setVisible(bool visible) if (visible) { if (window()->type() != Qt::ToolTip) - QWindowSystemInterface::handleWindowActivated(window()); + QWindowSystemInterface::handleFocusWindowChanged(window(), Qt::ActiveWindowFocusReason); if (m_pendingGeometryChangeOnShow) { m_pendingGeometryChangeOnShow = false; @@ -129,11 +94,26 @@ void QOffscreenWindow::setVisible(bool visible) } } + const QPoint cursorPos = QCursor::pos(); if (visible) { QRect rect(QPoint(), geometry().size()); QWindowSystemInterface::handleExposeEvent(window(), rect); + if (QWindowPrivate::get(window())->isPopup() && QGuiApplicationPrivate::currentMouseWindow) { + QWindowSystemInterface::handleLeaveEvent<QWindowSystemInterface::SynchronousDelivery> + (QGuiApplicationPrivate::currentMouseWindow); + } + if (geometry().contains(cursorPos)) + QWindowSystemInterface::handleEnterEvent(window(), + window()->mapFromGlobal(cursorPos), cursorPos); } else { QWindowSystemInterface::handleExposeEvent(window(), QRegion()); + if (window()->type() & Qt::Window) { + if (QWindow *windowUnderMouse = QGuiApplication::topLevelAt(cursorPos)) { + QWindowSystemInterface::handleEnterEvent(windowUnderMouse, + windowUnderMouse->mapFromGlobal(cursorPos), + cursorPos); + } + } } m_visible = visible; @@ -142,7 +122,7 @@ void QOffscreenWindow::setVisible(bool visible) void QOffscreenWindow::requestActivateWindow() { if (m_visible) - QWindowSystemInterface::handleWindowActivated(window()); + QWindowSystemInterface::handleFocusWindowChanged(window(), Qt::ActiveWindowFocusReason); } WId QOffscreenWindow::winId() const @@ -168,7 +148,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) @@ -185,9 +165,9 @@ void QOffscreenWindow::setWindowState(Qt::WindowStates state) QOffscreenWindow *QOffscreenWindow::windowForWinId(WId id) { - return m_windowForWinIdHash.value(id, 0); + return m_windowForWinIdHash.value(id, nullptr); } -QHash<WId, QOffscreenWindow *> QOffscreenWindow::m_windowForWinIdHash; +Q_CONSTINIT QHash<WId, QOffscreenWindow *> QOffscreenWindow::m_windowForWinIdHash; QT_END_NAMESPACE diff --git a/src/plugins/platforms/offscreen/qoffscreenwindow.h b/src/plugins/platforms/offscreen/qoffscreenwindow.h index e1f37bb034..d525f2c657 100644 --- a/src/plugins/platforms/offscreen/qoffscreenwindow.h +++ b/src/plugins/platforms/offscreen/qoffscreenwindow.h @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the plugins of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QOFFSCREENWINDOW_H #define QOFFSCREENWINDOW_H @@ -50,7 +14,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,9 +38,10 @@ private: bool m_positionIncludesFrame; bool m_visible; bool m_pendingGeometryChangeOnShow; + bool m_frameMarginsRequested; WId m_winId; - static QHash<WId, QOffscreenWindow *> m_windowForWinIdHash; + Q_CONSTINIT static QHash<WId, QOffscreenWindow *> m_windowForWinIdHash; }; QT_END_NAMESPACE |