From ca7f7a42c8876247c443a12647ab0b9f856de2c8 Mon Sep 17 00:00:00 2001 From: Vlad Zahorodnii Date: Tue, 6 Dec 2022 15:20:43 +0200 Subject: [PATCH] wayland: Make kwin_wayland create virtual outputs At the moment, we rely on placeholder output getting created, but there are cases where it's desired to spin kwin with virtual outputs so you could take screenshots and things as such. --- src/backends/virtual/virtual_backend.cpp | 26 +++++++++++++++------- src/backends/virtual/virtual_backend.h | 3 +++ src/backends/virtual/virtual_output.cpp | 28 +++++++----------------- src/backends/virtual/virtual_output.h | 4 +--- src/main_wayland.cpp | 9 ++++++-- 5 files changed, 37 insertions(+), 33 deletions(-) diff --git a/src/backends/virtual/virtual_backend.cpp b/src/backends/virtual/virtual_backend.cpp index 53f415d405..fec9fa2bdb 100644 --- a/src/backends/virtual/virtual_backend.cpp +++ b/src/backends/virtual/virtual_backend.cpp @@ -66,6 +66,23 @@ Outputs VirtualBackend::outputs() const return m_outputs; } +VirtualOutput *VirtualBackend::createOutput(const QPoint &position, const QSize &size, qreal scale) +{ + VirtualOutput *output = new VirtualOutput(this); + output->init(position, size, scale); + m_outputs.append(output); + Q_EMIT outputAdded(output); + output->updateEnabled(true); + return output; +} + +Output *VirtualBackend::addOutput(const QSize &size, qreal scale) +{ + VirtualOutput *output = createOutput(QPoint(), size * scale, scale); + Q_EMIT outputsQueried(); + return output; +} + void VirtualBackend::setVirtualOutputs(const QVector &geometries, QVector scales) { Q_ASSERT(scales.size() == 0 || scales.size() == geometries.size()); @@ -73,14 +90,7 @@ void VirtualBackend::setVirtualOutputs(const QVector &geometries, QVector const QVector removed = m_outputs; for (int i = 0; i < geometries.size(); i++) { - VirtualOutput *vo = new VirtualOutput(this); - vo->init(geometries[i].topLeft(), geometries[i].size()); - if (scales.size()) { - vo->updateScale(scales.at(i)); - } - m_outputs.append(vo); - Q_EMIT outputAdded(vo); - vo->updateEnabled(true); + createOutput(geometries[i].topLeft(), geometries[i].size(), scales.value(i, 1.0)); } for (VirtualOutput *output : removed) { diff --git a/src/backends/virtual/virtual_backend.h b/src/backends/virtual/virtual_backend.h index 3d1cd0268e..24c2472a71 100644 --- a/src/backends/virtual/virtual_backend.h +++ b/src/backends/virtual/virtual_backend.h @@ -41,6 +41,7 @@ public: std::unique_ptr createQPainterBackend() override; std::unique_ptr createOpenGLBackend() override; + Output *addOutput(const QSize &size, qreal scale); Q_INVOKABLE void setVirtualOutputs(const QVector &geometries, QVector scales = QVector()); Outputs outputs() const override; @@ -54,6 +55,8 @@ Q_SIGNALS: void virtualOutputsSet(bool countChanged); private: + VirtualOutput *createOutput(const QPoint &position, const QSize &size, qreal scale); + QVector m_outputs; std::unique_ptr m_screenshotDir; }; diff --git a/src/backends/virtual/virtual_output.cpp b/src/backends/virtual/virtual_output.cpp index e2f617b648..401e0108f9 100644 --- a/src/backends/virtual/virtual_output.cpp +++ b/src/backends/virtual/virtual_output.cpp @@ -44,32 +44,20 @@ SoftwareVsyncMonitor *VirtualOutput::vsyncMonitor() const return m_vsyncMonitor.get(); } -void VirtualOutput::init(const QPoint &logicalPosition, const QSize &pixelSize) +void VirtualOutput::init(const QPoint &logicalPosition, const QSize &pixelSize, qreal scale) { const int refreshRate = 60000; // TODO: Make the refresh rate configurable. m_renderLoop->setRefreshRate(refreshRate); m_vsyncMonitor->setRefreshRate(refreshRate); - setGeometry(QRect(logicalPosition, pixelSize)); -} + auto mode = std::make_shared(pixelSize, m_vsyncMonitor->refreshRate()); -void VirtualOutput::setGeometry(const QRect &geo) -{ - auto mode = std::make_shared(geo.size(), m_vsyncMonitor->refreshRate()); - - State next = m_state; - next.modes = {mode}; - next.currentMode = mode; - next.position = geo.topLeft(); - - setState(next); -} - -void VirtualOutput::updateScale(qreal scale) -{ - State next = m_state; - next.scale = scale; - setState(next); + setState(State{ + .position = logicalPosition, + .scale = scale, + .modes = {mode}, + .currentMode = mode, + }); } void VirtualOutput::updateEnabled(bool enabled) diff --git a/src/backends/virtual/virtual_output.h b/src/backends/virtual/virtual_output.h index 9bd4132f28..4531f86a91 100644 --- a/src/backends/virtual/virtual_output.h +++ b/src/backends/virtual/virtual_output.h @@ -30,9 +30,7 @@ public: RenderLoop *renderLoop() const override; SoftwareVsyncMonitor *vsyncMonitor() const; - void init(const QPoint &logicalPosition, const QSize &pixelSize); - void setGeometry(const QRect &geo); - void updateScale(qreal scale); + void init(const QPoint &logicalPosition, const QSize &pixelSize, qreal scale); void updateEnabled(bool enabled); private: diff --git a/src/main_wayland.cpp b/src/main_wayland.cpp index c97b7a849f..1574a77780 100644 --- a/src/main_wayland.cpp +++ b/src/main_wayland.cpp @@ -553,10 +553,15 @@ int main(int argc, char *argv[]) } a.setOutputBackend(std::make_unique(a.session())); break; - case BackendType::Virtual: + case BackendType::Virtual: { + auto outputBackend = std::make_unique(); + for (int i = 0; i < outputCount; ++i) { + outputBackend->addOutput(initialWindowSize, outputScale); + } a.setSession(KWin::Session::create(KWin::Session::Type::Noop)); - a.setOutputBackend(std::make_unique()); + a.setOutputBackend(std::move(outputBackend)); break; + } case BackendType::X11: { QString display = parser.value(x11DisplayOption); if (display.isEmpty()) {