text-backend.c 28.3 KB
Newer Older
1
2
/*
 * Copyright © 2012 Openismus GmbH
3
 * Copyright © 2012 Intel Corporation
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
 *
 * Permission to use, copy, modify, distribute, and sell this software and
 * its documentation for any purpose is hereby granted without fee, provided
 * that the above copyright notice appear in all copies and that both that
 * copyright notice and this permission notice appear in supporting
 * documentation, and that the name of the copyright holders not be used in
 * advertising or publicity pertaining to distribution of the software
 * without specific, written prior permission.  The copyright holders make
 * no representations about the suitability of this software for any
 * purpose.  It is provided "as is" without express or implied warranty.
 *
 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
 * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
 * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
 * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
 * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

24
25
#include "config.h"

26
#include <stdbool.h>
27
#include <stdlib.h>
28
#include <string.h>
29
#include <unistd.h>
30
#include <time.h>
31
32
33

#include "compositor.h"
#include "text-server-protocol.h"
34
#include "input-method-server-protocol.h"
35

36
struct text_input_manager;
37
struct input_method;
38
struct input_method_context;
39
struct text_backend;
40

41
struct text_input {
42
	struct wl_resource *resource;
43

44
	struct weston_compositor *ec;
45

46
	struct wl_list input_methods;
47

48
	struct weston_surface *surface;
49

50
51
	pixman_box32_t cursor_rectangle;

52
	bool input_panel_visible;
53
54

	struct text_input_manager *manager;
55
56
};

57
58
struct text_input_manager {
	struct wl_global *text_input_manager_global;
59
60
	struct wl_listener destroy_listener;

61
62
	struct text_input *current_panel;

63
64
65
	struct weston_compositor *ec;
};

66
struct input_method {
67
68
	struct wl_resource *input_method_binding;
	struct wl_global *input_method_global;
69
70
	struct wl_listener destroy_listener;

71
	struct weston_seat *seat;
72
	struct text_input *input;
73
74

	struct wl_list link;
75
76
77
78

	struct wl_listener keyboard_focus_listener;

	int focus_listener_initialized;
79
80

	struct input_method_context *context;
81
82

	struct text_backend *text_backend;
83
84
85
};

struct input_method_context {
86
	struct wl_resource *resource;
87

88
	struct text_input *input;
89
	struct input_method *input_method;
90

91
	struct wl_resource *keyboard;
92
93
};

94
95
96
97
98
99
100
101
struct text_backend {
	struct weston_compositor *compositor;

	struct {
		char *path;
		struct wl_resource *binding;
		struct weston_process process;
		struct wl_client *client;
102
103
104

		unsigned deathcount;
		uint32_t deathstamp;
105
106
107
108
109
110
	} input_method;

	struct wl_listener seat_created_listener;
	struct wl_listener destroy_listener;
};

Derek Foreman's avatar
Derek Foreman committed
111
static void
112
input_method_context_create(struct text_input *input,
Derek Foreman's avatar
Derek Foreman committed
113
114
115
			    struct input_method *input_method);
static void
input_method_context_end_keyboard_grab(struct input_method_context *context);
116

Derek Foreman's avatar
Derek Foreman committed
117
118
static void
input_method_init_seat(struct weston_seat *seat);
119

120
static void
121
deactivate_input_method(struct input_method *input_method)
122
{
123
	struct text_input *text_input = input_method->input;
124
	struct weston_compositor *ec = text_input->ec;
125

126
127
128
129
130
131
132
	if (input_method->context && input_method->input_method_binding) {
		input_method_context_end_keyboard_grab(input_method->context);
		wl_input_method_send_deactivate(input_method->input_method_binding,
						input_method->context->resource);
	}

	wl_list_remove(&input_method->link);
133
	input_method->input = NULL;
134
135
136
137
	input_method->context = NULL;

	if (wl_list_empty(&text_input->input_methods) &&
	    text_input->input_panel_visible) {
138
		wl_signal_emit(&ec->hide_input_panel_signal, ec);
139
140
		text_input->input_panel_visible = false;
		text_input->manager->current_panel = NULL;
141
	}
142
	wl_text_input_send_leave(text_input->resource);
143
144
}

145
static void
146
destroy_text_input(struct wl_resource *resource)
147
{
148
	struct text_input *text_input = wl_resource_get_user_data(resource);
149
	struct input_method *input_method, *next;
150

151
	wl_list_for_each_safe(input_method, next, &text_input->input_methods, link)
152
		deactivate_input_method(input_method);
153

154
	free(text_input);
155
156
157
}

static void
158
text_input_set_surrounding_text(struct wl_client *client,
159
				struct wl_resource *resource,
160
161
162
				const char *text,
				uint32_t cursor,
				uint32_t anchor)
163
{
164
	struct text_input *text_input = wl_resource_get_user_data(resource);
165
166
	struct input_method *input_method, *next;

167
	wl_list_for_each_safe(input_method, next, &text_input->input_methods, link) {
168
169
		if (!input_method->context)
			continue;
170
		wl_input_method_context_send_surrounding_text(input_method->context->resource,
171
172
173
							      text,
							      cursor,
							      anchor);
174
	}
175
176
177
}

static void
178
text_input_activate(struct wl_client *client,
179
		    struct wl_resource *resource,
180
181
		    struct wl_resource *seat,
		    struct wl_resource *surface)
182
{
183
	struct text_input *text_input = wl_resource_get_user_data(resource);
184
	struct weston_seat *weston_seat = wl_resource_get_user_data(seat);
185
	struct input_method *input_method = weston_seat->input_method;
186
	struct weston_compositor *ec = text_input->ec;
187
	struct text_input *current;
188

189
	if (input_method->input == text_input)
190
		return;
191

192
	if (input_method->input)
193
		deactivate_input_method(input_method);
194

195
	input_method->input = text_input;
196
	wl_list_insert(&text_input->input_methods, &input_method->link);
197
198
	input_method_init_seat(weston_seat);

199
	text_input->surface = wl_resource_get_user_data(surface);
200

Jan Arne Petersen's avatar
Jan Arne Petersen committed
201
	input_method_context_create(text_input, input_method);
202

203
204
205
206
207
208
209
210
	current = text_input->manager->current_panel;

	if (current && current != text_input) {
		current->input_panel_visible = false;
		wl_signal_emit(&ec->hide_input_panel_signal, ec);
		text_input->manager->current_panel = NULL;
	}

211
212
213
	if (text_input->input_panel_visible) {
		wl_signal_emit(&ec->show_input_panel_signal, text_input->surface);
		wl_signal_emit(&ec->update_input_panel_signal, &text_input->cursor_rectangle);
214
		text_input->manager->current_panel = text_input;
215
	}
216

217
	wl_text_input_send_enter(text_input->resource, text_input->surface->resource);
218
219
220
}

static void
221
text_input_deactivate(struct wl_client *client,
222
223
		      struct wl_resource *resource,
		      struct wl_resource *seat)
224
{
225
	struct weston_seat *weston_seat = wl_resource_get_user_data(seat);
226

227
	if (weston_seat->input_method->input)
228
		deactivate_input_method(weston_seat->input_method);
229
230
}

231
static void
232
text_input_reset(struct wl_client *client,
Jan Arne Petersen's avatar
Jan Arne Petersen committed
233
		 struct wl_resource *resource)
234
{
235
	struct text_input *text_input = wl_resource_get_user_data(resource);
236
237
	struct input_method *input_method, *next;

238
	wl_list_for_each_safe(input_method, next, &text_input->input_methods, link) {
239
240
		if (!input_method->context)
			continue;
241
		wl_input_method_context_send_reset(input_method->context->resource);
242
243
244
	}
}

245
static void
246
text_input_set_cursor_rectangle(struct wl_client *client,
247
248
249
250
251
				struct wl_resource *resource,
				int32_t x,
				int32_t y,
				int32_t width,
				int32_t height)
252
{
253
	struct text_input *text_input = wl_resource_get_user_data(resource);
254
255
256
257
258
259
260
261
	struct weston_compositor *ec = text_input->ec;

	text_input->cursor_rectangle.x1 = x;
	text_input->cursor_rectangle.y1 = y;
	text_input->cursor_rectangle.x2 = x + width;
	text_input->cursor_rectangle.y2 = y + height;

	wl_signal_emit(&ec->update_input_panel_signal, &text_input->cursor_rectangle);
262
263
264
}

static void
265
text_input_set_content_type(struct wl_client *client,
266
267
268
			    struct wl_resource *resource,
			    uint32_t hint,
			    uint32_t purpose)
269
{
270
	struct text_input *text_input = wl_resource_get_user_data(resource);
271
272
	struct input_method *input_method, *next;

273
	wl_list_for_each_safe(input_method, next, &text_input->input_methods, link) {
274
275
		if (!input_method->context)
			continue;
276
		wl_input_method_context_send_content_type(input_method->context->resource, hint, purpose);
277
	}
278
279
}

280
static void
281
text_input_invoke_action(struct wl_client *client,
282
283
284
285
			 struct wl_resource *resource,
			 uint32_t button,
			 uint32_t index)
{
286
	struct text_input *text_input = wl_resource_get_user_data(resource);
287
288
	struct input_method *input_method, *next;

289
	wl_list_for_each_safe(input_method, next, &text_input->input_methods, link) {
290
291
		if (!input_method->context)
			continue;
292
		wl_input_method_context_send_invoke_action(input_method->context->resource, button, index);
293
294
295
	}
}

Jan Arne Petersen's avatar
Jan Arne Petersen committed
296
static void
297
text_input_commit_state(struct wl_client *client,
Jan Arne Petersen's avatar
Jan Arne Petersen committed
298
299
			struct wl_resource *resource,
			uint32_t serial)
Jan Arne Petersen's avatar
Jan Arne Petersen committed
300
{
301
	struct text_input *text_input = wl_resource_get_user_data(resource);
Jan Arne Petersen's avatar
Jan Arne Petersen committed
302
303
	struct input_method *input_method, *next;

304
	wl_list_for_each_safe(input_method, next, &text_input->input_methods, link) {
Jan Arne Petersen's avatar
Jan Arne Petersen committed
305
306
		if (!input_method->context)
			continue;
307
		wl_input_method_context_send_commit_state(input_method->context->resource, serial);
Jan Arne Petersen's avatar
Jan Arne Petersen committed
308
309
310
	}
}

311
static void
312
text_input_show_input_panel(struct wl_client *client,
313
314
			    struct wl_resource *resource)
{
315
	struct text_input *text_input = wl_resource_get_user_data(resource);
316
	struct weston_compositor *ec = text_input->ec;
317

318
	text_input->input_panel_visible = true;
319

320
321
322
323
	if (!wl_list_empty(&text_input->input_methods)) {
		wl_signal_emit(&ec->show_input_panel_signal, text_input->surface);
		wl_signal_emit(&ec->update_input_panel_signal, &text_input->cursor_rectangle);
	}
324
325
326
}

static void
327
text_input_hide_input_panel(struct wl_client *client,
328
329
			    struct wl_resource *resource)
{
330
	struct text_input *text_input = wl_resource_get_user_data(resource);
331
	struct weston_compositor *ec = text_input->ec;
332

333
	text_input->input_panel_visible = false;
334

335
336
337
	if (!wl_list_empty(&text_input->input_methods) &&
	    text_input == text_input->manager->current_panel) {
		text_input->manager->current_panel = NULL;
338
		wl_signal_emit(&ec->hide_input_panel_signal, ec);
339
	}
340
341
}

342
static void
343
text_input_set_preferred_language(struct wl_client *client,
344
345
346
				  struct wl_resource *resource,
				  const char *language)
{
347
	struct text_input *text_input = wl_resource_get_user_data(resource);
348
349
	struct input_method *input_method, *next;

350
	wl_list_for_each_safe(input_method, next, &text_input->input_methods, link) {
351
352
		if (!input_method->context)
			continue;
353
		wl_input_method_context_send_preferred_language(input_method->context->resource,
354
								language);
355
356
357
	}
}

358
static const struct wl_text_input_interface text_input_implementation = {
359
360
361
362
363
364
365
366
367
368
369
	text_input_activate,
	text_input_deactivate,
	text_input_show_input_panel,
	text_input_hide_input_panel,
	text_input_reset,
	text_input_set_surrounding_text,
	text_input_set_content_type,
	text_input_set_cursor_rectangle,
	text_input_set_preferred_language,
	text_input_commit_state,
	text_input_invoke_action
370
371
};

372
static void text_input_manager_create_text_input(struct wl_client *client,
373
						 struct wl_resource *resource,
374
						 uint32_t id)
375
{
376
	struct text_input_manager *text_input_manager = wl_resource_get_user_data(resource);
377
	struct text_input *text_input;
378

379
380
381
	text_input = zalloc(sizeof *text_input);
	if (text_input == NULL)
		return;
382

383
384
385
386
387
	text_input->resource =
		wl_resource_create(client, &wl_text_input_interface, 1, id);
	wl_resource_set_implementation(text_input->resource,
				       &text_input_implementation,
				       text_input, destroy_text_input);
388

389
	text_input->ec = text_input_manager->ec;
390
	text_input->manager = text_input_manager;
391

392
	wl_list_init(&text_input->input_methods);
393
394
};

395
static const struct wl_text_input_manager_interface text_input_manager_implementation = {
396
	text_input_manager_create_text_input
397
398
399
};

static void
400
bind_text_input_manager(struct wl_client *client,
401
402
403
404
			void *data,
			uint32_t version,
			uint32_t id)
{
405
	struct text_input_manager *text_input_manager = data;
406
	struct wl_resource *resource;
407

408
409
410
411
412
413
414
415
	/* No checking for duplicate binding necessary.  */
	resource =
		wl_resource_create(client,
				   &wl_text_input_manager_interface, 1, id);
	if (resource)
		wl_resource_set_implementation(resource,
					       &text_input_manager_implementation,
					       text_input_manager, NULL);
