diff --git a/CMakeLists.txt b/CMakeLists.txt --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -453,6 +453,7 @@ decorations/decorationrenderer.cpp decorations/decorations_logging.cpp platform.cpp + abstract_output.cpp shell_client.cpp wayland_server.cpp wayland_cursor_theme.cpp diff --git a/abstract_output.h b/abstract_output.h new file mode 100644 --- /dev/null +++ b/abstract_output.h @@ -0,0 +1,146 @@ +/******************************************************************** + KWin - the KDE window manager + This file is part of the KDE project. + +Copyright 2018 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_OUTPUT_H +#define KWIN_OUTPUT_H + +#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 AbstractOutput : public QObject +{ + Q_OBJECT +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; + } + + bool isInternal() const { + 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); + virtual bool commitChanges() { return false; } + + QPointer waylandOutput() const { + return m_waylandOutput; + } + +protected: + QPointer changes() const { + return m_changeset; + } + + void setWaylandOutput(KWayland::Server::OutputInterface *set); + + QPointer xdgOutput() const { + return m_xdgOutput; + } + void createXdgOutput(); + + QPointer waylandOutputDevice() const { + return m_waylandOutputDevice; + } + void setWaylandOutputDevice(KWayland::Server::OutputDeviceInterface *set); + + 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; + } + +private: + QPointer m_changeset; + QPointer m_waylandOutput; + QPointer m_xdgOutput; + QPointer m_waylandOutputDevice; + + QPoint m_globalPos; + qreal m_scale = 1; + QSize m_physicalSize; + Qt::ScreenOrientation m_orientation = Qt::PrimaryOrientation; + bool m_internal = false; +}; + +} + +#endif // KWIN_OUTPUT_H diff --git a/abstract_output.cpp b/abstract_output.cpp new file mode 100644 --- /dev/null +++ b/abstract_output.cpp @@ -0,0 +1,130 @@ +/******************************************************************** + KWin - the KDE window manager + This file is part of the KDE project. + +Copyright 2018 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_output.h" +#include "wayland_server.h" + +// KWayland +#include +#include +#include +#include +// KF5 +#include + +#include + +namespace KWin +{ + +AbstractOutput::AbstractOutput(QObject *parent) + : 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 +{ + if (m_orientation == Qt::PortraitOrientation || m_orientation == Qt::InvertedPortraitOrientation) { + return m_physicalSize.transposed(); + } + return m_physicalSize; +} + +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(); + } +} + +void AbstractOutput::setChanges(KWayland::Server::OutputChangeSet *changes) +{ + m_changeset = changes; + qCDebug(KWIN_CORE) << "set changes in AbstractOutput"; + commitChanges(); +} + +void AbstractOutput::setWaylandOutput(KWayland::Server::OutputInterface *set) +{ + m_waylandOutput = set; +} + +void AbstractOutput::createXdgOutput() +{ + if (!m_waylandOutput || m_xdgOutput) { + return; + } + m_xdgOutput = waylandServer()->xdgOutputManager()->createXdgOutput(m_waylandOutput, m_waylandOutput); +} + +void AbstractOutput::setWaylandOutputDevice(KWayland::Server::OutputDeviceInterface *set) +{ + m_waylandOutputDevice = set; +} + +} diff --git a/platform.h b/platform.h --- a/platform.h +++ b/platform.h @@ -45,6 +45,7 @@ struct GammaRamp; } +class AbstractOutput; class Edge; class Compositor; class OverlayWindow; @@ -64,6 +65,17 @@ class DecoratedClientImpl; } +class KWIN_EXPORT Outputs : public QVector +{ +public: + Outputs(){}; + template + Outputs(const QVector &other) { + resize(other.size()); + std::copy(other.constBegin(), other.constEnd(), begin()); + } +}; + class KWIN_EXPORT Platform : public QObject { Q_OBJECT @@ -411,6 +423,15 @@ return false; } + // outputs with connections (org_kde_kwin_outputdevice) + virtual Outputs outputs() const { + return Outputs(); + } + // actively compositing outputs (wl_output) + virtual Outputs enabledOutputs() const { + return Outputs(); + } + /* * A string of information to include in kwin debug output * It should not be translated. diff --git a/plugins/platforms/drm/drm_backend.h b/plugins/platforms/drm/drm_backend.h --- a/plugins/platforms/drm/drm_backend.h +++ b/plugins/platforms/drm/drm_backend.h @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -93,12 +94,15 @@ int fd() const { return m_fd; } - QVector outputs() const { + Outputs outputs() const override; + Outputs enabledOutputs() const override; + QVector drmOutputs() const { return m_outputs; } - QVector enabledOutputs() const { + QVector drmEnabledOutputs() const { return m_enabledOutputs; } + QVector planes() const { return m_planes; } diff --git a/plugins/platforms/drm/drm_backend.cpp b/plugins/platforms/drm/drm_backend.cpp --- a/plugins/platforms/drm/drm_backend.cpp +++ b/plugins/platforms/drm/drm_backend.cpp @@ -49,6 +49,7 @@ #include #include // system +#include #include // drm #include @@ -90,7 +91,11 @@ while (m_pageFlipsPending != 0) { QCoreApplication::processEvents(QEventLoop::WaitForMoreEvents); } + // we need to first remove all outputs qDeleteAll(m_outputs); + m_outputs.clear(); + m_enabledOutputs.clear(); + qDeleteAll(m_planes); qDeleteAll(m_crtcs); qDeleteAll(m_connectors); @@ -116,6 +121,16 @@ } } +Outputs DrmBackend::outputs() const +{ + return m_outputs; +} + +Outputs DrmBackend::enabledOutputs() const +{ + return m_enabledOutputs; +} + void DrmBackend::outputWentOff() { if (!m_dpmsFilter.isNull()) { diff --git a/plugins/platforms/drm/drm_output.h b/plugins/platforms/drm/drm_output.h --- a/plugins/platforms/drm/drm_output.h +++ b/plugins/platforms/drm/drm_output.h @@ -20,31 +20,19 @@ #ifndef KWIN_DRM_OUTPUT_H #define KWIN_DRM_OUTPUT_H +#include "abstract_output.h" #include "drm_pointer.h" #include "drm_object.h" #include "drm_object_plane.h" #include #include -#include #include #include #include #include -namespace KWayland -{ -namespace Server -{ -class OutputInterface; -class OutputDeviceInterface; -class OutputChangeSet; -class OutputManagementInterface; -class XdgOutputInterface; -} -} - namespace KWin { @@ -55,7 +43,7 @@ class DrmConnector; class DrmCrtc; -class DrmOutput : public QObject +class KWIN_EXPORT DrmOutput : public AbstractOutput { Q_OBJECT public: @@ -86,23 +74,11 @@ * The default is on */ void setEnabled(bool enabled); - bool isEnabled() const; - - /** - * This sets the changes and tests them against the DRM output - */ - void setChanges(KWayland::Server::OutputChangeSet *changeset); - bool commitChanges(); - QSize pixelSize() const; - qreal scale() const; + bool commitChanges() override; - /* - * The geometry of this output in global compositor co-ordinates (i.e scaled) - */ - QRect geometry() const; + QSize pixelSize() const override; - QString name() const; int currentRefreshRate() const; // These values are defined by the kernel enum class DpmsMode { @@ -121,24 +97,10 @@ return m_uuid; } - QSize physicalSize() const; - bool initCursor(const QSize &cursorSize); bool supportsTransformations() const; - bool isInternal() const { - return m_internal; - } - - Qt::ScreenOrientation orientation() const { - return m_orientation; - } - - const QPointer getWaylandInterface() const { - return m_waylandOutput; - } - Q_SIGNALS: void dpmsChanged(); void modeChanged(); @@ -165,8 +127,6 @@ bool isCurrentMode(const drmModeModeInfo *mode) const; void initUuid(); - void setGlobalPos(const QPoint &pos); - void setScale(qreal scale); void initOutput(); bool initPrimaryPlane(); bool initCursorPlane(); @@ -183,15 +143,9 @@ DrmBackend *m_backend; DrmConnector *m_conn = nullptr; DrmCrtc *m_crtc = nullptr; - QPoint m_globalPos; - qreal m_scale = 1; bool m_lastGbm = false; drmModeModeInfo m_mode; Edid m_edid; - QPointer m_waylandOutput; - QPointer m_xdgOutput; - QPointer m_waylandOutputDevice; - QPointer m_changeset; KWin::ScopedDrmPointer<_drmModeProperty, &drmModeFreeProperty> m_dpms; DpmsMode m_dpmsMode = DpmsMode::On; DpmsMode m_dpmsModePending = DpmsMode::On; @@ -204,8 +158,6 @@ bool m_pageFlipPending = false; bool m_dpmsAtomicOffPending = false; bool m_modesetRequested = true; - QSize m_physicalSize; - Qt::ScreenOrientation m_orientation = Qt::PrimaryOrientation; struct { Qt::ScreenOrientation orientation; diff --git a/plugins/platforms/drm/drm_output.cpp b/plugins/platforms/drm/drm_output.cpp --- a/plugins/platforms/drm/drm_output.cpp +++ b/plugins/platforms/drm/drm_output.cpp @@ -36,7 +36,6 @@ #include #include #include -#include #include #include #include @@ -53,13 +52,11 @@ #include #include -#include - namespace KWin { DrmOutput::DrmOutput(DrmBackend *backend) - : QObject() + : AbstractOutput(backend) , m_backend(backend) { } @@ -91,8 +88,6 @@ m_crtc->setOutput(nullptr); m_conn->setOutput(nullptr); - delete m_waylandOutput.data(); - delete m_waylandOutputDevice.data(); delete m_cursor[0]; delete m_cursor[1]; if (!m_pageFlipPending) { @@ -146,11 +141,11 @@ m_hasNewCursor = true; QImage *c = m_cursor[m_cursorIndex]->image(); c->fill(Qt::transparent); - c->setDevicePixelRatio(m_scale); + c->setDevicePixelRatio(scale()); QPainter p; p.begin(c); - if (m_orientation == Qt::InvertedLandscapeOrientation) { + if (orientation() == Qt::InvertedLandscapeOrientation) { QMatrix4x4 matrix; matrix.translate(cursorImage.width() / 2.0, cursorImage.height() / 2.0); matrix.rotate(180.0f, 0.0f, 0.0f, 1.0f); @@ -165,48 +160,32 @@ { QMatrix4x4 matrix; QMatrix4x4 hotspotMatrix; - if (m_orientation == Qt::InvertedLandscapeOrientation) { + if (orientation() == Qt::InvertedLandscapeOrientation) { matrix.translate(pixelSize().width() /2.0, pixelSize().height() / 2.0); matrix.rotate(180.0f, 0.0f, 0.0f, 1.0f); matrix.translate(-pixelSize().width() /2.0, -pixelSize().height() / 2.0); const auto cursorSize = m_backend->softwareCursor().size(); hotspotMatrix.translate(cursorSize.width()/2.0, cursorSize.height()/2.0); hotspotMatrix.rotate(180.0f, 0.0f, 0.0f, 1.0f); hotspotMatrix.translate(-cursorSize.width()/2.0, -cursorSize.height()/2.0); } - hotspotMatrix.scale(m_scale); - matrix.scale(m_scale); - matrix.translate(-m_globalPos.x(), -m_globalPos.y()); + hotspotMatrix.scale(scale()); + matrix.scale(scale()); + const auto outputGlobalPos = AbstractOutput::globalPos(); + matrix.translate(-outputGlobalPos.x(), -outputGlobalPos.y()); const QPoint p = matrix.map(globalPos) - hotspotMatrix.map(m_backend->softwareCursorHotspot()); drmModeMoveCursor(m_backend->fd(), m_crtc->id(), p.x(), p.y()); } QSize DrmOutput::pixelSize() const { - if (m_orientation == Qt::PortraitOrientation || m_orientation == Qt::InvertedPortraitOrientation) { + auto orient = orientation(); + if (orient == Qt::PortraitOrientation || orient == Qt::InvertedPortraitOrientation) { return QSize(m_mode.vdisplay, m_mode.hdisplay); } return QSize(m_mode.hdisplay, m_mode.vdisplay); } -QSize DrmOutput::physicalSize() const -{ - if (m_orientation == Qt::PortraitOrientation || m_orientation == Qt::InvertedPortraitOrientation) { - return QSize(m_physicalSize.height(), m_physicalSize.width()); - } - return m_physicalSize; -} - -QRect DrmOutput::geometry() const -{ - return QRect(m_globalPos, pixelSize() / m_scale); -} - -qreal DrmOutput::scale() const -{ - return m_scale; -} - void DrmOutput::setEnabled(bool enabled) { if (enabled == isEnabled()) { @@ -217,17 +196,12 @@ initOutput(); } else { setDpms(DpmsMode::Off); - delete m_waylandOutput.data(); + delete waylandOutput().data(); } - m_waylandOutputDevice->setEnabled(enabled ? + waylandOutputDevice()->setEnabled(enabled ? KWayland::Server::OutputDeviceInterface::Enablement::Enabled : KWayland::Server::OutputDeviceInterface::Enablement::Disabled); } -bool DrmOutput::isEnabled() const -{ - return !m_waylandOutput.isNull(); -} - static KWayland::Server::OutputInterface::DpmsMode toWaylandDpmsMode(DrmOutput::DpmsMode mode) { using namespace KWayland::Server; @@ -314,9 +288,9 @@ return false; } - m_internal = connector->connector_type == DRM_MODE_CONNECTOR_LVDS || connector->connector_type == DRM_MODE_CONNECTOR_eDP; + setInternal(connector->connector_type == DRM_MODE_CONNECTOR_LVDS || connector->connector_type == DRM_MODE_CONNECTOR_eDP); - if (m_internal) { + if (internal()) { connect(kwinApp(), &Application::screensCreated, this, [this] { connect(screens()->orientationSensor(), &OrientationSensor::orientationChanged, this, &DrmOutput::automaticRotation); @@ -336,7 +310,7 @@ qCWarning(KWIN_DRM) << "Overwriting monitor physical size for" << m_edid.eisaId << "/" << m_edid.monitorName << "/" << m_edid.serialNumber << " from " << physicalSize << "to " << overwriteSize; physicalSize = overwriteSize; } - m_physicalSize = physicalSize; + setRawPhysicalSize(physicalSize); initOutputDevice(connector); @@ -356,67 +330,75 @@ void DrmOutput::initOutput() { - Q_ASSERT(m_waylandOutputDevice); - if (!m_waylandOutput.isNull()) { - delete m_waylandOutput.data(); - m_waylandOutput.clear(); + auto wlOutputDevice = waylandOutputDevice(); + Q_ASSERT(wlOutputDevice); + + auto wlOutput = waylandOutput(); + if (!wlOutput.isNull()) { + delete wlOutput.data(); + wlOutput.clear(); } - m_waylandOutput = waylandServer()->display()->createOutput(); - m_xdgOutput = waylandServer()->xdgOutputManager()->createXdgOutput(m_waylandOutput, m_waylandOutput); + wlOutput = waylandServer()->display()->createOutput(); + setWaylandOutput(wlOutput.data()); + createXdgOutput(); connect(this, &DrmOutput::modeChanged, this, [this] { - if (m_waylandOutput.isNull()) { + auto wlOutput = waylandOutput(); + if (wlOutput.isNull()) { return; } - m_waylandOutput->setCurrentMode(QSize(m_mode.hdisplay, m_mode.vdisplay), refreshRateForMode(&m_mode)); - if (m_xdgOutput) { - m_xdgOutput->setLogicalSize(pixelSize() / m_scale); - m_xdgOutput->done(); + wlOutput->setCurrentMode(QSize(m_mode.hdisplay, m_mode.vdisplay), + refreshRateForMode(&m_mode)); + auto xdg = xdgOutput(); + if (xdg) { + xdg->setLogicalSize(pixelSize() / scale()); + xdg->done(); } } ); - m_waylandOutput->setManufacturer(m_waylandOutputDevice->manufacturer()); - m_waylandOutput->setModel(m_waylandOutputDevice->model()); - m_waylandOutput->setPhysicalSize(m_physicalSize); + wlOutput->setManufacturer(wlOutputDevice->manufacturer()); + wlOutput->setModel(wlOutputDevice->model()); + wlOutput->setPhysicalSize(rawPhysicalSize()); // set dpms if (!m_dpms.isNull()) { - m_waylandOutput->setDpmsSupported(true); - m_waylandOutput->setDpmsMode(toWaylandDpmsMode(m_dpmsMode)); - connect(m_waylandOutput.data(), &KWayland::Server::OutputInterface::dpmsModeRequested, this, + wlOutput->setDpmsSupported(true); + wlOutput->setDpmsMode(toWaylandDpmsMode(m_dpmsMode)); + connect(wlOutput.data(), &KWayland::Server::OutputInterface::dpmsModeRequested, this, [this] (KWayland::Server::OutputInterface::DpmsMode mode) { setDpms(fromWaylandDpmsMode(mode)); }, Qt::QueuedConnection ); } - for(const auto &mode: m_waylandOutputDevice->modes()) { + for(const auto &mode: wlOutputDevice->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); + wlOutput->addMode(mode.size, flags, mode.refreshRate); } - m_waylandOutput->create(); + wlOutput->create(); } void DrmOutput::initOutputDevice(drmModeConnector *connector) { - if (!m_waylandOutputDevice.isNull()) { - delete m_waylandOutputDevice.data(); - m_waylandOutputDevice.clear(); + auto wlOutputDevice = waylandOutputDevice(); + if (!wlOutputDevice.isNull()) { + delete wlOutputDevice.data(); + wlOutputDevice.clear(); } - m_waylandOutputDevice = waylandServer()->display()->createOutputDevice(); - m_waylandOutputDevice->setUuid(m_uuid); + wlOutputDevice = waylandServer()->display()->createOutputDevice(); + wlOutputDevice->setUuid(m_uuid); if (!m_edid.eisaId.isEmpty()) { - m_waylandOutputDevice->setManufacturer(QString::fromLatin1(m_edid.eisaId)); + wlOutputDevice->setManufacturer(QString::fromLatin1(m_edid.eisaId)); } else { - m_waylandOutputDevice->setManufacturer(i18n("unknown")); + wlOutputDevice->setManufacturer(i18n("unknown")); } QString connectorName = s_connectorNames.value(connector->connector_type, QByteArrayLiteral("Unknown")); @@ -435,9 +417,9 @@ modelName = i18n("unknown"); } - m_waylandOutputDevice->setModel(connectorName + QStringLiteral("-") + QString::number(connector->connector_type_id) + QStringLiteral("-") + modelName); + wlOutputDevice->setModel(connectorName + QStringLiteral("-") + QString::number(connector->connector_type_id) + QStringLiteral("-") + modelName); - m_waylandOutputDevice->setPhysicalSize(m_physicalSize); + wlOutputDevice->setPhysicalSize(rawPhysicalSize()); // read in mode information for (int i = 0; i < connector->count_modes; ++i) { @@ -460,9 +442,10 @@ mode.flags = deviceflags; mode.refreshRate = refreshRate; qCDebug(KWIN_DRM) << "Adding mode: " << i << mode.size; - m_waylandOutputDevice->addMode(mode); + wlOutputDevice->addMode(mode); } - m_waylandOutputDevice->create(); + wlOutputDevice->create(); + setWaylandOutputDevice(wlOutputDevice.data()); } bool DrmOutput::isCurrentMode(const drmModeModeInfo *mode) const @@ -757,8 +740,9 @@ { qCDebug(KWIN_DRM) << "DPMS mode set for output" << m_crtc->id() << "to On."; - if (m_waylandOutput) { - m_waylandOutput->setDpmsMode(toWaylandDpmsMode(m_dpmsModePending)); + auto wlOutput = waylandOutput(); + if (wlOutput) { + wlOutput->setDpmsMode(toWaylandDpmsMode(m_dpmsModePending)); } emit dpmsChanged(); @@ -775,168 +759,124 @@ { qCDebug(KWIN_DRM) << "DPMS mode set for output" << m_crtc->id() << "to Off."; - if (m_waylandOutput) { - m_waylandOutput->setDpmsMode(toWaylandDpmsMode(m_dpmsModePending)); + auto wlOutput = waylandOutput(); + if (wlOutput) { + wlOutput->setDpmsMode(toWaylandDpmsMode(m_dpmsModePending)); } emit dpmsChanged(); m_backend->outputWentOff(); } -QString DrmOutput::name() const -{ - if (!m_waylandOutput) { - return i18n("unknown"); - } - return QStringLiteral("%1 %2").arg(m_waylandOutput->manufacturer()).arg(m_waylandOutput->model()); -} - int DrmOutput::currentRefreshRate() const { - if (!m_waylandOutput) { + auto wlOutput = waylandOutput(); + if (!wlOutput) { return 60000; } - return m_waylandOutput->refreshRate(); -} - -void DrmOutput::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 DrmOutput::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(); - } -} - -void DrmOutput::setChanges(KWayland::Server::OutputChangeSet *changes) -{ - m_changeset = changes; - qCDebug(KWIN_DRM) << "set changes in DrmOutput"; - commitChanges(); + return wlOutput->refreshRate(); } bool DrmOutput::commitChanges() { - Q_ASSERT(!m_waylandOutputDevice.isNull()); + auto wlOutputDevice = waylandOutputDevice(); + Q_ASSERT(!wlOutputDevice.isNull()); - if (m_changeset.isNull()) { + auto changeset = changes(); + + if (changeset.isNull()) { qCDebug(KWIN_DRM) << "no changes"; // No changes to an output is an entirely valid thing return true; } //enabledChanged is handled by drmbackend - if (m_changeset->modeChanged()) { - qCDebug(KWIN_DRM) << "Setting new mode:" << m_changeset->mode(); - m_waylandOutputDevice->setCurrentMode(m_changeset->mode()); - updateMode(m_changeset->mode()); - } - if (m_changeset->transformChanged()) { - qCDebug(KWIN_DRM) << "Server setting transform: " << (int)(m_changeset->transform()); - transform(m_changeset->transform()); - } - if (m_changeset->positionChanged()) { - qCDebug(KWIN_DRM) << "Server setting position: " << m_changeset->position(); - setGlobalPos(m_changeset->position()); + if (changeset->modeChanged()) { + qCDebug(KWIN_DRM) << "Setting new mode:" << changeset->mode(); + wlOutputDevice->setCurrentMode(changeset->mode()); + updateMode(changeset->mode()); + } + if (changeset->transformChanged()) { + qCDebug(KWIN_DRM) << "Server setting transform: " << (int)(changeset->transform()); + transform(changeset->transform()); + } + if (changeset->positionChanged()) { + qCDebug(KWIN_DRM) << "Server setting position: " << changeset->position(); + setGlobalPos(changeset->position()); // may just work already! } - if (m_changeset->scaleChanged()) { - qCDebug(KWIN_DRM) << "Setting scale:" << m_changeset->scale(); - setScale(m_changeset->scaleF()); + if (changeset->scaleChanged()) { + qCDebug(KWIN_DRM) << "Setting scale:" << changeset->scale(); + setScale(changeset->scaleF()); } return true; } void DrmOutput::transform(KWayland::Server::OutputDeviceInterface::Transform transform) { - m_waylandOutputDevice->setTransform(transform); + waylandOutputDevice()->setTransform(transform); using KWayland::Server::OutputDeviceInterface; using KWayland::Server::OutputInterface; + auto wlOutput = waylandOutput(); + switch (transform) { case OutputDeviceInterface::Transform::Normal: if (m_primaryPlane) { m_primaryPlane->setTransformation(DrmPlane::Transformation::Rotate0); } - if (m_waylandOutput) { - m_waylandOutput->setTransform(OutputInterface::Transform::Normal); + if (wlOutput) { + wlOutput->setTransform(OutputInterface::Transform::Normal); } - m_orientation = Qt::PrimaryOrientation; + setOrientation(Qt::PrimaryOrientation); break; case OutputDeviceInterface::Transform::Rotated90: if (m_primaryPlane) { m_primaryPlane->setTransformation(DrmPlane::Transformation::Rotate90); } - if (m_waylandOutput) { - m_waylandOutput->setTransform(OutputInterface::Transform::Rotated90); + if (wlOutput) { + wlOutput->setTransform(OutputInterface::Transform::Rotated90); } - m_orientation = Qt::PortraitOrientation; + setOrientation(Qt::PortraitOrientation); break; case OutputDeviceInterface::Transform::Rotated180: if (m_primaryPlane) { m_primaryPlane->setTransformation(DrmPlane::Transformation::Rotate180); } - if (m_waylandOutput) { - m_waylandOutput->setTransform(OutputInterface::Transform::Rotated180); + if (wlOutput) { + wlOutput->setTransform(OutputInterface::Transform::Rotated180); } - m_orientation = Qt::InvertedLandscapeOrientation; + setOrientation(Qt::InvertedLandscapeOrientation); break; case OutputDeviceInterface::Transform::Rotated270: if (m_primaryPlane) { m_primaryPlane->setTransformation(DrmPlane::Transformation::Rotate270); } - if (m_waylandOutput) { - m_waylandOutput->setTransform(OutputInterface::Transform::Rotated270); + if (wlOutput) { + wlOutput->setTransform(OutputInterface::Transform::Rotated270); } - m_orientation = Qt::InvertedPortraitOrientation; + setOrientation(Qt::InvertedPortraitOrientation); break; case OutputDeviceInterface::Transform::Flipped: // TODO: what is this exactly? - if (m_waylandOutput) { - m_waylandOutput->setTransform(OutputInterface::Transform::Flipped); + if (wlOutput) { + wlOutput->setTransform(OutputInterface::Transform::Flipped); } break; case OutputDeviceInterface::Transform::Flipped90: // TODO: what is this exactly? - if (m_waylandOutput) { - m_waylandOutput->setTransform(OutputInterface::Transform::Flipped90); + if (wlOutput) { + wlOutput->setTransform(OutputInterface::Transform::Flipped90); } break; case OutputDeviceInterface::Transform::Flipped180: // TODO: what is this exactly? - if (m_waylandOutput) { - m_waylandOutput->setTransform(OutputInterface::Transform::Flipped180); + if (wlOutput) { + wlOutput->setTransform(OutputInterface::Transform::Flipped180); } break; case OutputDeviceInterface::Transform::Flipped270: // TODO: what is this exactly? - if (m_waylandOutput) { - m_waylandOutput->setTransform(OutputInterface::Transform::Flipped270); + if (wlOutput) { + wlOutput->setTransform(OutputInterface::Transform::Flipped270); } break; } @@ -1070,7 +1010,7 @@ // go back to previous state if (m_lastWorkingState.valid) { m_mode = m_lastWorkingState.mode; - m_orientation = m_lastWorkingState.orientation; + setOrientation(m_lastWorkingState.orientation); setGlobalPos(m_lastWorkingState.globalPos); if (m_primaryPlane) { m_primaryPlane->setTransformation(m_lastWorkingState.planeTransformations); @@ -1094,8 +1034,8 @@ if (wasModeset) { // store current mode set as new good state m_lastWorkingState.mode = m_mode; - m_lastWorkingState.orientation = m_orientation; - m_lastWorkingState.globalPos = m_globalPos; + m_lastWorkingState.orientation = orientation(); + m_lastWorkingState.globalPos = globalPos(); if (m_primaryPlane) { m_lastWorkingState.planeTransformations = m_primaryPlane->transformation(); } diff --git a/plugins/platforms/drm/egl_gbm_backend.cpp b/plugins/platforms/drm/egl_gbm_backend.cpp --- a/plugins/platforms/drm/egl_gbm_backend.cpp +++ b/plugins/platforms/drm/egl_gbm_backend.cpp @@ -141,7 +141,7 @@ return false; } - const auto outputs = m_backend->outputs(); + const auto outputs = m_backend->drmOutputs(); for (DrmOutput *drmOutput: outputs) { createOutput(drmOutput); } diff --git a/plugins/platforms/drm/remoteaccess_manager.cpp b/plugins/platforms/drm/remoteaccess_manager.cpp --- a/plugins/platforms/drm/remoteaccess_manager.cpp +++ b/plugins/platforms/drm/remoteaccess_manager.cpp @@ -82,7 +82,7 @@ buf->setStride(gbm_bo_get_stride(bo)); buf->setFormat(gbm_bo_get_format(bo)); - m_interface->sendBufferReady(output->getWaylandInterface().data(), buf); + m_interface->sendBufferReady(output->waylandOutput().data(), buf); } } // KWin namespace diff --git a/plugins/platforms/drm/scene_qpainter_drm_backend.cpp b/plugins/platforms/drm/scene_qpainter_drm_backend.cpp --- a/plugins/platforms/drm/scene_qpainter_drm_backend.cpp +++ b/plugins/platforms/drm/scene_qpainter_drm_backend.cpp @@ -30,7 +30,7 @@ , QPainterBackend() , m_backend(backend) { - const auto outputs = m_backend->outputs(); + const auto outputs = m_backend->drmOutputs(); for (auto output: outputs) { initOutput(output); } diff --git a/plugins/platforms/drm/screens_drm.cpp b/plugins/platforms/drm/screens_drm.cpp --- a/plugins/platforms/drm/screens_drm.cpp +++ b/plugins/platforms/drm/screens_drm.cpp @@ -70,16 +70,17 @@ void DrmScreens::updateCount() { - setCount(m_backend->enabledOutputs().size()); + setCount(m_backend->drmEnabledOutputs().size()); } int DrmScreens::number(const QPoint &pos) const { int bestScreen = 0; int minDistance = INT_MAX; - const auto outputs = m_backend->enabledOutputs(); + const auto outputs = m_backend->drmEnabledOutputs(); for (int i = 0; i < outputs.size(); ++i) { - const QRect &geo = outputs.at(i)->geometry(); + auto o = outputs.at(i); + const QRect &geo = o->geometry(); if (geo.contains(pos)) { return i; } @@ -97,52 +98,52 @@ QString DrmScreens::name(int screen) const { - const auto outputs = m_backend->enabledOutputs(); + const auto outputs = m_backend->drmEnabledOutputs(); if (screen >= outputs.size()) { return Screens::name(screen); } return outputs.at(screen)->name(); } float DrmScreens::refreshRate(int screen) const { - const auto outputs = m_backend->enabledOutputs(); + const auto outputs = m_backend->drmEnabledOutputs(); if (screen >= outputs.size()) { return Screens::refreshRate(screen); } return outputs.at(screen)->currentRefreshRate() / 1000.0f; } QSizeF DrmScreens::physicalSize(int screen) const { - const auto outputs = m_backend->enabledOutputs(); + const auto outputs = m_backend->drmEnabledOutputs(); if (screen >= outputs.size()) { return Screens::physicalSize(screen); } return outputs.at(screen)->physicalSize(); } bool DrmScreens::isInternal(int screen) const { - const auto outputs = m_backend->enabledOutputs(); + const auto outputs = m_backend->drmEnabledOutputs(); if (screen >= outputs.size()) { return false; } return outputs.at(screen)->isInternal(); } bool DrmScreens::supportsTransformations(int screen) const { - const auto outputs = m_backend->enabledOutputs(); + const auto outputs = m_backend->drmEnabledOutputs(); if (screen >= outputs.size()) { return false; } return outputs.at(screen)->supportsTransformations(); } Qt::ScreenOrientation DrmScreens::orientation(int screen) const { - const auto outputs = m_backend->outputs(); + const auto outputs = m_backend->drmOutputs(); if (screen >= outputs.size()) { return Qt::PrimaryOrientation; } diff --git a/plugins/platforms/virtual/screens_virtual.cpp b/plugins/platforms/virtual/screens_virtual.cpp --- a/plugins/platforms/virtual/screens_virtual.cpp +++ b/plugins/platforms/virtual/screens_virtual.cpp @@ -52,7 +52,7 @@ QRect VirtualScreens::geometry(int screen) const { - const auto outputs = m_backend->outputs(); + const auto outputs = m_backend->virtualOutputs(); if (screen >= outputs.size()) { return QRect(); } @@ -73,7 +73,7 @@ { int bestScreen = 0; int minDistance = INT_MAX; - const auto outputs = m_backend->outputs(); + const auto outputs = m_backend->virtualOutputs(); for (int i = 0; i < outputs.size(); ++i) { const QRect &geo = outputs.at(i)->geometry(); if (geo.contains(pos)) { diff --git a/plugins/platforms/virtual/virtual_backend.h b/plugins/platforms/virtual/virtual_backend.h --- a/plugins/platforms/virtual/virtual_backend.h +++ b/plugins/platforms/virtual/virtual_backend.h @@ -48,7 +48,7 @@ int outputCount() const { return m_outputs.size(); } - const QVector outputs() const { + const QVector virtualOutputs() const { return m_outputs; } qreal outputScale() const {