583098772630a43faaa9b4184849695152ad785c
[platform/upstream/enlightenment.git] / src / bin / e_keyrouter_list.c
1 #include "e_keyrouter_private.h"
2
3 static int _e_keyrouter_find_duplicated_client(struct wl_resource *surface, struct wl_client *wc, uint32_t key, uint32_t mode);
4 static Eina_Bool _e_keyrouter_find_key_in_list(struct wl_resource *surface, struct wl_client *wc, int key, int mode);
5 static Eina_List **_e_keyrouter_get_list(int mode, int key);
6
7 /* add a new key grab info to the list */
8 int
9 e_keyrouter_set_keygrab_in_list(struct wl_resource *surface, struct wl_client *client, uint32_t key, uint32_t mode)
10 {
11    int res = TIZEN_KEYROUTER_ERROR_NONE;
12    Eina_List *keylist_ptr = NULL, *l = NULL;
13    E_Keyrouter_Key_List_NodePtr kdata = NULL;
14    int pid;
15
16    EINA_SAFETY_ON_FALSE_RETURN_VAL
17      (((mode == TIZEN_KEYROUTER_MODE_EXCLUSIVE) ||
18        (mode == TIZEN_KEYROUTER_MODE_OVERRIDABLE_EXCLUSIVE) ||
19        (mode == TIZEN_KEYROUTER_MODE_TOPMOST) ||
20        (mode == TIZEN_KEYROUTER_MODE_SHARED)),
21       TIZEN_KEYROUTER_ERROR_INVALID_MODE);
22
23    if ((mode == TIZEN_KEYROUTER_MODE_EXCLUSIVE) && (krt->HardKeys[key].excl_ptr != NULL))
24      {
25         keylist_ptr = krt->HardKeys[key].excl_ptr;
26
27         EINA_LIST_FOREACH(keylist_ptr, l, kdata)
28           {
29              pid = e_keyrouter_util_get_pid(kdata->wc, kdata->surface);
30              KLINF("The key(%d) is already grabbed exclusively by other [surface: %p, client: %p, pid:%d(%s)]",
31                     key, kdata->surface, kdata->wc, pid, e_keyrouter_util_cmd_get_from_pid(pid));
32           }
33         return TIZEN_KEYROUTER_ERROR_GRABBED_ALREADY;
34      }
35
36    if (mode == TIZEN_KEYROUTER_MODE_TOPMOST)
37      {
38         EINA_SAFETY_ON_NULL_RETURN_VAL
39           (surface, TIZEN_KEYROUTER_ERROR_INVALID_SURFACE);
40      }
41
42    res = e_keyrouter_prepend_to_keylist(surface,
43                                    surface ? NULL : client,
44                                    key,
45                                    mode,
46                                    EINA_FALSE);
47
48    EINA_SAFETY_ON_FALSE_RETURN_VAL(res == TIZEN_KEYROUTER_ERROR_NONE, res);
49
50    return res;
51 }
52
53 /* Function for checking whether the key has been grabbed already by the same wl_surface or not */
54 static int
55 _e_keyrouter_find_duplicated_client(struct wl_resource *surface, struct wl_client *wc, uint32_t key, uint32_t mode)
56 {
57    Eina_List *keylist_ptr = NULL, *l = NULL;
58    E_Keyrouter_Key_List_NodePtr key_node_data = NULL;
59
60    switch(mode)
61      {
62       case TIZEN_KEYROUTER_MODE_EXCLUSIVE:
63          return TIZEN_KEYROUTER_ERROR_NONE;
64
65       case TIZEN_KEYROUTER_MODE_OVERRIDABLE_EXCLUSIVE:
66          keylist_ptr = krt->HardKeys[key].or_excl_ptr;
67          break;
68
69       case TIZEN_KEYROUTER_MODE_TOPMOST:
70          keylist_ptr = krt->HardKeys[key].top_ptr;
71          break;
72
73       case TIZEN_KEYROUTER_MODE_SHARED:
74          keylist_ptr = krt->HardKeys[key].shared_ptr;
75          break;
76
77       case TIZEN_KEYROUTER_MODE_PRESSED:
78          keylist_ptr = krt->HardKeys[key].press_ptr;
79          break;
80
81      case TIZEN_KEYROUTER_MODE_PICTURE_OFF:
82          keylist_ptr = krt->HardKeys[key].pic_off_ptr;
83          break;
84       default:
85          KLWRN("Unknown key(%d) and grab mode(%d)", key, mode);
86          return TIZEN_KEYROUTER_ERROR_INVALID_MODE;
87      }
88
89    EINA_LIST_FOREACH(keylist_ptr, l, key_node_data)
90      {
91         if (!key_node_data) continue;
92
93         if (surface)
94           {
95              if (key_node_data->surface == surface)
96                {
97                   KLDBG("The key(%d) is already grabbed same mode(%s) on the same wl_surface %p",
98                         key, e_keyrouter_mode_to_string(mode), surface);
99                   return TIZEN_KEYROUTER_ERROR_GRABBED_ALREADY;
100                }
101           }
102         else
103           {
104              if (key_node_data->wc == wc)
105                {
106                   KLDBG("The key(%d) is already grabbed same mode(%s) on the same wl_client %p",
107                         key, e_keyrouter_mode_to_string(mode), wc);
108                   return TIZEN_KEYROUTER_ERROR_GRABBED_ALREADY;
109                }
110           }
111      }
112
113    return TIZEN_KEYROUTER_ERROR_NONE;
114 }
115
116 static Eina_Bool
117 _e_keyrouter_find_key_in_list(struct wl_resource *surface, struct wl_client *wc, int key, int mode)
118 {
119    Eina_List **list = NULL;
120    Eina_List *l = NULL, *l_next = NULL;
121    E_Keyrouter_Key_List_NodePtr key_node_data = NULL;
122
123    EINA_SAFETY_ON_TRUE_RETURN_VAL(((!surface) && (!wc)), EINA_FALSE);
124
125    list = _e_keyrouter_get_list(mode, key);
126    EINA_SAFETY_ON_NULL_RETURN_VAL(list, EINA_FALSE);
127
128    EINA_LIST_FOREACH_SAFE(*list, l, l_next, key_node_data)
129      {
130         if (!key_node_data) continue;
131
132         if ((surface) && (surface == key_node_data->surface)) return EINA_TRUE;
133         else if ((wc == key_node_data->wc)) return EINA_TRUE;
134      }
135
136    return EINA_FALSE;
137 }
138
139
140 /* Function for prepending a new key grab information in the keyrouting list */
141 int
142 e_keyrouter_prepend_to_keylist(struct wl_resource *surface, struct wl_client *wc, uint32_t key, uint32_t mode, Eina_Bool focused)
143 {
144    int res = TIZEN_KEYROUTER_ERROR_NONE;
145
146    res = _e_keyrouter_find_duplicated_client(surface, wc, key, mode);
147    CHECK_ERR_VAL(res);
148
149    E_Keyrouter_Key_List_NodePtr new_keyptr = E_NEW(E_Keyrouter_Key_List_Node, 1);
150
151    if (!new_keyptr)
152      {
153         KLERR("Failled to allocate memory for new_keyptr");
154         return TIZEN_KEYROUTER_ERROR_NO_SYSTEM_RESOURCES;
155      }
156
157    new_keyptr->surface = surface;
158    new_keyptr->wc = wc;
159    new_keyptr->focused = focused;
160    new_keyptr->status = E_KRT_CSTAT_ALIVE;
161
162    switch(mode)
163      {
164       case TIZEN_KEYROUTER_MODE_EXCLUSIVE:
165          krt->HardKeys[key].excl_ptr = eina_list_prepend(krt->HardKeys[key].excl_ptr, new_keyptr);
166          break;
167
168       case TIZEN_KEYROUTER_MODE_OVERRIDABLE_EXCLUSIVE:
169          krt->HardKeys[key].or_excl_ptr= eina_list_prepend(krt->HardKeys[key].or_excl_ptr, new_keyptr);
170          break;
171
172       case TIZEN_KEYROUTER_MODE_TOPMOST:
173          krt->HardKeys[key].top_ptr = eina_list_prepend(krt->HardKeys[key].top_ptr, new_keyptr);
174          break;
175
176       case TIZEN_KEYROUTER_MODE_SHARED:
177          krt->HardKeys[key].shared_ptr= eina_list_prepend(krt->HardKeys[key].shared_ptr, new_keyptr);
178          break;
179
180       case TIZEN_KEYROUTER_MODE_PRESSED:
181          krt->HardKeys[key].press_ptr = eina_list_append(krt->HardKeys[key].press_ptr, new_keyptr);
182          break;
183
184      case TIZEN_KEYROUTER_MODE_PICTURE_OFF:
185          krt->HardKeys[key].pic_off_ptr = eina_list_prepend(krt->HardKeys[key].pic_off_ptr, new_keyptr);
186          break;
187
188       default:
189          KLWRN("Unknown key(%d) and grab mode(%d)", key, mode);
190          E_FREE(new_keyptr);
191          return TIZEN_KEYROUTER_ERROR_INVALID_MODE;
192      }
193
194    if (TIZEN_KEYROUTER_MODE_PRESSED != mode)
195      {
196         if (surface)
197           {
198              e_keyrouter_wl_add_surface_destroy_listener(surface);
199              /* TODO: if failed add surface_destory_listener, remove keygrabs */
200           }
201         else if (wc)
202           {
203              e_keyrouter_wl_add_client_destroy_listener(wc);
204              /* TODO: if failed add client_destory_listener, remove keygrabs */
205           }
206      }
207
208    return TIZEN_KEYROUTER_ERROR_NONE;
209 }
210
211 /* remove key grab info from the list */
212 void
213 e_keyrouter_find_and_remove_client_from_list(struct wl_resource *surface, struct wl_client *wc, uint32_t key, uint32_t mode)
214 {
215    Eina_List **list = NULL;
216    Eina_List *l = NULL, *l_next = NULL;
217    E_Keyrouter_Key_List_NodePtr key_node_data = NULL;
218
219    list = _e_keyrouter_get_list(mode, key);
220    EINA_SAFETY_ON_NULL_RETURN(list);
221
222    EINA_LIST_FOREACH_SAFE(*list, l, l_next, key_node_data)
223      {
224         if (!key_node_data) continue;
225
226         if (surface)
227           {
228              if (surface == key_node_data->surface)
229                {
230                   if (mode == TIZEN_KEYROUTER_MODE_PRESSED)
231                     {
232                        key_node_data->status = E_KRT_CSTAT_UNGRAB;
233                     }
234                   else
235                     {
236                        *list = eina_list_remove_list(*list, l);
237                        E_FREE(key_node_data);
238                     }
239                   KLDBG("Remove a %s Mode Grabbed key(%d) by surface(%p)", e_keyrouter_mode_to_string(mode), key, surface);
240                }
241           }
242         else if ((wc == key_node_data->wc))
243           {
244              if (mode == TIZEN_KEYROUTER_MODE_PRESSED)
245                {
246                   key_node_data->status = E_KRT_CSTAT_UNGRAB;
247                }
248              else
249                {
250                   *list = eina_list_remove_list(*list, l);
251                   E_FREE(key_node_data);
252                }
253              KLDBG("Remove a %s Mode Grabbed key(%d) by wc(%p)", e_keyrouter_mode_to_string(mode), key, wc);
254           }
255      }
256 }
257
258 void
259 e_keyrouter_remove_client_from_list(struct wl_resource *surface, struct wl_client *wc)
260 {
261    int i = 0;
262    Eina_List *l = NULL, *l_next = NULL;
263    E_Keyrouter_Key_List_NodePtr key_node_data = NULL;
264
265    EINA_SAFETY_ON_TRUE_RETURN(((!surface) && (!wc)));
266
267    for (i = 0; i <= krt->max_tizen_hwkeys; i++)
268      {
269         if (0 == krt->HardKeys[i].keycode) continue;
270
271         EINA_LIST_FOREACH_SAFE(krt->HardKeys[i].excl_ptr, l, l_next, key_node_data)
272           {
273              if (!key_node_data) continue;
274
275              if (surface)
276                {
277                   if (surface == key_node_data->surface)
278                     {
279                        krt->HardKeys[i].excl_ptr = eina_list_remove_list(krt->HardKeys[i].excl_ptr, l);
280                        E_FREE(key_node_data);
281                        KLDBG("Remove a Exclusive Mode Grabbed key(%d) by wl_surface(%p)", i, surface);
282                     }
283                }
284              else if ((wc == key_node_data->wc))
285                {
286                   krt->HardKeys[i].excl_ptr = eina_list_remove_list(krt->HardKeys[i].excl_ptr, l);
287                   E_FREE(key_node_data);
288                   KLDBG("Remove a Exclusive Mode Grabbed key(%d) by wl_client(%p)", i, wc);
289                }
290           }
291         EINA_LIST_FOREACH_SAFE(krt->HardKeys[i].or_excl_ptr, l, l_next, key_node_data)
292           {
293              if (!key_node_data) continue;
294
295              if (surface)
296                {
297                   if (surface == key_node_data->surface)
298                     {
299                        krt->HardKeys[i].or_excl_ptr = eina_list_remove_list(krt->HardKeys[i].or_excl_ptr, l);
300                        E_FREE(key_node_data);
301                        KLDBG("Remove a Overridable_Exclusive Mode Grabbed key(%d) by wl_surface(%p)", i, surface);
302                     }
303                }
304              else if ((wc == key_node_data->wc))
305                {
306                   krt->HardKeys[i].or_excl_ptr = eina_list_remove_list(krt->HardKeys[i].or_excl_ptr, l);
307                   E_FREE(key_node_data);
308                   KLDBG("Remove a Overridable_Exclusive Mode Grabbed key(%d) by wl_client(%p)", i, wc);
309                }
310           }
311         EINA_LIST_FOREACH_SAFE(krt->HardKeys[i].top_ptr, l, l_next, key_node_data)
312           {
313              if (!key_node_data) continue;
314
315              if (surface)
316                {
317                   if (surface == key_node_data->surface)
318                     {
319                        krt->HardKeys[i].top_ptr = eina_list_remove_list(krt->HardKeys[i].top_ptr, l);
320                        E_FREE(key_node_data);
321                        KLDBG("Remove a Topmost Mode Grabbed key(%d) by wl_surface(%p)", i, surface);
322                     }
323                }
324              else if ((wc == key_node_data->wc))
325                {
326                   krt->HardKeys[i].top_ptr = eina_list_remove_list(krt->HardKeys[i].top_ptr, l);
327                   E_FREE(key_node_data);
328                   KLDBG("Remove a Topmost Mode Grabbed key(%d) by wl_client(%p)", i, wc);
329                }
330           }
331         EINA_LIST_FOREACH_SAFE(krt->HardKeys[i].shared_ptr, l, l_next, key_node_data)
332           {
333              if (!key_node_data) continue;
334
335              if (surface)
336                {
337                   if (surface == key_node_data->surface)
338                     {
339                        krt->HardKeys[i].shared_ptr = eina_list_remove_list(krt->HardKeys[i].shared_ptr, l);
340                        E_FREE(key_node_data);
341                        KLDBG("Remove a Shared Mode Grabbed key(%d) by wl_surface(%p)", i, surface);
342                     }
343                }
344              else if ((wc == key_node_data->wc))
345                {
346                   krt->HardKeys[i].shared_ptr = eina_list_remove_list(krt->HardKeys[i].shared_ptr, l);
347                   E_FREE(key_node_data);
348                   KLDBG("Remove a Shared Mode Grabbed key(%d) by wl_client(%p)", i, wc);
349                }
350           }
351         EINA_LIST_FOREACH_SAFE(krt->HardKeys[i].press_ptr, l, l_next, key_node_data)
352           {
353              if (!key_node_data) continue;
354
355              if (surface)
356                {
357                   if (surface == key_node_data->surface)
358                     {
359                        key_node_data->status = E_KRT_CSTAT_DEAD;
360                        KLDBG("Remove a Pressed  key(%d) by wl_surface(%p)", i, surface);
361                        key_node_data->wc = wl_resource_get_client(surface);
362                     }
363                }
364              else if ((wc == key_node_data->wc))
365                {
366                   key_node_data->status = E_KRT_CSTAT_DEAD;
367                   KLDBG("Remove a Pressed key(%d) by wl_client(%p)", i, wc);
368                }
369           }
370         EINA_LIST_FOREACH_SAFE(krt->HardKeys[i].pic_off_ptr, l, l_next, key_node_data)
371           {
372              if (!key_node_data) continue;
373              if (surface)
374                {
375                   if (surface == key_node_data->surface)
376                     {
377                        krt->HardKeys[i].pic_off_ptr = eina_list_remove_list(krt->HardKeys[i].pic_off_ptr, l);
378                        E_FREE(key_node_data);
379                     }
380                }
381              else if ( wc == key_node_data->wc)
382                {
383                   krt->HardKeys[i].pic_off_ptr = eina_list_remove_list(krt->HardKeys[i].pic_off_ptr, l);
384                   E_FREE(key_node_data);
385                }
386           }
387      }
388 }
389
390 int
391 e_keyrouter_find_key_in_list(struct wl_resource *surface, struct wl_client *wc, uint32_t key)
392 {
393    int mode = TIZEN_KEYROUTER_MODE_NONE;
394    Eina_Bool found = EINA_FALSE;
395
396    mode = TIZEN_KEYROUTER_MODE_EXCLUSIVE;
397    found = _e_keyrouter_find_key_in_list(surface, wc, key, mode);
398    if (found) goto finish;
399
400    mode = TIZEN_KEYROUTER_MODE_OVERRIDABLE_EXCLUSIVE;
401    found = _e_keyrouter_find_key_in_list(surface, wc, key, mode);
402    if (found) goto finish;
403
404    mode = TIZEN_KEYROUTER_MODE_TOPMOST;
405    found = _e_keyrouter_find_key_in_list(surface, wc, key, mode);
406    if (found) goto finish;
407
408    mode = TIZEN_KEYROUTER_MODE_SHARED;
409    found = _e_keyrouter_find_key_in_list(surface, wc, key, mode);
410    if (found) goto finish;
411
412    KLDBG("%d key is not grabbed by (wl_surface: %p, wl_client: %p)", key, surface, wc);
413    return TIZEN_KEYROUTER_MODE_NONE;
414
415 finish:
416    KLDBG("Find %d key grabbed by (wl_surface: %p, wl_client: %p) in %s mode",
417          key, surface, wc, e_keyrouter_mode_to_string(mode));
418    return mode;
419 }
420
421 const char *
422 e_keyrouter_mode_to_string(uint32_t mode)
423 {
424    const char *str = NULL;
425
426    switch (mode)
427      {
428       case TIZEN_KEYROUTER_MODE_EXCLUSIVE:             str = "Exclusive";             break;
429       case TIZEN_KEYROUTER_MODE_OVERRIDABLE_EXCLUSIVE: str = "Overridable_Exclusive"; break;
430       case TIZEN_KEYROUTER_MODE_TOPMOST:               str = "Topmost";               break;
431       case TIZEN_KEYROUTER_MODE_SHARED:                str = "Shared";                break;
432       case TIZEN_KEYROUTER_MODE_PRESSED:               str = "Pressed";               break;
433       default: str = "UnknownMode"; break;
434      }
435
436    return str;
437 }
438
439 static Eina_List **
440 _e_keyrouter_get_list(int mode, int key)
441 {
442    Eina_List **list = NULL;
443
444    switch (mode)
445      {
446         case TIZEN_KEYROUTER_MODE_EXCLUSIVE:             list = &krt->HardKeys[key].excl_ptr;    break;
447         case TIZEN_KEYROUTER_MODE_OVERRIDABLE_EXCLUSIVE: list = &krt->HardKeys[key].or_excl_ptr; break;
448         case TIZEN_KEYROUTER_MODE_TOPMOST:               list = &krt->HardKeys[key].top_ptr;     break;
449         case TIZEN_KEYROUTER_MODE_SHARED:                list = &krt->HardKeys[key].shared_ptr;  break;
450         case TIZEN_KEYROUTER_MODE_PRESSED:                list = &krt->HardKeys[key].press_ptr;  break;
451         default: break;
452      }
453
454    return list;
455 }
456
457
458 int
459 e_keyrouter_keygrab_set(struct wl_client *client, struct wl_resource *surface, int key, int mode)
460 {
461    int res=0;
462
463 #ifdef HAVE_CYNARA
464    if (EINA_FALSE == e_keyrouter_wl_util_do_privilege_check(client, mode, key))
465      {
466         KLINF("No permission for %d grab mode ! (key=%d)", mode, key);
467         return TIZEN_KEYROUTER_ERROR_NO_PERMISSION;
468      }
469 #endif
470
471    if (!surface)
472      {
473         /* Regarding topmost mode, a client must request to grab a key with a valid surface. */
474         if (mode == TIZEN_KEYROUTER_MODE_TOPMOST)
475           {
476              KLWRN("Invalid surface for %d grab mode ! (key=%d)", mode, key);
477
478              return TIZEN_KEYROUTER_ERROR_INVALID_SURFACE;
479           }
480      }
481
482    /* Check the given key range */
483    if (krt->max_tizen_hwkeys < key)
484      {
485         KLWRN("Invalid range of key ! (keycode:%d)", key);
486         return TIZEN_KEYROUTER_ERROR_INVALID_KEY;
487      }
488
489    /* Check whether the key can be grabbed or not !
490     * Only key listed in Tizen key layout file can be grabbed. */
491    if (0 == krt->HardKeys[key].keycode)
492      {
493         KLWRN("Invalid key ! Disabled to grab ! (keycode:%d)", key);
494         return TIZEN_KEYROUTER_ERROR_INVALID_KEY;
495      }
496
497    /* Check whether the request key can be grabbed or not */
498    res = e_keyrouter_set_keygrab_in_list(surface, client, key, mode);
499
500    return res;
501 }
502
503 int
504 e_keyrouter_keygrab_unset(struct wl_client *client, struct wl_resource *surface, int key)
505 {
506    /* Ungrab top position grabs first. This grab mode do not need privilege */
507    if (!surface)
508      e_keyrouter_find_and_remove_client_from_list(NULL, client, key, TIZEN_KEYROUTER_MODE_TOPMOST);
509    else
510      e_keyrouter_find_and_remove_client_from_list(surface, client, key, TIZEN_KEYROUTER_MODE_TOPMOST);
511
512 #ifdef HAVE_CYNARA
513    if (EINA_FALSE == e_keyrouter_wl_util_do_privilege_check(client, TIZEN_KEYROUTER_MODE_NONE, key))
514      {
515         goto finish;
516      }
517 #endif
518
519    if (!surface)
520      {
521         /* EXCLUSIVE grab */
522         e_keyrouter_find_and_remove_client_from_list(NULL, client, key, TIZEN_KEYROUTER_MODE_EXCLUSIVE);
523
524         /* OVERRIDABLE_EXCLUSIVE grab */
525         e_keyrouter_find_and_remove_client_from_list(NULL, client, key, TIZEN_KEYROUTER_MODE_OVERRIDABLE_EXCLUSIVE);
526
527         /* SHARED grab */
528         e_keyrouter_find_and_remove_client_from_list(NULL, client, key, TIZEN_KEYROUTER_MODE_SHARED);
529
530         /* Press List */
531         e_keyrouter_find_and_remove_client_from_list(NULL, client, key, TIZEN_KEYROUTER_MODE_PRESSED);
532      }
533    else
534      {
535         /* EXCLUSIVE grab */
536         e_keyrouter_find_and_remove_client_from_list(surface, client, key, TIZEN_KEYROUTER_MODE_EXCLUSIVE);
537
538         /* OVERRIDABLE_EXCLUSIVE grab */
539         e_keyrouter_find_and_remove_client_from_list(surface, client, key, TIZEN_KEYROUTER_MODE_OVERRIDABLE_EXCLUSIVE);
540
541         /* SHARED grab */
542         e_keyrouter_find_and_remove_client_from_list(surface, client, key, TIZEN_KEYROUTER_MODE_SHARED);
543
544         /* Press List */
545         e_keyrouter_find_and_remove_client_from_list(surface, client, key, TIZEN_KEYROUTER_MODE_PRESSED);
546      }
547
548 finish:
549    e_keyrouter_keycancel_send(client, surface, key);
550
551    return TIZEN_KEYROUTER_ERROR_NONE;
552 }