GCC Code Coverage Report


Directory: ./
File: server/text_input_v3.cpp
Date: 2024-01-22 17:25:27
Exec Total Coverage
Lines: 206 210 98.1%
Branches: 79 94 84.0%

Line Branch Exec Source
1 /*
2 SPDX-FileCopyrightText: 2018 Roman Glig <subdiff@gmail.com>
3 SPDX-FileCopyrightText: 2020 Bhushan Shah <bshah@kde.org>
4 SPDX-FileCopyrightText: 2021 dcz <gihuac.dcz@porcupinefactory.org>
5 SPDX-FileCopyrightText: 2021 Roman Glig <subdiff@gmail.com>
6
7 SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only
8 */
9 #include "text_input_v3_p.h"
10
11 #include "display.h"
12 #include "seat_p.h"
13 #include "surface_p.h"
14
15 namespace Wrapland::Server
16 {
17
18 struct zwp_text_input_manager_v3_interface const text_input_manager_v3::Private::s_interface = {
19 resourceDestroyCallback,
20 cb<get_text_input_callback>,
21 };
22
23 48 text_input_v3_content_hints convert_content_hint(uint32_t hint)
24 {
25 48 auto const hints = static_cast<zwp_text_input_v3_content_hint>(hint);
26 48 text_input_v3_content_hints ret = text_input_v3_content_hint::none;
27
28
2/2
✓ Branch 0 taken 45 times.
✓ Branch 1 taken 3 times.
48 if (hints & ZWP_TEXT_INPUT_V3_CONTENT_HINT_COMPLETION) {
29 3 ret |= text_input_v3_content_hint::completion;
30 3 }
31
2/2
✓ Branch 0 taken 45 times.
✓ Branch 1 taken 3 times.
48 if (hints & ZWP_TEXT_INPUT_V3_CONTENT_HINT_SPELLCHECK) {
32 3 ret |= text_input_v3_content_hint::spellcheck;
33 3 }
34
2/2
✓ Branch 0 taken 45 times.
✓ Branch 1 taken 3 times.
48 if (hints & ZWP_TEXT_INPUT_V3_CONTENT_HINT_AUTO_CAPITALIZATION) {
35 3 ret |= text_input_v3_content_hint::auto_capitalization;
36 3 }
37
2/2
✓ Branch 0 taken 46 times.
✓ Branch 1 taken 2 times.
48 if (hints & ZWP_TEXT_INPUT_V3_CONTENT_HINT_LOWERCASE) {
38 2 ret |= text_input_v3_content_hint::lowercase;
39 2 }
40
2/2
✓ Branch 0 taken 46 times.
✓ Branch 1 taken 2 times.
48 if (hints & ZWP_TEXT_INPUT_V3_CONTENT_HINT_UPPERCASE) {
41 2 ret |= text_input_v3_content_hint::uppercase;
42 2 }
43
2/2
✓ Branch 0 taken 46 times.
✓ Branch 1 taken 2 times.
48 if (hints & ZWP_TEXT_INPUT_V3_CONTENT_HINT_TITLECASE) {
44 2 ret |= text_input_v3_content_hint::titlecase;
45 2 }
46
2/2
✓ Branch 0 taken 46 times.
✓ Branch 1 taken 2 times.
48 if (hints & ZWP_TEXT_INPUT_V3_CONTENT_HINT_HIDDEN_TEXT) {
47 2 ret |= text_input_v3_content_hint::hidden_text;
48 35 }
49
2/2
✓ Branch 0 taken 46 times.
✓ Branch 1 taken 2 times.
81 if (hints & ZWP_TEXT_INPUT_V3_CONTENT_HINT_SENSITIVE_DATA) {
50 35 ret |= text_input_v3_content_hint::sensitive_data;
51 2 }
52
2/2
✓ Branch 0 taken 46 times.
✓ Branch 1 taken 2 times.
48 if (hints & ZWP_TEXT_INPUT_V3_CONTENT_HINT_LATIN) {
53 2 ret |= text_input_v3_content_hint::latin;
54 2 }
55
2/2
✓ Branch 0 taken 46 times.
✓ Branch 1 taken 2 times.
48 if (hints & ZWP_TEXT_INPUT_V3_CONTENT_HINT_MULTILINE) {
56 2 ret |= text_input_v3_content_hint::multiline;
57 2 }
58 48 return ret;
59 }
60
61 24 uint32_t convert_content_hints(text_input_v3_content_hints hints)
62 {
63 24 uint32_t ret = 0;
64
65
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 21 times.
94 if (hints & text_input_v3_content_hint::completion) {
66 3 ret |= ZWP_TEXT_INPUT_V3_CONTENT_HINT_COMPLETION;
67 3 }
68
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 21 times.
24 if (hints & text_input_v3_content_hint::spellcheck) {
69 3 ret |= ZWP_TEXT_INPUT_V3_CONTENT_HINT_SPELLCHECK;
70 3 }
71
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 21 times.
24 if (hints & text_input_v3_content_hint::auto_capitalization) {
72 3 ret |= ZWP_TEXT_INPUT_V3_CONTENT_HINT_AUTO_CAPITALIZATION;
73 3 }
74
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 22 times.
24 if (hints & text_input_v3_content_hint::lowercase) {
75 2 ret |= ZWP_TEXT_INPUT_V3_CONTENT_HINT_LOWERCASE;
76 2 }
77
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 22 times.
24 if (hints & text_input_v3_content_hint::uppercase) {
78 2 ret |= ZWP_TEXT_INPUT_V3_CONTENT_HINT_UPPERCASE;
79 2 }
80
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 22 times.
24 if (hints & text_input_v3_content_hint::titlecase) {
81 2 ret |= ZWP_TEXT_INPUT_V3_CONTENT_HINT_TITLECASE;
82 2 }
83
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 22 times.
24 if (hints & text_input_v3_content_hint::hidden_text) {
84 2 ret |= ZWP_TEXT_INPUT_V3_CONTENT_HINT_HIDDEN_TEXT;
85 2 }
86
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 22 times.
24 if (hints & text_input_v3_content_hint::sensitive_data) {
87 2 ret |= ZWP_TEXT_INPUT_V3_CONTENT_HINT_SENSITIVE_DATA;
88 2 }
89
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 22 times.
24 if (hints & text_input_v3_content_hint::latin) {
90 2 ret |= ZWP_TEXT_INPUT_V3_CONTENT_HINT_LATIN;
91 2 }
92
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 22 times.
24 if (hints & text_input_v3_content_hint::multiline) {
93 2 ret |= ZWP_TEXT_INPUT_V3_CONTENT_HINT_MULTILINE;
94 2 }
95 24 return ret;
96 }
97
98 namespace
99 {
100
101 48 text_input_v3_content_purpose convert_content_purpose(uint32_t purpose)
102 {
103 48 auto const wlPurpose = static_cast<zwp_text_input_v3_content_purpose>(purpose);
104
105
13/14
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 1 times.
✓ Branch 6 taken 1 times.
✓ Branch 7 taken 1 times.
✓ Branch 8 taken 1 times.
✓ Branch 9 taken 1 times.
✓ Branch 10 taken 1 times.
✓ Branch 11 taken 1 times.
✓ Branch 12 taken 36 times.
✗ Branch 13 not taken.
48 switch (wlPurpose) {
106 case ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_ALPHA:
107 1 return text_input_v3_content_purpose::alpha;
108 case ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_DIGITS:
109 1 return text_input_v3_content_purpose::digits;
110 case ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_NUMBER:
111 1 return text_input_v3_content_purpose::number;
112 case ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_PHONE:
113 1 return text_input_v3_content_purpose::phone;
114 case ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_URL:
115 1 return text_input_v3_content_purpose::url;
116 case ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_EMAIL:
117 1 return text_input_v3_content_purpose::email;
118 case ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_NAME:
119 1 return text_input_v3_content_purpose::name;
120 case ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_PASSWORD:
121 1 return text_input_v3_content_purpose::password;
122 case ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_DATE:
123 1 return text_input_v3_content_purpose::date;
124 case ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_TIME:
125 1 return text_input_v3_content_purpose::time;
126 case ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_DATETIME:
127 1 return text_input_v3_content_purpose::datetime;
128 case ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_TERMINAL:
129 1 return text_input_v3_content_purpose::terminal;
130 36 case ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_NORMAL:
131 default:
132 36 return text_input_v3_content_purpose::normal;
133 }
134 48 }
135
136 }
137
138 24 uint32_t convert_content_purpose(text_input_v3_content_purpose purpose)
139 {
140
13/14
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 1 times.
✓ Branch 6 taken 1 times.
✓ Branch 7 taken 1 times.
✓ Branch 8 taken 1 times.
✓ Branch 9 taken 1 times.
✓ Branch 10 taken 1 times.
✓ Branch 11 taken 1 times.
✓ Branch 12 taken 12 times.
✗ Branch 13 not taken.
24 switch (purpose) {
141 case text_input_v3_content_purpose::alpha:
142 1 return ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_ALPHA;
143 case text_input_v3_content_purpose::digits:
144 1 return ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_DIGITS;
145 case text_input_v3_content_purpose::number:
146 1 return ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_NUMBER;
147 case text_input_v3_content_purpose::phone:
148 1 return ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_PHONE;
149 case text_input_v3_content_purpose::url:
150 1 return ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_URL;
151 case text_input_v3_content_purpose::email:
152 1 return ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_EMAIL;
153 case text_input_v3_content_purpose::name:
154 1 return ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_NAME;
155 case text_input_v3_content_purpose::password:
156 1 return ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_PASSWORD;
157 case text_input_v3_content_purpose::date:
158 1 return ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_DATE;
159 case text_input_v3_content_purpose::time:
160 1 return ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_TIME;
161 case text_input_v3_content_purpose::datetime:
162 1 return ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_DATETIME;
163 case text_input_v3_content_purpose::terminal:
164 1 return ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_TERMINAL;
165 12 case text_input_v3_content_purpose::normal:
166 default:
167 12 return ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_NORMAL;
168 }
169 24 }
170
171 2 text_input_v3_change_cause convert_change_cause(uint32_t cause)
172 {
173 2 auto const wlCause = static_cast<zwp_text_input_v3_change_cause>(cause);
174
175
1/3
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 switch (wlCause) {
176 case ZWP_TEXT_INPUT_V3_CHANGE_CAUSE_INPUT_METHOD:
177 2 return text_input_v3_change_cause::input_method;
178 case ZWP_TEXT_INPUT_V3_CHANGE_CAUSE_OTHER:
179 default:
180 return text_input_v3_change_cause::other;
181 }
182 2 }
183
184 4 uint32_t convert_change_cause(text_input_v3_change_cause cause)
185 {
186
2/3
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 1 times.
4 switch (cause) {
187 case text_input_v3_change_cause::input_method:
188 3 return ZWP_TEXT_INPUT_V3_CHANGE_CAUSE_INPUT_METHOD;
189 1 case text_input_v3_change_cause::other:
190 default:
191 1 return ZWP_TEXT_INPUT_V3_CHANGE_CAUSE_OTHER;
192 }
193 4 }
194
195 97 text_input_manager_v3::Private::Private(Display* display, text_input_manager_v3* q_ptr)
196 194 : text_input_manager_v3_global(q_ptr,
197 97 display,
198 &zwp_text_input_manager_v3_interface,
199 &s_interface)
200 97 {
201
1/2
✓ Branch 0 taken 97 times.
✗ Branch 1 not taken.
97 create();
202 97 }
203
204 33 void text_input_manager_v3::Private::get_text_input_callback(text_input_manager_v3_bind* bind,
205 uint32_t id,
206 wl_resource* wlSeat)
207 {
208 33 auto seat = SeatGlobal::get_handle(wlSeat);
209
210
1/2
✓ Branch 0 taken 33 times.
✗ Branch 1 not taken.
33 auto textInput = new text_input_v3(bind->client->handle, bind->version, id);
211 33 textInput->d_ptr->seat = seat;
212 33 seat->d_ptr->text_inputs.register_device(textInput);
213 33 }
214
215 97 text_input_manager_v3::text_input_manager_v3(Display* display)
216
2/4
✓ Branch 0 taken 97 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 97 times.
97 : d_ptr(new Private(display, this))
217 97 {
218 97 }
219
220 194 text_input_manager_v3::~text_input_manager_v3() = default;
221
222 const struct zwp_text_input_v3_interface text_input_v3::Private::s_interface = {
223 destroyCallback,
224 enable_callback,
225 disable_callback,
226 set_surrounding_text_callback,
227 set_text_change_cause_callback,
228 set_content_type_callback,
229 set_cursor_rectangle_callback,
230 set_commit_callback,
231 };
232
233 66 text_input_v3::Private::Private(Client* client, uint32_t version, uint32_t id, text_input_v3* q_ptr)
234 66 : Wayland::Resource<text_input_v3>(client,
235 33 version,
236 33 id,
237 &zwp_text_input_v3_interface,
238 &s_interface,
239 33 q_ptr)
240 33 , q_ptr{q_ptr}
241 33 {
242 33 }
243
244 35 void text_input_v3::Private::send_enter(Surface* surface)
245 {
246
1/2
✓ Branch 0 taken 35 times.
✗ Branch 1 not taken.
35 assert(surface);
247 35 entered_surface = surface;
248 35 send<zwp_text_input_v3_send_enter>(surface->d_ptr->resource);
249 35 }
250
251 35 void text_input_v3::Private::send_leave(Surface* surface)
252 {
253
1/2
✓ Branch 0 taken 35 times.
✗ Branch 1 not taken.
35 assert(surface);
254 70 current = {};
255 70 pending = {};
256 35 entered_surface = nullptr;
257 35 send<zwp_text_input_v3_send_leave>(surface->d_ptr->resource);
258 35 }
259
260 8 void text_input_v3::Private::enable_callback([[maybe_unused]] wl_client* wlClient,
261 wl_resource* wlResource)
262 {
263 8 get_handle(wlResource)->d_ptr->pending.enabled = true;
264 8 }
265
266 1 void text_input_v3::Private::disable_callback([[maybe_unused]] wl_client* wlClient,
267 wl_resource* wlResource)
268 {
269 1 get_handle(wlResource)->d_ptr->pending.enabled = false;
270 1 }
271
272 2 void text_input_v3::Private::set_surrounding_text_callback([[maybe_unused]] wl_client* wlClient,
273 wl_resource* wlResource,
274 char const* text,
275 int32_t cursor,
276 int32_t anchor)
277 {
278 2 auto priv = get_handle(wlResource)->d_ptr;
279
280 2 priv->pending.surrounding_text.update = true;
281 2 priv->pending.surrounding_text.data = text;
282 2 priv->pending.surrounding_text.cursor_position = cursor;
283 2 priv->pending.surrounding_text.selection_anchor = anchor;
284 2 }
285
286 48 void text_input_v3::Private::set_content_type_callback([[maybe_unused]] wl_client* wlClient,
287 wl_resource* wlResource,
288 uint32_t hint,
289 uint32_t purpose)
290 {
291 48 auto priv = get_handle(wlResource)->d_ptr;
292
293 48 priv->pending.content.hints = convert_content_hint(hint);
294 48 priv->pending.content.purpose = convert_content_purpose(purpose);
295 48 }
296
297 1 void text_input_v3::Private::set_cursor_rectangle_callback([[maybe_unused]] wl_client* wlClient,
298 wl_resource* wlResource,
299 int32_t pos_x,
300 int32_t pos_y,
301 int32_t width,
302 int32_t height)
303 {
304 1 auto priv = get_handle(wlResource)->d_ptr;
305 1 priv->pending.cursor_rectangle = QRect(pos_x, pos_y, width, height);
306 1 }
307
308 2 void text_input_v3::Private::set_text_change_cause_callback([[maybe_unused]] wl_client* wlClient,
309 wl_resource* wlResource,
310 uint32_t cause)
311 {
312 2 auto priv = get_handle(wlResource)->d_ptr;
313 2 priv->pending.surrounding_text.change_cause = convert_change_cause(cause);
314 2 }
315
316 58 void text_input_v3::Private::set_commit_callback([[maybe_unused]] wl_client* wlClient,
317 wl_resource* wlResource)
318 {
319 58 auto priv = get_handle(wlResource)->d_ptr;
320
321 58 priv->serial++;
322
323
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 58 times.
116 if (auto pool = priv->seat->text_inputs(); pool.v3.text_input == priv->q_ptr) {
324
1/2
✓ Branch 0 taken 58 times.
✗ Branch 1 not taken.
58 pool.sync_to_input_method(priv->current, priv->pending);
325 58 }
326 58 priv->current = priv->pending;
327 58 priv->pending.surrounding_text.update = false;
328
329 58 Q_EMIT priv->handle->state_committed();
330 58 }
331
332 33 text_input_v3::text_input_v3(Client* client, uint32_t version, uint32_t id)
333 33 : QObject(nullptr)
334
2/4
✓ Branch 0 taken 33 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 33 times.
33 , d_ptr(new Private(client, version, id, this))
335 33 {
336 33 }
337
338 2 void text_input_v3::set_preedit_string(std::string const& text,
339 uint32_t cursor_begin,
340 uint32_t cursor_end)
341 {
342 2 d_ptr->send<zwp_text_input_v3_send_preedit_string>(text.c_str(), cursor_begin, cursor_end);
343 2 }
344
345 1 void text_input_v3::commit_string(std::string const& text)
346 {
347 1 d_ptr->send<zwp_text_input_v3_send_commit_string>(text.c_str());
348 1 }
349 void text_input_v3::delete_surrounding_text(uint32_t before_length, uint32_t after_length)
350 {
351 d_ptr->send<zwp_text_input_v3_send_delete_surrounding_text>(before_length, after_length);
352 }
353
354 2 void text_input_v3::done()
355 {
356 2 d_ptr->send<zwp_text_input_v3_send_done>(d_ptr->serial);
357 2 }
358
359 103 text_input_v3_state const& text_input_v3::state() const
360 {
361 103 return d_ptr->current;
362 }
363
364 39 Client* text_input_v3::client() const
365 {
366 39 return d_ptr->client->handle;
367 }
368
369 7 Surface* text_input_v3::entered_surface() const
370 {
371 7 return d_ptr->entered_surface;
372 }
373
374 }
375