plugins/qpa: Improve handling of output addition and removal
With this change, the QPA will try to avoid re-creating all platform screens if a single output has been connected or disconnected.
This commit is contained in:
parent
5943eea4c9
commit
fb0bcff1c8
6 changed files with 119 additions and 44 deletions
1
main.cpp
1
main.cpp
|
@ -450,6 +450,7 @@ void Application::initPlatform(const KPluginMetaData &plugin)
|
|||
}
|
||||
}
|
||||
}
|
||||
emit platformCreated();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
1
main.h
1
main.h
|
@ -197,6 +197,7 @@ Q_SIGNALS:
|
|||
void x11ConnectionAboutToBeDestroyed();
|
||||
void workspaceCreated();
|
||||
void screensCreated();
|
||||
void platformCreated();
|
||||
void virtualTerminalCreated();
|
||||
void started();
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
#include "integration.h"
|
||||
#include "abstract_output.h"
|
||||
#include "backingstore.h"
|
||||
#include "eglplatformcontext.h"
|
||||
#include "logging.h"
|
||||
|
@ -46,6 +47,9 @@ Integration::~Integration()
|
|||
for (QPlatformScreen *platformScreen : m_screens) {
|
||||
QWindowSystemInterface::handleScreenRemoved(platformScreen);
|
||||
}
|
||||
if (m_dummyScreen) {
|
||||
QWindowSystemInterface::handleScreenRemoved(m_dummyScreen);
|
||||
}
|
||||
}
|
||||
|
||||
bool Integration::hasCapability(Capability cap) const
|
||||
|
@ -71,16 +75,13 @@ bool Integration::hasCapability(Capability cap) const
|
|||
|
||||
void Integration::initialize()
|
||||
{
|
||||
connect(kwinApp(), &Application::screensCreated, this,
|
||||
[this] {
|
||||
connect(screens(), &Screens::changed, this, &Integration::initScreens);
|
||||
initScreens();
|
||||
}
|
||||
);
|
||||
// The QPA is initialized before the platform plugin is loaded.
|
||||
connect(kwinApp(), &Application::platformCreated, this, &Integration::handlePlatformCreated);
|
||||
|
||||
QPlatformIntegration::initialize();
|
||||
auto dummyScreen = new Screen(-1);
|
||||
QWindowSystemInterface::handleScreenAdded(dummyScreen);
|
||||
m_screens << dummyScreen;
|
||||
|
||||
m_dummyScreen = new PlaceholderScreen();
|
||||
QWindowSystemInterface::handleScreenAdded(m_dummyScreen);
|
||||
}
|
||||
|
||||
QAbstractEventDispatcher *Integration::createEventDispatcher() const
|
||||
|
@ -135,24 +136,44 @@ QPlatformOpenGLContext *Integration::createPlatformOpenGLContext(QOpenGLContext
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
void Integration::initScreens()
|
||||
void Integration::handlePlatformCreated()
|
||||
{
|
||||
QVector<Screen*> newScreens;
|
||||
newScreens.reserve(qMax(screens()->count(), 1));
|
||||
for (int i = 0; i < screens()->count(); i++) {
|
||||
auto screen = new Screen(i);
|
||||
QWindowSystemInterface::handleScreenAdded(screen);
|
||||
newScreens << screen;
|
||||
connect(kwinApp()->platform(), &Platform::outputEnabled,
|
||||
this, &Integration::handleOutputEnabled);
|
||||
connect(kwinApp()->platform(), &Platform::outputDisabled,
|
||||
this, &Integration::handleOutputDisabled);
|
||||
|
||||
const QVector<AbstractOutput *> outputs = kwinApp()->platform()->enabledOutputs();
|
||||
for (AbstractOutput *output : outputs) {
|
||||
handleOutputEnabled(output);
|
||||
}
|
||||
if (newScreens.isEmpty()) {
|
||||
auto dummyScreen = new Screen(-1);
|
||||
QWindowSystemInterface::handleScreenAdded(dummyScreen);
|
||||
newScreens << dummyScreen;
|
||||
}
|
||||
|
||||
void Integration::handleOutputEnabled(AbstractOutput *output)
|
||||
{
|
||||
Screen *platformScreen = new Screen(output);
|
||||
QWindowSystemInterface::handleScreenAdded(platformScreen);
|
||||
|
||||
if (m_dummyScreen) {
|
||||
QWindowSystemInterface::handleScreenRemoved(m_dummyScreen);
|
||||
m_dummyScreen = nullptr;
|
||||
}
|
||||
while (!m_screens.isEmpty()) {
|
||||
QWindowSystemInterface::handleScreenRemoved(m_screens.takeLast());
|
||||
}
|
||||
|
||||
void Integration::handleOutputDisabled(AbstractOutput *output)
|
||||
{
|
||||
Screen *platformScreen = m_screens.take(output);
|
||||
if (!platformScreen) {
|
||||
qCWarning(KWIN_QPA) << "Unknown output" << output;
|
||||
return;
|
||||
}
|
||||
m_screens = newScreens;
|
||||
|
||||
if (m_screens.isEmpty()) {
|
||||
m_dummyScreen = new PlaceholderScreen();
|
||||
QWindowSystemInterface::handleScreenAdded(m_dummyScreen);
|
||||
}
|
||||
|
||||
QWindowSystemInterface::handleScreenRemoved(platformScreen);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -19,6 +19,9 @@
|
|||
|
||||
namespace KWin
|
||||
{
|
||||
|
||||
class AbstractOutput;
|
||||
|
||||
namespace QPA
|
||||
{
|
||||
|
||||
|
@ -43,13 +46,16 @@ public:
|
|||
|
||||
void initialize() override;
|
||||
|
||||
private:
|
||||
void initScreens();
|
||||
private Q_SLOTS:
|
||||
void handleOutputEnabled(AbstractOutput *output);
|
||||
void handleOutputDisabled(AbstractOutput *output);
|
||||
void handlePlatformCreated();
|
||||
|
||||
private:
|
||||
QScopedPointer<QPlatformFontDatabase> m_fontDb;
|
||||
QPlatformNativeInterface *m_nativeInterface;
|
||||
Screen *m_dummyScreen = nullptr;
|
||||
QVector<Screen*> m_screens;
|
||||
QPlatformPlaceholderScreen *m_dummyScreen = nullptr;
|
||||
QHash<AbstractOutput *, Screen *> m_screens;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -7,19 +7,27 @@
|
|||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
#include "screen.h"
|
||||
#include "abstract_output.h"
|
||||
#include "logging.h"
|
||||
#include "platformcursor.h"
|
||||
#include "screens.h"
|
||||
|
||||
#include <qpa/qwindowsysteminterface.h>
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
namespace QPA
|
||||
{
|
||||
|
||||
Screen::Screen(int screen)
|
||||
: QPlatformScreen()
|
||||
, m_screen(screen)
|
||||
static int forcedDpi()
|
||||
{
|
||||
return qEnvironmentVariableIsSet("QT_WAYLAND_FORCE_DPI") ? qEnvironmentVariableIntValue("QT_WAYLAND_FORCE_DPI") : -1;
|
||||
}
|
||||
|
||||
Screen::Screen(AbstractOutput *output)
|
||||
: m_output(output)
|
||||
, m_cursor(new PlatformCursor)
|
||||
{
|
||||
connect(output, &AbstractOutput::geometryChanged, this, &Screen::handleGeometryChanged);
|
||||
}
|
||||
|
||||
Screen::~Screen() = default;
|
||||
|
@ -36,12 +44,20 @@ QImage::Format Screen::format() const
|
|||
|
||||
QRect Screen::geometry() const
|
||||
{
|
||||
return m_screen != -1 ? screens()->geometry(m_screen) : QRect(0, 0, 1, 1);
|
||||
if (Q_UNLIKELY(!m_output)) {
|
||||
qCCritical(KWIN_QPA) << "Attempting to get the geometry of a destroyed output";
|
||||
return QRect();
|
||||
}
|
||||
return m_output->geometry();
|
||||
}
|
||||
|
||||
QSizeF Screen::physicalSize() const
|
||||
{
|
||||
return m_screen != -1 ? screens()->physicalSize(m_screen) : QPlatformScreen::physicalSize();
|
||||
if (Q_UNLIKELY(!m_output)) {
|
||||
qCCritical(KWIN_QPA) << "Attempting to get the physical size of a destroyed output";
|
||||
return QSizeF();
|
||||
}
|
||||
return m_output->physicalSize();
|
||||
}
|
||||
|
||||
QPlatformCursor *Screen::cursor() const
|
||||
|
@ -51,22 +67,37 @@ 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);
|
||||
}
|
||||
|
||||
return QDpi(96, 96);
|
||||
const int dpi = forcedDpi();
|
||||
return dpi > 0 ? QDpi(dpi, dpi) : QDpi(96, 96);
|
||||
}
|
||||
|
||||
qreal Screen::devicePixelRatio() const
|
||||
{
|
||||
return m_screen != -1 ? screens()->scale(m_screen) : 1.0;
|
||||
if (Q_UNLIKELY(!m_output)) {
|
||||
qCCritical(KWIN_QPA) << "Attempting to get the scale factor of a destroyed output";
|
||||
return 1;
|
||||
}
|
||||
return m_output->scale();
|
||||
}
|
||||
|
||||
QString Screen::name() const
|
||||
{
|
||||
return m_screen != -1 ? screens()->name(m_screen) : QString();
|
||||
if (Q_UNLIKELY(!m_output)) {
|
||||
qCCritical(KWIN_QPA) << "Attempting to get the name of a destroyed output";
|
||||
return QString();
|
||||
}
|
||||
return m_output->name();
|
||||
}
|
||||
|
||||
void Screen::handleGeometryChanged()
|
||||
{
|
||||
QWindowSystemInterface::handleScreenGeometryChange(screen(), geometry(), geometry());
|
||||
}
|
||||
|
||||
QDpi PlaceholderScreen::logicalDpi() const
|
||||
{
|
||||
const int dpi = forcedDpi();
|
||||
return dpi > 0 ? QDpi(dpi, dpi) : QDpi(96, 96);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -10,18 +10,24 @@
|
|||
#define KWIN_QPA_SCREEN_H
|
||||
|
||||
#include <qpa/qplatformscreen.h>
|
||||
|
||||
#include <QPointer>
|
||||
#include <QScopedPointer>
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
class AbstractOutput;
|
||||
|
||||
namespace QPA
|
||||
{
|
||||
class PlatformCursor;
|
||||
|
||||
class Screen : public QPlatformScreen
|
||||
class Screen : public QObject, public QPlatformScreen
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit Screen(int screen);
|
||||
explicit Screen(AbstractOutput *output);
|
||||
~Screen() override;
|
||||
|
||||
QString name() const override;
|
||||
|
@ -33,11 +39,20 @@ public:
|
|||
QDpi logicalDpi() const override;
|
||||
qreal devicePixelRatio() const override;
|
||||
|
||||
private Q_SLOTS:
|
||||
void handleGeometryChanged();
|
||||
|
||||
private:
|
||||
int m_screen;
|
||||
QPointer<AbstractOutput> m_output;
|
||||
QScopedPointer<PlatformCursor> m_cursor;
|
||||
};
|
||||
|
||||
class PlaceholderScreen : public QPlatformPlaceholderScreen
|
||||
{
|
||||
public:
|
||||
QDpi logicalDpi() const override;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue