1 /*
2     SPDX-FileCopyrightText: 2021 Roman Gilg <subdiff@gmail.com>
3 
4     SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only
5 */
6 #include "input_method_v2_p.h"
7 
8 #include "text_input_v3_p.h"
9 
10 #include "event_queue.h"
11 #include "seat.h"
12 #include "surface.h"
13 
14 namespace Wrapland::Client
15 {
16 
input_method_manager_v2(QObject * parent)17 input_method_manager_v2::input_method_manager_v2(QObject* parent)
18     : QObject(parent)
19     , d_ptr(new Private)
20 {
21 }
22 
23 input_method_manager_v2::~input_method_manager_v2() = default;
24 
setup(zwp_input_method_manager_v2 * manager)25 void input_method_manager_v2::setup(zwp_input_method_manager_v2* manager)
26 {
27     assert(manager);
28     assert(!d_ptr->manager_ptr);
29     d_ptr->manager_ptr.setup(manager);
30 }
31 
release()32 void input_method_manager_v2::release()
33 {
34     d_ptr->release();
35 }
36 
setEventQueue(EventQueue * queue)37 void input_method_manager_v2::setEventQueue(EventQueue* queue)
38 {
39     d_ptr->queue = queue;
40 }
41 
event_queue()42 EventQueue* input_method_manager_v2::event_queue()
43 {
44     return d_ptr->queue;
45 }
46 
operator zwp_input_method_manager_v2*()47 input_method_manager_v2::operator zwp_input_method_manager_v2*()
48 {
49     return *(d_ptr.get());
50 }
51 
operator zwp_input_method_manager_v2*() const52 input_method_manager_v2::operator zwp_input_method_manager_v2*() const
53 {
54     return *(d_ptr.get());
55 }
56 
isValid() const57 bool input_method_manager_v2::isValid() const
58 {
59     return d_ptr->isValid();
60 }
61 
get_input_method(Seat * seat,QObject * parent)62 input_method_v2* input_method_manager_v2::get_input_method(Seat* seat, QObject* parent)
63 {
64     return d_ptr->get_input_method(seat, parent);
65 }
66 
release()67 void input_method_manager_v2::Private::release()
68 {
69     manager_ptr.release();
70 }
71 
isValid()72 bool input_method_manager_v2::Private::isValid()
73 {
74     return manager_ptr.isValid();
75 }
76 
get_input_method(Seat * seat,QObject * parent)77 input_method_v2* input_method_manager_v2::Private::get_input_method(Seat* seat, QObject* parent)
78 {
79     assert(isValid());
80     auto im = new input_method_v2(seat, parent);
81     auto wlim = zwp_input_method_manager_v2_get_input_method(manager_ptr, *seat);
82     if (queue) {
83         queue->addProxy(wlim);
84     }
85     im->setup(wlim);
86     return im;
87 }
88 
Private(Seat * seat,input_method_v2 * q)89 input_method_v2::Private::Private(Seat* seat, input_method_v2* q)
90     : seat{seat}
91     , q_ptr{q}
92 {
93 }
94 
95 zwp_input_method_v2_listener const input_method_v2::Private::s_listener = {
96     activate_callback,
97     deactivate_callback,
98     surrounding_text_callback,
99     text_change_cause_callback,
100     content_type_callback,
101     done_callback,
102     unavailable_callback,
103 };
104 
activate_callback(void * data,zwp_input_method_v2 * zwp_input_method_v2)105 void input_method_v2::Private::activate_callback(void* data,
106                                                  zwp_input_method_v2* zwp_input_method_v2)
107 {
108     auto priv = reinterpret_cast<input_method_v2::Private*>(data);
109     assert(priv->input_method_ptr == zwp_input_method_v2);
110     priv->pending = {};
111     priv->pending.active = true;
112 }
113 
deactivate_callback(void * data,zwp_input_method_v2 * zwp_input_method_v2)114 void input_method_v2::Private::deactivate_callback(void* data,
115                                                    zwp_input_method_v2* zwp_input_method_v2)
116 {
117     auto priv = reinterpret_cast<input_method_v2::Private*>(data);
118     assert(priv->input_method_ptr == zwp_input_method_v2);
119     priv->pending.active = false;
120 }
121 
surrounding_text_callback(void * data,zwp_input_method_v2 * zwp_input_method_v2,char const * text,uint32_t cursor,uint32_t anchor)122 void input_method_v2::Private::surrounding_text_callback(void* data,
123                                                          zwp_input_method_v2* zwp_input_method_v2,
124                                                          char const* text,
125                                                          uint32_t cursor,
126                                                          uint32_t anchor)
127 {
128     auto priv = reinterpret_cast<input_method_v2::Private*>(data);
129     assert(priv->input_method_ptr == zwp_input_method_v2);
130     priv->pending.surrounding_text.update = true;
131     priv->pending.surrounding_text.data = text;
132     priv->pending.surrounding_text.cursor_position = cursor;
133     priv->pending.surrounding_text.selection_anchor = anchor;
134 }
135 
text_change_cause_callback(void * data,zwp_input_method_v2 * zwp_input_method_v2,uint32_t cause)136 void input_method_v2::Private::text_change_cause_callback(void* data,
137                                                           zwp_input_method_v2* zwp_input_method_v2,
138                                                           uint32_t cause)
139 {
140     auto priv = reinterpret_cast<input_method_v2::Private*>(data);
141     assert(priv->input_method_ptr == zwp_input_method_v2);
142     priv->pending.surrounding_text.change_cause = convert_change_cause(cause);
143 }
144 
content_type_callback(void * data,zwp_input_method_v2 * zwp_input_method_v2,uint32_t hint,uint32_t purpose)145 void input_method_v2::Private::content_type_callback(void* data,
146                                                      zwp_input_method_v2* zwp_input_method_v2,
147                                                      uint32_t hint,
148                                                      uint32_t purpose)
149 {
150     auto priv = reinterpret_cast<input_method_v2::Private*>(data);
151     assert(priv->input_method_ptr == zwp_input_method_v2);
152     priv->pending.content.hints = convert_content_hints(hint);
153     priv->pending.content.purpose = convert_content_purpose(purpose);
154 }
155 
done_callback(void * data,zwp_input_method_v2 * zwp_input_method_v2)156 void input_method_v2::Private::done_callback(void* data, zwp_input_method_v2* zwp_input_method_v2)
157 {
158     auto priv = reinterpret_cast<input_method_v2::Private*>(data);
159     assert(priv->input_method_ptr == zwp_input_method_v2);
160     priv->serial++;
161     priv->current = priv->pending;
162     Q_EMIT priv->q_ptr->done();
163 }
164 
unavailable_callback(void * data,zwp_input_method_v2 * zwp_input_method_v2)165 void input_method_v2::Private::unavailable_callback(void* data,
166                                                     zwp_input_method_v2* zwp_input_method_v2)
167 {
168     auto priv = reinterpret_cast<input_method_v2::Private*>(data);
169     assert(priv->input_method_ptr == zwp_input_method_v2);
170     Q_EMIT priv->q_ptr->unavailable();
171 }
172 
setup(zwp_input_method_v2 * input_method)173 void input_method_v2::Private::setup(zwp_input_method_v2* input_method)
174 {
175     assert(input_method);
176     assert(!input_method_ptr);
177     input_method_ptr.setup(input_method);
178     zwp_input_method_v2_add_listener(input_method, &s_listener, this);
179 }
180 
isValid() const181 bool input_method_v2::Private::isValid() const
182 {
183     return input_method_ptr.isValid();
184 }
185 
input_method_v2(Seat * seat,QObject * parent)186 input_method_v2::input_method_v2(Seat* seat, QObject* parent)
187     : QObject(parent)
188     , d_ptr(new Private(seat, this))
189 {
190 }
191 
~input_method_v2()192 input_method_v2::~input_method_v2()
193 {
194     release();
195 }
196 
setEventQueue(EventQueue * queue)197 void input_method_v2::setEventQueue(EventQueue* queue)
198 {
199     d_ptr->queue = queue;
200 }
201 
event_queue() const202 EventQueue* input_method_v2::event_queue() const
203 {
204     return d_ptr->queue;
205 }
206 
isValid() const207 bool input_method_v2::isValid() const
208 {
209     return d_ptr->isValid();
210 }
211 
state() const212 input_method_v2_state const& input_method_v2::state() const
213 {
214     return d_ptr->current;
215 }
216 
setup(zwp_input_method_v2 * input_method)217 void input_method_v2::setup(zwp_input_method_v2* input_method)
218 {
219     d_ptr->setup(input_method);
220 }
221 
release()222 void input_method_v2::release()
223 {
224     d_ptr->input_method_ptr.release();
225 }
226 
operator zwp_input_method_v2*()227 input_method_v2::operator zwp_input_method_v2*()
228 {
229     return d_ptr->input_method_ptr;
230 }
231 
operator zwp_input_method_v2*() const232 input_method_v2::operator zwp_input_method_v2*() const
233 {
234     return d_ptr->input_method_ptr;
235 }
236 
commit_string(std::string const & text)237 void input_method_v2::commit_string(std::string const& text)
238 {
239     zwp_input_method_v2_commit_string(d_ptr->input_method_ptr, text.c_str());
240 }
241 
set_preedit_string(std::string const & text,int32_t cursor_begin,int32_t cursor_end)242 void input_method_v2::set_preedit_string(std::string const& text,
243                                          int32_t cursor_begin,
244                                          int32_t cursor_end)
245 {
246     zwp_input_method_v2_set_preedit_string(
247         d_ptr->input_method_ptr, text.c_str(), cursor_begin, cursor_end);
248 }
249 
delete_surrounding_text(uint32_t before_length,uint32_t after_length)250 void input_method_v2::delete_surrounding_text(uint32_t before_length, uint32_t after_length)
251 {
252     zwp_input_method_v2_delete_surrounding_text(
253         d_ptr->input_method_ptr, before_length, after_length);
254 }
255 
commit()256 void input_method_v2::commit()
257 {
258     zwp_input_method_v2_commit(d_ptr->input_method_ptr, d_ptr->serial);
259 }
260 
get_input_popup_surface(Surface * surface,QObject * parent)261 input_popup_surface_v2* input_method_v2::get_input_popup_surface(Surface* surface, QObject* parent)
262 {
263     assert(isValid());
264     auto ips = new input_popup_surface_v2(parent);
265     auto wlips = zwp_input_method_v2_get_input_popup_surface(d_ptr->input_method_ptr, *surface);
266     if (d_ptr->queue) {
267         d_ptr->queue->addProxy(wlips);
268     }
269     ips->setup(wlips);
270     return ips;
271 }
272 
grab_keyboard(QObject * parent)273 input_method_keyboard_grab_v2* input_method_v2::grab_keyboard(QObject* parent)
274 {
275     assert(isValid());
276     auto kg = new input_method_keyboard_grab_v2(parent);
277     auto wlkg = zwp_input_method_v2_grab_keyboard(d_ptr->input_method_ptr);
278     if (d_ptr->queue) {
279         d_ptr->queue->addProxy(wlkg);
280     }
281     kg->setup(wlkg);
282     return kg;
283 }
284 
Private(input_popup_surface_v2 * q)285 input_popup_surface_v2::Private::Private(input_popup_surface_v2* q)
286     : q_ptr{q}
287 {
288 }
289 
290 zwp_input_popup_surface_v2_listener const input_popup_surface_v2::Private::s_listener = {
291     text_input_rectangle_callback,
292 };
293 
text_input_rectangle_callback(void * data,zwp_input_popup_surface_v2 * zwp_input_popup_surface_v2,int32_t x,int32_t y,int32_t width,int32_t height)294 void input_popup_surface_v2::Private::text_input_rectangle_callback(
295     void* data,
296     zwp_input_popup_surface_v2* zwp_input_popup_surface_v2,
297     int32_t x,
298     int32_t y,
299     int32_t width,
300     int32_t height)
301 {
302     auto priv = reinterpret_cast<input_popup_surface_v2::Private*>(data);
303     assert(priv->input_popup_ptr == zwp_input_popup_surface_v2);
304     priv->text_input_rectangle = QRect(x, y, width, height);
305     Q_EMIT priv->q_ptr->text_input_rectangle_changed();
306 }
307 
setup(zwp_input_popup_surface_v2 * input_popup_surface)308 void input_popup_surface_v2::Private::setup(zwp_input_popup_surface_v2* input_popup_surface)
309 {
310     assert(input_popup_surface);
311     assert(!input_popup_ptr);
312     input_popup_ptr.setup(input_popup_surface);
313     zwp_input_popup_surface_v2_add_listener(input_popup_surface, &s_listener, this);
314 }
315 
isValid() const316 bool input_popup_surface_v2::Private::isValid() const
317 {
318     return input_popup_ptr.isValid();
319 }
320 
input_popup_surface_v2(QObject * parent)321 input_popup_surface_v2::input_popup_surface_v2(QObject* parent)
322     : QObject(parent)
323     , d_ptr(new Private(this))
324 {
325 }
326 
~input_popup_surface_v2()327 input_popup_surface_v2::~input_popup_surface_v2()
328 {
329     release();
330 }
331 
setEventQueue(EventQueue * queue)332 void input_popup_surface_v2::setEventQueue(EventQueue* queue)
333 {
334     d_ptr->queue = queue;
335 }
336 
event_queue() const337 EventQueue* input_popup_surface_v2::event_queue() const
338 {
339     return d_ptr->queue;
340 }
341 
isValid() const342 bool input_popup_surface_v2::isValid() const
343 {
344     return d_ptr->isValid();
345 }
346 
setup(zwp_input_popup_surface_v2 * input_popup_surface)347 void input_popup_surface_v2::setup(zwp_input_popup_surface_v2* input_popup_surface)
348 {
349     d_ptr->setup(input_popup_surface);
350 }
351 
release()352 void input_popup_surface_v2::release()
353 {
354     d_ptr->input_popup_ptr.release();
355 }
356 
operator zwp_input_popup_surface_v2*()357 input_popup_surface_v2::operator zwp_input_popup_surface_v2*()
358 {
359     return d_ptr->input_popup_ptr;
360 }
361 
operator zwp_input_popup_surface_v2*() const362 input_popup_surface_v2::operator zwp_input_popup_surface_v2*() const
363 {
364     return d_ptr->input_popup_ptr;
365 }
366 
text_input_rectangle() const367 QRect input_popup_surface_v2::text_input_rectangle() const
368 {
369     return d_ptr->text_input_rectangle;
370 }
371 
Private(input_method_keyboard_grab_v2 * q)372 input_method_keyboard_grab_v2::Private::Private(input_method_keyboard_grab_v2* q)
373     : q_ptr{q}
374 {
375 }
376 
377 zwp_input_method_keyboard_grab_v2_listener const input_method_keyboard_grab_v2::Private::s_listener
378     = {
379         keymap_callback,
380         key_callback,
381         modifiers_callback,
382         repeat_info_callback,
383 };
384 
keymap_callback(void * data,zwp_input_method_keyboard_grab_v2 * zwp_input_method_keyboard_grab_v2,uint32_t format,int fd,uint32_t size)385 void input_method_keyboard_grab_v2::Private::keymap_callback(
386     void* data,
387     zwp_input_method_keyboard_grab_v2* zwp_input_method_keyboard_grab_v2,
388     uint32_t format,
389     int fd,
390     uint32_t size)
391 {
392     auto priv = reinterpret_cast<input_method_keyboard_grab_v2::Private*>(data);
393     assert(priv->keyboard_grab_ptr == zwp_input_method_keyboard_grab_v2);
394 
395     if (format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1) {
396         return;
397     }
398     Q_EMIT priv->q_ptr->keymap_changed(fd, size);
399 }
400 
key_callback(void * data,zwp_input_method_keyboard_grab_v2 * zwp_input_method_keyboard_grab_v2,uint32_t serial,uint32_t time,uint32_t key,uint32_t state)401 void input_method_keyboard_grab_v2::Private::key_callback(
402     void* data,
403     zwp_input_method_keyboard_grab_v2* zwp_input_method_keyboard_grab_v2,
404     [[maybe_unused]] uint32_t serial,
405     uint32_t time,
406     uint32_t key,
407     uint32_t state)
408 {
409     auto priv = reinterpret_cast<input_method_keyboard_grab_v2::Private*>(data);
410     assert(priv->keyboard_grab_ptr == zwp_input_method_keyboard_grab_v2);
411 
412     auto to_state = [state] {
413         if (state == WL_KEYBOARD_KEY_STATE_RELEASED) {
414             return Keyboard::KeyState::Released;
415         } else {
416             return Keyboard::KeyState::Pressed;
417         }
418     };
419     Q_EMIT priv->q_ptr->key_changed(key, to_state(), time);
420 }
421 
modifiers_callback(void * data,zwp_input_method_keyboard_grab_v2 * zwp_input_method_keyboard_grab_v2,uint32_t serial,uint32_t depressed,uint32_t latched,uint32_t locked,uint32_t group)422 void input_method_keyboard_grab_v2::Private::modifiers_callback(
423     void* data,
424     zwp_input_method_keyboard_grab_v2* zwp_input_method_keyboard_grab_v2,
425     [[maybe_unused]] uint32_t serial,
426     uint32_t depressed,
427     uint32_t latched,
428     uint32_t locked,
429     uint32_t group)
430 {
431     auto priv = reinterpret_cast<input_method_keyboard_grab_v2::Private*>(data);
432     assert(priv->keyboard_grab_ptr == zwp_input_method_keyboard_grab_v2);
433 
434     Q_EMIT priv->q_ptr->modifiers_changed(depressed, latched, locked, group);
435 }
436 
repeat_info_callback(void * data,zwp_input_method_keyboard_grab_v2 * zwp_input_method_keyboard_grab_v2,int32_t rate,int32_t delay)437 void input_method_keyboard_grab_v2::Private::repeat_info_callback(
438     void* data,
439     zwp_input_method_keyboard_grab_v2* zwp_input_method_keyboard_grab_v2,
440     int32_t rate,
441     int32_t delay)
442 {
443     auto priv = reinterpret_cast<input_method_keyboard_grab_v2::Private*>(data);
444     assert(priv->keyboard_grab_ptr == zwp_input_method_keyboard_grab_v2);
445 
446     priv->repeat_info.rate = std::max(rate, 0);
447     priv->repeat_info.delay = std::max(delay, 0);
448     Q_EMIT priv->q_ptr->repeat_changed();
449 }
450 
setup(zwp_input_method_keyboard_grab_v2 * keyboard_grab)451 void input_method_keyboard_grab_v2::Private::setup(zwp_input_method_keyboard_grab_v2* keyboard_grab)
452 {
453     assert(keyboard_grab);
454     assert(!keyboard_grab_ptr);
455     keyboard_grab_ptr.setup(keyboard_grab);
456     zwp_input_method_keyboard_grab_v2_add_listener(keyboard_grab, &s_listener, this);
457 }
458 
isValid() const459 bool input_method_keyboard_grab_v2::Private::isValid() const
460 {
461     return keyboard_grab_ptr.isValid();
462 }
463 
input_method_keyboard_grab_v2(QObject * parent)464 input_method_keyboard_grab_v2::input_method_keyboard_grab_v2(QObject* parent)
465     : QObject(parent)
466     , d_ptr(new Private(this))
467 {
468 }
469 
~input_method_keyboard_grab_v2()470 input_method_keyboard_grab_v2::~input_method_keyboard_grab_v2()
471 {
472     release();
473 }
474 
setEventQueue(EventQueue * queue)475 void input_method_keyboard_grab_v2::setEventQueue(EventQueue* queue)
476 {
477     d_ptr->queue = queue;
478 }
479 
event_queue() const480 EventQueue* input_method_keyboard_grab_v2::event_queue() const
481 {
482     return d_ptr->queue;
483 }
484 
isValid() const485 bool input_method_keyboard_grab_v2::isValid() const
486 {
487     return d_ptr->isValid();
488 }
489 
setup(zwp_input_method_keyboard_grab_v2 * keyboard_grab)490 void input_method_keyboard_grab_v2::setup(zwp_input_method_keyboard_grab_v2* keyboard_grab)
491 {
492     d_ptr->setup(keyboard_grab);
493 }
494 
release()495 void input_method_keyboard_grab_v2::release()
496 {
497     d_ptr->keyboard_grab_ptr.release();
498 }
499 
operator zwp_input_method_keyboard_grab_v2*()500 input_method_keyboard_grab_v2::operator zwp_input_method_keyboard_grab_v2*()
501 {
502     return d_ptr->keyboard_grab_ptr;
503 }
504 
operator zwp_input_method_keyboard_grab_v2*() const505 input_method_keyboard_grab_v2::operator zwp_input_method_keyboard_grab_v2*() const
506 {
507     return d_ptr->keyboard_grab_ptr;
508 }
509 
repeat_rate() const510 int32_t input_method_keyboard_grab_v2::repeat_rate() const
511 {
512     return d_ptr->repeat_info.rate;
513 }
514 
repeat_delay() const515 int32_t input_method_keyboard_grab_v2::repeat_delay() const
516 {
517     return d_ptr->repeat_info.delay;
518 }
519 
520 }
521