File indexing completed on 2024-11-10 04:58:09

0001 /*
0002     SPDX-FileCopyrightText: 2016 Martin Gräßlin <mgraesslin@kde.org>
0003 
0004     SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
0005 */
0006 #include "KWayland/Client/compositor.h"
0007 #include "KWayland/Client/connection_thread.h"
0008 #include "KWayland/Client/datadevice.h"
0009 #include "KWayland/Client/datadevicemanager.h"
0010 #include "KWayland/Client/dataoffer.h"
0011 #include "KWayland/Client/event_queue.h"
0012 #include "KWayland/Client/keyboard.h"
0013 #include "KWayland/Client/registry.h"
0014 #include "KWayland/Client/seat.h"
0015 #include "KWayland/Client/shell.h"
0016 #include "KWayland/Client/shm_pool.h"
0017 #include "KWayland/Client/subcompositor.h"
0018 #include "KWayland/Client/surface.h"
0019 // Qt
0020 #include <QDebug>
0021 #include <QFile>
0022 #include <QGuiApplication>
0023 #include <QImage>
0024 #include <QMimeType>
0025 #include <QThread>
0026 #include <QTimer>
0027 // system
0028 #include <unistd.h>
0029 
0030 #include <linux/input.h>
0031 
0032 using namespace KWayland::Client;
0033 
0034 class SubSurfaceTest : public QObject
0035 {
0036     Q_OBJECT
0037 public:
0038     explicit SubSurfaceTest(QObject *parent = nullptr);
0039     virtual ~SubSurfaceTest();
0040 
0041     void init();
0042 
0043 private:
0044     void setupRegistry(Registry *registry);
0045     void render();
0046     QThread *m_connectionThread;
0047     ConnectionThread *m_connectionThreadObject;
0048     EventQueue *m_eventQueue = nullptr;
0049     Compositor *m_compositor = nullptr;
0050     Seat *m_seat = nullptr;
0051     Shell *m_shell = nullptr;
0052     ShellSurface *m_shellSurface = nullptr;
0053     ShmPool *m_shm = nullptr;
0054     Surface *m_surface = nullptr;
0055     SubCompositor *m_subCompositor = nullptr;
0056 };
0057 
0058 SubSurfaceTest::SubSurfaceTest(QObject *parent)
0059     : QObject(parent)
0060     , m_connectionThread(new QThread(this))
0061     , m_connectionThreadObject(new ConnectionThread())
0062 {
0063 }
0064 
0065 SubSurfaceTest::~SubSurfaceTest()
0066 {
0067     m_connectionThread->quit();
0068     m_connectionThread->wait();
0069     m_connectionThreadObject->deleteLater();
0070 }
0071 
0072 void SubSurfaceTest::init()
0073 {
0074     connect(
0075         m_connectionThreadObject,
0076         &ConnectionThread::connected,
0077         this,
0078         [this] {
0079             m_eventQueue = new EventQueue(this);
0080             m_eventQueue->setup(m_connectionThreadObject);
0081 
0082             Registry *registry = new Registry(this);
0083             setupRegistry(registry);
0084         },
0085         Qt::QueuedConnection);
0086     m_connectionThreadObject->moveToThread(m_connectionThread);
0087     m_connectionThread->start();
0088 
0089     m_connectionThreadObject->initConnection();
0090 }
0091 
0092 void SubSurfaceTest::setupRegistry(Registry *registry)
0093 {
0094     connect(registry, &Registry::compositorAnnounced, this, [this, registry](quint32 name, quint32 version) {
0095         m_compositor = registry->createCompositor(name, version, this);
0096     });
0097     connect(registry, &Registry::shellAnnounced, this, [this, registry](quint32 name, quint32 version) {
0098         m_shell = registry->createShell(name, version, this);
0099     });
0100     connect(registry, &Registry::shmAnnounced, this, [this, registry](quint32 name, quint32 version) {
0101         m_shm = registry->createShmPool(name, version, this);
0102     });
0103     connect(registry, &Registry::seatAnnounced, this, [this, registry](quint32 name, quint32 version) {
0104         m_seat = registry->createSeat(name, version, this);
0105     });
0106     connect(registry, &Registry::interfacesAnnounced, this, [this, registry] {
0107         Q_ASSERT(m_compositor);
0108         Q_ASSERT(m_seat);
0109         Q_ASSERT(m_shell);
0110         Q_ASSERT(m_shm);
0111         m_surface = m_compositor->createSurface(this);
0112         Q_ASSERT(m_surface);
0113         m_shellSurface = m_shell->createSurface(m_surface, this);
0114         Q_ASSERT(m_shellSurface);
0115         m_shellSurface->setToplevel();
0116         connect(m_shellSurface, &ShellSurface::sizeChanged, this, &SubSurfaceTest::render);
0117 
0118         auto subInterface = registry->interface(Registry::Interface::SubCompositor);
0119         if (subInterface.name != 0) {
0120             m_subCompositor = registry->createSubCompositor(subInterface.name, subInterface.version, this);
0121             Q_ASSERT(m_subCompositor);
0122             // create the sub surface
0123             auto surface = m_compositor->createSurface(this);
0124             Q_ASSERT(surface);
0125             auto subsurface = m_subCompositor->createSubSurface(surface, m_surface, this);
0126             Q_ASSERT(subsurface);
0127             QImage image(QSize(100, 100), QImage::Format_ARGB32_Premultiplied);
0128             image.fill(Qt::red);
0129             surface->attachBuffer(m_shm->createBuffer(image));
0130             surface->damage(QRect(0, 0, 100, 100));
0131             surface->commit(Surface::CommitFlag::None);
0132             // and another sub-surface to the sub-surface
0133             auto surface2 = m_compositor->createSurface(this);
0134             Q_ASSERT(surface2);
0135             auto subsurface2 = m_subCompositor->createSubSurface(surface2, surface, this);
0136             Q_ASSERT(subsurface2);
0137             QImage green(QSize(50, 50), QImage::Format_ARGB32_Premultiplied);
0138             green.fill(Qt::green);
0139             surface2->attachBuffer(m_shm->createBuffer(green));
0140             surface2->damage(QRect(0, 0, 50, 50));
0141             surface2->commit(Surface::CommitFlag::None);
0142             QTimer *timer = new QTimer(this);
0143             connect(timer, &QTimer::timeout, surface2, [surface2, this] {
0144                 QImage yellow(QSize(50, 50), QImage::Format_ARGB32_Premultiplied);
0145                 yellow.fill(Qt::yellow);
0146                 surface2->attachBuffer(m_shm->createBuffer(yellow));
0147                 surface2->damage(QRect(0, 0, 50, 50));
0148                 surface2->commit(Surface::CommitFlag::None);
0149                 m_surface->commit(Surface::CommitFlag::None);
0150             });
0151             timer->setSingleShot(true);
0152             timer->start(5000);
0153         }
0154         render();
0155     });
0156     registry->setEventQueue(m_eventQueue);
0157     registry->create(m_connectionThreadObject);
0158     registry->setup();
0159 }
0160 
0161 void SubSurfaceTest::render()
0162 {
0163     const QSize &size = m_shellSurface->size().isValid() ? m_shellSurface->size() : QSize(200, 200);
0164     auto buffer = m_shm->getBuffer(size, size.width() * 4).toStrongRef();
0165     buffer->setUsed(true);
0166     QImage image(buffer->address(), size.width(), size.height(), QImage::Format_ARGB32_Premultiplied);
0167     image.fill(Qt::blue);
0168 
0169     m_surface->attachBuffer(*buffer);
0170     m_surface->damage(QRect(QPoint(0, 0), size));
0171     m_surface->commit(Surface::CommitFlag::None);
0172     buffer->setUsed(false);
0173 }
0174 
0175 int main(int argc, char **argv)
0176 {
0177     QCoreApplication app(argc, argv);
0178     SubSurfaceTest client;
0179     client.init();
0180 
0181     return app.exec();
0182 }
0183 
0184 #include "subsurfacetest.moc"