Add TestOutputManagement::testOutputDeviceDisabled test
Allow VirtualBackend to supports Output changes.
This commit is contained in:
parent
866dfb4e89
commit
4f744d1bb6
11 changed files with 329 additions and 15 deletions
|
@ -263,10 +263,10 @@ void AbstractWaylandOutput::initInterfaces(const QString &model, const QString &
|
|||
{
|
||||
m_waylandOutputDevice->setUuid(uuid);
|
||||
|
||||
if (!manufacturer.isEmpty()) {
|
||||
m_waylandOutputDevice->setManufacturer(manufacturer);
|
||||
} else {
|
||||
if (manufacturer.isEmpty()) {
|
||||
m_waylandOutputDevice->setManufacturer(i18n("unknown"));
|
||||
} else {
|
||||
m_waylandOutputDevice->setManufacturer(manufacturer);
|
||||
}
|
||||
m_waylandOutputDevice->setEdid(edid);
|
||||
|
||||
|
|
|
@ -97,6 +97,7 @@ integrationTest(WAYLAND_ONLY NAME testPlacement SRCS placement_test.cpp)
|
|||
integrationTest(WAYLAND_ONLY NAME testActivation SRCS activation_test.cpp)
|
||||
integrationTest(WAYLAND_ONLY NAME testInputMethod SRCS inputmethod_test.cpp)
|
||||
integrationTest(WAYLAND_ONLY NAME testScreens SRCS screens_test.cpp)
|
||||
integrationTest(WAYLAND_ONLY NAME testOutputManagement SRCS outputmanagement_test.cpp)
|
||||
|
||||
if (KWIN_BUILD_CMS)
|
||||
integrationTest(WAYLAND_ONLY NAME testNightColor SRCS nightcolor_test.cpp LIBS KWinNightColorPlugin)
|
||||
|
|
|
@ -42,6 +42,7 @@ class Surface;
|
|||
class XdgDecorationManager;
|
||||
class OutputManagement;
|
||||
class TextInputManager;
|
||||
class OutputDevice;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -236,7 +237,8 @@ enum class AdditionalWaylandInterface {
|
|||
TextInputManagerV2 = 1 << 10,
|
||||
InputMethodV1 = 1 << 11,
|
||||
LayerShellV1 = 1 << 12,
|
||||
TextInputManagerV3 = 1 << 13
|
||||
TextInputManagerV3 = 1 << 13,
|
||||
OutputDevice = 1 << 14
|
||||
};
|
||||
Q_DECLARE_FLAGS(AdditionalWaylandInterfaces, AdditionalWaylandInterface)
|
||||
/**
|
||||
|
@ -271,6 +273,7 @@ KWayland::Client::XdgDecorationManager *xdgDecorationManager();
|
|||
KWayland::Client::OutputManagement *waylandOutputManagement();
|
||||
KWayland::Client::TextInputManager *waylandTextInputManager();
|
||||
QVector<KWayland::Client::Output *> waylandOutputs();
|
||||
QVector<KWayland::Client::OutputDevice *> waylandOutputDevices();
|
||||
|
||||
bool waitForWaylandPointer();
|
||||
bool waitForWaylandTouch();
|
||||
|
|
176
autotests/integration/outputmanagement_test.cpp
Normal file
176
autotests/integration/outputmanagement_test.cpp
Normal file
|
@ -0,0 +1,176 @@
|
|||
/*
|
||||
KWin - the KDE window manager
|
||||
This file is part of the KDE project.
|
||||
|
||||
SPDX-FileCopyrightText: 2020 Méven Car <meven.car@enioka.com>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
#include "kwin_wayland_test.h"
|
||||
#include "abstract_client.h"
|
||||
#include "abstract_wayland_output.h"
|
||||
#include "deleted.h"
|
||||
#include "platform.h"
|
||||
#include "screens.h"
|
||||
#include "wayland_server.h"
|
||||
|
||||
#include <KWayland/Client/outputmanagement.h>
|
||||
#include <KWayland/Client/outputconfiguration.h>
|
||||
#include <KWayland/Client/outputdevice.h>
|
||||
|
||||
#include <KWaylandServer/outputmanagement_interface.h>
|
||||
#include <KWaylandServer/outputconfiguration_interface.h>
|
||||
#include <KWaylandServer/outputdevice_interface.h>
|
||||
#include <KWayland/Client/output.h>
|
||||
#include <KWayland/Client/outputdevice.h>
|
||||
#include <KWayland/Client/server_decoration.h>
|
||||
#include <KWayland/Client/surface.h>
|
||||
#include <KWayland/Client/xdgshell.h>
|
||||
|
||||
#include <KWaylandServer/display.h>
|
||||
|
||||
using namespace KWin;
|
||||
using namespace KWayland::Client;
|
||||
|
||||
static const QString s_socketName = QStringLiteral("wayland_test_kwin_outputmanagement-0");
|
||||
|
||||
class TestOutputManagement : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
private Q_SLOTS:
|
||||
void initTestCase();
|
||||
void init();
|
||||
void cleanup();
|
||||
|
||||
void testOutputDeviceDisabled();
|
||||
};
|
||||
|
||||
void TestOutputManagement::initTestCase()
|
||||
{
|
||||
qRegisterMetaType<KWin::Deleted*>();
|
||||
qRegisterMetaType<KWin::AbstractClient*>();
|
||||
qRegisterMetaType<KWin::AbstractOutput*>();
|
||||
qRegisterMetaType<KWin::AbstractOutput*>("AbstractOutput *");
|
||||
qRegisterMetaType<KWayland::Client::Output*>();
|
||||
qRegisterMetaType<KWayland::Client::OutputDevice::Enablement>();
|
||||
qRegisterMetaType<OutputDevice::Enablement>("OutputDevice::Enablement");
|
||||
qRegisterMetaType<KWaylandServer::OutputDeviceInterface::Enablement>();
|
||||
|
||||
QSignalSpy applicationStartedSpy(kwinApp(), &Application::started);
|
||||
QVERIFY(applicationStartedSpy.isValid());
|
||||
kwinApp()->platform()->setInitialWindowSize(QSize(1280, 1024));
|
||||
QVERIFY(waylandServer()->init(s_socketName));
|
||||
QMetaObject::invokeMethod(kwinApp()->platform(), "setVirtualOutputs", Qt::DirectConnection, Q_ARG(int, 2));
|
||||
|
||||
kwinApp()->start();
|
||||
QVERIFY(applicationStartedSpy.wait());
|
||||
QCOMPARE(screens()->count(), 2);
|
||||
QCOMPARE(screens()->geometry(0), QRect(0, 0, 1280, 1024));
|
||||
QCOMPARE(screens()->geometry(1), QRect(1280, 0, 1280, 1024));
|
||||
waylandServer()->initWorkspace();
|
||||
}
|
||||
|
||||
void TestOutputManagement::init()
|
||||
{
|
||||
QVERIFY(Test::setupWaylandConnection(Test::AdditionalWaylandInterface::OutputManagement |
|
||||
Test::AdditionalWaylandInterface::OutputDevice));
|
||||
|
||||
screens()->setCurrent(0);
|
||||
//put mouse in the middle of screen one
|
||||
KWin::Cursors::self()->mouse()->setPos(QPoint(512, 512));
|
||||
}
|
||||
|
||||
void TestOutputManagement::cleanup()
|
||||
{
|
||||
Test::destroyWaylandConnection();
|
||||
}
|
||||
|
||||
void TestOutputManagement::testOutputDeviceDisabled()
|
||||
{
|
||||
// This tests checks that OutputConfiguration::apply aka Platform::requestOutputsChange works as expected
|
||||
// when disabling and enabling virtual OutputDevice
|
||||
|
||||
QScopedPointer<Surface> surface(Test::createSurface());
|
||||
QScopedPointer<XdgShellSurface> shellSurface(Test::createXdgShellStableSurface(surface.data()));
|
||||
auto size = QSize(200,200);
|
||||
|
||||
QSignalSpy outputEnteredSpy(surface.data(), &Surface::outputEntered);
|
||||
QSignalSpy outputLeftSpy(surface.data(), &Surface::outputLeft);
|
||||
|
||||
QSignalSpy outputEnabledSpy(kwinApp()->platform(), &Platform::outputEnabled);
|
||||
QSignalSpy outputDisabledSpy(kwinApp()->platform(), &Platform::outputDisabled);
|
||||
|
||||
auto c = Test::renderAndWaitForShown(surface.data(), size, Qt::blue);
|
||||
//move to be in the first screen
|
||||
c->setFrameGeometry(QRect(QPoint(100,100), size));
|
||||
//we don't don't know where the compositor first placed this window,
|
||||
//this might fire, it might not
|
||||
outputEnteredSpy.wait(5);
|
||||
outputEnteredSpy.clear();
|
||||
QCOMPARE(waylandServer()->display()->outputs().count(), 2);
|
||||
|
||||
QCOMPARE(surface->outputs().count(), 1);
|
||||
Output *firstOutput = surface->outputs().first();
|
||||
QCOMPARE(firstOutput->globalPosition(), QPoint(0,0));
|
||||
QSignalSpy modesChangedSpy(firstOutput, &Output::modeChanged);
|
||||
|
||||
QSignalSpy screenChangedSpy(screens(), &KWin::Screens::changed);
|
||||
|
||||
OutputManagement *outManagement = Test::waylandOutputManagement();
|
||||
|
||||
auto outputDevices = Test::waylandOutputDevices();
|
||||
QCOMPARE(outputDevices.count(), 2);
|
||||
|
||||
OutputDevice *device = outputDevices.first();
|
||||
QCOMPARE(device->enabled(), OutputDevice::Enablement::Enabled);
|
||||
QSignalSpy outputDeviceEnabledChangedSpy(device, &OutputDevice::enabledChanged);
|
||||
OutputConfiguration *config;
|
||||
|
||||
// Disables an output
|
||||
config = outManagement->createConfiguration();
|
||||
QSignalSpy configAppliedSpy (config, &OutputConfiguration::applied);
|
||||
config->setEnabled(device, OutputDevice::Enablement::Disabled);
|
||||
config->apply();
|
||||
QVERIFY(configAppliedSpy.wait());
|
||||
|
||||
QCOMPARE(outputDeviceEnabledChangedSpy.count(), 1);
|
||||
QCOMPARE(device->enabled(), OutputDevice::Enablement::Disabled);
|
||||
QCOMPARE(screenChangedSpy.count(), 3);
|
||||
QCOMPARE(outputLeftSpy.count(), 1);
|
||||
QCOMPARE(outputEnteredSpy.count(), 1); // surface was moved to other screen
|
||||
QCOMPARE(surface->outputs().count(), 1);
|
||||
QCOMPARE(screens()->count(), 1);
|
||||
QCOMPARE(modesChangedSpy.count(), 0);
|
||||
QCOMPARE(outputEnabledSpy.count(), 0);
|
||||
QCOMPARE(outputDisabledSpy.count(), 1);
|
||||
|
||||
screenChangedSpy.clear();
|
||||
outputLeftSpy.clear();
|
||||
outputEnteredSpy.clear();
|
||||
outputDeviceEnabledChangedSpy.clear();
|
||||
outputEnabledSpy.clear();
|
||||
outputDisabledSpy.clear();
|
||||
|
||||
// Enable the disabled output
|
||||
config = outManagement->createConfiguration();
|
||||
QSignalSpy configAppliedSpy2 (config, &OutputConfiguration::applied);
|
||||
config->setEnabled(device, OutputDevice::Enablement::Enabled);
|
||||
config->apply();
|
||||
QVERIFY(configAppliedSpy2.wait());
|
||||
|
||||
QVERIFY(outputEnteredSpy.wait());
|
||||
|
||||
QCOMPARE(outputDeviceEnabledChangedSpy.count(), 1);
|
||||
QCOMPARE(device->enabled(), OutputDevice::Enablement::Enabled);
|
||||
QCOMPARE(screenChangedSpy.count(), 3);
|
||||
QCOMPARE(outputLeftSpy.count(), 1);
|
||||
QCOMPARE(outputEnteredSpy.count(), 1); // surface moved back to first screen
|
||||
QCOMPARE(surface->outputs().count(), 1);
|
||||
QCOMPARE(screens()->count(), 2);
|
||||
QCOMPARE(modesChangedSpy.count(), 0);
|
||||
QCOMPARE(outputEnabledSpy.count(), 1);
|
||||
QCOMPARE(outputDisabledSpy.count(), 0);
|
||||
}
|
||||
|
||||
WAYLANDTEST_MAIN(TestOutputManagement)
|
||||
#include "outputmanagement_test.moc"
|
|
@ -27,6 +27,7 @@
|
|||
#include <KWayland/Client/shadow.h>
|
||||
#include <KWayland/Client/shm_pool.h>
|
||||
#include <KWayland/Client/output.h>
|
||||
#include <KWayland/Client/outputdevice.h>
|
||||
#include <KWayland/Client/subcompositor.h>
|
||||
#include <KWayland/Client/subsurface.h>
|
||||
#include <KWayland/Client/surface.h>
|
||||
|
@ -200,6 +201,7 @@ static struct {
|
|||
OutputManagement* outputManagement = nullptr;
|
||||
QThread *thread = nullptr;
|
||||
QVector<Output*> outputs;
|
||||
QVector<OutputDevice*> outputDevices;
|
||||
IdleInhibitManager *idleInhibit = nullptr;
|
||||
AppMenuManager *appMenu = nullptr;
|
||||
XdgDecorationManager *xdgDecoration = nullptr;
|
||||
|
@ -299,7 +301,7 @@ bool setupWaylandConnection(AdditionalWaylandInterfaces flags)
|
|||
registry->setEventQueue(s_waylandConnection.queue);
|
||||
|
||||
QObject::connect(registry, &Registry::outputAnnounced, [=](quint32 name, quint32 version) {
|
||||
auto output = registry->createOutput(name, version, s_waylandConnection.registry);
|
||||
Output* output = registry->createOutput(name, version, s_waylandConnection.registry);
|
||||
s_waylandConnection.outputs << output;
|
||||
QObject::connect(output, &Output::removed, [=]() {
|
||||
output->deleteLater();
|
||||
|
@ -310,6 +312,22 @@ bool setupWaylandConnection(AdditionalWaylandInterfaces flags)
|
|||
});
|
||||
});
|
||||
|
||||
if (flags.testFlag(AdditionalWaylandInterface::OutputDevice)) {
|
||||
QObject::connect(registry, &KWayland::Client::Registry::outputDeviceAnnounced,
|
||||
[=](quint32 name, quint32 version) {
|
||||
|
||||
OutputDevice *device = registry->createOutputDevice(name, version);
|
||||
s_waylandConnection.outputDevices << device;
|
||||
|
||||
QObject::connect(device, &OutputDevice::removed, [=]() {
|
||||
s_waylandConnection.outputDevices.removeOne(device);
|
||||
});
|
||||
QObject::connect(device, &OutputDevice::destroyed, [=]() {
|
||||
s_waylandConnection.outputDevices.removeOne(device);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
QObject::connect(registry, &Registry::interfaceAnnounced, [=](const QByteArray &interface, quint32 name, quint32 version) {
|
||||
if (flags & AdditionalWaylandInterface::InputMethodV1) {
|
||||
if (interface == QByteArrayLiteral("zwp_input_method_v1")) {
|
||||
|
@ -497,6 +515,8 @@ void destroyWaylandConnection()
|
|||
s_waylandConnection.thread = nullptr;
|
||||
s_waylandConnection.connection = nullptr;
|
||||
}
|
||||
s_waylandConnection.outputs.clear();
|
||||
s_waylandConnection.outputDevices.clear();
|
||||
}
|
||||
|
||||
ConnectionThread *waylandConnection()
|
||||
|
@ -584,6 +604,11 @@ QVector<KWayland::Client::Output *> waylandOutputs()
|
|||
return s_waylandConnection.outputs;
|
||||
}
|
||||
|
||||
QVector<OutputDevice *> waylandOutputDevices()
|
||||
{
|
||||
return s_waylandConnection.outputDevices;
|
||||
}
|
||||
|
||||
bool waitForWaylandPointer()
|
||||
{
|
||||
if (!s_waylandConnection.seat) {
|
||||
|
|
|
@ -122,16 +122,19 @@ void Platform::requestOutputsChange(KWaylandServer::OutputConfigurationInterface
|
|||
for (auto it = changes.begin(); it != changes.end(); it++) {
|
||||
const KWaylandServer::OutputChangeSet *changeset = it.value();
|
||||
|
||||
auto output = findOutput(it.key()->uuid());
|
||||
AbstractOutput* output = findOutput(it.key()->uuid());
|
||||
if (!output) {
|
||||
qCWarning(KWIN_CORE) << "Could NOT find output matching " << it.key()->uuid();
|
||||
continue;
|
||||
}
|
||||
|
||||
qDebug(KWIN_CORE) << "Platform::requestOutputsChange enabling" << changeset << it.key()->uuid() << changeset->enabledChanged() << (changeset->enabled() == Enablement::Enabled);
|
||||
|
||||
if (changeset->enabledChanged() &&
|
||||
changeset->enabled() == Enablement::Enabled) {
|
||||
output->setEnabled(true);
|
||||
}
|
||||
|
||||
output->applyChanges(changeset);
|
||||
}
|
||||
|
||||
|
@ -152,9 +155,11 @@ void Platform::requestOutputsChange(KWaylandServer::OutputConfigurationInterface
|
|||
qCWarning(KWIN_CORE) << "Could NOT find output matching " << it.key()->uuid();
|
||||
continue;
|
||||
}
|
||||
qDebug(KWIN_CORE) << "Platform::requestOutputsChange disabling false" << it.key()->uuid();
|
||||
output->setEnabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
emit screens()->changed();
|
||||
config->setApplied();
|
||||
}
|
||||
|
|
44
plugins/platforms/virtual/screens_virtual.cpp
Normal file
44
plugins/platforms/virtual/screens_virtual.cpp
Normal file
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
KWin - the KDE window manager
|
||||
This file is part of the KDE project.
|
||||
|
||||
SPDX-FileCopyrightText: 2015 Martin Gräßlin <mgraesslin@kde.org>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
#include "screens_virtual.h"
|
||||
#include "virtual_backend.h"
|
||||
#include "virtual_output.h"
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
|
||||
VirtualScreens::VirtualScreens(VirtualBackend *backend, QObject *parent)
|
||||
: OutputScreens(backend, parent)
|
||||
, m_backend(backend)
|
||||
{
|
||||
connect(backend, &VirtualBackend::screensQueried, this, &VirtualScreens::updateCount);
|
||||
connect(backend, &VirtualBackend::screensQueried, this, &VirtualScreens::changed);
|
||||
}
|
||||
|
||||
VirtualScreens::~VirtualScreens() = default;
|
||||
|
||||
void VirtualScreens::init()
|
||||
{
|
||||
updateCount();
|
||||
KWin::Screens::init();
|
||||
|
||||
connect(m_backend, &VirtualBackend::virtualOutputsSet, this,
|
||||
[this] (bool countChanged) {
|
||||
if (countChanged) {
|
||||
setCount(m_backend->outputs().size());
|
||||
} else {
|
||||
emit changed();
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
emit changed();
|
||||
}
|
||||
|
||||
}
|
|
@ -35,6 +35,8 @@ VirtualBackend::VirtualBackend(QObject *parent)
|
|||
qDebug() << "Screenshots saved to: " << m_screenshotDir->path();
|
||||
}
|
||||
}
|
||||
|
||||
supportsOutputChanges();
|
||||
setSupportsPointerWarping(true);
|
||||
setSupportsGammaControl(true);
|
||||
setPerScreenRenderingEnabled(true);
|
||||
|
@ -97,7 +99,7 @@ Outputs VirtualBackend::outputs() const
|
|||
|
||||
Outputs VirtualBackend::enabledOutputs() const
|
||||
{
|
||||
return m_outputs;
|
||||
return m_outputsEnabled;
|
||||
}
|
||||
|
||||
void VirtualBackend::setVirtualOutputs(int count, QVector<QRect> geometries, QVector<int> scales)
|
||||
|
@ -105,9 +107,15 @@ void VirtualBackend::setVirtualOutputs(int count, QVector<QRect> geometries, QVe
|
|||
Q_ASSERT(geometries.size() == 0 || geometries.size() == count);
|
||||
Q_ASSERT(scales.size() == 0 || scales.size() == count);
|
||||
|
||||
bool countChanged = m_outputs.size() != count;
|
||||
|
||||
while (!m_outputsEnabled.isEmpty()) {
|
||||
VirtualOutput *output = m_outputsEnabled.takeLast();
|
||||
emit outputDisabled(output);
|
||||
}
|
||||
|
||||
while (!m_outputs.isEmpty()) {
|
||||
VirtualOutput *output = m_outputs.takeLast();
|
||||
emit outputDisabled(output);
|
||||
emit outputRemoved(output);
|
||||
delete output;
|
||||
}
|
||||
|
@ -126,6 +134,7 @@ void VirtualBackend::setVirtualOutputs(int count, QVector<QRect> geometries, QVe
|
|||
vo->setScale(scales.at(i));
|
||||
}
|
||||
m_outputs.append(vo);
|
||||
m_outputsEnabled.append(vo);
|
||||
emit outputAdded(vo);
|
||||
emit outputEnabled(vo);
|
||||
}
|
||||
|
@ -133,4 +142,37 @@ void VirtualBackend::setVirtualOutputs(int count, QVector<QRect> geometries, QVe
|
|||
emit screensQueried();
|
||||
}
|
||||
|
||||
void VirtualBackend::enableOutput(VirtualOutput *output, bool enable)
|
||||
{
|
||||
if (enable) {
|
||||
Q_ASSERT(!m_outputsEnabled.contains(output));
|
||||
m_outputsEnabled << output;
|
||||
|
||||
emit outputEnabled(output);
|
||||
} else {
|
||||
Q_ASSERT(m_outputsEnabled.contains(output));
|
||||
m_outputsEnabled.removeOne(output);
|
||||
|
||||
emit outputDisabled(output);
|
||||
}
|
||||
|
||||
emit screensQueried();
|
||||
}
|
||||
|
||||
void VirtualBackend::removeOutput(AbstractOutput *output)
|
||||
{
|
||||
|
||||
VirtualOutput* virtualOutput = static_cast<VirtualOutput *>(output);
|
||||
if (m_outputsEnabled.removeOne(virtualOutput)) {
|
||||
emit outputDisabled(virtualOutput);
|
||||
}
|
||||
|
||||
emit outputRemoved(virtualOutput);
|
||||
m_outputsEnabled.removeOne(virtualOutput);
|
||||
|
||||
delete virtualOutput;
|
||||
|
||||
emit screensQueried();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -52,11 +52,16 @@ public:
|
|||
return QVector<CompositingType>{OpenGLCompositing, QPainterCompositing};
|
||||
}
|
||||
|
||||
void enableOutput(VirtualOutput *output, bool enable);
|
||||
|
||||
void removeOutput(AbstractOutput *output);
|
||||
|
||||
Q_SIGNALS:
|
||||
void virtualOutputsSet(bool countChanged);
|
||||
|
||||
private:
|
||||
QVector<VirtualOutput*> m_outputs;
|
||||
QVector<VirtualOutput*> m_outputsEnabled;
|
||||
QScopedPointer<QTemporaryDir> m_screenshotDir;
|
||||
};
|
||||
|
||||
|
|
|
@ -7,23 +7,24 @@
|
|||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
#include "virtual_output.h"
|
||||
#include "virtual_backend.h"
|
||||
|
||||
#include "renderloop_p.h"
|
||||
#include "softwarevsyncmonitor.h"
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
|
||||
VirtualOutput::VirtualOutput(QObject *parent)
|
||||
: AbstractWaylandOutput()
|
||||
VirtualOutput::VirtualOutput(VirtualBackend *parent)
|
||||
: AbstractWaylandOutput(parent)
|
||||
, m_backend(parent)
|
||||
, m_renderLoop(new RenderLoop(this))
|
||||
, m_vsyncMonitor(SoftwareVsyncMonitor::create(this))
|
||||
{
|
||||
Q_UNUSED(parent);
|
||||
|
||||
connect(m_vsyncMonitor, &VsyncMonitor::vblankOccurred, this, &VirtualOutput::vblank);
|
||||
|
||||
static int identifier = -1;
|
||||
identifier++;
|
||||
m_identifier = ++identifier;
|
||||
setName("Virtual-" + QString::number(identifier));
|
||||
}
|
||||
|
||||
|
@ -52,7 +53,10 @@ void VirtualOutput::init(const QPoint &logicalPosition, const QSize &pixelSize)
|
|||
mode.size = pixelSize;
|
||||
mode.flags = KWaylandServer::OutputDeviceInterface::ModeFlag::Current;
|
||||
mode.refreshRate = refreshRate;
|
||||
initInterfaces("model_TODO", "manufacturer_TODO", "UUID_TODO", pixelSize, { mode }, {});
|
||||
initInterfaces(QByteArray("model_").append(QString::number(m_identifier)),
|
||||
QByteArray("manufacturer_").append(QString::number(m_identifier)),
|
||||
QByteArray("UUID_").append(QString::number(m_identifier)),
|
||||
pixelSize, { mode }, QByteArray("EDID_").append(QString::number(m_identifier)));
|
||||
setGeometry(QRect(logicalPosition, pixelSize));
|
||||
}
|
||||
|
||||
|
@ -68,4 +72,9 @@ void VirtualOutput::vblank(std::chrono::nanoseconds timestamp)
|
|||
renderLoopPrivate->notifyFrameCompleted(timestamp);
|
||||
}
|
||||
|
||||
void VirtualOutput::updateEnablement(bool enable)
|
||||
{
|
||||
m_backend->enableOutput(this, enable);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@ class VirtualOutput : public AbstractWaylandOutput
|
|||
Q_OBJECT
|
||||
|
||||
public:
|
||||
VirtualOutput(QObject *parent = nullptr);
|
||||
VirtualOutput(VirtualBackend *parent = nullptr);
|
||||
~VirtualOutput() override;
|
||||
|
||||
RenderLoop *renderLoop() const override;
|
||||
|
@ -43,16 +43,20 @@ public:
|
|||
return m_gammaResult;
|
||||
}
|
||||
|
||||
void updateEnablement(bool enable) override;
|
||||
|
||||
private:
|
||||
void vblank(std::chrono::nanoseconds timestamp);
|
||||
|
||||
Q_DISABLE_COPY(VirtualOutput);
|
||||
friend class VirtualBackend;
|
||||
|
||||
VirtualBackend *m_backend;
|
||||
RenderLoop *m_renderLoop;
|
||||
SoftwareVsyncMonitor *m_vsyncMonitor;
|
||||
int m_gammaSize = 200;
|
||||
bool m_gammaResult = true;
|
||||
int m_identifier;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue