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.
This commit is contained in:
Vlad Zahorodnii 2022-09-06 13:10:28 +03:00
parent 192a57e2e1
commit d8ea87a9ea
18 changed files with 104 additions and 38 deletions

View file

@ -106,6 +106,7 @@ target_sources(kwin PRIVATE
osd.cpp
outline.cpp
placeholderinputeventfilter.cpp
placeholderoutput.cpp
placement.cpp
placementtracker.cpp
plugin.cpp

View file

@ -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;
}

View file

@ -60,7 +60,7 @@ public:
QVector<CompositingType> 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;

View file

@ -587,9 +587,9 @@ const QVector<DrmPipeline *> 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;

View file

@ -11,7 +11,6 @@
#define DRM_GPU_H
#include "drm_pipeline.h"
#include "drm_virtual_output.h"
#include <QPointer>
#include <QSize>
@ -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();

View file

@ -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{

View file

@ -9,7 +9,6 @@
*/
#pragma once
#include "core/platform.h"
#include "drm_abstract_output.h"
#include <QObject>
@ -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;

View file

@ -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)

View file

@ -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<DmaBufParams> testCreateDmaBuf(const QSize &size, quint32 format, const QVector<uint64_t> &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;

View file

@ -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<RenderLoop>())
, 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);

View file

@ -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;

View file

@ -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;
}

View file

@ -40,11 +40,6 @@ class ScreenEdges;
class OutputConfiguration;
struct DmaBufParams;
enum class VirtualOutputType {
Normal,
Placeholder,
};
class KWIN_EXPORT Outputs : public QVector<Output *>
{
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);
/**

42
src/placeholderoutput.cpp Normal file
View file

@ -0,0 +1,42 @@
/*
SPDX-FileCopyrightText: 2022 Vlad Zahorodnii <vlad.zahorodnii@kde.org>
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<OutputMode>(size, 60000);
m_renderLoop = std::make_unique<RenderLoop>();
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

28
src/placeholderoutput.h Normal file
View file

@ -0,0 +1,28 @@
/*
SPDX-FileCopyrightText: 2022 Vlad Zahorodnii <vlad.zahorodnii@kde.org>
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<RenderLoop> m_renderLoop;
};
} // namespace KWin

View file

@ -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);

View file

@ -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<PlaceholderOutput>(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<PlaceholderInputEventFilter>();
input()->prependInputEventFilter(m_placeholderFilter.get());

View file

@ -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<PlacementTracker> m_placementTracker;
Output *m_placeholderOutput = nullptr;
std::unique_ptr<PlaceholderOutput> m_placeholderOutput;
std::unique_ptr<PlaceholderInputEventFilter> m_placeholderFilter;
private: