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 | |
15 | namespace KWayland |
16 | { |
17 | namespace Client |
18 | { |
19 | class Q_DECL_HIDDEN Seat::Private |
20 | { |
21 | public: |
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 | |
33 | private: |
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 | |
46 | Seat::Private::Private(Seat *q) |
47 | : q(q) |
48 | { |
49 | } |
50 | |
51 | void 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 | |
59 | const wl_seat_listener Seat::Private::s_listener = {.capabilities: capabilitiesCallback, .name: nameCallback}; |
60 | |
61 | Seat::Seat(QObject *parent) |
62 | : QObject(parent) |
63 | , d(new Private(this)) |
64 | { |
65 | } |
66 | |
67 | Seat::~Seat() |
68 | { |
69 | release(); |
70 | } |
71 | |
72 | void Seat::release() |
73 | { |
74 | if (!d->seat) { |
75 | return; |
76 | } |
77 | Q_EMIT interfaceAboutToBeReleased(); |
78 | d->seat.release(); |
79 | d->resetSeat(); |
80 | } |
81 | |
82 | void Seat::destroy() |
83 | { |
84 | if (!d->seat) { |
85 | return; |
86 | } |
87 | Q_EMIT interfaceAboutToBeDestroyed(); |
88 | d->seat.destroy(); |
89 | d->resetSeat(); |
90 | } |
91 | |
92 | void Seat::setEventQueue(EventQueue *queue) |
93 | { |
94 | d->queue = queue; |
95 | } |
96 | |
97 | EventQueue *Seat::eventQueue() |
98 | { |
99 | return d->queue; |
100 | } |
101 | |
102 | void Seat::Private::resetSeat() |
103 | { |
104 | setHasKeyboard(false); |
105 | setHasPointer(false); |
106 | setHasTouch(false); |
107 | setName(QString()); |
108 | } |
109 | |
110 | void Seat::Private::setHasKeyboard(bool has) |
111 | { |
112 | if (capabilityKeyboard == has) { |
113 | return; |
114 | } |
115 | capabilityKeyboard = has; |
116 | Q_EMIT q->hasKeyboardChanged(capabilityKeyboard); |
117 | } |
118 | |
119 | void Seat::Private::setHasPointer(bool has) |
120 | { |
121 | if (capabilityPointer == has) { |
122 | return; |
123 | } |
124 | capabilityPointer = has; |
125 | Q_EMIT q->hasPointerChanged(capabilityPointer); |
126 | } |
127 | |
128 | void Seat::Private::setHasTouch(bool has) |
129 | { |
130 | if (capabilityTouch == has) { |
131 | return; |
132 | } |
133 | capabilityTouch = has; |
134 | Q_EMIT q->hasTouchChanged(capabilityTouch); |
135 | } |
136 | |
137 | void Seat::setup(wl_seat *seat) |
138 | { |
139 | d->setup(seat); |
140 | } |
141 | |
142 | void 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 | |
149 | void 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 | |
156 | void 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 | |
163 | Keyboard *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 | |
178 | Pointer *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 | |
193 | Touch *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 | |
208 | void 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 | |
217 | bool Seat::isValid() const |
218 | { |
219 | return d->seat.isValid(); |
220 | } |
221 | |
222 | bool Seat::hasKeyboard() const |
223 | { |
224 | return d->capabilityKeyboard; |
225 | } |
226 | |
227 | bool Seat::hasPointer() const |
228 | { |
229 | return d->capabilityPointer; |
230 | } |
231 | |
232 | bool Seat::hasTouch() const |
233 | { |
234 | return d->capabilityTouch; |
235 | } |
236 | |
237 | QString Seat::name() const |
238 | { |
239 | return d->name; |
240 | } |
241 | |
242 | Seat::operator wl_seat *() |
243 | { |
244 | return d->seat; |
245 | } |
246 | |
247 | Seat::operator wl_seat *() const |
248 | { |
249 | return d->seat; |
250 | } |
251 | |
252 | } |
253 | } |
254 | |
255 | #include "moc_seat.cpp" |
256 | |