From 0c34957625e5f2deab4580f0d70efa3a3c478335 Mon Sep 17 00:00:00 2001 From: Vlad Zahorodnii Date: Thu, 27 Oct 2022 13:37:46 +0300 Subject: [PATCH] wayland: Hide XdgOutputV1Interface class With the pull approach, the XdgOutputV1Interface class doesn't have to be exposed in the public api and can be made private to simplify the implementation of the xdg-output-v1 protocol. --- .../autotests/client/test_xdg_output.cpp | 3 +- src/wayland/xdgoutput_v1_interface.cpp | 129 ++++++++---------- src/wayland/xdgoutput_v1_interface.h | 42 +----- src/wayland_server.cpp | 2 +- 4 files changed, 61 insertions(+), 115 deletions(-) diff --git a/src/wayland/autotests/client/test_xdg_output.cpp b/src/wayland/autotests/client/test_xdg_output.cpp index 0a4ada1b4e..d66100589d 100644 --- a/src/wayland/autotests/client/test_xdg_output.cpp +++ b/src/wayland/autotests/client/test_xdg_output.cpp @@ -33,7 +33,6 @@ private: std::unique_ptr m_outputHandle; KWaylandServer::OutputInterface *m_serverOutput; KWaylandServer::XdgOutputManagerV1Interface *m_serverXdgOutputManager; - KWaylandServer::XdgOutputV1Interface *m_serverXdgOutput; KWayland::Client::ConnectionThread *m_connection; KWayland::Client::EventQueue *m_queue; QThread *m_thread; @@ -70,7 +69,7 @@ void TestXdgOutput::init() 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_serverXdgOutputManager->offer(m_serverOutput); // setup connection m_connection = new KWayland::Client::ConnectionThread; diff --git a/src/wayland/xdgoutput_v1_interface.cpp b/src/wayland/xdgoutput_v1_interface.cpp index 65ed5cc417..e4143659fa 100644 --- a/src/wayland/xdgoutput_v1_interface.cpp +++ b/src/wayland/xdgoutput_v1_interface.cpp @@ -22,6 +22,29 @@ namespace KWaylandServer { static const quint32 s_version = 3; +class XdgOutputV1Interface : public QObject, public QtWaylandServer::zxdg_output_v1 +{ +public: + explicit XdgOutputV1Interface(OutputInterface *wlOutput); + + void resend(); + void update(); + + QPointF pos; + QSizeF size; + QString name; + QString description; + QPointer output; + + void sendLogicalPosition(Resource *resource); + void sendLogicalSize(Resource *resource); + void sendDone(Resource *resource); + +protected: + void zxdg_output_v1_bind_resource(Resource *resource) override; + void zxdg_output_v1_destroy(Resource *resource) override; +}; + class XdgOutputManagerV1InterfacePrivate : public QtWaylandServer::zxdg_output_manager_v1 { public: @@ -35,31 +58,6 @@ protected: void zxdg_output_manager_v1_get_xdg_output(Resource *resource, uint32_t id, wl_resource *output) override; }; -class XdgOutputV1InterfacePrivate : public QtWaylandServer::zxdg_output_v1 -{ -public: - XdgOutputV1InterfacePrivate(XdgOutputV1Interface *q, OutputInterface *wlOutput) - : output(wlOutput) - , q(q) - { - } - - QPointF pos; - QSizeF size; - QString name; - QString description; - QPointer output; - XdgOutputV1Interface *const q; - - void sendLogicalPosition(Resource *resource); - void sendLogicalSize(Resource *resource); - void sendDone(Resource *resource); - -protected: - void zxdg_output_v1_bind_resource(Resource *resource) override; - void zxdg_output_v1_destroy(Resource *resource) override; -}; - XdgOutputManagerV1Interface::XdgOutputManagerV1Interface(Display *display, QObject *parent) : QObject(parent) , d(new XdgOutputManagerV1InterfacePrivate(this, display)) @@ -70,23 +68,15 @@ XdgOutputManagerV1Interface::~XdgOutputManagerV1Interface() { } -XdgOutputV1Interface *XdgOutputManagerV1Interface::createXdgOutput(OutputInterface *output, QObject *parent) +void XdgOutputManagerV1Interface::offer(OutputInterface *output) { - Q_ASSERT_X(!d->outputs.contains(output), "createXdgOutput", "An XdgOuputInterface already exists for this output"); + Q_ASSERT_X(!d->outputs.contains(output), "offer", "An XdgOuputInterface already exists for this output"); - auto xdgOutput = new XdgOutputV1Interface(output, parent); + auto xdgOutput = new XdgOutputV1Interface(output); d->outputs[output] = xdgOutput; - - // as XdgOutput lifespan is managed by user, delete our mapping when either - // it or the relevant Output gets deleted connect(output, &QObject::destroyed, this, [this, output]() { - d->outputs.remove(output); + delete d->outputs.take(output); }); - connect(xdgOutput, &QObject::destroyed, this, [this, output]() { - d->outputs.remove(output); - }); - - return xdgOutput; } XdgOutputManagerV1InterfacePrivate::XdgOutputManagerV1InterfacePrivate(XdgOutputManagerV1Interface *qptr, Display *d) @@ -105,7 +95,7 @@ void XdgOutputManagerV1InterfacePrivate::zxdg_output_manager_v1_get_xdg_output(R if (!xdgOutput) { return; // client is requesting XdgOutput for an Output that doesn't exist } - xdgOutput->d->add(resource->client(), id, resource->version()); + xdgOutput->add(resource->client(), id, resource->version()); } void XdgOutputManagerV1InterfacePrivate::zxdg_output_manager_v1_destroy(Resource *resource) @@ -113,62 +103,57 @@ void XdgOutputManagerV1InterfacePrivate::zxdg_output_manager_v1_destroy(Resource wl_resource_destroy(resource->handle); } -XdgOutputV1Interface::XdgOutputV1Interface(OutputInterface *output, QObject *parent) - : QObject(parent) - , d(new XdgOutputV1InterfacePrivate(this, output)) +XdgOutputV1Interface::XdgOutputV1Interface(OutputInterface *output) + : output(output) { const Output *handle = output->handle(); - d->name = handle->name(); - d->description = handle->description(); - d->pos = handle->geometry().topLeft(); - d->size = handle->geometry().size(); + name = handle->name(); + description = handle->description(); + pos = handle->geometry().topLeft(); + size = handle->geometry().size(); connect(handle, &Output::geometryChanged, this, &XdgOutputV1Interface::update); } -XdgOutputV1Interface::~XdgOutputV1Interface() -{ -} - void XdgOutputV1Interface::update() { - if (!d->output || d->output->isRemoved()) { + if (!output || output->isRemoved()) { return; } - const QRectF geometry = d->output->handle()->fractionalGeometry(); - const auto resources = d->resourceMap(); + const QRectF geometry = output->handle()->fractionalGeometry(); + const auto resources = resourceMap(); - if (d->pos != geometry.topLeft()) { - d->pos = geometry.topLeft(); + if (pos != geometry.topLeft()) { + pos = geometry.topLeft(); for (auto resource : resources) { - d->sendLogicalPosition(resource); + sendLogicalPosition(resource); } } - if (d->size != geometry.size()) { - d->size = geometry.size(); + if (size != geometry.size()) { + size = geometry.size(); for (auto resource : resources) { - d->sendLogicalSize(resource); + sendLogicalSize(resource); } } for (auto resource : resources) { if (wl_resource_get_version(resource->handle) < 3) { - d->send_done(resource->handle); + send_done(resource->handle); } } - d->output->scheduleDone(); + output->scheduleDone(); } -void XdgOutputV1InterfacePrivate::zxdg_output_v1_destroy(Resource *resource) +void XdgOutputV1Interface::zxdg_output_v1_destroy(Resource *resource) { wl_resource_destroy(resource->handle); } -void XdgOutputV1InterfacePrivate::zxdg_output_v1_bind_resource(Resource *resource) +void XdgOutputV1Interface::zxdg_output_v1_bind_resource(Resource *resource) { if (!output || output->isRemoved()) { return; @@ -186,10 +171,10 @@ 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::resend, Qt::UniqueConnection); + connect(connection, &ClientConnection::scaleOverrideChanged, this, &XdgOutputV1Interface::resend, Qt::UniqueConnection); } -void XdgOutputV1InterfacePrivate::sendLogicalSize(Resource *resource) +void XdgOutputV1Interface::sendLogicalSize(Resource *resource) { ClientConnection *connection = output->display()->getConnection(resource->client()); qreal scaleOverride = connection->scaleOverride(); @@ -197,7 +182,7 @@ void XdgOutputV1InterfacePrivate::sendLogicalSize(Resource *resource) send_logical_size(resource->handle, std::round(size.width() * scaleOverride), std::round(size.height() * scaleOverride)); } -void XdgOutputV1InterfacePrivate::sendLogicalPosition(Resource *resource) +void XdgOutputV1Interface::sendLogicalPosition(Resource *resource) { ClientConnection *connection = output->display()->getConnection(resource->client()); qreal scaleOverride = connection->scaleOverride(); @@ -205,7 +190,7 @@ void XdgOutputV1InterfacePrivate::sendLogicalPosition(Resource *resource) send_logical_position(resource->handle, pos.x() * scaleOverride, pos.y() * scaleOverride); } -void XdgOutputV1InterfacePrivate::sendDone(Resource *resource) +void XdgOutputV1Interface::sendDone(Resource *resource) { if (wl_resource_get_version(resource->handle) >= 3) { output->done(resource->client()); @@ -216,18 +201,18 @@ void XdgOutputV1InterfacePrivate::sendDone(Resource *resource) void XdgOutputV1Interface::resend() { - if (!d->output || d->output->isRemoved()) { + if (!output || output->isRemoved()) { return; } auto changedConnection = qobject_cast(sender()); - const auto outputResources = d->resourceMap(); + const auto outputResources = resourceMap(); for (auto resource : outputResources) { - ClientConnection *connection = d->output->display()->getConnection(resource->client()); + ClientConnection *connection = output->display()->getConnection(resource->client()); if (connection == changedConnection) { - d->sendLogicalPosition(resource); - d->sendLogicalSize(resource); - d->sendDone(resource); + sendLogicalPosition(resource); + sendLogicalSize(resource); + sendDone(resource); } } } diff --git a/src/wayland/xdgoutput_v1_interface.h b/src/wayland/xdgoutput_v1_interface.h index f0c44920fe..f8e1e780b2 100644 --- a/src/wayland/xdgoutput_v1_interface.h +++ b/src/wayland/xdgoutput_v1_interface.h @@ -12,20 +12,11 @@ #include #include -/* - * In terms of protocol XdgOutputInterface are a resource - * but for the sake of sanity, we should treat XdgOutputs as globals like Output is - * Hence this doesn't match most of kwayland API paradigms. - */ - namespace KWaylandServer { class Display; class OutputInterface; -class XdgOutputV1Interface; - class XdgOutputManagerV1InterfacePrivate; -class XdgOutputV1InterfacePrivate; /** * Global manager for XdgOutputs @@ -37,42 +28,13 @@ class KWIN_EXPORT XdgOutputManagerV1Interface : public QObject public: explicit XdgOutputManagerV1Interface(Display *display, QObject *parent = nullptr); ~XdgOutputManagerV1Interface() override; - /** - * Creates an XdgOutputInterface object for an existing Output - * which exposes XDG specific properties of outputs - * - * @arg output the wl_output interface this XDG output is for - * @parent the parent of the newly created object - */ - XdgOutputV1Interface *createXdgOutput(OutputInterface *output, QObject *parent); + + void offer(OutputInterface *output); private: std::unique_ptr d; }; -/** - * Extension to Output - * Users should set all relevant values on creation and on future changes. - * done() should be explicitly called after change batches including initial setting. - */ -class KWIN_EXPORT XdgOutputV1Interface : public QObject -{ - Q_OBJECT -public: - ~XdgOutputV1Interface() override; - -private: - void resend(); - void update(); - - explicit XdgOutputV1Interface(OutputInterface *output, QObject *parent); - friend class XdgOutputV1InterfacePrivate; - friend class XdgOutputManagerV1Interface; - friend class XdgOutputManagerV1InterfacePrivate; - - std::unique_ptr d; -}; - } #endif diff --git a/src/wayland_server.cpp b/src/wayland_server.cpp index 3f65b37ecc..40969c470c 100644 --- a/src/wayland_server.cpp +++ b/src/wayland_server.cpp @@ -299,7 +299,7 @@ void WaylandServer::handleOutputEnabled(Output *output) { if (!output->isPlaceholder() && !output->isNonDesktop()) { auto waylandOutput = new KWaylandServer::OutputInterface(waylandServer()->display(), output); - m_xdgOutputManagerV1->createXdgOutput(waylandOutput, waylandOutput); + m_xdgOutputManagerV1->offer(waylandOutput); m_waylandOutputs.insert(output, waylandOutput); }