diff --git a/plugins/qpa/integration.cpp b/plugins/qpa/integration.cpp index 903ed0005..3330be436 100644 --- a/plugins/qpa/integration.cpp +++ b/plugins/qpa/integration.cpp @@ -49,9 +49,12 @@ Integration::~Integration() for (QPlatformScreen* platformScreen : std::as_const(m_screens)) { QWindowSystemInterface::handleScreenRemoved(platformScreen); } + if (m_dummyScreen) { + QWindowSystemInterface::handleScreenRemoved(m_dummyScreen); + } } -QVector Integration::screens() const +QHash Integration::screens() const { return m_screens; } @@ -83,19 +86,14 @@ void Integration::initialize() connect(base::singleton_interface::app_singleton, &base::app_singleton::platform_created, this, - [this] { - assert(base::singleton_interface::platform); - QObject::connect(base::singleton_interface::platform, - &base::platform_qobject::topology_changed, - this, - &Integration::initScreens); - initScreens(); - }); + &Integration::handle_platform_created); QPlatformIntegration::initialize(); - auto dummyScreen = new Screen(nullptr, this); - QWindowSystemInterface::handleScreenAdded(dummyScreen); - m_screens << dummyScreen; + + assert(m_screens.empty()); + assert(!m_dummyScreen); + m_dummyScreen = new placeholder_screen; + QWindowSystemInterface::handleScreenAdded(m_dummyScreen); } QAbstractEventDispatcher* Integration::createEventDispatcher() const @@ -154,30 +152,44 @@ QPlatformAccessibility* Integration::accessibility() const return m_accessibility.get(); } -void Integration::initScreens() +void Integration::handle_platform_created() { - while (!m_screens.isEmpty()) { - QWindowSystemInterface::handleScreenRemoved(m_screens.takeLast()); - } + auto platform = base::singleton_interface::platform; + assert(platform); - auto const outputs = base::singleton_interface::get_outputs(); - QVector newScreens; + assert(base::singleton_interface::get_outputs().empty()); + QObject::connect( + platform, &base::platform_qobject::output_added, this, &Integration::handle_output_added); + QObject::connect(platform, + &base::platform_qobject::output_removed, + this, + &Integration::handle_output_removed); +} - newScreens.reserve(std::max(outputs.size(), 1)); +void Integration::handle_output_added(como::base::output* output) +{ + assert(!m_screens.contains(output)); - for (auto output : outputs) { - auto screen = new Screen(output, this); - QWindowSystemInterface::handleScreenAdded(screen); - newScreens << screen; + auto screen = new Screen(output, this); + m_screens.insert(output, screen); + QWindowSystemInterface::handleScreenAdded(screen); + + if (m_dummyScreen) { + QWindowSystemInterface::handleScreenRemoved(m_dummyScreen); + m_dummyScreen = nullptr; } +} + +void Integration::handle_output_removed(como::base::output* output) +{ + assert(m_screens.contains(output)); - if (newScreens.isEmpty()) { - auto dummyScreen = new Screen(nullptr, this); - QWindowSystemInterface::handleScreenAdded(dummyScreen); - newScreens << dummyScreen; + if (m_screens.size() == 1) { + m_dummyScreen = new placeholder_screen; + QWindowSystemInterface::handleScreenAdded(m_dummyScreen); } - m_screens = newScreens; + QWindowSystemInterface::handleScreenRemoved(m_screens.take(output)); } QPlatformNativeInterface* Integration::nativeInterface() const diff --git a/plugins/qpa/integration.h b/plugins/qpa/integration.h index e95518865..0d3ac5dc4 100644 --- a/plugins/qpa/integration.h +++ b/plugins/qpa/integration.h @@ -9,15 +9,22 @@ SPDX-License-Identifier: GPL-2.0-or-later #include +#include #include #include #include namespace como { + +namespace base +{ +class output; +} namespace QPA { +class placeholder_screen; class Screen; class Integration : public QObject, public QPlatformIntegration @@ -42,16 +49,18 @@ class Integration : public QObject, public QPlatformIntegration QPlatformServices* services() const override; void initialize() override; - QVector screens() const; + QHash screens() const; private: - void initScreens(); + void handle_platform_created(); + void handle_output_added(como::base::output*); + void handle_output_removed(como::base::output*); std::unique_ptr m_fontDb; mutable std::unique_ptr m_accessibility; QScopedPointer m_nativeInterface; - Screen* m_dummyScreen = nullptr; - QVector m_screens; + placeholder_screen* m_dummyScreen{nullptr}; + QHash m_screens; QScopedPointer m_services; }; diff --git a/plugins/qpa/screen.cpp b/plugins/qpa/screen.cpp index df8b11894..cb9c22602 100644 --- a/plugins/qpa/screen.cpp +++ b/plugins/qpa/screen.cpp @@ -9,18 +9,31 @@ SPDX-License-Identifier: GPL-2.0-or-later #include "platformcursor.h" #include +#include -namespace como +namespace como::QPA { -namespace QPA + +namespace +{ +int get_forced_dpi() { + return qEnvironmentVariableIsSet("QT_WAYLAND_FORCE_DPI") + ? qEnvironmentVariableIntValue("QT_WAYLAND_FORCE_DPI") + : -1; +} +} Screen::Screen(base::output* output, Integration* integration) - : QPlatformScreen() - , output{output} + : output{output} , m_cursor(new PlatformCursor) , m_integration(integration) { + QObject::connect(output->qobject.get(), &base::output_qobject::geometry_changed, this, [this] { + QWindowSystemInterface::handleScreenGeometryChange(screen(), geometry(), geometry()); + }); + QObject::connect( + output->qobject.get(), &QObject::destroyed, this, [this] { this->output = nullptr; }); } Screen::~Screen() = default; @@ -66,14 +79,12 @@ QPlatformCursor* Screen::cursor() const QDpi Screen::logicalDpi() const { - static int forceDpi = qEnvironmentVariableIsSet("QT_WAYLAND_FORCE_DPI") - ? qEnvironmentVariableIntValue("QT_WAYLAND_FORCE_DPI") - : -1; - if (forceDpi > 0) { - return QDpi(forceDpi, forceDpi); + auto const dpi = get_forced_dpi(); + if (dpi > 0) { + return {dpi, dpi}; } - return QDpi(96, 96); + return {96, 96}; } qreal Screen::devicePixelRatio() const @@ -86,5 +97,10 @@ QString Screen::name() const return output ? output->name() : QString(); } +QDpi placeholder_screen::logicalDpi() const +{ + auto const dpi = get_forced_dpi(); + return dpi > 0 ? QDpi{dpi, dpi} : QDpi{96, 96}; } + } diff --git a/plugins/qpa/screen.h b/plugins/qpa/screen.h index 365a08370..069e5710d 100644 --- a/plugins/qpa/screen.h +++ b/plugins/qpa/screen.h @@ -20,7 +20,7 @@ namespace QPA class Integration; class PlatformCursor; -class Screen : public QPlatformScreen +class Screen : public QPlatformScreen, public QObject { public: explicit Screen(base::output* output, Integration* integration); @@ -42,6 +42,12 @@ class Screen : public QPlatformScreen Integration* m_integration; }; +class placeholder_screen : public QPlatformPlaceholderScreen +{ +public: + QDpi logicalDpi() const override; +}; + } }