1/*
2 SPDX-FileCopyrightText: 2015 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/shadow.h"
7#include "../src/client/compositor.h"
8#include "../src/client/connection_thread.h"
9#include "../src/client/event_queue.h"
10#include "../src/client/registry.h"
11#include "../src/client/shell.h"
12#include "../src/client/shm_pool.h"
13#include "../src/client/surface.h"
14// Qt
15#include <QGuiApplication>
16#include <QImage>
17#include <QThread>
18
19using namespace KWayland::Client;
20
21class ShadowTest : public QObject
22{
23 Q_OBJECT
24public:
25 explicit ShadowTest(QObject *parent = nullptr);
26 ~ShadowTest() override;
27
28 void init();
29
30private:
31 void setupRegistry(Registry *registry);
32 void setupShadow();
33 void render();
34 QThread *m_connectionThread;
35 ConnectionThread *m_connectionThreadObject;
36 EventQueue *m_eventQueue = nullptr;
37 Compositor *m_compositor = nullptr;
38 Shell *m_shell = nullptr;
39 ShellSurface *m_shellSurface = nullptr;
40 ShmPool *m_shm = nullptr;
41 Surface *m_surface = nullptr;
42 ShadowManager *m_shadowManager = nullptr;
43};
44
45ShadowTest::ShadowTest(QObject *parent)
46 : QObject(parent)
47 , m_connectionThread(new QThread(this))
48 , m_connectionThreadObject(new ConnectionThread())
49{
50}
51
52ShadowTest::~ShadowTest()
53{
54 m_connectionThread->quit();
55 m_connectionThread->wait();
56 m_connectionThreadObject->deleteLater();
57}
58
59void ShadowTest::init()
60{
61 connect(
62 sender: m_connectionThreadObject,
63 signal: &ConnectionThread::connected,
64 context: this,
65 slot: [this] {
66 m_eventQueue = new EventQueue(this);
67 m_eventQueue->setup(m_connectionThreadObject);
68
69 Registry *registry = new Registry(this);
70 setupRegistry(registry);
71 },
72 type: Qt::QueuedConnection);
73 m_connectionThreadObject->moveToThread(thread: m_connectionThread);
74 m_connectionThread->start();
75
76 m_connectionThreadObject->initConnection();
77}
78
79void ShadowTest::setupRegistry(Registry *registry)
80{
81 connect(sender: registry, signal: &Registry::compositorAnnounced, context: this, slot: [this, registry](quint32 name, quint32 version) {
82 m_compositor = registry->createCompositor(name, version, parent: this);
83 });
84 connect(sender: registry, signal: &Registry::shellAnnounced, context: this, slot: [this, registry](quint32 name, quint32 version) {
85 m_shell = registry->createShell(name, version, parent: this);
86 });
87 connect(sender: registry, signal: &Registry::shmAnnounced, context: this, slot: [this, registry](quint32 name, quint32 version) {
88 m_shm = registry->createShmPool(name, version, parent: this);
89 });
90 connect(sender: registry, signal: &Registry::shadowAnnounced, context: this, slot: [this, registry](quint32 name, quint32 version) {
91 m_shadowManager = registry->createShadowManager(name, version, parent: this);
92 m_shadowManager->setEventQueue(m_eventQueue);
93 });
94 connect(sender: registry, signal: &Registry::interfacesAnnounced, context: this, slot: [this] {
95 Q_ASSERT(m_compositor);
96 Q_ASSERT(m_shell);
97 Q_ASSERT(m_shm);
98 m_surface = m_compositor->createSurface(parent: this);
99 Q_ASSERT(m_surface);
100 setupShadow();
101 m_shellSurface = m_shell->createSurface(surface: m_surface, parent: this);
102 Q_ASSERT(m_shellSurface);
103 m_shellSurface->setToplevel();
104 connect(sender: m_shellSurface, signal: &ShellSurface::sizeChanged, context: this, slot: &ShadowTest::render);
105 render();
106 });
107 registry->setEventQueue(m_eventQueue);
108 registry->create(connection: m_connectionThreadObject);
109 registry->setup();
110}
111
112void ShadowTest::setupShadow()
113{
114 Q_ASSERT(m_shadowManager);
115 Shadow *shadow = m_shadowManager->createShadow(surface: m_surface, parent: this);
116 Q_ASSERT(shadow);
117
118 auto addElement = [this](const QColor color) {
119 const QSize size = QSize(10, 10);
120 auto buffer = m_shm->getBuffer(size, stride: size.width() * 4).toStrongRef();
121 buffer->setUsed(true);
122 QImage image(buffer->address(), size.width(), size.height(), QImage::Format_ARGB32_Premultiplied);
123 image.fill(color);
124 return buffer;
125 };
126 shadow->attachTopLeft(buffer: addElement(Qt::red));
127 shadow->attachTop(buffer: addElement(Qt::darkRed));
128 shadow->attachTopRight(buffer: addElement(Qt::green));
129 shadow->attachRight(buffer: addElement(Qt::darkGreen));
130 shadow->attachBottomRight(buffer: addElement(Qt::darkBlue));
131 shadow->attachBottom(buffer: addElement(Qt::cyan));
132 shadow->attachBottomLeft(buffer: addElement(Qt::darkCyan));
133 shadow->attachLeft(buffer: addElement(Qt::magenta));
134 shadow->setOffsets(QMarginsF(5, 5, 5, 5));
135 shadow->commit();
136}
137
138void ShadowTest::render()
139{
140 const QSize &size = m_shellSurface->size().isValid() ? m_shellSurface->size() : QSize(300, 200);
141 auto buffer = m_shm->getBuffer(size, stride: size.width() * 4).toStrongRef();
142 buffer->setUsed(true);
143 QImage image(buffer->address(), size.width(), size.height(), QImage::Format_ARGB32_Premultiplied);
144 image.fill(color: QColor(255, 255, 255, 128));
145
146 m_surface->attachBuffer(buffer: *buffer);
147 m_surface->damage(rect: QRect(QPoint(0, 0), size));
148 m_surface->commit(flag: Surface::CommitFlag::None);
149 buffer->setUsed(false);
150}
151
152int main(int argc, char **argv)
153{
154 QCoreApplication app(argc, argv);
155 ShadowTest client;
156 client.init();
157
158 return app.exec();
159}
160
161#include "shadowtest.moc"
162

source code of kwayland/tests/shadowtest.cpp