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 "keyboard.h" |
7 | #include "surface.h" |
8 | #include "wayland_pointer_p.h" |
9 | #include <QPointer> |
10 | // wayland |
11 | #include <wayland-client-protocol.h> |
12 | |
13 | namespace KWayland |
14 | { |
15 | namespace Client |
16 | { |
17 | class Q_DECL_HIDDEN Keyboard::Private |
18 | { |
19 | public: |
20 | Private(Keyboard *q); |
21 | void setup(wl_keyboard *k); |
22 | |
23 | WaylandPointer<wl_keyboard, wl_keyboard_release> keyboard; |
24 | QPointer<Surface> enteredSurface; |
25 | QList<quint32> enteredKeys; |
26 | |
27 | struct { |
28 | qint32 charactersPerSecond = 0; |
29 | qint32 delay = 0; |
30 | } repeatInfo; |
31 | |
32 | private: |
33 | void enter(uint32_t serial, wl_surface *surface, wl_array *keys); |
34 | void leave(uint32_t serial); |
35 | static void keymapCallback(void *data, wl_keyboard *keyboard, uint32_t format, int fd, uint32_t size); |
36 | static void enterCallback(void *data, wl_keyboard *keyboard, uint32_t serial, wl_surface *surface, wl_array *keys); |
37 | static void leaveCallback(void *data, wl_keyboard *keyboard, uint32_t serial, wl_surface *surface); |
38 | static void keyCallback(void *data, wl_keyboard *keyboard, uint32_t serial, uint32_t time, uint32_t key, uint32_t state); |
39 | static void |
40 | modifiersCallback(void *data, wl_keyboard *keyboard, uint32_t serial, uint32_t modsDepressed, uint32_t modsLatched, uint32_t modsLocked, uint32_t group); |
41 | static void repeatInfoCallback(void *data, wl_keyboard *keyboard, int32_t charactersPerSecond, int32_t delay); |
42 | Keyboard *q; |
43 | static const wl_keyboard_listener s_listener; |
44 | }; |
45 | |
46 | Keyboard::Private::Private(Keyboard *q) |
47 | : q(q) |
48 | { |
49 | } |
50 | |
51 | void Keyboard::Private::setup(wl_keyboard *k) |
52 | { |
53 | Q_ASSERT(k); |
54 | Q_ASSERT(!keyboard); |
55 | keyboard.setup(pointer: k); |
56 | wl_keyboard_add_listener(wl_keyboard: keyboard, listener: &s_listener, data: this); |
57 | } |
58 | |
59 | const wl_keyboard_listener Keyboard::Private::s_listener = {.keymap: keymapCallback, .enter: enterCallback, .leave: leaveCallback, .key: keyCallback, .modifiers: modifiersCallback, .repeat_info: repeatInfoCallback}; |
60 | |
61 | Keyboard::Keyboard(QObject *parent) |
62 | : QObject(parent) |
63 | , d(new Private(this)) |
64 | { |
65 | } |
66 | |
67 | Keyboard::~Keyboard() |
68 | { |
69 | release(); |
70 | } |
71 | |
72 | void Keyboard::release() |
73 | { |
74 | d->keyboard.release(); |
75 | } |
76 | |
77 | void Keyboard::destroy() |
78 | { |
79 | d->keyboard.destroy(); |
80 | } |
81 | |
82 | void Keyboard::setup(wl_keyboard *keyboard) |
83 | { |
84 | d->setup(keyboard); |
85 | } |
86 | |
87 | void Keyboard::Private::enterCallback(void *data, wl_keyboard *keyboard, uint32_t serial, wl_surface *surface, wl_array *keys) |
88 | { |
89 | auto k = reinterpret_cast<Private *>(data); |
90 | Q_ASSERT(k->keyboard == keyboard); |
91 | k->enter(serial, surface, keys); |
92 | } |
93 | |
94 | void Keyboard::Private::enter(uint32_t serial, wl_surface *surface, wl_array *keys) |
95 | { |
96 | enteredSurface = Surface::get(native: surface); |
97 | |
98 | enteredKeys.clear(); |
99 | for (const uint32_t &key : std::span(static_cast<uint32_t *>(keys->data), keys->size / sizeof(uint32_t))) { |
100 | enteredKeys.append(t: key); |
101 | } |
102 | |
103 | Q_EMIT q->entered(serial); |
104 | } |
105 | |
106 | void Keyboard::Private::leaveCallback(void *data, wl_keyboard *keyboard, uint32_t serial, wl_surface *surface) |
107 | { |
108 | Q_UNUSED(surface) |
109 | auto k = reinterpret_cast<Private *>(data); |
110 | Q_ASSERT(k->keyboard == keyboard); |
111 | k->leave(serial); |
112 | } |
113 | |
114 | void Keyboard::Private::leave(uint32_t serial) |
115 | { |
116 | enteredSurface.clear(); |
117 | Q_EMIT q->left(serial); |
118 | } |
119 | |
120 | void Keyboard::Private::keyCallback(void *data, wl_keyboard *keyboard, uint32_t serial, uint32_t time, uint32_t key, uint32_t state) |
121 | { |
122 | Q_UNUSED(serial) |
123 | auto k = reinterpret_cast<Keyboard::Private *>(data); |
124 | Q_ASSERT(k->keyboard == keyboard); |
125 | auto toState = [state] { |
126 | if (state == WL_KEYBOARD_KEY_STATE_RELEASED) { |
127 | return KeyState::Released; |
128 | } else { |
129 | return KeyState::Pressed; |
130 | } |
131 | }; |
132 | Q_EMIT k->q->keyChanged(key, state: toState(), time); |
133 | } |
134 | |
135 | void Keyboard::Private::keymapCallback(void *data, wl_keyboard *keyboard, uint32_t format, int fd, uint32_t size) |
136 | { |
137 | auto k = reinterpret_cast<Keyboard::Private *>(data); |
138 | Q_ASSERT(k->keyboard == keyboard); |
139 | if (format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1) { |
140 | return; |
141 | } |
142 | Q_EMIT k->q->keymapChanged(fd, size); |
143 | } |
144 | |
145 | void Keyboard::Private::modifiersCallback(void *data, |
146 | wl_keyboard *keyboard, |
147 | uint32_t serial, |
148 | uint32_t modsDepressed, |
149 | uint32_t modsLatched, |
150 | uint32_t modsLocked, |
151 | uint32_t group) |
152 | { |
153 | Q_UNUSED(serial) |
154 | auto k = reinterpret_cast<Keyboard::Private *>(data); |
155 | Q_ASSERT(k->keyboard == keyboard); |
156 | Q_EMIT k->q->modifiersChanged(depressed: modsDepressed, latched: modsLatched, locked: modsLocked, group); |
157 | } |
158 | |
159 | void Keyboard::Private::repeatInfoCallback(void *data, wl_keyboard *keyboard, int32_t charactersPerSecond, int32_t delay) |
160 | { |
161 | auto k = reinterpret_cast<Keyboard::Private *>(data); |
162 | Q_ASSERT(k->keyboard == keyboard); |
163 | k->repeatInfo.charactersPerSecond = qMax(a: charactersPerSecond, b: 0); |
164 | k->repeatInfo.delay = qMax(a: delay, b: 0); |
165 | Q_EMIT k->q->keyRepeatChanged(); |
166 | } |
167 | |
168 | Surface *Keyboard::enteredSurface() |
169 | { |
170 | return d->enteredSurface.data(); |
171 | } |
172 | |
173 | Surface *Keyboard::enteredSurface() const |
174 | { |
175 | return d->enteredSurface.data(); |
176 | } |
177 | |
178 | QList<quint32> Keyboard::enteredKeys() const |
179 | { |
180 | return d->enteredKeys; |
181 | } |
182 | |
183 | bool Keyboard::isValid() const |
184 | { |
185 | return d->keyboard.isValid(); |
186 | } |
187 | |
188 | bool Keyboard::isKeyRepeatEnabled() const |
189 | { |
190 | return d->repeatInfo.charactersPerSecond > 0; |
191 | } |
192 | |
193 | qint32 Keyboard::keyRepeatDelay() const |
194 | { |
195 | return d->repeatInfo.delay; |
196 | } |
197 | |
198 | qint32 Keyboard::keyRepeatRate() const |
199 | { |
200 | return d->repeatInfo.charactersPerSecond; |
201 | } |
202 | |
203 | Keyboard::operator wl_keyboard *() |
204 | { |
205 | return d->keyboard; |
206 | } |
207 | |
208 | Keyboard::operator wl_keyboard *() const |
209 | { |
210 | return d->keyboard; |
211 | } |
212 | |
213 | } |
214 | } |
215 | |
216 | #include "moc_keyboard.cpp" |
217 | |