File indexing completed on 2024-05-19 16:33:11

0001 /*
0002     SPDX-FileCopyrightText: 2016 Martin Gräßlin <mgraesslin@kde.org>
0003     SPDX-FileCopyrightText: 2017 Marco Martin <mart@kde.org>
0004 
0005     SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
0006 */
0007 #include "../src/client/xdgforeign.h"
0008 #include "../src/client/compositor.h"
0009 #include "../src/client/connection_thread.h"
0010 #include "../src/client/event_queue.h"
0011 #include "../src/client/registry.h"
0012 #include "../src/client/server_decoration.h"
0013 #include "../src/client/shell.h"
0014 #include "../src/client/shm_pool.h"
0015 #include "../src/client/xdgshell.h"
0016 // Qt
0017 #include <QCommandLineParser>
0018 #include <QDebug>
0019 #include <QGuiApplication>
0020 #include <QImage>
0021 #include <QThread>
0022 using namespace KWayland::Client;
0023 
0024 class XdgForeignTest : public QObject
0025 {
0026     Q_OBJECT
0027 public:
0028     explicit XdgForeignTest(QObject *parent = nullptr);
0029     ~XdgForeignTest() override;
0030 
0031     void init();
0032 
0033 private:
0034     void setupRegistry(Registry *registry);
0035     void render();
0036     QThread *m_connectionThread;
0037     ConnectionThread *m_connectionThreadObject;
0038     EventQueue *m_eventQueue = nullptr;
0039     Compositor *m_compositor = nullptr;
0040     XdgShell *m_shell = nullptr;
0041     XdgShellSurface *m_shellSurface = nullptr;
0042     ShmPool *m_shm = nullptr;
0043     Surface *m_surface = nullptr;
0044 
0045     XdgShellSurface *m_childShellSurface = nullptr;
0046     Surface *m_childSurface = nullptr;
0047 
0048     KWayland::Client::XdgExporter *m_exporter = nullptr;
0049     KWayland::Client::XdgImporter *m_importer = nullptr;
0050     KWayland::Client::XdgExported *m_exported = nullptr;
0051     KWayland::Client::XdgImported *m_imported = nullptr;
0052     KWayland::Client::ServerSideDecorationManager *m_decoration = nullptr;
0053 };
0054 
0055 XdgForeignTest::XdgForeignTest(QObject *parent)
0056     : QObject(parent)
0057     , m_connectionThread(new QThread(this))
0058     , m_connectionThreadObject(new ConnectionThread())
0059 {
0060 }
0061 
0062 XdgForeignTest::~XdgForeignTest()
0063 {
0064     m_connectionThread->quit();
0065     m_connectionThread->wait();
0066     m_connectionThreadObject->deleteLater();
0067 }
0068 
0069 void XdgForeignTest::init()
0070 {
0071     connect(
0072         m_connectionThreadObject,
0073         &ConnectionThread::connected,
0074         this,
0075         [this] {
0076             m_eventQueue = new EventQueue(this);
0077             m_eventQueue->setup(m_connectionThreadObject);
0078 
0079             Registry *registry = new Registry(this);
0080             setupRegistry(registry);
0081         },
0082         Qt::QueuedConnection);
0083     m_connectionThreadObject->moveToThread(m_connectionThread);
0084     m_connectionThread->start();
0085 
0086     m_connectionThreadObject->initConnection();
0087 }
0088 
0089 void XdgForeignTest::setupRegistry(Registry *registry)
0090 {
0091     connect(registry, &Registry::compositorAnnounced, this, [this, registry](quint32 name, quint32 version) {
0092         m_compositor = registry->createCompositor(name, version, this);
0093     });
0094     connect(registry, &Registry::xdgShellUnstableV5Announced, this, [this, registry](quint32 name, quint32 version) {
0095         m_shell = registry->createXdgShell(name, version, this);
0096     });
0097     connect(registry, &Registry::shmAnnounced, this, [this, registry](quint32 name, quint32 version) {
0098         m_shm = registry->createShmPool(name, version, this);
0099     });
0100     connect(registry, &Registry::exporterUnstableV2Announced, this, [this, registry](quint32 name, quint32 version) {
0101         m_exporter = registry->createXdgExporter(name, version, this);
0102         m_exporter->setEventQueue(m_eventQueue);
0103     });
0104     connect(registry, &Registry::importerUnstableV2Announced, this, [this, registry](quint32 name, quint32 version) {
0105         m_importer = registry->createXdgImporter(name, version, this);
0106         m_importer->setEventQueue(m_eventQueue);
0107     });
0108     connect(registry, &Registry::serverSideDecorationManagerAnnounced, this, [this, registry](quint32 name, quint32 version) {
0109         m_decoration = registry->createServerSideDecorationManager(name, version, this);
0110         m_decoration->setEventQueue(m_eventQueue);
0111     });
0112     connect(registry, &Registry::interfacesAnnounced, this, [this] {
0113         Q_ASSERT(m_compositor);
0114         Q_ASSERT(m_shell);
0115         Q_ASSERT(m_shm);
0116         Q_ASSERT(m_exporter);
0117         Q_ASSERT(m_importer);
0118         m_surface = m_compositor->createSurface(this);
0119         Q_ASSERT(m_surface);
0120         auto parentDeco = m_decoration->create(m_surface, this);
0121         Q_UNUSED(parentDeco)
0122         m_shellSurface = m_shell->createSurface(m_surface, this);
0123         Q_ASSERT(m_shellSurface);
0124         connect(m_shellSurface, &XdgShellSurface::sizeChanged, this, &XdgForeignTest::render);
0125 
0126         m_childSurface = m_compositor->createSurface(this);
0127         Q_ASSERT(m_childSurface);
0128         auto childDeco = m_decoration->create(m_childSurface, this);
0129         Q_UNUSED(childDeco)
0130         m_childShellSurface = m_shell->createSurface(m_childSurface, this);
0131         Q_ASSERT(m_childShellSurface);
0132         connect(m_childShellSurface, &XdgShellSurface::sizeChanged, this, &XdgForeignTest::render);
0133 
0134         m_exported = m_exporter->exportTopLevel(m_surface, this);
0135         Q_ASSERT(m_decoration);
0136         connect(m_exported, &XdgExported::done, this, [this]() {
0137             m_imported = m_importer->importTopLevel(m_exported->handle(), this);
0138             m_imported->setParentOf(m_childSurface);
0139         });
0140         render();
0141     });
0142     registry->setEventQueue(m_eventQueue);
0143     registry->create(m_connectionThreadObject);
0144     registry->setup();
0145 }
0146 
0147 void XdgForeignTest::render()
0148 {
0149     QSize size = m_shellSurface->size().isValid() ? m_shellSurface->size() : QSize(500, 500);
0150     auto buffer = m_shm->getBuffer(size, size.width() * 4).toStrongRef();
0151     buffer->setUsed(true);
0152     QImage image(buffer->address(), size.width(), size.height(), QImage::Format_ARGB32_Premultiplied);
0153     image.fill(QColor(255, 255, 255, 255));
0154 
0155     m_surface->attachBuffer(*buffer);
0156     m_surface->damage(QRect(QPoint(0, 0), size));
0157     m_surface->commit(Surface::CommitFlag::None);
0158     buffer->setUsed(false);
0159 
0160     size = m_childShellSurface->size().isValid() ? m_childShellSurface->size() : QSize(200, 200);
0161     buffer = m_shm->getBuffer(size, size.width() * 4).toStrongRef();
0162     buffer->setUsed(true);
0163     image = QImage(buffer->address(), size.width(), size.height(), QImage::Format_ARGB32_Premultiplied);
0164     image.fill(QColor(255, 0, 0, 255));
0165 
0166     m_childSurface->attachBuffer(*buffer);
0167     m_childSurface->damage(QRect(QPoint(0, 0), size));
0168     m_childSurface->commit(Surface::CommitFlag::None);
0169     buffer->setUsed(false);
0170 }
0171 
0172 int main(int argc, char **argv)
0173 {
0174     QCoreApplication app(argc, argv);
0175 
0176     XdgForeignTest client;
0177 
0178     client.init();
0179 
0180     return app.exec();
0181 }
0182 
0183 #include "xdgforeigntest.moc"