keyrouter: Properly test for allocation failure
[platform/core/uifw/libds-tizen.git] / src / keyrouter / keyrouter_grab.c
1 #include <stdio.h>
2 #include <stdlib.h>
3
4 #include <libds/log.h>
5
6 #include "keyrouter.h"
7
8 static struct wl_list *
9 keyrouter_grab_get_grabbed_list(struct ds_tizen_keyrouter_grab *keyrouter_grab,
10         int type, int keycode)
11 {
12     switch(type) {
13         case TIZEN_KEYROUTER_MODE_EXCLUSIVE:
14             return &keyrouter_grab->hard_keys[keycode].grab.excl;
15         case TIZEN_KEYROUTER_MODE_OVERRIDABLE_EXCLUSIVE:
16             return &keyrouter_grab->hard_keys[keycode].grab.or_excl;
17         case TIZEN_KEYROUTER_MODE_TOPMOST:
18             return &keyrouter_grab->hard_keys[keycode].grab.top;
19         case TIZEN_KEYROUTER_MODE_SHARED:
20             return &keyrouter_grab->hard_keys[keycode].grab.shared;
21         default:
22             return NULL;
23     }
24 }
25
26 bool
27 keyrouter_grab_check_grabbed_key(struct ds_tizen_keyrouter_grab *keyrouter_grab, int keycode)
28 {
29     struct wl_list *list;
30
31     list = keyrouter_grab_get_grabbed_list(keyrouter_grab, TIZEN_KEYROUTER_MODE_EXCLUSIVE, keycode);
32     if (list && !wl_list_empty(list))
33         return true;
34
35     list = keyrouter_grab_get_grabbed_list(keyrouter_grab, TIZEN_KEYROUTER_MODE_OVERRIDABLE_EXCLUSIVE, keycode);
36     if (list && !wl_list_empty(list))
37         return true;
38
39     list = keyrouter_grab_get_grabbed_list(keyrouter_grab, TIZEN_KEYROUTER_MODE_TOPMOST, keycode);
40     if (list && !wl_list_empty(list))
41         return true;
42
43     list = keyrouter_grab_get_grabbed_list(keyrouter_grab, TIZEN_KEYROUTER_MODE_SHARED, keycode);
44     if (list && !wl_list_empty(list))
45         return true;
46
47     return false;
48 }
49
50 static bool
51 keyrouter_grab_check_duplicated_data(struct wl_list *list, void *data)
52 {
53     struct ds_tizen_keyrouter_key_info *info;
54
55     if (wl_list_empty(list))
56         return false;
57
58     wl_list_for_each(info, list, link) {
59         if (info->data == data)
60             return true;
61     }
62
63     return false;
64 }
65
66 static bool
67 keyrouter_grab_check_grabbed(struct ds_tizen_keyrouter_grab *keyrouter_grab,
68         int type, int keycode, void *data)
69 {
70     struct wl_list *list;
71     bool ret;
72
73     list = keyrouter_grab_get_grabbed_list(keyrouter_grab, type, keycode);
74     if (list == NULL) {
75         ds_err("keycode(%d) had no list for type(%d).", keycode, type);
76         return false;
77     }
78
79     switch(type) {
80         case TIZEN_KEYROUTER_MODE_EXCLUSIVE:
81             if (wl_list_empty(list) == false)
82                 ret = true;
83             else
84                 ret = false;
85             break;
86         case TIZEN_KEYROUTER_MODE_OVERRIDABLE_EXCLUSIVE:
87             ret = keyrouter_grab_check_duplicated_data(list, data);
88             break;
89         case TIZEN_KEYROUTER_MODE_TOPMOST:
90             ret = keyrouter_grab_check_duplicated_data(list, data);
91             break;
92         case TIZEN_KEYROUTER_MODE_SHARED:
93             ret = keyrouter_grab_check_duplicated_data(list, data);
94             break;
95         default:
96             ret = true;
97             break;
98     }
99
100     return ret;
101 }
102
103 void
104 keyrouter_grab_set_focus_client(struct ds_tizen_keyrouter_grab *keyrouter_grab,
105         void *focus_client)
106 {
107     keyrouter_grab->focus_client = focus_client;
108
109     if (focus_client)
110         ds_dbg("[%s] focus client has been set. (focus_client=0x%p)", __FUNCTION__, focus_client);
111     else
112         ds_dbg("[%s] focus client has been set to NULL.", __FUNCTION__);
113 }
114
115 void
116 keyrouter_grab_set_top_client(struct ds_tizen_keyrouter_grab *keyrouter_grab, void *top_client)
117 {
118     keyrouter_grab->top_client = top_client;
119
120     if (top_client)
121         ds_dbg("[%s] top client has been set. (top_client=0x%p)", __FUNCTION__, top_client);
122     else
123         ds_dbg("[%s] top client has been set to NULL.", __FUNCTION__);
124 }
125
126 int
127 keyrouter_grab_key_process(struct ds_tizen_keyrouter_grab *keyrouter_grab,
128         int keycode, int pressed, struct wl_list *delivery_list)
129 {
130     struct ds_tizen_keyrouter_key_info *info, *delivery;
131     int count = 0;
132
133     if (keycode <= 0 || keycode >= KEYROUTER_MAX_KEYS) {
134         ds_err("Invalid keycode(%d)", keycode);
135         return 0;
136     }
137
138     if (!wl_list_empty(&keyrouter_grab->hard_keys[keycode].grab.excl)) {
139         info = wl_container_of(keyrouter_grab->hard_keys[keycode].grab.excl.next, info, link);
140         if (info) {
141             delivery = calloc(1, sizeof(struct ds_tizen_keyrouter_key_info));
142             if (delivery == NULL) {
143                 ds_err("Failed to allocate memory.");
144                 return 0;
145             }
146             delivery->data = info->data;
147             wl_list_insert(delivery_list, &delivery->link);
148             ds_dbg("Exclusive Mode: keycode: %d to data: %p", keycode, info->data);
149             return 1;
150         }
151     } else if (!wl_list_empty(&keyrouter_grab->hard_keys[keycode].grab.or_excl)) {
152         info = wl_container_of(keyrouter_grab->hard_keys[keycode].grab.or_excl.next, info, link);
153         if (info) {
154             delivery = calloc(1, sizeof(struct ds_tizen_keyrouter_key_info));
155             if (delivery == NULL) {
156                 ds_err("Failed to allocate memory.");
157                 return 0;
158             }
159             delivery->data = info->data;
160             wl_list_insert(delivery_list, &delivery->link);
161             ds_dbg("OR-Excl Mode: keycode: %d to data: %p", keycode, info->data);
162             return 1;
163         }
164     } else if (!wl_list_empty(&keyrouter_grab->hard_keys[keycode].grab.top)) {
165         wl_list_for_each(info, &keyrouter_grab->hard_keys[keycode].grab.top, link) {
166             if (keyrouter_grab->top_client && keyrouter_grab->top_client == info->data) {
167                 delivery = calloc(1, sizeof(struct ds_tizen_keyrouter_key_info));
168                 if (delivery == NULL) {
169                     ds_err("Failed to allocate memory.");
170                     return 0;
171                 }
172                 delivery->data = info->data;
173                 wl_list_insert(delivery_list, &delivery->link);
174                 ds_dbg("Topmost Mode: keycode: %d to data: %p", keycode, info->data);
175                 return 1;
176             }
177         }
178     }
179
180     if (keyrouter_grab->focus_client) {
181         delivery = calloc(1, sizeof(struct ds_tizen_keyrouter_key_info));
182         if (delivery == NULL) {
183             ds_err("Failed to allocate memory.");
184             return 0;
185         }
186         delivery->data = keyrouter_grab->focus_client;
187         wl_list_insert(delivery_list, &delivery->link);
188         count++;
189         ds_dbg("Focus: keycode: %d to data: %p, count: %d", keycode, delivery->data, count);
190     }
191
192     if (!wl_list_empty(&keyrouter_grab->hard_keys[keycode].grab.shared)) {
193         wl_list_for_each(info, &keyrouter_grab->hard_keys[keycode].grab.shared, link) {
194             if (keyrouter_grab->focus_client && keyrouter_grab->focus_client == info->data)
195                 continue;
196             delivery = calloc(1, sizeof(struct ds_tizen_keyrouter_key_info));
197             if (delivery == NULL) {
198                 ds_err("Failed to allocate memory.");
199                 return 0;
200             }
201             delivery->data = info->data;
202             wl_list_insert(delivery_list, &delivery->link);
203             count++;
204             ds_dbg("Shared: keycode: %d to data: %p, count: %d", keycode, info->data, count);
205         }
206     }
207
208     return count;
209 }
210
211 int
212 keyrouter_grab_grab_key(struct ds_tizen_keyrouter_grab *keyrouter_grab,
213         int type, int keycode, void *data)
214 {
215     struct ds_tizen_keyrouter_key_info *info = NULL;
216     struct wl_list *list = NULL;
217
218     if (keycode <= 0 || keycode >= KEYROUTER_MAX_KEYS) {
219         ds_err("Invalid keycode(%d)", keycode);
220         return TIZEN_KEYROUTER_ERROR_INVALID_KEY;
221     }
222
223     if (keyrouter_grab_check_grabbed(keyrouter_grab, type, keycode, data))
224         return TIZEN_KEYROUTER_ERROR_GRABBED_ALREADY;
225
226     info = calloc(1, sizeof(struct ds_tizen_keyrouter_key_info));
227     if (info == NULL) {
228         ds_err("Failed to allocate memory.");
229         return TIZEN_KEYROUTER_ERROR_NO_SYSTEM_RESOURCES;
230     }
231     info->data = data;
232
233     wl_list_init(&info->link);
234
235     list = keyrouter_grab_get_grabbed_list(keyrouter_grab, type, keycode);
236     if (!list) {
237         ds_err("keycode(%d) had no list for type(%d)", keycode, type);
238         free(info);
239         return TIZEN_KEYROUTER_ERROR_INVALID_MODE;
240     }
241
242     if (!keyrouter_grab->hard_keys[keycode].keycode)
243         keyrouter_grab->hard_keys[keycode].keycode = keycode;
244
245     wl_list_insert(list, &info->link);
246
247     return TIZEN_KEYROUTER_ERROR_NONE;
248 }
249
250 static void
251 keyrouter_list_remove_data(struct wl_list *list, void *data)
252 {
253     struct ds_tizen_keyrouter_key_info *info, *tmp;
254
255     if (wl_list_empty(list))
256         return;
257
258     wl_list_for_each_safe(info ,tmp, list, link) {
259         if (info->data == data) {
260             wl_list_remove(&info->link);
261             free(info);
262         }
263     }
264 }
265
266 void
267 keyrouter_grab_ungrab_key(struct ds_tizen_keyrouter_grab *keyrouter_grab,
268         int type, int keycode, void *data)
269 {
270     struct wl_list *list;
271
272     if (keycode <= 0 || keycode >= KEYROUTER_MAX_KEYS) {
273         ds_err("Invalid keycode(%d)", keycode);
274         return;
275     }
276
277     if (keyrouter_grab->hard_keys[keycode].keycode == 0)
278         return;
279
280     list = keyrouter_grab_get_grabbed_list(keyrouter_grab, type, keycode);
281     if (list == NULL) {
282         ds_err("keycode(%d) had no list for type(%d)", keycode, type);
283         return;
284     }
285
286     keyrouter_list_remove_data(list, data);
287 }
288
289 struct ds_tizen_keyrouter_grab *
290 keyrouter_grab_create(void)
291 {
292     struct ds_tizen_keyrouter_grab *keyrouter_grab = NULL;
293     int i;
294
295     keyrouter_grab = calloc(1, sizeof(struct ds_tizen_keyrouter_grab));
296     if (keyrouter_grab == NULL) {
297         ds_err("Failed to allocate memory.");
298         return NULL;
299     }
300
301     /* FIXME: Who defined max keycode? */
302     keyrouter_grab->hard_keys = calloc(KEYROUTER_MAX_KEYS, sizeof(struct ds_tizen_keyrouter_grabbed));
303     if (keyrouter_grab->hard_keys == NULL) {
304         ds_err("Failed to allocate memory.");
305         free(keyrouter_grab);
306         return NULL;
307     }
308
309     for (i = 0; i < KEYROUTER_MAX_KEYS; i++) {
310         /* Enable all of keys to grab */
311         //keyrouter_grab->hard_keys[i].keycode = i;
312         wl_list_init(&keyrouter_grab->hard_keys[i].grab.excl);
313         wl_list_init(&keyrouter_grab->hard_keys[i].grab.or_excl);
314         wl_list_init(&keyrouter_grab->hard_keys[i].grab.top);
315         wl_list_init(&keyrouter_grab->hard_keys[i].grab.shared);
316         wl_list_init(&keyrouter_grab->hard_keys[i].pressed);
317     }
318
319     return keyrouter_grab;
320 }
321
322 static void
323 keyrouter_grab_delete_list(struct wl_list *list)
324 {
325     struct ds_tizen_keyrouter_key_info *info, *tmp;
326
327     if (wl_list_empty(list))
328         return;
329
330     wl_list_for_each_safe(info, tmp, list, link) {
331         wl_list_remove(&info->link);
332         free(info);
333     }
334 }
335
336 void
337 keyrouter_grab_destroy(struct ds_tizen_keyrouter_grab *keyrouter_grab)
338 {
339     int i;
340
341     for (i = 0; i < KEYROUTER_MAX_KEYS; i++) {
342         keyrouter_grab_delete_list(&keyrouter_grab->hard_keys[i].grab.excl);
343         keyrouter_grab_delete_list(&keyrouter_grab->hard_keys[i].grab.or_excl);
344         keyrouter_grab_delete_list(&keyrouter_grab->hard_keys[i].grab.top);
345         keyrouter_grab_delete_list(&keyrouter_grab->hard_keys[i].grab.shared);
346         keyrouter_grab_delete_list(&keyrouter_grab->hard_keys[i].pressed);
347     }
348
349     free(keyrouter_grab->hard_keys);
350     free(keyrouter_grab);
351 }