KWin
Loading...
Searching...
No Matches
keyboard.cpp
Go to the documentation of this file.
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 "clientconnection.h"
7#include "display.h"
8#include "keyboard_p.h"
9#include "seat.h"
10#include "seat_p.h"
11#include "surface.h"
12#include "utils/common.h"
13// Qt
14#include <QList>
15
16#include <unistd.h>
17
18namespace KWin
19{
24
26{
27 wl_resource_destroy(resource->handle);
28}
29
31{
32 const ClientConnection *focusedClient = focusedSurface ? focusedSurface->client() : nullptr;
33
34 if (resource->version() >= WL_KEYBOARD_REPEAT_INFO_SINCE_VERSION) {
35 send_repeat_info(resource->handle, keyRepeat.charactersPerSecond, keyRepeat.delay);
36 }
37 if (!keymap.isNull()) {
38 sendKeymap(resource);
39 }
40
41 if (focusedClient && focusedClient->client() == resource->client()) {
42 const QList<quint32> keys = pressedKeys();
43 const QByteArray keysData = QByteArray::fromRawData(reinterpret_cast<const char *>(keys.data()), sizeof(quint32) * keys.count());
44 const quint32 serial = seat->display()->nextSerial();
45
46 send_enter(resource->handle, serial, focusedSurface->resource(), keysData);
47 send_modifiers(resource->handle, serial, modifiers.depressed, modifiers.latched, modifiers.locked, modifiers.group);
48 }
49}
50
51QList<KeyboardInterfacePrivate::Resource *> KeyboardInterfacePrivate::keyboardsForClient(ClientConnection *client) const
52{
53 return resourceMap().values(client->client());
54}
55
57{
58 const QList<Resource *> keyboards = keyboardsForClient(surface->client());
59 for (Resource *keyboardResource : keyboards) {
60 send_leave(keyboardResource->handle, serial, surface->resource());
61 }
62}
63
65{
66 const auto states = pressedKeys();
67 QByteArray data = QByteArray::fromRawData(reinterpret_cast<const char *>(states.constData()), sizeof(quint32) * states.size());
68
69 const QList<Resource *> keyboards = keyboardsForClient(surface->client());
70 for (Resource *keyboardResource : keyboards) {
71 send_enter(keyboardResource->handle, serial, surface->resource(), data);
72 }
73}
74
76{
77 // From version 7 on, keymaps must be mapped privately, so that
78 // we can seal the fd and reuse it between clients.
79 if (resource->version() >= 7 && sharedKeymapFile.effectiveFlags().testFlag(RamFile::Flag::SealWrite)) {
80 send_keymap(resource->handle, keymap_format::keymap_format_xkb_v1, sharedKeymapFile.fd(), sharedKeymapFile.size());
81 // otherwise give each client its own unsealed copy.
82 } else {
83 RamFile keymapFile("kwin-xkb-keymap", keymap.constData(), keymap.size() + 1); // Include QByteArray null-terminator.
84 send_keymap(resource->handle, keymap_format::keymap_format_xkb_v1, keymapFile.fd(), keymapFile.size());
85 }
86}
87
88void KeyboardInterface::setKeymap(const QByteArray &content)
89{
90 if (content.isNull()) {
91 return;
92 }
93
94 d->keymap = content;
95 // +1 to include QByteArray null terminator.
96 d->sharedKeymapFile = RamFile("kwin-xkb-keymap-shared", content.constData(), content.size() + 1, RamFile::Flag::SealWrite);
97
98 const auto keyboardResources = d->resourceMap();
99 for (KeyboardInterfacePrivate::Resource *resource : keyboardResources) {
100 d->sendKeymap(resource);
101 }
102}
103
104void KeyboardInterfacePrivate::sendModifiers(SurfaceInterface *surface, quint32 depressed, quint32 latched, quint32 locked, quint32 group, quint32 serial)
105{
106 const QList<Resource *> keyboards = keyboardsForClient(surface->client());
107 for (Resource *keyboardResource : keyboards) {
108 send_modifiers(keyboardResource->handle, serial, depressed, latched, locked, group);
109 }
110}
111
113{
114 auto it = states.find(key);
115 if (it == states.end()) {
116 states.insert(key, state);
117 return true;
118 }
119 if (it.value() == state) {
120 return false;
121 }
122 it.value() = state;
123 return true;
124}
125
126KeyboardInterface::KeyboardInterface(SeatInterface *seat)
127 : d(new KeyboardInterfacePrivate(seat))
128{
129}
130
132
137
138void KeyboardInterface::setFocusedSurface(SurfaceInterface *surface, quint32 serial)
139{
140 if (d->focusedSurface == surface) {
141 return;
142 }
143
144 if (d->focusedSurface) {
145 d->sendLeave(d->focusedSurface, serial);
146 disconnect(d->destroyConnection);
147 }
148
149 d->focusedSurface = surface;
150 if (!d->focusedSurface) {
151 return;
152 }
153 d->destroyConnection = connect(d->focusedSurface, &SurfaceInterface::aboutToBeDestroyed, this, [this] {
154 d->sendLeave(d->focusedSurface, d->seat->display()->nextSerial());
155 d->focusedSurface = nullptr;
156 });
157
158 d->sendEnter(d->focusedSurface, serial);
159 d->sendModifiers(d->focusedSurface);
160}
161
162void KeyboardInterface::setModifierFocusSurface(SurfaceInterface *surface)
163{
164 if (d->modifierFocusSurface == surface) {
165 return;
166 }
167 d->modifierFocusSurface = surface;
168 if (d->modifierFocusSurface && d->focusedSurface != d->modifierFocusSurface) {
169 d->modifiers.serial = d->seat->display()->nextSerial();
170 d->sendModifiers(d->modifierFocusSurface);
171 }
172}
173
175{
176 QList<quint32> keys;
177 for (auto it = states.constBegin(); it != states.constEnd(); ++it) {
178 if (it.value() == KeyboardKeyState::Pressed) {
179 keys << it.key();
180 }
181 }
182 return keys;
183}
184
186{
187 const QList<KeyboardInterfacePrivate::Resource *> keyboards = d->keyboardsForClient(client);
188 const quint32 serial = d->seat->display()->nextSerial();
189 for (KeyboardInterfacePrivate::Resource *keyboardResource : keyboards) {
190 d->send_key(keyboardResource->handle, serial, d->seat->timestamp().count(), key, quint32(state));
191 }
192}
193
195{
196 if (!d->updateKey(key, state)) {
197 return;
198 }
199
200 if (!d->focusedSurface) {
201 return;
202 }
203
204 sendKey(key, state, d->focusedSurface->client());
205}
206
207void KeyboardInterface::sendModifiers(quint32 depressed, quint32 latched, quint32 locked, quint32 group)
208{
209 bool changed = false;
210 if (d->modifiers.depressed != depressed) {
211 d->modifiers.depressed = depressed;
212 changed = true;
213 }
214 if (d->modifiers.latched != latched) {
215 d->modifiers.latched = latched;
216 changed = true;
217 }
218 if (d->modifiers.locked != locked) {
219 d->modifiers.locked = locked;
220 changed = true;
221 }
222 if (d->modifiers.group != group) {
223 d->modifiers.group = group;
224 changed = true;
225 }
226 if (!changed) {
227 return;
228 }
229
230 if (d->focusedSurface) {
231 d->modifiers.serial = d->seat->display()->nextSerial();
232 d->sendModifiers(d->focusedSurface, depressed, latched, locked, group, d->modifiers.serial);
233 }
234 if (d->modifierFocusSurface && d->focusedSurface != d->modifierFocusSurface) {
235 d->modifiers.serial = d->seat->display()->nextSerial();
236 d->sendModifiers(d->modifierFocusSurface, depressed, latched, locked, group, d->modifiers.serial);
237 }
238}
239
240void KeyboardInterface::setRepeatInfo(qint32 charactersPerSecond, qint32 delay)
241{
242 d->keyRepeat.charactersPerSecond = std::max(charactersPerSecond, 0);
243 d->keyRepeat.delay = std::max(delay, 0);
244 const auto keyboards = d->resourceMap();
245 for (KeyboardInterfacePrivate::Resource *keyboardResource : keyboards) {
246 if (keyboardResource->version() >= WL_KEYBOARD_REPEAT_INFO_SINCE_VERSION) {
247 d->send_repeat_info(keyboardResource->handle, d->keyRepeat.charactersPerSecond, d->keyRepeat.delay);
248 }
249 }
250}
251
253{
254 return d->focusedSurface;
255}
256
258{
259 return d->keyRepeat.delay;
260}
261
263{
264 return d->keyRepeat.charactersPerSecond;
265}
266
267}
268
269#include "moc_keyboard.cpp"
Convenient Class which represents a wl_client.
wl_client * client() const
quint32 nextSerial()
Definition display.cpp:134
qint32 keyRepeatDelay() const
Definition keyboard.cpp:257
SurfaceInterface * focusedSurface() const
Definition keyboard.cpp:252
void sendModifiers(quint32 depressed, quint32 latched, quint32 locked, quint32 group)
Definition keyboard.cpp:207
void setRepeatInfo(qint32 charactersPerSecond, qint32 delay)
Definition keyboard.cpp:240
~KeyboardInterface() override
void sendKey(quint32 key, KeyboardKeyState state)
Definition keyboard.cpp:194
void setKeymap(const QByteArray &content)
Definition keyboard.cpp:88
qint32 keyRepeatRate() const
Definition keyboard.cpp:262
void sendModifiers(SurfaceInterface *surface)
Definition keyboard.cpp:133
void keyboard_release(Resource *resource) override
Definition keyboard.cpp:25
KeyboardInterfacePrivate(SeatInterface *s)
Definition keyboard.cpp:20
void sendKeymap(Resource *resource)
Definition keyboard.cpp:75
void sendLeave(SurfaceInterface *surface, quint32 serial)
Definition keyboard.cpp:56
void keyboard_bind_resource(Resource *resource) override
Definition keyboard.cpp:30
SurfaceInterface * focusedSurface
Definition keyboard_p.h:39
struct KWin::KeyboardInterfacePrivate::@27 keyRepeat
QList< quint32 > pressedKeys() const
Definition keyboard.cpp:174
QHash< quint32, KeyboardKeyState > states
Definition keyboard_p.h:61
void sendEnter(SurfaceInterface *surface, quint32 serial)
Definition keyboard.cpp:64
QList< Resource * > keyboardsForClient(ClientConnection *client) const
Definition keyboard.cpp:51
bool updateKey(quint32 key, KeyboardKeyState state)
Definition keyboard.cpp:112
Creates a file in memory.
Definition ramfile.h:47
int fd() const
Definition ramfile.cpp:150
@ SealWrite
Seal the file descriptor for writing.
Flags effectiveFlags() const
Definition ramfile.cpp:136
int size() const
Definition ramfile.cpp:159
Represents a Seat on the Wayland Display.
Definition seat.h:134
Display * display() const
Definition seat.cpp:424
Resource representing a wl_surface.
Definition surface.h:80
ClientConnection * client() const
Definition surface.cpp:444
wl_resource * resource() const
Definition surface.cpp:449
KeyboardKeyState
Definition seat.h:82