416
417
418
}

static void
419
text_input_manager_notifier_destroy(struct wl_listener *listener, void *data)
420
{
421
422
	struct text_input_manager *text_input_manager =
		container_of(listener, struct text_input_manager, destroy_listener);
423

424
	wl_global_destroy(text_input_manager->text_input_manager_global);
425

426
	free(text_input_manager);
427
428
}

429
static void
430
text_input_manager_create(struct weston_compositor *ec)
431
{
432
	struct text_input_manager *text_input_manager;
433

434
435
436
	text_input_manager = zalloc(sizeof *text_input_manager);
	if (text_input_manager == NULL)
		return;
437

438
	text_input_manager->ec = ec;
439

440
	text_input_manager->text_input_manager_global =
441
442
443
		wl_global_create(ec->wl_display,
				 &wl_text_input_manager_interface, 1,
				 text_input_manager, bind_text_input_manager);
444

445
446
	text_input_manager->destroy_listener.notify = text_input_manager_notifier_destroy;
	wl_signal_add(&ec->destroy_signal, &text_input_manager->destroy_listener);
447
448
}

449
static void
450
451
input_method_context_destroy(struct wl_client *client,
			     struct wl_resource *resource)
452
{
453
454
	wl_resource_destroy(resource);
}
455

456
457
458
static void
input_method_context_commit_string(struct wl_client *client,
				   struct wl_resource *resource,
459
				   uint32_t serial,
460
				   const char *text)
