From d8ea87a9eaa051844f95519273fc764405432773 Mon Sep 17 00:00:00 2001 From: Vlad Zahorodnii Date: Tue, 6 Sep 2022 13:10:28 +0300 Subject: [PATCH] Add dummy placeholder output type Placeholder outputs are not rendered so they don't need render data. Also, this simplifies the control flow when the last real output is removed. The Platform::screensQueried signal won't be emitted inside a Platform::screensQueried slot. --- src/CMakeLists.txt | 1 + src/backends/drm/drm_backend.cpp | 4 +- src/backends/drm/drm_backend.h | 2 +- src/backends/drm/drm_gpu.cpp | 4 +- src/backends/drm/drm_gpu.h | 4 +- src/backends/drm/drm_virtual_output.cpp | 3 +- src/backends/drm/drm_virtual_output.h | 3 +- src/backends/wayland/wayland_backend.cpp | 10 ++--- src/backends/wayland/wayland_backend.h | 4 +- src/backends/wayland/wayland_output.cpp | 7 ++-- src/backends/wayland/wayland_output.h | 4 +- src/core/platform.cpp | 3 +- src/core/platform.h | 7 +--- src/placeholderoutput.cpp | 42 ++++++++++++++++++++ src/placeholderoutput.h | 28 +++++++++++++ src/plugins/screencast/screencastmanager.cpp | 2 +- src/workspace.cpp | 11 +++-- src/workspace.h | 3 +- 18 files changed, 104 insertions(+), 38 deletions(-) create mode 100644 src/placeholderoutput.cpp create mode 100644 src/placeholderoutput.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index a9a2eadc7e..3c0a52e574 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -106,6 +106,7 @@ target_sources(kwin PRIVATE osd.cpp outline.cpp placeholderinputeventfilter.cpp + placeholderoutput.cpp placement.cpp placementtracker.cpp plugin.cpp diff --git a/src/backends/drm/drm_backend.cpp b/src/backends/drm/drm_backend.cpp index 156796e47f..cbed0b781c 100644 --- a/src/backends/drm/drm_backend.cpp +++ b/src/backends/drm/drm_backend.cpp @@ -403,9 +403,9 @@ QString DrmBackend::supportInformation() const return supportInfo; } -Output *DrmBackend::createVirtualOutput(const QString &name, const QSize &size, double scale, VirtualOutputType type) +Output *DrmBackend::createVirtualOutput(const QString &name, const QSize &size, double scale) { - auto output = primaryGpu()->createVirtualOutput(name, size * scale, scale, type); + auto output = primaryGpu()->createVirtualOutput(name, size * scale, scale); Q_EMIT screensQueried(); return output; } diff --git a/src/backends/drm/drm_backend.h b/src/backends/drm/drm_backend.h index 7abe010b4f..f33e8c51e9 100644 --- a/src/backends/drm/drm_backend.h +++ b/src/backends/drm/drm_backend.h @@ -60,7 +60,7 @@ public: QVector supportedCompositors() const override; QString supportInformation() const override; - Output *createVirtualOutput(const QString &name, const QSize &size, double scale, VirtualOutputType type) override; + Output *createVirtualOutput(const QString &name, const QSize &size, double scale) override; void removeVirtualOutput(Output *output) override; DrmGpu *primaryGpu() const; diff --git a/src/backends/drm/drm_gpu.cpp b/src/backends/drm/drm_gpu.cpp index 8566fbff69..a1355a5887 100644 --- a/src/backends/drm/drm_gpu.cpp +++ b/src/backends/drm/drm_gpu.cpp @@ -587,9 +587,9 @@ const QVector DrmGpu::pipelines() const return m_pipelines; } -DrmVirtualOutput *DrmGpu::createVirtualOutput(const QString &name, const QSize &size, double scale, VirtualOutputType type) +DrmVirtualOutput *DrmGpu::createVirtualOutput(const QString &name, const QSize &size, double scale) { - auto output = new DrmVirtualOutput(name, this, size, scale, type); + auto output = new DrmVirtualOutput(name, this, size, scale); m_outputs << output; Q_EMIT outputAdded(output); return output; diff --git a/src/backends/drm/drm_gpu.h b/src/backends/drm/drm_gpu.h index 691b22a83b..ba44eda96e 100644 --- a/src/backends/drm/drm_gpu.h +++ b/src/backends/drm/drm_gpu.h @@ -11,7 +11,6 @@ #define DRM_GPU_H #include "drm_pipeline.h" -#include "drm_virtual_output.h" #include #include @@ -42,6 +41,7 @@ class DrmBackend; class EglGbmBackend; class DrmAbstractOutput; class DrmRenderBackend; +class DrmVirtualOutput; class DrmGpu : public QObject { @@ -74,7 +74,7 @@ public: bool updateOutputs(); - DrmVirtualOutput *createVirtualOutput(const QString &name, const QSize &size, double scale, VirtualOutputType type); + DrmVirtualOutput *createVirtualOutput(const QString &name, const QSize &size, double scale); void removeVirtualOutput(DrmVirtualOutput *output); DrmPipeline::Error testPendingConfiguration(); diff --git a/src/backends/drm/drm_virtual_output.cpp b/src/backends/drm/drm_virtual_output.cpp index 3be92f3a53..f6c24641aa 100644 --- a/src/backends/drm/drm_virtual_output.cpp +++ b/src/backends/drm/drm_virtual_output.cpp @@ -20,7 +20,7 @@ namespace KWin { -DrmVirtualOutput::DrmVirtualOutput(const QString &name, DrmGpu *gpu, const QSize &size, qreal scale, VirtualOutputType type) +DrmVirtualOutput::DrmVirtualOutput(const QString &name, DrmGpu *gpu, const QSize &size, qreal scale) : DrmAbstractOutput(gpu) , m_vsyncMonitor(SoftwareVsyncMonitor::create()) { @@ -32,7 +32,6 @@ DrmVirtualOutput::DrmVirtualOutput(const QString &name, DrmGpu *gpu, const QSize setInformation(Information{ .name = QStringLiteral("Virtual-") + name, .physicalSize = size, - .placeholder = type == VirtualOutputType::Placeholder, }); setState(State{ diff --git a/src/backends/drm/drm_virtual_output.h b/src/backends/drm/drm_virtual_output.h index 12002ebacb..b19a6db8c1 100644 --- a/src/backends/drm/drm_virtual_output.h +++ b/src/backends/drm/drm_virtual_output.h @@ -9,7 +9,6 @@ */ #pragma once -#include "core/platform.h" #include "drm_abstract_output.h" #include @@ -27,7 +26,7 @@ class DrmVirtualOutput : public DrmAbstractOutput Q_OBJECT public: - DrmVirtualOutput(const QString &name, DrmGpu *gpu, const QSize &size, qreal scale, VirtualOutputType type); + DrmVirtualOutput(const QString &name, DrmGpu *gpu, const QSize &size, qreal scale); ~DrmVirtualOutput() override; bool present() override; diff --git a/src/backends/wayland/wayland_backend.cpp b/src/backends/wayland/wayland_backend.cpp index 9e238c2bd5..9610029366 100644 --- a/src/backends/wayland/wayland_backend.cpp +++ b/src/backends/wayland/wayland_backend.cpp @@ -775,11 +775,11 @@ void WaylandBackend::createOutputs() for (int i = 0; i < initialOutputCount(); i++) { const QString name = QStringLiteral("WL-%1").arg(i); - createOutput(name, QSize(pixelWidth, pixelHeight), false); + createOutput(name, QSize(pixelWidth, pixelHeight)); } } -WaylandOutput *WaylandBackend::createOutput(const QString &name, const QSize &size, bool placeholder) +WaylandOutput *WaylandBackend::createOutput(const QString &name, const QSize &size) { auto surface = m_compositor->createSurface(this); if (!surface || !surface->isValid()) { @@ -799,7 +799,7 @@ WaylandOutput *WaylandBackend::createOutput(const QString &name, const QSize &si WaylandOutput *waylandOutput = nullptr; if (m_xdgShell && m_xdgShell->isValid()) { - waylandOutput = new XdgShellOutput(name, surface, m_xdgShell, this, m_nextId++, placeholder); + waylandOutput = new XdgShellOutput(name, surface, m_xdgShell, this, m_nextId++); } if (!waylandOutput) { @@ -967,9 +967,9 @@ void WaylandBackend::clearDpmsFilter() m_dpmsFilter.reset(); } -Output *WaylandBackend::createVirtualOutput(const QString &name, const QSize &size, double scale, VirtualOutputType type) +Output *WaylandBackend::createVirtualOutput(const QString &name, const QSize &size, double scale) { - return createOutput(name, size * scale, type == VirtualOutputType::Placeholder); + return createOutput(name, size * scale); } void WaylandBackend::removeVirtualOutput(Output *output) diff --git a/src/backends/wayland/wayland_backend.h b/src/backends/wayland/wayland_backend.h index 3a1eddd23f..0ce2a7b65d 100644 --- a/src/backends/wayland/wayland_backend.h +++ b/src/backends/wayland/wayland_backend.h @@ -298,7 +298,7 @@ public: void createDpmsFilter(); void clearDpmsFilter(); - Output *createVirtualOutput(const QString &name, const QSize &size, double scale, VirtualOutputType type) override; + Output *createVirtualOutput(const QString &name, const QSize &size, double scale) override; void removeVirtualOutput(Output *output) override; std::optional testCreateDmaBuf(const QSize &size, quint32 format, const QVector &modifiers) override; @@ -327,7 +327,7 @@ private: void createOutputs(); void destroyOutputs(); - WaylandOutput *createOutput(const QString &name, const QSize &size, bool placeholder); + WaylandOutput *createOutput(const QString &name, const QSize &size); wl_display *m_display; KWayland::Client::EventQueue *m_eventQueue; diff --git a/src/backends/wayland/wayland_output.cpp b/src/backends/wayland/wayland_output.cpp index bfb447c416..57bdb11040 100644 --- a/src/backends/wayland/wayland_output.cpp +++ b/src/backends/wayland/wayland_output.cpp @@ -24,7 +24,7 @@ namespace Wayland using namespace KWayland::Client; static const int s_refreshRate = 60000; // TODO: can we get refresh rate data from Wayland host? -WaylandOutput::WaylandOutput(const QString &name, Surface *surface, WaylandBackend *backend, bool placeholder) +WaylandOutput::WaylandOutput(const QString &name, Surface *surface, WaylandBackend *backend) : Output(backend) , m_renderLoop(std::make_unique()) , m_surface(surface) @@ -34,7 +34,6 @@ WaylandOutput::WaylandOutput(const QString &name, Surface *surface, WaylandBacke .name = name, .model = name, .capabilities = Capability::Dpms, - .placeholder = placeholder, }); connect(surface, &Surface::frameRendered, this, &WaylandOutput::frameRendered); @@ -114,8 +113,8 @@ void WaylandOutput::updateEnabled(bool enabled) setState(next); } -XdgShellOutput::XdgShellOutput(const QString &name, Surface *surface, XdgShell *xdgShell, WaylandBackend *backend, int number, bool placeholder) - : WaylandOutput(name, surface, backend, placeholder) +XdgShellOutput::XdgShellOutput(const QString &name, Surface *surface, XdgShell *xdgShell, WaylandBackend *backend, int number) + : WaylandOutput(name, surface, backend) , m_number(number) { m_xdgShellSurface = xdgShell->createSurface(surface, this); diff --git a/src/backends/wayland/wayland_output.h b/src/backends/wayland/wayland_output.h index 899ca75990..0dcf7487a8 100644 --- a/src/backends/wayland/wayland_output.h +++ b/src/backends/wayland/wayland_output.h @@ -39,7 +39,7 @@ class WaylandOutput : public Output { Q_OBJECT public: - WaylandOutput(const QString &name, KWayland::Client::Surface *surface, WaylandBackend *backend, bool placeholder); + WaylandOutput(const QString &name, KWayland::Client::Surface *surface, WaylandBackend *backend); ~WaylandOutput() override; RenderLoop *renderLoop() const override; @@ -92,7 +92,7 @@ public: XdgShellOutput(const QString &name, KWayland::Client::Surface *surface, KWayland::Client::XdgShell *xdgShell, - WaylandBackend *backend, int number, bool placeholder); + WaylandBackend *backend, int number); ~XdgShellOutput() override; void lockPointer(KWayland::Client::Pointer *pointer, bool lock) override; diff --git a/src/core/platform.cpp b/src/core/platform.cpp index 5eb5a81064..c406357bf6 100644 --- a/src/core/platform.cpp +++ b/src/core/platform.cpp @@ -142,12 +142,11 @@ void Platform::setReady(bool ready) Q_EMIT readyChanged(m_ready); } -Output *Platform::createVirtualOutput(const QString &name, const QSize &size, double scale, VirtualOutputType type) +Output *Platform::createVirtualOutput(const QString &name, const QSize &size, double scale) { Q_UNUSED(name); Q_UNUSED(size); Q_UNUSED(scale); - Q_UNUSED(type); return nullptr; } diff --git a/src/core/platform.h b/src/core/platform.h index b21348a03a..d1d47652dd 100644 --- a/src/core/platform.h +++ b/src/core/platform.h @@ -40,11 +40,6 @@ class ScreenEdges; class OutputConfiguration; struct DmaBufParams; -enum class VirtualOutputType { - Normal, - Placeholder, -}; - class KWIN_EXPORT Outputs : public QVector { public: @@ -322,7 +317,7 @@ public: m_selectedCompositor = type; } - virtual Output *createVirtualOutput(const QString &name, const QSize &size, qreal scaling, VirtualOutputType type); + virtual Output *createVirtualOutput(const QString &name, const QSize &size, qreal scale); virtual void removeVirtualOutput(Output *output); /** diff --git a/src/placeholderoutput.cpp b/src/placeholderoutput.cpp new file mode 100644 index 0000000000..eecb4660f5 --- /dev/null +++ b/src/placeholderoutput.cpp @@ -0,0 +1,42 @@ +/* + SPDX-FileCopyrightText: 2022 Vlad Zahorodnii + + SPDX-License-Identifier: GPL-2.0-or-later +*/ + +#include "placeholderoutput.h" + +namespace KWin +{ + +PlaceholderOutput::PlaceholderOutput(const QSize &size, qreal scale) +{ + auto mode = std::make_shared(size, 60000); + + m_renderLoop = std::make_unique(); + m_renderLoop->setRefreshRate(mode->refreshRate()); + m_renderLoop->inhibit(); + + setState(State{ + .scale = scale, + .modes = {mode}, + .currentMode = mode, + .enabled = true, + }); + + setInformation(Information{ + .name = QStringLiteral("Placeholder-1"), + .placeholder = true, + }); +} + +PlaceholderOutput::~PlaceholderOutput() +{ +} + +RenderLoop *PlaceholderOutput::renderLoop() const +{ + return m_renderLoop.get(); +} + +} // namespace KWin diff --git a/src/placeholderoutput.h b/src/placeholderoutput.h new file mode 100644 index 0000000000..850227a4c2 --- /dev/null +++ b/src/placeholderoutput.h @@ -0,0 +1,28 @@ +/* + SPDX-FileCopyrightText: 2022 Vlad Zahorodnii + + SPDX-License-Identifier: GPL-2.0-or-later +*/ + +#pragma once + +#include "core/output.h" + +namespace KWin +{ + +class PlaceholderOutput : public Output +{ + Q_OBJECT + +public: + PlaceholderOutput(const QSize &size, qreal scale = 1); + ~PlaceholderOutput() override; + + RenderLoop *renderLoop() const override; + +private: + std::unique_ptr m_renderLoop; +}; + +} // namespace KWin diff --git a/src/plugins/screencast/screencastmanager.cpp b/src/plugins/screencast/screencastmanager.cpp index 58a2181b89..947311bee1 100644 --- a/src/plugins/screencast/screencastmanager.cpp +++ b/src/plugins/screencast/screencastmanager.cpp @@ -110,7 +110,7 @@ void ScreencastManager::streamVirtualOutput(KWaylandServer::ScreencastStreamV1In double scale, KWaylandServer::ScreencastV1Interface::CursorMode mode) { - auto output = kwinApp()->platform()->createVirtualOutput(name, size, scale, VirtualOutputType::Normal); + auto output = kwinApp()->platform()->createVirtualOutput(name, size, scale); streamOutput(stream, output, mode); connect(stream, &KWaylandServer::ScreencastStreamV1Interface::finished, output, [output] { kwinApp()->platform()->removeVirtualOutput(output); diff --git a/src/workspace.cpp b/src/workspace.cpp index ba9e2f9d48..f4a3ba07f7 100644 --- a/src/workspace.cpp +++ b/src/workspace.cpp @@ -48,6 +48,7 @@ #include "decorations/decorationbridge.h" #include "main.h" #include "placeholderinputeventfilter.h" +#include "placeholderoutput.h" #include "placementtracker.h" #include "unmanaged.h" #include "useractions.h" @@ -1452,8 +1453,9 @@ void Workspace::addOutput(Output *output) Q_EMIT outputAdded(output); if (m_placeholderOutput) { - kwinApp()->platform()->removeVirtualOutput(m_placeholderOutput); - m_placeholderOutput = nullptr; + m_outputs.removeOne(m_placeholderOutput.get()); + Q_EMIT outputRemoved(m_placeholderOutput.get()); + m_placeholderOutput.reset(); m_placeholderFilter.reset(); } } @@ -1465,8 +1467,9 @@ void Workspace::removeOutput(Output *output) } if (m_outputs.empty()) { // not all parts of KWin handle having no output yet. To prevent crashes, create a placeholder output - m_placeholderOutput = kwinApp()->platform()->createVirtualOutput("placeholder", output->pixelSize(), output->scale(), VirtualOutputType::Placeholder); - m_placeholderOutput->renderLoop()->inhibit(); + m_placeholderOutput = std::make_unique(output->pixelSize(), output->scale()); + m_outputs.append(m_placeholderOutput.get()); + Q_EMIT outputAdded(m_placeholderOutput.get()); // also prevent accidental inputs while the user has no screen connected m_placeholderFilter = std::make_unique(); input()->prependInputEventFilter(m_placeholderFilter.get()); diff --git a/src/workspace.h b/src/workspace.h index 0d09aa0822..4c78835719 100644 --- a/src/workspace.h +++ b/src/workspace.h @@ -76,6 +76,7 @@ class Screens; class Activities; #endif class PlaceholderInputEventFilter; +class PlaceholderOutput; class Placement; class KWIN_EXPORT Workspace : public QObject @@ -756,7 +757,7 @@ private: #endif std::unique_ptr m_placementTracker; - Output *m_placeholderOutput = nullptr; + std::unique_ptr m_placeholderOutput; std::unique_ptr m_placeholderFilter; private: