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

0001 /*
0002     SPDX-FileCopyrightText: 2015 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/shadow.h"
0007 #include "KWayland/Client/compositor.h"
0008 #include "KWayland/Client/connection_thread.h"
0009 #include "KWayland/Client/event_queue.h"
0010 #include "KWayland/Client/registry.h"
0011 #include "KWayland/Client/shell.h"
0012 #include "KWayland/Client/shm_pool.h"
0013 #include "KWayland/Client/surface.h"
0014 // Qt
0015 #include <QGuiApplication>
0016 #include <QImage>
0017 #include <QThread>
0018 
0019 using namespace KWayland::Client;
0020 
0021 class ShadowTest : public QObject
0022 {
0023     Q_OBJECT
0024 public:
0025     explicit ShadowTest(QObject *parent = nullptr);
0026     virtual ~ShadowTest();
0027 
0028     void init();
0029 
0030 private:
0031     void setupRegistry(Registry *registry);
0032     void setupShadow();
0033     void render();
0034     QThread *m_connectionThread;
0035     ConnectionThread *m_connectionThreadObject;
0036     EventQueue *m_eventQueue = nullptr;
0037     Compositor *m_compositor = nullptr;
0038     Shell *m_shell = nullptr;
0039     ShellSurface *m_shellSurface = nullptr;
0040     ShmPool *m_shm = nullptr;
0041     Surface *m_surface = nullptr;
0042     ShadowManager *m_shadowManager = nullptr;
0043 };
0044 
0045 ShadowTest::ShadowTest(QObject *parent)
0046     : QObject(parent)
0047     , m_connectionThread(new QThread(this))
0048     , m_connectionThreadObject(new ConnectionThread())
0049 {
0050 }
0051 
0052 ShadowTest::~ShadowTest()
0053 {
0054     m_connectionThread->quit();
0055     m_connectionThread->wait();
0056     m_connectionThreadObject->deleteLater();
0057 }
0058 
0059 void ShadowTest::init()
0060 {
0061     connect(
0062         m_connectionThreadObject,
0063         &ConnectionThread::connected,
0064         this,
0065         [this] {
0066             m_eventQueue = new EventQueue(this);
0067             m_eventQueue->setup(m_connectionThreadObject);
0068 
0069             Registry *registry = new Registry(this);
0070             setupRegistry(registry);
0071         },
0072         Qt::QueuedConnection);
0073     m_connectionThreadObject->moveToThread(m_connectionThread);
0074     m_connectionThread->start();
0075 
0076     m_connectionThreadObject->initConnection();
0077 }
0078 
0079 void ShadowTest::setupRegistry(Registry *registry)
0080 {
0081     connect(registry, &Registry::compositorAnnounced, this, [this, registry](quint32 name, quint32 version) {
0082         m_compositor = registry->createCompositor(name, version, this);
0083     });
0084     connect(registry, &Registry::shellAnnounced, this, [this, registry](quint32 name, quint32 version) {
0085         m_shell = registry->createShell(name, version, this);
0086     });
0087     connect(registry, &Registry::shmAnnounced, this, [this, registry](quint32 name, quint32 version) {
0088         m_shm = registry->createShmPool(name, version, this);
0089     });
0090     connect(registry, &Registry::shadowAnnounced, this, [this, registry](quint32 name, quint32 version) {
0091         m_shadowManager = registry->createShadowManager(name, version, this);
0092         m_shadowManager->setEventQueue(m_eventQueue);
0093     });
0094     connect(registry, &Registry::interfacesAnnounced, this, [this] {
0095         Q_ASSERT(m_compositor);
0096         Q_ASSERT(m_shell);
0097         Q_ASSERT(m_shm);
0098         m_surface = m_compositor->createSurface(this);
0099         Q_ASSERT(m_surface);
0100         setupShadow();
0101         m_shellSurface = m_shell->createSurface(m_surface, this);
0102         Q_ASSERT(m_shellSurface);
0103         m_shellSurface->setToplevel();
0104         connect(m_shellSurface, &ShellSurface::sizeChanged, this, &ShadowTest::render);
0105         render();
0106     });
0107     registry->setEventQueue(m_eventQueue);
0108     registry->create(m_connectionThreadObject);
0109     registry->setup();
0110 }
0111 
0112 void ShadowTest::setupShadow()
0113 {
0114     Q_ASSERT(m_shadowManager);
0115     Shadow *shadow = m_shadowManager->createShadow(m_surface, this);
0116     Q_ASSERT(shadow);
0117 
0118     auto addElement = [this](const QColor color) {
0119         const QSize size = QSize(10, 10);
0120         auto buffer = m_shm->getBuffer(size, size.width() * 4).toStrongRef();
0121         buffer->setUsed(true);
0122         QImage image(buffer->address(), size.width(), size.height(), QImage::Format_ARGB32_Premultiplied);
0123         image.fill(color);
0124         return buffer;
0125     };
0126     shadow->attachTopLeft(addElement(Qt::red));
0127     shadow->attachTop(addElement(Qt::darkRed));
0128     shadow->attachTopRight(addElement(Qt::green));
0129     shadow->attachRight(addElement(Qt::darkGreen));
0130     shadow->attachBottomRight(addElement(Qt::darkBlue));
0131     shadow->attachBottom(addElement(Qt::cyan));
0132     shadow->attachBottomLeft(addElement(Qt::darkCyan));
0133     shadow->attachLeft(addElement(Qt::magenta));
0134     shadow->setOffsets(QMarginsF(5, 5, 5, 5));
0135     shadow->commit();
0136 }
0137 
0138 void ShadowTest::render()
0139 {
0140     const QSize &size = m_shellSurface->size().isValid() ? m_shellSurface->size() : QSize(300, 200);
0141     auto buffer = m_shm->getBuffer(size, size.width() * 4).toStrongRef();
0142     buffer->setUsed(true);
0143     QImage image(buffer->address(), size.width(), size.height(), QImage::Format_ARGB32_Premultiplied);
0144     image.fill(QColor(255, 255, 255, 128));
0145 
0146     m_surface->attachBuffer(*buffer);
0147     m_surface->damage(QRect(QPoint(0, 0), size));
0148     m_surface->commit(Surface::CommitFlag::None);
0149     buffer->setUsed(false);
0150 }
0151 
0152 int main(int argc, char **argv)
0153 {
0154     QCoreApplication app(argc, argv);
0155     ShadowTest client;
0156     client.init();
0157 
0158     return app.exec();
0159 }
0160 
0161 #include "shadowtest.moc"