461
{
462
463
	struct input_method_context *context =
		wl_resource_get_user_data(resource);
464

465
466
	if (context->input)
		wl_text_input_send_commit_string(context->input->resource,
467
						 serial, text);
468
469
}

470
471
static void
input_method_context_preedit_string(struct wl_client *client,
472
				    struct wl_resource *resource,
473
				    uint32_t serial,
474
475
476
				    const char *text,
				    const char *commit)
{
477
478
	struct input_method_context *context =
		wl_resource_get_user_data(resource);
479

480
481
	if (context->input)
		wl_text_input_send_preedit_string(context->input->resource,
482
						  serial, text, commit);
483
484
485
486
487
488
489
490
491
}

static void
input_method_context_preedit_styling(struct wl_client *client,
				     struct wl_resource *resource,
				     uint32_t index,
				     uint32_t length,
				     uint32_t style)
{
492
493
	struct input_method_context *context =
		wl_resource_get_user_data(resource);
494

495
496
	if (context->input)
		wl_text_input_send_preedit_styling(context->input->resource,
497
						   index, length, style);
498
499
500
501
502
503
}

static void
input_method_context_preedit_cursor(struct wl_client *client,
				    struct wl_resource *resource,
				    int32_t cursor)
504
{
505
506
	struct input_method_context *context =
		wl_resource_get_user_data(resource);
507

508
509
	if (context->input)
		wl_text_input_send_preedit_cursor(context->input->resource,
510
						  cursor);
511
512
}

