Directory: | ./ |
---|---|
File: | server/keyboard.cpp |
Date: | 2024-01-22 17:25:27 |
Exec | Total | Coverage | |
---|---|---|---|
Lines: | 77 | 78 | 98.7% |
Branches: | 19 | 34 | 55.9% |
Line | Branch | Exec | Source |
---|---|---|---|
1 | /******************************************************************** | ||
2 | Copyright © 2020 Roman Gilg <subdiff@gmail.com> | ||
3 | |||
4 | This library is free software; you can redistribute it and/or | ||
5 | modify it under the terms of the GNU Lesser General Public | ||
6 | License as published by the Free Software Foundation; either | ||
7 | version 2.1 of the License, or (at your option) version 3, or any | ||
8 | later version accepted by the membership of KDE e.V. (or its | ||
9 | successor approved by the membership of KDE e.V.), which shall | ||
10 | act as a proxy defined in Section 6 of version 3 of the license. | ||
11 | |||
12 | This library is distributed in the hope that it will be useful, | ||
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
15 | Lesser General Public License for more details. | ||
16 | |||
17 | You should have received a copy of the GNU Lesser General Public | ||
18 | License along with this library. If not, see <http://www.gnu.org/licenses/>. | ||
19 | *********************************************************************/ | ||
20 | #include "keyboard.h" | ||
21 | #include "keyboard_p.h" | ||
22 | |||
23 | #include "client.h" | ||
24 | #include "display.h" | ||
25 | #include "seat.h" | ||
26 | #include "surface.h" | ||
27 | #include "surface_p.h" | ||
28 | |||
29 | #include <QVector> | ||
30 | #include <cstring> | ||
31 | |||
32 | #include <wayland-server.h> | ||
33 | |||
34 | namespace Wrapland::Server | ||
35 | { | ||
36 | |||
37 |
2/4✓ Branch 0 taken 49 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 49 times.
✗ Branch 3 not taken.
|
98 | Keyboard::Private::Private(Client* client, |
38 | uint32_t version, | ||
39 | uint32_t id, | ||
40 | Seat* _seat, | ||
41 | Keyboard* q_ptr) | ||
42 | 49 | : Wayland::Resource<Keyboard>(client, version, id, &wl_keyboard_interface, &s_interface, q_ptr) | |
43 | 49 | , seat(_seat) | |
44 | 49 | , q_ptr{q_ptr} | |
45 | 49 | { | |
46 | 49 | } | |
47 | |||
48 | const struct wl_keyboard_interface Keyboard::Private::s_interface { | ||
49 | destroyCallback, | ||
50 | }; | ||
51 | |||
52 | 71 | void Keyboard::Private::sendLeave(quint32 serial, Surface* surface) | |
53 | { | ||
54 |
3/4✓ Branch 0 taken 13 times.
✓ Branch 1 taken 58 times.
✓ Branch 2 taken 13 times.
✗ Branch 3 not taken.
|
71 | if (surface && surface->d_ptr->resource) { |
55 | 13 | send<wl_keyboard_send_leave>(serial, surface->d_ptr->resource); | |
56 | 13 | } | |
57 | 71 | } | |
58 | |||
59 | 58 | void Keyboard::Private::sendEnter(quint32 serial, Surface* surface) | |
60 | { | ||
61 | wl_array keys; | ||
62 | 58 | wl_array_init(&keys); | |
63 | 58 | auto const& states = seat->keyboards().pressed_keys(); | |
64 |
2/2✓ Branch 0 taken 58 times.
✓ Branch 1 taken 3 times.
|
61 | for (auto const btn : states) { |
65 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | auto key = static_cast<uint32_t*>(wl_array_add(&keys, sizeof(uint32_t))); |
66 | 3 | *key = btn; | |
67 | } | ||
68 |
1/2✓ Branch 0 taken 58 times.
✗ Branch 1 not taken.
|
58 | send<wl_keyboard_send_enter>(serial, surface->d_ptr->resource, &keys); |
69 |
1/2✓ Branch 0 taken 58 times.
✗ Branch 1 not taken.
|
58 | wl_array_release(&keys); |
70 | |||
71 |
1/2✓ Branch 0 taken 58 times.
✗ Branch 1 not taken.
|
58 | sendModifiers(); |
72 | 58 | } | |
73 | 49 | ||
74 | 2 | void Keyboard::Private::sendKeymap(int fd, quint32 size) | |
75 | { | ||
76 | 2 | send<wl_keyboard_send_keymap>(WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1, fd, size); | |
77 | 51 | } | |
78 | |||
79 | 59 | void Keyboard::Private::sendModifiers(quint32 serial, | |
80 | quint32 depressed, | ||
81 | quint32 latched, | ||
82 | quint32 locked, | ||
83 | quint32 group) | ||
84 | { | ||
85 | 59 | send<wl_keyboard_send_modifiers>(serial, depressed, latched, locked, group); | |
86 | 59 | } | |
87 | |||
88 | 58 | void Keyboard::Private::sendModifiers() | |
89 | { | ||
90 | 58 | auto const mods = seat->keyboards().get_modifiers(); | |
91 | 58 | sendModifiers(mods.serial, mods.depressed, mods.latched, mods.locked, mods.group); | |
92 | 58 | } | |
93 | |||
94 | 49 | Keyboard::Keyboard(Client* client, uint32_t version, uint32_t id, Seat* seat) | |
95 | 49 | : QObject(nullptr) | |
96 |
2/4✓ Branch 0 taken 49 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 49 times.
✗ Branch 3 not taken.
|
49 | , d_ptr(new Private(client, version, id, seat, this)) |
97 | 49 | { | |
98 |
1/2✓ Branch 0 taken 49 times.
✗ Branch 1 not taken.
|
95 | connect(client, &Client::disconnected, this, [this] { disconnect(d_ptr->destroyConnection); }); |
99 | 49 | } | |
100 | |||
101 | 2 | void Keyboard::setKeymap(char const* content) | |
102 | { | ||
103 | 2 | auto tmpf = std::tmpfile(); | |
104 | |||
105 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | if (auto rc = std::fputs(content, tmpf); rc < 0) { |
106 | ✗ | qCWarning(WRAPLAND_SERVER, "Failed to set keyboard keymap with %d.", rc); | |
107 | // TODO(romangg): Handle error by closing file here and returning? | ||
108 | } | ||
109 | |||
110 | 2 | std::rewind(tmpf); | |
111 | 2 | d_ptr->sendKeymap(fileno(tmpf), strlen(content)); | |
112 | 2 | d_ptr->keymap = file_wrap(tmpf); | |
113 | 2 | d_ptr->needs_keymap_update = false; | |
114 | 2 | } | |
115 | |||
116 | 69 | void Keyboard::setFocusedSurface(quint32 serial, Surface* surface) | |
117 | { | ||
118 | 69 | d_ptr->sendLeave(serial, d_ptr->focusedSurface); | |
119 | 69 | disconnect(d_ptr->destroyConnection); | |
120 | 69 | d_ptr->focusedSurface = surface; | |
121 |
2/2✓ Branch 0 taken 11 times.
✓ Branch 1 taken 58 times.
|
69 | if (!d_ptr->focusedSurface) { |
122 | 11 | return; | |
123 | } | ||
124 | 58 | d_ptr->destroyConnection = connect( | |
125 | 60 | d_ptr->focusedSurface, &Surface::resourceDestroyed, this, [this] { | |
126 | 2 | d_ptr->sendLeave(d_ptr->client->display()->handle->nextSerial(), d_ptr->focusedSurface); | |
127 | 2 | d_ptr->focusedSurface = nullptr; | |
128 | 2 | }); | |
129 | |||
130 | 58 | d_ptr->sendEnter(serial, d_ptr->focusedSurface); | |
131 | 58 | d_ptr->client->flush(); | |
132 | 69 | } | |
133 | |||
134 | 10 | void Keyboard::key(uint32_t serial, uint32_t key, key_state state) | |
135 | { | ||
136 |
1/2✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
|
10 | Q_ASSERT(d_ptr->focusedSurface); |
137 | 20 | d_ptr->send<wl_keyboard_send_key>(serial, | |
138 | 10 | d_ptr->seat->timestamp(), | |
139 | key, | ||
140 | 10 | state == key_state::pressed ? WL_KEYBOARD_KEY_STATE_PRESSED | |
141 | : WL_KEYBOARD_KEY_STATE_RELEASED); | ||
142 | 10 | } | |
143 | |||
144 | 1 | void Keyboard::updateModifiers(quint32 serial, | |
145 | quint32 depressed, | ||
146 | quint32 latched, | ||
147 | quint32 locked, | ||
148 | quint32 group) | ||
149 | { | ||
150 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | Q_ASSERT(d_ptr->focusedSurface); |
151 | 1 | d_ptr->sendModifiers(serial, depressed, latched, locked, group); | |
152 | 1 | } | |
153 | |||
154 | 50 | void Keyboard::repeatInfo(qint32 charactersPerSecond, qint32 delay) | |
155 | { | ||
156 | 50 | d_ptr->send<wl_keyboard_send_repeat_info, WL_KEYBOARD_REPEAT_INFO_SINCE_VERSION>( | |
157 | charactersPerSecond, delay); | ||
158 | 50 | } | |
159 | |||
160 | 3 | Surface* Keyboard::focusedSurface() const | |
161 | { | ||
162 | 3 | return d_ptr->focusedSurface; | |
163 | } | ||
164 | |||
165 | 64 | Client* Keyboard::client() const | |
166 | { | ||
167 | 64 | return d_ptr->client->handle; | |
168 | } | ||
169 | |||
170 | } | ||
171 |