File indexing completed on 2024-12-01 05:02:04

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