1 #include "e_keyrouter_intern.h"
2 #include "e_input_intern.h"
3 #include "e_input_backend_intern.h"
4 #include "e_comp_wl_input_intern.h"
5 #include "e_comp_wl_intern.h"
6 #include "e_client_intern.h"
7 #include "e_config_intern.h"
8 #include "e_comp_input_intern.h"
9 #include "e_input_thread_client_intern.h"
10 #include "e_security.h"
12 #include <tizen-extension-server-protocol.h>
15 e_keyrouter_wl_event_surface_send(struct wl_resource *surface, int key, int mode)
18 struct wl_resource *res_data;
21 EINA_SAFETY_ON_NULL_RETURN(krt);
22 EINA_SAFETY_ON_NULL_RETURN(surface);
24 wc = wl_resource_get_client(surface);
25 EINA_SAFETY_ON_NULL_RETURN(wc);
27 EINA_LIST_FOREACH(krt->resources, l, res_data)
29 if (wl_resource_get_client(res_data) != wc) continue;
30 if (wl_resource_get_version(res_data) < 2) continue;
32 if (e_config->key_input_ttrace_enable)
34 TRACE_INPUT_BEGIN(tizen_keyrouter_send_event_surface);
35 ELOGF("INPUT", "tizen_keyrouter_send_event_surface|B|", NULL);
38 tizen_keyrouter_send_event_surface(res_data, surface, key, mode);
40 if (e_config->key_input_ttrace_enable)
43 ELOGF("INPUT", "tizen_keyrouter_send_event_surface|E|", NULL);
49 _e_keyrouter_wl_key_send(Ecore_Event_Key *ev, E_Device *dev, enum wl_keyboard_key_state state, Eina_List *key_list, Eina_Bool focused, struct wl_client *client, struct wl_resource *surface)
51 struct wl_resource *res;
53 uint32_t serial, keycode;
55 E_Comp_Config *comp_conf = NULL;
57 keycode = (ev->keycode - 8);
59 serial = wl_display_next_serial(e_comp_wl->wl.disp);
61 comp_conf = e_comp_config_get();
63 if (surface && !focused)
65 e_comp_wl_connection_lock();
66 e_keyrouter_wl_event_surface_send(surface, ev->keycode, TIZEN_KEYROUTER_MODE_NONE);
67 e_comp_wl_connection_unlock();
70 if (e_config->key_input_ttrace_enable)
72 TRACE_INPUT_BEGIN(wl_keyboard_send_key:%s:%s, (state ? "PRESS" : "RELEASE"), ev->keyname);
73 ELOGF("INPUT", "wl_keyboard_send_key:%s:%s|B|", NULL, (state ? "PRESS" : "RELEASE"), ev->keyname);
76 EINA_LIST_FOREACH(key_list, l, res)
78 wc = wl_resource_get_client(res);
79 if (!focused && wc != client) continue;
80 TRACE_INPUT_BEGIN(_e_comp_wl_key_send);
81 if (!e_input_thread_mode_get())
83 e_comp_wl_send_event_device(client, ev->timestamp, ev->dev, serial);
88 e_comp_wl_send_event_e_device(client, ev->timestamp, dev, serial);
91 if (comp_conf && comp_conf->input_log_enable)
92 INF("[Server] Routed Key %s (time: %d)\n", (state ? "Down" : "Up"), ev->timestamp);
94 wl_keyboard_send_key(res, serial, ev->timestamp,
99 if (e_config->key_input_ttrace_enable)
102 ELOGF("INPUT", "wl_keyboard_send_key|E|", NULL);
107 e_keyrouter_wl_key_send(Ecore_Event_Key *ev, E_Device *dev, Eina_Bool pressed, struct wl_client *client, struct wl_resource *surface, Eina_Bool focused)
110 struct wl_client *wc = NULL;
112 enum wl_keyboard_key_state state;
114 if (ev->window != e_comp->ee_win)
119 keycode = (ev->keycode - 8);
120 if (!(e_comp_wl = e_comp->wl_comp_data))
125 #ifndef E_RELEASE_BUILD
126 if ((ev->modifiers & ECORE_EVENT_MODIFIER_CTRL) &&
127 ((ev->modifiers & ECORE_EVENT_MODIFIER_ALT) ||
128 (ev->modifiers & ECORE_EVENT_MODIFIER_ALTGR)) &&
129 eina_streq(ev->key, "BackSpace"))
135 if (pressed) state = WL_KEYBOARD_KEY_STATE_PRESSED;
136 else state = WL_KEYBOARD_KEY_STATE_RELEASED;
140 _e_keyrouter_wl_key_send(ev, dev, state, e_comp_input_key->kbd.resources, EINA_FALSE, client, surface);
144 if ((!e_client_action_get()) && (!e_comp->input_key_grabs))
146 ec = e_client_focused_get();
148 if (ec && ec->comp_data)
150 struct wl_resource *surface = e_comp_wl_client_surface_get(ec);
153 if (e_comp_input_key->kbd.focused)
155 wc = wl_resource_get_client(surface);
156 _e_keyrouter_wl_key_send(ev, dev, state, e_comp_input_key->kbd.focused, EINA_TRUE, wc, surface);
160 /* update modifier state */
161 e_comp_wl_input_keyboard_state_update(keycode, pressed);
168 e_keyrouter_keycancel_send(struct wl_client *client, struct wl_resource *surface, unsigned int key)
171 struct wl_resource *resource = NULL;
172 struct wl_client *wc = NULL;
173 E_Keyrouter_Key_List_NodePtr data;
174 Eina_List *press_ptr_list = NULL;
176 if (surface) wc = wl_resource_get_client(surface);
179 EINA_SAFETY_ON_NULL_RETURN(wc);
181 press_ptr_list = krt->HardKeys[key].press_ptr;
182 EINA_LIST_FOREACH(press_ptr_list, l, data)
186 if (surface == data->surface)
188 EINA_LIST_FOREACH(krt->resources, l, resource)
190 if (wl_resource_get_client(resource) != wc) continue;
192 tizen_keyrouter_send_key_cancel(resource, key-8);
196 else if (client == data->wc)
198 EINA_LIST_FOREACH(krt->resources, l, resource)
200 if (wl_resource_get_client(resource) != wc) continue;
202 tizen_keyrouter_send_key_cancel(resource, key-8);
209 _e_keyrouter_wl_array_length(const struct wl_array *array)
214 wl_array_for_each(data, array)
223 _e_keyrouter_input_thread_keygrab_set(void *data)
226 E_Input_Thread_Request_Keygrab_Data *keygrab_data = data;
227 EINA_SAFETY_ON_NULL_RETURN(keygrab_data);
229 TRACE_INPUT_BEGIN(_e_keyrouter_cb_keygrab_set);
231 res = e_keyrouter_keygrab_set(keygrab_data->client, keygrab_data->surface, keygrab_data->key, keygrab_data->mode);
235 if (res == TIZEN_KEYROUTER_ERROR_NONE)
237 KLINF("Success to %d key %s grab request (wl_client: %p, wl_surface: %p, pid: %d)", keygrab_data->key, e_keyrouter_mode_to_string(keygrab_data->mode),
238 keygrab_data->client, keygrab_data->surface, e_keyrouter_util_get_pid(keygrab_data->client, keygrab_data->surface));
241 KLINF("Failed to %d key %s grab request (wl_client: %p, wl_surface: %p, pid: %d): res: %d", keygrab_data->key, e_keyrouter_mode_to_string(keygrab_data->mode),
242 keygrab_data->client, keygrab_data->surface, e_keyrouter_util_get_pid(keygrab_data->client, keygrab_data->surface), res);
244 tizen_keyrouter_send_keygrab_notify(keygrab_data->resource, keygrab_data->surface, keygrab_data->key, keygrab_data->mode, res);
247 /* tizen_keyrouter_set_keygrab request handler */
249 _e_keyrouter_cb_keygrab_set(struct wl_client *client, struct wl_resource *resource, struct wl_resource *surface, uint32_t key, uint32_t mode)
251 TRACE_INPUT_BEGIN(_e_keyrouter_cb_keygrab_set);
253 E_Input_Thread_Request_Keygrab_Data keygrab_data;
255 keygrab_data.resource = resource;
256 keygrab_data.surface = surface;
257 keygrab_data.client = client;
258 keygrab_data.key = key;
259 keygrab_data.mode = mode;
261 INF("client: %p, surface: %p, key: %d, mode: %d\n", keygrab_data.client, keygrab_data.surface, keygrab_data.key, keygrab_data.mode);
262 e_input_backend_thread_safe_call(_e_keyrouter_input_thread_keygrab_set, &keygrab_data, sizeof(E_Input_Thread_Request_Keygrab_Data));
266 _e_keyrouter_input_thread_keygrab_unset(void *data)
269 E_Input_Thread_Request_Keygrab_Data *keygrab_data = data;
270 EINA_SAFETY_ON_NULL_RETURN(keygrab_data);
272 res = e_keyrouter_keygrab_unset(keygrab_data->client, keygrab_data->surface, keygrab_data->key);
276 if (res == TIZEN_KEYROUTER_ERROR_NONE)
277 KLDBG("Success to %d key ungrab request (wl_client: %p, wl_surface: %p, pid: %d)", keygrab_data->key, keygrab_data->client, keygrab_data->surface,
278 e_keyrouter_util_get_pid(keygrab_data->client, keygrab_data->surface));
280 KLINF("Failed to %d key ungrab request (wl_client: %p, wl_surface: %p, pid: %d): res: %d", keygrab_data->key, keygrab_data->client, keygrab_data->surface,
281 e_keyrouter_util_get_pid(keygrab_data->client, keygrab_data->surface), res);
283 tizen_keyrouter_send_keygrab_notify(keygrab_data->resource, keygrab_data->surface, keygrab_data->key, TIZEN_KEYROUTER_MODE_NONE, res);
286 /* tizen_keyrouter unset_keygrab request handler */
288 _e_keyrouter_cb_keygrab_unset(struct wl_client *client, struct wl_resource *resource, struct wl_resource *surface, uint32_t key)
290 TRACE_INPUT_BEGIN(_e_keyrouter_cb_keygrab_unset);
292 E_Input_Thread_Request_Keygrab_Data keygrab_data;
294 keygrab_data.resource = resource;
295 keygrab_data.surface = surface;
296 keygrab_data.client = client;
297 keygrab_data.key = key;
298 keygrab_data.mode = TIZEN_KEYROUTER_MODE_NONE; /* UNUSED */
300 INF("client: %p, surface: %p, key: %d\n", keygrab_data.client, keygrab_data.surface, keygrab_data.key);
301 e_input_backend_thread_safe_call(_e_keyrouter_input_thread_keygrab_unset, &keygrab_data, sizeof(E_Input_Thread_Request_Keygrab_Data));
304 /* tizen_keyrouter get_keygrab_status request handler */
306 _e_keyrouter_cb_get_keygrab_status(struct wl_client *client, struct wl_resource *resource, struct wl_resource *surface, uint32_t key)
312 int mode = TIZEN_KEYROUTER_MODE_NONE;
314 TRACE_INPUT_BEGIN(_e_keyrouter_cb_get_keygrab_status);
315 mode = e_keyrouter_find_key_in_list(surface, client, key);
318 tizen_keyrouter_send_keygrab_notify(resource, surface, key, mode, TIZEN_KEYROUTER_ERROR_NONE);
322 _e_keyrouter_cb_keygrab_set_list(struct wl_client *client, struct wl_resource *resource, struct wl_resource *surface, struct wl_array *grab_list)
324 E_Keyrouter_Grab_Request *grab_request = NULL;
325 int res = TIZEN_KEYROUTER_ERROR_NONE;
328 TRACE_INPUT_BEGIN(_e_keyrouter_cb_keygrab_set_list);
330 array_len = _e_keyrouter_wl_array_length(grab_list);
332 if (0 != (array_len % 3))
334 /* FIX ME: Which way is effectively to notify invalid pair to client */
335 KLWRN("Invalid keycode and grab mode pair. Check arguments in a list");
337 tizen_keyrouter_send_keygrab_notify_list(resource, surface, NULL);
341 wl_array_for_each(grab_request, grab_list)
343 res = e_keyrouter_keygrab_set(client, surface, grab_request->key, grab_request->mode);
344 grab_request->err = res;
345 if (res == TIZEN_KEYROUTER_ERROR_NONE)
346 KLDBG("Success to %d key %s grab using list(wl_client: %p, wl_surface: %p, pid: %d)",
347 grab_request->key, e_keyrouter_mode_to_string(grab_request->mode),
348 client, surface, e_keyrouter_util_get_pid(client, surface));
350 KLINF("Failed to %d key %s grab using list(wl_client: %p, wl_surface: %p, pid: %d): res: %d",
351 grab_request->key, e_keyrouter_mode_to_string(grab_request->mode),
352 client, surface, e_keyrouter_util_get_pid(client, surface), grab_request->err);
356 tizen_keyrouter_send_keygrab_notify_list(resource, surface, grab_list);
360 _e_keyrouter_cb_keygrab_unset_list(struct wl_client *client, struct wl_resource *resource, struct wl_resource *surface, struct wl_array *ungrab_list)
362 E_Keyrouter_Ungrab_Request *ungrab_request = NULL;
363 int res = TIZEN_KEYROUTER_ERROR_NONE;
366 TRACE_INPUT_BEGIN(_e_keyrouter_cb_keygrab_unset_list);
368 array_len = _e_keyrouter_wl_array_length(ungrab_list);
370 if (0 != (array_len % 2))
372 /* FIX ME: Which way is effectively to notify invalid pair to client */
373 KLWRN("Invalid keycode and error pair. Check arguments in a list");
375 tizen_keyrouter_send_keygrab_notify_list(resource, surface, ungrab_list);
379 wl_array_for_each(ungrab_request, ungrab_list)
381 res = e_keyrouter_keygrab_unset(client, surface, ungrab_request->key);
382 ungrab_request->err = res;
383 if (res == TIZEN_KEYROUTER_ERROR_NONE)
384 KLDBG("Success to ungrab using list: %d key (wl_client: %p, wl_surface: %p, pid: %d)",
385 ungrab_request->key, client, surface, e_keyrouter_util_get_pid(client, surface));
387 KLINF("Failed to ungrab using list: %d key (wl_client: %p, wl_surface: %p, pid: %d): res: %d",
388 ungrab_request->key, client, surface, e_keyrouter_util_get_pid(client, surface), ungrab_request->err);
392 tizen_keyrouter_send_keygrab_notify_list(resource, surface, ungrab_list);
396 _e_keyrouter_cb_keygrab_get_list(struct wl_client *client, struct wl_resource *resource, struct wl_resource *surface)
400 tizen_keyrouter_send_getgrab_notify_list(resource, surface, NULL);
404 _e_keyrouter_cb_set_register_none_key(struct wl_client *client, struct wl_resource *resource, struct wl_resource *surface, uint32_t data)
409 tizen_keyrouter_send_set_register_none_key_notify(resource, NULL, 0);
413 _e_keyrouter_cb_get_keyregister_status(struct wl_client *client, struct wl_resource *resource, uint32_t key)
418 tizen_keyrouter_send_keyregister_notify(resource, (int)EINA_FALSE);
422 _e_keyrouter_cb_set_input_config(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, struct wl_resource *surface EINA_UNUSED, uint32_t config_mode EINA_UNUSED, uint32_t value EINA_UNUSED)
424 tizen_keyrouter_send_set_input_config_notify(resource, 0);
428 _e_keyrouter_cb_destroy(struct wl_client *client, struct wl_resource *resource)
430 wl_resource_destroy(resource);
433 static const struct tizen_keyrouter_interface _e_keyrouter_implementation = {
434 _e_keyrouter_cb_keygrab_set,
435 _e_keyrouter_cb_keygrab_unset,
436 _e_keyrouter_cb_get_keygrab_status,
437 _e_keyrouter_cb_keygrab_set_list,
438 _e_keyrouter_cb_keygrab_unset_list,
439 _e_keyrouter_cb_keygrab_get_list,
440 _e_keyrouter_cb_set_register_none_key,
441 _e_keyrouter_cb_get_keyregister_status,
442 _e_keyrouter_cb_set_input_config,
443 _e_keyrouter_cb_destroy,
447 _e_keyrouter_cb_unbind(struct wl_resource *resource)
449 krt->resources = eina_list_remove(krt->resources, resource);
452 /* tizen_keyrouter global object bind function */
454 _e_keyrouter_cb_bind(struct wl_client *client, void *data, uint32_t version, uint32_t id)
456 E_KeyrouterPtr krt_instance = data;
457 struct wl_resource *resource;
459 resource = wl_resource_create(client, &tizen_keyrouter_interface, version, id);
461 KLDBG("wl_resource_create(...,&tizen_keyrouter_interface,...)");
465 KLERR("Failed to create resource ! (version :%d, id:%d)", version, id);
466 wl_client_post_no_memory(client);
470 krt->resources = eina_list_append(krt->resources, resource);
472 wl_resource_set_implementation(resource, &_e_keyrouter_implementation, krt_instance, _e_keyrouter_cb_unbind);
476 _e_keyrouter_wl_client_cb_destroy(struct wl_listener *l, void *data)
478 struct wl_client *client = data;
480 KLDBG("Listener(%p) called: wl_client: %p is died", l, client);
481 e_keyrouter_remove_client_from_list(NULL, client);
483 wl_list_remove(&l->link);
486 krt->grab_client_list = eina_list_remove(krt->grab_client_list, client);
490 _e_keyrouter_wl_surface_cb_destroy(struct wl_listener *l, void *data)
492 struct wl_resource *surface = (struct wl_resource *)data;
494 KLDBG("Listener(%p) called: surface: %p is died", l, surface);
495 e_keyrouter_remove_client_from_list(surface, NULL);
497 wl_list_remove(&l->link);
500 krt->grab_surface_list = eina_list_remove(krt->grab_surface_list, surface);
504 e_keyrouter_wl_add_client_destroy_listener(struct wl_client *client)
506 struct wl_listener *destroy_listener = NULL;
508 struct wl_client *wc_data;
510 if (!client) return TIZEN_KEYROUTER_ERROR_NONE;
512 EINA_LIST_FOREACH(krt->grab_client_list, l, wc_data)
516 if (wc_data == client)
518 return TIZEN_KEYROUTER_ERROR_NONE;
523 destroy_listener = E_NEW(struct wl_listener, 1);
525 if (!destroy_listener)
527 KLERR("Failed to allocate memory for wl_client destroy listener !");
528 return TIZEN_KEYROUTER_ERROR_NO_SYSTEM_RESOURCES;
531 destroy_listener->notify = _e_keyrouter_wl_client_cb_destroy;
532 wl_client_add_destroy_listener(client, destroy_listener);
533 krt->grab_client_list = eina_list_append(krt->grab_client_list, client);
535 return TIZEN_KEYROUTER_ERROR_NONE;
538 /* Function for registering wl_surface destroy listener */
540 e_keyrouter_wl_add_surface_destroy_listener(struct wl_resource *surface)
542 struct wl_listener *destroy_listener = NULL;
544 struct wl_resource *surface_data;
546 if (!surface) return TIZEN_KEYROUTER_ERROR_NONE;
548 EINA_LIST_FOREACH(krt->grab_surface_list, l, surface_data)
552 if (surface_data == surface)
554 return TIZEN_KEYROUTER_ERROR_NONE;
559 destroy_listener = E_NEW(struct wl_listener, 1);
561 if (!destroy_listener)
563 KLERR("Failed to allocate memory for wl_surface destroy listener !");
564 return TIZEN_KEYROUTER_ERROR_NO_SYSTEM_RESOURCES;
567 destroy_listener->notify = _e_keyrouter_wl_surface_cb_destroy;
568 wl_resource_add_destroy_listener(surface, destroy_listener);
569 krt->grab_surface_list = eina_list_append(krt->grab_surface_list, surface);
571 return TIZEN_KEYROUTER_ERROR_NONE;
576 _e_keyrouter_wl_util_cynara_log(const char *func_name, int err)
578 #define CYNARA_BUFSIZE 128
579 char buf[CYNARA_BUFSIZE] = "\0";
582 ret = cynara_strerror(err, buf, CYNARA_BUFSIZE);
583 if (ret != CYNARA_API_SUCCESS)
585 KLWRN("Failed to cynara_strerror: %d (error log about %s: %d)", ret, func_name, err);
588 KLWRN("%s is failed: %s", func_name, buf);
592 e_keyrouter_wl_util_do_privilege_check(struct wl_client *client, uint32_t mode, uint32_t keycode)
594 int ret, retry_cnt=0;
595 Eina_Bool res = EINA_FALSE;
597 struct wl_client *wc_data;
598 static Eina_Bool retried = EINA_FALSE;
603 /* Top position grab is always allowed. This mode do not need privilege.*/
604 if (mode == TIZEN_KEYROUTER_MODE_TOPMOST)
607 if (krt->HardKeys[keycode].no_privcheck == EINA_TRUE &&
608 mode == TIZEN_KEYROUTER_MODE_OVERRIDABLE_EXCLUSIVE)
611 if (!client) return EINA_FALSE;
613 /* If initialize cynara is failed, allow keygrabs regardless of the privilege permission. */
614 if (krt->p_cynara == NULL)
616 if (retried == EINA_FALSE)
619 for(retry_cnt = 0; retry_cnt < 5; retry_cnt++)
621 KLDBG("Retry cynara initialize: %d", retry_cnt+1);
622 ret = cynara_initialize(&krt->p_cynara, NULL);
623 if (EINA_UNLIKELY(CYNARA_API_SUCCESS != ret))
625 _e_keyrouter_wl_util_cynara_log("cynara_initialize", ret);
626 krt->p_cynara = NULL;
630 KLDBG("Success cynara initialize to try %d times", retry_cnt+1);
638 EINA_LIST_FOREACH(krt->grab_client_list, l, wc_data)
640 if (wc_data == client)
647 wl_client_get_credentials(client, &pid, &uid, &gid);
649 res = e_security_privilege_check(pid, uid, "http://tizen.org/privilege/keygrab");
652 KLINF("Fail to check cynara, (pid : %d)", pid);
661 e_keyrouter_wl_init(void)
665 EINA_SAFETY_ON_NULL_RETURN_VAL(krt, EINA_FALSE);
666 EINA_SAFETY_ON_NULL_RETURN_VAL(e_comp, EINA_FALSE);
668 krt->global = wl_global_create(e_comp_wl->wl.disp, &tizen_keyrouter_interface, 2, krt, _e_keyrouter_cb_bind);
669 EINA_SAFETY_ON_NULL_RETURN_VAL(krt->global, EINA_FALSE);
672 ret = cynara_initialize(&krt->p_cynara, NULL);
673 if (EINA_UNLIKELY(CYNARA_API_SUCCESS != ret))
675 _e_keyrouter_wl_util_cynara_log("cynara_initialize", ret);
676 krt->p_cynara = NULL;
684 e_keyrouter_wl_shutdown(void)
686 Eina_List *l, *l_next;
687 struct wl_resource *resource;
688 struct wl_client *client;
689 struct wl_listener *destroy_listener;
691 EINA_SAFETY_ON_NULL_RETURN(krt);
693 EINA_LIST_FOREACH_SAFE(krt->grab_client_list, l, l_next, client)
695 destroy_listener = wl_client_get_destroy_listener(client, _e_keyrouter_wl_client_cb_destroy);
696 if (destroy_listener)
698 wl_list_remove(&destroy_listener->link);
699 E_FREE(destroy_listener);
701 krt->grab_client_list = eina_list_remove(krt->grab_client_list, client);
703 EINA_LIST_FOREACH_SAFE(krt->grab_surface_list, l, l_next, resource)
705 destroy_listener = wl_resource_get_destroy_listener(resource, _e_keyrouter_wl_surface_cb_destroy);
706 if (destroy_listener)
708 wl_list_remove(&destroy_listener->link);
709 E_FREE(destroy_listener);
711 krt->grab_surface_list = eina_list_remove(krt->grab_surface_list, client);
714 EINA_LIST_FREE(krt->resources, resource)
715 wl_resource_destroy(resource);
717 if (krt->global) wl_global_destroy(krt->global);
720 if (krt->p_cynara) cynara_finish(krt->p_cynara);