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
13namespace KWayland
14{
15namespace Client
16{
17class Q_DECL_HIDDEN Keyboard::Private
18{
19public:
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
32private:
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
46Keyboard::Private::Private(Keyboard *q)
47 : q(q)
48{
49}
50
51void 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
59const wl_keyboard_listener Keyboard::Private::s_listener = {.keymap: keymapCallback, .enter: enterCallback, .leave: leaveCallback, .key: keyCallback, .modifiers: modifiersCallback, .repeat_info: repeatInfoCallback};
60
61Keyboard::Keyboard(QObject *parent)
62 : QObject(parent)
63 , d(new Private(this))
64{
65}
66
67Keyboard::~Keyboard()
68{
69 release();
70}
71
72void Keyboard::release()
73{
74 d->keyboard.release();
75}
76
77void Keyboard::destroy()
78{
79 d->keyboard.destroy();
80}
81
82void Keyboard::setup(wl_keyboard *keyboard)
83{
84 d->setup(keyboard);
85}
86
87void 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
94void 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
106void 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
114void Keyboard::Private::leave(uint32_t serial)
115{
116 enteredSurface.clear();
117 Q_EMIT q->left(serial);
118}
119
120void 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
135void 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
145void 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
159void 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
168Surface *Keyboard::enteredSurface()
169{
170 return d->enteredSurface.data();
171}
172
173Surface *Keyboard::enteredSurface() const
174{
175 return d->enteredSurface.data();
176}
177
178QList<quint32> Keyboard::enteredKeys() const
179{
180 return d->enteredKeys;
181}
182
183bool Keyboard::isValid() const
184{
185 return d->keyboard.isValid();
186}
187
188bool Keyboard::isKeyRepeatEnabled() const
189{
190 return d->repeatInfo.charactersPerSecond > 0;
191}
192
193qint32 Keyboard::keyRepeatDelay() const
194{
195 return d->repeatInfo.delay;
196}
197
198qint32 Keyboard::keyRepeatRate() const
199{
200 return d->repeatInfo.charactersPerSecond;
201}
202
203Keyboard::operator wl_keyboard *()
204{
205 return d->keyboard;
206}
207
208Keyboard::operator wl_keyboard *() const
209{
210 return d->keyboard;
211}
212
213}
214}
215
216#include "moc_keyboard.cpp"
217

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