2 * Copyright © 2012 Openismus GmbH
3 * Copyright © 2012 Intel Corporation
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.
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.
26 #include "compositor.h"
27 #include "text-server-protocol.h"
32 struct wl_resource resource;
34 struct weston_compositor *ec;
36 struct wl_list input_methods;
38 struct wl_surface *surface;
41 struct text_model_factory {
42 struct wl_global *text_model_factory_global;
43 struct wl_listener destroy_listener;
45 struct weston_compositor *ec;
49 struct wl_resource *input_method_binding;
50 struct wl_global *input_method_global;
51 struct wl_listener destroy_listener;
53 struct weston_seat *seat;
54 struct text_model *model;
58 struct wl_listener keyboard_focus_listener;
60 int focus_listener_initialized;
63 static void input_method_init_seat(struct weston_seat *seat);
66 deactivate_text_model(struct text_model *text_model,
67 struct input_method *input_method)
69 struct weston_compositor *ec = text_model->ec;
71 if (input_method->model == text_model) {
72 wl_list_remove(&input_method->link);
73 input_method->model = NULL;
74 wl_signal_emit(&ec->hide_input_panel_signal, ec);
75 text_model_send_deactivated(&text_model->resource);
80 destroy_text_model(struct wl_resource *resource)
82 struct text_model *text_model =
83 container_of(resource, struct text_model, resource);
84 struct input_method *input_method, *next;
86 wl_list_for_each_safe(input_method, next, &text_model->input_methods, link)
87 deactivate_text_model(text_model, input_method);
93 text_model_set_surrounding_text(struct wl_client *client,
94 struct wl_resource *resource,
100 text_model_set_cursor_index(struct wl_client *client,
101 struct wl_resource *resource,
107 text_model_activate(struct wl_client *client,
108 struct wl_resource *resource,
109 struct wl_resource *seat,
110 struct wl_resource *surface)
112 struct text_model *text_model = resource->data;
113 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;
117 if (old == text_model)
121 deactivate_text_model(old,
122 weston_seat->input_method);
125 weston_seat->input_method->model = text_model;
126 wl_list_insert(&text_model->input_methods, &weston_seat->input_method->link);
127 input_method_init_seat(weston_seat);
129 text_model->surface = surface->data;
131 wl_signal_emit(&ec->show_input_panel_signal, ec);
133 text_model_send_activated(&text_model->resource);
137 text_model_deactivate(struct wl_client *client,
138 struct wl_resource *resource,
139 struct wl_resource *seat)
141 struct text_model *text_model = resource->data;
142 struct weston_seat *weston_seat = seat->data;
144 deactivate_text_model(text_model,
145 weston_seat->input_method);
149 text_model_set_selected_text(struct wl_client *client,
150 struct wl_resource *resource,
157 text_model_set_micro_focus(struct wl_client *client,
158 struct wl_resource *resource,
167 text_model_set_preedit(struct wl_client *client,
168 struct wl_resource *resource)
173 text_model_set_content_type(struct wl_client *client,
174 struct wl_resource *resource)
178 static const struct text_model_interface text_model_implementation = {
179 text_model_set_surrounding_text,
180 text_model_set_cursor_index,
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
189 static void text_model_factory_create_text_model(struct wl_client *client,
190 struct wl_resource *resource,
193 struct text_model_factory *text_model_factory = resource->data;
194 struct text_model *text_model;
196 text_model = calloc(1, sizeof *text_model);
198 text_model->resource.object.id = id;
199 text_model->resource.object.interface = &text_model_interface;
200 text_model->resource.object.implementation =
201 (void (**)(void)) &text_model_implementation;
203 text_model->resource.data = text_model;
204 text_model->resource.destroy = destroy_text_model;
206 text_model->ec = text_model_factory->ec;
208 wl_list_init(&text_model->input_methods);
210 wl_client_add_resource(client, &text_model->resource);
213 static const struct text_model_factory_interface text_model_factory_implementation = {
214 text_model_factory_create_text_model
218 bind_text_model_factory(struct wl_client *client,
223 struct text_model_factory *text_model_factory = data;
225 /* No checking for duplicate binding necessary.
226 * No events have to be sent, so we don't need the return value. */
227 wl_client_add_object(client, &text_model_factory_interface,
228 &text_model_factory_implementation,
229 id, text_model_factory);
233 text_model_factory_notifier_destroy(struct wl_listener *listener, void *data)
235 struct text_model_factory *text_model_factory =
236 container_of(listener, struct text_model_factory, destroy_listener);
238 wl_display_remove_global(text_model_factory->ec->wl_display,
239 text_model_factory->text_model_factory_global);
241 free(text_model_factory);
245 text_model_factory_create(struct weston_compositor *ec)
247 struct text_model_factory *text_model_factory;
249 text_model_factory = calloc(1, sizeof *text_model_factory);
251 text_model_factory->ec = ec;
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);
258 text_model_factory->destroy_listener.notify = text_model_factory_notifier_destroy;
259 wl_signal_add(&ec->destroy_signal, &text_model_factory->destroy_listener);
263 input_method_commit_string(struct wl_client *client,
264 struct wl_resource *resource,
268 struct input_method *input_method = resource->data;
270 if (input_method->model) {
271 text_model_send_commit_string(&input_method->model->resource, text, index);
275 static const struct input_method_interface input_method_implementation = {
276 input_method_commit_string
280 unbind_input_method(struct wl_resource *resource)
282 struct input_method *input_method = resource->data;
284 input_method->input_method_binding = NULL;
289 bind_input_method(struct wl_client *client,
294 struct input_method *input_method = data;
295 struct wl_resource *resource;
297 resource = wl_client_add_object(client, &input_method_interface,
298 &input_method_implementation,
301 if (input_method->input_method_binding == NULL) {
302 resource->destroy = unbind_input_method;
303 input_method->input_method_binding = resource;
307 wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
308 "interface object already bound");
309 wl_resource_destroy(resource);
313 input_method_notifier_destroy(struct wl_listener *listener, void *data)
315 struct input_method *input_method =
316 container_of(listener, struct input_method, destroy_listener);
318 if (input_method->model)
319 deactivate_text_model(input_method->model, input_method);
321 wl_display_remove_global(input_method->seat->compositor->wl_display,
322 input_method->input_method_global);
328 handle_keyboard_focus(struct wl_listener *listener, void *data)
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;
335 if (!input_method->model)
338 if (!surface || input_method->model->surface != surface)
339 deactivate_text_model(input_method->model,
344 input_method_init_seat(struct weston_seat *seat)
346 if (seat->input_method->focus_listener_initialized)
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);
354 seat->input_method->focus_listener_initialized = 1;
358 input_method_create(struct weston_compositor *ec,
359 struct weston_seat *seat)
361 struct input_method *input_method;
363 input_method = calloc(1, sizeof *input_method);
365 input_method->seat = seat;
366 input_method->model = NULL;
367 input_method->focus_listener_initialized = 0;
369 input_method->input_method_global =
370 wl_display_add_global(ec->wl_display,
371 &input_method_interface,
372 input_method, bind_input_method);
374 input_method->destroy_listener.notify = input_method_notifier_destroy;
375 wl_signal_add(&seat->seat.destroy_signal, &input_method->destroy_listener);
377 seat->input_method = input_method;