513
514
515
516
517
518
static void
input_method_context_delete_surrounding_text(struct wl_client *client,
					     struct wl_resource *resource,
					     int32_t index,
					     uint32_t length)
{
519
520
	struct input_method_context *context =
		wl_resource_get_user_data(resource);
521

522
523
	if (context->input)
		wl_text_input_send_delete_surrounding_text(context->input->resource,
524
							   index, length);
525
526
}

527
528
529
530
531
532
static void
input_method_context_cursor_position(struct wl_client *client,
				     struct wl_resource *resource,
				     int32_t index,
				     int32_t anchor)
{
533
534
	struct input_method_context *context =
		wl_resource_get_user_data(resource);
535

536
537
	if (context->input)
		wl_text_input_send_cursor_position(context->input->resource,
538
						   index, anchor);
539
540
}

541
static void
542
543
544
545
input_method_context_modifiers_map(struct wl_client *client,
				   struct wl_resource *resource,
				   struct wl_array *map)
{
546
547
	struct input_method_context *context =
		wl_resource_get_user_data(resource);
548

549
550
	if (context->input)
		wl_text_input_send_modifiers_map(context->input->resource, map);
551
552
553
554
555
556
557
558
559
560
}

static void
input_method_context_keysym(struct wl_client *client,
			    struct wl_resource *resource,
			    uint32_t serial,
			    uint32_t time,
			    uint32_t sym,
			    uint32_t state,
			    uint32_t modifiers)
