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: