1 | /* |
2 | SPDX-FileCopyrightText: 2016 Martin Gräßlin <mgraesslin@kde.org> |
3 | SPDX-FileCopyrightText: 2017 Marco Martin <mart@kde.org> |
4 | |
5 | SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL |
6 | */ |
7 | #include "../src/client/xdgforeign.h" |
8 | #include "../src/client/compositor.h" |
9 | #include "../src/client/connection_thread.h" |
10 | #include "../src/client/event_queue.h" |
11 | #include "../src/client/registry.h" |
12 | #include "../src/client/shell.h" |
13 | #include "../src/client/shm_pool.h" |
14 | #include "../src/client/xdgshell.h" |
15 | // Qt |
16 | #include <QCommandLineParser> |
17 | #include <QDebug> |
18 | #include <QGuiApplication> |
19 | #include <QImage> |
20 | #include <QThread> |
21 | using namespace KWayland::Client; |
22 | |
23 | class XdgForeignTest : public QObject |
24 | { |
25 | Q_OBJECT |
26 | public: |
27 | explicit XdgForeignTest(QObject *parent = nullptr); |
28 | ~XdgForeignTest() override; |
29 | |
30 | void init(); |
31 | |
32 | private: |
33 | void setupRegistry(Registry *registry); |
34 | void render(); |
35 | QThread *m_connectionThread; |
36 | ConnectionThread *m_connectionThreadObject; |
37 | EventQueue *m_eventQueue = nullptr; |
38 | Compositor *m_compositor = nullptr; |
39 | XdgShell *m_shell = nullptr; |
40 | XdgShellSurface *m_shellSurface = nullptr; |
41 | ShmPool *m_shm = nullptr; |
42 | Surface *m_surface = nullptr; |
43 | |
44 | XdgShellSurface *m_childShellSurface = nullptr; |
45 | Surface *m_childSurface = nullptr; |
46 | |
47 | KWayland::Client::XdgExporter *m_exporter = nullptr; |
48 | KWayland::Client::XdgImporter *m_importer = nullptr; |
49 | KWayland::Client::XdgExported *m_exported = nullptr; |
50 | KWayland::Client::XdgImported *m_imported = nullptr; |
51 | }; |
52 | |
53 | XdgForeignTest::XdgForeignTest(QObject *parent) |
54 | : QObject(parent) |
55 | , m_connectionThread(new QThread(this)) |
56 | , m_connectionThreadObject(new ConnectionThread()) |
57 | { |
58 | } |
59 | |
60 | XdgForeignTest::~XdgForeignTest() |
61 | { |
62 | m_connectionThread->quit(); |
63 | m_connectionThread->wait(); |
64 | m_connectionThreadObject->deleteLater(); |
65 | } |
66 | |
67 | void XdgForeignTest::init() |
68 | { |
69 | connect( |
70 | sender: m_connectionThreadObject, |
71 | signal: &ConnectionThread::connected, |
72 | context: this, |
73 | slot: [this] { |
74 | m_eventQueue = new EventQueue(this); |
75 | m_eventQueue->setup(m_connectionThreadObject); |
76 | |
77 | Registry *registry = new Registry(this); |
78 | setupRegistry(registry); |
79 | }, |
80 | type: Qt::QueuedConnection); |
81 | m_connectionThreadObject->moveToThread(thread: m_connectionThread); |
82 | m_connectionThread->start(); |
83 | |
84 | m_connectionThreadObject->initConnection(); |
85 | } |
86 | |
87 | void XdgForeignTest::setupRegistry(Registry *registry) |
88 | { |
89 | connect(sender: registry, signal: &Registry::compositorAnnounced, context: this, slot: [this, registry](quint32 name, quint32 version) { |
90 | m_compositor = registry->createCompositor(name, version, parent: this); |
91 | }); |
92 | connect(sender: registry, signal: &Registry::xdgShellUnstableV5Announced, context: this, slot: [this, registry](quint32 name, quint32 version) { |
93 | m_shell = registry->createXdgShell(name, version, parent: this); |
94 | }); |
95 | connect(sender: registry, signal: &Registry::shmAnnounced, context: this, slot: [this, registry](quint32 name, quint32 version) { |
96 | m_shm = registry->createShmPool(name, version, parent: this); |
97 | }); |
98 | connect(sender: registry, signal: &Registry::exporterUnstableV2Announced, context: this, slot: [this, registry](quint32 name, quint32 version) { |
99 | m_exporter = registry->createXdgExporter(name, version, parent: this); |
100 | m_exporter->setEventQueue(m_eventQueue); |
101 | }); |
102 | connect(sender: registry, signal: &Registry::importerUnstableV2Announced, context: this, slot: [this, registry](quint32 name, quint32 version) { |
103 | m_importer = registry->createXdgImporter(name, version, parent: this); |
104 | m_importer->setEventQueue(m_eventQueue); |
105 | }); |
106 | connect(sender: registry, signal: &Registry::interfacesAnnounced, context: this, slot: [this] { |
107 | Q_ASSERT(m_compositor); |
108 | Q_ASSERT(m_shell); |
109 | Q_ASSERT(m_shm); |
110 | Q_ASSERT(m_exporter); |
111 | Q_ASSERT(m_importer); |
112 | m_surface = m_compositor->createSurface(parent: this); |
113 | Q_ASSERT(m_surface); |
114 | m_shellSurface = m_shell->createSurface(surface: m_surface, parent: this); |
115 | Q_ASSERT(m_shellSurface); |
116 | connect(sender: m_shellSurface, signal: &XdgShellSurface::sizeChanged, context: this, slot: &XdgForeignTest::render); |
117 | |
118 | m_childSurface = m_compositor->createSurface(parent: this); |
119 | Q_ASSERT(m_childSurface); |
120 | m_childShellSurface = m_shell->createSurface(surface: m_childSurface, parent: this); |
121 | Q_ASSERT(m_childShellSurface); |
122 | connect(sender: m_childShellSurface, signal: &XdgShellSurface::sizeChanged, context: this, slot: &XdgForeignTest::render); |
123 | |
124 | m_exported = m_exporter->exportTopLevel(surface: m_surface, parent: this); |
125 | connect(sender: m_exported, signal: &XdgExported::done, context: this, slot: [this]() { |
126 | m_imported = m_importer->importTopLevel(handle: m_exported->handle(), parent: this); |
127 | m_imported->setParentOf(m_childSurface); |
128 | }); |
129 | render(); |
130 | }); |
131 | registry->setEventQueue(m_eventQueue); |
132 | registry->create(connection: m_connectionThreadObject); |
133 | registry->setup(); |
134 | } |
135 | |
136 | void XdgForeignTest::render() |
137 | { |
138 | QSize size = m_shellSurface->size().isValid() ? m_shellSurface->size() : QSize(500, 500); |
139 | auto buffer = m_shm->getBuffer(size, stride: size.width() * 4).toStrongRef(); |
140 | buffer->setUsed(true); |
141 | QImage image(buffer->address(), size.width(), size.height(), QImage::Format_ARGB32_Premultiplied); |
142 | image.fill(color: QColor(255, 255, 255, 255)); |
143 | |
144 | m_surface->attachBuffer(buffer: *buffer); |
145 | m_surface->damage(rect: QRect(QPoint(0, 0), size)); |
146 | m_surface->commit(flag: Surface::CommitFlag::None); |
147 | buffer->setUsed(false); |
148 | |
149 | size = m_childShellSurface->size().isValid() ? m_childShellSurface->size() : QSize(200, 200); |
150 | buffer = m_shm->getBuffer(size, stride: size.width() * 4).toStrongRef(); |
151 | buffer->setUsed(true); |
152 | image = QImage(buffer->address(), size.width(), size.height(), QImage::Format_ARGB32_Premultiplied); |
153 | image.fill(color: QColor(255, 0, 0, 255)); |
154 | |
155 | m_childSurface->attachBuffer(buffer: *buffer); |
156 | m_childSurface->damage(rect: QRect(QPoint(0, 0), size)); |
157 | m_childSurface->commit(flag: Surface::CommitFlag::None); |
158 | buffer->setUsed(false); |
159 | } |
160 | |
161 | int main(int argc, char **argv) |
162 | { |
163 | QCoreApplication app(argc, argv); |
164 | |
165 | XdgForeignTest client; |
166 | |
167 | client.init(); |
168 | |
169 | return app.exec(); |
170 | } |
171 | |
172 | #include "xdgforeigntest.moc" |
173 | |