1 #include "e_keyrouter_wl_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"
11 #include "e_keyrouter_intern.h"
13 #include <tizen-extension-server-protocol.h>
15 static E_Tizen_Keyrouter *g_tizen_keyrouter = NULL;
17 struct _E_Tizen_Keyrouter
19 struct wl_global *global;
23 Eina_List *grab_surface_list;
24 Eina_List *grab_client_list;
28 e_keyrouter_wl_event_surface_send(struct wl_resource *surface, int key, int mode)
31 struct wl_resource *res_data;
34 EINA_SAFETY_ON_NULL_RETURN(surface);
36 wc = wl_resource_get_client(surface);
37 EINA_SAFETY_ON_NULL_RETURN(wc);
39 EINA_LIST_FOREACH(g_tizen_keyrouter->resources, l, res_data)
41 if (wl_resource_get_client(res_data) != wc) continue;
42 if (wl_resource_get_version(res_data) < 2) continue;
44 if (e_config->key_input_ttrace_enable)
46 TRACE_INPUT_BEGIN(tizen_keyrouter_send_event_surface);
47 ELOGF("INPUT", "tizen_keyrouter_send_event_surface|B|", NULL);
50 tizen_keyrouter_send_event_surface(res_data, surface, key, mode);
52 if (e_config->key_input_ttrace_enable)
55 ELOGF("INPUT", "tizen_keyrouter_send_event_surface|E|", NULL);
61 _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)
63 struct wl_resource *res;
65 uint32_t serial, keycode;
67 E_Comp_Config *comp_conf = NULL;
69 keycode = (ev->keycode - 8);
71 serial = wl_display_next_serial(e_comp_wl->wl.disp);
73 comp_conf = e_comp_config_get();
75 if (surface && !focused)
77 e_comp_wl_connection_lock();
78 e_keyrouter_wl_event_surface_send(surface, ev->keycode, TIZEN_KEYROUTER_MODE_NONE);
79 e_comp_wl_connection_unlock();
82 if (e_config->key_input_ttrace_enable)
84 TRACE_INPUT_BEGIN(wl_keyboard_send_key:%s:%s, (state ? "PRESS" : "RELEASE"), ev->keyname);
85 ELOGF("INPUT", "wl_keyboard_send_key:%s:%s|B|", NULL, (state ? "PRESS" : "RELEASE"), ev->keyname);
88 EINA_LIST_FOREACH(key_list, l, res)
90 wc = wl_resource_get_client(res);
91 if (!focused && wc != client) continue;
92 TRACE_INPUT_BEGIN(_e_comp_wl_key_send);
93 if (!e_input_thread_mode_get())
95 e_comp_wl_send_event_device(client, ev->timestamp, ev->dev, serial);
100 e_comp_wl_send_event_e_device(client, ev->timestamp, dev, serial);
103 if (comp_conf && comp_conf->input_log_enable)
104 INF("[Server] Routed Key %s (time: %d)\n", (state ? "Down" : "Up"), ev->timestamp);
106 wl_keyboard_send_key(res, serial, ev->timestamp,
111 if (e_config->key_input_ttrace_enable)
114 ELOGF("INPUT", "wl_keyboard_send_key|E|", NULL);
119 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)
122 struct wl_client *wc = NULL;
124 enum wl_keyboard_key_state state;
126 if (ev->window != e_comp->ee_win)
131 keycode = (ev->keycode - 8);
132 if (!(e_comp_wl = e_comp->wl_comp_data))
137 #ifndef E_RELEASE_BUILD
138 if ((ev->modifiers & ECORE_EVENT_MODIFIER_CTRL) &&
139 ((ev->modifiers & ECORE_EVENT_MODIFIER_ALT) ||
140 (ev->modifiers & ECORE_EVENT_MODIFIER_ALTGR)) &&
141 eina_streq(ev->key, "BackSpace"))
147 if (pressed) state = WL_KEYBOARD_KEY_STATE_PRESSED;
148 else state = WL_KEYBOARD_KEY_STATE_RELEASED;
152 _e_keyrouter_wl_key_send(ev, dev, state, e_comp_input_key->kbd.resources, EINA_FALSE, client, surface);
156 if ((!e_client_action_get()) && (!e_comp->input_key_grabs))
158 ec = e_client_focused_get();
160 if (ec && ec->comp_data)
162 struct wl_resource *surface = e_comp_wl_client_surface_get(ec);
165 if (e_comp_input_key->kbd.focused)
167 wc = wl_resource_get_client(surface);
168 _e_keyrouter_wl_key_send(ev, dev, state, e_comp_input_key->kbd.focused, EINA_TRUE, wc, surface);
172 /* update modifier state */
173 e_comp_wl_input_keyboard_state_update(keycode, pressed);
180 e_keyrouter_keycancel_send(struct wl_client *client, struct wl_resource *surface, unsigned int key)
183 struct wl_resource *resource = NULL;
184 struct wl_client *wc = NULL;
185 E_Keyrouter_Key_List_NodePtr data;
186 Eina_List *press_ptr_list = NULL;
188 if (surface) wc = wl_resource_get_client(surface);
191 EINA_SAFETY_ON_NULL_RETURN(wc);
193 g_rec_mutex_lock(&krt->grab_key_mutex);
194 press_ptr_list = krt->HardKeys[key].press_ptr;
195 EINA_LIST_FOREACH(press_ptr_list, l, data)
199 if (surface == data->surface)
201 EINA_LIST_FOREACH(g_tizen_keyrouter->resources, l, resource)
203 if (wl_resource_get_client(resource) != wc) continue;
205 tizen_keyrouter_send_key_cancel(resource, key-8);
209 else if (client == data->wc)
211 EINA_LIST_FOREACH(g_tizen_keyrouter->resources, l, resource)
213 if (wl_resource_get_client(resource) != wc) continue;
215 tizen_keyrouter_send_key_cancel(resource, key-8);
219 g_rec_mutex_unlock(&krt->grab_key_mutex);
223 _e_keyrouter_wl_array_length(const struct wl_array *array)
228 wl_array_for_each(data, array)
237 _e_keyrouter_keygrab_set_available_check(struct wl_client *client, struct wl_resource *surface, int key, int mode)
239 if (!((mode == TIZEN_KEYROUTER_MODE_EXCLUSIVE) ||
240 (mode == TIZEN_KEYROUTER_MODE_OVERRIDABLE_EXCLUSIVE) ||
241 (mode == TIZEN_KEYROUTER_MODE_TOPMOST) ||
242 (mode == TIZEN_KEYROUTER_MODE_SHARED)))
243 return TIZEN_KEYROUTER_ERROR_INVALID_MODE;
246 if (!e_keyrouter_wl_util_do_privilege_check(client, mode, key))
248 KLINF("No permission for %d grab mode ! (key=%d)", mode, key);
249 return TIZEN_KEYROUTER_ERROR_NO_PERMISSION;
253 /* Regarding topmost mode, a client must request to grab a key with a valid surface. */
254 if (!surface && mode == TIZEN_KEYROUTER_MODE_TOPMOST)
256 KLWRN("Invalid surface for %d grab mode ! (key=%d)", mode, key);
257 return TIZEN_KEYROUTER_ERROR_INVALID_SURFACE;
260 return TIZEN_KEYROUTER_ERROR_NONE;
264 _e_keyrouter_keygrab_key_available_check(int key)
266 /* Check the given key range */
267 if (krt->max_tizen_hwkeys < key)
269 KLWRN("Invalid range of key ! (keycode:%d) maximum value(%d)", key, krt->max_tizen_hwkeys);
270 return TIZEN_KEYROUTER_ERROR_INVALID_KEY;
273 /* Check whether the key can be grabbed or not !
274 * Only key listed in Tizen key layout file can be grabbed. */
275 if (0 == krt->HardKeys[key].keycode)
277 KLWRN("Invalid key ! Disabled to set keygrab ! (keycode:%d)", key);
278 return TIZEN_KEYROUTER_ERROR_INVALID_KEY;
281 return TIZEN_KEYROUTER_ERROR_NONE;
285 _e_keyrouter_input_thread_keygrab_set(void *data)
287 E_Input_Thread_Request_Keygrab_Data *keygrab_data = data;
290 res = _e_keyrouter_keygrab_set_available_check(keygrab_data->client,
291 keygrab_data->surface, keygrab_data->key, keygrab_data->mode);
292 if (res != TIZEN_KEYROUTER_ERROR_NONE)
295 res = _e_keyrouter_keygrab_key_available_check(keygrab_data->key);
296 if (res != TIZEN_KEYROUTER_ERROR_NONE)
299 res = e_keyrouter_keygrab_set(keygrab_data->client, keygrab_data->surface,
300 keygrab_data->key, keygrab_data->mode);
301 if (res != TIZEN_KEYROUTER_ERROR_NONE)
304 KLINF("Success to %d key %s grab request (wl_client: %p, wl_surface: %p, pid: %d)",
305 keygrab_data->key, e_keyrouter_mode_to_string(keygrab_data->mode),
306 keygrab_data->client, keygrab_data->surface,
307 e_keyrouter_util_get_pid(keygrab_data->client, keygrab_data->surface));
309 tizen_keyrouter_send_keygrab_notify(keygrab_data->resource,
310 keygrab_data->surface, keygrab_data->key, keygrab_data->mode, res);
315 KLINF("Failed to %d key %s grab request (wl_client: %p, wl_surface: %p, pid: %d): res: %d",
316 keygrab_data->key, e_keyrouter_mode_to_string(keygrab_data->mode),
317 keygrab_data->client, keygrab_data->surface,
318 e_keyrouter_util_get_pid(keygrab_data->client, keygrab_data->surface),
321 tizen_keyrouter_send_keygrab_notify(keygrab_data->resource,
322 keygrab_data->surface, keygrab_data->key, keygrab_data->mode, res);
325 /* tizen_keyrouter_set_keygrab request handler */
327 _e_keyrouter_cb_keygrab_set(struct wl_client *client, struct wl_resource *resource, struct wl_resource *surface, uint32_t key, uint32_t mode)
329 TRACE_INPUT_BEGIN(_e_keyrouter_cb_keygrab_set);
331 E_Input_Thread_Request_Keygrab_Data keygrab_data;
333 keygrab_data.resource = resource;
334 keygrab_data.surface = surface;
335 keygrab_data.client = client;
336 keygrab_data.key = key;
337 keygrab_data.mode = mode;
339 INF("client: %p, surface: %p, key: %d, mode: %d\n", keygrab_data.client, keygrab_data.surface, keygrab_data.key, keygrab_data.mode);
340 _e_keyrouter_input_thread_keygrab_set(&keygrab_data);
346 _e_keyrouter_input_thread_keygrab_unset(void *data)
348 E_Input_Thread_Request_Keygrab_Data *keygrab_data = data;
351 res = _e_keyrouter_keygrab_key_available_check(keygrab_data->key);
352 if (res != TIZEN_KEYROUTER_ERROR_NONE)
355 e_keyrouter_keygrab_unset(keygrab_data->client,
356 keygrab_data->surface, keygrab_data->key);
358 KLDBG("Success to %d key ungrab request (wl_client: %p, wl_surface: %p, pid: %d)",
359 keygrab_data->key, keygrab_data->client, keygrab_data->surface,
360 e_keyrouter_util_get_pid(keygrab_data->client, keygrab_data->surface));
362 tizen_keyrouter_send_keygrab_notify(keygrab_data->resource,
363 keygrab_data->surface, keygrab_data->key, TIZEN_KEYROUTER_MODE_NONE, res);
368 KLINF("Failed to %d key ungrab request (wl_client: %p, wl_surface: %p, pid: %d): res: %d",
369 keygrab_data->key, keygrab_data->client, keygrab_data->surface,
370 e_keyrouter_util_get_pid(keygrab_data->client, keygrab_data->surface),
373 tizen_keyrouter_send_keygrab_notify(keygrab_data->resource,
374 keygrab_data->surface, keygrab_data->key, TIZEN_KEYROUTER_MODE_NONE, res);
377 /* tizen_keyrouter unset_keygrab request handler */
379 _e_keyrouter_cb_keygrab_unset(struct wl_client *client, struct wl_resource *resource, struct wl_resource *surface, uint32_t key)
381 TRACE_INPUT_BEGIN(_e_keyrouter_cb_keygrab_unset);
383 E_Input_Thread_Request_Keygrab_Data keygrab_data;
385 keygrab_data.resource = resource;
386 keygrab_data.surface = surface;
387 keygrab_data.client = client;
388 keygrab_data.key = key;
389 keygrab_data.mode = TIZEN_KEYROUTER_MODE_NONE; /* UNUSED */
391 INF("client: %p, surface: %p, key: %d\n", keygrab_data.client,
392 keygrab_data.surface, keygrab_data.key);
394 _e_keyrouter_input_thread_keygrab_unset(&keygrab_data);
399 /* tizen_keyrouter get_keygrab_status request handler */
401 _e_keyrouter_cb_get_keygrab_status(struct wl_client *client, struct wl_resource *resource, struct wl_resource *surface, uint32_t key)
407 int mode = TIZEN_KEYROUTER_MODE_NONE;
409 TRACE_INPUT_BEGIN(_e_keyrouter_cb_get_keygrab_status);
410 mode = e_keyrouter_find_key_in_list(surface, client, key);
413 tizen_keyrouter_send_keygrab_notify(resource, surface, key, mode, TIZEN_KEYROUTER_ERROR_NONE);
417 _e_keyrouter_cb_keygrab_set_list(struct wl_client *client, struct wl_resource *resource, struct wl_resource *surface, struct wl_array *grab_list)
419 E_Keyrouter_Grab_Request *grab_request = NULL;
420 int res = TIZEN_KEYROUTER_ERROR_NONE;
423 TRACE_INPUT_BEGIN(_e_keyrouter_cb_keygrab_set_list);
425 array_len = _e_keyrouter_wl_array_length(grab_list);
427 if (0 != (array_len % 3))
429 /* FIX ME: Which way is effectively to notify invalid pair to client */
430 KLWRN("Invalid keycode and grab mode pair. Check arguments in a list");
432 tizen_keyrouter_send_keygrab_notify_list(resource, surface, NULL);
436 wl_array_for_each(grab_request, grab_list)
438 res = _e_keyrouter_keygrab_set_available_check(client, surface,
439 grab_request->key, grab_request->mode);
440 if (res != TIZEN_KEYROUTER_ERROR_NONE)
443 res = _e_keyrouter_keygrab_key_available_check(grab_request->key);
444 if (res != TIZEN_KEYROUTER_ERROR_NONE)
447 res = e_keyrouter_keygrab_set(client, surface,
448 grab_request->key, grab_request->mode);
451 grab_request->err = res;
453 if (res == TIZEN_KEYROUTER_ERROR_NONE)
454 KLDBG("Success to %d key %s grab using list(wl_client: %p, wl_surface: %p, pid: %d)",
455 grab_request->key, e_keyrouter_mode_to_string(grab_request->mode),
456 client, surface, e_keyrouter_util_get_pid(client, surface));
458 KLINF("Failed to %d key %s grab using list(wl_client: %p, wl_surface: %p, pid: %d): res: %d",
459 grab_request->key, e_keyrouter_mode_to_string(grab_request->mode),
460 client, surface, e_keyrouter_util_get_pid(client, surface),
466 tizen_keyrouter_send_keygrab_notify_list(resource, surface, grab_list);
470 _e_keyrouter_cb_keygrab_unset_list(struct wl_client *client, struct wl_resource *resource, struct wl_resource *surface, struct wl_array *ungrab_list)
472 E_Keyrouter_Ungrab_Request *ungrab_request = NULL;
473 int res = TIZEN_KEYROUTER_ERROR_NONE;
476 TRACE_INPUT_BEGIN(_e_keyrouter_cb_keygrab_unset_list);
478 array_len = _e_keyrouter_wl_array_length(ungrab_list);
480 if (0 != (array_len % 2))
482 /* FIX ME: Which way is effectively to notify invalid pair to client */
483 KLWRN("Invalid keycode and error pair. Check arguments in a list");
485 tizen_keyrouter_send_keygrab_notify_list(resource, surface, ungrab_list);
489 wl_array_for_each(ungrab_request, ungrab_list)
491 res = _e_keyrouter_keygrab_key_available_check(ungrab_request->key);
492 if (res != TIZEN_KEYROUTER_ERROR_NONE)
495 e_keyrouter_keygrab_unset(client, surface, ungrab_request->key);
498 ungrab_request->err = res;
500 if (res == TIZEN_KEYROUTER_ERROR_NONE)
501 KLDBG("Success to ungrab using list: %d key (wl_client: %p, wl_surface: %p, pid: %d)",
502 ungrab_request->key, client, surface,
503 e_keyrouter_util_get_pid(client, surface));
505 KLINF("Failed to ungrab using list: %d key (wl_client: %p, wl_surface: %p, pid: %d): res: %d",
506 ungrab_request->key, client, surface,
507 e_keyrouter_util_get_pid(client, surface), ungrab_request->err);
512 tizen_keyrouter_send_keygrab_notify_list(resource, surface, ungrab_list);
516 _e_keyrouter_cb_keygrab_get_list(struct wl_client *client, struct wl_resource *resource, struct wl_resource *surface)
520 tizen_keyrouter_send_getgrab_notify_list(resource, surface, NULL);
524 _e_keyrouter_cb_set_register_none_key(struct wl_client *client, struct wl_resource *resource, struct wl_resource *surface, uint32_t data)
529 tizen_keyrouter_send_set_register_none_key_notify(resource, NULL, 0);
533 _e_keyrouter_cb_get_keyregister_status(struct wl_client *client, struct wl_resource *resource, uint32_t key)
538 tizen_keyrouter_send_keyregister_notify(resource, (int)EINA_FALSE);
542 _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)
544 tizen_keyrouter_send_set_input_config_notify(resource, 0);
548 _e_keyrouter_cb_destroy(struct wl_client *client, struct wl_resource *resource)
550 wl_resource_destroy(resource);
553 static const struct tizen_keyrouter_interface _e_keyrouter_implementation = {
554 _e_keyrouter_cb_keygrab_set,
555 _e_keyrouter_cb_keygrab_unset,
556 _e_keyrouter_cb_get_keygrab_status,
557 _e_keyrouter_cb_keygrab_set_list,
558 _e_keyrouter_cb_keygrab_unset_list,
559 _e_keyrouter_cb_keygrab_get_list,
560 _e_keyrouter_cb_set_register_none_key,
561 _e_keyrouter_cb_get_keyregister_status,
562 _e_keyrouter_cb_set_input_config,
563 _e_keyrouter_cb_destroy,
567 _e_keyrouter_cb_unbind(struct wl_resource *resource)
569 g_tizen_keyrouter->resources = eina_list_remove(g_tizen_keyrouter->resources, resource);
572 /* tizen_keyrouter global object bind function */
574 _e_keyrouter_cb_bind(struct wl_client *client, void *data, uint32_t version, uint32_t id)
576 struct wl_resource *resource;
578 resource = wl_resource_create(client, &tizen_keyrouter_interface, version, id);
580 KLDBG("wl_resource_create(...,&tizen_keyrouter_interface,...)");
584 KLERR("Failed to create resource ! (version :%d, id:%d)", version, id);
585 wl_client_post_no_memory(client);
589 g_tizen_keyrouter->resources = eina_list_append(g_tizen_keyrouter->resources, resource);
591 wl_resource_set_implementation(resource, &_e_keyrouter_implementation, NULL, _e_keyrouter_cb_unbind);
595 _e_keyrouter_wl_client_cb_destroy(struct wl_listener *l, void *data)
597 struct wl_client *client = data;
599 KLDBG("Listener(%p) called: wl_client: %p is died", l, client);
600 e_keyrouter_remove_client_from_list(NULL, client);
602 wl_list_remove(&l->link);
605 g_tizen_keyrouter->grab_client_list = eina_list_remove(g_tizen_keyrouter->grab_client_list, client);
609 _e_keyrouter_wl_surface_cb_destroy(struct wl_listener *l, void *data)
611 struct wl_resource *surface = (struct wl_resource *)data;
613 KLDBG("Listener(%p) called: surface: %p is died", l, surface);
614 e_keyrouter_remove_client_from_list(surface, NULL);
616 wl_list_remove(&l->link);
619 g_tizen_keyrouter->grab_surface_list = eina_list_remove(g_tizen_keyrouter->grab_surface_list, surface);
623 e_keyrouter_wl_add_client_destroy_listener(struct wl_client *client)
625 struct wl_listener *destroy_listener = NULL;
627 struct wl_client *wc_data;
629 if (!client) return TIZEN_KEYROUTER_ERROR_NONE;
631 EINA_LIST_FOREACH(g_tizen_keyrouter->grab_client_list, l, wc_data)
635 if (wc_data == client)
637 return TIZEN_KEYROUTER_ERROR_NONE;
642 destroy_listener = E_NEW(struct wl_listener, 1);
644 if (!destroy_listener)
646 KLERR("Failed to allocate memory for wl_client destroy listener !");
647 return TIZEN_KEYROUTER_ERROR_NO_SYSTEM_RESOURCES;
650 destroy_listener->notify = _e_keyrouter_wl_client_cb_destroy;
651 wl_client_add_destroy_listener(client, destroy_listener);
652 g_tizen_keyrouter->grab_client_list = eina_list_append(g_tizen_keyrouter->grab_client_list, client);
654 return TIZEN_KEYROUTER_ERROR_NONE;
657 /* Function for registering wl_surface destroy listener */
659 e_keyrouter_wl_add_surface_destroy_listener(struct wl_resource *surface)
661 struct wl_listener *destroy_listener = NULL;
663 struct wl_resource *surface_data;
665 if (!surface) return TIZEN_KEYROUTER_ERROR_NONE;
667 EINA_LIST_FOREACH(g_tizen_keyrouter->grab_surface_list, l, surface_data)
671 if (surface_data == surface)
673 return TIZEN_KEYROUTER_ERROR_NONE;
678 destroy_listener = E_NEW(struct wl_listener, 1);
680 if (!destroy_listener)
682 KLERR("Failed to allocate memory for wl_surface destroy listener !");
683 return TIZEN_KEYROUTER_ERROR_NO_SYSTEM_RESOURCES;
686 destroy_listener->notify = _e_keyrouter_wl_surface_cb_destroy;
687 wl_resource_add_destroy_listener(surface, destroy_listener);
688 g_tizen_keyrouter->grab_surface_list = eina_list_append(g_tizen_keyrouter->grab_surface_list, surface);
690 return TIZEN_KEYROUTER_ERROR_NONE;
694 EINTERN EINTERN Eina_Bool
695 e_keyrouter_wl_util_do_privilege_check(struct wl_client *client, uint32_t mode, uint32_t keycode)
697 Eina_Bool res = EINA_FALSE;
699 struct wl_client *wc_data;
704 /* Top position grab is always allowed. This mode do not need privilege.*/
705 if (mode == TIZEN_KEYROUTER_MODE_TOPMOST)
708 if (krt->HardKeys[keycode].no_privcheck == EINA_TRUE &&
709 mode == TIZEN_KEYROUTER_MODE_OVERRIDABLE_EXCLUSIVE)
712 if (!client) return EINA_FALSE;
714 EINA_LIST_FOREACH(g_tizen_keyrouter->grab_client_list, l, wc_data)
716 if (wc_data == client)
723 wl_client_get_credentials(client, &pid, &uid, &gid);
724 res = e_security_privilege_check(pid, uid, "http://tizen.org/privilege/keygrab");
727 KLINF("Fail to check privilege, (pid : %d)", pid);
735 EINTERN E_Tizen_Keyrouter *
736 e_keyrouter_wl_init(struct wl_display *display)
738 EINA_SAFETY_ON_NULL_RETURN_VAL(display, NULL);
740 if (g_tizen_keyrouter) return g_tizen_keyrouter;
742 g_tizen_keyrouter = E_NEW(E_Tizen_Keyrouter, 1);
743 EINA_SAFETY_ON_NULL_RETURN_VAL(g_tizen_keyrouter, NULL);
746 g_tizen_keyrouter->global = wl_global_create(display,
747 &tizen_keyrouter_interface, 2, NULL, _e_keyrouter_cb_bind);
748 EINA_SAFETY_ON_NULL_RETURN_VAL(g_tizen_keyrouter->global, NULL);
750 return g_tizen_keyrouter;
754 e_keyrouter_wl_shutdown(void)
756 Eina_List *l, *l_next;
757 struct wl_resource *resource;
758 struct wl_client *client;
759 struct wl_listener *destroy_listener;
761 if (!g_tizen_keyrouter) return;
763 EINA_LIST_FOREACH_SAFE(g_tizen_keyrouter->grab_client_list, l, l_next, client)
765 destroy_listener = wl_client_get_destroy_listener(client, _e_keyrouter_wl_client_cb_destroy);
766 if (destroy_listener)
768 wl_list_remove(&destroy_listener->link);
769 E_FREE(destroy_listener);
771 g_tizen_keyrouter->grab_client_list = eina_list_remove(g_tizen_keyrouter->grab_client_list, client);
773 EINA_LIST_FOREACH_SAFE(g_tizen_keyrouter->grab_surface_list, l, l_next, resource)
775 destroy_listener = wl_resource_get_destroy_listener(resource, _e_keyrouter_wl_surface_cb_destroy);
776 if (destroy_listener)
778 wl_list_remove(&destroy_listener->link);
779 E_FREE(destroy_listener);
781 g_tizen_keyrouter->grab_surface_list = eina_list_remove(g_tizen_keyrouter->grab_surface_list, client);
784 EINA_LIST_FREE(g_tizen_keyrouter->resources, resource)
785 wl_resource_destroy(resource);
787 if (g_tizen_keyrouter->global)
789 wl_global_destroy(g_tizen_keyrouter->global);
791 E_FREE(g_tizen_keyrouter);