561
{
562
563
	struct input_method_context *context =
		wl_resource_get_user_data(resource);
564

565
566
	if (context->input)
		wl_text_input_send_keysym(context->input->resource,
567
					  serial, time, sym, state, modifiers);
568
569
}

570
571
572
static void
unbind_keyboard(struct wl_resource *resource)
{
573
574
	struct input_method_context *context =
		wl_resource_get_user_data(resource);
575
576
577
578
579
580

	input_method_context_end_keyboard_grab(context);
	context->keyboard = NULL;
}

static void
581
input_method_context_grab_key(struct weston_keyboard_grab *grab,
582
583
			      uint32_t time, uint32_t key, uint32_t state_w)
{
584
	struct weston_keyboard *keyboard = grab->keyboard;
585
	struct wl_display *display;
586
	uint32_t serial;
587
588
589
590

	if (!keyboard->input_method_resource)
		return;

591
	display = wl_client_get_display(wl_resource_get_client(keyboard->input_method_resource));
592
593
594
	serial = wl_display_next_serial(display);
	wl_keyboard_send_key(keyboard->input_method_resource,
			     serial, time, key, state_w);
595
596
597
}

static void
598
input_method_context_grab_modifier(struct weston_keyboard_grab *grab, uint32_t serial,
599
600
601
				   uint32_t mods_depressed, uint32_t mods_latched,
				   uint32_t mods_locked, uint32_t group)
{
602
	struct weston_keyboard *keyboard = grab->keyboard;
603

604
	if (!keyboard->input_method_resource)
605
606
		return;

607
	wl_keyboard_send_modifiers(keyboard->input_method_resource,
608
609
610
611
				   serial, mods_depressed, mods_latched,
				   mods_locked, group);
}

612
613
614
615
616
617
static void
input_method_context_grab_cancel(struct weston_keyboard_grab *grab)
{
	weston_keyboard_end_grab(grab->keyboard);
}

618
static const struct weston_keyboard_grab_interface input_method_context_grab = {
619
620
	input_method_context_grab_key,
	input_method_context_grab_modifier,
621
	input_method_context_grab_cancel,
622
623
624
625
626
627
628
};

static void
input_method_context_grab_keyboard(struct wl_client *client,
				   struct wl_resource *resource,
				   uint32_t id)
{
629
	struct input_method_context *context = wl_resource_get_user_data(resource);
630
631
	struct wl_resource *cr;
	struct weston_seat *seat = context->input_method->seat;
632
	struct weston_keyboard *keyboard = seat->keyboard;
633

634
635
	cr = wl_resource_create(client, &wl_keyboard_interface, 1, id);
	wl_resource_set_implementation(cr, NULL, context, unbind_keyboard);
636
637
638
639

	context->keyboard = cr;

	wl_keyboard_send_keymap(cr, WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1,
640
641
				keyboard->xkb_info->keymap_fd,
				keyboard->xkb_info->keymap_size);
642

643
644
	if (keyboard->grab != &keyboard->default_grab) {
		weston_keyboard_end_grab(keyboard);
645
	}
646
	weston_keyboard_start_grab(keyboard, &keyboard->input_method_grab);
647
	keyboard->input_method_resource = cr;
648
649
}

650
651
652
653
654
655
656
657
static void
input_method_context_key(struct wl_client *client,
			 struct wl_resource *resource,
			 uint32_t serial,
			 uint32_t time,
			 uint32_t key,
			 uint32_t state_w)
{
658
	struct input_method_context *context = wl_resource_get_user_data(resource);
659
	struct weston_seat *seat = context->input_method->seat;
660
	struct weston_keyboard *keyboard = seat->keyboard;
661
	struct weston_keyboard_grab *default_grab = &keyboard->default_grab;
662
663
664
665
666
667
668
669
670
671
672
673
674

	default_grab->interface->key(default_grab, time, key, state_w);
}

static void
input_method_context_modifiers(struct wl_client *client,
			       struct wl_resource *resource,
			       uint32_t serial,
			       uint32_t mods_depressed,
			       uint32_t mods_latched,
			       uint32_t mods_locked,
			       uint32_t group)
{
675
	struct input_method_context *context = wl_resource_get_user_data(resource);
676
677

	struct weston_seat *seat = context->input_method->seat;
678
	struct weston_keyboard *keyboard = seat->keyboard;
679
	struct weston_keyboard_grab *default_grab = &keyboard->default_grab;
680
681
682
683
684
685
686

	default_grab->interface->modifiers(default_grab,
					   serial, mods_depressed,
					   mods_latched, mods_locked,
					   group);
}

687
688
689
690
691
692
static void
input_method_context_language(struct wl_client *client,
			      struct wl_resource *resource,
			      uint32_t serial,
			      const char *language)
{
693
	struct input_method_context *context = wl_resource_get_user_data(resource);
694

695
696
	if (context->input)
		wl_text_input_send_language(context->input->resource,
697
					    serial, language);
698
699
700
701
702
703
704
705
}

static void
input_method_context_text_direction(struct wl_client *client,
				    struct wl_resource *resource,
				    uint32_t serial,
				    uint32_t direction)
{
706
	struct input_method_context *context = wl_resource_get_user_data(resource);
707

708
709
	if (context->input)
		wl_text_input_send_text_direction(context->input->resource,
710
						  serial, direction);
711
712
713
}


714
static const struct wl_input_method_context_interface input_method_context_implementation = {
715
	input_method_context_destroy,
716
717
	input_method_context_commit_string,
	input_method_context_preedit_string,
718
719
	input_method_context_preedit_styling,
	input_method_context_preedit_cursor,
720
	input_method_context_delete_surrounding_text,
721
	input_method_context_cursor_position,
722
	input_method_context_modifiers_map,
723
	input_method_context_keysym,
724
725
	input_method_context_grab_keyboard,
	input_method_context_key,
726
727
728
	input_method_context_modifiers,
	input_method_context_language,
	input_method_context_text_direction
729
730
};

731
732
733
static void
destroy_input_method_context(struct wl_resource *resource)
{
734
	struct input_method_context *context = wl_resource_get_user_data(resource);
735

736
737
738
739
	if (context->keyboard) {
		wl_resource_destroy(context->keyboard);
	}

740
741
742
	if (context->input_method && context->input_method->context == context)
		context->input_method->context = NULL;

743
744
745
746
	free(context);
}

static void
747
input_method_context_create(struct text_input *input,
Jan Arne Petersen's avatar
Jan Arne Petersen committed
748
			    struct input_method *input_method)
749
750
{
	struct input_method_context *context;
751
	struct wl_resource *binding;
752
753
754
755

	if (!input_method->input_method_binding)
		return;

756
	context = zalloc(sizeof *context);
757
758
759
	if (context == NULL)
		return;

760
	binding = input_method->input_method_binding;
761
762
763
764
765
766
	context->resource =
		wl_resource_create(wl_resource_get_client(binding),
				   &wl_input_method_context_interface, 1, 0);
	wl_resource_set_implementation(context->resource,
				       &input_method_context_implementation,
				       context, destroy_input_method_context);
767

768
	context->input = input;
769
	context->input_method = input_method;
770
771
772
	input_method->context = context;


773
	wl_input_method_send_activate(binding, context->resource);
774
775
}

776
777
778
static void
input_method_context_end_keyboard_grab(struct input_method_context *context)
{
779
780
781
782
783
	struct weston_keyboard_grab *grab;
	struct weston_keyboard *keyboard;

	if (!context->input_method->seat->keyboard)
		return;
784

785
786
787
	grab = &context->input_method->seat->keyboard->input_method_grab;
	keyboard = grab->keyboard;
	if (!keyboard)
788
789
		return;

790
791
	if (keyboard->grab == grab)
		weston_keyboard_end_grab(keyboard);
792

793
794
	keyboard->input_method_resource = NULL;
}
795

