e_keyrouter_wl: remove the unused function
[platform/upstream/enlightenment.git] / src / bin / server / e_keyrouter_wl.c
1 #include "e_keyrouter_wl_intern.h"
2 #include "e_input_intern.h"
3 #include "e_input_backend_intern.h"
4 #include "e_comp_wl_input_intern.h"
5 #include "e_comp_wl_intern.h"
6 #include "e_client_intern.h"
7 #include "e_config_intern.h"
8 #include "e_comp_input_intern.h"
9 #include "e_input_thread_client_intern.h"
10 #include "e_security.h"
11 #include "e_keyrouter_intern.h"
12
13 #include <tizen-extension-server-protocol.h>
14
15 static E_Tizen_Keyrouter *g_tizen_keyrouter = NULL;
16
17 struct _E_Tizen_Keyrouter
18 {
19    struct wl_global *global;
20
21    Eina_List *resources;
22
23    Eina_List *grab_surface_list;
24    Eina_List *grab_client_list;
25 };
26
27 EINTERN void
28 e_keyrouter_wl_event_surface_send(struct wl_resource *surface, int key, int mode)
29 {
30    Eina_List *l;
31    struct wl_resource *res_data;
32    struct wl_client *wc;
33
34    EINA_SAFETY_ON_NULL_RETURN(surface);
35
36    wc = wl_resource_get_client(surface);
37    EINA_SAFETY_ON_NULL_RETURN(wc);
38
39    EINA_LIST_FOREACH(g_tizen_keyrouter->resources, l, res_data)
40      {
41         if (wl_resource_get_client(res_data) != wc) continue;
42         if (wl_resource_get_version(res_data) < 2) continue;
43
44         if (e_config->key_input_ttrace_enable)
45           {
46              TRACE_INPUT_BEGIN(tizen_keyrouter_send_event_surface);
47              ELOGF("INPUT", "tizen_keyrouter_send_event_surface|B|", NULL);
48           }
49
50         tizen_keyrouter_send_event_surface(res_data, surface, key, mode);
51
52         if (e_config->key_input_ttrace_enable)
53           {
54              TRACE_INPUT_END();
55              ELOGF("INPUT", "tizen_keyrouter_send_event_surface|E|", NULL);
56           }
57      }
58 }
59
60 static void
61 _e_keyrouter_wl_key_send(Ecore_Event_Key *ev, E_Device *dev, enum wl_keyboard_key_state state, Eina_List *key_list, Eina_Bool focused, struct wl_client *client, struct wl_resource *surface)
62 {
63    struct wl_resource *res;
64    Eina_List *l;
65    uint32_t serial, keycode;
66    struct wl_client *wc;
67    E_Comp_Config *comp_conf = NULL;
68
69    keycode = (ev->keycode - 8);
70
71    serial = wl_display_next_serial(e_comp_wl->wl.disp);
72
73    comp_conf = e_comp_config_get();
74
75    if (surface && !focused)
76      {
77         e_comp_wl_connection_lock();
78         e_keyrouter_wl_event_surface_send(surface, ev->keycode, TIZEN_KEYROUTER_MODE_NONE);
79         e_comp_wl_connection_unlock();
80      }
81
82    if (e_config->key_input_ttrace_enable)
83      {
84         TRACE_INPUT_BEGIN(wl_keyboard_send_key:%s:%s, (state ? "PRESS" : "RELEASE"), ev->keyname);
85         ELOGF("INPUT", "wl_keyboard_send_key:%s:%s|B|", NULL, (state ? "PRESS" : "RELEASE"), ev->keyname);
86      }
87
88    EINA_LIST_FOREACH(key_list, l, res)
89      {
90         wc = wl_resource_get_client(res);
91         if (!focused && wc != client) continue;
92         TRACE_INPUT_BEGIN(_e_comp_wl_key_send);
93         if (!e_input_thread_mode_get())
94           {
95              e_comp_wl_send_event_device(client, ev->timestamp, ev->dev, serial);
96           }
97         else
98           {
99              if (dev)
100                e_comp_wl_send_event_e_device(client, ev->timestamp, dev, serial);
101           }
102
103         if (comp_conf && comp_conf->input_log_enable)
104           INF("[Server] Routed Key %s (time: %d)\n", (state ? "Down" : "Up"), ev->timestamp);
105
106         wl_keyboard_send_key(res, serial, ev->timestamp,
107                              keycode, state);
108         TRACE_INPUT_END();
109      }
110
111    if (e_config->key_input_ttrace_enable)
112      {
113         TRACE_INPUT_END();
114         ELOGF("INPUT", "wl_keyboard_send_key|E|", NULL);
115      }
116 }
117
118 Eina_Bool
119 e_keyrouter_wl_key_send(Ecore_Event_Key *ev, E_Device *dev, Eina_Bool pressed, struct wl_client *client, struct wl_resource *surface, Eina_Bool focused)
120 {
121    E_Client *ec = NULL;
122    struct wl_client *wc = NULL;
123    uint32_t keycode;
124    enum wl_keyboard_key_state state;
125
126    if (ev->window != e_comp->ee_win)
127      {
128         return EINA_FALSE;
129      }
130
131    keycode = (ev->keycode - 8);
132    if (!(e_comp_wl = e_comp->wl_comp_data))
133      {
134         return EINA_FALSE;
135      }
136
137 #ifndef E_RELEASE_BUILD
138    if ((ev->modifiers & ECORE_EVENT_MODIFIER_CTRL) &&
139        ((ev->modifiers & ECORE_EVENT_MODIFIER_ALT) ||
140        (ev->modifiers & ECORE_EVENT_MODIFIER_ALTGR)) &&
141        eina_streq(ev->key, "BackSpace"))
142      {
143         exit(0);
144      }
145 #endif
146
147    if (pressed) state = WL_KEYBOARD_KEY_STATE_PRESSED;
148    else state = WL_KEYBOARD_KEY_STATE_RELEASED;
149
150    if (!focused)
151      {
152         _e_keyrouter_wl_key_send(ev, dev, state, e_comp_input_key->kbd.resources, EINA_FALSE, client, surface);
153         return EINA_FALSE;
154      }
155
156    if ((!e_client_action_get()) && (!e_comp->input_key_grabs))
157      {
158         ec = e_client_focused_get();
159
160         if (ec && ec->comp_data)
161           {
162              struct wl_resource *surface = e_comp_wl_client_surface_get(ec);
163              if (surface)
164                {
165                   if (e_comp_input_key->kbd.focused)
166                     {
167                        wc = wl_resource_get_client(surface);
168                        _e_keyrouter_wl_key_send(ev, dev, state, e_comp_input_key->kbd.focused, EINA_TRUE, wc, surface);
169                     }
170                }
171
172              /* update modifier state */
173              e_comp_wl_input_keyboard_state_update(keycode, pressed);
174           }
175      }
176    return !!ec;
177 }
178
179 EINTERN void
180 e_keyrouter_surface_keycancel_send(struct wl_resource *surface, unsigned int key)
181 {
182    Eina_List *l;
183    Eina_List *press_ptr_list;
184    E_Keyrouter_Key_List_NodePtr data;
185    struct wl_resource *resource;
186    struct wl_client *client;
187
188    EINA_SAFETY_ON_NULL_RETURN(surface);
189
190    client = wl_resource_get_client(surface);
191
192    g_rec_mutex_lock(&krt->grab_key_mutex);
193
194    press_ptr_list = krt->HardKeys[key].press_ptr;
195    EINA_LIST_FOREACH(press_ptr_list, l, data)
196      {
197         if (surface != data->surface) continue;
198
199         EINA_LIST_FOREACH(g_tizen_keyrouter->resources, l, resource)
200           {
201              if (wl_resource_get_client(resource) != client) continue;
202
203              tizen_keyrouter_send_key_cancel(resource, key-8);
204           }
205      }
206
207    g_rec_mutex_unlock(&krt->grab_key_mutex);
208 }
209
210 EINTERN void
211 e_keyrouter_client_keycancel_send(struct wl_client *client, unsigned int key)
212 {
213    Eina_List *l;
214    E_Keyrouter_Key_List_NodePtr data;
215    Eina_List *press_ptr_list;
216    struct wl_resource *resource;
217
218    EINA_SAFETY_ON_NULL_RETURN(client);
219
220    g_rec_mutex_lock(&krt->grab_key_mutex);
221
222    press_ptr_list = krt->HardKeys[key].press_ptr;
223    EINA_LIST_FOREACH(press_ptr_list, l, data)
224      {
225         if (client != data->wc) continue;
226
227         EINA_LIST_FOREACH(g_tizen_keyrouter->resources, l, resource)
228           {
229              if (wl_resource_get_client(resource) != client) continue;
230
231              tizen_keyrouter_send_key_cancel(resource, key-8);
232           }
233      }
234
235    g_rec_mutex_unlock(&krt->grab_key_mutex);
236 }
237
238 static int
239 _e_keyrouter_wl_array_length(const struct wl_array *array)
240 {
241    int *data = NULL;
242    int count = 0;
243
244    wl_array_for_each(data, array)
245      {
246         count++;
247      }
248
249    return count;
250 }
251
252 static int
253 _e_keyrouter_keygrab_set_available_check(struct wl_client *client, struct wl_resource *surface, int key, int mode)
254 {
255    if (!((mode == TIZEN_KEYROUTER_MODE_EXCLUSIVE) ||
256          (mode == TIZEN_KEYROUTER_MODE_OVERRIDABLE_EXCLUSIVE) ||
257          (mode == TIZEN_KEYROUTER_MODE_TOPMOST) ||
258          (mode == TIZEN_KEYROUTER_MODE_SHARED)))
259      return TIZEN_KEYROUTER_ERROR_INVALID_MODE;
260
261    /* Regarding topmost mode, a client must request to grab a key with a valid surface. */
262    if (!surface && mode == TIZEN_KEYROUTER_MODE_TOPMOST)
263      {
264         KLWRN("Invalid surface for %d grab mode ! (key=%d)", mode, key);
265         return TIZEN_KEYROUTER_ERROR_INVALID_SURFACE;
266      }
267
268    return TIZEN_KEYROUTER_ERROR_NONE;
269 }
270
271 static int
272 _e_keyrouter_keygrab_privilege_available_check(struct wl_client *client, int key, int mode)
273 {
274 #ifdef HAVE_CYNARA
275    if (!e_keyrouter_wl_util_do_privilege_check(client, mode, key))
276      {
277         KLINF("No permission for %d grab mode ! (key=%d)", mode, key);
278         return TIZEN_KEYROUTER_ERROR_NO_PERMISSION;
279      }
280 #endif
281
282    return TIZEN_KEYROUTER_ERROR_NONE;
283 }
284
285 static int
286 _e_keyrouter_keygrab_key_available_check(int key)
287 {
288    /* Check the given key range */
289    if (krt->max_tizen_hwkeys < key)
290      {
291         KLWRN("Invalid range of key ! (keycode:%d) maximum value(%d)", key, krt->max_tizen_hwkeys);
292         return TIZEN_KEYROUTER_ERROR_INVALID_KEY;
293      }
294
295    /* Check whether the key can be grabbed or not !
296     * Only key listed in Tizen key layout file can be grabbed. */
297    if (0 == krt->HardKeys[key].keycode)
298      {
299         KLWRN("Invalid key ! Disabled to set keygrab ! (keycode:%d)", key);
300         return TIZEN_KEYROUTER_ERROR_INVALID_KEY;
301      }
302
303    return TIZEN_KEYROUTER_ERROR_NONE;
304 }
305
306 static void
307 _e_keyrouter_input_thread_keygrab_set(void *data)
308 {
309    E_Input_Thread_Request_Keygrab_Data *keygrab_data = data;
310    int res = TIZEN_KEYROUTER_ERROR_NONE;
311
312    res = _e_keyrouter_keygrab_set_available_check(keygrab_data->client,
313             keygrab_data->surface, keygrab_data->key, keygrab_data->mode);
314    if (res != TIZEN_KEYROUTER_ERROR_NONE)
315       goto failed;
316
317    res = _e_keyrouter_keygrab_privilege_available_check(keygrab_data->client,
318             keygrab_data->key, keygrab_data->mode);
319    if (res != TIZEN_KEYROUTER_ERROR_NONE)
320       goto failed;
321
322    res = _e_keyrouter_keygrab_key_available_check(keygrab_data->key);
323    if (res != TIZEN_KEYROUTER_ERROR_NONE)
324       goto failed;
325
326    res = e_keyrouter_keygrab_set(keygrab_data->client, keygrab_data->surface,
327                keygrab_data->key, keygrab_data->mode);
328    if (res != TIZEN_KEYROUTER_ERROR_NONE)
329       goto failed;
330
331    KLINF("Success to %d key %s grab request (wl_client: %p, wl_surface: %p, pid: %d)",
332          keygrab_data->key, e_keyrouter_mode_to_string(keygrab_data->mode),
333          keygrab_data->client, keygrab_data->surface,
334          e_keyrouter_util_get_pid(keygrab_data->client, keygrab_data->surface));
335
336    tizen_keyrouter_send_keygrab_notify(keygrab_data->resource,
337          keygrab_data->surface, keygrab_data->key, keygrab_data->mode, res);
338
339    return;
340
341 failed:
342    KLINF("Failed to %d key %s grab request (wl_client: %p, wl_surface: %p, pid: %d): res: %d",
343          keygrab_data->key, e_keyrouter_mode_to_string(keygrab_data->mode),
344          keygrab_data->client, keygrab_data->surface,
345          e_keyrouter_util_get_pid(keygrab_data->client, keygrab_data->surface),
346          res);
347
348    tizen_keyrouter_send_keygrab_notify(keygrab_data->resource,
349          keygrab_data->surface, keygrab_data->key, keygrab_data->mode, res);
350 }
351
352 /* tizen_keyrouter_set_keygrab request handler */
353 static void
354 _e_keyrouter_cb_keygrab_set(struct wl_client *client, struct wl_resource *resource, struct wl_resource *surface, uint32_t key, uint32_t mode)
355 {
356    TRACE_INPUT_BEGIN(_e_keyrouter_cb_keygrab_set);
357
358    E_Input_Thread_Request_Keygrab_Data keygrab_data;
359
360    keygrab_data.resource = resource;
361    keygrab_data.surface = surface;
362    keygrab_data.client = client;
363    keygrab_data.key = key;
364    keygrab_data.mode = mode;
365
366    INF("client: %p, surface: %p, key: %d, mode: %d\n", keygrab_data.client, keygrab_data.surface, keygrab_data.key, keygrab_data.mode);
367    _e_keyrouter_input_thread_keygrab_set(&keygrab_data);
368
369    TRACE_INPUT_END();
370 }
371
372 static void
373 _e_keyrouter_input_thread_keygrab_unset(void *data)
374 {
375    E_Input_Thread_Request_Keygrab_Data *keygrab_data = data;
376    int res = TIZEN_KEYROUTER_ERROR_NONE;
377
378    res = _e_keyrouter_keygrab_key_available_check(keygrab_data->key);
379    if (res != TIZEN_KEYROUTER_ERROR_NONE)
380       goto failed;
381
382    res = _e_keyrouter_keygrab_privilege_available_check(keygrab_data->client,
383          keygrab_data->key, TIZEN_KEYROUTER_MODE_NONE);
384    if (res != TIZEN_KEYROUTER_ERROR_NONE)
385       goto cancel;
386
387    if (keygrab_data->surface)
388      e_keyrouter_surface_keygrab_unset(keygrab_data->surface, keygrab_data->key);
389    else
390      e_keyrouter_client_keygrab_unset(keygrab_data->client, keygrab_data->key);
391
392    KLDBG("Success to %d key ungrab request (wl_client: %p, wl_surface: %p, pid: %d)",
393          keygrab_data->key, keygrab_data->client, keygrab_data->surface,
394          e_keyrouter_util_get_pid(keygrab_data->client, keygrab_data->surface));
395
396    tizen_keyrouter_send_keygrab_notify(keygrab_data->resource,
397       keygrab_data->surface, keygrab_data->key, TIZEN_KEYROUTER_MODE_NONE, res);
398
399    return;
400
401 cancel:
402    if (keygrab_data->surface)
403      e_keyrouter_surface_keycancel_send(keygrab_data->surface, keygrab_data->key);
404    else
405      e_keyrouter_client_keycancel_send(keygrab_data->client, keygrab_data->key);
406
407 failed:
408    KLINF("Failed to %d key ungrab request (wl_client: %p, wl_surface: %p, pid: %d): res: %d",
409          keygrab_data->key, keygrab_data->client, keygrab_data->surface,
410          e_keyrouter_util_get_pid(keygrab_data->client, keygrab_data->surface),
411          res);
412
413    tizen_keyrouter_send_keygrab_notify(keygrab_data->resource,
414       keygrab_data->surface, keygrab_data->key, TIZEN_KEYROUTER_MODE_NONE, res);
415 }
416
417 /* tizen_keyrouter unset_keygrab request handler */
418 static void
419 _e_keyrouter_cb_keygrab_unset(struct wl_client *client, struct wl_resource *resource, struct wl_resource *surface, uint32_t key)
420 {
421    TRACE_INPUT_BEGIN(_e_keyrouter_cb_keygrab_unset);
422
423    E_Input_Thread_Request_Keygrab_Data keygrab_data;
424
425    keygrab_data.resource = resource;
426    keygrab_data.surface = surface;
427    keygrab_data.client = client;
428    keygrab_data.key = key;
429    keygrab_data.mode = TIZEN_KEYROUTER_MODE_NONE; /* UNUSED */
430
431    INF("client: %p, surface: %p, key: %d\n", keygrab_data.client,
432        keygrab_data.surface, keygrab_data.key);
433
434    _e_keyrouter_input_thread_keygrab_unset(&keygrab_data);
435
436    TRACE_INPUT_END();
437 }
438
439 /* tizen_keyrouter get_keygrab_status request handler */
440 static void
441 _e_keyrouter_cb_get_keygrab_status(struct wl_client *client, struct wl_resource *resource, struct wl_resource *surface, uint32_t key)
442 {
443    (void) client;
444    (void) resource;
445    (void) surface;
446    (void) key;
447    int mode = TIZEN_KEYROUTER_MODE_NONE;
448
449    TRACE_INPUT_BEGIN(_e_keyrouter_cb_get_keygrab_status);
450    mode = e_keyrouter_find_key_in_list(surface, client, key);
451
452    TRACE_INPUT_END();
453    tizen_keyrouter_send_keygrab_notify(resource, surface, key, mode, TIZEN_KEYROUTER_ERROR_NONE);
454 }
455
456 static void
457 _e_keyrouter_cb_keygrab_set_list(struct wl_client *client, struct wl_resource *resource, struct wl_resource *surface, struct wl_array *grab_list)
458 {
459    E_Keyrouter_Grab_Request *grab_request = NULL;
460    int res = TIZEN_KEYROUTER_ERROR_NONE;
461    int array_len = 0;
462
463    TRACE_INPUT_BEGIN(_e_keyrouter_cb_keygrab_set_list);
464
465    array_len = _e_keyrouter_wl_array_length(grab_list);
466
467    if (0 != (array_len % 3))
468      {
469         /* FIX ME: Which way is effectively to notify invalid pair to client */
470         KLWRN("Invalid keycode and grab mode pair. Check arguments in a list");
471         TRACE_INPUT_END();
472         tizen_keyrouter_send_keygrab_notify_list(resource, surface, NULL);
473         return;
474      }
475
476    wl_array_for_each(grab_request, grab_list)
477      {
478         res = _e_keyrouter_keygrab_set_available_check(client, surface,
479                   grab_request->key, grab_request->mode);
480         if (res != TIZEN_KEYROUTER_ERROR_NONE)
481           goto done;
482
483         res = _e_keyrouter_keygrab_privilege_available_check(client,
484                   grab_request->key, grab_request->mode);
485         if (res != TIZEN_KEYROUTER_ERROR_NONE)
486           goto done;
487
488         res = _e_keyrouter_keygrab_key_available_check(grab_request->key);
489         if (res != TIZEN_KEYROUTER_ERROR_NONE)
490           goto done;
491
492         res = e_keyrouter_keygrab_set(client, surface,
493                      grab_request->key, grab_request->mode);
494
495 done:
496         grab_request->err = res;
497
498         if (res == TIZEN_KEYROUTER_ERROR_NONE)
499           KLDBG("Success to %d key %s grab using list(wl_client: %p, wl_surface: %p, pid: %d)",
500                 grab_request->key, e_keyrouter_mode_to_string(grab_request->mode),
501                 client, surface, e_keyrouter_util_get_pid(client, surface));
502         else
503           KLINF("Failed to %d key %s grab using list(wl_client: %p, wl_surface: %p, pid: %d): res: %d",
504                 grab_request->key, e_keyrouter_mode_to_string(grab_request->mode),
505                 client, surface, e_keyrouter_util_get_pid(client, surface),
506                 grab_request->err);
507      }
508
509    TRACE_INPUT_END();
510
511    tizen_keyrouter_send_keygrab_notify_list(resource, surface, grab_list);
512 }
513
514 static void
515 _e_keyrouter_cb_keygrab_unset_list(struct wl_client *client, struct wl_resource *resource, struct wl_resource *surface, struct wl_array *ungrab_list)
516 {
517    E_Keyrouter_Ungrab_Request *ungrab_request = NULL;
518    int res = TIZEN_KEYROUTER_ERROR_NONE;
519    int array_len = 0;
520
521    TRACE_INPUT_BEGIN(_e_keyrouter_cb_keygrab_unset_list);
522
523    array_len = _e_keyrouter_wl_array_length(ungrab_list);
524
525    if (0 != (array_len % 2))
526      {
527         /* FIX ME: Which way is effectively to notify invalid pair to client */
528         KLWRN("Invalid keycode and error pair. Check arguments in a list");
529         TRACE_INPUT_END();
530         tizen_keyrouter_send_keygrab_notify_list(resource, surface, ungrab_list);
531         return;
532      }
533
534    wl_array_for_each(ungrab_request, ungrab_list)
535      {
536         res = _e_keyrouter_keygrab_key_available_check(ungrab_request->key);
537         if (res != TIZEN_KEYROUTER_ERROR_NONE)
538           goto done;
539
540         res = _e_keyrouter_keygrab_privilege_available_check(client,
541                   ungrab_request->key, TIZEN_KEYROUTER_MODE_NONE);
542         if (res != TIZEN_KEYROUTER_ERROR_NONE)
543           goto cancel;
544
545         if (surface)
546           e_keyrouter_client_keygrab_unset(client, ungrab_request->key);
547         else
548           e_keyrouter_surface_keygrab_unset(surface, ungrab_request->key);
549
550 cancel:
551         if (surface)
552           e_keyrouter_surface_keycancel_send(surface, ungrab_request->key);
553         else
554           e_keyrouter_client_keycancel_send(client, ungrab_request->key);
555
556 done:
557         ungrab_request->err = res;
558
559         if (res == TIZEN_KEYROUTER_ERROR_NONE)
560           KLDBG("Success to ungrab using list: %d key (wl_client: %p, wl_surface: %p, pid: %d)",
561                 ungrab_request->key, client, surface,
562                 e_keyrouter_util_get_pid(client, surface));
563         else
564           KLINF("Failed to ungrab using list: %d key (wl_client: %p, wl_surface: %p, pid: %d): res: %d",
565                 ungrab_request->key, client, surface,
566                 e_keyrouter_util_get_pid(client, surface), ungrab_request->err);
567      }
568
569    TRACE_INPUT_END();
570
571    tizen_keyrouter_send_keygrab_notify_list(resource, surface, ungrab_list);
572 }
573
574 static void
575 _e_keyrouter_cb_keygrab_get_list(struct wl_client *client, struct wl_resource *resource, struct wl_resource *surface)
576 {
577    (void) client;
578
579    tizen_keyrouter_send_getgrab_notify_list(resource, surface, NULL);
580 }
581
582 static void
583 _e_keyrouter_cb_set_register_none_key(struct wl_client *client, struct wl_resource *resource, struct wl_resource *surface, uint32_t data)
584 {
585    (void) client;
586    (void) data;
587
588    tizen_keyrouter_send_set_register_none_key_notify(resource, NULL, 0);
589 }
590
591 static void
592 _e_keyrouter_cb_get_keyregister_status(struct wl_client *client, struct wl_resource *resource, uint32_t key)
593 {
594    (void) client;
595    (void) key;
596
597    tizen_keyrouter_send_keyregister_notify(resource, (int)EINA_FALSE);
598 }
599
600 static void
601 _e_keyrouter_cb_set_input_config(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, struct wl_resource *surface EINA_UNUSED, uint32_t config_mode EINA_UNUSED, uint32_t value EINA_UNUSED)
602 {
603    tizen_keyrouter_send_set_input_config_notify(resource, 0);
604 }
605
606 static void
607 _e_keyrouter_cb_destroy(struct wl_client *client, struct wl_resource *resource)
608 {
609    wl_resource_destroy(resource);
610 }
611
612 static const struct tizen_keyrouter_interface _e_keyrouter_implementation = {
613    _e_keyrouter_cb_keygrab_set,
614    _e_keyrouter_cb_keygrab_unset,
615    _e_keyrouter_cb_get_keygrab_status,
616    _e_keyrouter_cb_keygrab_set_list,
617    _e_keyrouter_cb_keygrab_unset_list,
618    _e_keyrouter_cb_keygrab_get_list,
619    _e_keyrouter_cb_set_register_none_key,
620    _e_keyrouter_cb_get_keyregister_status,
621    _e_keyrouter_cb_set_input_config,
622    _e_keyrouter_cb_destroy,
623 };
624
625 static void
626 _e_keyrouter_cb_unbind(struct wl_resource *resource)
627 {
628    g_tizen_keyrouter->resources = eina_list_remove(g_tizen_keyrouter->resources, resource);
629 }
630
631 /* tizen_keyrouter global object bind function */
632 static void
633 _e_keyrouter_cb_bind(struct wl_client *client, void *data, uint32_t version, uint32_t id)
634 {
635    struct wl_resource *resource;
636
637    resource = wl_resource_create(client, &tizen_keyrouter_interface, version, id);
638
639    KLDBG("wl_resource_create(...,&tizen_keyrouter_interface,...)");
640
641    if (!resource)
642      {
643         KLERR("Failed to create resource ! (version :%d, id:%d)", version, id);
644         wl_client_post_no_memory(client);
645          return;
646      }
647
648    g_tizen_keyrouter->resources = eina_list_append(g_tizen_keyrouter->resources, resource);
649
650    wl_resource_set_implementation(resource, &_e_keyrouter_implementation, NULL, _e_keyrouter_cb_unbind);
651 }
652
653 static void
654 _e_keyrouter_wl_client_cb_destroy(struct wl_listener *l, void *data)
655 {
656    struct wl_client *client = data;
657
658    KLDBG("Listener(%p) called: wl_client: %p is died", l, client);
659    e_keyrouter_remove_client_from_list(NULL, client);
660
661    wl_list_remove(&l->link);
662    E_FREE(l);
663
664    g_tizen_keyrouter->grab_client_list = eina_list_remove(g_tizen_keyrouter->grab_client_list, client);
665 }
666
667 static void
668 _e_keyrouter_wl_surface_cb_destroy(struct wl_listener *l, void *data)
669 {
670    struct wl_resource *surface = (struct wl_resource *)data;
671
672    KLDBG("Listener(%p) called: surface: %p is died", l, surface);
673    e_keyrouter_remove_client_from_list(surface, NULL);
674
675    wl_list_remove(&l->link);
676    E_FREE(l);
677
678    g_tizen_keyrouter->grab_surface_list = eina_list_remove(g_tizen_keyrouter->grab_surface_list, surface);
679 }
680
681 EINTERN int
682 e_keyrouter_wl_add_client_destroy_listener(struct wl_client *client)
683 {
684    struct wl_listener *destroy_listener = NULL;
685    Eina_List *l;
686    struct wl_client *wc_data;
687
688    if (!client) return TIZEN_KEYROUTER_ERROR_NONE;
689
690    EINA_LIST_FOREACH(g_tizen_keyrouter->grab_client_list, l, wc_data)
691      {
692         if (wc_data)
693           {
694              if (wc_data == client)
695                {
696                   return TIZEN_KEYROUTER_ERROR_NONE;
697                }
698           }
699      }
700
701    destroy_listener = E_NEW(struct wl_listener, 1);
702
703    if (!destroy_listener)
704      {
705         KLERR("Failed to allocate memory for wl_client destroy listener !");
706         return TIZEN_KEYROUTER_ERROR_NO_SYSTEM_RESOURCES;
707      }
708
709    destroy_listener->notify = _e_keyrouter_wl_client_cb_destroy;
710    wl_client_add_destroy_listener(client, destroy_listener);
711    g_tizen_keyrouter->grab_client_list = eina_list_append(g_tizen_keyrouter->grab_client_list, client);
712
713    return TIZEN_KEYROUTER_ERROR_NONE;
714 }
715
716 /* Function for registering wl_surface destroy listener */
717 EINTERN int
718 e_keyrouter_wl_add_surface_destroy_listener(struct wl_resource *surface)
719 {
720    struct wl_listener *destroy_listener = NULL;
721    Eina_List *l;
722    struct wl_resource *surface_data;
723
724    if (!surface) return TIZEN_KEYROUTER_ERROR_NONE;
725
726    EINA_LIST_FOREACH(g_tizen_keyrouter->grab_surface_list, l, surface_data)
727      {
728         if (surface_data)
729           {
730              if (surface_data == surface)
731                {
732                   return TIZEN_KEYROUTER_ERROR_NONE;
733                }
734           }
735      }
736
737    destroy_listener = E_NEW(struct wl_listener, 1);
738
739    if (!destroy_listener)
740      {
741         KLERR("Failed to allocate memory for wl_surface destroy listener !");
742         return TIZEN_KEYROUTER_ERROR_NO_SYSTEM_RESOURCES;
743      }
744
745    destroy_listener->notify = _e_keyrouter_wl_surface_cb_destroy;
746    wl_resource_add_destroy_listener(surface, destroy_listener);
747    g_tizen_keyrouter->grab_surface_list = eina_list_append(g_tizen_keyrouter->grab_surface_list, surface);
748
749    return TIZEN_KEYROUTER_ERROR_NONE;
750 }
751
752 #ifdef HAVE_CYNARA
753 EINTERN Eina_Bool
754 e_keyrouter_wl_util_do_privilege_check(struct wl_client *client, uint32_t mode, uint32_t keycode)
755 {
756    Eina_Bool res = EINA_FALSE;
757    Eina_List *l;
758    struct wl_client *wc_data;
759    pid_t pid = 0;
760    uid_t uid = 0;
761    gid_t gid = 0;
762
763    /* Top position grab is always allowed. This mode do not need privilege.*/
764    if (mode == TIZEN_KEYROUTER_MODE_TOPMOST)
765      return EINA_TRUE;
766
767    if (krt->HardKeys[keycode].no_privcheck == EINA_TRUE &&
768        mode == TIZEN_KEYROUTER_MODE_OVERRIDABLE_EXCLUSIVE)
769      return EINA_TRUE;
770
771    if (!client) return EINA_FALSE;
772
773    EINA_LIST_FOREACH(g_tizen_keyrouter->grab_client_list, l, wc_data)
774      {
775         if (wc_data == client)
776           {
777              res = EINA_TRUE;
778              goto finish;
779           }
780      }
781
782    wl_client_get_credentials(client, &pid, &uid, &gid);
783    res = e_security_privilege_check(pid, uid, "http://tizen.org/privilege/keygrab");
784    if (!res)
785      {
786         KLINF("Fail to check privilege,  (pid : %d)", pid);
787      }
788
789 finish:
790    return res;
791 }
792 #endif
793
794 EINTERN E_Tizen_Keyrouter *
795 e_keyrouter_wl_init(struct wl_display *display)
796 {
797    EINA_SAFETY_ON_NULL_RETURN_VAL(display, NULL);
798
799    if (g_tizen_keyrouter) return g_tizen_keyrouter;
800
801    g_tizen_keyrouter = E_NEW(E_Tizen_Keyrouter, 1);
802    EINA_SAFETY_ON_NULL_RETURN_VAL(g_tizen_keyrouter, NULL);
803
804
805    g_tizen_keyrouter->global = wl_global_create(display,
806                   &tizen_keyrouter_interface, 2, NULL, _e_keyrouter_cb_bind);
807    EINA_SAFETY_ON_NULL_RETURN_VAL(g_tizen_keyrouter->global, NULL);
808
809    return g_tizen_keyrouter;
810 }
811
812 EINTERN void
813 e_keyrouter_wl_shutdown(void)
814 {
815    Eina_List *l, *l_next;
816    struct wl_resource *resource;
817    struct wl_client *client;
818    struct wl_listener *destroy_listener;
819
820    if (!g_tizen_keyrouter) return;
821
822    EINA_LIST_FOREACH_SAFE(g_tizen_keyrouter->grab_client_list, l, l_next, client)
823      {
824         destroy_listener = wl_client_get_destroy_listener(client, _e_keyrouter_wl_client_cb_destroy);
825         if (destroy_listener)
826           {
827              wl_list_remove(&destroy_listener->link);
828              E_FREE(destroy_listener);
829           }
830         g_tizen_keyrouter->grab_client_list = eina_list_remove(g_tizen_keyrouter->grab_client_list, client);
831      }
832    EINA_LIST_FOREACH_SAFE(g_tizen_keyrouter->grab_surface_list, l, l_next, resource)
833      {
834         destroy_listener = wl_resource_get_destroy_listener(resource, _e_keyrouter_wl_surface_cb_destroy);
835         if (destroy_listener)
836           {
837              wl_list_remove(&destroy_listener->link);
838              E_FREE(destroy_listener);
839           }
840         g_tizen_keyrouter->grab_surface_list = eina_list_remove(g_tizen_keyrouter->grab_surface_list, client);
841      }
842
843    EINA_LIST_FREE(g_tizen_keyrouter->resources, resource)
844      wl_resource_destroy(resource);
845
846    if (g_tizen_keyrouter->global)
847
848    wl_global_destroy(g_tizen_keyrouter->global);
849
850    E_FREE(g_tizen_keyrouter);
851 }