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