796
797
798
static void
unbind_input_method(struct wl_resource *resource)
{
799
	struct input_method *input_method = wl_resource_get_user_data(resource);
800
	struct text_backend *text_backend = input_method->text_backend;
801
802

	input_method->input_method_binding = NULL;
803
804
	input_method->context = NULL;

805
	text_backend->input_method.binding = NULL;
806
807
}

808
809
810
811
812
813
static void
bind_input_method(struct wl_client *client,
		  void *data,
		  uint32_t version,
		  uint32_t id)
{
814
	struct input_method *input_method = data;
815
	struct text_backend *text_backend = input_method->text_backend;
816
817
	struct wl_resource *resource;

818
819
	resource =
		wl_resource_create(client, &wl_input_method_interface, 1, id);
820

821
822
823
824
825
	if (input_method->input_method_binding != NULL) {
		wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
				       "interface object already bound");
		return;
	}
826

827
828
	if (text_backend->input_method.client != client) {
		wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
829
				       "permission to bind input_method denied");
830
831
832
		return;
	}

833
834
	wl_resource_set_implementation(resource, NULL, input_method,
				       unbind_input_method);
835
836
837
	input_method->input_method_binding = resource;

	text_backend->input_method.binding = resource;
838
839
840
841
842
}

static void
input_method_notifier_destroy(struct wl_listener *listener, void *data)
{
843
844
	struct input_method *input_method =
		container_of(listener, struct input_method, destroy_listener);
845

846
	if (input_method->input)
847
		deactivate_input_method(input_method);
848

849
	wl_global_destroy(input_method->input_method_global);
850
	wl_list_remove(&input_method->destroy_listener.link);
851

852
853
854
	free(input_method);
}

855
856
857
static void
handle_keyboard_focus(struct wl_listener *listener, void *data)
{
858
	struct weston_keyboard *keyboard = data;
859
860
	struct input_method *input_method =
		container_of(listener, struct input_method, keyboard_focus_listener);
861
	struct weston_surface *surface = keyboard->focus;
862

863
	if (!input_method->input)
864
865
		return;

866
	if (!surface || input_method->input->surface != surface)
867
		deactivate_input_method(input_method);
868
869
870
871
872
873
874
875
}

static void
input_method_init_seat(struct weston_seat *seat)
{
	if (seat->input_method->focus_listener_initialized)
		return;

876
	if (seat->keyboard) {
877
		seat->input_method->keyboard_focus_listener.notify = handle_keyboard_focus;
878
879
		wl_signal_add(&seat->keyboard->focus_signal, &seat->input_method->keyboard_focus_listener);
		seat->keyboard->input_method_grab.interface = &input_method_context_grab;
880
881
882
883
884
	}

	seat->input_method->focus_listener_initialized = 1;
}

885
886
static void launch_input_method(struct text_backend *text_backend);

887
888
889
static void
handle_input_method_sigchld(struct weston_process *process, int status)
{
890
	uint32_t time;
891
892
893
894
895
	struct text_backend *text_backend =
		container_of(process, struct text_backend, input_method.process);

	text_backend->input_method.process.pid = 0;
	text_backend->input_method.client = NULL;
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911

	/* if input_method dies more than 5 times in 10 seconds, give up */
	time = weston_compositor_get_time();
	if (time - text_backend->input_method.deathstamp > 10000) {
		text_backend->input_method.deathstamp = time;
		text_backend->input_method.deathcount = 0;
	}

	text_backend->input_method.deathcount++;
	if (text_backend->input_method.deathcount > 5) {
		weston_log("input_method died, giving up.\n");
		return;
	}

	weston_log("input_method died, respawning...\n");
	launch_input_method(text_backend);
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
}

static void
launch_input_method(struct text_backend *text_backend)
{
	if (text_backend->input_method.binding)
		return;

	if (!text_backend->input_method.path)
		return;

	if (text_backend->input_method.process.pid != 0)
		return;

	text_backend->input_method.client = weston_client_launch(text_backend->compositor,
927
928
929
								 &text_backend->input_method.process,
								 text_backend->input_method.path,
								 handle_input_method_sigchld);
930
931
932
933
934
935

	if (!text_backend->input_method.client)
		weston_log("not able to start %s\n", text_backend->input_method.path);
}