wayland: Make OutputInterface pull information from Output

It's a necessary step towards killing src/waylandoutput.{h,cpp}. Besides
that, it makes OutputInterface more reusable and less error prone.
master
Vlad Zahorodnii 2 years ago
parent 7734676aa1
commit 146bed14bc

@ -40,8 +40,6 @@ private Q_SLOTS:
private:
KWaylandServer::Display *m_display;
std::unique_ptr<FakeOutput> m_outputHandle;
std::unique_ptr<KWaylandServer::OutputInterface> m_outputInterface;
KWayland::Client::ConnectionThread *m_connection;
KWayland::Client::EventQueue *m_queue;
QThread *m_thread;
@ -66,12 +64,6 @@ void TestWaylandOutput::init()
m_display->start();
QVERIFY(m_display->isRunning());
m_outputHandle = std::make_unique<FakeOutput>();
m_outputHandle->setMode(QSize(1024, 768), 60000);
m_outputInterface = std::make_unique<OutputInterface>(m_display, m_outputHandle.get());
m_outputInterface->setMode(QSize(1024, 768), 60000);
// setup connection
m_connection = new KWayland::Client::ConnectionThread;
QSignalSpy connectedSpy(m_connection, &KWayland::Client::ConnectionThread::connected);
@ -107,35 +99,16 @@ void TestWaylandOutput::cleanup()
delete m_display;
m_display = nullptr;
m_outputInterface.reset();
m_outputHandle.reset();
}
void TestWaylandOutput::testRegistry()
{
QSignalSpy globalPositionChangedSpy(m_outputInterface.get(), &KWaylandServer::OutputInterface::globalPositionChanged);
QCOMPARE(m_outputInterface->globalPosition(), QPoint(0, 0));
m_outputHandle->moveTo(QPoint(100, 50));
m_outputInterface->setGlobalPosition(QPoint(100, 50));
QCOMPARE(m_outputInterface->globalPosition(), QPoint(100, 50));
QCOMPARE(globalPositionChangedSpy.count(), 1);
// changing again should not trigger signal
m_outputHandle->moveTo(QPoint(100, 50));
m_outputInterface->setGlobalPosition(QPoint(100, 50));
QCOMPARE(globalPositionChangedSpy.count(), 1);
QSignalSpy physicalSizeChangedSpy(m_outputInterface.get(), &KWaylandServer::OutputInterface::physicalSizeChanged);
QCOMPARE(m_outputInterface->physicalSize(), QSize());
m_outputHandle->setPhysicalSize(QSize(200, 100));
m_outputInterface->setPhysicalSize(QSize(200, 100));
QCOMPARE(m_outputInterface->physicalSize(), QSize(200, 100));
QCOMPARE(physicalSizeChangedSpy.count(), 1);
// changing again should not trigger signal
m_outputHandle->setPhysicalSize(QSize(200, 100));
m_outputInterface->setPhysicalSize(QSize(200, 100));
QCOMPARE(physicalSizeChangedSpy.count(), 1);
m_outputInterface->done();
auto outputHandle = std::make_unique<FakeOutput>();
outputHandle->setMode(QSize(1024, 768), 60000);
outputHandle->moveTo(QPoint(100, 50));
outputHandle->setPhysicalSize(QSize(200, 100));
auto outputInterface = std::make_unique<KWaylandServer::OutputInterface>(m_display, outputHandle.get());
KWayland::Client::Registry registry;
QSignalSpy announced(&registry, &KWayland::Client::Registry::outputAnnounced);
@ -168,8 +141,8 @@ void TestWaylandOutput::testRegistry()
QCOMPARE(output.geometry(), QRect(100, 50, 1024, 768));
QCOMPARE(output.globalPosition(), QPoint(100, 50));
QCOMPARE(output.manufacturer(), QStringLiteral("org.kde.kwin"));
QCOMPARE(output.model(), QStringLiteral("none"));
QCOMPARE(output.manufacturer(), QString());
QCOMPARE(output.model(), QString());
QCOMPARE(output.physicalSize(), QSize(200, 100));
QCOMPARE(output.pixelSize(), QSize(1024, 768));
QCOMPARE(output.refreshRate(), 60000);
@ -182,6 +155,11 @@ void TestWaylandOutput::testRegistry()
void TestWaylandOutput::testModeChange()
{
auto outputHandle = std::make_unique<FakeOutput>();
outputHandle->setMode(QSize(1024, 768), 60000);
auto outputInterface = std::make_unique<KWaylandServer::OutputInterface>(m_display, outputHandle.get());
using namespace KWayland::Client;
KWayland::Client::Registry registry;
QSignalSpy announced(&registry, &KWayland::Client::Registry::outputAnnounced);
@ -207,10 +185,7 @@ void TestWaylandOutput::testModeChange()
QCOMPARE(output.refreshRate(), 60000);
// change once more
m_outputHandle->setMode(QSize(1280, 1024), 90000);
m_outputInterface->setMode(QSize(1280, 1024), 90000);
QCOMPARE(m_outputInterface->refreshRate(), 90000);
m_outputInterface->done();
outputHandle->setMode(QSize(1280, 1024), 90000);
QVERIFY(outputChanged.wait());
QCOMPARE(modeAddedSpy.count(), 2);
QCOMPARE(modeAddedSpy.at(1).first().value<Output::Mode>().size, QSize(1280, 1024));
@ -223,6 +198,11 @@ void TestWaylandOutput::testModeChange()
void TestWaylandOutput::testScaleChange()
{
auto outputHandle = std::make_unique<FakeOutput>();
outputHandle->setMode(QSize(1024, 768), 60000);
auto outputInterface = std::make_unique<KWaylandServer::OutputInterface>(m_display, outputHandle.get());
KWayland::Client::Registry registry;
QSignalSpy announced(&registry, &KWayland::Client::Registry::outputAnnounced);
registry.create(m_connection->display());
@ -240,26 +220,16 @@ void TestWaylandOutput::testScaleChange()
// change the scale
outputChanged.clear();
QCOMPARE(m_outputInterface->scale(), 1);
QSignalSpy serverScaleChanged(m_outputInterface.get(), &KWaylandServer::OutputInterface::scaleChanged);
m_outputHandle->setScale(2);
m_outputInterface->setScale(2);
QCOMPARE(m_outputInterface->scale(), 2);
m_outputInterface->done();
QCOMPARE(serverScaleChanged.count(), 1);
outputHandle->setScale(2);
QVERIFY(outputChanged.wait());
QCOMPARE(output.scale(), 2);
// changing to same value should not trigger
m_outputHandle->setScale(2);
m_outputInterface->setScale(2);
QCOMPARE(serverScaleChanged.count(), 1);
outputHandle->setScale(2);
QVERIFY(!outputChanged.wait(100));
// change once more
outputChanged.clear();
m_outputHandle->setScale(4);
m_outputInterface->setScale(4);
m_outputInterface->done();
outputHandle->setScale(4);
QVERIFY(outputChanged.wait());
QCOMPARE(output.scale(), 4);
}
@ -280,19 +250,16 @@ void TestWaylandOutput::testSubPixel_data()
void TestWaylandOutput::testSubPixel()
{
QFETCH(KWin::Output::SubPixel, actual);
auto outputHandle = std::make_unique<FakeOutput>();
outputHandle->setMode(QSize(1024, 768), 60000);
outputHandle->setSubPixel(actual);
auto outputInterface = std::make_unique<KWaylandServer::OutputInterface>(m_display, outputHandle.get());
using namespace KWayland::Client;
using namespace KWaylandServer;
QFETCH(KWin::Output::SubPixel, actual);
QCOMPARE(m_outputInterface->subPixel(), KWin::Output::SubPixel::Unknown);
QSignalSpy serverSubPixelChangedSpy(m_outputInterface.get(), &KWaylandServer::OutputInterface::subPixelChanged);
m_outputHandle->setSubPixel(actual);
m_outputInterface->setSubPixel(actual);
QCOMPARE(m_outputInterface->subPixel(), actual);
QCOMPARE(serverSubPixelChangedSpy.count(), 1);
// changing to same value should not trigger the signal
m_outputHandle->setSubPixel(actual);
m_outputInterface->setSubPixel(actual);
QCOMPARE(serverSubPixelChangedSpy.count(), 1);
KWayland::Client::Registry registry;
QSignalSpy announced(&registry, &KWayland::Client::Registry::outputAnnounced);
@ -314,11 +281,7 @@ void TestWaylandOutput::testSubPixel()
// change back to unknown
outputChanged.clear();
m_outputHandle->setSubPixel(KWin::Output::SubPixel::Unknown);
m_outputInterface->setSubPixel(KWin::Output::SubPixel::Unknown);
QCOMPARE(m_outputInterface->subPixel(), KWin::Output::SubPixel::Unknown);
m_outputInterface->done();
QCOMPARE(serverSubPixelChangedSpy.count(), 2);
outputHandle->setSubPixel(KWin::Output::SubPixel::Unknown);
if (outputChanged.isEmpty()) {
QVERIFY(outputChanged.wait());
}
@ -343,19 +306,16 @@ void TestWaylandOutput::testTransform_data()
void TestWaylandOutput::testTransform()
{
QFETCH(KWin::Output::Transform, actual);
auto outputHandle = std::make_unique<FakeOutput>();
outputHandle->setMode(QSize(1024, 768), 60000);
outputHandle->setTransform(actual);
auto outputInterface = std::make_unique<KWaylandServer::OutputInterface>(m_display, outputHandle.get());
using namespace KWayland::Client;
using namespace KWaylandServer;
QFETCH(KWin::Output::Transform, actual);
QCOMPARE(m_outputInterface->transform(), KWin::Output::Transform::Normal);
QSignalSpy serverTransformChangedSpy(m_outputInterface.get(), &KWaylandServer::OutputInterface::transformChanged);
m_outputHandle->setTransform(actual);
m_outputInterface->setTransform(actual);
QCOMPARE(m_outputInterface->transform(), actual);
QCOMPARE(serverTransformChangedSpy.count(), 1);
// changing to same should not trigger signal
m_outputHandle->setTransform(actual);
m_outputInterface->setTransform(actual);
QCOMPARE(serverTransformChangedSpy.count(), 1);
KWayland::Client::Registry registry;
QSignalSpy announced(&registry, &KWayland::Client::Registry::outputAnnounced);
@ -376,11 +336,7 @@ void TestWaylandOutput::testTransform()
// change back to normal
outputChanged.clear();
m_outputHandle->setTransform(KWin::Output::Transform::Normal);
m_outputInterface->setTransform(KWin::Output::Transform::Normal);
QCOMPARE(m_outputInterface->transform(), KWin::Output::Transform::Normal);
m_outputInterface->done();
QCOMPARE(serverTransformChangedSpy.count(), 2);
outputHandle->setTransform(KWin::Output::Transform::Normal);
if (outputChanged.isEmpty()) {
QVERIFY(outputChanged.wait());
}

@ -63,7 +63,6 @@ void TestXdgOutput::init()
m_outputHandle->setMode(QSize(1920, 1080), 60000);
m_serverOutput = new OutputInterface(m_display, m_outputHandle.get(), this);
m_serverOutput->setMode(QSize(1920, 1080));
m_serverXdgOutputManager = new XdgOutputManagerV1Interface(m_display, this);
m_serverXdgOutput = m_serverXdgOutputManager->createXdgOutput(m_serverOutput, this);
@ -159,7 +158,7 @@ void TestXdgOutput::testChanges()
// names cannot dynamically change according to the spec
m_serverXdgOutput->done();
m_serverOutput->done();
m_serverOutput->scheduleDone();
QVERIFY(xdgOutputChanged.wait());
QCOMPARE(xdgOutputChanged.count(), 1);

@ -99,11 +99,9 @@ void XdgShellTest::init()
m_output1Handle = std::make_unique<FakeOutput>();
m_output1Handle->setMode(QSize(1024, 768), 60000);
m_output1Interface = new OutputInterface(m_display, m_output1Handle.get(), m_display);
m_output1Interface->setMode(QSize(1024, 768));
m_output2Handle = std::make_unique<FakeOutput>();
m_output2Handle->setMode(QSize(1024, 768), 60000);
m_output2Interface = new OutputInterface(m_display, m_output2Handle.get(), m_display);
m_output2Interface->setMode(QSize(1024, 768));
m_seatInterface = new SeatInterface(m_display, m_display);
m_seatInterface->setHasKeyboard(true);
m_seatInterface->setHasPointer(true);

@ -14,6 +14,7 @@
#include "qwayland-server-wayland.h"
#include <QPointer>
#include <QTimer>
#include <QVector>
namespace KWaylandServer
@ -30,21 +31,21 @@ public:
void sendMode(Resource *resource);
void sendDone(Resource *resource);
void broadcastGeometry();
OutputInterface *q;
QPointer<Display> display;
QPointer<KWin::Output> handle;
QSize physicalSize;
QPoint globalPosition;
QString manufacturer = QStringLiteral("org.kde.kwin");
QString model = QStringLiteral("none");
QString manufacturer;
QString model;
int scale = 1;
KWin::Output::SubPixel subPixel = KWin::Output::SubPixel::Unknown;
KWin::Output::Transform transform = KWin::Output::Transform::Normal;
OutputInterface::Mode mode;
QSize modeSize;
int refreshRate = 0;
QString name;
QString description;
QTimer doneTimer;
private:
void output_destroy_global() override;
@ -62,7 +63,7 @@ OutputInterfacePrivate::OutputInterfacePrivate(Display *display, OutputInterface
void OutputInterfacePrivate::sendMode(Resource *resource)
{
send_mode(resource->handle, mode_current, mode.size.width(), mode.size.height(), mode.refreshRate);
send_mode(resource->handle, mode_current, modeSize.width(), modeSize.height(), refreshRate);
}
void OutputInterfacePrivate::sendScale(Resource *resource)
@ -136,14 +137,6 @@ void OutputInterfacePrivate::sendDone(Resource *resource)
}
}
void OutputInterfacePrivate::broadcastGeometry()
{
const auto outputResources = resourceMap();
for (Resource *resource : outputResources) {
sendGeometry(resource);
}
}
void OutputInterfacePrivate::output_destroy_global()
{
delete q;
@ -181,6 +174,78 @@ OutputInterface::OutputInterface(Display *display, KWin::Output *handle, QObject
{
DisplayPrivate *displayPrivate = DisplayPrivate::get(display);
displayPrivate->outputs.append(this);
// Delay the done event to batch property updates.
d->doneTimer.setSingleShot(true);
d->doneTimer.setInterval(0);
connect(&d->doneTimer, &QTimer::timeout, this, [this]() {
const auto resources = d->resourceMap();
for (const auto &resource : resources) {
d->sendDone(resource);
}
});
d->name = handle->name();
d->description = handle->description();
d->transform = handle->transform();
d->manufacturer = handle->manufacturer();
d->model = handle->model();
d->physicalSize = handle->physicalSize();
d->globalPosition = handle->geometry().topLeft();
d->scale = std::ceil(handle->scale());
d->modeSize = handle->modeSize();
d->refreshRate = handle->refreshRate();
d->subPixel = handle->subPixel();
connect(handle, &KWin::Output::geometryChanged, this, [this]() {
const QPoint position = d->handle->geometry().topLeft();
if (d->globalPosition != position) {
d->globalPosition = position;
const auto resources = d->resourceMap();
for (const auto &resource : resources) {
d->sendGeometry(resource);
}
scheduleDone();
}
});
connect(handle, &KWin::Output::scaleChanged, this, [this]() {
const int scale = std::ceil(d->handle->scale());
if (d->scale != scale) {
d->scale = scale;
const auto resources = d->resourceMap();
for (const auto &resource : resources) {
d->sendScale(resource);
}
scheduleDone();
}
});
connect(handle, &KWin::Output::transformChanged, this, [this]() {
const KWin::Output::Transform transform = d->handle->transform();
if (d->transform != transform) {
d->transform = transform;
const auto resources = d->resourceMap();
for (const auto &resource : resources) {
d->sendGeometry(resource);
}
scheduleDone();
}
});
connect(handle, &KWin::Output::currentModeChanged, this, [this]() {
const QSize size = d->handle->modeSize();
const int refreshRate = d->handle->refreshRate();
if (d->modeSize != size || d->refreshRate != refreshRate) {
d->modeSize = size;
d->refreshRate = refreshRate;
const auto resources = d->resourceMap();
for (const auto &resource : resources) {
d->sendMode(resource);
}
scheduleDone();
}
});
}
OutputInterface::~OutputInterface()
@ -188,6 +253,11 @@ OutputInterface::~OutputInterface()
remove();
}
Display *OutputInterface::display() const
{
return d->display;
}
KWin::Output *OutputInterface::handle() const
{
return d->handle;
@ -213,163 +283,6 @@ void OutputInterface::remove()
d->globalRemove();
}
QSize OutputInterface::pixelSize() const
{
return d->mode.size;
}
int OutputInterface::refreshRate() const
{
return d->mode.refreshRate;
}
OutputInterface::Mode OutputInterface::mode() const
{
return d->mode;
}
void OutputInterface::setMode(const Mode &mode)
{
if (d->mode.size == mode.size && d->mode.refreshRate == mode.refreshRate) {
return;
}
d->mode = mode;
const auto outputResources = d->resourceMap();
for (OutputInterfacePrivate::Resource *resource : outputResources) {
d->sendMode(resource);
}
Q_EMIT modeChanged();
Q_EMIT refreshRateChanged(mode.refreshRate);
Q_EMIT pixelSizeChanged(mode.size);
}
void OutputInterface::setMode(const QSize &size, int refreshRate)
{
setMode({size, refreshRate});
}
void OutputInterface::setName(const QString &name)
{
d->name = name;
}
void OutputInterface::setDescription(const QString &description)
{
d->description = description;
}
QSize OutputInterface::physicalSize() const
{
return d->physicalSize;
}
void OutputInterface::setPhysicalSize(const QSize &physicalSize)
{
if (d->physicalSize == physicalSize) {
return;
}
d->physicalSize = physicalSize;
d->broadcastGeometry();
Q_EMIT physicalSizeChanged(d->physicalSize);
}
QPoint OutputInterface::globalPosition() const
{
return d->globalPosition;
}
void OutputInterface::setGlobalPosition(const QPoint &globalPos)
{
if (d->globalPosition == globalPos) {
return;
}
d->globalPosition = globalPos;
Q_EMIT globalPositionChanged(d->globalPosition);
}
QString OutputInterface::manufacturer() const
{
return d->manufacturer;
}
void OutputInterface::setManufacturer(const QString &manufacturer)
{
if (d->manufacturer == manufacturer) {
return;
}
d->manufacturer = manufacturer;
d->broadcastGeometry();
Q_EMIT manufacturerChanged(d->manufacturer);
}
QString OutputInterface::model() const
{
return d->model;
}
void OutputInterface::setModel(const QString &model)
{
if (d->model == model) {
return;
}
d->model = model;
d->broadcastGeometry();
Q_EMIT modelChanged(d->model);
}
int OutputInterface::scale() const
{
return d->scale;
}
void OutputInterface::setScale(int scale)
{
if (d->scale == scale) {
return;
}
d->scale = scale;
const auto outputResources = d->resourceMap();
for (OutputInterfacePrivate::Resource *resource : outputResources) {
d->sendScale(resource);
}
Q_EMIT scaleChanged(d->scale);
}
KWin::Output::SubPixel OutputInterface::subPixel() const
{
return d->subPixel;
}
void OutputInterface::setSubPixel(KWin::Output::SubPixel subPixel)
{
if (d->subPixel == subPixel) {
return;
}
d->subPixel = subPixel;
d->broadcastGeometry();
Q_EMIT subPixelChanged(d->subPixel);
}
KWin::Output::Transform OutputInterface::transform() const
{
return d->transform;
}
void OutputInterface::setTransform(KWin::Output::Transform transform)
{
if (d->transform == transform) {
return;
}
d->transform = transform;
d->broadcastGeometry();
Q_EMIT transformChanged(d->transform);
}
QVector<wl_resource *> OutputInterface::clientResources(ClientConnection *client) const
{
const auto outputResources = d->resourceMap().values(client->client());
@ -383,12 +296,9 @@ QVector<wl_resource *> OutputInterface::clientResources(ClientConnection *client
return ret;
}
void OutputInterface::done()
void OutputInterface::scheduleDone()
{
const auto outputResources = d->resourceMap();
for (OutputInterfacePrivate::Resource *resource : outputResources) {
d->sendDone(resource);
}
d->doneTimer.start();
}
void OutputInterface::done(wl_client *client)
@ -404,9 +314,4 @@ OutputInterface *OutputInterface::get(wl_resource *native)
return nullptr;
}
Display *OutputInterface::display() const
{
return d->display;
}
} // namespace KWaylandServer

@ -34,20 +34,8 @@ class OutputInterfacePrivate;
class KWIN_EXPORT OutputInterface : public QObject
{
Q_OBJECT
Q_PROPERTY(QSize physicalSize READ physicalSize WRITE setPhysicalSize NOTIFY physicalSizeChanged)
Q_PROPERTY(QPoint globalPosition READ globalPosition WRITE setGlobalPosition NOTIFY globalPositionChanged)
Q_PROPERTY(QString manufacturer READ manufacturer WRITE setManufacturer NOTIFY manufacturerChanged)
Q_PROPERTY(QString model READ model WRITE setModel NOTIFY modelChanged)
Q_PROPERTY(QSize pixelSize READ pixelSize NOTIFY pixelSizeChanged)
Q_PROPERTY(int refreshRate READ refreshRate NOTIFY refreshRateChanged)
Q_PROPERTY(int scale READ scale WRITE setScale NOTIFY scaleChanged)
public:
struct Mode
{
QSize size = QSize();
int refreshRate = 60000;
};
public:
explicit OutputInterface(Display *display, KWin::Output *handle, QObject *parent = nullptr);
~OutputInterface() override;
@ -56,29 +44,6 @@ public:
KWin::Output *handle() const;
QSize physicalSize() const;
QPoint globalPosition() const;
QString manufacturer() const;
QString model() const;
QSize pixelSize() const;
int refreshRate() const;
int scale() const;
KWin::Output::SubPixel subPixel() const;
KWin::Output::Transform transform() const;
Mode mode() const;
void setPhysicalSize(const QSize &size);
void setGlobalPosition(const QPoint &pos);
void setManufacturer(const QString &manufacturer);
void setModel(const QString &model);
void setScale(int scale);
void setSubPixel(KWin::Output::SubPixel subPixel);
void setTransform(KWin::Output::Transform transform);
void setMode(const Mode &mode);
void setMode(const QSize &size, int refreshRate = 60000);
void setName(const QString &name);
void setDescription(const QString &description);
/**
* @returns all wl_resources bound for the @p client
*/
@ -87,7 +52,7 @@ public:
/**
* Submit changes to all clients.
*/
void done();
void scheduleDone();
/**
* Submit changes to @p client.
@ -99,16 +64,6 @@ public:
Display *display() const;
Q_SIGNALS:
void physicalSizeChanged(const QSize &);
void globalPositionChanged(const QPoint &);
void manufacturerChanged(const QString &);
void modelChanged(const QString &);
void pixelSizeChanged(const QSize &);
void refreshRateChanged(int);
void scaleChanged(int);
void subPixelChanged(KWin::Output::SubPixel);
void transformChanged(KWin::Output::Transform);
void modeChanged();
void removed();
/**

@ -251,9 +251,7 @@ int main(int argc, char **argv)
outputHandle->setPhysicalSize(QSize(269, 202));
outputHandle->setMode(windowSize, 60000);
OutputInterface *outputInterface = new OutputInterface(&display, outputHandle.get(), &display);
outputInterface->setPhysicalSize(QSize(269, 202));
outputInterface->setMode(windowSize);
auto outputInterface = std::make_unique<OutputInterface>(&display, outputHandle.get());
SeatInterface *seat = new SeatInterface(&display);
seat->setHasKeyboard(true);

@ -82,9 +82,7 @@ int main(int argc, char **argv)
outputHandle->setMode(QSize(1024, 768), 60000);
outputHandle->setPhysicalSize(QSize(10, 10));
OutputInterface *outputInterface = new OutputInterface(&display, outputHandle.get(), &display);
outputInterface->setPhysicalSize(QSize(10, 10));
outputInterface->setMode(QSize(1024, 768));
auto outputInterface = std::make_unique<OutputInterface>(&display, outputHandle.get());
// starts XWayland by forking and opening a pipe
const int pipe = startXServer();

@ -19,55 +19,26 @@ WaylandOutput::WaylandOutput(Output *output, QObject *parent)
, m_xdgOutputV1(waylandServer()->xdgOutputManagerV1()->createXdgOutput(m_waylandOutput.get(), m_waylandOutput.get()))
{
const QRect geometry = m_platformOutput->geometry();
m_waylandOutput->setName(output->name());
m_waylandOutput->setDescription(output->description());
m_waylandOutput->setTransform(output->transform());
m_waylandOutput->setManufacturer(output->manufacturer());
m_waylandOutput->setModel(output->model());
m_waylandOutput->setPhysicalSize(output->physicalSize());
m_waylandOutput->setGlobalPosition(geometry.topLeft());
m_waylandOutput->setScale(std::ceil(output->scale()));
m_waylandOutput->setMode(output->modeSize(), output->refreshRate());
m_waylandOutput->setSubPixel(output->subPixel());
m_xdgOutputV1->setName(output->name());
m_xdgOutputV1->setDescription(output->description());
m_xdgOutputV1->setLogicalPosition(geometry.topLeft());
m_xdgOutputV1->setLogicalSize(geometry.size());
m_waylandOutput->done();
m_xdgOutputV1->done();
m_waylandOutput->scheduleDone();
// The timer is used to compress output updates so the wayland clients are not spammed.
m_updateTimer.setSingleShot(true);
connect(&m_updateTimer, &QTimer::timeout, this, &WaylandOutput::update);
connect(output, &Output::currentModeChanged, this, &WaylandOutput::scheduleUpdate);
connect(output, &Output::geometryChanged, this, &WaylandOutput::scheduleUpdate);
connect(output, &Output::transformChanged, this, &WaylandOutput::scheduleUpdate);
connect(output, &Output::scaleChanged, this, &WaylandOutput::scheduleUpdate);
}
void WaylandOutput::scheduleUpdate()
{
m_updateTimer.start();
connect(output, &Output::geometryChanged, this, &WaylandOutput::update);
}
void WaylandOutput::update()
{
const QRect geometry = m_platformOutput->geometry();
m_waylandOutput->setGlobalPosition(geometry.topLeft());
m_waylandOutput->setScale(std::ceil(m_platformOutput->scale()));
m_waylandOutput->setTransform(m_platformOutput->transform());
m_waylandOutput->setMode(m_platformOutput->modeSize(), m_platformOutput->refreshRate());
m_xdgOutputV1->setLogicalPosition(geometry.topLeft());
m_xdgOutputV1->setLogicalSize(geometry.size());
m_waylandOutput->done();
m_xdgOutputV1->done();
m_waylandOutput->scheduleDone();
}
} // namespace KWin

@ -11,8 +11,6 @@
#include "wayland/utils.h"
#include "wayland/xdgoutput_v1_interface.h"
#include <QTimer>
namespace KWin
{
@ -25,11 +23,9 @@ public:
private Q_SLOTS:
void update();
void scheduleUpdate();
private:
Output *m_platformOutput;
QTimer m_updateTimer;
KWaylandServer::ScopedGlobalPointer<KWaylandServer::OutputInterface> m_waylandOutput;
KWaylandServer::XdgOutputV1Interface *m_xdgOutputV1;
};

Loading…
Cancel
Save