diff --git a/CMakeLists.txt b/CMakeLists.txt
index 2de1a9a6af..d31a9abf67 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -470,6 +470,7 @@ set(kwin_KDEINIT_SRCS
decorations/decorations_logging.cpp
platform.cpp
abstract_output.cpp
+ abstract_wayland_output.cpp
shell_client.cpp
wayland_server.cpp
wayland_cursor_theme.cpp
diff --git a/abstract_output.cpp b/abstract_output.cpp
index eaba345c76..1536697c90 100644
--- a/abstract_output.cpp
+++ b/abstract_output.cpp
@@ -18,12 +18,7 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see .
*********************************************************************/
#include "abstract_output.h"
-#include "wayland_server.h"
-// KWayland
-#include
-#include
-#include
// KF5
#include
@@ -39,224 +34,6 @@ AbstractOutput::AbstractOutput(QObject *parent)
AbstractOutput::~AbstractOutput()
{
- delete m_waylandOutputDevice.data();
- delete m_xdgOutput.data();
- delete m_waylandOutput.data();
-}
-
-QString AbstractOutput::name() const
-{
- if (!m_waylandOutput) {
- return i18n("unknown");
- }
- return QStringLiteral("%1 %2").arg(m_waylandOutput->manufacturer()).arg(m_waylandOutput->model());
-}
-
-QRect AbstractOutput::geometry() const
-{
- return QRect(m_globalPos, pixelSize() / scale());
-}
-
-QSize AbstractOutput::physicalSize() const
-{
- return orientateSize(m_physicalSize);
-}
-
-int AbstractOutput::refreshRate() const
-{
- if (!m_waylandOutput) {
- return 60000;
- }
- return m_waylandOutput->refreshRate();
-}
-
-void AbstractOutput::setGlobalPos(const QPoint &pos)
-{
- m_globalPos = pos;
- if (m_waylandOutput) {
- m_waylandOutput->setGlobalPosition(pos);
- }
- if (m_waylandOutputDevice) {
- m_waylandOutputDevice->setGlobalPosition(pos);
- }
- if (m_xdgOutput) {
- m_xdgOutput->setLogicalPosition(pos);
- m_xdgOutput->done();
- }
-}
-
-void AbstractOutput::setScale(qreal scale)
-{
- m_scale = scale;
- if (m_waylandOutput) {
- // this is the scale that clients will ideally use for their buffers
- // this has to be an int which is fine
-
- // I don't know whether we want to round or ceil
- // or maybe even set this to 3 when we're scaling to 1.5
- // don't treat this like it's chosen deliberately
- m_waylandOutput->setScale(std::ceil(scale));
- }
- if (m_waylandOutputDevice) {
- m_waylandOutputDevice->setScaleF(scale);
- }
- if (m_xdgOutput) {
- m_xdgOutput->setLogicalSize(pixelSize() / m_scale);
- m_xdgOutput->done();
- }
- emit modeChanged();
-}
-
-void AbstractOutput::setChanges(KWayland::Server::OutputChangeSet *changes)
-{
- qCDebug(KWIN_CORE) << "Set changes in AbstractOutput.";
- Q_ASSERT(!m_waylandOutputDevice.isNull());
-
- if (!changes) {
- qCDebug(KWIN_CORE) << "No changes.";
- // No changes to an output is an entirely valid thing
- }
- //enabledChanged is handled by plugin code
- if (changes->modeChanged()) {
- qCDebug(KWIN_CORE) << "Setting new mode:" << changes->mode();
- m_waylandOutputDevice->setCurrentMode(changes->mode());
- updateMode(changes->mode());
- }
- if (changes->transformChanged()) {
- qCDebug(KWIN_CORE) << "Server setting transform: " << (int)(changes->transform());
- transform(changes->transform());
- }
- if (changes->positionChanged()) {
- qCDebug(KWIN_CORE) << "Server setting position: " << changes->position();
- setGlobalPos(changes->position());
- // may just work already!
- }
- if (changes->scaleChanged()) {
- qCDebug(KWIN_CORE) << "Setting scale:" << changes->scale();
- setScale(changes->scaleF());
- }
-}
-
-void AbstractOutput::setEnabled(bool enable)
-{
- if (enable == isEnabled()) {
- return;
- }
- if (enable) {
- updateDpms(KWayland::Server::OutputInterface::DpmsMode::On);
- initWaylandOutput();
- } else {
- updateDpms(KWayland::Server::OutputInterface::DpmsMode::Off);
- delete waylandOutput().data();
- }
- waylandOutputDevice()->setEnabled(enable ? KWayland::Server::OutputDeviceInterface::Enablement::Enabled :
- KWayland::Server::OutputDeviceInterface::Enablement::Disabled);
-}
-
-void AbstractOutput::setWaylandMode(const QSize &size, int refreshRate)
-{
- if (m_waylandOutput.isNull()) {
- return;
- }
- m_waylandOutput->setCurrentMode(size, refreshRate);
- if (m_xdgOutput) {
- m_xdgOutput->setLogicalSize(pixelSize() / scale());
- m_xdgOutput->done();
- }
-}
-
-void AbstractOutput::createXdgOutput()
-{
- if (!m_waylandOutput || m_xdgOutput) {
- return;
- }
- m_xdgOutput = waylandServer()->xdgOutputManager()->createXdgOutput(m_waylandOutput, m_waylandOutput);
- m_xdgOutput->setLogicalSize(pixelSize() / scale());
- m_xdgOutput->setLogicalPosition(m_globalPos);
- m_xdgOutput->done();
-}
-
-void AbstractOutput::initWaylandOutput()
-{
- Q_ASSERT(m_waylandOutputDevice);
-
- if (!m_waylandOutput.isNull()) {
- delete m_waylandOutput.data();
- m_waylandOutput.clear();
- }
- m_waylandOutput = waylandServer()->display()->createOutput();
- createXdgOutput();
-
- /*
- * add base wayland output data
- */
- m_waylandOutput->setManufacturer(m_waylandOutputDevice->manufacturer());
- m_waylandOutput->setModel(m_waylandOutputDevice->model());
- m_waylandOutput->setPhysicalSize(rawPhysicalSize());
-
- /*
- * add modes
- */
- for(const auto &mode: m_waylandOutputDevice->modes()) {
- KWayland::Server::OutputInterface::ModeFlags flags;
- if (mode.flags & KWayland::Server::OutputDeviceInterface::ModeFlag::Current) {
- flags |= KWayland::Server::OutputInterface::ModeFlag::Current;
- }
- if (mode.flags & KWayland::Server::OutputDeviceInterface::ModeFlag::Preferred) {
- flags |= KWayland::Server::OutputInterface::ModeFlag::Preferred;
- }
- m_waylandOutput->addMode(mode.size, flags, mode.refreshRate);
- }
- m_waylandOutput->create();
-
- /*
- * set dpms
- */
- m_waylandOutput->setDpmsSupported(m_supportsDpms);
- // set to last known mode
- m_waylandOutput->setDpmsMode(m_dpms);
- connect(m_waylandOutput.data(), &KWayland::Server::OutputInterface::dpmsModeRequested, this,
- [this] (KWayland::Server::OutputInterface::DpmsMode mode) {
- updateDpms(mode);
- }, Qt::QueuedConnection
- );
-}
-
-void AbstractOutput::initWaylandOutputDevice(const QString &model,
- const QString &manufacturer,
- const QByteArray &uuid,
- const QVector &modes)
-{
- if (!m_waylandOutputDevice.isNull()) {
- delete m_waylandOutputDevice.data();
- m_waylandOutputDevice.clear();
- }
- m_waylandOutputDevice = waylandServer()->display()->createOutputDevice();
- m_waylandOutputDevice->setUuid(uuid);
-
- if (!manufacturer.isEmpty()) {
- m_waylandOutputDevice->setManufacturer(manufacturer);
- } else {
- m_waylandOutputDevice->setManufacturer(i18n("unknown"));
- }
-
- m_waylandOutputDevice->setModel(model);
- m_waylandOutputDevice->setPhysicalSize(m_physicalSize);
-
- int i = 0;
- for (auto mode : modes) {
- qCDebug(KWIN_CORE).nospace() << "Adding mode " << ++i << ": " << mode.size << " [" << mode.refreshRate << "]";
- m_waylandOutputDevice->addMode(mode);
- }
- m_waylandOutputDevice->create();
-}
-
-QSize AbstractOutput::orientateSize(const QSize &size) const
-{
- if (m_orientation == Qt::PortraitOrientation || m_orientation == Qt::InvertedPortraitOrientation) {
- return size.transposed();
- }
- return size;
}
}
diff --git a/abstract_output.h b/abstract_output.h
index f6bd238d73..63ae4ba1dd 100644
--- a/abstract_output.h
+++ b/abstract_output.h
@@ -2,7 +2,7 @@
KWin - the KDE window manager
This file is part of the KDE project.
-Copyright 2018 Roman Gilg
+Copyright 2019 Roman Gilg
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -17,33 +17,14 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
*********************************************************************/
-#ifndef KWIN_OUTPUT_H
-#define KWIN_OUTPUT_H
+#ifndef KWIN_ABSTRACT_OUTPUT_H
+#define KWIN_ABSTRACT_OUTPUT_H
-#include
#include
#include
-#include
-#include
#include
#include
-#include
-
-#include
-#include
-
-namespace KWayland
-{
-namespace Server
-{
-class OutputInterface;
-class OutputDeviceInterface;
-class OutputChangeSet;
-class OutputManagementInterface;
-class XdgOutputInterface;
-}
-}
namespace KWin
{
@@ -62,52 +43,26 @@ public:
explicit AbstractOutput(QObject *parent = nullptr);
virtual ~AbstractOutput();
- QString name() const;
- bool isEnabled() const {
- return !m_waylandOutput.isNull();
- }
-
- virtual QSize pixelSize() const = 0;
- qreal scale() const {
- return m_scale;
- }
- /**
- * The geometry of this output in global compositor co-ordinates (i.e scaled)
- **/
- QRect geometry() const;
- QSize physicalSize() const;
- Qt::ScreenOrientation orientation() const {
- return m_orientation;
- }
+ virtual QString name() const = 0;
+ virtual QRect geometry() const = 0;
/**
* Current refresh rate in 1/ms.
**/
- int refreshRate() const;
+ virtual int refreshRate() const = 0;
- bool isInternal() const {
- return m_internal;
+ virtual bool isInternal() const {
+ return false;
}
-
- void setGlobalPos(const QPoint &pos);
- void setScale(qreal scale);
-
- /**
- * This sets the changes and tests them against the specific output.
- **/
- void setChanges(KWayland::Server::OutputChangeSet *changeset);
-
- QPointer waylandOutput() const {
- return m_waylandOutput;
+ virtual qreal scale() const {
+ return 1.;
+ }
+ virtual QSize physicalSize() const {
+ return QSize();
+ }
+ virtual Qt::ScreenOrientation orientation() const {
+ return Qt::PrimaryOrientation;
}
-
- /**
- * Enable or disable the output.
- *
- * This differs from updateDpms as it also removes the wl_output.
- * The default is on.
- **/
- void setEnabled(bool enable);
virtual int getGammaRampSize() const {
return 0;
@@ -116,75 +71,8 @@ public:
Q_UNUSED(gamma);
return false;
}
-
-Q_SIGNALS:
- void modeChanged();
-
-protected:
- void initWaylandOutput();
- void initWaylandOutputDevice(const QString &model,
- const QString &manufacturer,
- const QByteArray &uuid,
- const QVector &modes);
-
- QPointer xdgOutput() const {
- return m_xdgOutput;
- }
- void createXdgOutput();
-
- QPointer waylandOutputDevice() const {
- return m_waylandOutputDevice;
- }
-
- QPoint globalPos() const {
- return m_globalPos;
- }
-
- QSize rawPhysicalSize() const {
- return m_physicalSize;
- }
- void setRawPhysicalSize(const QSize &set) {
- m_physicalSize = set;
- }
-
- void setOrientation(Qt::ScreenOrientation set) {
- m_orientation = set;
- }
- void setInternal(bool set) {
- m_internal = set;
- }
- void setDpmsSupported(bool set) {
- m_supportsDpms = set;
- }
- virtual void updateDpms(KWayland::Server::OutputInterface::DpmsMode mode) {
- Q_UNUSED(mode);
- }
- virtual void updateMode(int modeIndex) {
- Q_UNUSED(modeIndex);
- }
- virtual void transform(KWayland::Server::OutputDeviceInterface::Transform transform) {
- Q_UNUSED(transform);
- }
-
- void setWaylandMode(const QSize &size, int refreshRate);
-
- QSize orientateSize(const QSize &size) const;
-
-private:
- QPointer m_waylandOutput;
- QPointer m_xdgOutput;
- QPointer m_waylandOutputDevice;
-
- KWayland::Server::OutputInterface::DpmsMode m_dpms = KWayland::Server::OutputInterface::DpmsMode::On;
-
- QPoint m_globalPos;
- qreal m_scale = 1;
- QSize m_physicalSize;
- Qt::ScreenOrientation m_orientation = Qt::PrimaryOrientation;
- bool m_internal = false;
- bool m_supportsDpms = false;
};
}
-#endif // KWIN_OUTPUT_H
+#endif
diff --git a/abstract_wayland_output.cpp b/abstract_wayland_output.cpp
new file mode 100644
index 0000000000..c08a073046
--- /dev/null
+++ b/abstract_wayland_output.cpp
@@ -0,0 +1,259 @@
+/********************************************************************
+ KWin - the KDE window manager
+ This file is part of the KDE project.
+
+Copyright 2019 Roman Gilg
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
+*********************************************************************/
+#include "abstract_wayland_output.h"
+#include "wayland_server.h"
+
+// KWayland
+#include
+#include
+#include
+// KF5
+#include
+
+#include
+
+namespace KWin
+{
+
+AbstractWaylandOutput::AbstractWaylandOutput(QObject *parent)
+ : AbstractOutput(parent)
+{
+}
+
+AbstractWaylandOutput::~AbstractWaylandOutput()
+{
+ delete m_waylandOutputDevice.data();
+ delete m_xdgOutput.data();
+ delete m_waylandOutput.data();
+}
+
+QString AbstractWaylandOutput::name() const
+{
+ if (!m_waylandOutput) {
+ return i18n("unknown");
+ }
+ return QStringLiteral("%1 %2").arg(m_waylandOutput->manufacturer()).arg(m_waylandOutput->model());
+}
+
+QRect AbstractWaylandOutput::geometry() const
+{
+ return QRect(m_globalPos, pixelSize() / scale());
+}
+
+QSize AbstractWaylandOutput::physicalSize() const
+{
+ return orientateSize(m_physicalSize);
+}
+
+int AbstractWaylandOutput::refreshRate() const
+{
+ if (!m_waylandOutput) {
+ return 60000;
+ }
+ return m_waylandOutput->refreshRate();
+}
+
+void AbstractWaylandOutput::setGlobalPos(const QPoint &pos)
+{
+ m_globalPos = pos;
+ if (m_waylandOutput) {
+ m_waylandOutput->setGlobalPosition(pos);
+ }
+ if (m_waylandOutputDevice) {
+ m_waylandOutputDevice->setGlobalPosition(pos);
+ }
+ if (m_xdgOutput) {
+ m_xdgOutput->setLogicalPosition(pos);
+ m_xdgOutput->done();
+ }
+}
+
+void AbstractWaylandOutput::setScale(qreal scale)
+{
+ m_scale = scale;
+ if (m_waylandOutput) {
+ // this is the scale that clients will ideally use for their buffers
+ // this has to be an int which is fine
+
+ // I don't know whether we want to round or ceil
+ // or maybe even set this to 3 when we're scaling to 1.5
+ // don't treat this like it's chosen deliberately
+ m_waylandOutput->setScale(std::ceil(scale));
+ }
+ if (m_waylandOutputDevice) {
+ m_waylandOutputDevice->setScaleF(scale);
+ }
+ if (m_xdgOutput) {
+ m_xdgOutput->setLogicalSize(pixelSize() / m_scale);
+ m_xdgOutput->done();
+ }
+ emit modeChanged();
+}
+
+void AbstractWaylandOutput::setChanges(KWayland::Server::OutputChangeSet *changes)
+{
+ qCDebug(KWIN_CORE) << "Set changes in AbstractWaylandOutput.";
+ Q_ASSERT(!m_waylandOutputDevice.isNull());
+
+ if (!changes) {
+ qCDebug(KWIN_CORE) << "No changes.";
+ // No changes to an output is an entirely valid thing
+ }
+ //enabledChanged is handled by plugin code
+ if (changes->modeChanged()) {
+ qCDebug(KWIN_CORE) << "Setting new mode:" << changes->mode();
+ m_waylandOutputDevice->setCurrentMode(changes->mode());
+ updateMode(changes->mode());
+ }
+ if (changes->transformChanged()) {
+ qCDebug(KWIN_CORE) << "Server setting transform: " << (int)(changes->transform());
+ transform(changes->transform());
+ }
+ if (changes->positionChanged()) {
+ qCDebug(KWIN_CORE) << "Server setting position: " << changes->position();
+ setGlobalPos(changes->position());
+ // may just work already!
+ }
+ if (changes->scaleChanged()) {
+ qCDebug(KWIN_CORE) << "Setting scale:" << changes->scale();
+ setScale(changes->scaleF());
+ }
+}
+
+void AbstractWaylandOutput::setEnabled(bool enable)
+{
+ if (enable == isEnabled()) {
+ return;
+ }
+ if (enable) {
+ updateDpms(KWayland::Server::OutputInterface::DpmsMode::On);
+ initWaylandOutput();
+ } else {
+ updateDpms(KWayland::Server::OutputInterface::DpmsMode::Off);
+ delete waylandOutput().data();
+ }
+ waylandOutputDevice()->setEnabled(enable ? KWayland::Server::OutputDeviceInterface::Enablement::Enabled :
+ KWayland::Server::OutputDeviceInterface::Enablement::Disabled);
+}
+
+void AbstractWaylandOutput::setWaylandMode(const QSize &size, int refreshRate)
+{
+ if (m_waylandOutput.isNull()) {
+ return;
+ }
+ m_waylandOutput->setCurrentMode(size, refreshRate);
+ if (m_xdgOutput) {
+ m_xdgOutput->setLogicalSize(pixelSize() / scale());
+ m_xdgOutput->done();
+ }
+}
+
+void AbstractWaylandOutput::createXdgOutput()
+{
+ if (!m_waylandOutput || m_xdgOutput) {
+ return;
+ }
+ m_xdgOutput = waylandServer()->xdgOutputManager()->createXdgOutput(m_waylandOutput, m_waylandOutput);
+}
+
+void AbstractWaylandOutput::initWaylandOutput()
+{
+ Q_ASSERT(m_waylandOutputDevice);
+
+ if (!m_waylandOutput.isNull()) {
+ delete m_waylandOutput.data();
+ m_waylandOutput.clear();
+ }
+ m_waylandOutput = waylandServer()->display()->createOutput();
+ createXdgOutput();
+
+ /*
+ * add base wayland output data
+ */
+ m_waylandOutput->setManufacturer(m_waylandOutputDevice->manufacturer());
+ m_waylandOutput->setModel(m_waylandOutputDevice->model());
+ m_waylandOutput->setPhysicalSize(rawPhysicalSize());
+
+ /*
+ * add modes
+ */
+ for(const auto &mode: m_waylandOutputDevice->modes()) {
+ KWayland::Server::OutputInterface::ModeFlags flags;
+ if (mode.flags & KWayland::Server::OutputDeviceInterface::ModeFlag::Current) {
+ flags |= KWayland::Server::OutputInterface::ModeFlag::Current;
+ }
+ if (mode.flags & KWayland::Server::OutputDeviceInterface::ModeFlag::Preferred) {
+ flags |= KWayland::Server::OutputInterface::ModeFlag::Preferred;
+ }
+ m_waylandOutput->addMode(mode.size, flags, mode.refreshRate);
+ }
+ m_waylandOutput->create();
+
+ /*
+ * set dpms
+ */
+ m_waylandOutput->setDpmsSupported(m_supportsDpms);
+ // set to last known mode
+ m_waylandOutput->setDpmsMode(m_dpms);
+ connect(m_waylandOutput.data(), &KWayland::Server::OutputInterface::dpmsModeRequested, this,
+ [this] (KWayland::Server::OutputInterface::DpmsMode mode) {
+ updateDpms(mode);
+ }, Qt::QueuedConnection
+ );
+}
+
+void AbstractWaylandOutput::initWaylandOutputDevice(const QString &model,
+ const QString &manufacturer,
+ const QByteArray &uuid,
+ const QVector &modes)
+{
+ if (!m_waylandOutputDevice.isNull()) {
+ delete m_waylandOutputDevice.data();
+ m_waylandOutputDevice.clear();
+ }
+ m_waylandOutputDevice = waylandServer()->display()->createOutputDevice();
+ m_waylandOutputDevice->setUuid(uuid);
+
+ if (!manufacturer.isEmpty()) {
+ m_waylandOutputDevice->setManufacturer(manufacturer);
+ } else {
+ m_waylandOutputDevice->setManufacturer(i18n("unknown"));
+ }
+
+ m_waylandOutputDevice->setModel(model);
+ m_waylandOutputDevice->setPhysicalSize(m_physicalSize);
+
+ int i = 0;
+ for (auto mode : modes) {
+ qCDebug(KWIN_CORE).nospace() << "Adding mode " << ++i << ": " << mode.size << " [" << mode.refreshRate << "]";
+ m_waylandOutputDevice->addMode(mode);
+ }
+ m_waylandOutputDevice->create();
+}
+
+QSize AbstractWaylandOutput::orientateSize(const QSize &size) const
+{
+ if (m_orientation == Qt::PortraitOrientation || m_orientation == Qt::InvertedPortraitOrientation) {
+ return size.transposed();
+ }
+ return size;
+}
+
+}
diff --git a/abstract_wayland_output.h b/abstract_wayland_output.h
new file mode 100644
index 0000000000..c11c3e7dc9
--- /dev/null
+++ b/abstract_wayland_output.h
@@ -0,0 +1,182 @@
+/********************************************************************
+ KWin - the KDE window manager
+ This file is part of the KDE project.
+
+Copyright 2019 Roman Gilg
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
+*********************************************************************/
+#ifndef KWIN_ABSTRACT_WAYLAND_OUTPUT_H
+#define KWIN_ABSTRACT_WAYLAND_OUTPUT_H
+
+#include "abstract_output.h"
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+
+namespace KWayland
+{
+namespace Server
+{
+class OutputInterface;
+class OutputDeviceInterface;
+class OutputChangeSet;
+class OutputManagementInterface;
+class XdgOutputInterface;
+}
+}
+
+namespace KWin
+{
+
+/**
+ * Generic output representation in a Wayland session
+ **/
+class KWIN_EXPORT AbstractWaylandOutput : public AbstractOutput
+{
+ Q_OBJECT
+public:
+ explicit AbstractWaylandOutput(QObject *parent = nullptr);
+ virtual ~AbstractWaylandOutput();
+
+ QString name() const override;
+ bool isEnabled() const {
+ return !m_waylandOutput.isNull();
+ }
+
+ virtual QSize pixelSize() const = 0;
+ qreal scale() const override {
+ return m_scale;
+ }
+ /**
+ * The geometry of this output in global compositor co-ordinates (i.e scaled)
+ **/
+ QRect geometry() const override;
+ QSize physicalSize() const override;
+ Qt::ScreenOrientation orientation() const override {
+ return m_orientation;
+ }
+
+ /**
+ * Current refresh rate in 1/ms.
+ **/
+ int refreshRate() const override;
+
+ bool isInternal() const override {
+ return m_internal;
+ }
+
+ void setGlobalPos(const QPoint &pos);
+ void setScale(qreal scale);
+
+ /**
+ * This sets the changes and tests them against the specific output.
+ **/
+ void setChanges(KWayland::Server::OutputChangeSet *changeset);
+
+ QPointer waylandOutput() const {
+ return m_waylandOutput;
+ }
+
+ /**
+ * Enable or disable the output.
+ *
+ * This differs from updateDpms as it also removes the wl_output.
+ * The default is on.
+ **/
+ void setEnabled(bool enable);
+
+Q_SIGNALS:
+ void modeChanged();
+
+protected:
+ void initWaylandOutput();
+ void initWaylandOutputDevice(const QString &model,
+ const QString &manufacturer,
+ const QByteArray &uuid,
+ const QVector &modes);
+
+ QPointer xdgOutput() const {
+ return m_xdgOutput;
+ }
+ void createXdgOutput();
+
+ QPointer waylandOutputDevice() const {
+ return m_waylandOutputDevice;
+ }
+
+ QPoint globalPos() const {
+ return m_globalPos;
+ }
+
+ QSize rawPhysicalSize() const {
+ return m_physicalSize;
+ }
+ void setRawPhysicalSize(const QSize &set) {
+ m_physicalSize = set;
+ }
+
+ void setOrientation(Qt::ScreenOrientation set) {
+ m_orientation = set;
+ }
+ bool internal() const {
+ return m_internal;
+ }
+ void setInternal(bool set) {
+ m_internal = set;
+ }
+ void setDpmsSupported(bool set) {
+ m_supportsDpms = set;
+ }
+ virtual void updateDpms(KWayland::Server::OutputInterface::DpmsMode mode) {
+ Q_UNUSED(mode);
+ }
+ virtual void updateMode(int modeIndex) {
+ Q_UNUSED(modeIndex);
+ }
+ virtual void transform(KWayland::Server::OutputDeviceInterface::Transform transform) {
+ Q_UNUSED(transform);
+ }
+
+ void setWaylandMode(const QSize &size, int refreshRate);
+
+ QSize orientateSize(const QSize &size) const;
+
+private:
+ QPointer m_waylandOutput;
+ QPointer m_xdgOutput;
+ QPointer m_waylandOutputDevice;
+
+ KWayland::Server::OutputInterface::DpmsMode m_dpms = KWayland::Server::OutputInterface::DpmsMode::On;
+
+ QPoint m_globalPos;
+ qreal m_scale = 1;
+ QSize m_physicalSize;
+ Qt::ScreenOrientation m_orientation = Qt::PrimaryOrientation;
+ bool m_internal = false;
+ bool m_supportsDpms = false;
+};
+
+}
+
+#endif // KWIN_OUTPUT_H
diff --git a/autotests/CMakeLists.txt b/autotests/CMakeLists.txt
index 0aed9e5edc..d80a6f4cc7 100644
--- a/autotests/CMakeLists.txt
+++ b/autotests/CMakeLists.txt
@@ -259,48 +259,6 @@ target_link_libraries(testScreens
add_test(NAME kwin_testScreens COMMAND testScreens)
ecm_mark_as_test(testScreens)
-########################################################
-# Test XrandRScreens
-########################################################
-set( testXRandRScreens_SRCS
- test_xrandr_screens.cpp
- mock_abstract_client.cpp
- mock_client.cpp
- mock_screens.cpp
- mock_workspace.cpp
- ../screens.cpp
- ../plugins/platforms/x11/standalone/screens_xrandr.cpp
- ../xcbutils.cpp # init of extensions
- ../x11eventfilter.cpp
- ../orientation_sensor.cpp
-)
-kconfig_add_kcfg_files(testXRandRScreens_SRCS ../settings.kcfgc)
-qt5_add_dbus_adaptor( testXRandRScreens_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/../org.kde.kwin.OrientationSensor.xml ${CMAKE_CURRENT_SOURCE_DIR}/../orientation_sensor.h KWin::OrientationSensor)
-add_executable( testXRandRScreens ${testXRandRScreens_SRCS} )
-target_link_libraries( testXRandRScreens
- Qt5::Test
- Qt5::DBus
- Qt5::Gui
- Qt5::Sensors
- Qt5::Widgets
- KF5::ConfigCore
- KF5::ConfigGui
- KF5::I18n
- KF5::Notifications
- KF5::WindowSystem
- XCB::XCB
- XCB::RANDR
- XCB::XFIXES
- XCB::SYNC
- XCB::COMPOSITE
- XCB::DAMAGE
- XCB::GLX
- XCB::SHM
-)
-
-add_test(NAME kwin-testXRandRScreens COMMAND testXRandRScreens)
-ecm_mark_as_test(testXRandRScreens)
-
########################################################
# Test ScreenEdges
########################################################
diff --git a/autotests/test_xrandr_screens.cpp b/autotests/test_xrandr_screens.cpp
deleted file mode 100644
index e0f6b14a53..0000000000
--- a/autotests/test_xrandr_screens.cpp
+++ /dev/null
@@ -1,287 +0,0 @@
-/********************************************************************
-KWin - the KDE window manager
-This file is part of the KDE project.
-
-Copyright (C) 2014 Martin Gräßlin
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see .
-*********************************************************************/
-#include "../plugins/platforms/x11/standalone/screens_xrandr.h"
-#include "../cursor.h"
-#include "../xcbutils.h"
-#include "mock_workspace.h"
-// Qt
-#include
-// system
-#include
-
-Q_LOGGING_CATEGORY(KWIN_CORE, "kwin_core")
-
-// mocking
-namespace KWin
-{
-
-QPoint Cursor::pos()
-{
- return QPoint(0, 0);
-}
-} // namespace KWin
-
-static xcb_window_t s_rootWindow = XCB_WINDOW_NONE;
-static xcb_connection_t *s_connection = nullptr;
-
-using namespace KWin;
-using namespace KWin::Xcb;
-
-class TestXRandRScreens : public QObject
-{
- Q_OBJECT
-private Q_SLOTS:
- void initTestCase();
- void cleanupTestCase();
- void testStartup();
- void testChange();
- void testMultipleChanges();
-private:
- QScopedPointer m_xserver;
-};
-
-void TestXRandRScreens::initTestCase()
-{
- // TODO: turn into init instead of initTestCase
- // needs to be initTestCase as KWin::connection caches the first created xcb_connection_t
- // thus changing X server for each test run would create problems
- qsrand(QDateTime::currentMSecsSinceEpoch());
- // first reset just to be sure
- s_connection = nullptr;
- s_rootWindow = XCB_WINDOW_NONE;
- // start X Server
- m_xserver.reset(new QProcess);
- // use pipe to pass fd to Xephyr to get back the display id
- int pipeFds[2];
- QVERIFY(pipe(pipeFds) == 0);
- // using Xephyr as Xvfb doesn't support render extension
- m_xserver->start(QStringLiteral("Xephyr"), QStringList({ QStringLiteral("-displayfd"), QString::number(pipeFds[1]) }));
- QVERIFY(m_xserver->waitForStarted());
- QCOMPARE(m_xserver->state(), QProcess::Running);
-
- // reads from pipe, closes write side
- close(pipeFds[1]);
-
- QFile readPipe;
- QVERIFY(readPipe.open(pipeFds[0], QIODevice::ReadOnly, QFileDevice::AutoCloseHandle));
- QByteArray displayNumber = readPipe.readLine();
- readPipe.close();
-
- displayNumber.prepend(QByteArray(":"));
- displayNumber.remove(displayNumber.size() -1, 1);
-
- // create X connection
- int screen = 0;
- s_connection = xcb_connect(displayNumber.constData(), &screen);
- QVERIFY(s_connection);
-
- // set root window
- xcb_screen_iterator_t iter = xcb_setup_roots_iterator(xcb_get_setup(s_connection));
- for (xcb_screen_iterator_t it = xcb_setup_roots_iterator(xcb_get_setup(s_connection));
- it.rem;
- --screen, xcb_screen_next(&it)) {
- if (screen == 0) {
- s_rootWindow = iter.data->root;
- break;
- }
- }
- QVERIFY(s_rootWindow != XCB_WINDOW_NONE);
- qApp->setProperty("x11RootWindow", QVariant::fromValue(s_rootWindow));
- qApp->setProperty("x11Connection", QVariant::fromValue(s_connection));
-
- // get the extensions
- if (!Extensions::self()->isRandrAvailable()) {
- QSKIP("XRandR extension required");
- }
- for (const auto &extension : Extensions::self()->extensions()) {
- if (extension.name == QByteArrayLiteral("RANDR")) {
- if (extension.version < 1 * 0x10 + 4) {
- QSKIP("At least XRandR 1.4 required");
- }
- }
- }
-}
-
-void TestXRandRScreens::cleanupTestCase()
-{
- Extensions::destroy();
- // close connection
- xcb_disconnect(s_connection);
- s_connection = nullptr;
- s_rootWindow = XCB_WINDOW_NONE;
- // kill X
- m_xserver->terminate();
- m_xserver->waitForFinished();
-}
-
-void TestXRandRScreens::testStartup()
-{
- KWin::MockWorkspace ws;
- QScopedPointer screens(new XRandRScreens(this));
- QVERIFY(!screens->eventTypes().isEmpty());
- QCOMPARE(screens->eventTypes().first(), Xcb::Extensions::self()->randrNotifyEvent());
- QCOMPARE(screens->extension(), 0);
- QCOMPARE(screens->genericEventTypes(), QVector{0});
- screens->init();
- QRect xephyrDefault = QRect(0, 0, 640, 480);
- QCOMPARE(screens->count(), 1);
- QCOMPARE(screens->geometry(0), xephyrDefault);
- QCOMPARE(screens->geometry(1), QRect());
- QCOMPARE(screens->geometry(-1), QRect());
- QCOMPARE(static_cast(screens.data())->geometry(), xephyrDefault);
- QCOMPARE(screens->size(0), xephyrDefault.size());
- QCOMPARE(screens->size(1), QSize());
- QCOMPARE(screens->size(-1), QSize());
- QCOMPARE(static_cast(screens.data())->size(), xephyrDefault.size());
- // unfortunately we only have one output, so let's try at least to test somewhat
- QCOMPARE(screens->number(QPoint(0, 0)), 0);
- QCOMPARE(screens->number(QPoint(639, 479)), 0);
- QCOMPARE(screens->number(QPoint(1280, 1024)), 0);
-
- // let's change the mode
- RandR::CurrentResources resources(s_rootWindow);
- auto *crtcs = resources.crtcs();
- auto *modes = xcb_randr_get_screen_resources_current_modes(resources.data());
- auto *outputs = xcb_randr_get_screen_resources_current_outputs(resources.data());
- RandR::SetCrtcConfig setter(crtcs[0], resources->timestamp, resources->config_timestamp, 0, 0, modes[0].id, XCB_RANDR_ROTATION_ROTATE_0, 1, outputs);
- QVERIFY(!setter.isNull());
-
- // now let's recreate the XRandRScreens
- screens.reset(new XRandRScreens(this));
- screens->init();
- QRect geo = QRect(0, 0, modes[0].width, modes[0].height);
- QCOMPARE(screens->count(), 1);
- QCOMPARE(screens->geometry(0), geo);
- QCOMPARE(static_cast(screens.data())->geometry(), geo);
- QCOMPARE(screens->size(0), geo.size());
- QCOMPARE(static_cast(screens.data())->size(), geo.size());
-}
-
-void TestXRandRScreens::testChange()
-{
- KWin::MockWorkspace ws;
- QScopedPointer screens(new XRandRScreens(this));
- screens->init();
-
- // create some signal spys
- QSignalSpy changedSpy(screens.data(), SIGNAL(changed()));
- QVERIFY(changedSpy.isValid());
- QVERIFY(changedSpy.isEmpty());
- QVERIFY(changedSpy.wait());
- changedSpy.clear();
- QSignalSpy geometrySpy(screens.data(), SIGNAL(geometryChanged()));
- QVERIFY(geometrySpy.isValid());
- QVERIFY(geometrySpy.isEmpty());
- QSignalSpy sizeSpy(screens.data(), SIGNAL(sizeChanged()));
- QVERIFY(sizeSpy.isValid());
- QVERIFY(sizeSpy.isEmpty());
-
- // clear the event loop
- while (xcb_generic_event_t *e = xcb_poll_for_event(s_connection)) {
- free(e);
- }
-
- // let's change
- RandR::CurrentResources resources(s_rootWindow);
- auto *crtcs = resources.crtcs();
- auto *modes = xcb_randr_get_screen_resources_current_modes(resources.data());
- auto *outputs = xcb_randr_get_screen_resources_current_outputs(resources.data());
- RandR::SetCrtcConfig setter(crtcs[0], resources->timestamp, resources->config_timestamp, 0, 0, modes[1].id, XCB_RANDR_ROTATION_ROTATE_0, 1, outputs);
- xcb_flush(s_connection);
- QVERIFY(!setter.isNull());
- QVERIFY(setter->status == XCB_RANDR_SET_CONFIG_SUCCESS);
-
- xcb_generic_event_t *e = xcb_wait_for_event(s_connection);
- screens->event(e);
- free(e);
-
- QVERIFY(changedSpy.wait());
- QCOMPARE(changedSpy.size(), 1);
- QCOMPARE(sizeSpy.size(), 1);
- QCOMPARE(geometrySpy.size(), 1);
- QRect geo = QRect(0, 0, modes[1].width, modes[1].height);
- QCOMPARE(screens->count(), 1);
- QCOMPARE(screens->geometry(0), geo);
- QCOMPARE(static_cast(screens.data())->geometry(), geo);
- QCOMPARE(screens->size(0), geo.size());
- QCOMPARE(static_cast(screens.data())->size(), geo.size());
-}
-
-void TestXRandRScreens::testMultipleChanges()
-{
- KWin::MockWorkspace ws;
- // multiple changes should only hit one changed signal
- QScopedPointer screens(new XRandRScreens(this));
- screens->init();
-
- // create some signal spys
- QSignalSpy changedSpy(screens.data(), SIGNAL(changed()));
- QVERIFY(changedSpy.isValid());
- QVERIFY(changedSpy.isEmpty());
- QVERIFY(changedSpy.wait());
- changedSpy.clear();
- QSignalSpy geometrySpy(screens.data(), SIGNAL(geometryChanged()));
- QVERIFY(geometrySpy.isValid());
- QVERIFY(geometrySpy.isEmpty());
- QSignalSpy sizeSpy(screens.data(), SIGNAL(sizeChanged()));
- QVERIFY(sizeSpy.isValid());
- QVERIFY(sizeSpy.isEmpty());
-
- // clear the event loop
- while (xcb_generic_event_t *e = xcb_poll_for_event(s_connection)) {
- free(e);
- }
-
- // first change
- RandR::CurrentResources resources(s_rootWindow);
- auto *crtcs = resources.crtcs();
- auto *modes = xcb_randr_get_screen_resources_current_modes(resources.data());
- auto *outputs = xcb_randr_get_screen_resources_current_outputs(resources.data());
- RandR::SetCrtcConfig setter(crtcs[0], resources->timestamp, resources->config_timestamp, 0, 0, modes[0].id, XCB_RANDR_ROTATION_ROTATE_0, 1, outputs);
- QVERIFY(!setter.isNull());
- QVERIFY(setter->status == XCB_RANDR_SET_CONFIG_SUCCESS);
- // second change
- RandR::SetCrtcConfig setter2(crtcs[0], setter->timestamp, resources->config_timestamp, 0, 0, modes[1].id, XCB_RANDR_ROTATION_ROTATE_0, 1, outputs);
- QVERIFY(!setter2.isNull());
- QVERIFY(setter2->status == XCB_RANDR_SET_CONFIG_SUCCESS);
-
- auto passEvent = [&screens]() {
- xcb_generic_event_t *e = xcb_wait_for_event(s_connection);
- screens->event(e);
- free(e);
- };
- passEvent();
- passEvent();
-
- QVERIFY(changedSpy.wait());
- QCOMPARE(changedSpy.size(), 1);
- // previous state was modes[1] so the size didn't change
- QVERIFY(sizeSpy.isEmpty());
- QVERIFY(geometrySpy.isEmpty());
- QRect geo = QRect(0, 0, modes[1].width, modes[1].height);
- QCOMPARE(screens->count(), 1);
- QCOMPARE(screens->geometry(0), geo);
- QCOMPARE(static_cast(screens.data())->geometry(), geo);
- QCOMPARE(screens->size(0), geo.size());
- QCOMPARE(static_cast(screens.data())->size(), geo.size());
-}
-
-QTEST_GUILESS_MAIN(TestXRandRScreens)
-#include "test_xrandr_screens.moc"
diff --git a/plugins/platforms/drm/drm_output.cpp b/plugins/platforms/drm/drm_output.cpp
index 3710295624..1bce5d3a57 100644
--- a/plugins/platforms/drm/drm_output.cpp
+++ b/plugins/platforms/drm/drm_output.cpp
@@ -51,7 +51,7 @@ namespace KWin
{
DrmOutput::DrmOutput(DrmBackend *backend)
- : AbstractOutput(backend)
+ : AbstractWaylandOutput(backend)
, m_backend(backend)
{
}
@@ -180,7 +180,7 @@ void DrmOutput::moveCursor(const QPoint &globalPos)
{
const QMatrix4x4 hotspotMatrix = matrixDisplay(m_backend->softwareCursor().size());
- QPoint p = globalPos-AbstractOutput::globalPos();
+ QPoint p = globalPos - AbstractWaylandOutput::globalPos();
switch (orientation()) {
case Qt::PrimaryOrientation:
case Qt::LandscapeOrientation:
@@ -343,7 +343,7 @@ void DrmOutput::initOutputDevice(drmModeConnector *connector)
modes << mode;
}
- AbstractOutput::initWaylandOutputDevice(model, manufacturer, m_uuid, modes);
+ AbstractWaylandOutput::initWaylandOutputDevice(model, manufacturer, m_uuid, modes);
}
bool DrmOutput::isCurrentMode(const drmModeModeInfo *mode) const
@@ -819,8 +819,8 @@ QSize DrmOutput::pixelSize() const
void DrmOutput::setWaylandMode()
{
- AbstractOutput::setWaylandMode(QSize(m_mode.hdisplay, m_mode.vdisplay),
- refreshRateForMode(&m_mode));
+ AbstractWaylandOutput::setWaylandMode(QSize(m_mode.hdisplay, m_mode.vdisplay),
+ refreshRateForMode(&m_mode));
}
void DrmOutput::pageFlipped()
diff --git a/plugins/platforms/drm/drm_output.h b/plugins/platforms/drm/drm_output.h
index bc77d89919..c2199e677f 100644
--- a/plugins/platforms/drm/drm_output.h
+++ b/plugins/platforms/drm/drm_output.h
@@ -20,7 +20,7 @@ along with this program. If not, see .
#ifndef KWIN_DRM_OUTPUT_H
#define KWIN_DRM_OUTPUT_H
-#include "abstract_output.h"
+#include "abstract_wayland_output.h"
#include "drm_pointer.h"
#include "drm_object.h"
#include "drm_object_plane.h"
@@ -41,7 +41,7 @@ class DrmPlane;
class DrmConnector;
class DrmCrtc;
-class KWIN_EXPORT DrmOutput : public AbstractOutput
+class KWIN_EXPORT DrmOutput : public AbstractWaylandOutput
{
Q_OBJECT
public:
diff --git a/plugins/platforms/fbdev/fb_backend.h b/plugins/platforms/fbdev/fb_backend.h
index 8b7c8ab43c..666cf3f167 100644
--- a/plugins/platforms/fbdev/fb_backend.h
+++ b/plugins/platforms/fbdev/fb_backend.h
@@ -20,7 +20,7 @@ along with this program. If not, see .
*********************************************************************/
#ifndef KWIN_FB_BACKEND_H
#define KWIN_FB_BACKEND_H
-#include "abstract_output.h"
+#include "abstract_wayland_output.h"
#include "platform.h"
#include
@@ -29,12 +29,12 @@ along with this program. If not, see .
namespace KWin
{
-class FramebufferOutput : public AbstractOutput
+class FramebufferOutput : public AbstractWaylandOutput
{
Q_OBJECT
public:
- FramebufferOutput(QObject *parent = nullptr) : AbstractOutput(parent) {}
+ FramebufferOutput(QObject *parent = nullptr) : AbstractWaylandOutput(parent) {}
virtual ~FramebufferOutput() = default;
QSize pixelSize() const override {
@@ -45,7 +45,7 @@ public:
}
void setRawPhysicalSize(const QSize &set) {
- AbstractOutput::setRawPhysicalSize(set);
+ AbstractWaylandOutput::setRawPhysicalSize(set);
}
private:
diff --git a/plugins/platforms/hwcomposer/hwcomposer_backend.cpp b/plugins/platforms/hwcomposer/hwcomposer_backend.cpp
index da1ca11bdd..58a9b88c02 100644
--- a/plugins/platforms/hwcomposer/hwcomposer_backend.cpp
+++ b/plugins/platforms/hwcomposer/hwcomposer_backend.cpp
@@ -482,7 +482,7 @@ void HwcomposerWindow::present(HWComposerNativeWindowBuffer *buffer)
}
HwcomposerOutput::HwcomposerOutput(hwc_composer_device_1_t *device)
- : AbstractOutput()
+ : AbstractWaylandOutput()
, m_device(device)
{
uint32_t configs[5];
diff --git a/plugins/platforms/hwcomposer/hwcomposer_backend.h b/plugins/platforms/hwcomposer/hwcomposer_backend.h
index 35fbfb7af2..cadaff2684 100644
--- a/plugins/platforms/hwcomposer/hwcomposer_backend.h
+++ b/plugins/platforms/hwcomposer/hwcomposer_backend.h
@@ -20,7 +20,7 @@ along with this program. If not, see .
#ifndef KWIN_HWCOMPOSER_BACKEND_H
#define KWIN_HWCOMPOSER_BACKEND_H
#include "platform.h"
-#include "abstract_output.h"
+#include "abstract_wayland_output.h"
#include "input.h"
#include
@@ -47,7 +47,7 @@ namespace KWin
class HwcomposerWindow;
class BacklightInputEventFilter;
-class HwcomposerOutput : public AbstractOutput
+class HwcomposerOutput : public AbstractWaylandOutput
{
Q_OBJECT
public:
diff --git a/plugins/platforms/virtual/virtual_output.cpp b/plugins/platforms/virtual/virtual_output.cpp
index 05ba336604..28ede1c276 100644
--- a/plugins/platforms/virtual/virtual_output.cpp
+++ b/plugins/platforms/virtual/virtual_output.cpp
@@ -23,7 +23,7 @@ namespace KWin
{
VirtualOutput::VirtualOutput(QObject *parent)
- : AbstractOutput()
+ : AbstractWaylandOutput()
{
Q_UNUSED(parent);
diff --git a/plugins/platforms/virtual/virtual_output.h b/plugins/platforms/virtual/virtual_output.h
index 450a868699..4569c7dd07 100644
--- a/plugins/platforms/virtual/virtual_output.h
+++ b/plugins/platforms/virtual/virtual_output.h
@@ -20,7 +20,7 @@ along with this program. If not, see .
#ifndef KWIN_VIRTUAL_OUTPUT_H
#define KWIN_VIRTUAL_OUTPUT_H
-#include "abstract_output.h"
+#include "abstract_wayland_output.h"
#include
#include
@@ -29,7 +29,7 @@ namespace KWin
{
class VirtualBackend;
-class VirtualOutput : public AbstractOutput
+class VirtualOutput : public AbstractWaylandOutput
{
Q_OBJECT
diff --git a/plugins/platforms/wayland/wayland_output.cpp b/plugins/platforms/wayland/wayland_output.cpp
index 828f5d622b..07aca39123 100644
--- a/plugins/platforms/wayland/wayland_output.cpp
+++ b/plugins/platforms/wayland/wayland_output.cpp
@@ -39,7 +39,7 @@ namespace Wayland
using namespace KWayland::Client;
WaylandOutput::WaylandOutput(Surface *surface, QObject *parent)
- : AbstractOutput(parent),
+ : AbstractWaylandOutput(parent),
m_surface(surface)
{
connect(surface, &Surface::frameRendered, [this] {
diff --git a/plugins/platforms/wayland/wayland_output.h b/plugins/platforms/wayland/wayland_output.h
index 5dfbf3f38e..09e749ecb4 100644
--- a/plugins/platforms/wayland/wayland_output.h
+++ b/plugins/platforms/wayland/wayland_output.h
@@ -20,7 +20,7 @@ along with this program. If not, see .
#ifndef KWIN_WAYLAND_OUTPUT_H
#define KWIN_WAYLAND_OUTPUT_H
-#include "abstract_output.h"
+#include "abstract_wayland_output.h"
#include
@@ -46,7 +46,7 @@ namespace Wayland
{
class WaylandBackend;
-class WaylandOutput : public AbstractOutput
+class WaylandOutput : public AbstractWaylandOutput
{
Q_OBJECT
public:
diff --git a/plugins/platforms/x11/standalone/CMakeLists.txt b/plugins/platforms/x11/standalone/CMakeLists.txt
index 266ce176b3..80c139b772 100644
--- a/plugins/platforms/x11/standalone/CMakeLists.txt
+++ b/plugins/platforms/x11/standalone/CMakeLists.txt
@@ -3,6 +3,7 @@ set(X11PLATFORM_SOURCES
logging.cpp
x11cursor.cpp
x11_platform.cpp
+ x11_output.cpp
screens_xrandr.cpp
windowselector.cpp
overlaywindow_x11.cpp
diff --git a/plugins/platforms/x11/standalone/screens_xrandr.cpp b/plugins/platforms/x11/standalone/screens_xrandr.cpp
index 4f552834ca..aec04c92fb 100644
--- a/plugins/platforms/x11/standalone/screens_xrandr.cpp
+++ b/plugins/platforms/x11/standalone/screens_xrandr.cpp
@@ -18,6 +18,8 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see .
*********************************************************************/
#include "screens_xrandr.h"
+#include "x11_platform.h"
+
#ifndef KWIN_UNIT_TEST
#include "composite.h"
#include "options.h"
@@ -29,160 +31,28 @@ along with this program. If not, see .
namespace KWin
{
-XRandRScreens::XRandRScreens(QObject *parent)
- : Screens(parent)
+XRandRScreens::XRandRScreens(X11StandalonePlatform *backend, QObject *parent)
+ : OutputScreens(backend, parent)
, X11EventFilter(Xcb::Extensions::self()->randrNotifyEvent())
+ , m_backend(backend)
{
}
XRandRScreens::~XRandRScreens() = default;
-template
-void XRandRScreens::update()
-{
- auto fallback = [this]() {
- m_geometries << QRect();
- m_refreshRates << -1.0f;
- m_names << "Xinerama";
- setCount(1);
- };
- m_geometries.clear();
- m_names.clear();
- if (!Xcb::Extensions::self()->isRandrAvailable()) {
- fallback();
- return;
- }
- T resources(rootWindow());
- if (resources.isNull()) {
- fallback();
- return;
- }
- xcb_randr_crtc_t *crtcs = resources.crtcs();
- xcb_randr_mode_info_t *modes = resources.modes();
-
- QVector infos(resources->num_crtcs);
- for (int i = 0; i < resources->num_crtcs; ++i) {
- infos[i] = Xcb::RandR::CrtcInfo(crtcs[i], resources->config_timestamp);
- }
-
- for (int i = 0; i < resources->num_crtcs; ++i) {
- Xcb::RandR::CrtcInfo info(infos.at(i));
-
- xcb_randr_output_t *outputs = info.outputs();
- QVector outputInfos(outputs ? resources->num_outputs : 0);
- if (outputs) {
- for (int i = 0; i < resources->num_outputs; ++i) {
- outputInfos[i] = Xcb::RandR::OutputInfo(outputs[i], resources->config_timestamp);
- }
- }
-
- float refreshRate = -1.0f;
- for (int j = 0; j < resources->num_modes; ++j) {
- if (info->mode == modes[j].id) {
- if (modes[j].htotal != 0 && modes[j].vtotal != 0) { // BUG 313996
- // refresh rate calculation - WTF was wikipedia 1998 when I needed it?
- int dotclock = modes[j].dot_clock,
- vtotal = modes[j].vtotal;
- if (modes[j].mode_flags & XCB_RANDR_MODE_FLAG_INTERLACE)
- dotclock *= 2;
- if (modes[j].mode_flags & XCB_RANDR_MODE_FLAG_DOUBLE_SCAN)
- vtotal *= 2;
- refreshRate = dotclock/float(modes[j].htotal*vtotal);
- }
- break; // found mode
- }
- }
-
- const QRect geo = info.rect();
- if (geo.isValid()) {
- m_geometries << geo;
- m_refreshRates << refreshRate;
- QString name;
- for (int j = 0; j < info->num_outputs; ++j) {
- Xcb::RandR::OutputInfo outputInfo(outputInfos.at(j));
- if (crtcs[i] == outputInfo->crtc) {
- name = outputInfo.name();
- break;
- }
- }
- m_names << name;
- }
- }
- if (m_geometries.isEmpty()) {
- fallback();
- return;
- }
-
- setCount(m_geometries.count());
-}
-
-
void XRandRScreens::init()
{
KWin::Screens::init();
// we need to call ScreenResources at least once to be able to use current
- update();
+ m_backend->initOutputs();
+ setCount(m_backend->outputs().count());
emit changed();
}
-QRect XRandRScreens::geometry(int screen) const
-{
- if (screen >= m_geometries.size() || screen < 0) {
- return QRect();
- }
- return m_geometries.at(screen).isValid() ? m_geometries.at(screen) :
- QRect(QPoint(0, 0), displaySize()); // xinerama, lacks RandR
-}
-
-QString XRandRScreens::name(int screen) const
-{
- if (screen >= m_names.size() || screen < 0) {
- return QString();
- }
- return m_names.at(screen);
-}
-
-int XRandRScreens::number(const QPoint &pos) const
-{
- int bestScreen = 0;
- int minDistance = INT_MAX;
- for (int i = 0; i < m_geometries.size(); ++i) {
- const QRect &geo = m_geometries.at(i);
- if (geo.contains(pos)) {
- return i;
- }
- int distance = QPoint(geo.topLeft() - pos).manhattanLength();
- distance = qMin(distance, QPoint(geo.topRight() - pos).manhattanLength());
- distance = qMin(distance, QPoint(geo.bottomRight() - pos).manhattanLength());
- distance = qMin(distance, QPoint(geo.bottomLeft() - pos).manhattanLength());
- if (distance < minDistance) {
- minDistance = distance;
- bestScreen = i;
- }
- }
- return bestScreen;
-}
-
-float XRandRScreens::refreshRate(int screen) const
-{
- if (screen >= m_refreshRates.size() || screen < 0) {
- return -1.0f;
- }
- return m_refreshRates.at(screen);
-}
-
-QSize XRandRScreens::size(int screen) const
-{
- const QRect geo = geometry(screen);
- if (!geo.isValid()) {
- return QSize();
- }
- return geo.size();
-}
-
void XRandRScreens::updateCount()
{
- update();
+ m_backend->updateOutputs();
+ setCount(m_backend->outputs().count());
}
bool XRandRScreens::event(xcb_generic_event_t *event)
diff --git a/plugins/platforms/x11/standalone/screens_xrandr.h b/plugins/platforms/x11/standalone/screens_xrandr.h
index 5a7a748794..e0f9b6a084 100644
--- a/plugins/platforms/x11/standalone/screens_xrandr.h
+++ b/plugins/platforms/x11/standalone/screens_xrandr.h
@@ -20,40 +20,30 @@ along with this program. If not, see .
#ifndef KWIN_SCREENS_XRANDR_H
#define KWIN_SCREENS_XRANDR_H
// kwin
-#include "screens.h"
+#include "outputscreens.h"
#include "x11eventfilter.h"
-// Qt
-#include
namespace KWin
{
+class X11StandalonePlatform;
-class XRandRScreens : public Screens, public X11EventFilter
+class XRandRScreens : public OutputScreens, public X11EventFilter
{
Q_OBJECT
public:
- XRandRScreens(QObject *parent);
+ XRandRScreens(X11StandalonePlatform *backend, QObject *parent = nullptr);
virtual ~XRandRScreens();
void init() override;
- QRect geometry(int screen) const override;
- QString name(int screen) const override;
- int number(const QPoint& pos) const override;
- float refreshRate(int screen) const override;
- QSize size(int screen) const override;
+
QSize displaySize() const override;
using QObject::event;
bool event(xcb_generic_event_t *event) override;
-protected Q_SLOTS:
+private:
void updateCount() override;
-private:
- template
- void update();
- QVector m_geometries;
- QVector m_refreshRates;
- QVector m_names;
+ X11StandalonePlatform *m_backend;
};
} // namespace
diff --git a/plugins/platforms/x11/standalone/x11_output.cpp b/plugins/platforms/x11/standalone/x11_output.cpp
new file mode 100644
index 0000000000..9a1e30a08c
--- /dev/null
+++ b/plugins/platforms/x11/standalone/x11_output.cpp
@@ -0,0 +1,64 @@
+/********************************************************************
+ KWin - the KDE window manager
+ This file is part of the KDE project.
+
+Copyright 2019 Roman Gilg
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
+*********************************************************************/
+#include "x11_output.h"
+#include "screens.h"
+
+namespace KWin
+{
+
+X11Output::X11Output(QObject *parent)
+ : AbstractOutput(parent)
+{
+}
+
+QString X11Output::name() const
+{
+ return m_name;
+}
+
+void X11Output::setName(QString set)
+{
+ m_name = set;
+}
+
+QRect X11Output::geometry() const
+{
+ if (m_geometry.isValid()) {
+ return m_geometry;
+ }
+ return QRect(QPoint(0, 0), Screens::self()->displaySize()); // xinerama, lacks RandR
+}
+
+void X11Output::setGeometry(QRect set)
+{
+ m_geometry = set;
+}
+
+int X11Output::refreshRate() const
+{
+ return m_refreshRate;
+}
+
+void X11Output::setRefreshRate(int set)
+{
+ m_refreshRate = set;
+}
+
+}
diff --git a/plugins/platforms/x11/standalone/x11_output.h b/plugins/platforms/x11/standalone/x11_output.h
new file mode 100644
index 0000000000..d5f094058f
--- /dev/null
+++ b/plugins/platforms/x11/standalone/x11_output.h
@@ -0,0 +1,64 @@
+/********************************************************************
+ KWin - the KDE window manager
+ This file is part of the KDE project.
+
+Copyright 2019 Roman Gilg
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
+*********************************************************************/
+#ifndef KWIN_X11_OUTPUT_H
+#define KWIN_X11_OUTPUT_H
+
+#include "abstract_output.h"
+#include
+
+#include
+#include
+
+namespace KWin
+{
+
+/**
+ * X11 output representation
+ **/
+class KWIN_EXPORT X11Output : public AbstractOutput
+{
+ Q_OBJECT
+public:
+ explicit X11Output(QObject *parent = nullptr);
+ virtual ~X11Output() = default;
+
+ QString name() const override;
+ void setName(QString set);
+ /**
+ * The geometry of this output in global compositor co-ordinates (i.e scaled)
+ **/
+ QRect geometry() const override;
+ void setGeometry(QRect set);
+
+ /**
+ * Current refresh rate in 1/ms.
+ **/
+ int refreshRate() const override;
+ void setRefreshRate(int set);
+
+private:
+ QString m_name;
+ QRect m_geometry;
+ int m_refreshRate;
+};
+
+}
+
+#endif
diff --git a/plugins/platforms/x11/standalone/x11_platform.cpp b/plugins/platforms/x11/standalone/x11_platform.cpp
index e7b5fba2f0..215af1ca24 100644
--- a/plugins/platforms/x11/standalone/x11_platform.cpp
+++ b/plugins/platforms/x11/standalone/x11_platform.cpp
@@ -42,6 +42,8 @@ along with this program. If not, see .
#include "non_composited_outline.h"
#include "workspace.h"
#include "x11_decoration_renderer.h"
+#include "x11_output.h"
+#include "xcbutils.h"
#include
@@ -106,7 +108,7 @@ void X11StandalonePlatform::init()
Screens *X11StandalonePlatform::createScreens(QObject *parent)
{
- return new XRandRScreens(parent);
+ return new XRandRScreens(this, parent);
}
OpenGLBackend *X11StandalonePlatform::createOpenGLBackend()
@@ -439,4 +441,109 @@ QVector X11StandalonePlatform::supportedCompositors() const
return compositors;
}
+void X11StandalonePlatform::initOutputs()
+{
+ doUpdateOutputs();
+}
+
+void X11StandalonePlatform::updateOutputs()
+{
+ doUpdateOutputs();
+}
+
+template
+void X11StandalonePlatform::doUpdateOutputs()
+{
+ auto fallback = [this]() {
+ auto *o = new X11Output(this);
+ o->setRefreshRate(-1.0f);
+ o->setName(QStringLiteral("Xinerama"));
+ m_outputs << o;
+ };
+
+ // TODO: instead of resetting all outputs, check if new output is added/removed
+ // or still available and leave still available outputs in m_outputs
+ // untouched (like in DRM backend)
+ qDeleteAll(m_outputs);
+ m_outputs.clear();
+
+ if (!Xcb::Extensions::self()->isRandrAvailable()) {
+ fallback();
+ return;
+ }
+ T resources(rootWindow());
+ if (resources.isNull()) {
+ fallback();
+ return;
+ }
+ xcb_randr_crtc_t *crtcs = resources.crtcs();
+ xcb_randr_mode_info_t *modes = resources.modes();
+
+ QVector infos(resources->num_crtcs);
+ for (int i = 0; i < resources->num_crtcs; ++i) {
+ infos[i] = Xcb::RandR::CrtcInfo(crtcs[i], resources->config_timestamp);
+ }
+
+ for (int i = 0; i < resources->num_crtcs; ++i) {
+ Xcb::RandR::CrtcInfo info(infos.at(i));
+
+ xcb_randr_output_t *outputs = info.outputs();
+ QVector outputInfos(outputs ? resources->num_outputs : 0);
+ if (outputs) {
+ for (int i = 0; i < resources->num_outputs; ++i) {
+ outputInfos[i] = Xcb::RandR::OutputInfo(outputs[i], resources->config_timestamp);
+ }
+ }
+
+ float refreshRate = -1.0f;
+ for (int j = 0; j < resources->num_modes; ++j) {
+ if (info->mode == modes[j].id) {
+ if (modes[j].htotal != 0 && modes[j].vtotal != 0) { // BUG 313996
+ // refresh rate calculation - WTF was wikipedia 1998 when I needed it?
+ int dotclock = modes[j].dot_clock,
+ vtotal = modes[j].vtotal;
+ if (modes[j].mode_flags & XCB_RANDR_MODE_FLAG_INTERLACE)
+ dotclock *= 2;
+ if (modes[j].mode_flags & XCB_RANDR_MODE_FLAG_DOUBLE_SCAN)
+ vtotal *= 2;
+ refreshRate = dotclock/float(modes[j].htotal*vtotal);
+ }
+ break; // found mode
+ }
+ }
+
+ const QRect geo = info.rect();
+ if (geo.isValid()) {
+ auto *o = new X11Output(this);
+ o->setGeometry(geo);
+ o->setRefreshRate(refreshRate);
+
+ QString name;
+ for (int j = 0; j < info->num_outputs; ++j) {
+ Xcb::RandR::OutputInfo outputInfo(outputInfos.at(j));
+ if (crtcs[i] == outputInfo->crtc) {
+ name = outputInfo.name();
+ break;
+ }
+ }
+ o->setName(name);
+ m_outputs << o;
+ }
+ }
+
+ if (m_outputs.isEmpty()) {
+ fallback();
+ }
+}
+
+Outputs X11StandalonePlatform::outputs() const
+{
+ return m_outputs;
+}
+
+Outputs X11StandalonePlatform::enabledOutputs() const
+{
+ return m_outputs;
+}
+
}
diff --git a/plugins/platforms/x11/standalone/x11_platform.h b/plugins/platforms/x11/standalone/x11_platform.h
index 7321775378..44e4e4ad01 100644
--- a/plugins/platforms/x11/standalone/x11_platform.h
+++ b/plugins/platforms/x11/standalone/x11_platform.h
@@ -33,6 +33,7 @@ class SyncFilter;
class XInputIntegration;
class WindowSelector;
class X11EventFilter;
+class X11Output;
class KWIN_EXPORT X11StandalonePlatform : public Platform
{
@@ -71,6 +72,12 @@ public:
void createEffectsHandler(Compositor *compositor, Scene *scene) override;
QVector supportedCompositors() const override;
+ void initOutputs();
+ void updateOutputs();
+
+ Outputs outputs() const override;
+ Outputs enabledOutputs() const override;
+
protected:
void doHideCursor() override;
void doShowCursor() override;
@@ -87,6 +94,9 @@ private:
**/
static bool hasGlx();
+ template
+ void doUpdateOutputs();
+
XInputIntegration *m_xinputIntegration = nullptr;
QThread *m_openGLFreezeProtectionThread = nullptr;
QTimer *m_openGLFreezeProtection = nullptr;
@@ -95,6 +105,7 @@ private:
QScopedPointer m_screenEdgesFilter;
std::unique_ptr m_syncFilter;
+ QVector m_outputs;
};
}
diff --git a/plugins/platforms/x11/windowed/x11windowed_output.cpp b/plugins/platforms/x11/windowed/x11windowed_output.cpp
index cbcbd65a5f..9889d32760 100644
--- a/plugins/platforms/x11/windowed/x11windowed_output.cpp
+++ b/plugins/platforms/x11/windowed/x11windowed_output.cpp
@@ -33,7 +33,7 @@ namespace KWin
{
X11WindowedOutput::X11WindowedOutput(X11WindowedBackend *backend)
- : AbstractOutput(backend)
+ : AbstractWaylandOutput(backend)
, m_backend(backend)
{
m_window = xcb_generate_id(m_backend->connection());
diff --git a/plugins/platforms/x11/windowed/x11windowed_output.h b/plugins/platforms/x11/windowed/x11windowed_output.h
index 06390c2b55..893b1882d3 100644
--- a/plugins/platforms/x11/windowed/x11windowed_output.h
+++ b/plugins/platforms/x11/windowed/x11windowed_output.h
@@ -20,7 +20,7 @@ along with this program. If not, see .
#ifndef KWIN_X11WINDOWED_OUTPUT_H
#define KWIN_X11WINDOWED_OUTPUT_H
-#include "abstract_output.h"
+#include "abstract_wayland_output.h"
#include
#include
@@ -38,7 +38,7 @@ class X11WindowedBackend;
/**
* Wayland outputs in a nested X11 setup
**/
-class KWIN_EXPORT X11WindowedOutput : public AbstractOutput
+class KWIN_EXPORT X11WindowedOutput : public AbstractWaylandOutput
{
Q_OBJECT
public: