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