1 | /* |
2 | SPDX-FileCopyrightText: 2014 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/datasource.h" |
11 | #include "../src/client/event_queue.h" |
12 | #include "../src/client/keyboard.h" |
13 | #include "../src/client/pointer.h" |
14 | #include "../src/client/registry.h" |
15 | #include "../src/client/seat.h" |
16 | #include "../src/client/shell.h" |
17 | #include "../src/client/shm_pool.h" |
18 | #include "../src/client/surface.h" |
19 | // Qt |
20 | #include <QCoreApplication> |
21 | #include <QDebug> |
22 | #include <QFile> |
23 | #include <QImage> |
24 | #include <QThread> |
25 | |
26 | using namespace KWayland::Client; |
27 | |
28 | class CopyClient : public QObject |
29 | { |
30 | Q_OBJECT |
31 | public: |
32 | explicit CopyClient(QObject *parent = nullptr); |
33 | ~CopyClient() override; |
34 | |
35 | void init(); |
36 | |
37 | private: |
38 | void setupRegistry(Registry *registry); |
39 | void render(); |
40 | void copy(const QString &mimeType, qint32 fd); |
41 | QThread *m_connectionThread; |
42 | ConnectionThread *m_connectionThreadObject; |
43 | EventQueue *m_eventQueue = nullptr; |
44 | Compositor *m_compositor = nullptr; |
45 | DataDeviceManager *m_dataDeviceManager = nullptr; |
46 | DataDevice *m_dataDevice = nullptr; |
47 | DataSource *m_copySource = nullptr; |
48 | Seat *m_seat = nullptr; |
49 | Shell *m_shell = nullptr; |
50 | ShellSurface *m_shellSurface = nullptr; |
51 | ShmPool *m_shm = nullptr; |
52 | Surface *m_surface = nullptr; |
53 | }; |
54 | |
55 | CopyClient::CopyClient(QObject *parent) |
56 | : QObject(parent) |
57 | , m_connectionThread(new QThread(this)) |
58 | , m_connectionThreadObject(new ConnectionThread()) |
59 | { |
60 | } |
61 | |
62 | CopyClient::~CopyClient() |
63 | { |
64 | m_connectionThread->quit(); |
65 | m_connectionThread->wait(); |
66 | m_connectionThreadObject->deleteLater(); |
67 | } |
68 | |
69 | void CopyClient::init() |
70 | { |
71 | connect( |
72 | sender: m_connectionThreadObject, |
73 | signal: &ConnectionThread::connected, |
74 | context: this, |
75 | slot: [this] { |
76 | m_eventQueue = new EventQueue(this); |
77 | m_eventQueue->setup(m_connectionThreadObject); |
78 | |
79 | Registry *registry = new Registry(this); |
80 | setupRegistry(registry); |
81 | }, |
82 | type: Qt::QueuedConnection); |
83 | m_connectionThreadObject->moveToThread(thread: m_connectionThread); |
84 | m_connectionThread->start(); |
85 | |
86 | m_connectionThreadObject->initConnection(); |
87 | } |
88 | |
89 | void CopyClient::setupRegistry(Registry *registry) |
90 | { |
91 | connect(sender: registry, signal: &Registry::compositorAnnounced, context: this, slot: [this, registry](quint32 name, quint32 version) { |
92 | m_compositor = registry->createCompositor(name, version, parent: this); |
93 | }); |
94 | connect(sender: registry, signal: &Registry::shellAnnounced, context: this, slot: [this, registry](quint32 name, quint32 version) { |
95 | m_shell = registry->createShell(name, version, parent: this); |
96 | }); |
97 | connect(sender: registry, signal: &Registry::shmAnnounced, context: this, slot: [this, registry](quint32 name, quint32 version) { |
98 | m_shm = registry->createShmPool(name, version, parent: this); |
99 | }); |
100 | connect(sender: registry, signal: &Registry::seatAnnounced, context: this, slot: [this, registry](quint32 name, quint32 version) { |
101 | m_seat = registry->createSeat(name, version, parent: this); |
102 | connect(sender: m_seat, signal: &Seat::hasPointerChanged, context: this, slot: [this] { |
103 | auto p = m_seat->createPointer(parent: this); |
104 | connect(sender: p, signal: &Pointer::entered, context: this, slot: [this](quint32 serial) { |
105 | if (m_copySource) { |
106 | m_dataDevice->setSelection(serial, source: m_copySource); |
107 | } |
108 | }); |
109 | }); |
110 | }); |
111 | connect(sender: registry, signal: &Registry::dataDeviceManagerAnnounced, context: this, slot: [this, registry](quint32 name, quint32 version) { |
112 | m_dataDeviceManager = registry->createDataDeviceManager(name, version, parent: this); |
113 | }); |
114 | connect(sender: registry, signal: &Registry::interfacesAnnounced, context: this, slot: [this] { |
115 | Q_ASSERT(m_compositor); |
116 | Q_ASSERT(m_dataDeviceManager); |
117 | Q_ASSERT(m_seat); |
118 | Q_ASSERT(m_shell); |
119 | Q_ASSERT(m_shm); |
120 | m_surface = m_compositor->createSurface(parent: this); |
121 | Q_ASSERT(m_surface); |
122 | m_shellSurface = m_shell->createSurface(surface: m_surface, parent: this); |
123 | Q_ASSERT(m_shellSurface); |
124 | m_shellSurface->setFullscreen(); |
125 | connect(sender: m_shellSurface, signal: &ShellSurface::sizeChanged, context: this, slot: &CopyClient::render); |
126 | |
127 | m_dataDevice = m_dataDeviceManager->getDataDevice(seat: m_seat, parent: this); |
128 | m_copySource = m_dataDeviceManager->createDataSource(parent: this); |
129 | m_copySource->offer(QStringLiteral("text/plain" )); |
130 | connect(sender: m_copySource, signal: &DataSource::sendDataRequested, context: this, slot: &CopyClient::copy); |
131 | }); |
132 | registry->setEventQueue(m_eventQueue); |
133 | registry->create(connection: m_connectionThreadObject); |
134 | registry->setup(); |
135 | } |
136 | |
137 | void CopyClient::render() |
138 | { |
139 | const QSize &size = m_shellSurface->size(); |
140 | auto buffer = m_shm->getBuffer(size, stride: size.width() * 4).toStrongRef(); |
141 | buffer->setUsed(true); |
142 | QImage image(buffer->address(), size.width(), size.height(), QImage::Format_ARGB32_Premultiplied); |
143 | image.fill(color: Qt::green); |
144 | |
145 | m_surface->attachBuffer(buffer: *buffer); |
146 | m_surface->damage(rect: QRect(QPoint(0, 0), size)); |
147 | m_surface->commit(flag: Surface::CommitFlag::None); |
148 | buffer->setUsed(false); |
149 | } |
150 | |
151 | void CopyClient::copy(const QString &mimeType, qint32 fd) |
152 | { |
153 | qDebug() << "Requested to copy for mimeType" << mimeType; |
154 | QFile c; |
155 | if (c.open(fd, ioFlags: QFile::WriteOnly, handleFlags: QFile::AutoCloseHandle)) { |
156 | c.write(QByteArrayLiteral("foo" )); |
157 | c.close(); |
158 | qDebug() << "Copied foo" ; |
159 | } |
160 | } |
161 | |
162 | int main(int argc, char **argv) |
163 | { |
164 | QCoreApplication app(argc, argv); |
165 | CopyClient client; |
166 | client.init(); |
167 | |
168 | return app.exec(); |
169 | } |
170 | |
171 | #include "copyclient.moc" |
172 | |