KWaylandServer

keyboard_interface.cpp
1 /*
2  SPDX-FileCopyrightText: 2014 Martin Gräßlin <[email protected]>
3 
4  SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
5 */
6 #include "keyboard_interface_p.h"
7 #include "display.h"
8 #include "logging.h"
9 #include "seat_interface.h"
10 #include "seat_interface_p.h"
11 #include "surface_interface.h"
12 #include "compositor_interface.h"
13 // Qt
14 #include <QTemporaryFile>
15 #include <QVector>
16 
17 #include <unistd.h>
18 
19 namespace KWaylandServer
20 {
21 
22 KeyboardInterfacePrivate::KeyboardInterfacePrivate(SeatInterface *s)
23  : seat(s)
24 {
25 }
26 
27 void KeyboardInterfacePrivate::keyboard_bind_resource(Resource *resource)
28 {
29  const ClientConnection *focusedClient = focusedSurface ? focusedSurface->client() : nullptr;
30 
31  if (resource->version() >= WL_KEYBOARD_REPEAT_INFO_SINCE_VERSION) {
32  send_repeat_info(resource->handle, keyRepeat.charactersPerSecond, keyRepeat.delay);
33  }
34  if (!keymap.isNull()) {
35  send_keymap(resource->handle, keymap_format::keymap_format_xkb_v1, keymap->handle(), keymap->size());
36  }
37 
38  if (focusedClient && focusedClient->client() == resource->client()) {
39  const QVector<quint32> keys = pressedKeys();
40  const QByteArray keysData = QByteArray::fromRawData(reinterpret_cast<const char *>(keys.data()),
41  sizeof(quint32) * keys.count());
42  const quint32 serial = seat->display()->nextSerial();
43 
44  send_enter(resource->handle, serial, focusedSurface->resource(), keysData);
45  send_modifiers(resource->handle, serial, modifiers.depressed, modifiers.latched,
46  modifiers.locked, modifiers.group);
47  }
48 }
49 
50 QList<KeyboardInterfacePrivate::Resource *> KeyboardInterfacePrivate::keyboardsForClient(ClientConnection *client) const
51 {
52  return resourceMap().values(client->client());
53 }
54 
55 void KeyboardInterfacePrivate::focusChildSurface(SurfaceInterface *childSurface, quint32 serial)
56 {
57  if (focusedChildSurface == childSurface) {
58  return;
59  }
60  sendLeave(focusedChildSurface.data(), serial);
61  focusedChildSurface = QPointer<SurfaceInterface>(childSurface);
62  sendEnter(focusedChildSurface.data(), serial);
63 }
64 
65 void KeyboardInterfacePrivate::sendLeave(SurfaceInterface *surface, quint32 serial)
66 {
67  if (!surface) {
68  return;
69  }
70  const QList<Resource *> keyboards = keyboardsForClient(surface->client());
71  for (Resource *keyboardResource : keyboards) {
72  send_leave(keyboardResource->handle, serial, surface->resource());
73  }
74 }
75 
76 void KeyboardInterfacePrivate::sendEnter(SurfaceInterface *surface, quint32 serial)
77 {
78  if (!surface) {
79  return;
80  }
81  const auto states = pressedKeys();
83  reinterpret_cast<const char*>(states.constData()),
84  sizeof(quint32) * states.size()
85  );
86 
87  const QList<Resource *> keyboards = keyboardsForClient(surface->client());
88  for (Resource *keyboardResource : keyboards) {
89  send_enter(keyboardResource->handle, serial, surface->resource(), data);
90  }
91 
92  sendModifiers();
93 }
94 
95 void KeyboardInterface::setKeymap(const QByteArray &content)
96 {
97  if (content.isNull()) {
98  return;
99  }
101  if (!tmp->open()) {
102  return;
103  }
104  unlink(tmp->fileName().toUtf8().constData());
105  if (!tmp->resize(content.size())) {
106  return;
107  }
108  uchar *address = tmp->map(0, content.size());
109  if (!address) {
110  return;
111  }
112  if (qstrncpy(reinterpret_cast<char*>(address), content.constData(), content.size() + 1) == nullptr) {
113  return;
114  }
115  tmp->unmap(address);
116 
117  d->sendKeymap(tmp->handle(), content.size());
118  d->keymap.swap(tmp);
119 }
120 
121 void KeyboardInterfacePrivate::sendKeymap(int fd, quint32 size)
122 {
123  const QList<Resource *> keyboards = resourceMap().values();
124  for (Resource *keyboardResource : keyboards) {
125  send_keymap(keyboardResource->handle, keymap_format::keymap_format_xkb_v1, fd, size);
126  }
127 }
128 
129 void KeyboardInterfacePrivate::sendModifiers(quint32 depressed, quint32 latched, quint32 locked, quint32 group, quint32 serial)
130 {
131  if (!focusedSurface) {
132  return;
133  }
134  const QList<Resource *> keyboards = keyboardsForClient(focusedSurface->client());
135  for (Resource *keyboardResource : keyboards) {
136  send_modifiers(keyboardResource->handle, serial, depressed, latched, locked, group);
137  }
138 }
139 
140 bool KeyboardInterfacePrivate::updateKey(quint32 key, State state)
141 {
142  auto it = states.find(key);
143  if (it == states.end()) {
144  states.insert(key, state);
145  return true;
146  }
147  if (it.value() == state) {
148  return false;
149  }
150  it.value() = state;
151  return true;
152 }
153 
154 KeyboardInterface::KeyboardInterface(SeatInterface *seat)
155  : d(new KeyboardInterfacePrivate(seat))
156 {
157 }
158 
159 KeyboardInterface::~KeyboardInterface() = default;
160 
161 void KeyboardInterfacePrivate::sendModifiers()
162 {
163  sendModifiers(modifiers.depressed, modifiers.latched, modifiers.locked, modifiers.group, modifiers.serial);
164 }
165 
166 void KeyboardInterface::setFocusedSurface(SurfaceInterface *surface, quint32 serial)
167 {
168  if (d->focusedSurface == surface) {
169  return;
170  }
171 
172  d->sendLeave(d->focusedChildSurface, serial);
173  disconnect(d->destroyConnection);
174  d->focusedChildSurface.clear();
175  d->focusedSurface = surface;
176  if (!d->focusedSurface) {
177  return;
178  }
179  d->destroyConnection = connect(d->focusedSurface, &SurfaceInterface::aboutToBeDestroyed, this,
180  [this] {
181  CompositorInterface *compositor = d->focusedChildSurface->compositor();
182  d->sendLeave(d->focusedChildSurface.data(), compositor->display()->nextSerial());
183  d->focusedSurface = nullptr;
184  d->focusedChildSurface.clear();
185  }
186  );
187  d->focusedChildSurface = QPointer<SurfaceInterface>(surface);
188 
189  d->sendEnter(d->focusedSurface, serial);
190 }
191 
192 QVector<quint32> KeyboardInterfacePrivate::pressedKeys() const
193 {
194  QVector<quint32> keys;
195  for (auto it = states.constBegin(); it != states.constEnd(); ++it) {
196  if (it.value() == State::Pressed) {
197  keys << it.key();
198  }
199  }
200  return keys;
201 }
202 
203 
204 void KeyboardInterface::keyPressed(quint32 key)
205 {
206  if (!d->focusedSurface) {
207  return;
208  }
209 
210  if (!d->updateKey(key, KeyboardInterfacePrivate::State::Pressed)) {
211  return;
212  }
213 
214  const QList<KeyboardInterfacePrivate::Resource *> keyboards = d->keyboardsForClient(d->focusedSurface->client());
215  const quint32 serial = d->seat->d_func()->nextSerial();
216  for (KeyboardInterfacePrivate::Resource *keyboardResource : keyboards) {
217  d->send_key(keyboardResource->handle, serial, d->seat->timestamp(), key, KeyboardInterfacePrivate::key_state::key_state_pressed);
218  }
219 }
220 
221 void KeyboardInterface::keyReleased(quint32 key)
222 {
223  if (!d->focusedSurface) {
224  return;
225  }
226 
227  if (!d->updateKey(key, KeyboardInterfacePrivate::State::Released)) {
228  return;
229  }
230 
231  const QList<KeyboardInterfacePrivate::Resource *> keyboards = d->keyboardsForClient(d->focusedSurface->client());
232  const quint32 serial = d->seat->d_func()->nextSerial();
233  for (KeyboardInterfacePrivate::Resource *keyboardResource : keyboards) {
234  d->send_key(keyboardResource->handle, serial, d->seat->timestamp(), key, KeyboardInterfacePrivate::key_state::key_state_released);
235  }
236 }
237 
238 void KeyboardInterface::updateModifiers(quint32 depressed, quint32 latched, quint32 locked, quint32 group)
239 {
240  bool changed = false;
241 #define UPDATE( value ) \
242  if (d->modifiers.value != value) { \
243  d->modifiers.value = value; \
244  changed = true; \
245  }
246  UPDATE(depressed)
247  UPDATE(latched)
248  UPDATE(locked)
249  UPDATE(group)
250  if (!changed) {
251  return;
252  }
253 
254  if (!d->focusedSurface) {
255  return;
256  }
257 
258  d->modifiers.serial = d->seat->d_func()->nextSerial();
259  d->sendModifiers(depressed, latched, locked, group, d->modifiers.serial);
260 }
261 
262 void KeyboardInterface::setRepeatInfo(qint32 charactersPerSecond, qint32 delay)
263 {
264  d->keyRepeat.charactersPerSecond = qMax(charactersPerSecond, 0);
265  d->keyRepeat.delay = qMax(delay, 0);
266  const QList<KeyboardInterfacePrivate::Resource *> keyboards = d->resourceMap().values();
267  for (KeyboardInterfacePrivate::Resource *keyboardResource : keyboards) {
268  if (keyboardResource->version() >= WL_KEYBOARD_REPEAT_INFO_SINCE_VERSION) {
269  d->send_repeat_info(keyboardResource->handle, d->keyRepeat.charactersPerSecond, d->keyRepeat.delay);
270  }
271  }
272 }
273 
275 {
276  return d->focusedSurface;
277 }
278 
280 {
281  return d->keyRepeat.delay;
282 }
283 
285 {
286  return d->keyRepeat.charactersPerSecond;
287 }
288 
289 }
void swap(QScopedPointer< T, Cleanup > &other)
void setRepeatInfo(qint32 charactersPerSecond, qint32 delay)
Sets the key repeat information to be forwarded to all bound keyboards.
bool isNull() const const
QByteArray fromRawData(const char *data, int size)
bool disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *method)
T * data()
PostalAddress address(const QVariant &location)
const char * constData() const const
SurfaceInterface * focusedSurface() const
int count(const T &value) const const
Resource representing a wl_surface.
int size() const const
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
void aboutToBeDestroyed()
This signal is emitted when the underlying wl_surface resource is about to be freed.
This file is part of the KDE documentation.
Documentation copyright © 1996-2021 The KDE developers.
Generated on Tue Mar 2 2021 02:42:43 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.