2 * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 #include "efl_assist.h"
20 #include "efl_assist_private.h"
22 typedef struct _Ea_Event_Mgr Ea_Event_Mgr;
26 Eina_List *obj_events;
28 Evas_Object *key_grab_rect;
31 typedef struct _Ea_Object_Event
36 Eina_Bool delete_me : 1;
37 Eina_Bool on_callback : 1;
40 typedef struct _Ea_Event_Callback
42 Ea_Callback_Type type;
43 void (*func)(void *data, Evas_Object *obj, void *event_info);
47 const char *EA_OBJ_KEY_EVENT_MGR = "_ea_obj_key_event_mgr";
48 const char *EA_OBJ_KEY_OBJ_EVENT = "_ea_obj_key_obj_event";
49 const char *EA_KEY_STOP = "XF86Stop";
50 const char *EA_KEY_STOP2 = "Escape";
51 const char *EA_KEY_SEND = "XF86Send";
52 const char *EA_KEY_SEND2 = "Menu";
55 static Eina_List *event_mgrs = NULL;
58 _ea_event_mgr_del(Ea_Event_Mgr *event_mgr)
60 if (event_mgr->obj_events) return;
62 //Redundant Event Mgr. Remove it.
63 evas_object_del(event_mgr->key_grab_rect);
64 event_mgrs = eina_list_remove(event_mgrs, event_mgr);
69 _ea_object_del_cb(void *data, Evas *e, Evas_Object *obj, void *event_info)
71 Ea_Event_Mgr *event_mgr = evas_object_data_get(obj, EA_OBJ_KEY_EVENT_MGR);
72 Ea_Object_Event *obj_event = data;
74 Ea_Event_Callback *callback;
76 l = eina_list_data_find_list(event_mgr->obj_events, obj_event);
79 event_mgr->obj_events = eina_list_remove_list(event_mgr->obj_events, l);
81 EINA_LIST_FOREACH(obj_event->callbacks, l, callback)
83 obj_event->callbacks = eina_list_free(obj_event->callbacks);
85 if (obj_event->on_callback) obj_event->delete_me = EINA_TRUE;
88 _ea_event_mgr_del(event_mgr);
92 _ea_layer_sort_cb(const void *data1, const void *data2)
94 const Ea_Object_Event *obj_event = data1;
95 const Ea_Object_Event *obj_event2 = data2;
98 int layer1 = evas_object_layer_get(obj_event->obj);
99 int layer2 = evas_object_layer_get(obj_event2->obj);
101 return (layer1 < layer2) ? -1 : 1;
105 _ea_top_parent_candidates(Eina_List **candidates, Evas *e)
109 Eina_List *l, *l_next;
110 Ea_Object_Event *obj_event;
111 Eina_List *_candidates = *candidates;
112 Eina_Bool found = EINA_FALSE;
114 //Get the top parent lists
115 EINA_LIST_FOREACH(_candidates, l, obj_event)
117 temp = obj_event->obj;
118 parent = obj_event->obj;
122 temp = evas_object_smart_parent_get(temp);
124 obj_event->parent = parent;
127 //Leave only parent candidates.
128 parent = evas_object_top_get(e);
132 EINA_LIST_FOREACH(_candidates, l, obj_event)
134 if (parent == obj_event->parent)
137 obj_event->parent = NULL;
141 parent = evas_object_below_get(parent);
144 //Redundant parents (no candidates)
145 EINA_LIST_FOREACH_SAFE(_candidates, l, l_next, obj_event)
147 if (!obj_event->parent) continue;
148 _candidates = eina_list_remove_list(_candidates, l);
151 *candidates = _candidates;
155 static Ea_Object_Event *
156 _ea_find_event_target(Eina_List *candidates, Evas_Object *parent)
158 Ea_Object_Event *obj_event = NULL;
161 Eina_List *members = evas_object_smart_members_get(parent);
164 EINA_LIST_REVERSE_FOREACH(members, l, obj)
166 obj_event = _ea_find_event_target(candidates, obj);
170 eina_list_free(members);
174 eina_list_free(members);
177 EINA_LIST_REVERSE_FOREACH(candidates, l, obj_event)
180 if (parent == obj_event->obj) return obj_event;
186 static Ea_Object_Event *
187 _ea_top_obj_event_find(Ea_Event_Mgr *event_mgr)
189 Ea_Object_Event *obj_event = NULL;
190 Eina_List *l, *l_next;
191 Eina_List *candidates = NULL;
196 //1. filter the invisible objs
197 EINA_LIST_FOREACH(event_mgr->obj_events, l, obj_event)
199 parent = obj_event->obj;
200 invisible = EINA_FALSE;
204 if (!evas_object_visible_get(parent))
206 invisible = EINA_TRUE;
209 parent = evas_object_smart_parent_get(parent);
211 if (invisible) continue;
212 candidates = eina_list_append(candidates, obj_event);
214 if (!candidates) return NULL; //no visible objects.
215 if (eina_list_count(candidates) == 1) goto found;
217 //2.1. sort by layer order
218 candidates = eina_list_sort(candidates, eina_list_count(candidates),
221 //2.2. leave the only top layer
222 obj_event = eina_list_data_get(eina_list_last(candidates));
223 top_layer = evas_object_layer_get(obj_event->obj);
225 EINA_LIST_FOREACH_SAFE(candidates, l, l_next, obj_event)
227 if (evas_object_layer_get(obj_event->obj) < top_layer)
228 candidates = eina_list_remove_list(candidates, l);
230 if (eina_list_count(candidates) == 1) goto found;
232 //3. find the top parent candidate.
233 parent = _ea_top_parent_candidates(&candidates, event_mgr->e);
234 if (eina_list_count(candidates) == 1) goto found;
236 //4. find the target in this parent tree.
237 return _ea_find_event_target(candidates, parent);
240 obj_event = eina_list_data_get(candidates);
241 eina_list_free(candidates);
246 _ea_key_grab_rect_key_up_cb(void *data, Evas *e, Evas_Object *obj,
249 Evas_Event_Key_Down *ev = event_info;
250 Ea_Event_Mgr *event_mgr = data;
251 Ea_Object_Event *obj_event;
252 Ea_Event_Callback *callback;
253 Ea_Callback_Type type;
256 obj_event = _ea_top_obj_event_find(event_mgr);
257 if (!obj_event) return;
259 if (!strcmp(ev->keyname, EA_KEY_STOP) || !strcmp(ev->keyname, EA_KEY_STOP2))
260 type = EA_CALLBACK_BACK;
261 else if (!strcmp(ev->keyname, EA_KEY_SEND) ||
262 !strcmp(ev->keyname, EA_KEY_SEND2))
263 type = EA_CALLBACK_MORE;
266 obj_event->on_callback = EINA_TRUE;
267 EINA_LIST_FOREACH(obj_event->callbacks, l, callback)
269 if (obj_event->delete_me) break;
270 if (callback->type != type) continue;
271 callback->func(callback->data, obj_event->obj, (void*) type);
273 if (obj_event->delete_me) free(obj_event);
274 else obj_event->on_callback = EINA_FALSE;
278 _ea_key_grab_obj_create(Ea_Event_Mgr *event_mgr)
280 Evas_Object *key_grab_rect = evas_object_rectangle_add(event_mgr->e);
282 evas_object_event_callback_add(key_grab_rect, EVAS_CALLBACK_KEY_UP,
283 _ea_key_grab_rect_key_up_cb, event_mgr);
284 if (!evas_object_key_grab(key_grab_rect, EA_KEY_STOP, 0, 0, EINA_FALSE))
285 LOGE("Failed to grab END KEY\n");
287 if (!evas_object_key_grab(key_grab_rect, EA_KEY_STOP2, 0, 0, EINA_FALSE))
288 LOGE("Failed to grab END KEY\n");
290 if (!evas_object_key_grab(key_grab_rect, EA_KEY_SEND, 0, 0, EINA_FALSE))
291 LOGE("Failed to grab MORE KEY\n");
293 if (!evas_object_key_grab(key_grab_rect, EA_KEY_SEND2, 0, 0, EINA_FALSE))
294 LOGE("Failed to grab MORE KEY\n");
296 event_mgr->key_grab_rect = key_grab_rect;
299 static Ea_Event_Mgr *
300 _ea_event_mgr_new(Evas *e)
302 Ea_Event_Mgr *event_mgr = calloc(1, sizeof(Ea_Event_Mgr));
305 LOGE("Failed to allocate event manager");
309 _ea_key_grab_obj_create(event_mgr);
315 ea_object_event_callback_del(Evas_Object *obj, Ea_Callback_Type type, Ea_Event_Cb func)
317 Ea_Object_Event *obj_event;
318 Ea_Event_Mgr *event_mgr;
320 Ea_Event_Callback *callback;
323 //Check the validation
324 event_mgr = evas_object_data_get(obj, EA_OBJ_KEY_EVENT_MGR);
325 obj_event = evas_object_data_get(obj, EA_OBJ_KEY_OBJ_EVENT);
327 if (!event_mgr || !obj_event)
329 LOGW("This object(%p) hasn't been registered before", obj);
333 evas_object_event_callback_del(obj, EVAS_CALLBACK_DEL, _ea_object_del_cb);
335 //Remove the callback data
336 EINA_LIST_REVERSE_FOREACH(obj_event->callbacks, l, callback)
338 if ((callback->func == func) && (callback->type == type)) break;
341 data = callback->data;
342 obj_event->callbacks = eina_list_remove_list(obj_event->callbacks, l);
345 //This object is not managed anymore.
346 if (!obj_event->callbacks)
348 evas_object_data_set(obj, EA_OBJ_KEY_OBJ_EVENT, NULL);
349 evas_object_data_set(obj, EA_OBJ_KEY_EVENT_MGR, NULL);
350 Eina_List *l = eina_list_data_find_list(event_mgr->obj_events,
353 event_mgr->obj_events = eina_list_remove_list(event_mgr->obj_events,
355 if (obj_event->on_callback) obj_event->delete_me = EINA_TRUE;
356 else free(obj_event);
359 _ea_event_mgr_del(event_mgr);
365 ea_object_event_callback_add(Evas_Object *obj, Ea_Callback_Type type, Ea_Event_Cb func, void *data)
367 Ea_Event_Mgr *event_mgr;
369 Ea_Object_Event *obj_event = NULL;
371 Ea_Event_Callback *callback;
372 Eina_Bool new_event_mgr = EINA_TRUE;
374 //Check the registered event manager for this Evas.
375 e = evas_object_evas_get(obj);
377 EINA_LIST_FOREACH(event_mgrs, l, event_mgr)
379 if (event_mgr->e == e)
381 new_event_mgr = EINA_FALSE;
386 //New Evas comes. Create new event manager for this Evas.
389 if (!(event_mgr = _ea_event_mgr_new(e))) return;
390 event_mgrs = eina_list_append(event_mgrs, event_mgr);
393 obj_event = evas_object_data_get(obj, EA_OBJ_KEY_OBJ_EVENT);
395 //New Object Event. Probably user adds ea_object_event_callback first time.
398 obj_event = calloc(1, sizeof(Ea_Object_Event));
401 LOGE("Failed to allocate object event");
404 evas_object_data_set(obj, EA_OBJ_KEY_OBJ_EVENT, obj_event);
405 evas_object_data_set(obj, EA_OBJ_KEY_EVENT_MGR, event_mgr);
406 evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL,
409 event_mgr->obj_events = eina_list_append(event_mgr->obj_events,
411 obj_event->obj = obj;
414 //Append this callback.
415 callback = calloc(1, sizeof(Ea_Event_Callback));
418 LOGE("Failed to allocate event callback");
421 callback->type = type;
422 callback->func = func;
423 callback->data = data;
425 obj_event->callbacks = eina_list_append(obj_event->callbacks, callback);