Directory: | ./ |
---|---|
File: | server/seat.cpp |
Date: | 2024-01-22 17:25:27 |
Exec | Total | Coverage | |
---|---|---|---|
Lines: | 127 | 138 | 92.0% |
Branches: | 30 | 56 | 53.6% |
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 "seat.h" | ||
21 | #include "seat_p.h" | ||
22 | |||
23 | #include "client.h" | ||
24 | #include "data_device.h" | ||
25 | #include "data_source.h" | ||
26 | #include "display.h" | ||
27 | #include "primary_selection.h" | ||
28 | #include "surface.h" | ||
29 | |||
30 | #include <config-wrapland.h> | ||
31 | #include <cstdint> | ||
32 | |||
33 | #ifndef WL_SEAT_NAME_SINCE_VERSION | ||
34 | #define WL_SEAT_NAME_SINCE_VERSION 2 | ||
35 | #endif | ||
36 | |||
37 | namespace Wrapland::Server | ||
38 | { | ||
39 | |||
40 | 927 | Seat::Private::Private(Seat* q_ptr, Display* display) | |
41 | 309 | : SeatGlobal(q_ptr, display, &wl_seat_interface, &s_interface) | |
42 |
1/2✓ Branch 0 taken 309 times.
✗ Branch 1 not taken.
|
309 | , drags{q_ptr} |
43 |
1/2✓ Branch 0 taken 309 times.
✗ Branch 1 not taken.
|
309 | , data_devices{q_ptr} |
44 |
1/2✓ Branch 0 taken 309 times.
✗ Branch 1 not taken.
|
309 | , primary_selection_devices{q_ptr} |
45 |
1/2✓ Branch 0 taken 309 times.
✗ Branch 1 not taken.
|
309 | , text_inputs{q_ptr} |
46 | 309 | , q_ptr{q_ptr} | |
47 | 309 | { | |
48 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 309 times.
|
309 | display->globals.seats.push_back(q_ptr); |
49 | 309 | } | |
50 | |||
51 | 618 | Seat::Private::~Private() | |
52 | 618 | { | |
53 |
3/4✓ Branch 0 taken 309 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✓ Branch 3 taken 300 times.
|
309 | if (display()) { |
54 |
2/4✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
|
9 | remove_all(display()->handle->globals.seats, q_ptr); |
55 | 9 | } | |
56 | 618 | } | |
57 | |||
58 | const struct wl_seat_interface Seat::Private::s_interface = { | ||
59 | cb<getPointerCallback>, | ||
60 | cb<getKeyboardCallback>, | ||
61 | cb<getTouchCallback>, | ||
62 | resourceDestroyCallback, | ||
63 | }; | ||
64 | |||
65 | 309 | Seat::Seat(Display* display) | |
66 |
2/4✓ Branch 0 taken 309 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 309 times.
✗ Branch 3 not taken.
|
309 | : d_ptr(new Private(this, display)) |
67 | 309 | { | |
68 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 309 times.
|
309 | d_ptr->create(); |
69 | 309 | } | |
70 | |||
71 | 618 | Seat::~Seat() = default; | |
72 | |||
73 | 278 | void Seat::Private::bindInit(SeatBind* bind) | |
74 | { | ||
75 | 278 | send<wl_seat_send_capabilities>(bind, getCapabilities()); | |
76 | 278 | send<wl_seat_send_name, WL_SEAT_NAME_SINCE_VERSION>(bind, name.c_str()); | |
77 | 278 | } | |
78 | |||
79 | 59 | void Seat::Private::sendName() | |
80 | { | ||
81 | 59 | send<wl_seat_send_name, WL_SEAT_NAME_SINCE_VERSION>(name.c_str()); | |
82 | 368 | } | |
83 | |||
84 | 721 | uint32_t Seat::Private::getCapabilities() const | |
85 | { | ||
86 | 721 | uint32_t capabilities = 0; | |
87 |
2/2✓ Branch 0 taken 399 times.
✓ Branch 1 taken 322 times.
|
1030 | if (pointers) { |
88 | 322 | capabilities |= WL_SEAT_CAPABILITY_POINTER; | |
89 | 322 | } | |
90 |
2/2✓ Branch 0 taken 191 times.
✓ Branch 1 taken 530 times.
|
721 | if (keyboards) { |
91 | 530 | capabilities |= WL_SEAT_CAPABILITY_KEYBOARD; | |
92 | 530 | } | |
93 |
2/2✓ Branch 0 taken 500 times.
✓ Branch 1 taken 221 times.
|
721 | if (touches) { |
94 | 221 | capabilities |= WL_SEAT_CAPABILITY_TOUCH; | |
95 | 221 | } | |
96 | 721 | return capabilities; | |
97 | 309 | } | |
98 | |||
99 | 443 | void Seat::Private::sendCapabilities() | |
100 | { | ||
101 | 443 | send<wl_seat_send_capabilities>(getCapabilities()); | |
102 | 443 | } | |
103 | |||
104 | 194 | void Seat::setHasKeyboard(bool has) | |
105 | { | ||
106 | 194 | d_ptr->set_capability(WL_SEAT_CAPABILITY_KEYBOARD, d_ptr->keyboards, has); | |
107 | 194 | } | |
108 | |||
109 | 146 | void Seat::setHasPointer(bool has) | |
110 | { | ||
111 | 146 | d_ptr->set_capability(WL_SEAT_CAPABILITY_POINTER, d_ptr->pointers, has); | |
112 | 146 | } | |
113 | |||
114 | 117 | void Seat::setHasTouch(bool has) | |
115 | { | ||
116 | 117 | d_ptr->set_capability(WL_SEAT_CAPABILITY_TOUCH, d_ptr->touches, has); | |
117 | 117 | } | |
118 | |||
119 | 228 | pointer_pool& Seat::pointers() const | |
120 | { | ||
121 |
1/2✓ Branch 0 taken 228 times.
✗ Branch 1 not taken.
|
228 | assert(hasPointer()); |
122 | |||
123 | // We already check with the assert. | ||
124 | // NOLINTNEXTLINE(bugprone-unchecked-optional-access) | ||
125 | 228 | return *d_ptr->pointers; | |
126 | } | ||
127 | |||
128 | 160 | keyboard_pool& Seat::keyboards() const | |
129 | { | ||
130 |
1/2✓ Branch 0 taken 160 times.
✗ Branch 1 not taken.
|
160 | assert(hasKeyboard()); |
131 | |||
132 | // We already check with the assert. | ||
133 | // NOLINTNEXTLINE(bugprone-unchecked-optional-access) | ||
134 | 160 | return *d_ptr->keyboards; | |
135 | } | ||
136 | |||
137 | 10 | touch_pool& Seat::touches() const | |
138 | { | ||
139 |
1/2✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
|
10 | assert(hasTouch()); |
140 | |||
141 | // We already check with the assert. | ||
142 | // NOLINTNEXTLINE(bugprone-unchecked-optional-access) | ||
143 | 10 | return *d_ptr->touches; | |
144 | } | ||
145 | |||
146 | 349 | text_input_pool& Seat::text_inputs() const | |
147 | { | ||
148 | 349 | return d_ptr->text_inputs; | |
149 | } | ||
150 | |||
151 | 242 | drag_pool& Seat::drags() const | |
152 | { | ||
153 | 242 | return d_ptr->drags; | |
154 | } | ||
155 | |||
156 | 59 | void Seat::setName(std::string const& name) | |
157 | { | ||
158 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 59 times.
|
59 | if (d_ptr->name == name) { |
159 | ✗ | return; | |
160 | } | ||
161 | 59 | d_ptr->name = name; | |
162 | 59 | d_ptr->sendName(); | |
163 | 59 | } | |
164 | |||
165 | 65 | void Seat::Private::getPointerCallback(SeatBind* bind, uint32_t id) | |
166 | { | ||
167 | 65 | auto priv = bind->global()->handle->d_ptr.get(); | |
168 | 65 | auto& manager = priv->pointers; | |
169 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 65 times.
|
65 | if (!manager) { |
170 | // If we have no pointer capability we ignore the created resource. | ||
171 | ✗ | if (!(priv->prior_caps & WL_SEAT_CAPABILITY_POINTER)) { | |
172 | ✗ | bind->post_error(WL_SEAT_ERROR_MISSING_CAPABILITY, | |
173 | "Seat never had the pointer capability"); | ||
174 | } | ||
175 | ✗ | return; | |
176 | } | ||
177 | 65 | manager.value().create_device(bind->client->handle, bind->version, id); | |
178 | 65 | } | |
179 | |||
180 | 49 | void Seat::Private::getKeyboardCallback(SeatBind* bind, uint32_t id) | |
181 | { | ||
182 | 49 | auto priv = bind->global()->handle->d_ptr.get(); | |
183 | 49 | auto& manager = priv->keyboards; | |
184 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 49 times.
|
49 | if (!manager) { |
185 | // If we have no keyboard capability we ignore the created resource. | ||
186 | ✗ | if (!(priv->prior_caps & WL_SEAT_CAPABILITY_KEYBOARD)) { | |
187 | ✗ | bind->post_error(WL_SEAT_ERROR_MISSING_CAPABILITY, | |
188 | "Seat never had the keyboard capability"); | ||
189 | } | ||
190 | ✗ | return; | |
191 | } | ||
192 | 49 | manager.value().create_device(bind->client->handle, bind->version, id); | |
193 | 49 | } | |
194 | |||
195 | 12 | void Seat::Private::getTouchCallback(SeatBind* bind, uint32_t id) | |
196 | { | ||
197 | 12 | auto priv = bind->global()->handle->d_ptr.get(); | |
198 | 12 | auto& manager = priv->touches; | |
199 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
|
12 | if (!manager) { |
200 | // If we have no touch capability we ignore the created resource. | ||
201 | ✗ | if (!(priv->prior_caps & WL_SEAT_CAPABILITY_TOUCH)) { | |
202 | ✗ | bind->post_error(WL_SEAT_ERROR_MISSING_CAPABILITY, | |
203 | "Seat never had the touch capability"); | ||
204 | } | ||
205 | ✗ | return; | |
206 | } | ||
207 | 12 | manager.value().create_device(bind->client->handle, bind->version, id); | |
208 | 12 | } | |
209 | |||
210 | 2 | std::string Seat::name() const | |
211 | { | ||
212 | 2 | return d_ptr->name; | |
213 | } | ||
214 | |||
215 | 246 | bool Seat::hasPointer() const | |
216 | { | ||
217 | 246 | return d_ptr->pointers.has_value(); | |
218 | } | ||
219 | |||
220 | 344 | bool Seat::hasKeyboard() const | |
221 | { | ||
222 | 344 | return d_ptr->keyboards.has_value(); | |
223 | } | ||
224 | |||
225 | 20 | bool Seat::hasTouch() const | |
226 | { | ||
227 | 20 | return d_ptr->touches.has_value(); | |
228 | } | ||
229 | |||
230 | 131 | uint32_t Seat::timestamp() const | |
231 | { | ||
232 | 131 | return d_ptr->timestamp; | |
233 | } | ||
234 | |||
235 | 141 | void Seat::setTimestamp(uint32_t time) | |
236 | { | ||
237 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 141 times.
|
141 | if (d_ptr->timestamp == time) { |
238 | ✗ | return; | |
239 | } | ||
240 | 141 | d_ptr->timestamp = time; | |
241 | 141 | Q_EMIT timestampChanged(time); | |
242 | 141 | } | |
243 | |||
244 | 113 | void Seat::setFocusedKeyboardSurface(Surface* surface) | |
245 | { | ||
246 |
1/2✓ Branch 0 taken 113 times.
✗ Branch 1 not taken.
|
113 | assert(hasKeyboard()); |
247 | |||
248 | // We already check with the assert. | ||
249 | // NOLINTNEXTLINE(bugprone-unchecked-optional-access) | ||
250 | 113 | auto& keys = d_ptr->keyboards.value(); | |
251 | |||
252 |
2/2✓ Branch 0 taken 112 times.
✓ Branch 1 taken 1 times.
|
113 | if (surface == keys.get_focus().surface) { |
253 | 1 | return; | |
254 | } | ||
255 | |||
256 | // Data sharing devices receive a potential selection directly before keyboard enter. | ||
257 | 112 | d_ptr->data_devices.set_focused_surface(surface); | |
258 | 112 | d_ptr->primary_selection_devices.set_focused_surface(surface); | |
259 | |||
260 | 112 | keys.set_focused_surface(surface); | |
261 | |||
262 | // Focused text input surface follows keyboard. | ||
263 | 112 | d_ptr->text_inputs.set_focused_surface(surface); | |
264 | 113 | } | |
265 | |||
266 | 176 | input_method_v2* Seat::get_input_method_v2() const | |
267 | { | ||
268 | 176 | return d_ptr->input_method; | |
269 | } | ||
270 | |||
271 | 13 | data_source* Seat::selection() const | |
272 | { | ||
273 | 13 | return d_ptr->data_devices.focus.source; | |
274 | } | ||
275 | |||
276 | 10 | void Seat::setSelection(data_source* source) | |
277 | { | ||
278 | 10 | d_ptr->data_devices.set_selection(source); | |
279 | 10 | } | |
280 | |||
281 | 3 | primary_selection_source* Seat::primarySelection() const | |
282 | { | ||
283 | 3 | return d_ptr->primary_selection_devices.focus.source; | |
284 | } | ||
285 | |||
286 | 2 | void Seat::setPrimarySelection(primary_selection_source* source) | |
287 | { | ||
288 | 2 | d_ptr->primary_selection_devices.set_selection(source); | |
289 | 2 | } | |
290 | |||
291 | } | ||
292 |