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