From c3f970b3c3a05e6f8571dfc3a5f890f3aa46041d Mon Sep 17 00:00:00 2001 From: Vlad Zahorodnii Date: Thu, 20 Oct 2022 12:15:47 +0300 Subject: [PATCH] wayland: Make XdgOutputV1Interface pull information from Output --- .../autotests/client/test_xdg_output.cpp | 34 ++--- src/wayland/tests/fakeoutput.cpp | 21 +++ src/wayland/tests/fakeoutput.h | 3 + src/wayland/xdgoutput_v1_interface.cpp | 120 +++++++----------- src/wayland/xdgoutput_v1_interface.h | 53 +------- src/waylandoutput.cpp | 21 --- src/waylandoutput.h | 3 - 7 files changed, 88 insertions(+), 167 deletions(-) diff --git a/src/wayland/autotests/client/test_xdg_output.cpp b/src/wayland/autotests/client/test_xdg_output.cpp index 228c770922..0a4ada1b4e 100644 --- a/src/wayland/autotests/client/test_xdg_output.cpp +++ b/src/wayland/autotests/client/test_xdg_output.cpp @@ -61,17 +61,16 @@ void TestXdgOutput::init() m_outputHandle = std::make_unique(); m_outputHandle->setMode(QSize(1920, 1080), 60000); + m_outputHandle->moveTo(QPoint(11, 12)); // not a sensible value for one monitor, but works for this test + m_outputHandle->setScale(1.5); + m_outputHandle->setName("testName"); + m_outputHandle->setManufacturer("foo"); + m_outputHandle->setModel("bar"); m_serverOutput = new OutputInterface(m_display, m_outputHandle.get(), this); m_serverXdgOutputManager = new XdgOutputManagerV1Interface(m_display, this); m_serverXdgOutput = m_serverXdgOutputManager->createXdgOutput(m_serverOutput, this); - m_serverXdgOutput->setLogicalSize(QSize(1280, 720)); // a 1.5 scale factor - m_serverXdgOutput->setLogicalPosition(QPoint(11, 12)); // not a sensible value for one monitor, but works for this test - m_serverXdgOutput->setName("testName"); - m_serverXdgOutput->setDescription("testDescription"); - - m_serverXdgOutput->done(); // setup connection m_connection = new KWayland::Client::ConnectionThread; @@ -150,20 +149,23 @@ void TestXdgOutput::testChanges() QCOMPARE(xdgOutput->logicalPosition(), QPoint(11, 12)); QCOMPARE(xdgOutput->logicalSize(), QSize(1280, 720)); QCOMPARE(xdgOutput->name(), "testName"); - QCOMPARE(xdgOutput->description(), "testDescription"); - - // dynamic updates - m_serverXdgOutput->setLogicalPosition(QPoint(1000, 2000)); - m_serverXdgOutput->setLogicalSize(QSize(100, 200)); - // names cannot dynamically change according to the spec - - m_serverXdgOutput->done(); - m_serverOutput->scheduleDone(); + QCOMPARE(xdgOutput->description(), "foo bar"); + // change the logical position + m_outputHandle->moveTo(QPoint(1000, 2000)); QVERIFY(xdgOutputChanged.wait()); QCOMPARE(xdgOutputChanged.count(), 1); QCOMPARE(xdgOutput->logicalPosition(), QPoint(1000, 2000)); - QCOMPARE(xdgOutput->logicalSize(), QSize(100, 200)); + QEXPECT_FAIL("", "KWayland::Client::XdgOutput incorrectly handles partial updates", Continue); + QCOMPARE(xdgOutput->logicalSize(), QSize(1280, 720)); + + // change the logical size + m_outputHandle->setScale(2); + QVERIFY(xdgOutputChanged.wait()); + QCOMPARE(xdgOutputChanged.count(), 2); + QEXPECT_FAIL("", "KWayland::Client::XdgOutput incorrectly handles partial updates", Continue); + QCOMPARE(xdgOutput->logicalPosition(), QPoint(1000, 2000)); + QCOMPARE(xdgOutput->logicalSize(), QSize(960, 540)); } QTEST_GUILESS_MAIN(TestXdgOutput) diff --git a/src/wayland/tests/fakeoutput.cpp b/src/wayland/tests/fakeoutput.cpp index 0d7feb3870..ca647268bd 100644 --- a/src/wayland/tests/fakeoutput.cpp +++ b/src/wayland/tests/fakeoutput.cpp @@ -69,3 +69,24 @@ void FakeOutput::setPhysicalSize(QSize size) .physicalSize = size, }); } + +void FakeOutput::setName(const QString &name) +{ + Information info = m_information; + info.name = name; + setInformation(info); +} + +void FakeOutput::setManufacturer(const QString &manufacturer) +{ + Information info = m_information; + info.manufacturer = manufacturer; + setInformation(info); +} + +void FakeOutput::setModel(const QString &model) +{ + Information info = m_information; + info.model = model; + setInformation(info); +} diff --git a/src/wayland/tests/fakeoutput.h b/src/wayland/tests/fakeoutput.h index 3ae080c1e6..2e0dac27d6 100644 --- a/src/wayland/tests/fakeoutput.h +++ b/src/wayland/tests/fakeoutput.h @@ -18,6 +18,9 @@ public: FakeOutput(); KWin::RenderLoop *renderLoop() const override; + void setName(const QString &name); + void setManufacturer(const QString &manufacturer); + void setModel(const QString &model); void setMode(QSize size, uint32_t refreshRate); void setSubPixel(SubPixel subPixel); void setDpmsSupported(bool supported); diff --git a/src/wayland/xdgoutput_v1_interface.cpp b/src/wayland/xdgoutput_v1_interface.cpp index 23e0eb2aa4..3436359da8 100644 --- a/src/wayland/xdgoutput_v1_interface.cpp +++ b/src/wayland/xdgoutput_v1_interface.cpp @@ -10,10 +10,14 @@ #include "qwayland-server-xdg-output-unstable-v1.h" +#include "core/output.h" + #include #include #include +using namespace KWin; + namespace KWaylandServer { static const quint32 s_version = 3; @@ -44,14 +48,11 @@ public: QSize size; QString name; QString description; - bool dirty = false; - bool doneOnce = false; QPointer output; XdgOutputV1Interface *const q; - void sendLogicalPosition(Resource *resource, const QPoint &position); - void sendLogicalSize(Resource *resource, const QSize &size); - + void sendLogicalPosition(Resource *resource); + void sendLogicalSize(Resource *resource); void sendDone(Resource *resource); protected: @@ -116,76 +117,50 @@ XdgOutputV1Interface::XdgOutputV1Interface(OutputInterface *output, QObject *par : QObject(parent) , d(new XdgOutputV1InterfacePrivate(this, output)) { + const Output *handle = output->handle(); + + d->name = handle->name(); + d->description = handle->description(); + d->pos = handle->geometry().topLeft(); + d->size = handle->geometry().size(); + + connect(handle, &Output::geometryChanged, this, &XdgOutputV1Interface::update); } XdgOutputV1Interface::~XdgOutputV1Interface() { } -void XdgOutputV1Interface::setLogicalSize(const QSize &size) +void XdgOutputV1Interface::update() { - if (size == d->size) { + if (!d->output || d->output->isRemoved()) { return; } - d->size = size; - d->dirty = true; - const auto outputResources = d->resourceMap(); - for (auto resource : outputResources) { - d->sendLogicalSize(resource, size); + const QRect geometry = d->output->handle()->geometry(); + const auto resources = d->resourceMap(); + + if (d->pos != geometry.topLeft()) { + d->pos = geometry.topLeft(); + for (auto resource : resources) { + d->sendLogicalPosition(resource); + } } -} -QSize XdgOutputV1Interface::logicalSize() const -{ - return d->size; -} - -void XdgOutputV1Interface::setLogicalPosition(const QPoint &pos) -{ - if (pos == d->pos) { - return; + if (d->size != geometry.size()) { + d->size = geometry.size(); + for (auto resource : resources) { + d->sendLogicalSize(resource); + } } - d->pos = pos; - d->dirty = true; - const auto outputResources = d->resourceMap(); - for (auto resource : outputResources) { - d->sendLogicalPosition(resource, pos); - } -} - -QPoint XdgOutputV1Interface::logicalPosition() const -{ - return d->pos; -} - -void XdgOutputV1Interface::setName(const QString &name) -{ - d->name = name; - // this can only be set once before the client connects -} - -void XdgOutputV1Interface::setDescription(const QString &description) -{ - d->description = description; - // this can only be set once before the client connects -} - -void XdgOutputV1Interface::done() -{ - d->doneOnce = true; - if (!d->dirty) { - return; - } - d->dirty = false; - - const auto outputResources = d->resourceMap(); - for (auto resource : outputResources) { + for (auto resource : resources) { if (wl_resource_get_version(resource->handle) < 3) { d->send_done(resource->handle); } } + + d->output->scheduleDone(); } void XdgOutputV1InterfacePrivate::zxdg_output_v1_destroy(Resource *resource) @@ -199,8 +174,8 @@ void XdgOutputV1InterfacePrivate::zxdg_output_v1_bind_resource(Resource *resourc return; } - sendLogicalPosition(resource, pos); - sendLogicalSize(resource, size); + sendLogicalPosition(resource); + sendLogicalSize(resource); if (resource->version() >= ZXDG_OUTPUT_V1_NAME_SINCE_VERSION) { send_name(resource->handle, name); } @@ -211,25 +186,19 @@ void XdgOutputV1InterfacePrivate::zxdg_output_v1_bind_resource(Resource *resourc sendDone(resource); ClientConnection *connection = output->display()->getConnection(resource->client()); - QObject::connect(connection, &ClientConnection::scaleOverrideChanged, q, &XdgOutputV1Interface::sendRefresh, Qt::UniqueConnection); + QObject::connect(connection, &ClientConnection::scaleOverrideChanged, q, &XdgOutputV1Interface::resend, Qt::UniqueConnection); } -void XdgOutputV1InterfacePrivate::sendLogicalSize(Resource *resource, const QSize &size) +void XdgOutputV1InterfacePrivate::sendLogicalSize(Resource *resource) { - if (!output || output->isRemoved()) { - return; - } ClientConnection *connection = output->display()->getConnection(resource->client()); qreal scaleOverride = connection->scaleOverride(); send_logical_size(resource->handle, size.width() * scaleOverride, size.height() * scaleOverride); } -void XdgOutputV1InterfacePrivate::sendLogicalPosition(Resource *resource, const QPoint &pos) +void XdgOutputV1InterfacePrivate::sendLogicalPosition(Resource *resource) { - if (!output || output->isRemoved()) { - return; - } ClientConnection *connection = output->display()->getConnection(resource->client()); qreal scaleOverride = connection->scaleOverride(); @@ -238,10 +207,6 @@ void XdgOutputV1InterfacePrivate::sendLogicalPosition(Resource *resource, const void XdgOutputV1InterfacePrivate::sendDone(Resource *resource) { - if (!doneOnce || !output || output->isRemoved()) { - return; - } - if (wl_resource_get_version(resource->handle) >= 3) { output->done(resource->client()); } else { @@ -249,16 +214,19 @@ void XdgOutputV1InterfacePrivate::sendDone(Resource *resource) } } -void XdgOutputV1Interface::sendRefresh() +void XdgOutputV1Interface::resend() { - auto changedConnection = qobject_cast(sender()); + if (!d->output || d->output->isRemoved()) { + return; + } + auto changedConnection = qobject_cast(sender()); const auto outputResources = d->resourceMap(); for (auto resource : outputResources) { ClientConnection *connection = d->output->display()->getConnection(resource->client()); if (connection == changedConnection) { - d->sendLogicalPosition(resource, d->pos); - d->sendLogicalSize(resource, d->size); + d->sendLogicalPosition(resource); + d->sendLogicalSize(resource); d->sendDone(resource); } } diff --git a/src/wayland/xdgoutput_v1_interface.h b/src/wayland/xdgoutput_v1_interface.h index e508e8266e..f0c44920fe 100644 --- a/src/wayland/xdgoutput_v1_interface.h +++ b/src/wayland/xdgoutput_v1_interface.h @@ -61,58 +61,9 @@ class KWIN_EXPORT XdgOutputV1Interface : public QObject public: ~XdgOutputV1Interface() override; - /** - * Sets the size of this output in logical co-ordinates. - * Users should call done() after setting all values - */ - void setLogicalSize(const QSize &size); - - /** - * Returns the last set logical size on this output - */ - QSize logicalSize() const; - - /** - * Sets the topleft position of this output in logical co-ordinates. - * Users should call done() after setting all values - * @see OutputInterface::setPosition - */ - void setLogicalPosition(const QPoint &pos); - - /** - * Returns the last set logical position on this output - */ - QPoint logicalPosition() const; - - /** - * @brief Sets a short name of the output - * This should be consistent across reboots for the same monitor - * It should be set once before the first done call - */ - void setName(const QString &name); - /** - * The last set name - */ - void name() const; - - /** - * @brief Sets a longer description of the output - * This should be consistent across reboots for the same monitor - * It should be set once before the first done call - */ - void setDescription(const QString &description); - /** - * The last set description - */ - void description() const; - - /** - * Submit changes to all clients - */ - void done(); - private: - void sendRefresh(); + void resend(); + void update(); explicit XdgOutputV1Interface(OutputInterface *output, QObject *parent); friend class XdgOutputV1InterfacePrivate; diff --git a/src/waylandoutput.cpp b/src/waylandoutput.cpp index 01773f4d7d..74e0bf537a 100644 --- a/src/waylandoutput.cpp +++ b/src/waylandoutput.cpp @@ -18,27 +18,6 @@ WaylandOutput::WaylandOutput(Output *output, QObject *parent) , m_waylandOutput(new KWaylandServer::OutputInterface(waylandServer()->display(), output)) , m_xdgOutputV1(waylandServer()->xdgOutputManagerV1()->createXdgOutput(m_waylandOutput.get(), m_waylandOutput.get())) { - const QRect geometry = m_platformOutput->geometry(); - m_xdgOutputV1->setName(output->name()); - m_xdgOutputV1->setDescription(output->description()); - m_xdgOutputV1->setLogicalPosition(geometry.topLeft()); - m_xdgOutputV1->setLogicalSize(geometry.size()); - - m_xdgOutputV1->done(); - m_waylandOutput->scheduleDone(); - - connect(output, &Output::geometryChanged, this, &WaylandOutput::update); -} - -void WaylandOutput::update() -{ - const QRect geometry = m_platformOutput->geometry(); - - m_xdgOutputV1->setLogicalPosition(geometry.topLeft()); - m_xdgOutputV1->setLogicalSize(geometry.size()); - - m_xdgOutputV1->done(); - m_waylandOutput->scheduleDone(); } } // namespace KWin diff --git a/src/waylandoutput.h b/src/waylandoutput.h index a3ca7e83f1..e4edae313f 100644 --- a/src/waylandoutput.h +++ b/src/waylandoutput.h @@ -21,9 +21,6 @@ class WaylandOutput : public QObject public: explicit WaylandOutput(Output *output, QObject *parent = nullptr); -private Q_SLOTS: - void update(); - private: Output *m_platformOutput; KWaylandServer::ScopedGlobalPointer m_waylandOutput;