diff --git a/autotests/server/test_display.cpp b/autotests/server/test_display.cpp index f9e2ee6..b70b53f 100644 --- a/autotests/server/test_display.cpp +++ b/autotests/server/test_display.cpp @@ -1,220 +1,220 @@ /******************************************************************** Copyright 2014 Martin Gräßlin This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its successor approved by the membership of KDE e.V.), which shall act as a proxy defined in Section 6 of version 3 of the license. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library. If not, see . *********************************************************************/ // Qt #include // WaylandServer #include "../../src/server/display.h" #include "../../src/server/clientconnection.h" #include "../../src/server/outputmanagement_interface.h" #include "../../src/server/output_interface.h" // Wayland #include // system #include #include #include using namespace KWayland::Server; class TestWaylandServerDisplay : public QObject { Q_OBJECT private Q_SLOTS: void testSocketName(); void testStartStop(); void testAddRemoveOutput(); void testClientConnection(); void testConnectNoSocket(); void testOutputManagement(); }; void TestWaylandServerDisplay::testSocketName() { Display display; QSignalSpy changedSpy(&display, SIGNAL(socketNameChanged(QString))); QVERIFY(changedSpy.isValid()); QCOMPARE(display.socketName(), QStringLiteral("wayland-0")); const QString testSName = QStringLiteral("fooBar"); display.setSocketName(testSName); QCOMPARE(display.socketName(), testSName); QCOMPARE(changedSpy.count(), 1); QCOMPARE(changedSpy.first().first().toString(), testSName); // changing to same name again should not emit signal display.setSocketName(testSName); QCOMPARE(changedSpy.count(), 1); } void TestWaylandServerDisplay::testStartStop() { const QString testSocketName = QStringLiteral("kwin-wayland-server-display-test-0"); QDir runtimeDir(qgetenv("XDG_RUNTIME_DIR")); QVERIFY(runtimeDir.exists()); QVERIFY(!runtimeDir.exists(testSocketName)); Display display; QSignalSpy runningSpy(&display, SIGNAL(runningChanged(bool))); QVERIFY(runningSpy.isValid()); display.setSocketName(testSocketName); QVERIFY(!display.isRunning()); display.start(); // QVERIFY(runningSpy.wait()); QCOMPARE(runningSpy.count(), 1); QVERIFY(runningSpy.first().first().toBool()); QVERIFY(display.isRunning()); QVERIFY(runtimeDir.exists(testSocketName)); display.terminate(); QVERIFY(!display.isRunning()); QCOMPARE(runningSpy.count(), 2); QVERIFY(runningSpy.first().first().toBool()); QVERIFY(!runningSpy.last().first().toBool()); QVERIFY(!runtimeDir.exists(testSocketName)); } void TestWaylandServerDisplay::testAddRemoveOutput() { Display display; display.setSocketName(QStringLiteral("kwin-wayland-server-display-test-output-0")); display.start(); OutputInterface *output = display.createOutput(); QCOMPARE(display.outputs().size(), 1); QCOMPARE(display.outputs().first(), output); // create a second output OutputInterface *output2 = display.createOutput(); QCOMPARE(display.outputs().size(), 2); QCOMPARE(display.outputs().first(), output); QCOMPARE(display.outputs().last(), output2); // remove the first output display.removeOutput(output); QCOMPARE(display.outputs().size(), 1); QCOMPARE(display.outputs().first(), output2); // and delete the second delete output2; QVERIFY(display.outputs().isEmpty()); } void TestWaylandServerDisplay::testClientConnection() { Display display; display.setSocketName(QStringLiteral("kwin-wayland-server-display-test-client-connection")); display.start(); QSignalSpy connectedSpy(&display, SIGNAL(clientConnected(KWayland::Server::ClientConnection*))); QVERIFY(connectedSpy.isValid()); QSignalSpy disconnectedSpy(&display, SIGNAL(clientDisconnected(KWayland::Server::ClientConnection*))); QVERIFY(disconnectedSpy.isValid()); int sv[2]; QVERIFY(socketpair(AF_UNIX, SOCK_STREAM, 0, sv) >= 0); auto client = wl_client_create(display, sv[0]); QVERIFY(client); QVERIFY(connectedSpy.isEmpty()); QVERIFY(display.connections().isEmpty()); ClientConnection *connection = display.getConnection(client); QVERIFY(connection); QCOMPARE(connection->client(), client); if (getuid() == 0) { QEXPECT_FAIL("", "Please don't run test as root", Continue); } QVERIFY(connection->userId() != 0); if (getgid() == 0) { QEXPECT_FAIL("", "Please don't run test as root", Continue); } QVERIFY(connection->groupId() != 0); QVERIFY(connection->processId() != 0); QCOMPARE(connection->display(), &display); QCOMPARE(connection->executablePath(), QCoreApplication::applicationFilePath()); QCOMPARE((wl_client*)*connection, client); const ClientConnection &constRef = *connection; QCOMPARE((wl_client*)constRef, client); QCOMPARE(connectedSpy.count(), 1); QCOMPARE(connectedSpy.first().first().value(), connection); QCOMPARE(display.connections().count(), 1); QCOMPARE(display.connections().first(), connection); QCOMPARE(connection, display.getConnection(client)); QCOMPARE(connectedSpy.count(), 1); // create a second client int sv2[2]; QVERIFY(socketpair(AF_UNIX, SOCK_STREAM, 0, sv2) >= 0); auto client2 = display.createClient(sv2[0]); QVERIFY(client2); ClientConnection *connection2 = display.getConnection(client2->client()); QVERIFY(connection2); QCOMPARE(connection2, client2); QCOMPARE(connectedSpy.count(), 2); QCOMPARE(connectedSpy.first().first().value(), connection); QCOMPARE(connectedSpy.last().first().value(), connection2); QCOMPARE(connectedSpy.last().first().value(), client2); QCOMPARE(display.connections().count(), 2); QCOMPARE(display.connections().first(), connection); QCOMPARE(display.connections().last(), connection2); QCOMPARE(display.connections().last(), client2); // and destroy QVERIFY(disconnectedSpy.isEmpty()); wl_client_destroy(client); QCOMPARE(disconnectedSpy.count(), 1); QSignalSpy clientDestroyedSpy(client2, &QObject::destroyed); QVERIFY(clientDestroyedSpy.isValid()); client2->destroy(); QVERIFY(clientDestroyedSpy.wait()); QCOMPARE(disconnectedSpy.count(), 2); close(sv[0]); close(sv[1]); close(sv2[0]); close(sv2[1]); QVERIFY(display.connections().isEmpty()); } void TestWaylandServerDisplay::testConnectNoSocket() { Display display; display.start(Display::StartMode::ConnectClientsOnly); QVERIFY(display.isRunning()); // let's try connecting a client int sv[2]; QVERIFY(socketpair(AF_UNIX, SOCK_STREAM, 0, sv) >= 0); auto client = display.createClient(sv[0]); QVERIFY(client); wl_client_destroy(client->client()); close(sv[0]); close(sv[1]); } void TestWaylandServerDisplay::testOutputManagement() { - auto display = new KWayland::Server::Display(this); - display->setSocketName("kwayland-test-0"); - display->start(); - auto kwin = display->createOutputManagement(this); + Display display; + display.setSocketName("kwayland-test-0"); + display.start(); + auto kwin = display.createOutputManagement(this); kwin->create(); QVERIFY(kwin->isValid()); } QTEST_GUILESS_MAIN(TestWaylandServerDisplay) #include "test_display.moc" diff --git a/src/client/xdgoutput.cpp b/src/client/xdgoutput.cpp index e7ee221..7cdfb11 100644 --- a/src/client/xdgoutput.cpp +++ b/src/client/xdgoutput.cpp @@ -1,240 +1,240 @@ /**************************************************************************** Copyright 2018 David Edmundson This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its successor approved by the membership of KDE e.V.), which shall act as a proxy defined in Section 6 of version 3 of the license. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library. If not, see . ****************************************************************************/ #include "xdgoutput.h" #include "event_queue.h" #include "wayland_pointer_p.h" #include "output.h" #include #include #include namespace KWayland { namespace Client { class XdgOutputManager::Private { public: Private() = default; void setup(zxdg_output_manager_v1 *arg); WaylandPointer xdgoutputmanager; EventQueue *queue = nullptr; }; XdgOutputManager::XdgOutputManager(QObject *parent) : QObject(parent) , d(new Private) { } void XdgOutputManager::Private::setup(zxdg_output_manager_v1 *arg) { Q_ASSERT(arg); Q_ASSERT(!xdgoutputmanager); xdgoutputmanager.setup(arg); } XdgOutputManager::~XdgOutputManager() { release(); } void XdgOutputManager::setup(zxdg_output_manager_v1 *xdgoutputmanager) { d->setup(xdgoutputmanager); } void XdgOutputManager::release() { d->xdgoutputmanager.release(); } void XdgOutputManager::destroy() { d->xdgoutputmanager.destroy(); } XdgOutputManager::operator zxdg_output_manager_v1*() { return d->xdgoutputmanager; } XdgOutputManager::operator zxdg_output_manager_v1*() const { return d->xdgoutputmanager; } bool XdgOutputManager::isValid() const { return d->xdgoutputmanager.isValid(); } void XdgOutputManager::setEventQueue(EventQueue *queue) { d->queue = queue; } EventQueue *XdgOutputManager::eventQueue() { return d->queue; } XdgOutput *XdgOutputManager::getXdgOutput(Output *output, QObject *parent) { Q_ASSERT(isValid()); auto p = new XdgOutput(parent); auto w = zxdg_output_manager_v1_get_xdg_output(d->xdgoutputmanager, *output); if (d->queue) { d->queue->addProxy(w); } p->setup(w); return p; } struct XdgOutputBuffer { QPoint logicalPosition; QSize logicalSize; }; class XdgOutput::Private { public: Private(XdgOutput *q); void setup(zxdg_output_v1 *arg); WaylandPointer xdgoutput; XdgOutputBuffer current; XdgOutputBuffer pending; private: XdgOutput *q; private: static void logical_positionCallback(void *data, zxdg_output_v1 *zxdg_output_v1, int32_t x, int32_t y); static void logical_sizeCallback(void *data, zxdg_output_v1 *zxdg_output_v1, int32_t width, int32_t height); static void doneCallback(void *data, zxdg_output_v1 *zxdg_output_v1); static const zxdg_output_v1_listener s_listener; }; const zxdg_output_v1_listener XdgOutput::Private::s_listener = { logical_positionCallback, logical_sizeCallback, doneCallback }; void XdgOutput::Private::logical_positionCallback(void *data, zxdg_output_v1 *zxdg_output_v1, int32_t x, int32_t y) { auto p = reinterpret_cast(data); Q_ASSERT(p->xdgoutput == zxdg_output_v1); p->pending.logicalPosition = QPoint(x,y); } void XdgOutput::Private::logical_sizeCallback(void *data, zxdg_output_v1 *zxdg_output_v1, int32_t width, int32_t height) { auto p = reinterpret_cast(data); Q_ASSERT(p->xdgoutput == zxdg_output_v1); p->pending.logicalSize = QSize(width,height); } void XdgOutput::Private::doneCallback(void *data, zxdg_output_v1 *zxdg_output_v1) { auto p = reinterpret_cast(data); Q_ASSERT(p->xdgoutput == zxdg_output_v1); std::swap(p->current, p->pending); if (p->current.logicalSize != p->pending.logicalSize || p->current.logicalPosition != p->pending.logicalPosition) { emit p->q->changed(); } } -XdgOutput::Private::Private(XdgOutput *q) - : q(q) +XdgOutput::Private::Private(XdgOutput *qptr) + : q(qptr) { } XdgOutput::XdgOutput(QObject *parent) : QObject(parent) , d(new Private(this)) { } void XdgOutput::Private::setup(zxdg_output_v1 *arg) { Q_ASSERT(arg); Q_ASSERT(!xdgoutput); xdgoutput.setup(arg); zxdg_output_v1_add_listener(xdgoutput, &s_listener, this); } XdgOutput::~XdgOutput() { release(); } void XdgOutput::setup(zxdg_output_v1 *xdgoutput) { d->setup(xdgoutput); } void XdgOutput::release() { d->xdgoutput.release(); } void XdgOutput::destroy() { d->xdgoutput.destroy(); } QSize XdgOutput::logicalSize() const { return d->current.logicalSize; } QPoint XdgOutput::logicalPosition() const { return d->current.logicalPosition; } XdgOutput::operator zxdg_output_v1*() { return d->xdgoutput; } XdgOutput::operator zxdg_output_v1*() const { return d->xdgoutput; } bool XdgOutput::isValid() const { return d->xdgoutput.isValid(); } } } diff --git a/src/server/dpms_interface.cpp b/src/server/dpms_interface.cpp index ce57d36..3f48e43 100644 --- a/src/server/dpms_interface.cpp +++ b/src/server/dpms_interface.cpp @@ -1,176 +1,176 @@ /******************************************************************** Copyright 2015 Martin Gräßlin This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its successor approved by the membership of KDE e.V.), which shall act as a proxy defined in Section 6 of version 3 of the license. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library. If not, see . *********************************************************************/ #include "dpms_interface_p.h" #include "display.h" #include "output_interface.h" namespace KWayland { namespace Server { const quint32 DpmsManagerInterface::Private::s_version = 1; #ifndef DOXYGEN_SHOULD_SKIP_THIS const struct org_kde_kwin_dpms_manager_interface DpmsManagerInterface::Private::s_interface = { getDpmsCallback }; #endif -DpmsManagerInterface::Private::Private(DpmsManagerInterface *q, Display *d) +DpmsManagerInterface::Private::Private(DpmsManagerInterface *qptr, Display *d) : Global::Private(d, &org_kde_kwin_dpms_manager_interface, s_version) - , q(q) + , q(qptr) { } void DpmsManagerInterface::Private::bind(wl_client *client, uint32_t version, uint32_t id) { auto c = display->getConnection(client); wl_resource *dpms = c->createResource(&org_kde_kwin_dpms_manager_interface, qMin(version, s_version), id); if (!dpms) { wl_client_post_no_memory(client); return; } wl_resource_set_implementation(dpms, &s_interface, this, nullptr); } void DpmsManagerInterface::Private::getDpmsCallback(wl_client *client, wl_resource *resource, uint32_t id, wl_resource *output) { auto p = Private::cast(resource); auto c = p->display->getConnection(client); OutputInterface *o = OutputInterface::get(output); DpmsInterface *dpms = new DpmsInterface(o, resource, p->q); dpms->create(c, wl_resource_get_version(resource), id); if (!dpms->resource()) { wl_resource_post_no_memory(resource); return; } dpms->sendSupported(); dpms->sendMode(); dpms->sendDone(); } DpmsManagerInterface::DpmsManagerInterface(Display *display, QObject *parent) : Global(new Private(this, display), parent) { } DpmsManagerInterface::~DpmsManagerInterface() = default; #ifndef DOXYGEN_SHOULD_SKIP_THIS const struct org_kde_kwin_dpms_interface DpmsInterface::Private::s_interface = { setCallback, resourceDestroyedCallback }; #endif -DpmsInterface::Private::Private(DpmsInterface *q, DpmsManagerInterface *g, wl_resource *parentResource, OutputInterface *output) +DpmsInterface::Private::Private(DpmsInterface *q, DpmsManagerInterface *g, wl_resource *parentResource, OutputInterface *outputInterface) : Resource::Private(q, g, parentResource, &org_kde_kwin_dpms_interface, &s_interface) - , output(output) + , output(outputInterface) { } void DpmsInterface::Private::setCallback(wl_client *client, wl_resource *resource, uint32_t mode) { Q_UNUSED(client) OutputInterface::DpmsMode dpmsMode; switch (mode) { case ORG_KDE_KWIN_DPMS_MODE_ON: dpmsMode = OutputInterface::DpmsMode::On; break; case ORG_KDE_KWIN_DPMS_MODE_STANDBY: dpmsMode = OutputInterface::DpmsMode::Standby; break; case ORG_KDE_KWIN_DPMS_MODE_SUSPEND: dpmsMode = OutputInterface::DpmsMode::Suspend; break; case ORG_KDE_KWIN_DPMS_MODE_OFF: dpmsMode = OutputInterface::DpmsMode::Off; break; default: return; } emit cast(resource)->output->dpmsModeRequested(dpmsMode); } DpmsInterface::DpmsInterface(OutputInterface *output, wl_resource *parentResource, DpmsManagerInterface *manager) : Resource(new Private(this, manager, parentResource, output)) { connect(output, &OutputInterface::dpmsSupportedChanged, this, [this] { sendSupported(); sendDone(); } ); connect(output, &OutputInterface::dpmsModeChanged, this, [this] { sendMode(); sendDone(); } ); } DpmsInterface::~DpmsInterface() = default; void DpmsInterface::sendSupported() { Q_D(); org_kde_kwin_dpms_send_supported(d->resource, d->output->isDpmsSupported() ? 1 : 0); } void DpmsInterface::sendMode() { Q_D(); const auto mode = d->output->dpmsMode(); org_kde_kwin_dpms_mode wlMode; switch (mode) { case OutputInterface::DpmsMode::On: wlMode = ORG_KDE_KWIN_DPMS_MODE_ON; break; case OutputInterface::DpmsMode::Standby: wlMode = ORG_KDE_KWIN_DPMS_MODE_STANDBY; break; case OutputInterface::DpmsMode::Suspend: wlMode = ORG_KDE_KWIN_DPMS_MODE_SUSPEND; break; case OutputInterface::DpmsMode::Off: wlMode = ORG_KDE_KWIN_DPMS_MODE_OFF; break; default: Q_UNREACHABLE(); } org_kde_kwin_dpms_send_mode(d->resource, wlMode); } void DpmsInterface::sendDone() { Q_D(); org_kde_kwin_dpms_send_done(d->resource); client()->flush(); } DpmsInterface::Private *DpmsInterface::d_func() const { return reinterpret_cast(d.data()); } } } diff --git a/src/server/xdgoutput_interface.cpp b/src/server/xdgoutput_interface.cpp index 7794021..6d51626 100644 --- a/src/server/xdgoutput_interface.cpp +++ b/src/server/xdgoutput_interface.cpp @@ -1,307 +1,307 @@ /**************************************************************************** Copyright 2018 David Edmundson This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its successor approved by the membership of KDE e.V.), which shall act as a proxy defined in Section 6 of version 3 of the license. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library. If not, see . ****************************************************************************/ #include "xdgoutput_interface.h" #include "display.h" #include "global_p.h" #include "resource_p.h" #include "output_interface.h" #include namespace KWayland { namespace Server { class XdgOutputManagerInterface::Private : public Global::Private { public: Private(XdgOutputManagerInterface *q, Display *d); QHash outputs; private: void bind(wl_client *client, uint32_t version, uint32_t id) override; static void unbind(wl_resource *resource); static Private *cast(wl_resource *r) { return reinterpret_cast(wl_resource_get_user_data(r)); } static void destroyCallback(wl_client *client, wl_resource *resource); static void getXdgOutputCallback(wl_client *client, wl_resource *resource, uint32_t id, wl_resource * output); XdgOutputManagerInterface *q; static const struct zxdg_output_manager_v1_interface s_interface; static const quint32 s_version; }; const quint32 XdgOutputManagerInterface::Private::s_version = 1; #ifndef DOXYGEN_SHOULD_SKIP_THIS const struct zxdg_output_manager_v1_interface XdgOutputManagerInterface::Private::s_interface = { destroyCallback, getXdgOutputCallback }; #endif class XdgOutputV1Interface: public Resource { public: XdgOutputV1Interface(XdgOutputManagerInterface *parent, wl_resource *parentResource); ~XdgOutputV1Interface(); void setLogicalSize(const QSize &size); void setLogicalPosition(const QPoint &pos); void done(); private: class Private; }; class XdgOutputInterface::Private { public: void resourceConnected(XdgOutputV1Interface *resource); void resourceDisconnected(XdgOutputV1Interface *resource); QPoint pos; QSize size; bool doneOnce = false; QList resources; }; XdgOutputManagerInterface::XdgOutputManagerInterface(Display *display, QObject *parent) : Global(new XdgOutputManagerInterface::Private(this, display), parent) { } XdgOutputManagerInterface::~XdgOutputManagerInterface() {} XdgOutputInterface* XdgOutputManagerInterface::createXdgOutput(OutputInterface *output, QObject *parent) { Q_D(); if (!d->outputs.contains(output)) { auto xdgOutput = new XdgOutputInterface(parent); 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]() { Q_D(); d->outputs.remove(output); }); connect(xdgOutput, &QObject::destroyed, this, [this, output]() { Q_D(); d->outputs.remove(output); }); } return d->outputs[output]; } XdgOutputManagerInterface::Private* XdgOutputManagerInterface::d_func() const { return reinterpret_cast(d.data()); } void XdgOutputManagerInterface::Private::destroyCallback(wl_client *client, wl_resource *resource) { Q_UNUSED(client) wl_resource_destroy(resource); } void XdgOutputManagerInterface::Private::getXdgOutputCallback(wl_client *client, wl_resource *resource, uint32_t id, wl_resource * outputResource) { auto d = cast(resource); auto output = OutputInterface::get(outputResource); if (!output) { // output client is requesting XdgOutput for an Output that doesn't exist return; } if (!d->outputs.contains(output)) { return; //server hasn't created an XdgOutput for this output yet, give the client nothing } auto iface = new XdgOutputV1Interface(d->q, resource); iface->create(d->display->getConnection(client), wl_resource_get_version(resource), id); if (!iface->resource()) { wl_resource_post_no_memory(resource); delete iface; return; } auto xdgOutput = d->outputs[output]; xdgOutput->d->resourceConnected(iface); connect(iface, &XdgOutputV1Interface::unbound, xdgOutput, [xdgOutput, iface]() { xdgOutput->d->resourceDisconnected(iface); }); } -XdgOutputManagerInterface::Private::Private(XdgOutputManagerInterface *q, Display *d) +XdgOutputManagerInterface::Private::Private(XdgOutputManagerInterface *qptr, Display *d) : Global::Private(d, &zxdg_output_manager_v1_interface, s_version) - , q(q) + , q(qptr) { } void XdgOutputManagerInterface::Private::bind(wl_client *client, uint32_t version, uint32_t id) { auto c = display->getConnection(client); wl_resource *resource = c->createResource(&zxdg_output_manager_v1_interface, qMin(version, s_version), id); if (!resource) { wl_client_post_no_memory(client); return; } wl_resource_set_implementation(resource, &s_interface, this, unbind); } void XdgOutputManagerInterface::Private::unbind(wl_resource *resource) { Q_UNUSED(resource) } XdgOutputInterface::XdgOutputInterface(QObject *parent): QObject(parent), d(new XdgOutputInterface::Private) { } XdgOutputInterface::~XdgOutputInterface() {} void XdgOutputInterface::setLogicalSize(const QSize &size) { if (size == d->size) { return; } d->size = size; for(auto resource: d->resources) { resource->setLogicalSize(size); } } QSize XdgOutputInterface::logicalSize() const { return d->size; } void XdgOutputInterface::setLogicalPosition(const QPoint &pos) { if (pos == d->pos) { return; } d->pos = pos; for(auto resource: d->resources) { resource->setLogicalPosition(pos); } } QPoint XdgOutputInterface::logicalPosition() const { return d->pos; } void XdgOutputInterface::done() { d->doneOnce = true; for(auto resource: d->resources) { resource->done(); } } void XdgOutputInterface::Private::resourceConnected(XdgOutputV1Interface *resource) { resource->setLogicalPosition(pos); resource->setLogicalSize(size); if (doneOnce) { resource->done(); } resources << resource; } void XdgOutputInterface::Private::resourceDisconnected(XdgOutputV1Interface *resource) { resources.removeOne(resource); } class XdgOutputV1Interface::Private : public Resource::Private { public: Private(XdgOutputV1Interface *q, XdgOutputManagerInterface *c, wl_resource *parentResource); ~Private(); private: XdgOutputV1Interface *q_func() { return reinterpret_cast(q); } static const struct zxdg_output_v1_interface s_interface; }; XdgOutputV1Interface::XdgOutputV1Interface(XdgOutputManagerInterface *parent, wl_resource *parentResource) :Resource(new XdgOutputV1Interface::Private(this, parent, parentResource)) {} XdgOutputV1Interface::~XdgOutputV1Interface() {} void XdgOutputV1Interface::setLogicalSize(const QSize &size) { if (!d->resource) { return; } zxdg_output_v1_send_logical_size(d->resource, size.width(), size.height()); } void XdgOutputV1Interface::setLogicalPosition(const QPoint &pos) { if (!d->resource) { return; } zxdg_output_v1_send_logical_position(d->resource, pos.x(), pos.y()); } void XdgOutputV1Interface::done() { if (!d->resource) { return; } zxdg_output_v1_send_done(d->resource); } #ifndef DOXYGEN_SHOULD_SKIP_THIS const struct zxdg_output_v1_interface XdgOutputV1Interface::Private::s_interface = { resourceDestroyedCallback }; #endif XdgOutputV1Interface::Private::Private(XdgOutputV1Interface *q, XdgOutputManagerInterface *c, wl_resource *parentResource) : Resource::Private(q, c, parentResource, &zxdg_output_v1_interface, &s_interface) { } XdgOutputV1Interface::Private::~Private() { if (resource) { wl_resource_destroy(resource); resource = nullptr; } } } }