e_keyrouter_wl: refactor code
[platform/upstream/enlightenment.git] / src / bin / server / e_keyrouter_wl.c
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"
12
13 #include <tizen-extension-server-protocol.h>
14
15 static E_Tizen_Keyrouter *g_tizen_keyrouter = NULL;
16
17 struct _E_Tizen_Keyrouter
18 {
19    struct wl_global *global;
20
21    Eina_List *resources;
22
23    Eina_List *grab_surface_list;
24    Eina_List *grab_client_list;
25 };
26
27 EINTERN void
28 e_keyrouter_wl_event_surface_send(struct wl_resource *surface, int key, int mode)
29 {
30    Eina_List *l;
31    struct wl_resource *res_data;
32    struct wl_client *wc;
33
34    EINA_SAFETY_ON_NULL_RETURN(surface);
35
36    wc = wl_resource_get_client(surface);
37    EINA_SAFETY_ON_NULL_RETURN(wc);
38
39    EINA_LIST_FOREACH(g_tizen_keyrouter->resources, l, res_data)
40      {
41         if (wl_resource_get_client(res_data) != wc) continue;
42         if (wl_resource_get_version(res_data) < 2) continue;
43
44         if (e_config->key_input_ttrace_enable)
45           {
46              TRACE_INPUT_BEGIN(tizen_keyrouter_send_event_surface);
47              ELOGF("INPUT", "tizen_keyrouter_send_event_surface|B|", NULL);
48           }
49
50         tizen_keyrouter_send_event_surface(res_data, surface, key, mode);
51
52         if (e_config->key_input_ttrace_enable)
53           {
54              TRACE_INPUT_END();
55              ELOGF("INPUT", "tizen_keyrouter_send_event_surface|E|", NULL);
56           }
57      }
58 }
59
60 static void
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)
62 {
63    struct wl_resource *res;
64    Eina_List *l;
65    uint32_t serial, keycode;
66    struct wl_client *wc;
67    E_Comp_Config *comp_conf = NULL;
68
69    keycode = (ev->keycode - 8);
70
71    serial = wl_display_next_serial(e_comp_wl->wl.disp);
72
73    comp_conf = e_comp_config_get();
74
75    if (surface && !focused)
76      {
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();
80      }
81
82    if (e_config->key_input_ttrace_enable)
83      {
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);
86      }
87
88    EINA_LIST_FOREACH(key_list, l, res)
89      {
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())
94           {
95              e_comp_wl_send_event_device(client, ev->timestamp, ev->dev, serial);
96           }
97         else
98           {
99              if (dev)
100                e_comp_wl_send_event_e_device(client, ev->timestamp, dev, serial);
101           }
102
103         if (comp_conf && comp_conf->input_log_enable)
104           INF("[Server] Routed Key %s (time: %d)\n", (state ? "Down" : "Up"), ev->timestamp);
105
106         wl_keyboard_send_key(res, serial, ev->timestamp,
107                              keycode, state);
108         TRACE_INPUT_END();
109      }
110
111    if (e_config->key_input_ttrace_enable)
112      {
113         TRACE_INPUT_END();
114         ELOGF("INPUT", "wl_keyboard_send_key|E|", NULL);
115      }
116 }
117
118 Eina_Bool
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)
120 {
121    E_Client *ec = NULL;
122    struct wl_client *wc = NULL;
123    uint32_t keycode;
124    enum wl_keyboard_key_state state;
125
126    if (ev->window != e_comp->ee_win)
127      {
128         return EINA_FALSE;
129      }
130
131    keycode = (ev->keycode - 8);
132    if (!(e_comp_wl = e_comp->wl_comp_data))
133      {
134         return EINA_FALSE;
135      }
136
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"))
142      {
143         exit(0);
144      }
145 #endif
146
147    if (pressed) state = WL_KEYBOARD_KEY_STATE_PRESSED;
148    else state = WL_KEYBOARD_KEY_STATE_RELEASED;
149
150    if (!focused)
151      {
152         _e_keyrouter_wl_key_send(ev, dev, state, e_comp_input_key->kbd.resources, EINA_FALSE, client, surface);
153         return EINA_FALSE;
154      }
155
156    if ((!e_client_action_get()) && (!e_comp->input_key_grabs))
157      {
158         ec = e_client_focused_get();
159
160         if (ec && ec->comp_data)
161           {
162              struct wl_resource *surface = e_comp_wl_client_surface_get(ec);
163              if (surface)
164                {
165                   if (e_comp_input_key->kbd.focused)
166                     {
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);
169                     }
170                }
171
172              /* update modifier state */
173              e_comp_wl_input_keyboard_state_update(keycode, pressed);
174           }
175      }
176    return !!ec;
177 }
178
179 EINTERN void
180 e_keyrouter_keycancel_send(struct wl_client *client, struct wl_resource *surface, unsigned int key)
181 {
182    Eina_List *l;
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;
187
188    if (surface) wc = wl_resource_get_client(surface);
189    else wc = client;
190
191    EINA_SAFETY_ON_NULL_RETURN(wc);
192
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)
196      {
197         if (surface)
198           {
199              if (surface == data->surface)
200                {
201                   EINA_LIST_FOREACH(g_tizen_keyrouter->resources, l, resource)
202                     {
203                        if (wl_resource_get_client(resource) != wc) continue;
204
205                        tizen_keyrouter_send_key_cancel(resource, key-8);
206                     }
207                }
208           }
209         else if (client == data->wc)
210           {
211              EINA_LIST_FOREACH(g_tizen_keyrouter->resources, l, resource)
212                {
213                   if (wl_resource_get_client(resource) != wc) continue;
214
215                   tizen_keyrouter_send_key_cancel(resource, key-8);
216                }
217           }
218      }
219    g_rec_mutex_unlock(&krt->grab_key_mutex);
220 }
221
222 static int
223 _e_keyrouter_wl_array_length(const struct wl_array *array)
224 {
225    int *data = NULL;
226    int count = 0;
227
228    wl_array_for_each(data, array)
229      {
230         count++;
231      }
232
233    return count;
234 }
235
236 static int
237 _e_keyrouter_keygrab_set_available_check(struct wl_client *client, struct wl_resource *surface, int key, int mode)
238 {
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;
244
245 #ifdef HAVE_CYNARA
246    if (!e_keyrouter_wl_util_do_privilege_check(client, mode, key))
247      {
248         KLINF("No permission for %d grab mode ! (key=%d)", mode, key);
249         return TIZEN_KEYROUTER_ERROR_NO_PERMISSION;
250      }
251 #endif
252
253    /* Regarding topmost mode, a client must request to grab a key with a valid surface. */
254    if (!surface && mode == TIZEN_KEYROUTER_MODE_TOPMOST)
255      {
256         KLWRN("Invalid surface for %d grab mode ! (key=%d)", mode, key);
257         return TIZEN_KEYROUTER_ERROR_INVALID_SURFACE;
258      }
259
260    return TIZEN_KEYROUTER_ERROR_NONE;
261 }
262
263 static int
264 _e_keyrouter_keygrab_key_available_check(int key)
265 {
266    /* Check the given key range */
267    if (krt->max_tizen_hwkeys < key)
268      {
269         KLWRN("Invalid range of key ! (keycode:%d) maximum value(%d)", key, krt->max_tizen_hwkeys);
270         return TIZEN_KEYROUTER_ERROR_INVALID_KEY;
271      }
272
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)
276      {
277         KLWRN("Invalid key ! Disabled to set keygrab ! (keycode:%d)", key);
278         return TIZEN_KEYROUTER_ERROR_INVALID_KEY;
279      }
280
281    return TIZEN_KEYROUTER_ERROR_NONE;
282 }
283
284 static void
285 _e_keyrouter_input_thread_keygrab_set(void *data)
286 {
287    E_Input_Thread_Request_Keygrab_Data *keygrab_data = data;
288    int res = 0;
289
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)
293       goto failed;
294
295    res = _e_keyrouter_keygrab_key_available_check(keygrab_data->key);
296    if (res != TIZEN_KEYROUTER_ERROR_NONE)
297       goto failed;
298
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)
302       goto failed;
303
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));
308
309    tizen_keyrouter_send_keygrab_notify(keygrab_data->resource,
310          keygrab_data->surface, keygrab_data->key, keygrab_data->mode, res);
311
312    return;
313
314 failed:
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),
319          res);
320
321    tizen_keyrouter_send_keygrab_notify(keygrab_data->resource,
322          keygrab_data->surface, keygrab_data->key, keygrab_data->mode, res);
323 }
324
325 /* tizen_keyrouter_set_keygrab request handler */
326 static void
327 _e_keyrouter_cb_keygrab_set(struct wl_client *client, struct wl_resource *resource, struct wl_resource *surface, uint32_t key, uint32_t mode)
328 {
329    TRACE_INPUT_BEGIN(_e_keyrouter_cb_keygrab_set);
330
331    E_Input_Thread_Request_Keygrab_Data keygrab_data;
332
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;
338
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);
341
342    TRACE_INPUT_END();
343 }
344
345 static void
346 _e_keyrouter_input_thread_keygrab_unset(void *data)
347 {
348    E_Input_Thread_Request_Keygrab_Data *keygrab_data = data;
349    int res = 0;
350
351    res = _e_keyrouter_keygrab_key_available_check(keygrab_data->key);
352    if (res != TIZEN_KEYROUTER_ERROR_NONE)
353       goto failed;
354
355    e_keyrouter_keygrab_unset(keygrab_data->client,
356                keygrab_data->surface, keygrab_data->key);
357
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));
361
362    tizen_keyrouter_send_keygrab_notify(keygrab_data->resource,
363       keygrab_data->surface, keygrab_data->key, TIZEN_KEYROUTER_MODE_NONE, res);
364
365    return;
366
367 failed:
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),
371          res);
372
373    tizen_keyrouter_send_keygrab_notify(keygrab_data->resource,
374       keygrab_data->surface, keygrab_data->key, TIZEN_KEYROUTER_MODE_NONE, res);
375 }
376
377 /* tizen_keyrouter unset_keygrab request handler */
378 static void
379 _e_keyrouter_cb_keygrab_unset(struct wl_client *client, struct wl_resource *resource, struct wl_resource *surface, uint32_t key)
380 {
381    TRACE_INPUT_BEGIN(_e_keyrouter_cb_keygrab_unset);
382
383    E_Input_Thread_Request_Keygrab_Data keygrab_data;
384
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 */
390
391    INF("client: %p, surface: %p, key: %d\n", keygrab_data.client,
392        keygrab_data.surface, keygrab_data.key);
393
394    _e_keyrouter_input_thread_keygrab_unset(&keygrab_data);
395
396    TRACE_INPUT_END();
397 }
398
399 /* tizen_keyrouter get_keygrab_status request handler */
400 static void
401 _e_keyrouter_cb_get_keygrab_status(struct wl_client *client, struct wl_resource *resource, struct wl_resource *surface, uint32_t key)
402 {
403    (void) client;
404    (void) resource;
405    (void) surface;
406    (void) key;
407    int mode = TIZEN_KEYROUTER_MODE_NONE;
408
409    TRACE_INPUT_BEGIN(_e_keyrouter_cb_get_keygrab_status);
410    mode = e_keyrouter_find_key_in_list(surface, client, key);
411
412    TRACE_INPUT_END();
413    tizen_keyrouter_send_keygrab_notify(resource, surface, key, mode, TIZEN_KEYROUTER_ERROR_NONE);
414 }
415
416 static void
417 _e_keyrouter_cb_keygrab_set_list(struct wl_client *client, struct wl_resource *resource, struct wl_resource *surface, struct wl_array *grab_list)
418 {
419    E_Keyrouter_Grab_Request *grab_request = NULL;
420    int res = TIZEN_KEYROUTER_ERROR_NONE;
421    int array_len = 0;
422
423    TRACE_INPUT_BEGIN(_e_keyrouter_cb_keygrab_set_list);
424
425    array_len = _e_keyrouter_wl_array_length(grab_list);
426
427    if (0 != (array_len % 3))
428      {
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");
431         TRACE_INPUT_END();
432         tizen_keyrouter_send_keygrab_notify_list(resource, surface, NULL);
433         return;
434      }
435
436    wl_array_for_each(grab_request, grab_list)
437      {
438         res = _e_keyrouter_keygrab_set_available_check(client, surface,
439                   grab_request->key, grab_request->mode);
440         if (res != TIZEN_KEYROUTER_ERROR_NONE)
441           goto done;
442
443         res = _e_keyrouter_keygrab_key_available_check(grab_request->key);
444         if (res != TIZEN_KEYROUTER_ERROR_NONE)
445           goto done;
446
447         res = e_keyrouter_keygrab_set(client, surface,
448                      grab_request->key, grab_request->mode);
449
450 done:
451         grab_request->err = res;
452
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));
457         else
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),
461                 grab_request->err);
462      }
463
464    TRACE_INPUT_END();
465
466    tizen_keyrouter_send_keygrab_notify_list(resource, surface, grab_list);
467 }
468
469 static void
470 _e_keyrouter_cb_keygrab_unset_list(struct wl_client *client, struct wl_resource *resource, struct wl_resource *surface, struct wl_array *ungrab_list)
471 {
472    E_Keyrouter_Ungrab_Request *ungrab_request = NULL;
473    int res = TIZEN_KEYROUTER_ERROR_NONE;
474    int array_len = 0;
475
476    TRACE_INPUT_BEGIN(_e_keyrouter_cb_keygrab_unset_list);
477
478    array_len = _e_keyrouter_wl_array_length(ungrab_list);
479
480    if (0 != (array_len % 2))
481      {
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");
484         TRACE_INPUT_END();
485         tizen_keyrouter_send_keygrab_notify_list(resource, surface, ungrab_list);
486         return;
487      }
488
489    wl_array_for_each(ungrab_request, ungrab_list)
490      {
491         res = _e_keyrouter_keygrab_key_available_check(ungrab_request->key);
492         if (res != TIZEN_KEYROUTER_ERROR_NONE)
493           goto done;
494
495         e_keyrouter_keygrab_unset(client, surface, ungrab_request->key);
496
497 done:
498         ungrab_request->err = res;
499
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));
504         else
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);
508      }
509
510    TRACE_INPUT_END();
511
512    tizen_keyrouter_send_keygrab_notify_list(resource, surface, ungrab_list);
513 }
514
515 static void
516 _e_keyrouter_cb_keygrab_get_list(struct wl_client *client, struct wl_resource *resource, struct wl_resource *surface)
517 {
518    (void) client;
519
520    tizen_keyrouter_send_getgrab_notify_list(resource, surface, NULL);
521 }
522
523 static void
524 _e_keyrouter_cb_set_register_none_key(struct wl_client *client, struct wl_resource *resource, struct wl_resource *surface, uint32_t data)
525 {
526    (void) client;
527    (void) data;
528
529    tizen_keyrouter_send_set_register_none_key_notify(resource, NULL, 0);
530 }
531
532 static void
533 _e_keyrouter_cb_get_keyregister_status(struct wl_client *client, struct wl_resource *resource, uint32_t key)
534 {
535    (void) client;
536    (void) key;
537
538    tizen_keyrouter_send_keyregister_notify(resource, (int)EINA_FALSE);
539 }
540
541 static void
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)
543 {
544    tizen_keyrouter_send_set_input_config_notify(resource, 0);
545 }
546
547 static void
548 _e_keyrouter_cb_destroy(struct wl_client *client, struct wl_resource *resource)
549 {
550    wl_resource_destroy(resource);
551 }
552
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,
564 };
565
566 static void
567 _e_keyrouter_cb_unbind(struct wl_resource *resource)
568 {
569    g_tizen_keyrouter->resources = eina_list_remove(g_tizen_keyrouter->resources, resource);
570 }
571
572 /* tizen_keyrouter global object bind function */
573 static void
574 _e_keyrouter_cb_bind(struct wl_client *client, void *data, uint32_t version, uint32_t id)
575 {
576    struct wl_resource *resource;
577
578    resource = wl_resource_create(client, &tizen_keyrouter_interface, version, id);
579
580    KLDBG("wl_resource_create(...,&tizen_keyrouter_interface,...)");
581
582    if (!resource)
583      {
584         KLERR("Failed to create resource ! (version :%d, id:%d)", version, id);
585         wl_client_post_no_memory(client);
586          return;
587      }
588
589    g_tizen_keyrouter->resources = eina_list_append(g_tizen_keyrouter->resources, resource);
590
591    wl_resource_set_implementation(resource, &_e_keyrouter_implementation, NULL, _e_keyrouter_cb_unbind);
592 }
593
594 static void
595 _e_keyrouter_wl_client_cb_destroy(struct wl_listener *l, void *data)
596 {
597    struct wl_client *client = data;
598
599    KLDBG("Listener(%p) called: wl_client: %p is died", l, client);
600    e_keyrouter_remove_client_from_list(NULL, client);
601
602    wl_list_remove(&l->link);
603    E_FREE(l);
604
605    g_tizen_keyrouter->grab_client_list = eina_list_remove(g_tizen_keyrouter->grab_client_list, client);
606 }
607
608 static void
609 _e_keyrouter_wl_surface_cb_destroy(struct wl_listener *l, void *data)
610 {
611    struct wl_resource *surface = (struct wl_resource *)data;
612
613    KLDBG("Listener(%p) called: surface: %p is died", l, surface);
614    e_keyrouter_remove_client_from_list(surface, NULL);
615
616    wl_list_remove(&l->link);
617    E_FREE(l);
618
619    g_tizen_keyrouter->grab_surface_list = eina_list_remove(g_tizen_keyrouter->grab_surface_list, surface);
620 }
621
622 EINTERN int
623 e_keyrouter_wl_add_client_destroy_listener(struct wl_client *client)
624 {
625    struct wl_listener *destroy_listener = NULL;
626    Eina_List *l;
627    struct wl_client *wc_data;
628
629    if (!client) return TIZEN_KEYROUTER_ERROR_NONE;
630
631    EINA_LIST_FOREACH(g_tizen_keyrouter->grab_client_list, l, wc_data)
632      {
633         if (wc_data)
634           {
635              if (wc_data == client)
636                {
637                   return TIZEN_KEYROUTER_ERROR_NONE;
638                }
639           }
640      }
641
642    destroy_listener = E_NEW(struct wl_listener, 1);
643
644    if (!destroy_listener)
645      {
646         KLERR("Failed to allocate memory for wl_client destroy listener !");
647         return TIZEN_KEYROUTER_ERROR_NO_SYSTEM_RESOURCES;
648      }
649
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);
653
654    return TIZEN_KEYROUTER_ERROR_NONE;
655 }
656
657 /* Function for registering wl_surface destroy listener */
658 EINTERN int
659 e_keyrouter_wl_add_surface_destroy_listener(struct wl_resource *surface)
660 {
661    struct wl_listener *destroy_listener = NULL;
662    Eina_List *l;
663    struct wl_resource *surface_data;
664
665    if (!surface) return TIZEN_KEYROUTER_ERROR_NONE;
666
667    EINA_LIST_FOREACH(g_tizen_keyrouter->grab_surface_list, l, surface_data)
668      {
669         if (surface_data)
670           {
671              if (surface_data == surface)
672                {
673                   return TIZEN_KEYROUTER_ERROR_NONE;
674                }
675           }
676      }
677
678    destroy_listener = E_NEW(struct wl_listener, 1);
679
680    if (!destroy_listener)
681      {
682         KLERR("Failed to allocate memory for wl_surface destroy listener !");
683         return TIZEN_KEYROUTER_ERROR_NO_SYSTEM_RESOURCES;
684      }
685
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);
689
690    return TIZEN_KEYROUTER_ERROR_NONE;
691 }
692
693 #ifdef HAVE_CYNARA
694 EINTERN EINTERN Eina_Bool
695 e_keyrouter_wl_util_do_privilege_check(struct wl_client *client, uint32_t mode, uint32_t keycode)
696 {
697    Eina_Bool res = EINA_FALSE;
698    Eina_List *l;
699    struct wl_client *wc_data;
700    pid_t pid = 0;
701    uid_t uid = 0;
702    gid_t gid = 0;
703
704    /* Top position grab is always allowed. This mode do not need privilege.*/
705    if (mode == TIZEN_KEYROUTER_MODE_TOPMOST)
706      return EINA_TRUE;
707
708    if (krt->HardKeys[keycode].no_privcheck == EINA_TRUE &&
709        mode == TIZEN_KEYROUTER_MODE_OVERRIDABLE_EXCLUSIVE)
710      return EINA_TRUE;
711
712    if (!client) return EINA_FALSE;
713
714    EINA_LIST_FOREACH(g_tizen_keyrouter->grab_client_list, l, wc_data)
715      {
716         if (wc_data == client)
717           {
718              res = EINA_TRUE;
719              goto finish;
720           }
721      }
722
723    wl_client_get_credentials(client, &pid, &uid, &gid);
724    res = e_security_privilege_check(pid, uid, "http://tizen.org/privilege/keygrab");
725    if (!res)
726      {
727         KLINF("Fail to check privilege,  (pid : %d)", pid);
728      }
729
730 finish:
731    return res;
732 }
733 #endif
734
735 EINTERN E_Tizen_Keyrouter *
736 e_keyrouter_wl_init(struct wl_display *display)
737 {
738    EINA_SAFETY_ON_NULL_RETURN_VAL(display, NULL);
739
740    if (g_tizen_keyrouter) return g_tizen_keyrouter;
741
742    g_tizen_keyrouter = E_NEW(E_Tizen_Keyrouter, 1);
743    EINA_SAFETY_ON_NULL_RETURN_VAL(g_tizen_keyrouter, NULL);
744
745
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);
749
750    return g_tizen_keyrouter;
751 }
752
753 EINTERN void
754 e_keyrouter_wl_shutdown(void)
755 {
756    Eina_List *l, *l_next;
757    struct wl_resource *resource;
758    struct wl_client *client;
759    struct wl_listener *destroy_listener;
760
761    if (!g_tizen_keyrouter) return;
762
763    EINA_LIST_FOREACH_SAFE(g_tizen_keyrouter->grab_client_list, l, l_next, client)
764      {
765         destroy_listener = wl_client_get_destroy_listener(client, _e_keyrouter_wl_client_cb_destroy);
766         if (destroy_listener)
767           {
768              wl_list_remove(&destroy_listener->link);
769              E_FREE(destroy_listener);
770           }
771         g_tizen_keyrouter->grab_client_list = eina_list_remove(g_tizen_keyrouter->grab_client_list, client);
772      }
773    EINA_LIST_FOREACH_SAFE(g_tizen_keyrouter->grab_surface_list, l, l_next, resource)
774      {
775         destroy_listener = wl_resource_get_destroy_listener(resource, _e_keyrouter_wl_surface_cb_destroy);
776         if (destroy_listener)
777           {
778              wl_list_remove(&destroy_listener->link);
779              E_FREE(destroy_listener);
780           }
781         g_tizen_keyrouter->grab_surface_list = eina_list_remove(g_tizen_keyrouter->grab_surface_list, client);
782      }
783
784    EINA_LIST_FREE(g_tizen_keyrouter->resources, resource)
785      wl_resource_destroy(resource);
786
787    if (g_tizen_keyrouter->global)
788
789    wl_global_destroy(g_tizen_keyrouter->global);
790
791    E_FREE(g_tizen_keyrouter);
792 }