blob: 5375f3fd25a2b224cee6744f9c6202d518bac7be [file] [log] [blame]
Jan Arne Petersen1f17be42012-06-21 21:52:18 +02001/*
2 * Copyright © 2012 Openismus GmbH
Jan Arne Petersen4c265182012-09-09 23:08:30 +02003 * Copyright © 2012 Intel Corporation
Jan Arne Petersen1f17be42012-06-21 21:52:18 +02004 *
5 * Permission to use, copy, modify, distribute, and sell this software and
6 * its documentation for any purpose is hereby granted without fee, provided
7 * that the above copyright notice appear in all copies and that both that
8 * copyright notice and this permission notice appear in supporting
9 * documentation, and that the name of the copyright holders not be used in
10 * advertising or publicity pertaining to distribution of the software
11 * without specific, written prior permission. The copyright holders make
12 * no representations about the suitability of this software for any
13 * purpose. It is provided "as is" without express or implied warranty.
14 *
15 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
16 * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17 * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
18 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
19 * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
20 * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
21 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22 */
23
24#include <stdlib.h>
25
26#include "compositor.h"
27#include "text-server-protocol.h"
28
29struct input_method;
30
31struct text_model {
32 struct wl_resource resource;
33
Jan Arne Petersene829adc2012-08-10 16:47:22 +020034 struct weston_compositor *ec;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020035
Jan Arne Petersene829adc2012-08-10 16:47:22 +020036 struct wl_list input_methods;
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +020037
38 struct wl_surface *surface;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020039};
40
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +020041struct text_model_factory {
Jan Arne Petersen51963742012-08-10 16:47:20 +020042 struct wl_global *text_model_factory_global;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020043 struct wl_listener destroy_listener;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020044
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +020045 struct weston_compositor *ec;
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +020046};
47
48struct input_method {
49 struct wl_resource *input_method_binding;
50 struct wl_global *input_method_global;
51 struct wl_listener destroy_listener;
52
53 struct weston_seat *seat;
Jan Arne Petersene829adc2012-08-10 16:47:22 +020054 struct text_model *model;
55
56 struct wl_list link;
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +020057
58 struct wl_listener keyboard_focus_listener;
59
60 int focus_listener_initialized;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020061};
62
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +020063static void input_method_init_seat(struct weston_seat *seat);
64
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020065static void
Jan Arne Petersene829adc2012-08-10 16:47:22 +020066deactivate_text_model(struct text_model *text_model,
67 struct input_method *input_method)
Philipp Brüschweiler17467812012-07-11 22:25:30 +020068{
Jan Arne Petersene829adc2012-08-10 16:47:22 +020069 struct weston_compositor *ec = text_model->ec;
Philipp Brüschweiler17467812012-07-11 22:25:30 +020070
Jan Arne Petersene829adc2012-08-10 16:47:22 +020071 if (input_method->model == text_model) {
72 wl_list_remove(&input_method->link);
73 input_method->model = NULL;
Kristian Høgsbergf97f3792012-07-22 11:51:42 -040074 wl_signal_emit(&ec->hide_input_panel_signal, ec);
Jan Arne Petersende3b6a12012-08-10 16:47:21 +020075 text_model_send_deactivated(&text_model->resource);
Philipp Brüschweiler17467812012-07-11 22:25:30 +020076 }
77}
78
79static void
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020080destroy_text_model(struct wl_resource *resource)
81{
Kristian Høgsbergf97f3792012-07-22 11:51:42 -040082 struct text_model *text_model =
83 container_of(resource, struct text_model, resource);
Jan Arne Petersene829adc2012-08-10 16:47:22 +020084 struct input_method *input_method, *next;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020085
Jan Arne Petersene829adc2012-08-10 16:47:22 +020086 wl_list_for_each_safe(input_method, next, &text_model->input_methods, link)
87 deactivate_text_model(text_model, input_method);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020088
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020089 free(text_model);
90}
91
92static void
93text_model_set_surrounding_text(struct wl_client *client,
94 struct wl_resource *resource,
95 const char *text)
96{
97}
98
99static void
100text_model_set_cursor_index(struct wl_client *client,
101 struct wl_resource *resource,
102 uint32_t index)
103{
104}
105
106static void
107text_model_activate(struct wl_client *client,
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200108 struct wl_resource *resource,
109 struct wl_resource *seat,
110 struct wl_resource *surface)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200111{
112 struct text_model *text_model = resource->data;
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200113 struct weston_seat *weston_seat = seat->data;
114 struct text_model *old = weston_seat->input_method->model;
115 struct weston_compositor *ec = text_model->ec;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200116
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200117 if (old == text_model)
118 return;
Jan Arne Petersende3b6a12012-08-10 16:47:21 +0200119
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200120 if (old) {
121 deactivate_text_model(old,
122 weston_seat->input_method);
Jan Arne Petersende3b6a12012-08-10 16:47:21 +0200123 }
124
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200125 weston_seat->input_method->model = text_model;
126 wl_list_insert(&text_model->input_methods, &weston_seat->input_method->link);
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200127 input_method_init_seat(weston_seat);
128
129 text_model->surface = surface->data;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200130
Kristian Høgsbergf97f3792012-07-22 11:51:42 -0400131 wl_signal_emit(&ec->show_input_panel_signal, ec);
Jan Arne Petersende3b6a12012-08-10 16:47:21 +0200132
133 text_model_send_activated(&text_model->resource);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200134}
135
136static void
137text_model_deactivate(struct wl_client *client,
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200138 struct wl_resource *resource,
139 struct wl_resource *seat)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200140{
141 struct text_model *text_model = resource->data;
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200142 struct weston_seat *weston_seat = seat->data;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200143
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200144 deactivate_text_model(text_model,
145 weston_seat->input_method);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200146}
147
148static void
149text_model_set_selected_text(struct wl_client *client,
150 struct wl_resource *resource,
151 const char *text,
152 int32_t index)
153{
154}
155
156static void
157text_model_set_micro_focus(struct wl_client *client,
158 struct wl_resource *resource,
159 int32_t x,
160 int32_t y,
161 int32_t width,
162 int32_t height)
163{
164}
165
166static void
167text_model_set_preedit(struct wl_client *client,
168 struct wl_resource *resource)
169{
170}
171
172static void
173text_model_set_content_type(struct wl_client *client,
174 struct wl_resource *resource)
175{
176}
177
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200178static const struct text_model_interface text_model_implementation = {
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200179 text_model_set_surrounding_text,
180 text_model_set_cursor_index,
181 text_model_activate,
182 text_model_deactivate,
183 text_model_set_selected_text,
184 text_model_set_micro_focus,
185 text_model_set_preedit,
186 text_model_set_content_type
187};
188
Jan Arne Petersen51963742012-08-10 16:47:20 +0200189static void text_model_factory_create_text_model(struct wl_client *client,
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200190 struct wl_resource *resource,
Jan Arne Petersen4c265182012-09-09 23:08:30 +0200191 uint32_t id)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200192{
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200193 struct text_model_factory *text_model_factory = resource->data;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200194 struct text_model *text_model;
195
Philipp Brüschweiler17467812012-07-11 22:25:30 +0200196 text_model = calloc(1, sizeof *text_model);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200197
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200198 text_model->resource.object.id = id;
199 text_model->resource.object.interface = &text_model_interface;
Philipp Brüschweiler17467812012-07-11 22:25:30 +0200200 text_model->resource.object.implementation =
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200201 (void (**)(void)) &text_model_implementation;
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200202
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200203 text_model->resource.data = text_model;
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200204 text_model->resource.destroy = destroy_text_model;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200205
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200206 text_model->ec = text_model_factory->ec;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200207
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200208 wl_list_init(&text_model->input_methods);
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200209
210 wl_client_add_resource(client, &text_model->resource);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200211};
212
Jan Arne Petersen51963742012-08-10 16:47:20 +0200213static const struct text_model_factory_interface text_model_factory_implementation = {
214 text_model_factory_create_text_model
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200215};
216
217static void
Jan Arne Petersen51963742012-08-10 16:47:20 +0200218bind_text_model_factory(struct wl_client *client,
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200219 void *data,
220 uint32_t version,
221 uint32_t id)
222{
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200223 struct text_model_factory *text_model_factory = data;
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200224
225 /* No checking for duplicate binding necessary.
226 * No events have to be sent, so we don't need the return value. */
Jan Arne Petersen51963742012-08-10 16:47:20 +0200227 wl_client_add_object(client, &text_model_factory_interface,
228 &text_model_factory_implementation,
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200229 id, text_model_factory);
230}
231
232static void
233text_model_factory_notifier_destroy(struct wl_listener *listener, void *data)
234{
235 struct text_model_factory *text_model_factory =
236 container_of(listener, struct text_model_factory, destroy_listener);
237
238 wl_display_remove_global(text_model_factory->ec->wl_display,
239 text_model_factory->text_model_factory_global);
240
241 free(text_model_factory);
242}
243
244WL_EXPORT void
245text_model_factory_create(struct weston_compositor *ec)
246{
247 struct text_model_factory *text_model_factory;
248
249 text_model_factory = calloc(1, sizeof *text_model_factory);
250
251 text_model_factory->ec = ec;
252
253 text_model_factory->text_model_factory_global =
254 wl_display_add_global(ec->wl_display,
255 &text_model_factory_interface,
256 text_model_factory, bind_text_model_factory);
257
258 text_model_factory->destroy_listener.notify = text_model_factory_notifier_destroy;
259 wl_signal_add(&ec->destroy_signal, &text_model_factory->destroy_listener);
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200260}
261
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200262static void
263input_method_commit_string(struct wl_client *client,
264 struct wl_resource *resource,
265 const char *text,
266 uint32_t index)
267{
268 struct input_method *input_method = resource->data;
269
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200270 if (input_method->model) {
271 text_model_send_commit_string(&input_method->model->resource, text, index);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200272 }
273}
274
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200275static const struct input_method_interface input_method_implementation = {
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200276 input_method_commit_string
277};
278
279static void
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200280unbind_input_method(struct wl_resource *resource)
281{
282 struct input_method *input_method = resource->data;
283
284 input_method->input_method_binding = NULL;
285 free(resource);
286}
287
288static void
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200289bind_input_method(struct wl_client *client,
290 void *data,
291 uint32_t version,
292 uint32_t id)
293{
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200294 struct input_method *input_method = data;
295 struct wl_resource *resource;
296
297 resource = wl_client_add_object(client, &input_method_interface,
298 &input_method_implementation,
299 id, input_method);
300
301 if (input_method->input_method_binding == NULL) {
302 resource->destroy = unbind_input_method;
303 input_method->input_method_binding = resource;
304 return;
305 }
306
307 wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
308 "interface object already bound");
309 wl_resource_destroy(resource);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200310}
311
312static void
313input_method_notifier_destroy(struct wl_listener *listener, void *data)
314{
Kristian Høgsbergf97f3792012-07-22 11:51:42 -0400315 struct input_method *input_method =
316 container_of(listener, struct input_method, destroy_listener);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200317
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200318 if (input_method->model)
319 deactivate_text_model(input_method->model, input_method);
320
321 wl_display_remove_global(input_method->seat->compositor->wl_display,
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200322 input_method->input_method_global);
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200323
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200324 free(input_method);
325}
326
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200327static void
328handle_keyboard_focus(struct wl_listener *listener, void *data)
329{
330 struct wl_keyboard *keyboard = data;
331 struct input_method *input_method =
332 container_of(listener, struct input_method, keyboard_focus_listener);
333 struct wl_surface *surface = keyboard->focus;
334
335 if (!input_method->model)
336 return;
337
338 if (!surface || input_method->model->surface != surface)
339 deactivate_text_model(input_method->model,
340 input_method);
341}
342
343static void
344input_method_init_seat(struct weston_seat *seat)
345{
346 if (seat->input_method->focus_listener_initialized)
347 return;
348
349 if (seat->has_keyboard) {
350 seat->input_method->keyboard_focus_listener.notify = handle_keyboard_focus;
351 wl_signal_add(&seat->seat.keyboard->focus_signal, &seat->input_method->keyboard_focus_listener);
352 }
353
354 seat->input_method->focus_listener_initialized = 1;
355}
356
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200357WL_EXPORT void
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200358input_method_create(struct weston_compositor *ec,
359 struct weston_seat *seat)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200360{
361 struct input_method *input_method;
362
Philipp Brüschweiler17467812012-07-11 22:25:30 +0200363 input_method = calloc(1, sizeof *input_method);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200364
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200365 input_method->seat = seat;
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200366 input_method->model = NULL;
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200367 input_method->focus_listener_initialized = 0;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200368
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200369 input_method->input_method_global =
370 wl_display_add_global(ec->wl_display,
371 &input_method_interface,
372 input_method, bind_input_method);
373
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200374 input_method->destroy_listener.notify = input_method_notifier_destroy;
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200375 wl_signal_add(&seat->seat.destroy_signal, &input_method->destroy_listener);
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200376
377 seat->input_method = input_method;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200378}
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200379