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 "seat.h"
7#include "event_queue.h"
8#include "keyboard.h"
9#include "pointer.h"
10#include "touch.h"
11#include "wayland_pointer_p.h"
12// Wayland
13#include <wayland-client-protocol.h>
14
15namespace KWayland
16{
17namespace Client
18{
19class Q_DECL_HIDDEN Seat::Private
20{
21public:
22 Private(Seat *q);
23 void resetSeat();
24 void setup(wl_seat *seat);
25
26 WaylandPointer<wl_seat, wl_seat_destroy> seat;
27 EventQueue *queue = nullptr;
28 bool capabilityKeyboard = false;
29 bool capabilityPointer = false;
30 bool capabilityTouch = false;
31 QString name;
32
33private:
34 void setHasKeyboard(bool has);
35 void setHasPointer(bool has);
36 void setHasTouch(bool has);
37 void capabilitiesChanged(uint32_t capabilities);
38 void setName(const QString &name);
39 static void capabilitiesCallback(void *data, wl_seat *seat, uint32_t capabilities);
40 static void nameCallback(void *data, wl_seat *wl_seat, const char *name);
41
42 Seat *q;
43 static const wl_seat_listener s_listener;
44};
45
46Seat::Private::Private(Seat *q)
47 : q(q)
48{
49}
50
51void Seat::Private::setup(wl_seat *s)
52{
53 Q_ASSERT(s);
54 Q_ASSERT(!seat);
55 seat.setup(pointer: s);
56 wl_seat_add_listener(wl_seat: seat, listener: &s_listener, data: this);
57}
58
59const wl_seat_listener Seat::Private::s_listener = {.capabilities: capabilitiesCallback, .name: nameCallback};
60
61Seat::Seat(QObject *parent)
62 : QObject(parent)
63 , d(new Private(this))
64{
65}
66
67Seat::~Seat()
68{
69 release();
70}
71
72void Seat::release()
73{
74 if (!d->seat) {
75 return;
76 }
77 Q_EMIT interfaceAboutToBeReleased();
78 d->seat.release();
79 d->resetSeat();
80}
81
82void Seat::destroy()
83{
84 if (!d->seat) {
85 return;
86 }
87 Q_EMIT interfaceAboutToBeDestroyed();
88 d->seat.destroy();
89 d->resetSeat();
90}
91
92void Seat::setEventQueue(EventQueue *queue)
93{
94 d->queue = queue;
95}
96
97EventQueue *Seat::eventQueue()
98{
99 return d->queue;
100}
101
102void Seat::Private::resetSeat()
103{
104 setHasKeyboard(false);
105 setHasPointer(false);
106 setHasTouch(false);
107 setName(QString());
108}
109
110void Seat::Private::setHasKeyboard(bool has)
111{
112 if (capabilityKeyboard == has) {
113 return;
114 }
115 capabilityKeyboard = has;
116 Q_EMIT q->hasKeyboardChanged(capabilityKeyboard);
117}
118
119void Seat::Private::setHasPointer(bool has)
120{
121 if (capabilityPointer == has) {
122 return;
123 }
124 capabilityPointer = has;
125 Q_EMIT q->hasPointerChanged(capabilityPointer);
126}
127
128void Seat::Private::setHasTouch(bool has)
129{
130 if (capabilityTouch == has) {
131 return;
132 }
133 capabilityTouch = has;
134 Q_EMIT q->hasTouchChanged(capabilityTouch);
135}
136
137void Seat::setup(wl_seat *seat)
138{
139 d->setup(seat);
140}
141
142void Seat::Private::capabilitiesCallback(void *data, wl_seat *seat, uint32_t capabilities)
143{
144 auto s = reinterpret_cast<Seat::Private *>(data);
145 Q_ASSERT(s->seat == seat);
146 s->capabilitiesChanged(capabilities);
147}
148
149void Seat::Private::nameCallback(void *data, wl_seat *seat, const char *name)
150{
151 auto s = reinterpret_cast<Seat::Private *>(data);
152 Q_ASSERT(s->seat == seat);
153 s->setName(QString::fromUtf8(utf8: name));
154}
155
156void Seat::Private::capabilitiesChanged(uint32_t capabilities)
157{
158 setHasKeyboard(capabilities & WL_SEAT_CAPABILITY_KEYBOARD);
159 setHasPointer(capabilities & WL_SEAT_CAPABILITY_POINTER);
160 setHasTouch(capabilities & WL_SEAT_CAPABILITY_TOUCH);
161}
162
163Keyboard *Seat::createKeyboard(QObject *parent)
164{
165 Q_ASSERT(isValid());
166 Q_ASSERT(d->capabilityKeyboard);
167 Keyboard *k = new Keyboard(parent);
168 connect(sender: this, signal: &Seat::interfaceAboutToBeReleased, context: k, slot: &Keyboard::release);
169 connect(sender: this, signal: &Seat::interfaceAboutToBeDestroyed, context: k, slot: &Keyboard::destroy);
170 auto w = wl_seat_get_keyboard(wl_seat: d->seat);
171 if (d->queue) {
172 d->queue->addProxy(proxy: w);
173 }
174 k->setup(w);
175 return k;
176}
177
178Pointer *Seat::createPointer(QObject *parent)
179{
180 Q_ASSERT(isValid());
181 Q_ASSERT(d->capabilityPointer);
182 Pointer *p = new Pointer(parent);
183 connect(sender: this, signal: &Seat::interfaceAboutToBeReleased, context: p, slot: &Pointer::release);
184 connect(sender: this, signal: &Seat::interfaceAboutToBeDestroyed, context: p, slot: &Pointer::destroy);
185 auto w = wl_seat_get_pointer(wl_seat: d->seat);
186 if (d->queue) {
187 d->queue->addProxy(proxy: w);
188 }
189 p->setup(w);
190 return p;
191}
192
193Touch *Seat::createTouch(QObject *parent)
194{
195 Q_ASSERT(isValid());
196 Q_ASSERT(d->capabilityTouch);
197 Touch *t = new Touch(parent);
198 connect(sender: this, signal: &Seat::interfaceAboutToBeReleased, context: t, slot: &Touch::release);
199 connect(sender: this, signal: &Seat::interfaceAboutToBeDestroyed, context: t, slot: &Touch::destroy);
200 auto w = wl_seat_get_touch(wl_seat: d->seat);
201 if (d->queue) {
202 d->queue->addProxy(proxy: w);
203 }
204 t->setup(w);
205 return t;
206}
207
208void Seat::Private::setName(const QString &n)
209{
210 if (name == n) {
211 return;
212 }
213 name = n;
214 Q_EMIT q->nameChanged(name);
215}
216
217bool Seat::isValid() const
218{
219 return d->seat.isValid();
220}
221
222bool Seat::hasKeyboard() const
223{
224 return d->capabilityKeyboard;
225}
226
227bool Seat::hasPointer() const
228{
229 return d->capabilityPointer;
230}
231
232bool Seat::hasTouch() const
233{
234 return d->capabilityTouch;
235}
236
237QString Seat::name() const
238{
239 return d->name;
240}
241
242Seat::operator wl_seat *()
243{
244 return d->seat;
245}
246
247Seat::operator wl_seat *() const
248{
249 return d->seat;
250}
251
252}
253}
254
255#include "moc_seat.cpp"
256

source code of kwayland/src/client/seat.cpp