Fix a memory leak
[platform/core/uifw/e-mod-tizen-keyrouter.git] / src / e_mod_keyrouter_events.c
1 #define E_COMP_WL
2 #include "e_mod_main_wl.h"
3 #include <string.h>
4
5 static Eina_Bool _e_keyrouter_send_key_events(int type, Ecore_Event_Key *ev);
6 static Eina_Bool _e_keyrouter_send_key_events_press(int type, Ecore_Event_Key *ev);
7 static Eina_Bool _e_keyrouter_send_key_events_release(int type, Ecore_Event_Key *ev);
8 static Eina_Bool _e_keyrouter_send_key_event(int type, struct wl_resource *surface, struct wl_client *wc, Ecore_Event_Key *ev, Eina_Bool focused, unsigned int mode);
9
10 static Eina_Bool _e_keyrouter_send_key_events_register(int type, Ecore_Event_Key *ev);
11
12 static Eina_Bool _e_keyrouter_is_key_grabbed(int key);
13 static Eina_Bool _e_keyrouter_check_top_visible_window(E_Client *ec_focus, int arr_idx);
14
15 static Eina_Bool
16 _e_keyrouter_is_key_grabbed(int key)
17 {
18    if (!krt->HardKeys[key].keycode)
19      {
20         return EINA_FALSE;
21      }
22    if (krt->HardKeys[key].excl_ptr ||
23         krt->HardKeys[key].or_excl_ptr ||
24         krt->HardKeys[key].top_ptr ||
25         krt->HardKeys[key].shared_ptr ||
26         krt->HardKeys[key].registered_ptr)
27      {
28         return EINA_TRUE;
29      }
30
31    return EINA_FALSE;
32 }
33
34 /* Function for checking the existing grab for a key and sending key event(s) */
35 Eina_Bool
36 e_keyrouter_process_key_event(void *event, int type)
37 {
38    Eina_Bool res = EINA_TRUE;
39    Ecore_Event_Key *ev = event;
40
41    if (!ev) goto finish;
42
43    KLDBG("[%s] keyname: %s, key: %s, keycode: %d\n", (type == ECORE_EVENT_KEY_DOWN) ? "KEY_PRESS" : "KEY_RELEASE", ev->keyname, ev->key, ev->keycode);
44
45    if (ev->data)
46      {
47         KLDBG("data is exist send to compositor: %p\n", ev->data);
48         goto finish;
49      }
50
51    if (krt->max_tizen_hwkeys < ev->keycode)
52      {
53         KLWRN("The key(%d) is too larger to process keyrouting: Invalid keycode\n", ev->keycode);
54         goto finish;
55      }
56
57    if ((ECORE_EVENT_KEY_DOWN == type) && (!_e_keyrouter_is_key_grabbed(ev->keycode)))
58      {
59         KLDBG("The press key(%d) isn't a grabbable key or has not been grabbed yet !\n", ev->keycode);
60         goto finish;
61      }
62
63    if ((ECORE_EVENT_KEY_UP == type) && (!krt->HardKeys[ev->keycode].press_ptr))
64      {
65         KLDBG("The release key(%d) isn't a grabbable key or has not been grabbed yet !\n", ev->keycode);
66         goto finish;
67      }
68
69    //KLDBG("The key(%d) is going to be sent to the proper wl client(s) !\n", ev->keycode);
70
71   if (_e_keyrouter_send_key_events(type, ev))
72     res = EINA_FALSE;
73
74 finish:
75    return res;
76 }
77
78 /* Function for sending key events to wl_client(s) */
79 static Eina_Bool
80 _e_keyrouter_send_key_events(int type, Ecore_Event_Key *ev)
81 {
82    Eina_Bool res;
83    if (ECORE_EVENT_KEY_DOWN == type)
84      {
85         res = _e_keyrouter_send_key_events_press(type, ev);
86      }
87   else
88      {
89         res = _e_keyrouter_send_key_events_release(type, ev);
90      }
91   return res;
92 }
93
94 static Eina_Bool
95 _e_keyrouter_send_key_events_release(int type, Ecore_Event_Key *ev)
96 {
97    E_Keyrouter_Key_List_NodePtr key_node_data;
98    Eina_Bool res = EINA_TRUE, ret = EINA_TRUE;
99
100    /* Deliver release  clean up pressed key list */
101    EINA_LIST_FREE(krt->HardKeys[ev->keycode].press_ptr, key_node_data)
102      {
103         if (key_node_data)
104           {
105              res = _e_keyrouter_send_key_event(type, key_node_data->surface, key_node_data->wc, ev,
106                                                key_node_data->focused, TIZEN_KEYROUTER_MODE_PRESSED);
107              KLINF("Release Pair : Key %s(%s:%d)(Focus: %d) ===> E_Client (%p) WL_Client (%p) (pid: %d)\n",
108                       ((ECORE_EVENT_KEY_DOWN == type) ? "Down" : "Up"), ev->keyname, ev->keycode, key_node_data->focused,
109                       key_node_data->surface, key_node_data->wc, e_keyrouter_util_get_pid(key_node_data->wc, key_node_data->surface));
110              E_FREE(key_node_data);
111              if (res == EINA_FALSE) ret = EINA_FALSE;
112           }
113      }
114    krt->HardKeys[ev->keycode].press_ptr = NULL;
115
116    return ret;
117 }
118
119 static Eina_Bool
120 _e_keyrouter_send_key_events_press(int type, Ecore_Event_Key *ev)
121 {
122    unsigned int keycode = ev->keycode;
123    struct wl_resource *surface_focus = NULL;
124    E_Client *ec_focus = NULL;
125    Eina_Bool res = EINA_TRUE;
126
127    E_Keyrouter_Key_List_NodePtr key_node_data;
128    Eina_List *l = NULL;
129
130    EINA_LIST_FOREACH(krt->HardKeys[keycode].excl_ptr, l, key_node_data)
131      {
132         if (key_node_data)
133           {
134              res = _e_keyrouter_send_key_event(type, key_node_data->surface, key_node_data->wc, ev,
135                                                key_node_data->focused, TIZEN_KEYROUTER_MODE_EXCLUSIVE);
136              KLINF("EXCLUSIVE Mode : Key %s(%s:%d) ===> Surface (%p) WL_Client (%p) (pid: %d)\n",
137                       ((ECORE_EVENT_KEY_DOWN == type) ? "Down" : "Up"), ev->keyname, ev->keycode,
138                       key_node_data->surface, key_node_data->wc, e_keyrouter_util_get_pid(key_node_data->wc, key_node_data->surface));
139
140              return res;
141           }
142      }
143
144    EINA_LIST_FOREACH(krt->HardKeys[keycode].or_excl_ptr, l, key_node_data)
145      {
146         if (key_node_data)
147           {
148              res = _e_keyrouter_send_key_event(type, key_node_data->surface, key_node_data->wc, ev,
149                                                key_node_data->focused, TIZEN_KEYROUTER_MODE_OVERRIDABLE_EXCLUSIVE);
150              KLINF("OVERRIDABLE_EXCLUSIVE Mode : Key %s(%s:%d) ===> Surface (%p) WL_Client (%p) (pid: %d)\n",
151                      ((ECORE_EVENT_KEY_DOWN == type) ? "Down" : "Up"), ev->keyname, ev->keycode,
152                      key_node_data->surface, key_node_data->wc, e_keyrouter_util_get_pid(key_node_data->wc, key_node_data->surface));
153
154              return res;
155           }
156      }
157
158    ec_focus = e_client_focused_get();
159    surface_focus = e_keyrouter_util_get_surface_from_eclient(ec_focus);
160
161    // Top position grab must need a focus surface.
162    if (surface_focus)
163      {
164         EINA_LIST_FOREACH(krt->HardKeys[keycode].top_ptr, l, key_node_data)
165           {
166              if (key_node_data)
167                {
168                   if ((EINA_FALSE == krt->isWindowStackChanged) && (surface_focus == key_node_data->surface))
169                     {
170                        res = _e_keyrouter_send_key_event(type, key_node_data->surface, NULL, ev, key_node_data->focused,
171                                                          TIZEN_KEYROUTER_MODE_TOPMOST);
172                        KLINF("TOPMOST (TOP_POSITION) Mode : Key %s (%s:%d) ===> Surface (%p) (pid: %d)\n",
173                                 ((ECORE_EVENT_KEY_DOWN == type) ? "Down" : "Up"), ev->keyname, ev->keycode,
174                                 key_node_data->surface, e_keyrouter_util_get_pid(key_node_data->wc, key_node_data->surface));
175
176                        return res;
177                     }
178                   krt->isWindowStackChanged = EINA_FALSE;
179
180                   if (_e_keyrouter_check_top_visible_window(ec_focus, keycode))
181                     {
182                        res = _e_keyrouter_send_key_event(type, key_node_data->surface, NULL, ev, key_node_data->focused,
183                                                          TIZEN_KEYROUTER_MODE_TOPMOST);
184                        KLINF("TOPMOST (TOP_POSITION) Mode : Key %s (%s:%d) ===> Surface (%p) (pid: %d)\n",
185                              ((ECORE_EVENT_KEY_DOWN == type) ? "Down" : "Up"), ev->keyname, ev->keycode,
186                              key_node_data->surface, e_keyrouter_util_get_pid(key_node_data->wc, key_node_data->surface));
187
188                        return res;
189                     }
190                   break;
191                }
192           }
193      }
194
195    if (krt->HardKeys[keycode].shared_ptr)
196      {
197         res = _e_keyrouter_send_key_event(type, surface_focus, NULL, ev, EINA_TRUE, TIZEN_KEYROUTER_MODE_SHARED);
198         KLINF("SHARED [Focus client] : Key %s (%s:%d) ===> Surface (%p) (pid: %d)\n",
199                  ((ECORE_EVENT_KEY_DOWN == type) ? "Down" : "Up "), ev->keyname, ev->keycode,
200                  surface_focus, e_keyrouter_util_get_pid(NULL, surface_focus));
201         e_keyrouter_add_surface_destroy_listener(surface_focus);
202
203         EINA_LIST_FOREACH(krt->HardKeys[keycode].shared_ptr, l, key_node_data)
204           {
205              if (key_node_data)
206                {
207                   if (key_node_data->surface)
208                     {
209                        if (key_node_data->surface != surface_focus)
210                          {
211                             _e_keyrouter_send_key_event(type, key_node_data->surface,
212                                                         key_node_data->wc, ev, EINA_FALSE,
213                                                         TIZEN_KEYROUTER_MODE_SHARED);
214                             KLINF("SHARED Mode : Key %s(%s:%d) ===> Surface (%p) WL_Client (%p) (pid: %d)\n",
215                                      ((ECORE_EVENT_KEY_DOWN == type) ? "Down" : "Up"), ev->keyname, ev->keycode,
216                                      key_node_data->surface, key_node_data->wc, e_keyrouter_util_get_pid(key_node_data->wc, key_node_data->surface));
217                          }
218                     }
219                   else
220                     {
221                        if (((surface_focus) && (key_node_data->wc != wl_resource_get_client(surface_focus))) ||
222                            (!surface_focus))
223                          {
224                             _e_keyrouter_send_key_event(type, key_node_data->surface,
225                                                         key_node_data->wc, ev, EINA_FALSE,
226                                                         TIZEN_KEYROUTER_MODE_SHARED);
227                             KLINF("SHARED Mode : Key %s(%s:%d) ===> Surface (%p) WL_Client (%p) (pid: %d)\n",
228                                      ((ECORE_EVENT_KEY_DOWN == type) ? "Down" : "Up"), ev->keyname, ev->keycode,
229                                      key_node_data->surface, key_node_data->wc, e_keyrouter_util_get_pid(key_node_data->wc, key_node_data->surface));
230                          }
231                     }
232                }
233           }
234
235         return res;
236      }
237
238    if (_e_keyrouter_send_key_events_register(type, ev))
239      {
240         return EINA_TRUE;
241      }
242
243    return EINA_FALSE;
244 }
245
246 static Eina_Bool
247 _e_keyrouter_send_key_events_register(int type, Ecore_Event_Key *ev)
248 {
249    unsigned int keycode = ev->keycode;
250    Eina_Bool res = EINA_TRUE;
251
252    if (!krt->HardKeys[keycode].registered_ptr)
253      {
254         KLDBG("This keycode is not registered\n");
255         return EINA_FALSE;
256      }
257
258    res = _e_keyrouter_send_key_event(type, krt->HardKeys[keycode].registered_ptr->surface,
259                                      NULL, ev, krt->HardKeys[keycode].registered_ptr->focused,
260                                      TIZEN_KEYROUTER_MODE_REGISTERED);
261    KLINF("REGISTER Mode : Key %s(%s:%d) ===> Surface (%p) (pid: %d)\n",
262             ((ECORE_EVENT_KEY_DOWN == type) ? "Down" : "Up"), ev->keyname, ev->keycode,
263             krt->HardKeys[keycode].registered_ptr->surface, e_keyrouter_util_get_pid(NULL, krt->HardKeys[keycode].registered_ptr->surface));
264
265    return res;
266 }
267
268 static Eina_Bool
269 _e_keyrouter_check_top_visible_window(E_Client *ec_focus, int arr_idx)
270 {
271    E_Client *ec_top = NULL;
272    Eina_List *l = NULL, *l_next = NULL;
273    E_Keyrouter_Key_List_NodePtr key_node_data = NULL;
274
275    ec_top = e_client_top_get();
276
277    while (ec_top)
278      {
279         if (!ec_top->visible && ec_top == ec_focus)
280           {
281              KLDBG("Top Client(%p) is invisible(%d) but focus client\n", ec_top, ec_top->visible);
282              return EINA_FALSE;
283           }
284
285         /* TODO: Check this client is located inside a display boundary */
286
287         EINA_LIST_FOREACH_SAFE(krt->HardKeys[arr_idx].top_ptr, l, l_next, key_node_data)
288           {
289              if (key_node_data)
290                {
291                   if (ec_top == wl_resource_get_user_data(key_node_data->surface))
292                     {
293                        krt->HardKeys[arr_idx].top_ptr = eina_list_promote_list(krt->HardKeys[arr_idx].top_ptr, l);
294                        KLDBG("Move a client(%p) to first index of list(key: %d)\n",
295                                 ec_top, arr_idx);
296                        return EINA_TRUE;
297                     }
298                }
299           }
300
301         if (ec_top == ec_focus)
302           {
303              KLDBG("The Client(%p) is a focus client\n", ec_top);
304              return EINA_FALSE;
305           }
306
307         ec_top = e_client_below_get(ec_top);
308      }
309    return EINA_FALSE;
310 }
311
312 /* Function for sending key event to wl_client(s) */
313 static Eina_Bool
314 _e_keyrouter_send_key_event(int type, struct wl_resource *surface, struct wl_client *wc, Ecore_Event_Key *ev, Eina_Bool focused, unsigned int mode)
315 {
316    struct wl_client *wc_send;
317    Ecore_Event_Key *ev_cpy;
318    int len;
319
320    if (surface == NULL)
321      {
322         wc_send = wc;
323      }
324    else
325      {
326         wc_send = wl_resource_get_client(surface);
327      }
328
329    if (!wc_send)
330      {
331         KLWRN("surface: %p or wc: %p returns null wayland client\n", surface, wc);
332         return EINA_FALSE;
333      }
334
335    if (ECORE_EVENT_KEY_DOWN == type)
336      {
337         if (mode == TIZEN_KEYROUTER_MODE_EXCLUSIVE ||
338             mode == TIZEN_KEYROUTER_MODE_OVERRIDABLE_EXCLUSIVE ||
339             mode == TIZEN_KEYROUTER_MODE_TOPMOST ||
340             mode == TIZEN_KEYROUTER_MODE_REGISTERED)
341           {
342              focused = EINA_TRUE;
343              ev->data = wc_send;
344              KLDBG("Send only one key! wc_send: %p(%d)\n", wc_send, e_keyrouter_util_get_pid(wc_send, NULL));
345           }
346         else if (focused == EINA_TRUE)
347           {
348              ev->data = wc_send;
349           }
350         e_keyrouter_prepend_to_keylist(surface, wc, ev->keycode, TIZEN_KEYROUTER_MODE_PRESSED, focused);
351      }
352    else
353      {
354         if (focused == EINA_TRUE) ev->data = wc_send;
355      }
356
357    if (focused == EINA_TRUE) return EINA_FALSE;
358
359    KLDBG("Generate new key event! wc_send: %p(%d)\n", wc_send, e_keyrouter_util_get_pid(wc_send, NULL));
360
361    len = sizeof(Ecore_Event_Key) + strlen(ev->key) + strlen(ev->keyname) + ((ev->compose) ? strlen(ev->compose) : 0) + 3;
362    ev_cpy = calloc(1, len);
363    memcpy(ev_cpy, ev, len);
364    ev_cpy->data = wc_send;
365
366    if (ECORE_EVENT_KEY_DOWN == type)
367      ecore_event_add(ECORE_EVENT_KEY_DOWN, ev_cpy, NULL, NULL);
368    else
369      ecore_event_add(ECORE_EVENT_KEY_UP, ev_cpy, NULL, NULL);
370
371    return EINA_TRUE;
372 }
373
374 struct wl_resource *
375 e_keyrouter_util_get_surface_from_eclient(E_Client *client)
376 {
377    EINA_SAFETY_ON_NULL_RETURN_VAL
378      (client, NULL);
379    EINA_SAFETY_ON_NULL_RETURN_VAL
380      (client->comp_data, NULL);
381
382    return client->comp_data->wl_surface;
383 }
384
385 int
386 e_keyrouter_util_get_pid(struct wl_client *client, struct wl_resource *surface)
387 {
388    pid_t pid = 0;
389    uid_t uid = 0;
390    gid_t gid = 0;
391    struct wl_client *cur_client = NULL;
392
393    if (client) cur_client = client;
394    else if (surface) cur_client = wl_resource_get_client(surface);
395    EINA_SAFETY_ON_NULL_RETURN_VAL(cur_client, 0);
396
397    wl_client_get_credentials(cur_client, &pid, &uid, &gid);
398
399    return pid;
400 }