8 #include "libds-tizen/keyrouter.h"
12 #include "keyrouter.h"
14 #define TIZEN_KEYROUTER_VERSION 2
15 #define TIZEN_KEYROUTER_PRIVILEGE "http://tizen.org/privilege/keygrab"
17 static void keyrouter_bind(struct wl_client *wl_client, void *data,
18 uint32_t version, uint32_t id);
19 static void keyrouter_handle_display_destroy(struct wl_listener *listener,
21 static void keyrouter_options_set(struct ds_tizen_keyrouter *keyrouter);
22 static void create_keyrouter_client(struct ds_tizen_keyrouter *keyrouter,
23 struct wl_client *wl_client, uint32_t version, uint32_t id);
24 static void destroy_keyrouter_client(struct keyrouter_client *client);
26 keyrouter_client_check_privilege(struct keyrouter_client *client, uint32_t mode,
28 static int keyrouter_client_grab_key(struct keyrouter_client *client, int mode,
30 static int keyrouter_client_ungrab_key(struct keyrouter_client *client,
33 keyrouter_seat_broadcast_key(struct ds_seat *seat, struct wl_array *keyroutes,
34 bool with_focus, uint32_t time_msec, uint32_t keycode, uint32_t state);
36 WL_EXPORT struct ds_tizen_keyrouter *
37 ds_tizen_keyrouter_create(struct wl_display *display)
39 struct ds_tizen_keyrouter *keyrouter;
41 keyrouter = calloc(1, sizeof *keyrouter);
46 keyrouter->global = wl_global_create(display, &tizen_keyrouter_interface,
47 TIZEN_KEYROUTER_VERSION, keyrouter, keyrouter_bind);
48 if (!keyrouter->global) {
53 keyrouter_grab_init(&keyrouter->keygrab);
55 wl_list_init(&keyrouter->clients);
57 wl_signal_init(&keyrouter->events.destroy);
59 keyrouter->display_destroy.notify = keyrouter_handle_display_destroy;
60 wl_display_add_destroy_listener(display, &keyrouter->display_destroy);
62 keyrouter_options_set(keyrouter);
64 keyrouter->security_initialized = tizen_security_init();
65 if (!keyrouter->security_initialized) {
66 ds_inf("tizen_security_init() is not sucessful. "
67 "keyrouter works without security.");
70 ds_inf("Global created: ds_tizen_keyrouter(%p)", keyrouter);
76 ds_tizen_keyrouter_add_destroy_listener(struct ds_tizen_keyrouter *keyrouter,
77 struct wl_listener *listener)
79 wl_signal_add(&keyrouter->events.destroy, listener);
83 ds_tizen_keyrouter_notify_key(struct ds_tizen_keyrouter *keyrouter,
84 struct ds_seat *seat, struct ds_surface *topmost_surface,
85 uint32_t time_msec, uint32_t keycode, uint32_t state)
87 struct wl_client *topmost_wl_client = NULL;
88 struct wl_resource *surface_resource;
89 struct wl_array keyroutes;
90 enum keyroute_mode mode;
92 wl_array_init(&keyroutes);
94 if (topmost_surface) {
95 surface_resource = ds_surface_get_wl_resource(topmost_surface);
96 if (surface_resource) {
97 topmost_wl_client = wl_resource_get_client(
98 ds_surface_get_wl_resource(topmost_surface));
102 mode = keyrouter_grab_get_keyroutes(&keyrouter->keygrab, keycode + 8,
103 topmost_wl_client, &keyroutes);
105 if (mode == KEYROUTE_MODE_EXCLUSIVE) {
106 keyrouter_seat_broadcast_key(seat, &keyroutes, true,
107 time_msec, keycode, state);
112 if (mode == KEYROUTE_MODE_SHARED) {
113 keyrouter_seat_broadcast_key(seat, &keyroutes, false,
114 time_msec, keycode, state);
117 ds_seat_keyboard_notify_key(seat, time_msec, keycode, state);
120 wl_array_release(&keyroutes);
124 keyrouter_client_handle_set_keygrab(struct wl_client *wl_client,
125 struct wl_resource *resource, struct wl_resource *surface,
126 uint32_t key, uint32_t mode)
128 struct keyrouter_client *client;
131 client = wl_resource_get_user_data(resource);
132 err = keyrouter_client_grab_key(client, mode, key);
133 tizen_keyrouter_send_keygrab_notify(resource, surface, key, mode, err);
137 keyrouter_client_handle_unset_keygrab(struct wl_client *wl_client,
138 struct wl_resource *resource, struct wl_resource *surface, uint32_t key)
140 struct keyrouter_client *client;
143 client = wl_resource_get_user_data(resource);
144 err = keyrouter_client_ungrab_key(client, key);
145 tizen_keyrouter_send_keygrab_notify(resource, surface, key,
146 TIZEN_KEYROUTER_MODE_NONE, err);
150 keyrouter_client_handle_get_keygrab_status(struct wl_client *wl_client,
151 struct wl_resource *resource, struct wl_resource *surface, uint32_t key)
153 tizen_keyrouter_send_keygrab_notify(resource, surface, key,
154 TIZEN_KEYROUTER_MODE_NONE, TIZEN_KEYROUTER_ERROR_NO_PERMISSION);
158 keyrouter_get_array_length(const struct wl_array *array)
163 wl_array_for_each(data, array)
170 keyrouter_client_handle_set_keygrab_list(struct wl_client *wl_client,
171 struct wl_resource *resource, struct wl_resource *surface, struct wl_array *grab_list)
173 struct keyrouter_client *client;
174 struct ds_tizen_grab_data *grab_data;
175 struct wl_array *return_list;
177 if ((keyrouter_get_array_length(grab_list) % 3) != 0) {
178 ds_err("Invalid keycode and grab mode pair. Check arguments in a list.");
179 tizen_keyrouter_send_keygrab_notify_list(resource, surface, NULL);
183 client = wl_resource_get_user_data(resource);
185 wl_array_for_each(grab_data, grab_list) {
186 grab_data->err = keyrouter_client_grab_key(client, grab_data->mode,
190 return_list = grab_list;
192 tizen_keyrouter_send_keygrab_notify_list(resource, surface, return_list);
196 keyrouter_client_handle_unset_keygrab_list(struct wl_client *wl_client,
197 struct wl_resource *resource, struct wl_resource *surface,
198 struct wl_array *ungrab_list)
200 struct keyrouter_client *client;
201 struct wl_array *return_list;
202 struct ds_tizen_ungrab_data *ungrab_data;
204 if ((keyrouter_get_array_length(ungrab_list) % 3) != 0) {
205 ds_err("Invalid keycode and grab mode pair. Check arguments in a list.");
206 tizen_keyrouter_send_keygrab_notify_list(resource, surface, NULL);
210 client = wl_resource_get_user_data(resource);
212 wl_array_for_each(ungrab_data, ungrab_list) {
213 ungrab_data->err = keyrouter_client_ungrab_key(client,
217 return_list = ungrab_list;
219 tizen_keyrouter_send_keygrab_notify_list(resource, surface, return_list);
223 keyrouter_client_handle_get_keygrab_list(struct wl_client *wl_client,
224 struct wl_resource *resource, struct wl_resource *surface)
226 tizen_keyrouter_send_getgrab_notify_list(resource, surface, NULL);
230 keyrouter_client_handle_set_register_none_key(struct wl_client *wl_client,
231 struct wl_resource *resource, struct wl_resource *surface,
234 tizen_keyrouter_send_set_register_none_key_notify(resource, NULL, 0);
238 keyrouter_client_handle_get_keyregister_status(struct wl_client *wl_client,
239 struct wl_resource *resource, uint32_t key)
241 tizen_keyrouter_send_keyregister_notify(resource, (int)false);
245 keyrouter_client_handle_set_input_config(struct wl_client *wl_client,
246 struct wl_resource *resource, struct wl_resource *surface,
247 uint32_t config_mode, uint32_t value)
249 tizen_keyrouter_send_set_input_config_notify(resource, (int)false);
253 keyrouter_client_handle_destroy(struct wl_client *wl_client,
254 struct wl_resource *resource)
256 wl_resource_destroy(resource);
259 static const struct tizen_keyrouter_interface tizen_keyrouter_impl = {
260 .set_keygrab = keyrouter_client_handle_set_keygrab,
261 .unset_keygrab = keyrouter_client_handle_unset_keygrab,
262 .get_keygrab_status = keyrouter_client_handle_get_keygrab_status,
263 .set_keygrab_list = keyrouter_client_handle_set_keygrab_list,
264 .unset_keygrab_list = keyrouter_client_handle_unset_keygrab_list,
265 .get_keygrab_list = keyrouter_client_handle_get_keygrab_list,
266 .set_register_none_key = keyrouter_client_handle_set_register_none_key,
267 .get_keyregister_status = keyrouter_client_handle_get_keyregister_status,
268 .set_input_config = keyrouter_client_handle_set_input_config,
269 .destroy = keyrouter_client_handle_destroy
273 keyrouter_client_handle_resource_destroy(struct wl_resource *resource)
275 struct keyrouter_client *client;
277 client = wl_resource_get_user_data(resource);
278 destroy_keyrouter_client(client);
282 keyrouter_bind(struct wl_client *wl_client, void *data, uint32_t version,
285 struct ds_tizen_keyrouter *keyrouter = data;
287 create_keyrouter_client(keyrouter, wl_client, version, id);
291 keyrouter_handle_display_destroy(struct wl_listener *listener, void *data)
293 struct ds_tizen_keyrouter *keyrouter;
295 keyrouter = wl_container_of(listener, keyrouter, display_destroy);
297 ds_inf("Global destroy: ds_tizen_keyrouter(%p)", keyrouter);
299 wl_signal_emit_mutable(&keyrouter->events.destroy, keyrouter);
301 if (keyrouter->security_initialized)
302 tizen_security_finish();
304 free(keyrouter->opts);
306 wl_list_remove(&keyrouter->display_destroy.link);
308 wl_global_destroy(keyrouter->global);
310 keyrouter_grab_finish(&keyrouter->keygrab);
316 keyrouter_options_set(struct ds_tizen_keyrouter *keyrouter)
320 char *ret, *tmp, *buf_ptr, buf[1024] = {0,};
322 keyrouter->opts = calloc(KEYROUTER_MAX_KEYS,
323 sizeof(struct keyrouter_key_options));
324 if (!keyrouter->opts) {
328 file = fopen(KEYLAYOUT_DIR, "r");
330 ds_err("Failed to open key layout file(%s): (err msg: %m)\n", KEYLAYOUT_DIR);
331 free(keyrouter->opts);
332 keyrouter->opts = NULL;
336 while (!feof(file)) {
337 ret = fgets(buf, 1024, file);
340 tmp = strtok_r(buf, " ", &buf_ptr);
341 tmp = strtok_r(NULL, " ", &buf_ptr);
344 if ((0 >= keycode) || (keycode >= KEYROUTER_MAX_KEYS)) {
345 ds_err("Currently %d key is invalid to support\n", keycode);
349 keyrouter->opts[keycode].enabled = true;
351 if (strstr(buf_ptr, "no_priv") != NULL) {
352 keyrouter->opts[keycode].no_privilege = true;
360 create_keyrouter_client(struct ds_tizen_keyrouter *keyrouter,
361 struct wl_client *wl_client, uint32_t version, uint32_t id)
363 struct keyrouter_client *client;
365 client = calloc(1, sizeof *client);
367 wl_client_post_no_memory(wl_client);
371 client->keyrouter = keyrouter;
372 client->wl_client = wl_client;
373 client->resource = wl_resource_create(wl_client, &tizen_keyrouter_interface,
374 MIN(version, TIZEN_KEYROUTER_VERSION), id);
375 if (!client->resource) {
376 ds_err("wl_resource_create() failed. (version :%d, id:%d)",
379 wl_client_post_no_memory(wl_client);
383 wl_resource_set_implementation(client->resource, &tizen_keyrouter_impl,
384 client, keyrouter_client_handle_resource_destroy);
386 wl_list_insert(&keyrouter->clients, &client->link);
390 destroy_keyrouter_client(struct keyrouter_client *client)
392 wl_list_remove(&client->link);
397 keyrouter_client_check_privilege(struct keyrouter_client *client, uint32_t mode,
400 struct ds_tizen_keyrouter *keyrouter = client->keyrouter;
404 /* Top position grab is always allowed. This mode do not need privilege.*/
405 if (mode == TIZEN_KEYROUTER_MODE_TOPMOST)
408 // check no privilege option on the keycode
409 if (keyrouter->opts && keyrouter->opts[keycode].no_privilege)
412 // already checked the privilege before.
413 if (client->privileged)
416 wl_client_get_credentials(client->wl_client, &pid, &uid, NULL);
418 client->privileged = tizen_security_check_privilege(pid, uid,
419 TIZEN_KEYROUTER_PRIVILEGE);
421 return client->privileged;
425 keyrouter_client_grab_key(struct keyrouter_client *client, int mode,
428 struct ds_tizen_keyrouter *keyrouter = client->keyrouter;
430 if (!keyrouter_client_check_privilege(client, mode, keycode))
431 return TIZEN_KEYROUTER_ERROR_NO_PERMISSION;
433 return keyrouter_grab_grab_key(&keyrouter->keygrab, mode, keycode,
438 keyrouter_client_ungrab_key(struct keyrouter_client *client, int keycode)
440 struct ds_tizen_keyrouter *keyrouter = client->keyrouter;
442 /* ungrab TOP POSITION grab first, this grab mode is not check privilege */
443 keyrouter_grab_ungrab_key(&keyrouter->keygrab,
444 TIZEN_KEYROUTER_MODE_TOPMOST, keycode, client->wl_client);
446 if (!keyrouter_client_check_privilege(client, TIZEN_KEYROUTER_MODE_NONE,
448 return TIZEN_KEYROUTER_ERROR_NO_PERMISSION;
450 keyrouter_grab_ungrab_key(&keyrouter->keygrab,
451 TIZEN_KEYROUTER_MODE_EXCLUSIVE, keycode, client->wl_client);
452 keyrouter_grab_ungrab_key(&keyrouter->keygrab,
453 TIZEN_KEYROUTER_MODE_OVERRIDABLE_EXCLUSIVE, keycode,
455 keyrouter_grab_ungrab_key(&keyrouter->keygrab,
456 TIZEN_KEYROUTER_MODE_TOPMOST, keycode, client->wl_client);
457 keyrouter_grab_ungrab_key(&keyrouter->keygrab,
458 TIZEN_KEYROUTER_MODE_SHARED, keycode, client->wl_client);
460 return TIZEN_KEYROUTER_ERROR_NONE;
464 keyrouter_seat_broadcast_key(struct ds_seat *seat, struct wl_array *keyroutes,
465 bool with_focus, uint32_t time_msec, uint32_t keycode, uint32_t state)
467 struct ds_seat_client *seat_client, *focused_client;
468 struct wl_client **wl_client_ptr;
470 focused_client = ds_seat_keyboard_get_focused_client(seat);
472 wl_array_for_each(wl_client_ptr, keyroutes) {
473 seat_client = ds_seat_client_for_wl_client(seat, *wl_client_ptr);
475 ds_inf("Could not find ds_seat_client for given wl_client(%p)",
480 if (seat_client == focused_client) {
482 ds_seat_keyboard_notify_key(seat, time_msec, keycode, state);
485 ds_seat_client_send_key(seat_client, time_msec, keycode, state);