1/*
2 SPDX-FileCopyrightText: 2016 Martin Gräßlin <mgraesslin@kde.org>
3
4 SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
5*/
6#include "../src/client/compositor.h"
7#include "../src/client/connection_thread.h"
8#include "../src/client/datadevice.h"
9#include "../src/client/datadevicemanager.h"
10#include "../src/client/dataoffer.h"
11#include "../src/client/event_queue.h"
12#include "../src/client/keyboard.h"
13#include "../src/client/registry.h"
14#include "../src/client/seat.h"
15#include "../src/client/shell.h"
16#include "../src/client/shm_pool.h"
17#include "../src/client/subcompositor.h"
18#include "../src/client/surface.h"
19// Qt
20#include <QDebug>
21#include <QFile>
22#include <QGuiApplication>
23#include <QImage>
24#include <QMimeType>
25#include <QThread>
26#include <QTimer>
27// system
28#include <unistd.h>
29
30#include <linux/input.h>
31
32using namespace KWayland::Client;
33
34class SubSurfaceTest : public QObject
35{
36 Q_OBJECT
37public:
38 explicit SubSurfaceTest(QObject *parent = nullptr);
39 ~SubSurfaceTest() override;
40
41 void init();
42
43private:
44 void setupRegistry(Registry *registry);
45 void render();
46 QThread *m_connectionThread;
47 ConnectionThread *m_connectionThreadObject;
48 EventQueue *m_eventQueue = nullptr;
49 Compositor *m_compositor = nullptr;
50 Seat *m_seat = nullptr;
51 Shell *m_shell = nullptr;
52 ShellSurface *m_shellSurface = nullptr;
53 ShmPool *m_shm = nullptr;
54 Surface *m_surface = nullptr;
55 SubCompositor *m_subCompositor = nullptr;
56};
57
58SubSurfaceTest::SubSurfaceTest(QObject *parent)
59 : QObject(parent)
60 , m_connectionThread(new QThread(this))
61 , m_connectionThreadObject(new ConnectionThread())
62{
63}
64
65SubSurfaceTest::~SubSurfaceTest()
66{
67 m_connectionThread->quit();
68 m_connectionThread->wait();
69 m_connectionThreadObject->deleteLater();
70}
71
72void SubSurfaceTest::init()
73{
74 connect(
75 sender: m_connectionThreadObject,
76 signal: &ConnectionThread::connected,
77 context: this,
78 slot: [this] {
79 m_eventQueue = new EventQueue(this);
80 m_eventQueue->setup(m_connectionThreadObject);
81
82 Registry *registry = new Registry(this);
83 setupRegistry(registry);
84 },
85 type: Qt::QueuedConnection);
86 m_connectionThreadObject->moveToThread(thread: m_connectionThread);
87 m_connectionThread->start();
88
89 m_connectionThreadObject->initConnection();
90}
91
92void SubSurfaceTest::setupRegistry(Registry *registry)
93{
94 connect(sender: registry, signal: &Registry::compositorAnnounced, context: this, slot: [this, registry](quint32 name, quint32 version) {
95 m_compositor = registry->createCompositor(name, version, parent: this);
96 });
97 connect(sender: registry, signal: &Registry::shellAnnounced, context: this, slot: [this, registry](quint32 name, quint32 version) {
98 m_shell = registry->createShell(name, version, parent: this);
99 });
100 connect(sender: registry, signal: &Registry::shmAnnounced, context: this, slot: [this, registry](quint32 name, quint32 version) {
101 m_shm = registry->createShmPool(name, version, parent: this);
102 });
103 connect(sender: registry, signal: &Registry::seatAnnounced, context: this, slot: [this, registry](quint32 name, quint32 version) {
104 m_seat = registry->createSeat(name, version, parent: this);
105 });
106 connect(sender: registry, signal: &Registry::interfacesAnnounced, context: this, slot: [this, registry] {
107 Q_ASSERT(m_compositor);
108 Q_ASSERT(m_seat);
109 Q_ASSERT(m_shell);
110 Q_ASSERT(m_shm);
111 m_surface = m_compositor->createSurface(parent: this);
112 Q_ASSERT(m_surface);
113 m_shellSurface = m_shell->createSurface(surface: m_surface, parent: this);
114 Q_ASSERT(m_shellSurface);
115 m_shellSurface->setToplevel();
116 connect(sender: m_shellSurface, signal: &ShellSurface::sizeChanged, context: this, slot: &SubSurfaceTest::render);
117
118 auto subInterface = registry->interface(interface: Registry::Interface::SubCompositor);
119 if (subInterface.name != 0) {
120 m_subCompositor = registry->createSubCompositor(name: subInterface.name, version: subInterface.version, parent: this);
121 Q_ASSERT(m_subCompositor);
122 // create the sub surface
123 auto surface = m_compositor->createSurface(parent: this);
124 Q_ASSERT(surface);
125 auto subsurface = m_subCompositor->createSubSurface(surface, parentSurface: m_surface, parent: this);
126 Q_ASSERT(subsurface);
127 QImage image(QSize(100, 100), QImage::Format_ARGB32_Premultiplied);
128 image.fill(color: Qt::red);
129 surface->attachBuffer(buffer: m_shm->createBuffer(image));
130 surface->damage(rect: QRect(0, 0, 100, 100));
131 surface->commit(flag: Surface::CommitFlag::None);
132 // and another sub-surface to the sub-surface
133 auto surface2 = m_compositor->createSurface(parent: this);
134 Q_ASSERT(surface2);
135 auto subsurface2 = m_subCompositor->createSubSurface(surface: surface2, parentSurface: surface, parent: this);
136 Q_ASSERT(subsurface2);
137 QImage green(QSize(50, 50), QImage::Format_ARGB32_Premultiplied);
138 green.fill(color: Qt::green);
139 surface2->attachBuffer(buffer: m_shm->createBuffer(image: green));
140 surface2->damage(rect: QRect(0, 0, 50, 50));
141 surface2->commit(flag: Surface::CommitFlag::None);
142 QTimer *timer = new QTimer(this);
143 connect(sender: timer, signal: &QTimer::timeout, context: surface2, slot: [surface2, this] {
144 QImage yellow(QSize(50, 50), QImage::Format_ARGB32_Premultiplied);
145 yellow.fill(color: Qt::yellow);
146 surface2->attachBuffer(buffer: m_shm->createBuffer(image: yellow));
147 surface2->damage(rect: QRect(0, 0, 50, 50));
148 surface2->commit(flag: Surface::CommitFlag::None);
149 m_surface->commit(flag: Surface::CommitFlag::None);
150 });
151 timer->setSingleShot(true);
152 timer->start(msec: 5000);
153 }
154 render();
155 });
156 registry->setEventQueue(m_eventQueue);
157 registry->create(connection: m_connectionThreadObject);
158 registry->setup();
159}
160
161void SubSurfaceTest::render()
162{
163 const QSize &size = m_shellSurface->size().isValid() ? m_shellSurface->size() : QSize(200, 200);
164 auto buffer = m_shm->getBuffer(size, stride: size.width() * 4).toStrongRef();
165 buffer->setUsed(true);
166 QImage image(buffer->address(), size.width(), size.height(), QImage::Format_ARGB32_Premultiplied);
167 image.fill(color: Qt::blue);
168
169 m_surface->attachBuffer(buffer: *buffer);
170 m_surface->damage(rect: QRect(QPoint(0, 0), size));
171 m_surface->commit(flag: Surface::CommitFlag::None);
172 buffer->setUsed(false);
173}
174
175int main(int argc, char **argv)
176{
177 QCoreApplication app(argc, argv);
178 SubSurfaceTest client;
179 client.init();
180
181 return app.exec();
182}
183
184#include "subsurfacetest.moc"
185

source code of kwayland/tests/subsurfacetest.cpp