1 /*
2 * Copyright (C) 2017, 2018 Red Hat
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
17 * 02111-1307, USA.
18 *
19 * Author: Carlos Garnacho <carlosg@gnome.org>
20 */
21
22 #include "config.h"
23
24 #include <wayland-server.h>
25
26 #include "wayland/meta-wayland-private.h"
27 #include "wayland/meta-wayland-seat.h"
28 #include "wayland/meta-wayland-text-input-legacy.h"
29 #include "wayland/meta-wayland-versions.h"
30
31 #include "gtk-text-input-server-protocol.h"
32
33 #define META_TYPE_WAYLAND_GTK_TEXT_INPUT_FOCUS (meta_wayland_gtk_text_input_focus_get_type ())
34
35 typedef enum
36 {
37 META_WAYLAND_PENDING_STATE_NONE = 0,
38 META_WAYLAND_PENDING_STATE_INPUT_RECT = 1 << 0,
39 META_WAYLAND_PENDING_STATE_CONTENT_TYPE = 1 << 1,
40 META_WAYLAND_PENDING_STATE_SURROUNDING_TEXT = 1 << 2,
41 } MetaWaylandTextInputPendingState;
42
43 typedef struct _MetaWaylandGtkTextInput MetaWaylandGtkTextInput;
44
45 struct _MetaWaylandGtkTextInput
46 {
47 MetaWaylandSeat *seat;
48 ClutterInputFocus *input_focus;
49
50 struct wl_list resource_list;
51 struct wl_list focus_resource_list;
52 MetaWaylandSurface *surface;
53 struct wl_listener surface_listener;
54 uint32_t focus_serial;
55
56 MetaWaylandTextInputPendingState pending_state;
57
58 struct
59 {
60 char *text;
61 uint32_t cursor;
62 uint32_t anchor;
63 } surrounding;
64
65 cairo_rectangle_int_t cursor_rect;
66
67 uint32_t content_type_hint;
68 uint32_t content_type_purpose;
69 };
70
71 struct _MetaWaylandGtkTextInputFocus
72 {
73 ClutterInputFocus parent_instance;
74 MetaWaylandGtkTextInput *text_input;
75 };
76
G_DECLARE_FINAL_TYPE(MetaWaylandGtkTextInputFocus,meta_wayland_gtk_text_input_focus,META,WAYLAND_GTK_TEXT_INPUT_FOCUS,ClutterInputFocus)77 G_DECLARE_FINAL_TYPE (MetaWaylandGtkTextInputFocus,
78 meta_wayland_gtk_text_input_focus,
79 META, WAYLAND_GTK_TEXT_INPUT_FOCUS, ClutterInputFocus)
80 G_DEFINE_TYPE (MetaWaylandGtkTextInputFocus, meta_wayland_gtk_text_input_focus,
81 CLUTTER_TYPE_INPUT_FOCUS)
82
83 static void
84 meta_wayland_text_input_focus_request_surrounding (ClutterInputFocus *focus)
85 {
86 MetaWaylandGtkTextInput *text_input;
87
88 text_input = META_WAYLAND_GTK_TEXT_INPUT_FOCUS (focus)->text_input;
89 clutter_input_focus_set_surrounding (focus,
90 text_input->surrounding.text,
91 text_input->surrounding.cursor,
92 text_input->surrounding.anchor);
93 }
94
95 static void
meta_wayland_text_input_focus_delete_surrounding(ClutterInputFocus * focus,int offset,guint len)96 meta_wayland_text_input_focus_delete_surrounding (ClutterInputFocus *focus,
97 int offset,
98 guint len)
99 {
100 MetaWaylandGtkTextInput *text_input;
101 uint32_t before_length;
102 uint32_t after_length;
103 struct wl_resource *resource;
104
105 text_input = META_WAYLAND_GTK_TEXT_INPUT_FOCUS (focus)->text_input;
106 before_length = ABS (MIN (offset, 0));
107 after_length = MAX (0, offset + len);
108 g_warn_if_fail (ABS (offset) <= len);
109
110 wl_resource_for_each (resource, &text_input->focus_resource_list)
111 {
112 gtk_text_input_send_delete_surrounding_text (resource,
113 before_length,
114 after_length);
115 }
116 }
117
118 static void
meta_wayland_text_input_focus_commit_text(ClutterInputFocus * focus,const gchar * text)119 meta_wayland_text_input_focus_commit_text (ClutterInputFocus *focus,
120 const gchar *text)
121 {
122 MetaWaylandGtkTextInput *text_input;
123 struct wl_resource *resource;
124
125 text_input = META_WAYLAND_GTK_TEXT_INPUT_FOCUS (focus)->text_input;
126
127 wl_resource_for_each (resource, &text_input->focus_resource_list)
128 {
129 gtk_text_input_send_preedit_string (resource, NULL, 0);
130 gtk_text_input_send_commit_string (resource, text);
131 }
132 }
133
134 static void
meta_wayland_text_input_focus_set_preedit_text(ClutterInputFocus * focus,const gchar * text,guint cursor)135 meta_wayland_text_input_focus_set_preedit_text (ClutterInputFocus *focus,
136 const gchar *text,
137 guint cursor)
138 {
139 MetaWaylandGtkTextInput *text_input;
140 struct wl_resource *resource;
141
142 text_input = META_WAYLAND_GTK_TEXT_INPUT_FOCUS (focus)->text_input;
143
144 wl_resource_for_each (resource, &text_input->focus_resource_list)
145 {
146 gtk_text_input_send_preedit_string (resource, text, cursor);
147 }
148 }
149
150 static void
meta_wayland_gtk_text_input_focus_class_init(MetaWaylandGtkTextInputFocusClass * klass)151 meta_wayland_gtk_text_input_focus_class_init (MetaWaylandGtkTextInputFocusClass *klass)
152 {
153 ClutterInputFocusClass *focus_class = CLUTTER_INPUT_FOCUS_CLASS (klass);
154
155 focus_class->request_surrounding = meta_wayland_text_input_focus_request_surrounding;
156 focus_class->delete_surrounding = meta_wayland_text_input_focus_delete_surrounding;
157 focus_class->commit_text = meta_wayland_text_input_focus_commit_text;
158 focus_class->set_preedit_text = meta_wayland_text_input_focus_set_preedit_text;
159 }
160
161 static void
meta_wayland_gtk_text_input_focus_init(MetaWaylandGtkTextInputFocus * focus)162 meta_wayland_gtk_text_input_focus_init (MetaWaylandGtkTextInputFocus *focus)
163 {
164 }
165
166 static ClutterInputFocus *
meta_wayland_text_input_focus_new(MetaWaylandGtkTextInput * text_input)167 meta_wayland_text_input_focus_new (MetaWaylandGtkTextInput *text_input)
168 {
169 MetaWaylandGtkTextInputFocus *focus;
170
171 focus = g_object_new (META_TYPE_WAYLAND_GTK_TEXT_INPUT_FOCUS, NULL);
172 focus->text_input = text_input;
173
174 return CLUTTER_INPUT_FOCUS (focus);
175 }
176
177 static void
text_input_handle_focus_surface_destroy(struct wl_listener * listener,void * data)178 text_input_handle_focus_surface_destroy (struct wl_listener *listener,
179 void *data)
180 {
181 MetaWaylandGtkTextInput *text_input = wl_container_of (listener, text_input,
182 surface_listener);
183
184 meta_wayland_gtk_text_input_set_focus (text_input, NULL);
185 }
186
187 static void
move_resources(struct wl_list * destination,struct wl_list * source)188 move_resources (struct wl_list *destination, struct wl_list *source)
189 {
190 wl_list_insert_list (destination, source);
191 wl_list_init (source);
192 }
193
194 static void
move_resources_for_client(struct wl_list * destination,struct wl_list * source,struct wl_client * client)195 move_resources_for_client (struct wl_list *destination,
196 struct wl_list *source,
197 struct wl_client *client)
198 {
199 struct wl_resource *resource, *tmp;
200 wl_resource_for_each_safe (resource, tmp, source)
201 {
202 if (wl_resource_get_client (resource) == client)
203 {
204 wl_list_remove (wl_resource_get_link (resource));
205 wl_list_insert (destination, wl_resource_get_link (resource));
206 }
207 }
208 }
209
210 void
meta_wayland_gtk_text_input_set_focus(MetaWaylandGtkTextInput * text_input,MetaWaylandSurface * surface)211 meta_wayland_gtk_text_input_set_focus (MetaWaylandGtkTextInput *text_input,
212 MetaWaylandSurface *surface)
213 {
214 if (text_input->surface == surface)
215 return;
216
217 text_input->pending_state = META_WAYLAND_PENDING_STATE_NONE;
218
219 if (text_input->surface)
220 {
221 if (!wl_list_empty (&text_input->focus_resource_list))
222 {
223 ClutterInputFocus *focus = text_input->input_focus;
224 ClutterInputMethod *input_method;
225 struct wl_resource *resource;
226 uint32_t serial;
227
228 if (clutter_input_focus_is_focused (focus))
229 {
230 input_method = clutter_backend_get_input_method (clutter_get_default_backend ());
231 clutter_input_method_focus_out (input_method);
232 }
233
234 serial = wl_display_next_serial (text_input->seat->wl_display);
235
236 wl_resource_for_each (resource, &text_input->focus_resource_list)
237 {
238 gtk_text_input_send_leave (resource, serial,
239 text_input->surface->resource);
240 }
241
242 move_resources (&text_input->resource_list,
243 &text_input->focus_resource_list);
244 }
245
246 wl_list_remove (&text_input->surface_listener.link);
247 text_input->surface = NULL;
248 }
249
250 if (surface)
251 {
252 struct wl_resource *focus_surface_resource;
253
254 text_input->surface = surface;
255 focus_surface_resource = text_input->surface->resource;
256 wl_resource_add_destroy_listener (focus_surface_resource,
257 &text_input->surface_listener);
258
259 move_resources_for_client (&text_input->focus_resource_list,
260 &text_input->resource_list,
261 wl_resource_get_client (focus_surface_resource));
262
263 if (!wl_list_empty (&text_input->focus_resource_list))
264 {
265 struct wl_resource *resource;
266
267 text_input->focus_serial =
268 wl_display_next_serial (text_input->seat->wl_display);
269
270 wl_resource_for_each (resource, &text_input->focus_resource_list)
271 {
272 gtk_text_input_send_enter (resource, text_input->focus_serial,
273 surface->resource);
274 }
275 }
276 }
277 }
278
279 static void
unbind_resource(struct wl_resource * resource)280 unbind_resource (struct wl_resource *resource)
281 {
282 wl_list_remove (wl_resource_get_link (resource));
283 }
284
285 static void
text_input_destroy(struct wl_client * client,struct wl_resource * resource)286 text_input_destroy (struct wl_client *client,
287 struct wl_resource *resource)
288 {
289 wl_resource_destroy (resource);
290 }
291
292 static void
text_input_enable(struct wl_client * client,struct wl_resource * resource,uint32_t serial,uint32_t flags)293 text_input_enable (struct wl_client *client,
294 struct wl_resource *resource,
295 uint32_t serial,
296 uint32_t flags)
297 {
298 MetaWaylandGtkTextInput *text_input = wl_resource_get_user_data (resource);
299 ClutterInputFocus *focus = text_input->input_focus;
300 ClutterInputMethod *input_method;
301 gboolean show_preedit;
302
303 if (serial != text_input->focus_serial)
304 return;
305
306 if (!clutter_input_focus_is_focused (focus))
307 {
308 input_method = clutter_backend_get_input_method (clutter_get_default_backend ());
309 if (input_method)
310 clutter_input_method_focus_in (input_method, focus);
311 else
312 return;
313 }
314
315 show_preedit = (flags & GTK_TEXT_INPUT_ENABLE_FLAGS_CAN_SHOW_PREEDIT) != 0;
316 clutter_input_focus_set_can_show_preedit (focus, show_preedit);
317
318 if (flags & GTK_TEXT_INPUT_ENABLE_FLAGS_TOGGLE_INPUT_PANEL)
319 clutter_input_focus_set_input_panel_state (focus, CLUTTER_INPUT_PANEL_STATE_TOGGLE);
320 }
321
322 static void
text_input_disable(struct wl_client * client,struct wl_resource * resource)323 text_input_disable (struct wl_client *client,
324 struct wl_resource *resource)
325 {
326 MetaWaylandGtkTextInput *text_input = wl_resource_get_user_data (resource);
327 ClutterInputFocus *focus = text_input->input_focus;
328 ClutterInputMethod *input_method;
329
330 if (!clutter_input_focus_is_focused (focus))
331 return;
332
333 clutter_input_focus_reset (text_input->input_focus);
334 text_input->pending_state = META_WAYLAND_PENDING_STATE_NONE;
335
336 input_method = clutter_backend_get_input_method (clutter_get_default_backend ());
337 clutter_input_method_focus_out (input_method);
338 }
339
340 static void
text_input_set_surrounding_text(struct wl_client * client,struct wl_resource * resource,const char * text,int32_t cursor,int32_t anchor)341 text_input_set_surrounding_text (struct wl_client *client,
342 struct wl_resource *resource,
343 const char *text,
344 int32_t cursor,
345 int32_t anchor)
346 {
347 MetaWaylandGtkTextInput *text_input = wl_resource_get_user_data (resource);
348
349 g_free (text_input->surrounding.text);
350 text_input->surrounding.text = g_strdup (text);
351 text_input->surrounding.cursor = cursor;
352 text_input->surrounding.anchor = anchor;
353 text_input->pending_state |= META_WAYLAND_PENDING_STATE_SURROUNDING_TEXT;
354 }
355
356 static ClutterInputContentHintFlags
translate_hints(uint32_t hints)357 translate_hints (uint32_t hints)
358 {
359 ClutterInputContentHintFlags clutter_hints = 0;
360
361 if (hints & GTK_TEXT_INPUT_CONTENT_HINT_COMPLETION)
362 clutter_hints |= CLUTTER_INPUT_CONTENT_HINT_COMPLETION;
363 if (hints & GTK_TEXT_INPUT_CONTENT_HINT_SPELLCHECK)
364 clutter_hints |= CLUTTER_INPUT_CONTENT_HINT_SPELLCHECK;
365 if (hints & GTK_TEXT_INPUT_CONTENT_HINT_AUTO_CAPITALIZATION)
366 clutter_hints |= CLUTTER_INPUT_CONTENT_HINT_AUTO_CAPITALIZATION;
367 if (hints & GTK_TEXT_INPUT_CONTENT_HINT_LOWERCASE)
368 clutter_hints |= CLUTTER_INPUT_CONTENT_HINT_LOWERCASE;
369 if (hints & GTK_TEXT_INPUT_CONTENT_HINT_UPPERCASE)
370 clutter_hints |= CLUTTER_INPUT_CONTENT_HINT_UPPERCASE;
371 if (hints & GTK_TEXT_INPUT_CONTENT_HINT_TITLECASE)
372 clutter_hints |= CLUTTER_INPUT_CONTENT_HINT_TITLECASE;
373 if (hints & GTK_TEXT_INPUT_CONTENT_HINT_HIDDEN_TEXT)
374 clutter_hints |= CLUTTER_INPUT_CONTENT_HINT_HIDDEN_TEXT;
375 if (hints & GTK_TEXT_INPUT_CONTENT_HINT_SENSITIVE_DATA)
376 clutter_hints |= CLUTTER_INPUT_CONTENT_HINT_SENSITIVE_DATA;
377 if (hints & GTK_TEXT_INPUT_CONTENT_HINT_LATIN)
378 clutter_hints |= CLUTTER_INPUT_CONTENT_HINT_LATIN;
379 if (hints & GTK_TEXT_INPUT_CONTENT_HINT_MULTILINE)
380 clutter_hints |= CLUTTER_INPUT_CONTENT_HINT_MULTILINE;
381
382 return clutter_hints;
383 }
384
385 static ClutterInputContentPurpose
translate_purpose(uint32_t purpose)386 translate_purpose (uint32_t purpose)
387 {
388 switch (purpose)
389 {
390 case GTK_TEXT_INPUT_CONTENT_PURPOSE_NORMAL:
391 return CLUTTER_INPUT_CONTENT_PURPOSE_NORMAL;
392 case GTK_TEXT_INPUT_CONTENT_PURPOSE_ALPHA:
393 return CLUTTER_INPUT_CONTENT_PURPOSE_ALPHA;
394 case GTK_TEXT_INPUT_CONTENT_PURPOSE_DIGITS:
395 return CLUTTER_INPUT_CONTENT_PURPOSE_DIGITS;
396 case GTK_TEXT_INPUT_CONTENT_PURPOSE_NUMBER:
397 return CLUTTER_INPUT_CONTENT_PURPOSE_NUMBER;
398 case GTK_TEXT_INPUT_CONTENT_PURPOSE_PHONE:
399 return CLUTTER_INPUT_CONTENT_PURPOSE_PHONE;
400 case GTK_TEXT_INPUT_CONTENT_PURPOSE_URL:
401 return CLUTTER_INPUT_CONTENT_PURPOSE_URL;
402 case GTK_TEXT_INPUT_CONTENT_PURPOSE_EMAIL:
403 return CLUTTER_INPUT_CONTENT_PURPOSE_EMAIL;
404 case GTK_TEXT_INPUT_CONTENT_PURPOSE_NAME:
405 return CLUTTER_INPUT_CONTENT_PURPOSE_NAME;
406 case GTK_TEXT_INPUT_CONTENT_PURPOSE_PASSWORD:
407 return CLUTTER_INPUT_CONTENT_PURPOSE_PASSWORD;
408 case GTK_TEXT_INPUT_CONTENT_PURPOSE_DATE:
409 return CLUTTER_INPUT_CONTENT_PURPOSE_DATE;
410 case GTK_TEXT_INPUT_CONTENT_PURPOSE_TIME:
411 return CLUTTER_INPUT_CONTENT_PURPOSE_TIME;
412 case GTK_TEXT_INPUT_CONTENT_PURPOSE_DATETIME:
413 return CLUTTER_INPUT_CONTENT_PURPOSE_DATETIME;
414 case GTK_TEXT_INPUT_CONTENT_PURPOSE_TERMINAL:
415 return CLUTTER_INPUT_CONTENT_PURPOSE_TERMINAL;
416 }
417
418 g_warn_if_reached ();
419 return CLUTTER_INPUT_CONTENT_PURPOSE_NORMAL;
420 }
421
422 static void
text_input_set_content_type(struct wl_client * client,struct wl_resource * resource,uint32_t hint,uint32_t purpose)423 text_input_set_content_type (struct wl_client *client,
424 struct wl_resource *resource,
425 uint32_t hint,
426 uint32_t purpose)
427 {
428 MetaWaylandGtkTextInput *text_input = wl_resource_get_user_data (resource);
429
430 if (!text_input->surface)
431 return;
432
433 text_input->content_type_hint = hint;
434 text_input->content_type_purpose = purpose;
435 text_input->pending_state |= META_WAYLAND_PENDING_STATE_CONTENT_TYPE;
436 }
437
438 static void
text_input_set_cursor_rectangle(struct wl_client * client,struct wl_resource * resource,int32_t x,int32_t y,int32_t width,int32_t height)439 text_input_set_cursor_rectangle (struct wl_client *client,
440 struct wl_resource *resource,
441 int32_t x,
442 int32_t y,
443 int32_t width,
444 int32_t height)
445 {
446 MetaWaylandGtkTextInput *text_input = wl_resource_get_user_data (resource);
447
448 if (!text_input->surface)
449 return;
450
451 text_input->cursor_rect = (cairo_rectangle_int_t) { x, y, width, height };
452 text_input->pending_state |= META_WAYLAND_PENDING_STATE_INPUT_RECT;
453 }
454
455 static void
text_input_commit_state(struct wl_client * client,struct wl_resource * resource)456 text_input_commit_state (struct wl_client *client,
457 struct wl_resource *resource)
458 {
459 MetaWaylandGtkTextInput *text_input = wl_resource_get_user_data (resource);
460 ClutterInputFocus *focus = text_input->input_focus;
461
462 if (!clutter_input_focus_is_focused (focus))
463 return;
464 if (text_input->surface == NULL)
465 return;
466
467 if (text_input->pending_state & META_WAYLAND_PENDING_STATE_CONTENT_TYPE)
468 {
469 clutter_input_focus_set_content_hints (text_input->input_focus,
470 translate_hints (text_input->content_type_hint));
471 clutter_input_focus_set_content_purpose (text_input->input_focus,
472 translate_purpose (text_input->content_type_purpose));
473 }
474
475 if (text_input->pending_state & META_WAYLAND_PENDING_STATE_SURROUNDING_TEXT)
476 {
477 clutter_input_focus_set_surrounding (text_input->input_focus,
478 text_input->surrounding.text,
479 text_input->surrounding.cursor,
480 text_input->surrounding.anchor);
481 }
482
483 if (text_input->pending_state & META_WAYLAND_PENDING_STATE_INPUT_RECT)
484 {
485 graphene_rect_t cursor_rect;
486 float x1, y1, x2, y2;
487 cairo_rectangle_int_t rect;
488
489 rect = text_input->cursor_rect;
490 meta_wayland_surface_get_absolute_coordinates (text_input->surface,
491 rect.x, rect.y, &x1, &y1);
492 meta_wayland_surface_get_absolute_coordinates (text_input->surface,
493 rect.x + rect.width,
494 rect.y + rect.height,
495 &x2, &y2);
496
497 graphene_rect_init (&cursor_rect, x1, y1, x2 - x1, y2 - y1);
498 clutter_input_focus_set_cursor_location (text_input->input_focus,
499 &cursor_rect);
500 }
501
502 text_input->pending_state = META_WAYLAND_PENDING_STATE_NONE;
503 }
504
505 static struct gtk_text_input_interface meta_text_input_interface = {
506 text_input_destroy,
507 text_input_enable,
508 text_input_disable,
509 text_input_set_surrounding_text,
510 text_input_set_content_type,
511 text_input_set_cursor_rectangle,
512 text_input_commit_state,
513 };
514
515 MetaWaylandGtkTextInput *
meta_wayland_gtk_text_input_new(MetaWaylandSeat * seat)516 meta_wayland_gtk_text_input_new (MetaWaylandSeat *seat)
517 {
518 MetaWaylandGtkTextInput *text_input;
519
520 text_input = g_new0 (MetaWaylandGtkTextInput, 1);
521 text_input->input_focus = meta_wayland_text_input_focus_new (text_input);
522 text_input->seat = seat;
523
524 wl_list_init (&text_input->resource_list);
525 wl_list_init (&text_input->focus_resource_list);
526 text_input->surface_listener.notify = text_input_handle_focus_surface_destroy;
527
528 return text_input;
529 }
530
531 void
meta_wayland_gtk_text_input_destroy(MetaWaylandGtkTextInput * text_input)532 meta_wayland_gtk_text_input_destroy (MetaWaylandGtkTextInput *text_input)
533 {
534 meta_wayland_gtk_text_input_set_focus (text_input, NULL);
535 g_object_unref (text_input->input_focus);
536 g_free (text_input);
537 }
538
539 static void
meta_wayland_text_input_create_new_resource(MetaWaylandGtkTextInput * text_input,struct wl_client * client,struct wl_resource * seat_resource,uint32_t id)540 meta_wayland_text_input_create_new_resource (MetaWaylandGtkTextInput *text_input,
541 struct wl_client *client,
542 struct wl_resource *seat_resource,
543 uint32_t id)
544 {
545 struct wl_resource *text_input_resource;
546
547 text_input_resource = wl_resource_create (client,
548 >k_text_input_interface,
549 META_GTK_TEXT_INPUT_VERSION,
550 id);
551
552 wl_resource_set_implementation (text_input_resource,
553 &meta_text_input_interface,
554 text_input, unbind_resource);
555
556 if (text_input->surface &&
557 wl_resource_get_client (text_input->surface->resource) == client)
558 {
559 wl_list_insert (&text_input->focus_resource_list,
560 wl_resource_get_link (text_input_resource));
561
562 gtk_text_input_send_enter (text_input_resource,
563 text_input->focus_serial,
564 text_input->surface->resource);
565 }
566 else
567 {
568 wl_list_insert (&text_input->resource_list,
569 wl_resource_get_link (text_input_resource));
570 }
571 }
572
573 static void
text_input_manager_destroy(struct wl_client * client,struct wl_resource * resource)574 text_input_manager_destroy (struct wl_client *client,
575 struct wl_resource *resource)
576 {
577 wl_resource_destroy (resource);
578 }
579
580 static void
text_input_manager_get_text_input(struct wl_client * client,struct wl_resource * resource,uint32_t id,struct wl_resource * seat_resource)581 text_input_manager_get_text_input (struct wl_client *client,
582 struct wl_resource *resource,
583 uint32_t id,
584 struct wl_resource *seat_resource)
585 {
586 MetaWaylandSeat *seat = wl_resource_get_user_data (seat_resource);
587
588 meta_wayland_text_input_create_new_resource (seat->gtk_text_input, client,
589 seat_resource, id);
590 }
591
592 static struct gtk_text_input_manager_interface meta_text_input_manager_interface = {
593 text_input_manager_destroy,
594 text_input_manager_get_text_input,
595 };
596
597 static void
bind_text_input(struct wl_client * client,void * data,uint32_t version,uint32_t id)598 bind_text_input (struct wl_client *client,
599 void *data,
600 uint32_t version,
601 uint32_t id)
602 {
603 struct wl_resource *resource;
604
605 resource = wl_resource_create (client,
606 >k_text_input_manager_interface,
607 META_GTK_TEXT_INPUT_VERSION,
608 id);
609 wl_resource_set_implementation (resource,
610 &meta_text_input_manager_interface,
611 NULL, NULL);
612 }
613
614 gboolean
meta_wayland_gtk_text_input_init(MetaWaylandCompositor * compositor)615 meta_wayland_gtk_text_input_init (MetaWaylandCompositor *compositor)
616 {
617 return (wl_global_create (compositor->wayland_display,
618 >k_text_input_manager_interface,
619 META_GTK_TEXT_INPUT_VERSION,
620 compositor->seat->gtk_text_input,
621 bind_text_input) != NULL);
622 }
623
624 gboolean
meta_wayland_gtk_text_input_handle_event(MetaWaylandGtkTextInput * text_input,const ClutterEvent * event)625 meta_wayland_gtk_text_input_handle_event (MetaWaylandGtkTextInput *text_input,
626 const ClutterEvent *event)
627 {
628 if (!text_input->surface ||
629 !clutter_input_focus_is_focused (text_input->input_focus))
630 return FALSE;
631
632 return clutter_input_focus_filter_event (text_input->input_focus, event);
633 }
634