diff --git a/CMakeLists.txt b/CMakeLists.txt --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -410,6 +410,7 @@ killwindow.cpp geometrytip.cpp screens.cpp + outputscreens.cpp shadow.cpp sm.cpp group.cpp @@ -453,6 +454,7 @@ decorations/decorationrenderer.cpp decorations/decorations_logging.cpp platform.cpp + output.cpp shell_client.cpp wayland_server.cpp wayland_cursor_theme.cpp diff --git a/autotests/integration/screen_changes_test.cpp b/autotests/integration/screen_changes_test.cpp --- a/autotests/integration/screen_changes_test.cpp +++ b/autotests/integration/screen_changes_test.cpp @@ -125,15 +125,15 @@ QCOMPARE(outputRemovedSpy.count(), 1); // let's create the output objects to ensure they are correct - QScopedPointer o1(registry.createOutput(outputAnnouncedSpy.first().first().value(), outputAnnouncedSpy.first().last().value())); + QScopedPointer o1(registry.createOutput(outputAnnouncedSpy.first().first().value(), outputAnnouncedSpy.first().last().value())); QVERIFY(o1->isValid()); - QSignalSpy o1ChangedSpy(o1.data(), &Output::changed); + QSignalSpy o1ChangedSpy(o1.data(), &KWayland::Client::Output::changed); QVERIFY(o1ChangedSpy.isValid()); QVERIFY(o1ChangedSpy.wait()); QCOMPARE(o1->geometry(), geometries.at(0)); - QScopedPointer o2(registry.createOutput(outputAnnouncedSpy.last().first().value(), outputAnnouncedSpy.last().last().value())); + QScopedPointer o2(registry.createOutput(outputAnnouncedSpy.last().first().value(), outputAnnouncedSpy.last().last().value())); QVERIFY(o2->isValid()); - QSignalSpy o2ChangedSpy(o2.data(), &Output::changed); + QSignalSpy o2ChangedSpy(o2.data(), &KWayland::Client::Output::changed); QVERIFY(o2ChangedSpy.isValid()); QVERIFY(o2ChangedSpy.wait()); QCOMPARE(o2->geometry(), geometries.at(1)); @@ -143,9 +143,9 @@ outputRemovedSpy.clear(); screensChangedSpy.clear(); - QSignalSpy o1RemovedSpy(o1.data(), &Output::removed); + QSignalSpy o1RemovedSpy(o1.data(), &KWayland::Client::Output::removed); QVERIFY(o1RemovedSpy.isValid()); - QSignalSpy o2RemovedSpy(o2.data(), &Output::removed); + QSignalSpy o2RemovedSpy(o2.data(), &KWayland::Client::Output::removed); QVERIFY(o2RemovedSpy.isValid()); const QVector geometries2{QRect(0, 0, 1280, 1024)}; diff --git a/colorcorrection/manager.cpp b/colorcorrection/manager.cpp --- a/colorcorrection/manager.cpp +++ b/colorcorrection/manager.cpp @@ -25,6 +25,7 @@ #include #include +#include #include #include #include @@ -509,10 +510,10 @@ void Manager::commitGammaRamps(int temperature) { - int nscreens = Screens::self()->count(); + const auto outs = kwinApp()->platform()->outputs(); - for (int screen = 0; screen < nscreens; screen++) { - int rampsize = kwinApp()->platform()->gammaRampSize(screen); + for (auto *o : outs) { + int rampsize = o->getGammaRampSize(); GammaRamp ramp(rampsize); /* @@ -542,13 +543,13 @@ ramp.blue[i] = (double)ramp.blue[i] / (UINT16_MAX+1) * whitePoint[2] * (UINT16_MAX+1); } - if (kwinApp()->platform()->setGammaRamp(screen, ramp)) { + if (o->setGammaRamp(ramp)) { m_currentTemp = temperature; m_failedCommitAttempts = 0; } else { m_failedCommitAttempts++; if (m_failedCommitAttempts < 10) { - qCWarning(KWIN_COLORCORRECTION).nospace() << "Committing Gamma Ramp failed for screen " << screen << + qCWarning(KWIN_COLORCORRECTION).nospace() << "Committing Gamma Ramp failed for output " << o->name() << ". Trying " << (10 - m_failedCommitAttempts) << " times more."; } else { // TODO: On multi monitor setups we could try to rollback earlier changes for already commited outputs diff --git a/output.h b/output.h new file mode 100644 --- /dev/null +++ b/output.h @@ -0,0 +1,117 @@ +/******************************************************************** + 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; +} +} + +namespace KWin +{ + +namespace ColorCorrect { +struct GammaRamp; +} + +/** + * Generic output representation in a Wayland session + **/ +class KWIN_EXPORT Output : public QObject +{ + Q_OBJECT +public: + virtual ~Output() {} + + 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; } + + const QPointer getWaylandInterface() const { + return m_waylandOutput; + } + + virtual int getGammaRampSize() const { + return 0; + } + virtual bool setGammaRamp(ColorCorrect::GammaRamp &gamma) { + Q_UNUSED(gamma); + return false; + } + +protected: + QPointer m_changeset; + QPointer m_waylandOutput; + 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/output.cpp b/output.cpp new file mode 100644 --- /dev/null +++ b/output.cpp @@ -0,0 +1,82 @@ +/******************************************************************** + 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 "output.h" + +// KWayland +#include +#include +#include +// KF5 +#include + +namespace KWin +{ + +QString Output::name() const +{ + if (!m_waylandOutput) { + return i18n("unknown"); + } + return QStringLiteral("%1 %2").arg(m_waylandOutput->manufacturer()).arg(m_waylandOutput->model()); +} + +QRect Output::geometry() const +{ + return QRect(m_globalPos, pixelSize() / scale()); +} + +QSize Output::physicalSize() const +{ + if (m_orientation == Qt::PortraitOrientation || m_orientation == Qt::InvertedPortraitOrientation) { + return QSize(m_physicalSize.height(), m_physicalSize.width()); + } + return m_physicalSize; +} + +void Output::setGlobalPos(const QPoint &pos) +{ + m_globalPos = pos; + if (m_waylandOutput) { + m_waylandOutput->setGlobalPosition(pos); + } + if (m_waylandOutputDevice) { + m_waylandOutputDevice->setGlobalPosition(pos); + } +} + +void Output::setScale(qreal scale) +{ + m_scale = scale; + if (m_waylandOutput) { + m_waylandOutput->setScale(scale); + } + if (m_waylandOutputDevice) { + m_waylandOutputDevice->setScale(scale); + } +} + +void Output::setChanges(KWayland::Server::OutputChangeSet *changes) +{ + m_changeset = changes; + qCDebug(KWIN_CORE) << "set changes in Output"; + commitChanges(); +} + +} diff --git a/plugins/platforms/drm/screens_drm.h b/outputscreens.h copy from plugins/platforms/drm/screens_drm.h copy to outputscreens.h --- a/plugins/platforms/drm/screens_drm.h +++ b/outputscreens.h @@ -2,7 +2,7 @@ KWin - the KDE window manager This file is part of the KDE project. -Copyright (C) 2015 Martin Gräßlin +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 @@ -17,38 +17,39 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . *********************************************************************/ -#ifndef KWIN_SCREENS_DRM_H -#define KWIN_SCREENS_DRM_H +#ifndef KWIN_OUTPUTSCREENS_H +#define KWIN_OUTPUTSCREENS_H + #include "screens.h" namespace KWin { -class DrmBackend; -class DrmScreens : public Screens +/** + * @brief Implementation for backends with Outputs + **/ +class KWIN_EXPORT OutputScreens : public Screens { Q_OBJECT public: - DrmScreens(DrmBackend *backend, QObject *parent = nullptr); - virtual ~DrmScreens(); + OutputScreens(Platform *platform, QObject *parent = nullptr); + virtual ~OutputScreens(); + void init() override; + QString name(int screen) const override; + bool isInternal(int screen) const; + QSizeF physicalSize(int screen) const; QRect geometry(int screen) const override; - int number(const QPoint &pos) const override; - qreal scale(int screen) const override; QSize size(int screen) const override; + qreal scale(int screen) const override; + Qt::ScreenOrientation orientation(int screen) const; void updateCount() override; - QString name(int screen) const override; - float refreshRate(int screen) const override; - - QSizeF physicalSize(int screen) const override; - bool isInternal(int screen) const override; - bool supportsTransformations(int screen) const override; - Qt::ScreenOrientation orientation(int screen) const override; + int number(const QPoint &pos) const override; -private: - DrmBackend *m_backend; +protected: + Platform *m_platform; }; } -#endif +#endif // KWIN_OUTPUTSCREENS_H diff --git a/outputscreens.cpp b/outputscreens.cpp new file mode 100644 --- /dev/null +++ b/outputscreens.cpp @@ -0,0 +1,132 @@ +/******************************************************************** + 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 "outputscreens.h" +#include "platform.h" +#include "output.h" + +namespace KWin +{ + +OutputScreens::OutputScreens(Platform *platform, QObject *parent) + : Screens(parent), + m_platform(platform) +{ +} + +OutputScreens::~OutputScreens() = default; + +void OutputScreens::init() +{ + updateCount(); + KWin::Screens::init(); + emit changed(); +} + +QString OutputScreens::name(int screen) const +{ + auto enOuts = m_platform->enabledOutputs(); + if (screen >= enOuts.size()) { + return Screens::name(screen); + } + return enOuts.at(screen)->name(); +} + +bool OutputScreens::isInternal(int screen) const +{ + const auto enOuts = m_platform->enabledOutputs(); + if (screen >= enOuts.size()) { + return false; + } + return enOuts.at(screen)->isInternal(); +} + +QRect OutputScreens::geometry(int screen) const +{ + auto enOuts = m_platform->enabledOutputs(); + if (screen >= enOuts.size()) { + return QRect(); + } + return enOuts.at(screen)->geometry(); +} + +QSize OutputScreens::size(int screen) const +{ + auto enOuts = m_platform->enabledOutputs(); + if (screen >= enOuts.size()) { + return QSize(); + } + return enOuts.at(screen)->geometry().size(); +} + +qreal OutputScreens::scale(int screen) const +{ + auto enOuts = m_platform->enabledOutputs(); + if (screen >= enOuts.size()) { + return 1; + } + return enOuts.at(screen)->scale(); +} + +QSizeF OutputScreens::physicalSize(int screen) const +{ + auto enOuts = m_platform->enabledOutputs(); + if (screen >= enOuts.size()) { + return Screens::physicalSize(screen); + } + return enOuts.at(screen)->physicalSize(); +} + +Qt::ScreenOrientation OutputScreens::orientation(int screen) const +{ + const auto enOuts = m_platform->enabledOutputs(); + if (screen >= enOuts.size()) { + return Qt::PrimaryOrientation; + } + return enOuts.at(screen)->orientation(); +} + +void OutputScreens::updateCount() +{ + setCount(m_platform->enabledOutputs().size()); +} + +int OutputScreens::number(const QPoint &pos) const +{ + int bestScreen = 0; + int minDistance = INT_MAX; + const auto enOuts = m_platform->enabledOutputs(); + for (int i = 0; i < enOuts.size(); ++i) { + const QRect &geo = enOuts.at(i)->geometry(); + 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; +} + +} // namespace diff --git a/platform.h b/platform.h --- a/platform.h +++ b/platform.h @@ -42,9 +42,9 @@ { namespace ColorCorrect { class Manager; -struct GammaRamp; } +class Output; class Edge; class Compositor; class OverlayWindow; @@ -401,16 +401,6 @@ return m_colorCorrect; } - virtual int gammaRampSize(int screen) const { - Q_UNUSED(screen); - return 0; - } - virtual bool setGammaRamp(int screen, ColorCorrect::GammaRamp &gamma) { - Q_UNUSED(screen); - Q_UNUSED(gamma); - return false; - } - /* * A string of information to include in kwin debug output * It should not be translated. @@ -420,6 +410,15 @@ */ virtual QString supportInformation() const; + // outputs with connections (org_kde_kwin_outputdevice) + QVector outputs() const { + return m_outputs; + } + // actively compositing outputs (wl_output) + QVector enabledOutputs() const { + return m_enabledOutputs; + } + public Q_SLOTS: void pointerMotion(const QPointF &position, quint32 time); void pointerButtonPressed(quint32 button, quint32 time); @@ -450,6 +449,7 @@ void initFailed(); void cursorChanged(); void readyChanged(bool); + /** * Emitted by backends using a one screen (nested window) approach and when the size of that changes. **/ @@ -500,6 +500,9 @@ **/ virtual void doShowCursor(); + QVector m_outputs; + QVector m_enabledOutputs; + private: void triggerCursorRepaint(); bool m_softWareCursor = false; diff --git a/platform.cpp b/platform.cpp --- a/platform.cpp +++ b/platform.cpp @@ -46,6 +46,7 @@ Platform::~Platform() { + qDeleteAll(m_outputs); if (m_eglDisplay != EGL_NO_DISPLAY) { eglTerminate(m_eglDisplay); } 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 @@ -55,10 +55,6 @@ namespace KWin { -namespace ColorCorrect { -struct GammaRamp; -} - class Udev; class UdevMonitor; @@ -93,12 +89,6 @@ int fd() const { return m_fd; } - QVector outputs() const { - return m_outputs; - } - QVector enabledOutputs() const { - return m_enabledOutputs; - } QVector planes() const { return m_planes; } @@ -124,8 +114,6 @@ gbm_device *gbmDevice() const { return m_gbmDevice; } - int gammaRampSize(int screen) const override; - bool setGammaRamp(int screen, ColorCorrect::GammaRamp &gamma) override; QVector supportedCompositors() const override; @@ -173,10 +161,6 @@ QVector m_crtcs; // all connectors QVector m_connectors; - // active output pipelines (planes + crtc + encoder + connector) - QVector m_outputs; - // active and enabled pipelines (above + wl_output) - QVector m_enabledOutputs; bool m_deleteBufferAfterPageFlip; bool m_atomicModeSetting = false; 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 @@ -31,7 +31,6 @@ #include "screens_drm.h" #include "udev.h" #include "wayland_server.h" -#include #if HAVE_GBM #include "egl_gbm_backend.h" #include @@ -90,7 +89,10 @@ while (m_pageFlipsPending != 0) { QCoreApplication::processEvents(QEventLoop::WaitForMoreEvents); } + // we need to first remove all outputs qDeleteAll(m_outputs); + m_outputs.clear(); + qDeleteAll(m_planes); qDeleteAll(m_crtcs); qDeleteAll(m_connectors); @@ -130,7 +132,8 @@ { m_dpmsFilter.reset(); for (auto it = m_enabledOutputs.constBegin(), end = m_enabledOutputs.constEnd(); it != end; it++) { - (*it)->setDpms(DrmOutput::DpmsMode::On); + auto *o = qobject_cast(*it); + o->setDpms(DrmOutput::DpmsMode::On); } } @@ -141,7 +144,8 @@ return; } for (auto it = m_enabledOutputs.constBegin(), end = m_enabledOutputs.constEnd(); it != end; it++) { - if (!(*it)->isDpmsEnabled()) { + auto *o = qobject_cast(*it); + if (!o->isDpmsEnabled()) { // dpms still disabled, need to keep the filter return; } @@ -170,7 +174,7 @@ if (!usesSoftwareCursor()) { const QPoint cp = Cursor::pos() - softwareCursorHotspot(); for (auto it = m_outputs.constBegin(); it != m_outputs.constEnd(); ++it) { - DrmOutput *o = *it; + auto *o = qobject_cast(*it); // only relevant in atomic mode o->m_modesetRequested = true; o->pageFlipped(); // TODO: Do we really need this? @@ -198,7 +202,7 @@ } // hide cursor and disable for (auto it = m_outputs.constBegin(); it != m_outputs.constEnd(); ++it) { - DrmOutput *o = *it; + auto *o = qobject_cast(*it); o->hideCursor(); } m_active = false; @@ -373,7 +377,7 @@ return; } - QVector connectedOutputs; + QVector connectedOutputs; QVector pendingConnectors; // split up connected connectors in already or not yet assigned ones @@ -392,15 +396,15 @@ // check for outputs which got removed auto it = m_outputs.begin(); while (it != m_outputs.end()) { - if (connectedOutputs.contains(*it)) { + Output *o = *it; + if (connectedOutputs.contains(o)) { it++; continue; } - DrmOutput *removed = *it; it = m_outputs.erase(it); - m_enabledOutputs.removeOne(removed); - emit outputRemoved(removed); - delete removed; + m_enabledOutputs.removeOne(o); + emit outputRemoved(qobject_cast(o)); + delete o; } // now check new connections @@ -427,8 +431,8 @@ // check if crtc isn't used yet -- currently we don't allow multiple outputs on one crtc (cloned mode) auto it = std::find_if(connectedOutputs.constBegin(), connectedOutputs.constEnd(), - [crtc] (DrmOutput *o) { - return o->m_crtc == crtc; + [crtc] (Output *o) { + return qobject_cast(o)->m_crtc == crtc; } ); if (it != connectedOutputs.constEnd()) { @@ -476,7 +480,9 @@ } } } - std::sort(connectedOutputs.begin(), connectedOutputs.end(), [] (DrmOutput *a, DrmOutput *b) { return a->m_conn->id() < b->m_conn->id(); }); + std::sort(connectedOutputs.begin(), connectedOutputs.end(), [] (Output *a, Output *b) { + return qobject_cast(a)->m_conn->id() < qobject_cast(b)->m_conn->id(); + }); m_outputs = connectedOutputs; m_enabledOutputs = connectedOutputs; readOutputsConfiguration(); @@ -496,25 +502,27 @@ // default position goes from left to right QPoint pos(0, 0); for (auto it = m_outputs.begin(); it != m_outputs.end(); ++it) { - qCDebug(KWIN_DRM) << "Reading output configuration for [" << uuid << "] ["<< (*it)->uuid() << "]"; - const auto outputConfig = configGroup.group((*it)->uuid()); - (*it)->setGlobalPos(outputConfig.readEntry("Position", pos)); + auto *o = qobject_cast(*it); + qCDebug(KWIN_DRM) << "Reading output configuration for [" << uuid << "] ["<< o->uuid() << "]"; + const auto outputConfig = configGroup.group(o->uuid()); + o->setGlobalPos(outputConfig.readEntry("Position", pos)); // TODO: add mode - (*it)->setScale(outputConfig.readEntry("Scale", 1.0)); - pos.setX(pos.x() + (*it)->geometry().width()); + o->setScale(outputConfig.readEntry("Scale", 1.0)); + pos.setX(pos.x() + o->geometry().width()); } } QByteArray DrmBackend::generateOutputConfigurationUuid() const { auto it = m_outputs.constBegin(); if (m_outputs.size() == 1) { // special case: one output - return (*it)->uuid(); + return qobject_cast(*it)->uuid(); } QCryptographicHash hash(QCryptographicHash::Md5); for (; it != m_outputs.constEnd(); ++it) { - hash.addData((*it)->uuid()); + auto *o = qobject_cast(*it); + hash.addData(o->uuid()); } return hash.result().toHex().left(10); } @@ -574,22 +582,22 @@ DrmOutput *DrmBackend::findOutput(quint32 connector) { - auto it = std::find_if(m_outputs.constBegin(), m_outputs.constEnd(), [connector] (DrmOutput *o) { - return o->m_conn->id() == connector; + auto it = std::find_if(m_outputs.constBegin(), m_outputs.constEnd(), [connector] (Output *o) { + return qobject_cast(o)->m_conn->id() == connector; }); if (it != m_outputs.constEnd()) { - return *it; + return qobject_cast(*it); } return nullptr; } DrmOutput *DrmBackend::findOutput(const QByteArray &uuid) { - auto it = std::find_if(m_outputs.constBegin(), m_outputs.constEnd(), [uuid] (DrmOutput *o) { - return o->m_uuid == uuid; + auto it = std::find_if(m_outputs.constBegin(), m_outputs.constEnd(), [uuid] (Output *o) { + return qobject_cast(o)->m_uuid == uuid; }); if (it != m_outputs.constEnd()) { - return *it; + return qobject_cast(*it); } return nullptr; } @@ -623,10 +631,11 @@ return; } for (auto it = m_outputs.constBegin(); it != m_outputs.constEnd(); ++it) { + auto *o = qobject_cast(*it); if (m_cursorEnabled) { - (*it)->showCursor(); + o->showCursor(); } else { - (*it)->hideCursor(); + o->hideCursor(); } } } @@ -653,7 +662,8 @@ { if (m_cursorEnabled) { for (auto it = m_outputs.constBegin(); it != m_outputs.constEnd(); ++it) { - (*it)->showCursor(); + auto *o = qobject_cast(*it); + o->showCursor(); } } markCursorAsRendered(); @@ -673,7 +683,8 @@ return; } for (auto it = m_outputs.constBegin(); it != m_outputs.constEnd(); ++it) { - (*it)->updateCursor(); + auto *o = qobject_cast(*it); + o->updateCursor(); } setCursor(); @@ -691,7 +702,8 @@ return; } for (auto it = m_outputs.constBegin(); it != m_outputs.constEnd(); ++it) { - (*it)->hideCursor(); + auto *o = qobject_cast(*it); + o->hideCursor(); } } @@ -701,7 +713,8 @@ return; } for (auto it = m_outputs.constBegin(); it != m_outputs.constEnd(); ++it) { - (*it)->moveCursor(Cursor::pos()); + auto *o = qobject_cast(*it); + o->moveCursor(Cursor::pos()); } } @@ -747,7 +760,8 @@ } bool enabled = false; for (auto it = m_enabledOutputs.constBegin(); it != m_enabledOutputs.constEnd(); ++it) { - enabled = enabled || (*it)->isDpmsEnabled(); + auto *o = qobject_cast(*it); + enabled = enabled || o->isDpmsEnabled(); } setOutputsEnabled(enabled); } @@ -761,22 +775,6 @@ #endif } -int DrmBackend::gammaRampSize(int screen) const -{ - if (m_outputs.size() <= screen) { - return 0; - } - return m_outputs.at(screen)->m_crtc->getGammaRampSize(); -} - -bool DrmBackend::setGammaRamp(int screen, ColorCorrect::GammaRamp &gamma) -{ - if (m_outputs.size() <= screen) { - return false; - } - return m_outputs.at(screen)->m_crtc->setGammaRamp(gamma); -} - QString DrmBackend::supportInformation() const { QString supportInfo; 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,30 +20,19 @@ #ifndef KWIN_DRM_OUTPUT_H #define KWIN_DRM_OUTPUT_H +#include "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; -} -} - namespace KWin { @@ -54,7 +43,7 @@ class DrmConnector; class DrmCrtc; -class DrmOutput : public QObject +class KWIN_EXPORT DrmOutput : public Output { Q_OBJECT public: @@ -82,23 +71,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(); + virtual bool commitChanges() override; - QSize pixelSize() const; - qreal scale() const; - - /* - * 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 { @@ -117,24 +94,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(); @@ -160,8 +123,6 @@ bool isCurrentMode(const drmModeModeInfo *mode) const; void initUuid(); - void setGlobalPos(const QPoint &pos); - void setScale(qreal scale); void initOutput(); bool initPrimaryPlane(); bool initCursorPlane(); @@ -175,17 +136,15 @@ void transform(KWayland::Server::OutputDeviceInterface::Transform transform); void automaticRotation(); + int getGammaRampSize() const override; + bool setGammaRamp(ColorCorrect::GammaRamp &gamma) override; + 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_waylandOutputDevice; - QPointer m_changeset; KWin::ScopedDrmPointer<_drmModeProperty, &drmModeFreeProperty> m_dpms; DpmsMode m_dpmsMode = DpmsMode::On; DpmsMode m_dpmsModePending = DpmsMode::On; @@ -198,8 +157,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; @@ -211,7 +168,6 @@ DrmDumbBuffer *m_cursor[2] = {nullptr, nullptr}; int m_cursorIndex = 0; bool m_hasNewCursor = false; - bool m_internal = false; }; } 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 // KF5 @@ -57,7 +56,7 @@ { DrmOutput::DrmOutput(DrmBackend *backend) - : QObject() + : Output() , m_backend(backend) { } @@ -165,24 +164,6 @@ 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() / scale()); -} - -qreal DrmOutput::scale() const -{ - return m_scale; -} - void DrmOutput::setEnabled(bool enabled) { if (enabled == isEnabled()) { @@ -199,11 +180,6 @@ 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; @@ -754,51 +730,14 @@ 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) { 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); - } -} - -void DrmOutput::setScale(qreal scale) -{ - m_scale = scale; - if (m_waylandOutput) { - m_waylandOutput->setScale(scale); - } - if (m_waylandOutputDevice) { - m_waylandOutputDevice->setScale(scale); - } -} - -void DrmOutput::setChanges(KWayland::Server::OutputChangeSet *changes) -{ - m_changeset = changes; - qCDebug(KWIN_DRM) << "set changes in DrmOutput"; - commitChanges(); -} - bool DrmOutput::commitChanges() { Q_ASSERT(!m_waylandOutputDevice.isNull()); @@ -1295,4 +1234,14 @@ emit screens()->changed(); } +int DrmOutput::getGammaRampSize() const +{ + return m_crtc->getGammaRampSize(); +} + +bool DrmOutput::setGammaRamp(ColorCorrect::GammaRamp &gamma) +{ + return m_crtc->setGammaRamp(gamma); +} + } diff --git a/plugins/platforms/drm/egl_gbm_backend.h b/plugins/platforms/drm/egl_gbm_backend.h --- a/plugins/platforms/drm/egl_gbm_backend.h +++ b/plugins/platforms/drm/egl_gbm_backend.h @@ -61,7 +61,7 @@ bool initBufferConfigs(); bool initRenderingContext(); void initRemotePresent(); - struct Output { + struct EglGbmOutput { DrmOutput *output = nullptr; DrmBuffer *buffer = nullptr; std::shared_ptr gbmSurface; @@ -72,13 +72,13 @@ */ QList damageHistory; }; - bool resetOutput(Output &output, DrmOutput *drmOutput); - bool makeContextCurrent(const Output &output); - void presentOnOutput(Output &output); - void cleanupOutput(const Output &output); + bool resetOutput(EglGbmOutput &output, DrmOutput *drmOutput); + bool makeContextCurrent(const EglGbmOutput &output); + void presentOnOutput(EglGbmOutput &output); + void cleanupOutput(const EglGbmOutput &output); void createOutput(DrmOutput *output); DrmBackend *m_backend; - QVector m_outputs; + QVector m_outputs; QScopedPointer m_remoteaccessManager; friend class EglGbmTexture; }; 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 @@ -22,6 +22,7 @@ #include "composite.h" #include "drm_backend.h" #include "drm_output.h" +#include "screens_drm.h" #include "gbm_surface.h" #include "logging.h" #include "options.h" @@ -47,7 +48,7 @@ connect(m_backend, &DrmBackend::outputRemoved, this, [this] (DrmOutput *output) { auto it = std::find_if(m_outputs.begin(), m_outputs.end(), - [output] (const Output &o) { + [output] (const EglGbmOutput &o) { return o.output == output; } ); @@ -73,7 +74,7 @@ m_outputs.clear(); } -void EglGbmBackend::cleanupOutput(const Output &o) +void EglGbmBackend::cleanupOutput(const EglGbmOutput &o) { o.output->releaseGbm(); @@ -142,8 +143,8 @@ } const auto outputs = m_backend->outputs(); - for (DrmOutput *drmOutput: outputs) { - createOutput(drmOutput); + for (Output *drmOutput: outputs) { + createOutput(qobject_cast(drmOutput)); } if (m_outputs.isEmpty()) { qCCritical(KWIN_DRM) << "Create Window Surfaces failed"; @@ -165,7 +166,7 @@ m_remoteaccessManager.reset(new RemoteAccessManager); } -bool EglGbmBackend::resetOutput(Output &o, DrmOutput *drmOutput) +bool EglGbmBackend::resetOutput(EglGbmOutput &o, DrmOutput *drmOutput) { o.output = drmOutput; auto size = drmOutput->pixelSize(); @@ -196,7 +197,7 @@ void EglGbmBackend::createOutput(DrmOutput *drmOutput) { - Output o; + EglGbmOutput o; if (resetOutput(o, drmOutput)) { connect(drmOutput, &DrmOutput::modeChanged, this, [drmOutput, this] { @@ -215,7 +216,7 @@ } } -bool EglGbmBackend::makeContextCurrent(const Output &output) +bool EglGbmBackend::makeContextCurrent(const EglGbmOutput &output) { const EGLSurface surface = output.eglSurface; if (surface == EGL_NO_SURFACE) { @@ -279,7 +280,7 @@ } } -void EglGbmBackend::presentOnOutput(EglGbmBackend::Output &o) +void EglGbmBackend::presentOnOutput(EglGbmBackend::EglGbmOutput &o) { eglSwapBuffers(eglDisplay(), o.eglSurface); o.buffer = m_backend->createBuffer(o.gbmSurface); @@ -315,7 +316,7 @@ QRegion EglGbmBackend::prepareRenderingForScreen(int screenId) { - const Output &o = m_outputs.at(screenId); + const EglGbmOutput &o = m_outputs.at(screenId); makeContextCurrent(o); if (supportsBufferAge()) { QRegion region; @@ -341,7 +342,7 @@ void EglGbmBackend::endRenderingFrameForScreen(int screenId, const QRegion &renderedRegion, const QRegion &damagedRegion) { - Output &o = m_outputs[screenId]; + EglGbmOutput &o = m_outputs[screenId]; if (damagedRegion.intersected(o.output->geometry()).isEmpty() && screenId == 0) { // If the damaged region of a window is fully occluded, the only diff --git a/plugins/platforms/drm/scene_qpainter_drm_backend.h b/plugins/platforms/drm/scene_qpainter_drm_backend.h --- a/plugins/platforms/drm/scene_qpainter_drm_backend.h +++ b/plugins/platforms/drm/scene_qpainter_drm_backend.h @@ -47,12 +47,12 @@ private: void initOutput(DrmOutput *output); - struct Output { + struct QPainterOutput { DrmDumbBuffer *buffer[2]; DrmOutput *output; int index = 0; }; - QVector m_outputs; + QVector m_outputs; DrmBackend *m_backend; }; } 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 @@ -20,6 +20,7 @@ #include "scene_qpainter_drm_backend.h" #include "drm_backend.h" #include "drm_output.h" +#include "screens_drm.h" #include "logind.h" namespace KWin @@ -32,13 +33,13 @@ { const auto outputs = m_backend->outputs(); for (auto output: outputs) { - initOutput(output); + initOutput(qobject_cast(output)); } connect(m_backend, &DrmBackend::outputAdded, this, &DrmQPainterBackend::initOutput); connect(m_backend, &DrmBackend::outputRemoved, this, [this] (DrmOutput *o) { auto it = std::find_if(m_outputs.begin(), m_outputs.end(), - [o] (const Output &output) { + [o] (const QPainterOutput &output) { return output.output == o; } ); @@ -62,7 +63,7 @@ void DrmQPainterBackend::initOutput(DrmOutput *output) { - Output o; + QPainterOutput o; auto initBuffer = [&o, output, this] (int index) { o.buffer[index] = m_backend->createBuffer(output->pixelSize()); o.buffer[index]->map(); @@ -102,7 +103,7 @@ QImage *DrmQPainterBackend::bufferForScreen(int screenId) { - const Output &o = m_outputs.at(screenId); + const QPainterOutput &o = m_outputs.at(screenId); return o.buffer[o.index]->image(); } @@ -126,7 +127,7 @@ return; } for (auto it = m_outputs.begin(); it != m_outputs.end(); ++it) { - const Output &o = *it; + const QPainterOutput &o = *it; m_backend->present(o.buffer[o.index], o.output); } } diff --git a/plugins/platforms/drm/screens_drm.h b/plugins/platforms/drm/screens_drm.h --- a/plugins/platforms/drm/screens_drm.h +++ b/plugins/platforms/drm/screens_drm.h @@ -19,34 +19,21 @@ *********************************************************************/ #ifndef KWIN_SCREENS_DRM_H #define KWIN_SCREENS_DRM_H -#include "screens.h" +#include "outputscreens.h" namespace KWin { class DrmBackend; -class DrmScreens : public Screens +class DrmScreens : public OutputScreens { Q_OBJECT public: DrmScreens(DrmBackend *backend, QObject *parent = nullptr); virtual ~DrmScreens(); - void init() override; - QRect geometry(int screen) const override; - int number(const QPoint &pos) const override; - qreal scale(int screen) const override; - QSize size(int screen) const override; - void updateCount() override; - QString name(int screen) const override; - float refreshRate(int screen) const override; - QSizeF physicalSize(int screen) const override; - bool isInternal(int screen) const override; + float refreshRate(int screen) const override; bool supportsTransformations(int screen) const override; - Qt::ScreenOrientation orientation(int screen) const override; - -private: - DrmBackend *m_backend; }; } 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 @@ -25,128 +25,32 @@ { DrmScreens::DrmScreens(DrmBackend *backend, QObject *parent) - : Screens(parent) - , m_backend(backend) + : OutputScreens(backend, parent) { connect(backend, &DrmBackend::screensQueried, this, &DrmScreens::updateCount); connect(backend, &DrmBackend::screensQueried, this, &DrmScreens::changed); } DrmScreens::~DrmScreens() = default; -void DrmScreens::init() -{ - updateCount(); - KWin::Screens::init(); - emit changed(); -} - -QRect DrmScreens::geometry(int screen) const -{ - const auto outputs = m_backend->enabledOutputs(); - if (screen >= outputs.size()) { - return QRect(); - } - return outputs.at(screen)->geometry(); -} - -qreal DrmScreens::scale(int screen) const -{ - const auto outputs = m_backend->enabledOutputs(); - if (screen >= outputs.size()) { - return 1; - } - return outputs.at(screen)->scale(); -} - -QSize DrmScreens::size(int screen) const -{ - const auto outputs = m_backend->enabledOutputs(); - if (screen >= outputs.size()) { - return QSize(); - } - return outputs.at(screen)->geometry().size(); -} - -void DrmScreens::updateCount() -{ - setCount(m_backend->enabledOutputs().size()); -} - -int DrmScreens::number(const QPoint &pos) const -{ - int bestScreen = 0; - int minDistance = INT_MAX; - const auto outputs = m_backend->enabledOutputs(); - for (int i = 0; i < outputs.size(); ++i) { - const QRect &geo = outputs.at(i)->geometry(); - 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; -} - -QString DrmScreens::name(int screen) const -{ - const auto outputs = m_backend->enabledOutputs(); - 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(); - if (screen >= outputs.size()) { + const auto enOuts = m_platform->enabledOutputs(); + if (screen >= enOuts.size()) { return Screens::refreshRate(screen); } - return outputs.at(screen)->currentRefreshRate() / 1000.0f; -} - -QSizeF DrmScreens::physicalSize(int screen) const -{ - const auto outputs = m_backend->enabledOutputs(); - 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(); - if (screen >= outputs.size()) { - return false; - } - return outputs.at(screen)->isInternal(); + auto *o = qobject_cast(enOuts.at(screen)); + return o->currentRefreshRate() / 1000.0f; } bool DrmScreens::supportsTransformations(int screen) const { - const auto outputs = m_backend->enabledOutputs(); - if (screen >= outputs.size()) { + const auto enOuts = m_platform->enabledOutputs(); + if (screen >= enOuts.size()) { return false; } - return outputs.at(screen)->supportsTransformations(); -} - -Qt::ScreenOrientation DrmScreens::orientation(int screen) const -{ - const auto outputs = m_backend->outputs(); - if (screen >= outputs.size()) { - return Qt::PrimaryOrientation; - } - return outputs.at(screen)->orientation(); + auto *o = qobject_cast(enOuts.at(screen)); + return o->supportsTransformations(); } } diff --git a/plugins/platforms/virtual/screens_virtual.h b/plugins/platforms/virtual/screens_virtual.h --- a/plugins/platforms/virtual/screens_virtual.h +++ b/plugins/platforms/virtual/screens_virtual.h @@ -19,24 +19,20 @@ *********************************************************************/ #ifndef KWIN_SCREENS_VIRTUAL_H #define KWIN_SCREENS_VIRTUAL_H -#include "screens.h" +#include "outputscreens.h" #include namespace KWin { class VirtualBackend; -class VirtualScreens : public Screens +class VirtualScreens : public OutputScreens { Q_OBJECT public: VirtualScreens(VirtualBackend *backend, QObject *parent = nullptr); virtual ~VirtualScreens(); void init() override; - QRect geometry(int screen) const override; - int number(const QPoint &pos) const override; - QSize size(int screen) const override; - void updateCount() override; private: void createOutputs(); 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 @@ -25,7 +25,7 @@ { VirtualScreens::VirtualScreens(VirtualBackend *backend, QObject *parent) - : Screens(parent) + : OutputScreens(backend, parent) , m_backend(backend) { } @@ -40,7 +40,7 @@ connect(m_backend, &VirtualBackend::virtualOutputsSet, this, [this] (bool countChanged) { if (countChanged) { - setCount(m_backend->outputCount()); + setCount(m_backend->outputs().size()); } else { emit changed(); } @@ -50,45 +50,4 @@ emit changed(); } -QRect VirtualScreens::geometry(int screen) const -{ - const auto outputs = m_backend->outputs(); - if (screen >= outputs.size()) { - return QRect(); - } - return outputs.at(screen)->geometry(); -} - -QSize VirtualScreens::size(int screen) const -{ - return geometry(screen).size(); -} - -void VirtualScreens::updateCount() -{ - setCount(m_backend->outputCount()); -} - -int VirtualScreens::number(const QPoint &pos) const -{ - int bestScreen = 0; - int minDistance = INT_MAX; - const auto outputs = m_backend->outputs(); - for (int i = 0; i < outputs.size(); ++i) { - const QRect &geo = outputs.at(i)->geometry(); - 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; -} - } 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 @@ -45,16 +45,6 @@ virtual ~VirtualBackend(); void init() override; - int outputCount() const { - return m_outputs.size(); - } - const QVector outputs() const { - return m_outputs; - } - qreal outputScale() const { - return m_outputScale; - } - bool saveFrames() const { return !m_screenshotDir.isNull(); } @@ -66,10 +56,6 @@ Q_INVOKABLE void setVirtualOutputs(int count, QVector geometries = QVector()); - Q_INVOKABLE void setOutputScale(qreal scale) { - m_outputScale = scale; - } - int drmFd() const { return m_drmFd; } @@ -83,8 +69,6 @@ void setGbmDevice(gbm_device *device) { m_gbmDevice = device; } - virtual int gammaRampSize(int screen) const override; - virtual bool setGammaRamp(int screen, ColorCorrect::GammaRamp &gamma) override; QVector supportedCompositors() const override { return QVector{OpenGLCompositing, QPainterCompositing}; @@ -94,10 +78,6 @@ void virtualOutputsSet(bool countChanged); private: - QVector m_outputs; - - qreal m_outputScale = 1; - QScopedPointer m_screenshotDir; int m_drmFd = -1; gbm_device *m_gbmDevice = nullptr; diff --git a/plugins/platforms/virtual/virtual_backend.cpp b/plugins/platforms/virtual/virtual_backend.cpp --- a/plugins/platforms/virtual/virtual_backend.cpp +++ b/plugins/platforms/virtual/virtual_backend.cpp @@ -76,8 +76,9 @@ */ if (!m_outputs.size()) { VirtualOutput *dummyOutput = new VirtualOutput(this); - dummyOutput->m_geo = QRect(QPoint(0, 0), initialWindowSize()); - m_outputs = { dummyOutput }; + dummyOutput->setGeometry(QRect(QPoint(0, 0), initialWindowSize())); + m_outputs << dummyOutput ; + m_enabledOutputs << dummyOutput ; } @@ -120,29 +121,21 @@ bool countChanged = m_outputs.size() != count; qDeleteAll(m_outputs.begin(), m_outputs.end()); m_outputs.resize(count); + m_enabledOutputs.resize(count); int sumWidth = 0; for (int i = 0; i < count; i++) { VirtualOutput *vo = new VirtualOutput(this); if (geometries.size()) { - vo->m_geo = geometries.at(i); - } else if (!vo->m_geo.isValid()) { - vo->m_geo = QRect(QPoint(sumWidth, 0), initialWindowSize()); - sumWidth += vo->m_geo.width(); + vo->setGeometry(geometries.at(i)); + } else if (!vo->geometry().isValid()) { + vo->setGeometry(QRect(QPoint(sumWidth, 0), initialWindowSize())); + sumWidth += initialWindowSize().width(); } - m_outputs[i] = vo; + m_outputs[i] = m_enabledOutputs[i] = vo; } emit virtualOutputsSet(countChanged); } -int VirtualBackend::gammaRampSize(int screen) const { - return m_outputs[screen]->m_gammaSize; -} - -bool VirtualBackend::setGammaRamp(int screen, ColorCorrect::GammaRamp &gamma) { - Q_UNUSED(gamma); - return m_outputs[screen]->m_gammaResult; -} - } diff --git a/plugins/platforms/virtual/virtual_output.h b/plugins/platforms/virtual/virtual_output.h --- a/plugins/platforms/virtual/virtual_output.h +++ b/plugins/platforms/virtual/virtual_output.h @@ -20,31 +20,40 @@ #ifndef KWIN_VIRTUAL_OUTPUT_H #define KWIN_VIRTUAL_OUTPUT_H +#include "output.h" + #include #include namespace KWin { class VirtualBackend; -class VirtualOutput : public QObject +class VirtualOutput : public Output { Q_OBJECT public: VirtualOutput(QObject *parent = nullptr); VirtualOutput(const VirtualOutput &o); virtual ~VirtualOutput(); - QRect geometry() const { - return m_geo; + QSize pixelSize() const override; + + void setGeometry(const QRect &geo); + + int getGammaRampSize() const override { + return m_gammaSize; + } + bool setGammaRamp(ColorCorrect::GammaRamp &gamma) override { + Q_UNUSED(gamma); + return m_gammaResult; } private: friend class VirtualBackend; - QRect m_geo; - qreal m_outputScale = 1; + QSize m_pixelSize; int m_gammaSize = 200; bool m_gammaResult = true; diff --git a/plugins/platforms/virtual/virtual_output.cpp b/plugins/platforms/virtual/virtual_output.cpp --- a/plugins/platforms/virtual/virtual_output.cpp +++ b/plugins/platforms/virtual/virtual_output.cpp @@ -23,13 +23,15 @@ { VirtualOutput::VirtualOutput(QObject *parent) - : QObject(parent) + : Output() { + Q_UNUSED(parent); + + setScale(1.); } VirtualOutput::VirtualOutput(const VirtualOutput &o) - : m_geo(o.m_geo), - m_outputScale(o.m_outputScale), + : m_pixelSize(o.m_pixelSize), m_gammaSize(o.m_gammaSize), m_gammaResult(o.m_gammaResult) { @@ -39,4 +41,15 @@ { } +QSize VirtualOutput::pixelSize() const +{ + return m_pixelSize; +} + +void VirtualOutput::setGeometry(const QRect &geo) +{ + m_pixelSize = geo.size(); + setGlobalPos(geo.topLeft()); +} + }