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