90a58e81bebb23d6eb9e2d6e39f58206471c4f17
[platform/core/uifw/e-mod-tizen-keyrouter.git] / src / e_mod_main_wl.c
1 #define E_COMP_WL
2 #include "e_mod_main_wl.h"
3 #include <device/power.h>
4 #include <device/callback.h>
5 #include <device/display.h>
6
7 #define KRT_IPD_INPUT_CONFIG          444
8
9 E_KeyrouterPtr krt = NULL;
10 E_API E_Module_Api e_modapi = { E_MODULE_API_VERSION, "Keyrouter Module of Window Manager" };
11
12 static E_Keyrouter_Config_Data *_e_keyrouter_init(E_Module *m);
13 static void _e_keyrouter_init_handlers(void);
14 static void _e_keyrouter_deinit_handlers(void);
15
16 static Eina_Bool _e_keyrouter_query_tizen_key_table(void);
17 static int _e_keyrouter_wl_array_length(const struct wl_array *array);
18
19 static Eina_Bool _e_keyrouter_client_cb_stack(void *data, int type, void *event);
20 static Eina_Bool _e_keyrouter_client_cb_remove(void *data, int type, void *event);
21 static void _e_keyrouter_wl_client_cb_destroy(struct wl_listener *l, void *data);
22 static void _e_keyrouter_wl_surface_cb_destroy(struct wl_listener *l, void *data);
23
24 static int _e_keyrouter_keygrab_set(struct wl_client *client, struct wl_resource *surface, uint32_t key, uint32_t mode);
25 static int _e_keyrouter_keygrab_unset(struct wl_client *client, struct wl_resource *surface, uint32_t key);
26 static Eina_Bool _e_keyrouter_cb_idler(void *data);
27 static void _e_keyrouter_cb_power_change(device_callback_e type, void* value, void* user_data);
28 #ifdef ENABLE_CYNARA
29 static void _e_keyrouter_util_cynara_log(const char *func_name, int err);
30 static Eina_Bool _e_keyrouter_util_do_privilege_check(struct wl_client *client, uint32_t mode, uint32_t keycode);
31
32 #define E_KEYROUTER_CYNARA_ERROR_CHECK_GOTO(func_name, ret, label) \
33   do \
34     { \
35        if (EINA_UNLIKELY(CYNARA_API_SUCCESS != ret)) \
36           { \
37              _e_keyrouter_util_cynara_log(func_name, ret); \
38              goto label; \
39           } \
40     } \
41   while (0)
42 #endif
43
44 int _keyrouter_log_dom = -1;
45
46 static int
47 _e_keyrouter_keygrab_set(struct wl_client *client, struct wl_resource *surface, uint32_t key, uint32_t mode)
48 {
49    int res=0;
50
51 #ifdef ENABLE_CYNARA
52    if (EINA_FALSE == _e_keyrouter_util_do_privilege_check(client, mode, key))
53      {
54         KLINF("No permission for %d grab mode ! (key=%d)", mode, key);
55         return TIZEN_KEYROUTER_ERROR_NO_PERMISSION;
56      }
57 #endif
58
59    if (!surface)
60      {
61         /* Regarding topmost mode, a client must request to grab a key with a valid surface. */
62         if (mode == TIZEN_KEYROUTER_MODE_TOPMOST ||
63             mode == TIZEN_KEYROUTER_MODE_REGISTERED)
64           {
65              KLWRN("Invalid surface for %d grab mode ! (key=%d)", mode, key);
66
67              return TIZEN_KEYROUTER_ERROR_INVALID_SURFACE;
68           }
69      }
70
71    /* Check the given key range */
72    if (krt->max_tizen_hwkeys < key)
73      {
74         KLWRN("Invalid range of key ! (keycode:%d)", key);
75         return TIZEN_KEYROUTER_ERROR_INVALID_KEY;
76      }
77
78    /* Check whether the key can be grabbed or not !
79     * Only key listed in Tizen key layout file can be grabbed. */
80    if (0 == krt->HardKeys[key].keycode)
81      {
82         KLWRN("Invalid key ! Disabled to grab ! (keycode:%d)", key);
83         return TIZEN_KEYROUTER_ERROR_INVALID_KEY;
84      }
85
86    /* Check whether the mode is valid or not */
87    if (TIZEN_KEYROUTER_MODE_REGISTERED < mode)
88      {
89         KLWRN("Invalid range of mode ! (mode:%d)", mode);
90         return  TIZEN_KEYROUTER_ERROR_INVALID_MODE;
91      }
92
93    /* Check whether the request key can be grabbed or not */
94    res = e_keyrouter_set_keygrab_in_list(surface, client, key, mode);
95
96    return res;
97 }
98
99 static void
100 _e_keyrouter_keycancel_send(struct wl_client *client, struct wl_resource *surface, unsigned int key)
101 {
102    Eina_List *l;
103    struct wl_resource *resource = NULL;
104    struct wl_client *wc = NULL;
105    E_Keyrouter_Key_List_NodePtr data;
106
107    if (surface) wc = wl_resource_get_client(surface);
108    else wc = client;
109
110    EINA_SAFETY_ON_NULL_RETURN(wc);
111
112    EINA_LIST_FOREACH(krt->HardKeys[key].press_ptr, l, data)
113      {
114         if (surface)
115           {
116              if (surface == data->surface)
117                {
118                   EINA_LIST_FOREACH(krt->resources, l, resource)
119                     {
120                        if (wl_resource_get_client(resource) != wc) continue;
121
122                        tizen_keyrouter_send_key_cancel(resource, key-8);
123                     }
124                }
125           }
126         else if (client == data->wc)
127           {
128              EINA_LIST_FOREACH(krt->resources, l, resource)
129                {
130                   if (wl_resource_get_client(resource) != wc) continue;
131
132                   tizen_keyrouter_send_key_cancel(resource, key-8);
133                }
134           }
135      }
136 }
137
138 static int
139 _e_keyrouter_keygrab_unset(struct wl_client *client, struct wl_resource *surface, uint32_t key)
140 {
141    /* Ungrab top position grabs first. This grab mode do not need privilege */
142    if (!surface)
143      e_keyrouter_find_and_remove_client_from_list(NULL, client, key, TIZEN_KEYROUTER_MODE_TOPMOST);
144    else
145      e_keyrouter_find_and_remove_client_from_list(surface, client, key, TIZEN_KEYROUTER_MODE_TOPMOST);
146
147 #ifdef ENABLE_CYNARA
148    if (EINA_FALSE == _e_keyrouter_util_do_privilege_check(client, TIZEN_KEYROUTER_MODE_NONE, key))
149      {
150         goto finish;
151      }
152 #endif
153
154    if (!surface)
155      {
156         /* EXCLUSIVE grab */
157         e_keyrouter_find_and_remove_client_from_list(NULL, client, key, TIZEN_KEYROUTER_MODE_EXCLUSIVE);
158
159         /* OVERRIDABLE_EXCLUSIVE grab */
160         e_keyrouter_find_and_remove_client_from_list(NULL, client, key, TIZEN_KEYROUTER_MODE_OVERRIDABLE_EXCLUSIVE);
161
162         /* SHARED grab */
163         e_keyrouter_find_and_remove_client_from_list(NULL, client, key, TIZEN_KEYROUTER_MODE_SHARED);
164
165         /* Press List */
166         e_keyrouter_find_and_remove_client_from_list(NULL, client, key, TIZEN_KEYROUTER_MODE_PRESSED);
167      }
168    else
169      {
170         /* EXCLUSIVE grab */
171         e_keyrouter_find_and_remove_client_from_list(surface, client, key, TIZEN_KEYROUTER_MODE_EXCLUSIVE);
172
173         /* OVERRIDABLE_EXCLUSIVE grab */
174         e_keyrouter_find_and_remove_client_from_list(surface, client, key, TIZEN_KEYROUTER_MODE_OVERRIDABLE_EXCLUSIVE);
175
176         /* SHARED grab */
177         e_keyrouter_find_and_remove_client_from_list(surface, client, key, TIZEN_KEYROUTER_MODE_SHARED);
178
179         /* REGISTERED grab */
180         e_keyrouter_unset_keyregister(surface, client, key);
181
182         /* Press List */
183         e_keyrouter_find_and_remove_client_from_list(surface, client, key, TIZEN_KEYROUTER_MODE_PRESSED);
184      }
185
186 finish:
187    _e_keyrouter_keycancel_send(client, surface, key);
188
189    return TIZEN_KEYROUTER_ERROR_NONE;
190 }
191
192 /* tizen_keyrouter_set_keygrab request handler */
193 static void
194 _e_keyrouter_cb_keygrab_set(struct wl_client *client, struct wl_resource *resource, struct wl_resource *surface, uint32_t key, uint32_t mode)
195 {
196    int res = 0;
197
198    TRACE_INPUT_BEGIN(_e_keyrouter_cb_keygrab_set);
199
200    res = _e_keyrouter_keygrab_set(client, surface, key, mode);
201
202    TRACE_INPUT_END();
203
204    if (res == TIZEN_KEYROUTER_ERROR_NONE)
205      {
206         if (mode == TIZEN_KEYROUTER_MODE_EXCLUSIVE)
207           {
208              KLINF("Success to %d key %s grab request (wl_client: %p, wl_surface: %p, pid: %d)", key, e_keyrouter_mode_to_string(mode),
209                 client, surface, e_keyrouter_util_get_pid(client, surface));
210           }
211         else
212           {
213              KLDBG("Success to %d key %s grab request (wl_client: %p, wl_surface: %p, pid: %d)", key, e_keyrouter_mode_to_string(mode),
214                 client, surface, e_keyrouter_util_get_pid(client, surface));
215           }
216      }
217    else
218      KLINF("Failed to %d key %s grab request (wl_client: %p, wl_surface: %p, pid: %d): res: %d", key, e_keyrouter_mode_to_string(mode),
219         client, surface, e_keyrouter_util_get_pid(client, surface), res);
220    tizen_keyrouter_send_keygrab_notify(resource, surface, key, mode, res);
221 }
222
223 /* tizen_keyrouter unset_keygrab request handler */
224 static void
225 _e_keyrouter_cb_keygrab_unset(struct wl_client *client, struct wl_resource *resource, struct wl_resource *surface, uint32_t key)
226 {
227    int res = 0;
228
229    TRACE_INPUT_BEGIN(_e_keyrouter_cb_keygrab_unset);
230
231    res = _e_keyrouter_keygrab_unset(client, surface, key);
232
233    TRACE_INPUT_END();
234
235    if (res == TIZEN_KEYROUTER_ERROR_NONE)
236      KLDBG("Success to %d key ungrab request (wl_client: %p, wl_surface: %p, pid: %d)", key, client, surface,
237            e_keyrouter_util_get_pid(client, surface));
238    else
239      KLINF("Failed to %d key ungrab request (wl_client: %p, wl_surface: %p, pid: %d): res: %d", key, client, surface,
240            e_keyrouter_util_get_pid(client, surface), res);
241    tizen_keyrouter_send_keygrab_notify(resource, surface, key, TIZEN_KEYROUTER_MODE_NONE, res);
242 }
243
244 /* tizen_keyrouter get_keygrab_status request handler */
245 static void
246 _e_keyrouter_cb_get_keygrab_status(struct wl_client *client, struct wl_resource *resource, struct wl_resource *surface, uint32_t key)
247 {
248    (void) client;
249    (void) resource;
250    (void) surface;
251    (void) key;
252    int mode = TIZEN_KEYROUTER_MODE_NONE;
253
254    TRACE_INPUT_BEGIN(_e_keyrouter_cb_get_keygrab_status);
255    mode = e_keyrouter_find_key_in_list(surface, client, key);
256
257    TRACE_INPUT_END();
258    tizen_keyrouter_send_keygrab_notify(resource, surface, key, mode, TIZEN_KEYROUTER_ERROR_NONE);
259 }
260
261 static void
262 _e_keyrouter_cb_keygrab_set_list(struct wl_client *client, struct wl_resource *resource, struct wl_resource *surface, struct wl_array *grab_list)
263 {
264    E_Keyrouter_Grab_Request *grab_request = NULL;
265    int res = TIZEN_KEYROUTER_ERROR_NONE;
266    int array_len = 0;
267
268    TRACE_INPUT_BEGIN(_e_keyrouter_cb_keygrab_set_list);
269
270    array_len = _e_keyrouter_wl_array_length(grab_list);
271
272    if (0 != (array_len % 3))
273      {
274         /* FIX ME: Which way is effectively to notify invalid pair to client */
275         KLWRN("Invalid keycode and grab mode pair. Check arguments in a list");
276         TRACE_INPUT_END();
277         tizen_keyrouter_send_keygrab_notify_list(resource, surface, NULL);
278         return;
279      }
280
281    wl_array_for_each(grab_request, grab_list)
282      {
283         res = _e_keyrouter_keygrab_set(client, surface, grab_request->key, grab_request->mode);
284         grab_request->err = res;
285         if (res == TIZEN_KEYROUTER_ERROR_NONE)
286           KLDBG("Success to %d key %s grab using list(wl_client: %p, wl_surface: %p, pid: %d)",
287                 grab_request->key, e_keyrouter_mode_to_string(grab_request->mode),
288                 client, surface, e_keyrouter_util_get_pid(client, surface));
289         else
290           KLINF("Failed to %d key %s grab using list(wl_client: %p, wl_surface: %p, pid: %d): res: %d",
291                 grab_request->key, e_keyrouter_mode_to_string(grab_request->mode),
292                 client, surface, e_keyrouter_util_get_pid(client, surface), grab_request->err);
293      }
294
295
296    TRACE_INPUT_END();
297    tizen_keyrouter_send_keygrab_notify_list(resource, surface, grab_list);
298 }
299
300 static void
301 _e_keyrouter_cb_keygrab_unset_list(struct wl_client *client, struct wl_resource *resource, struct wl_resource *surface, struct wl_array *ungrab_list)
302 {
303    E_Keyrouter_Ungrab_Request *ungrab_request = NULL;
304    int res = TIZEN_KEYROUTER_ERROR_NONE;
305    int array_len = 0;
306
307    TRACE_INPUT_BEGIN(_e_keyrouter_cb_keygrab_unset_list);
308
309    array_len = _e_keyrouter_wl_array_length(ungrab_list);
310
311    if (0 != (array_len % 2))
312      {
313         /* FIX ME: Which way is effectively to notify invalid pair to client */
314         KLWRN("Invalid keycode and error pair. Check arguments in a list");
315         TRACE_INPUT_END();
316         tizen_keyrouter_send_keygrab_notify_list(resource, surface, ungrab_list);
317         return;
318      }
319
320    wl_array_for_each(ungrab_request, ungrab_list)
321      {
322         res = _e_keyrouter_keygrab_unset(client, surface, ungrab_request->key);
323         ungrab_request->err = res;
324         if (res == TIZEN_KEYROUTER_ERROR_NONE)
325           KLDBG("Success to ungrab using list: %d key (wl_client: %p, wl_surface: %p, pid: %d)",
326                 ungrab_request->key, client, surface, e_keyrouter_util_get_pid(client, surface));
327         else
328           KLINF("Failed to ungrab using list: %d key (wl_client: %p, wl_surface: %p, pid: %d): res: %d",
329                 ungrab_request->key, client, surface, e_keyrouter_util_get_pid(client, surface), ungrab_request->err);
330      }
331
332    TRACE_INPUT_END();
333    tizen_keyrouter_send_keygrab_notify_list(resource, surface, ungrab_list);
334 }
335
336 static void
337 _e_keyrouter_cb_get_keyregister_status(struct wl_client *client, struct wl_resource *resource, uint32_t key)
338 {
339    (void) client;
340    (void) key;
341
342    int delivery_mode = TIZEN_KEYROUTER_MODE_NONE;
343    Eina_Bool below_focus = EINA_FALSE;
344    E_Client *ec_top = NULL, *ec_focus = NULL;
345    struct wl_resource *surface = NULL, *surface_focus = NULL;
346    Eina_List* key_list = NULL, *l = NULL, *l_next = NULL;
347    E_Keyrouter_Key_List_NodePtr key_node_data = NULL;
348
349    int *key_data = NULL;
350    int deliver_invisible = 0;
351
352     // Check for exclusive & or_exclusive mode delivery
353    if (krt->HardKeys[key].excl_ptr)
354      {
355         delivery_mode = TIZEN_KEYROUTER_MODE_EXCLUSIVE;
356         goto finish;
357      }
358    if (krt->HardKeys[key].or_excl_ptr)
359       {
360          delivery_mode = TIZEN_KEYROUTER_MODE_OVERRIDABLE_EXCLUSIVE;
361          goto finish;
362       }
363
364    ec_top = e_client_top_get();
365    ec_focus = e_client_focused_get();
366    surface_focus = e_keyrouter_util_get_surface_from_eclient(ec_focus);
367
368    for (; ec_top != NULL; ec_top = e_client_below_get(ec_top))
369      {
370         surface = e_keyrouter_util_get_surface_from_eclient(ec_top);
371
372         if (surface == NULL)
373           {
374              // Not a valid surface.
375              continue;
376           }
377
378         if (ec_top->is_cursor) continue;
379
380         //Check Top-Most Delivery
381         if( below_focus == EINA_FALSE)
382           {
383              EINA_LIST_FOREACH_SAFE(krt->HardKeys[key].top_ptr, l, l_next, key_node_data)
384                {
385                   if (!key_node_data) continue;
386                   if ((ec_top->visible) && (ec_top == wl_resource_get_user_data(key_node_data->surface)))
387                     {
388                        delivery_mode = TIZEN_KEYROUTER_MODE_TOPMOST;
389                        goto finish;
390                     }
391                }
392           }
393
394         // Check if window stack reaches to focus window
395         if (ec_top == ec_focus)
396           {
397              below_focus = EINA_TRUE;
398           }
399
400         // Check for FORCE DELIVER to INVISIBLE WINDOW
401         if (deliver_invisible && IsInvisibleGetWindow(surface))
402           {
403              goto finish;
404           }
405
406         // Check for visible window first <Consider VISIBILITY>
407         // return if not visible
408         if (ec_top->visibility.obscured == E_VISIBILITY_FULLY_OBSCURED || ec_top->visibility.obscured == E_VISIBILITY_UNKNOWN)
409           {
410              continue;
411           }
412
413         // Set key Event Delivery for INVISIBLE WINDOW
414         if (IsInvisibleSetWindow(surface))
415           {
416              deliver_invisible = 1;
417           }
418
419         if (IsNoneKeyRegisterWindow(surface))
420           {
421              continue;
422           }
423
424         if (e_keyrouter_is_registered_window(surface))
425           {
426              // get the key list and deliver events if it has registered for that key
427              key_list = _e_keyrouter_registered_window_key_list(surface);
428              if (key_list)
429                {
430                   EINA_LIST_FOREACH(key_list, l, key_data)
431                     {
432                        if(!key_data)
433                          {
434                             continue;
435                          }
436
437                        if(*key_data == key)
438                          {
439                             delivery_mode = TIZEN_KEYROUTER_MODE_REGISTERED;
440                             goto finish;
441                          }
442                     }
443                }
444           }
445
446         if (surface != surface_focus)
447           {
448              if (below_focus == EINA_FALSE)
449                {
450                   continue;
451                }
452
453              // Deliver to below Non Registered window
454              else if (!e_keyrouter_is_registered_window(surface))
455                {
456                   goto finish;
457                }
458              else
459                {
460                   continue;
461                }
462           }
463         else
464           {
465              // Deliver to Focus Surface window from FOCUS MODE
466              if (!e_keyrouter_is_registered_window(surface))
467                {
468                   goto finish;
469                }
470              else
471                {
472                   continue;
473                }
474           }
475     }
476
477    finish:
478    tizen_keyrouter_send_keyregister_notify(resource, (int)delivery_mode);
479 }
480
481 static void
482 _e_keyrouter_cb_set_input_config(struct wl_client *client, struct wl_resource *resource, struct wl_resource *surface, uint32_t config_mode, uint32_t value)
483 {
484    Eina_Bool res = EINA_TRUE;
485
486    if (surface == NULL && config_mode != TIZEN_KEYROUTER_CONFIG_MODE_PICTURE_OFF)
487      {
488         KLWRN("Error Surface is NULL");
489         res = EINA_FALSE;
490         goto send_input_config_notify;
491      }
492
493    switch (config_mode)
494      {
495         case TIZEN_KEYROUTER_CONFIG_MODE_INVISIBLE_SET:
496            if (value)
497              {
498                 krt->invisible_set_window_list= eina_list_append(krt->invisible_set_window_list, surface);
499              }
500            else
501              {
502                 krt->invisible_set_window_list= eina_list_remove(krt->invisible_set_window_list, surface);
503              }
504            break;
505
506         case KRT_IPD_INPUT_CONFIG:
507            krt->playback_daemon_surface = surface;
508            KLINF("Registered playback daemon wl_surface: %p",surface);
509            break;
510
511         case TIZEN_KEYROUTER_CONFIG_MODE_INVISIBLE_GET:
512            if (value)
513              {
514                 krt->invisible_get_window_list= eina_list_append(krt->invisible_get_window_list, surface);
515              }
516            else
517              {
518                 krt->invisible_get_window_list= eina_list_remove(krt->invisible_get_window_list, surface);
519              }
520            break;
521
522         case TIZEN_KEYROUTER_CONFIG_MODE_NUM_KEY_FOCUS:
523             // to do ;
524             break;
525
526         case TIZEN_KEYROUTER_CONFIG_MODE_PICTURE_OFF:
527             res = e_keyrouter_prepend_to_keylist(surface, surface ? NULL : client, value, TIZEN_KEYROUTER_MODE_PICTURE_OFF, EINA_FALSE);
528             /* As surface/client destroy listener got added in e_keyrouter_prepend_to_keylist() function already */
529             value = 0;
530             break;
531
532         default:
533             KLWRN("Invalid mode: %d", config_mode);
534             res= EINA_FALSE;
535             goto send_input_config_notify;
536      }
537
538    if (value)
539      {
540         KLDBG("Add a wl_surface(%p) to destory listener", surface);
541         e_keyrouter_add_surface_destroy_listener(surface);
542      }
543
544 send_input_config_notify:
545    if (res == TIZEN_KEYROUTER_ERROR_NONE)
546      {
547         KLDBG("Success to set input config: wl_surface (%p) for mode %d with value (%d)", surface, config_mode, value);
548      }
549    else
550      {
551         KLINF("Failed to set input config (res: %d): wl_surface (%p) for mode %d with value (%d)", res, surface, config_mode, value);
552      }
553    tizen_keyrouter_send_set_input_config_notify(resource, (int)res);
554 }
555
556 /* tizen_keyrouter check if given surface in register none key list */
557 Eina_Bool
558 IsNoneKeyRegisterWindow(struct wl_resource *surface)
559 {
560    struct wl_resource *surface_ldata = NULL;
561    Eina_List *l = NULL, *l_next = NULL;
562
563    EINA_LIST_FOREACH_SAFE (krt->registered_none_key_window_list, l, l_next, surface_ldata)
564      {
565         if (surface_ldata == surface)
566           {
567              KLDBG("Given wl_surface(%p) is in NoneKeyRegisterWindow", surface);
568              return EINA_TRUE;
569           }
570      }
571    return EINA_FALSE;
572 }
573
574 /* tizen_keyrouter check if given surface in register invisible set list */
575 Eina_Bool
576 IsInvisibleSetWindow(struct wl_resource *surface)
577 {
578    struct wl_resource *surface_ldata = NULL;
579    Eina_List *l = NULL, *l_next = NULL;
580
581    EINA_LIST_FOREACH_SAFE(krt->invisible_set_window_list, l, l_next, surface_ldata)
582      {
583         if (surface_ldata == surface)
584           {
585              return EINA_TRUE;
586           }
587      }
588    return EINA_FALSE;
589 }
590
591 /* tizen_keyrouter check if given surface in register invisible get list */
592 Eina_Bool
593 IsInvisibleGetWindow(struct wl_resource *surface)
594 {
595    struct wl_resource *surface_ldata = NULL;
596    Eina_List *l = NULL, *l_next = NULL;
597
598    EINA_LIST_FOREACH_SAFE(krt->invisible_get_window_list, l, l_next, surface_ldata)
599      {
600         if (surface_ldata == surface)
601           {
602              return EINA_TRUE;
603           }
604      }
605    return EINA_FALSE;
606 }
607
608 static void
609 _e_keyrouter_cb_set_register_none_key(struct wl_client *client, struct wl_resource *resource, struct wl_resource *surface, uint32_t data)
610 {
611    (void) client;
612
613    // Register None key set/get
614    krt->register_none_key = data;
615    if (krt->register_none_key)
616      {
617         krt->registered_none_key_window_list = eina_list_append(krt->registered_none_key_window_list, surface);
618         if (surface)
619           {
620              e_keyrouter_add_surface_destroy_listener(surface);
621              /* TODO: if failed add surface_destory_listener, remove keygrabs */
622           }
623      }
624    else
625      {
626         krt->registered_none_key_window_list = eina_list_remove(krt->registered_none_key_window_list, surface);
627      }
628
629    KLDBG("Set Registered None Key called on wl_surface (%p) with data (%d)", surface, krt->register_none_key);
630    tizen_keyrouter_send_set_register_none_key_notify(resource, NULL, krt->register_none_key);
631 }
632
633 static void
634 _e_keyrouter_cb_keygrab_get_list(struct wl_client *client, struct wl_resource *resource, struct wl_resource *surface)
635 {
636    E_Keyrouter_Key_List_NodePtr key_node_data = NULL;
637    struct wl_array grab_result_list = {0,};
638    E_Keyrouter_Grab_Request *grab_result = NULL;
639    E_Keyrouter_Registered_Window_Info *rwin_info = NULL;
640    Eina_List *l = NULL, *ll = NULL, *l_next = NULL;
641    int *key_data;
642    int i;
643
644    wl_array_init(&grab_result_list);
645
646    for (i = 0; i < krt->max_tizen_hwkeys; i++)
647      {
648         if (0 == krt->HardKeys[i].keycode) continue;
649
650         EINA_LIST_FOREACH_SAFE(krt->HardKeys[i].excl_ptr, l, l_next, key_node_data)
651           {
652              if (surface == key_node_data->surface)
653                {
654                   grab_result = wl_array_add(&grab_result_list, sizeof(E_Keyrouter_Grab_Request));
655                   if (grab_result)
656                     {
657                        grab_result->key = i;
658                        grab_result->mode = TIZEN_KEYROUTER_MODE_EXCLUSIVE;
659                        grab_result->err = TIZEN_KEYROUTER_ERROR_NONE;
660                     }
661                }
662           }
663         EINA_LIST_FOREACH_SAFE(krt->HardKeys[i].or_excl_ptr, l, l_next, key_node_data)
664           {
665              if (surface == key_node_data->surface)
666                {
667                   grab_result = wl_array_add(&grab_result_list, sizeof(E_Keyrouter_Grab_Request));
668                   if (grab_result)
669                     {
670                        grab_result->key = i;
671                        grab_result->mode = TIZEN_KEYROUTER_MODE_OVERRIDABLE_EXCLUSIVE;
672                        grab_result->err = TIZEN_KEYROUTER_ERROR_NONE;
673                     }
674                }
675           }
676         EINA_LIST_FOREACH_SAFE(krt->HardKeys[i].top_ptr, l, l_next, key_node_data)
677           {
678              if (surface == key_node_data->surface)
679                {
680                   grab_result = wl_array_add(&grab_result_list, sizeof(E_Keyrouter_Grab_Request));
681                   if (grab_result)
682                     {
683                        grab_result->key = i;
684                        grab_result->mode = TIZEN_KEYROUTER_MODE_TOPMOST;
685                        grab_result->err = TIZEN_KEYROUTER_ERROR_NONE;
686                     }
687                }
688           }
689         EINA_LIST_FOREACH_SAFE(krt->HardKeys[i].shared_ptr, l, l_next, key_node_data)
690           {
691              if (surface == key_node_data->surface)
692                {
693                   grab_result = wl_array_add(&grab_result_list, sizeof(E_Keyrouter_Grab_Request));
694                   if (grab_result)
695                     {
696                        grab_result->key = i;
697                        grab_result->mode = TIZEN_KEYROUTER_MODE_SHARED;
698                        grab_result->err = TIZEN_KEYROUTER_ERROR_NONE;
699                     }
700                }
701           }
702      }
703    // handle register mode here
704    EINA_LIST_FOREACH(krt->registered_window_list, l, rwin_info)
705      {
706         if (rwin_info->surface == surface)
707           {
708              EINA_LIST_FOREACH(rwin_info->keys, ll, key_data)
709                {
710                   grab_result = wl_array_add(&grab_result_list, sizeof(E_Keyrouter_Grab_Request));
711                   if (grab_result)
712                     {
713                        grab_result->key = *key_data;
714                        grab_result->mode = TIZEN_KEYROUTER_MODE_REGISTERED;
715                        grab_result->err = TIZEN_KEYROUTER_ERROR_NONE;
716                     }
717                }
718           }
719      }
720
721    tizen_keyrouter_send_getgrab_notify_list(resource, surface, &grab_result_list);
722    wl_array_release(&grab_result_list);
723 }
724
725 /* Function for registering wl_client destroy listener */
726 int
727 e_keyrouter_add_client_destroy_listener(struct wl_client *client)
728 {
729    struct wl_listener *destroy_listener = NULL;
730    Eina_List *l;
731    struct wl_client *wc_data;
732
733    if (!client) return TIZEN_KEYROUTER_ERROR_NONE;
734
735    EINA_LIST_FOREACH(krt->grab_client_list, l, wc_data)
736      {
737         if (wc_data)
738           {
739              if (wc_data == client)
740                {
741                   return TIZEN_KEYROUTER_ERROR_NONE;
742                }
743           }
744      }
745
746    destroy_listener = E_NEW(struct wl_listener, 1);
747
748    if (!destroy_listener)
749      {
750         KLERR("Failed to allocate memory for wl_client destroy listener !");
751         return TIZEN_KEYROUTER_ERROR_NO_SYSTEM_RESOURCES;
752      }
753
754    destroy_listener->notify = _e_keyrouter_wl_client_cb_destroy;
755    wl_client_add_destroy_listener(client, destroy_listener);
756    krt->grab_client_list = eina_list_append(krt->grab_client_list, client);
757
758    return TIZEN_KEYROUTER_ERROR_NONE;
759 }
760
761 /* Function for registering wl_surface destroy listener */
762 int
763 e_keyrouter_add_surface_destroy_listener(struct wl_resource *surface)
764 {
765    struct wl_listener *destroy_listener = NULL;
766    Eina_List *l;
767    struct wl_resource *surface_data;
768
769    if (!surface) return TIZEN_KEYROUTER_ERROR_NONE;
770
771    EINA_LIST_FOREACH(krt->grab_surface_list, l, surface_data)
772      {
773         if (surface_data)
774           {
775              if (surface_data == surface)
776                {
777                   return TIZEN_KEYROUTER_ERROR_NONE;
778                }
779           }
780      }
781
782    destroy_listener = E_NEW(struct wl_listener, 1);
783
784    if (!destroy_listener)
785      {
786         KLERR("Failed to allocate memory for wl_surface destroy listener !");
787         return TIZEN_KEYROUTER_ERROR_NO_SYSTEM_RESOURCES;
788      }
789
790    destroy_listener->notify = _e_keyrouter_wl_surface_cb_destroy;
791    wl_resource_add_destroy_listener(surface, destroy_listener);
792    krt->grab_surface_list = eina_list_append(krt->grab_surface_list, surface);
793
794    return TIZEN_KEYROUTER_ERROR_NONE;
795 }
796
797 static void
798 _e_keyrouter_cb_destroy(struct wl_client *client, struct wl_resource *resource)
799 {
800    wl_resource_destroy(resource);
801 }
802
803 static const struct tizen_keyrouter_interface _e_keyrouter_implementation = {
804    _e_keyrouter_cb_keygrab_set,
805    _e_keyrouter_cb_keygrab_unset,
806    _e_keyrouter_cb_get_keygrab_status,
807    _e_keyrouter_cb_keygrab_set_list,
808    _e_keyrouter_cb_keygrab_unset_list,
809    _e_keyrouter_cb_keygrab_get_list,
810    _e_keyrouter_cb_set_register_none_key,
811    _e_keyrouter_cb_get_keyregister_status,
812    _e_keyrouter_cb_set_input_config,
813    _e_keyrouter_cb_destroy,
814 };
815
816 static void
817 _e_keyrouter_cb_unbind(struct wl_resource *resource)
818 {
819    krt->resources = eina_list_remove(krt->resources, resource);
820 }
821
822 /* tizen_keyrouter global object bind function */
823 static void
824 _e_keyrouter_cb_bind(struct wl_client *client, void *data, uint32_t version, uint32_t id)
825 {
826    E_KeyrouterPtr krt_instance = data;
827    struct wl_resource *resource;
828
829    resource = wl_resource_create(client, &tizen_keyrouter_interface, version, id);
830
831    KLDBG("wl_resource_create(...,&tizen_keyrouter_interface,...)");
832
833    if (!resource)
834      {
835         KLERR("Failed to create resource ! (version :%d, id:%d)", version, id);
836         wl_client_post_no_memory(client);
837          return;
838      }
839
840    krt->resources = eina_list_append(krt->resources, resource);
841
842    wl_resource_set_implementation(resource, &_e_keyrouter_implementation, krt_instance, _e_keyrouter_cb_unbind);
843 }
844
845 static void
846 _e_keyrouter_keygrab_status_print(FILE *log_fl, Eina_List *list)
847 {
848    Eina_List *l;
849    E_Keyrouter_Key_List_NodePtr kdata;
850    int pid;
851    char *cmd;
852
853    EINA_LIST_FOREACH(list, l, kdata)
854      {
855         pid = e_keyrouter_util_get_pid(kdata->wc, kdata->surface);
856         cmd = e_keyrouter_util_cmd_get_from_pid(pid);
857         fprintf(log_fl, "                [surface: %p, client: %p, pid: %d(%s)]\n", kdata->surface, kdata->wc, pid, cmd ?: "Unknown");
858         if(cmd) E_FREE(cmd);
859         if (kdata->surface)
860           {
861              fprintf(log_fl, "                    -- Surface Information --\n");
862              fprintf(log_fl, "                        = client: %p\n", wl_resource_get_client(kdata->surface));
863              fprintf(log_fl, "                        = resource: %s(%d)\n", wl_resource_get_class(kdata->surface), wl_resource_get_id(kdata->surface));
864           }
865         else
866           {
867              fprintf(log_fl, "                    -- Client Information --\n");
868              fprintf(log_fl, "                        = connected fd: %d\n", wl_client_get_fd(kdata->wc));
869           }
870      }
871 }
872
873
874 static void
875 _e_keyrouter_info_print(void *data, const char *log_path)
876 {
877    char *keyname, *cmd;
878    int  i, c, pid, *idata;
879    FILE *log_fl;
880    Eina_List *l, *ll;
881    E_Keyrouter_Registered_Window_Info *rdata;
882
883    log_fl = fopen(log_path, "a");
884    if (!log_fl)
885      {
886         KLERR("failed: open file(%s)", log_path);
887         return;
888      }
889
890    setvbuf(log_fl, NULL, _IOLBF, 512);
891
892    fprintf(log_fl, "\n===== Keyrouter Information =====\n");
893    fprintf(log_fl, "    ----- Grabbable Keys -----\n");
894    for (i = 8; i <= krt->max_tizen_hwkeys; i++)
895      {
896         if (!krt->HardKeys[i].keycode) continue;
897
898         keyname = e_keyrouter_util_keyname_get_from_keycode(i);
899
900         fprintf(log_fl, "         Key [%3d], Keyname: %s\n", i, keyname);
901
902         free(keyname);
903         keyname = NULL;
904      }
905    fprintf(log_fl, "    ----- End -----\n\n");
906
907    fprintf(log_fl, "    ----- Register Window List -----\n");
908    EINA_LIST_FOREACH(krt->registered_window_list, l, rdata)
909      {
910         pid = e_keyrouter_util_get_pid(NULL, rdata->surface);
911         cmd = e_keyrouter_util_cmd_get_from_pid(pid);
912         fprintf(log_fl, "        [ surface: %p, client: %p, pid: %d(%s) ]\n",
913                          rdata->surface, wl_resource_get_client(rdata->surface), pid, cmd ?: "Unknown");
914         if(cmd) E_FREE(cmd);
915         c = 0;
916         EINA_LIST_FOREACH(rdata->keys, ll, idata)
917           {
918              keyname = e_keyrouter_util_keyname_get_from_keycode(*idata);
919              if (c == 0)
920                fprintf(log_fl, "            registered key: Key [%3d], Keyname: %s\n", *idata, keyname);
921              else
922                fprintf(log_fl, "                            Key [%3d], Keyname: %s\n", *idata, keyname);
923              c++;
924              free(keyname);
925              keyname = NULL;
926           }
927      }
928    fprintf(log_fl, "    ----- End -----\n\n");
929
930    fclose(log_fl);
931    log_fl = NULL;
932 }
933
934 static void
935 _e_keyrouter_keygrab_print(void *data, const char *log_path)
936 {
937    Eina_List *l;
938    E_Keyrouter_Key_List_NodePtr kdata;
939    E_Client *ec_focus;
940    struct wl_resource *surface_focus;
941    struct wl_client *wc_focus;
942    int pid_focus, pid, i;
943    char *cmd_focus, *cmd, *keyname;
944    FILE *log_fl;
945
946    (void) data;
947
948    log_fl = fopen(log_path, "a");
949    if (!log_fl)
950      {
951         KLERR("failed: open file(%s)", log_path);
952         return;
953      }
954
955    setvbuf(log_fl, NULL, _IOLBF, 512);
956
957    fprintf(log_fl, "\n===== Keygrab Status =====\n");
958
959    ec_focus = e_client_focused_get();
960    fprintf(log_fl, "    ----- Focus Window Info -----\n");
961    if (ec_focus)
962      {
963         surface_focus = e_keyrouter_util_get_surface_from_eclient(ec_focus);
964         wc_focus = wl_resource_get_client(surface_focus);
965         pid_focus = e_keyrouter_util_get_pid(NULL, surface_focus);
966         cmd_focus = e_keyrouter_util_cmd_get_from_pid(pid_focus);
967
968         fprintf(log_fl, "        Focus Client: E_Client: %p\n", ec_focus);
969         fprintf(log_fl, "                      Surface: %p, Client: %p\n", surface_focus, wc_focus);
970         fprintf(log_fl, "                      pid: %d, cmd: %s\n", pid_focus, cmd_focus ?: "Unknown");
971         if(cmd_focus) E_FREE(cmd_focus);
972      }
973    else
974      {
975         fprintf(log_fl, "        No Focus Client\n");
976      }
977    fprintf(log_fl, "    ----- End -----\n\n");
978
979    fprintf(log_fl, "    ----- Grabbed keys Info -----\n\n");
980    for (i = 8; i <= krt->max_tizen_hwkeys; i++)
981      {
982         if (!krt->HardKeys[i].keycode) continue;
983         if (!krt->HardKeys[i].excl_ptr &&
984             !krt->HardKeys[i].or_excl_ptr &&
985             !krt->HardKeys[i].top_ptr &&
986             !krt->HardKeys[i].shared_ptr &&
987             !krt->HardKeys[i].registered_ptr)
988           continue;
989
990         keyname = e_keyrouter_util_keyname_get_from_keycode(i);
991
992         fprintf(log_fl, "        [ Keycode: %d, Keyname: %s ]\n", i, keyname);
993
994         free(keyname);
995         keyname = NULL;
996
997         if (krt->HardKeys[i].excl_ptr)
998           {
999              fprintf(log_fl, "            == Exclusive Grab ==\n");
1000              EINA_LIST_FOREACH(krt->HardKeys[i].excl_ptr, l, kdata)
1001                {
1002                   pid = e_keyrouter_util_get_pid(kdata->wc, kdata->surface);
1003                   cmd = e_keyrouter_util_cmd_get_from_pid(pid);
1004                   fprintf(log_fl, "                [surface: %p, client: %p, pid: %d(%s)]\n", kdata->surface, kdata->wc, pid, cmd ?: "Unknown");
1005                   if(cmd) E_FREE(cmd);
1006                   if (kdata->surface)
1007                     {
1008                        fprintf(log_fl, "                    -- Surface Information --\n");
1009                        fprintf(log_fl, "                        = wl_client: %p\n", wl_resource_get_client(kdata->surface));
1010                        fprintf(log_fl, "                        = resource: %s(%d)\n", wl_resource_get_class(kdata->surface), wl_resource_get_id(kdata->surface));
1011                     }
1012                   else
1013                     {
1014                        fprintf(log_fl, "                    -- Client Information --\n");
1015                        fprintf(log_fl, "                        = connected fd: %d\n", wl_client_get_fd(kdata->wc));
1016                     }
1017                }
1018             }
1019
1020         if (krt->HardKeys[i].or_excl_ptr)
1021           {
1022              fprintf(log_fl, "            == Overidable Exclusive Grab ==\n");
1023              _e_keyrouter_keygrab_status_print(log_fl, krt->HardKeys[i].or_excl_ptr);
1024           }
1025
1026         if (krt->HardKeys[i].top_ptr)
1027           {
1028              fprintf(log_fl, "            == Top Position Grab ==\n");
1029              _e_keyrouter_keygrab_status_print(log_fl, krt->HardKeys[i].top_ptr);
1030           }
1031
1032         if (krt->HardKeys[i].shared_ptr)
1033           {
1034              fprintf(log_fl, "            == Shared Grab ==\n");
1035              _e_keyrouter_keygrab_status_print(log_fl, krt->HardKeys[i].shared_ptr);
1036           }
1037
1038         fprintf(log_fl, "\n");
1039      }
1040
1041    fprintf(log_fl, "    ----- End -----\n\n");
1042
1043    fclose(log_fl);
1044    log_fl = NULL;
1045 }
1046
1047 static Eina_Bool
1048 _event_filter(void *data, void *loop_data EINA_UNUSED, int type, void *event)
1049 {
1050    (void) data;
1051    (void) type;
1052    (void) event;
1053
1054    Ecore_Event_Key *ev;
1055
1056    /* Filter only for key down/up event */
1057    if (ECORE_EVENT_KEY_DOWN == type || ECORE_EVENT_KEY_UP == type)
1058      {
1059         ev = event;
1060
1061         if (ECORE_EVENT_KEY_DOWN == type)
1062           {
1063              if (event)
1064                {
1065                   TRACE_INPUT_BEGIN(event_filter:KEY_PRESS(%d), ev->keycode);
1066                   TRACE_INPUT_END();
1067                }
1068              else
1069                {
1070                   TRACE_INPUT_BEGIN(event_filter:KEY_PRESS);
1071                   TRACE_INPUT_END();
1072                }
1073
1074           }
1075         else if (ECORE_EVENT_KEY_UP == type)
1076           {
1077
1078              if (event)
1079                {
1080                   TRACE_INPUT_BEGIN(event_filter:KEY_RELEASE(%d), ev->keycode);
1081                   TRACE_INPUT_END();
1082                }
1083              else
1084                {
1085                   TRACE_INPUT_BEGIN(event_filter:KEY_RELEASE);
1086                   TRACE_INPUT_END();
1087                }
1088
1089           }
1090         return e_keyrouter_process_key_event(event, type);
1091      }
1092
1093    return EINA_TRUE;
1094 }
1095
1096 static void
1097 _e_keyrouter_cb_power_change(device_callback_e type, void* value, void* user_data)
1098 {
1099    if (type != DEVICE_CALLBACK_DISPLAY_STATE)
1100      {
1101         KLWRN("type is not DISPLAY_STATE");
1102         return;
1103      }
1104
1105    display_state_e state = (display_state_e)value;
1106    switch (state)
1107      {
1108         case DISPLAY_STATE_SCREEN_OFF:
1109            krt->isPictureOffEnabled = 1;
1110            break;
1111         case DISPLAY_STATE_NORMAL:
1112            krt->isPictureOffEnabled = 0;
1113            break;
1114         case DISPLAY_STATE_SCREEN_DIM:
1115            krt->isPictureOffEnabled = 0;
1116            break;
1117         default:
1118            krt->isPictureOffEnabled = 0;
1119            break;
1120      }
1121    KLDBG("Picture off flag changed to %d", krt->isPictureOffEnabled);
1122 }
1123
1124 static Eina_Bool _e_keyrouter_cb_idler(void *data)
1125 {
1126     device_add_callback(DEVICE_CALLBACK_DISPLAY_STATE,_e_keyrouter_cb_power_change,NULL);
1127     return ECORE_CALLBACK_CANCEL;
1128 }
1129
1130 static void *
1131 _e_keyrouter_keygrab_list_get(void)
1132 {
1133    EINA_SAFETY_ON_NULL_RETURN_VAL(krt, NULL);
1134    return krt->HardKeys;
1135 }
1136
1137 static int
1138 _e_keyrouter_max_keycode_get(void)
1139 {
1140    EINA_SAFETY_ON_NULL_RETURN_VAL(krt, 0);
1141    return krt->max_tizen_hwkeys;
1142 }
1143
1144 static E_Keyrouter_Config_Data *
1145 _e_keyrouter_init(E_Module *m)
1146 {
1147    E_Keyrouter_Config_Data *kconfig = NULL;
1148    krt = E_NEW(E_Keyrouter, 1);
1149    Eina_Bool res = EINA_FALSE;
1150    int ret;
1151
1152    TRACE_INPUT_BEGIN(_e_keyrouter_init);
1153
1154    _keyrouter_log_dom = eina_log_domain_register("e-keyrouter", EINA_COLOR_RED);
1155    if (_keyrouter_log_dom < 0)
1156      {
1157         KLERR("Failed to set eina_log_domain (%d)\n", _keyrouter_log_dom);
1158         return NULL;
1159      }
1160    eina_log_domain_level_set("e-keyrouter", EINA_LOG_LEVEL_INFO);
1161
1162    if (!krt)
1163      {
1164         KLERR("Failed to allocate memory for krt !");
1165         TRACE_INPUT_END();
1166         return NULL;
1167      }
1168
1169    if (!e_comp)
1170      {
1171         KLERR("Failed to initialize keyrouter module ! (e_comp == NULL)");
1172         goto err;
1173      }
1174
1175    kconfig = E_NEW(E_Keyrouter_Config_Data, 1);
1176    EINA_SAFETY_ON_NULL_GOTO(kconfig, err);
1177
1178    kconfig->module = m;
1179
1180    e_keyrouter_conf_init(kconfig);
1181    EINA_SAFETY_ON_NULL_GOTO(kconfig->conf, err);
1182    krt->conf = kconfig;
1183    krt->pictureoff_disabled = !!kconfig->conf->pictureoff_disabled;
1184
1185    /* Get keyname and keycode pair from Tizen Key Layout file */
1186    res = _e_keyrouter_query_tizen_key_table();
1187    EINA_SAFETY_ON_FALSE_GOTO(res, err);
1188
1189    /* Add filtering mechanism */
1190    krt->ef_handler = ecore_event_filter_add(NULL, _event_filter, NULL, NULL);
1191    //ecore handler add for power callback registration
1192    if (!krt->pictureoff_disabled)
1193      ecore_idle_enterer_add(_e_keyrouter_cb_idler, NULL);
1194    _e_keyrouter_init_handlers();
1195
1196    krt->global = wl_global_create(e_comp_wl->wl.disp, &tizen_keyrouter_interface, 1, krt, _e_keyrouter_cb_bind);
1197    if (!krt->global)
1198      {
1199         KLERR("Failed to create global !");
1200         goto err;
1201      }
1202
1203    e_keyrouter.keygrab_list_get = _e_keyrouter_keygrab_list_get;
1204    e_keyrouter.max_keycode_get = _e_keyrouter_max_keycode_get;
1205
1206 #ifdef ENABLE_CYNARA
1207    ret = cynara_initialize(&krt->p_cynara, NULL);
1208    if (EINA_UNLIKELY(CYNARA_API_SUCCESS != ret))
1209      {
1210         _e_keyrouter_util_cynara_log("cynara_initialize", ret);
1211         krt->p_cynara = NULL;
1212      }
1213 #endif
1214
1215    TRACE_INPUT_END();
1216    return kconfig;
1217
1218 err:
1219    if (kconfig)
1220      {
1221         e_keyrouter_conf_deinit(kconfig);
1222         E_FREE(kconfig);
1223      }
1224    _e_keyrouter_deinit_handlers();
1225    if (krt && krt->ef_handler) ecore_event_filter_del(krt->ef_handler);
1226    if (krt) E_FREE(krt);
1227
1228    TRACE_INPUT_END();
1229    return NULL;
1230 }
1231
1232 E_API void *
1233 e_modapi_init(E_Module *m)
1234 {
1235    return _e_keyrouter_init(m);
1236 }
1237
1238 E_API int
1239 e_modapi_shutdown(E_Module *m)
1240 {
1241    int i;
1242    Eina_List *l, *l_next;
1243    E_Keyrouter_Config_Data *kconfig = m->data;
1244    struct wl_resource *resource;
1245    struct wl_client *client;
1246    struct wl_listener *destroy_listener;
1247
1248    e_keyrouter_conf_deinit(kconfig);
1249    E_FREE(kconfig);
1250
1251    _e_keyrouter_deinit_handlers();
1252    if (krt->ef_handler) ecore_event_filter_del(krt->ef_handler);
1253
1254    for (i = 0; i < krt->max_tizen_hwkeys+1; i++)
1255      {
1256         if (krt->HardKeys[i].keyname)
1257           eina_stringshare_del(krt->HardKeys[i].keyname);
1258      }
1259    E_FREE(krt->HardKeys);
1260
1261    EINA_LIST_FOREACH_SAFE(krt->grab_client_list, l, l_next, client)
1262      {
1263         destroy_listener = wl_client_get_destroy_listener(client, _e_keyrouter_wl_client_cb_destroy);
1264         if (destroy_listener)
1265           {
1266              wl_list_remove(&destroy_listener->link);
1267              E_FREE(destroy_listener);
1268           }
1269         krt->grab_client_list = eina_list_remove(krt->grab_client_list, client);
1270      }
1271    EINA_LIST_FOREACH_SAFE(krt->grab_surface_list, l, l_next, resource)
1272      {
1273         destroy_listener = wl_resource_get_destroy_listener(resource, _e_keyrouter_wl_surface_cb_destroy);
1274         if (destroy_listener)
1275           {
1276              wl_list_remove(&destroy_listener->link);
1277              E_FREE(destroy_listener);
1278           }
1279         krt->grab_surface_list = eina_list_remove(krt->grab_surface_list, client);
1280      }
1281
1282    EINA_LIST_FREE(krt->registered_window_list, resource);
1283
1284    EINA_LIST_FREE(krt->resources, resource)
1285      wl_resource_destroy(resource);
1286
1287    wl_global_destroy(krt->global);
1288
1289 #ifdef ENABLE_CYNARA
1290    if (krt->p_cynara) cynara_finish(krt->p_cynara);
1291 #endif
1292
1293    E_FREE(krt);
1294    /* TODO: free allocated memory */
1295
1296    eina_log_domain_unregister(_keyrouter_log_dom);
1297
1298    return 1;
1299 }
1300
1301 E_API int
1302 e_modapi_save(E_Module *m)
1303 {
1304    /* Save something to be kept */
1305    E_Keyrouter_Config_Data *kconfig = m->data;
1306    e_config_domain_save("module.keyrouter",
1307                         kconfig->conf_edd,
1308                         kconfig->conf);
1309
1310    return 1;
1311 }
1312
1313 /* Function for getting keyname/keycode information from a key layout file */
1314 static Eina_Bool
1315 _e_keyrouter_query_tizen_key_table(void)
1316 {
1317    E_Keyrouter_Conf_Edd *kconf = krt->conf->conf;
1318    Eina_List *l;
1319    E_Keyrouter_Tizen_HWKey *data;
1320    int res;
1321    struct xkb_rule_names names={0,};
1322
1323    /* TODO: Make struct in HardKeys to pointer.
1324                   If a key is defined, allocate memory to pointer,
1325                   that makes to save unnecessary memory */
1326    krt->HardKeys = E_NEW(E_Keyrouter_Grabbed_Key, kconf->max_keycode + 1);
1327    EINA_SAFETY_ON_NULL_RETURN_VAL(krt->HardKeys, EINA_FALSE);
1328
1329    krt->numTizenHWKeys = kconf->num_keycode;
1330    krt->max_tizen_hwkeys = kconf->max_keycode;
1331
1332    EINA_LIST_FOREACH(kconf->KeyList, l, data)
1333      {
1334         if (!data) continue;
1335
1336         if (0 > data->keycode || krt->max_tizen_hwkeys < data->keycode)
1337           {
1338              KLWRN("Given keycode(%d) is invalid. It must be bigger than zero, smaller than the maximum value(%d) or equal to it.", data->keycode, kconf->max_keycode);
1339              continue;
1340           }
1341
1342         krt->HardKeys[data->keycode].keycode = data->keycode;
1343         krt->HardKeys[data->keycode].keyname = (char *)eina_stringshare_add(data->name);
1344         krt->HardKeys[data->keycode].no_privcheck = data->no_privcheck ? EINA_TRUE : EINA_FALSE;
1345         krt->HardKeys[data->keycode].repeat = data->repeat ? EINA_TRUE : EINA_FALSE;
1346
1347         if (e_comp_wl_input_keymap_cache_file_use_get() == EINA_FALSE)
1348           {
1349              if (krt->HardKeys[data->keycode].repeat == EINA_FALSE)
1350                {
1351                   res = xkb_keymap_key_set_repeats(e_comp_wl->xkb.keymap, data->keycode, 0);
1352                   if (!res)
1353                     {
1354                        KLWRN("Failed to set repeat key(%d), value(%d)", data->keycode, 0);
1355                     }
1356                }
1357           }
1358      }
1359
1360    if (e_comp_wl_input_keymap_cache_file_use_get() == EINA_FALSE)
1361      {
1362         KLINF("Server create a new cache file: %s", e_comp_wl_input_keymap_path_get(names));
1363         res = unlink(e_comp_wl_input_keymap_path_get(names));
1364
1365         e_comp_wl_input_keymap_set(NULL, NULL, NULL, NULL, NULL, xkb_context_ref(e_comp_wl->xkb.context), xkb_keymap_ref(e_comp_wl->xkb.keymap));
1366      }
1367    else
1368      KLINF("Currently cache file is exist. Do not change it.");
1369
1370    return EINA_TRUE;
1371 }
1372
1373 static int
1374 _e_keyrouter_wl_array_length(const struct wl_array *array)
1375 {
1376    int *data = NULL;
1377    int count = 0;
1378
1379    wl_array_for_each(data, array)
1380      {
1381         count++;
1382      }
1383
1384    return count;
1385 }
1386
1387 static void
1388 _e_keyrouter_deinit_handlers(void)
1389 {
1390    Ecore_Event_Handler *h = NULL;
1391
1392    if (!krt ||  !krt->handlers) return;
1393
1394    EINA_LIST_FREE(krt->handlers, h)
1395      ecore_event_handler_del(h);
1396
1397    e_info_server_hook_set("keyrouter", NULL, NULL);
1398    e_info_server_hook_set("keygrab", NULL, NULL);
1399 }
1400
1401 static void
1402 _e_keyrouter_init_handlers(void)
1403 {
1404    E_LIST_HANDLER_APPEND(krt->handlers, E_EVENT_CLIENT_STACK, _e_keyrouter_client_cb_stack, NULL);
1405    E_LIST_HANDLER_APPEND(krt->handlers, E_EVENT_CLIENT_REMOVE, _e_keyrouter_client_cb_remove, NULL);
1406
1407    e_info_server_hook_set("keyrouter", _e_keyrouter_info_print, NULL);
1408    e_info_server_hook_set("keygrab", _e_keyrouter_keygrab_print, NULL);
1409 }
1410
1411 static Eina_Bool
1412 _e_keyrouter_client_cb_stack(void *data, int type, void *event)
1413 {
1414    E_Event_Client *ev = event;
1415    E_Client *ec = ev->ec;
1416
1417    (void) data;
1418    (void) type;
1419    (void) event;
1420    (void) ev;
1421    (void) ec;
1422
1423    //KLDBG("ec: %p, visibile: %d, focused: %d, take_focus: %d, want_focus: %d, bordername: %s, input_only: %d",
1424    //        ec, ec->visible, ec->focused, ec->take_focus, ec->want_focus, ec->bordername, ec->input_only);
1425
1426    krt->isWindowStackChanged = EINA_TRUE;
1427    e_keyrouter_clear_registered_window();
1428
1429    return ECORE_CALLBACK_PASS_ON;
1430 }
1431
1432 static Eina_Bool
1433 _e_keyrouter_client_cb_remove(void *data, int type, void *event)
1434 {
1435    E_Event_Client *ev = event;
1436    E_Client *ec = ev->ec;
1437
1438    (void) data;
1439    (void) type;
1440    (void) ev;
1441    (void) ec;
1442
1443    /* FIXME: Remove this callback or do something others.
1444     *             It was moved to _e_keyrouter_wl_surface_cb_destroy() where it had here.
1445     */
1446
1447    return ECORE_CALLBACK_PASS_ON;
1448 }
1449
1450 static void
1451 _e_keyrouter_wl_client_cb_destroy(struct wl_listener *l, void *data)
1452 {
1453    struct wl_client *client = data;
1454
1455    KLDBG("Listener(%p) called: wl_client: %p is died", l, client);
1456    e_keyrouter_remove_client_from_list(NULL, client);
1457
1458    wl_list_remove(&l->link);
1459    E_FREE(l);
1460
1461    krt->grab_client_list = eina_list_remove(krt->grab_client_list, client);
1462 }
1463
1464 static void
1465 _e_keyrouter_wl_surface_cb_destroy(struct wl_listener *l, void *data)
1466 {
1467    struct wl_resource *surface = (struct wl_resource *)data;
1468
1469    KLDBG("Listener(%p) called: surface: %p is died", l, surface);
1470    e_keyrouter_remove_client_from_list(surface, NULL);
1471
1472    wl_list_remove(&l->link);
1473    E_FREE(l);
1474
1475    krt->grab_surface_list = eina_list_remove(krt->grab_surface_list, surface);
1476    krt->registered_none_key_window_list = eina_list_remove(krt->registered_none_key_window_list, surface);
1477    krt->invisible_set_window_list= eina_list_remove(krt->invisible_set_window_list, surface);
1478    krt->invisible_get_window_list= eina_list_remove(krt->invisible_get_window_list, surface);
1479    if (surface == krt->playback_daemon_surface)
1480      {
1481         krt->playback_daemon_surface = NULL;
1482         KLDBG("playback daemon surface destroyed!");
1483      }
1484 }
1485
1486 #ifdef ENABLE_CYNARA
1487 static void
1488 _e_keyrouter_util_cynara_log(const char *func_name, int err)
1489 {
1490 #define CYNARA_BUFSIZE 128
1491    char buf[CYNARA_BUFSIZE] = "\0";
1492    int ret;
1493
1494    ret = cynara_strerror(err, buf, CYNARA_BUFSIZE);
1495    if (ret != CYNARA_API_SUCCESS)
1496      {
1497         KLWRN("Failed to cynara_strerror: %d (error log about %s: %d)", ret, func_name, err);
1498         return;
1499      }
1500    KLWRN("%s is failed: %s", func_name, buf);
1501 }
1502
1503 static Eina_Bool
1504 _e_keyrouter_util_do_privilege_check(struct wl_client *client, uint32_t mode, uint32_t keycode)
1505 {
1506    int ret, retry_cnt=0, len=0;
1507    char *clientSmack=NULL, *client_session=NULL, uid2[16]={0, };
1508    Eina_Bool res = EINA_FALSE;
1509    Eina_List *l;
1510    struct wl_client *wc_data;
1511    static Eina_Bool retried = EINA_FALSE;
1512    pid_t pid = 0;
1513    uid_t uid = 0;
1514    gid_t gid = 0;
1515
1516    /* Top position grab is always allowed. This mode do not need privilege.*/
1517    if (mode == TIZEN_KEYROUTER_MODE_TOPMOST)
1518      return EINA_TRUE;
1519
1520    if (krt->HardKeys[keycode].no_privcheck == EINA_TRUE)
1521      return EINA_TRUE;
1522
1523    if (!client) return EINA_FALSE;
1524
1525    /* If initialize cynara is failed, allow keygrabs regardless of the previlege permition. */
1526    if (krt->p_cynara == NULL)
1527      {
1528         if (retried == EINA_FALSE)
1529           {
1530              retried = EINA_TRUE;
1531              for(retry_cnt = 0; retry_cnt < 5; retry_cnt++)
1532                {
1533                   KLDBG("Retry cynara initialize: %d", retry_cnt+1);
1534                   ret = cynara_initialize(&krt->p_cynara, NULL);
1535                   if (EINA_UNLIKELY(CYNARA_API_SUCCESS != ret))
1536                     {
1537                       _e_keyrouter_util_cynara_log("cynara_initialize", ret);
1538                        krt->p_cynara = NULL;
1539                     }
1540                   else
1541                     {
1542                        KLDBG("Success cynara initialize to try %d times", retry_cnt+1);
1543                        break;
1544                     }
1545                }
1546           }
1547         return EINA_TRUE;
1548      }
1549
1550    EINA_LIST_FOREACH(krt->grab_client_list, l, wc_data)
1551      {
1552         if (wc_data == client)
1553           {
1554              res = EINA_TRUE;
1555              goto finish;
1556           }
1557      }
1558
1559    wl_client_get_credentials(client, &pid, &uid, &gid);
1560
1561    len = smack_new_label_from_process((int)pid, &clientSmack);
1562    if (len <= 0) goto finish;
1563
1564    snprintf(uid2, 15, "%d", (int)uid);
1565    client_session = cynara_session_from_pid(pid);
1566
1567    ret = cynara_check(krt->p_cynara, clientSmack, client_session, uid2, "http://tizen.org/privilege/keygrab");
1568    if (CYNARA_API_ACCESS_ALLOWED == ret)
1569      {
1570         res = EINA_TRUE;
1571      }
1572    else
1573      {
1574         KLINF("Fail to check cynara,  error : %d (pid : %d)", ret, pid);
1575      }
1576 finish:
1577    if (client_session) E_FREE(client_session);
1578    if (clientSmack) E_FREE(clientSmack);
1579
1580    return res;
1581 }
1582 #endif