0c552cc7a2aee28c015463338e1f8b31f3ba23dc
[platform/upstream/elementary.git] / src / mobile_lib / elc_ctxpopup.c
1 #ifdef HAVE_CONFIG_H
2 # include "elementary_config.h"
3 #endif
4
5 #define ELM_INTERFACE_ATSPI_ACCESSIBLE_PROTECTED
6 #define ELM_INTERFACE_ATSPI_COMPONENT_PROTECTED
7 #define ELM_INTERFACE_ATSPI_WIDGET_ACTION_PROTECTED
8 #define ELM_WIDGET_ITEM_PROTECTED
9
10 #include <Elementary.h>
11
12 #include "elm_priv.h"
13 #include "elm_widget_ctxpopup.h"
14
15 #define MY_CLASS ELM_CTXPOPUP_CLASS
16
17 #define MY_CLASS_NAME "Elm_Ctxpopup"
18 #define MY_CLASS_NAME_LEGACY "elm_ctxpopup"
19
20 EAPI const char ELM_CTXPOPUP_SMART_NAME[] = "elm_ctxpopup";
21
22 #define ELM_PRIV_CTXPOPUP_SIGNALS(cmd) \
23    cmd(SIG_DISMISSED, "dismissed", "") \
24
25 ELM_PRIV_CTXPOPUP_SIGNALS(ELM_PRIV_STATIC_VARIABLE_DECLARE);
26
27 static const Evas_Smart_Cb_Description _smart_callbacks[] = {
28    ELM_PRIV_CTXPOPUP_SIGNALS(ELM_PRIV_SMART_CALLBACKS_DESC)
29    {SIG_WIDGET_LANG_CHANGED, ""}, /**< handled by elm_widget */
30    {SIG_WIDGET_ACCESS_CHANGED, ""}, /**< handled by elm_widget */
31    {SIG_LAYOUT_FOCUSED, ""}, /**< handled by elm_layout */
32    {SIG_LAYOUT_UNFOCUSED, ""}, /**< handled by elm_layout */
33    {NULL, NULL}
34 };
35 #undef ELM_PRIV_CTXPOPUP_SIGNALS
36
37 #define TTS_STR_MENU_POPUP dgettext(PACKAGE, "IDS_SCR_OPT_MENU_POP_UP_TTS")
38 #define TTS_STR_MENU_CLOSE dgettext(PACKAGE, "IDS_ST_BODY_DOUBLE_TAP_TO_CLOSE_THE_MENU_T_TTS")
39
40 static const char ACCESS_OUTLINE_PART[] = "access.outline";
41
42 static void _on_move(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED);
43 static void _item_sizing_eval(Elm_Ctxpopup_Item_Data *item);
44 static Eina_Bool _key_action_escape(Evas_Object *obj, const char *params EINA_UNUSED);
45 //TIZEN ONLY(20161014) : Accessibility: scroll the content when highlight frame goes out of view port
46 static void _content_move_down_cb(void *data, Evas_Object *obj, void *ev EINA_UNUSED);
47 static void _content_move_up_cb(void *data, Evas_Object *obj, void *ev EINA_UNUSED);
48 //
49
50 EOLIAN static Eina_Bool
51 _elm_ctxpopup_elm_widget_translate(Eo *obj, Elm_Ctxpopup_Data *sd)
52 {
53    Eina_List *l;
54    Elm_Ctxpopup_Item_Data *it;
55
56    if (sd->auto_hide)
57      {
58         evas_object_hide(obj);
59         eo_do(obj, eo_event_callback_call(ELM_CTXPOPUP_EVENT_DISMISSED, NULL));
60      }
61
62    EINA_LIST_FOREACH(sd->items, l, it)
63      eo_do(EO_OBJ(it), elm_wdg_item_translate());
64
65    eo_do_super(obj, MY_CLASS, elm_obj_widget_translate());
66
67    return EINA_TRUE;
68 }
69
70 static Evas_Object *
71 _access_object_get(const Evas_Object *obj, const char* part)
72 {
73    Evas_Object *po, *ao;
74
75    ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd, NULL);
76
77    po = (Evas_Object *)edje_object_part_object_get(wd->resize_obj, part);
78    ao = evas_object_data_get(po, "_part_access_obj");
79
80    return ao;
81 }
82
83 EOLIAN static Eina_Bool
84 _elm_ctxpopup_elm_widget_focus_next(Eo *obj EINA_UNUSED, Elm_Ctxpopup_Data *sd, Elm_Focus_Direction dir, Evas_Object **next, Elm_Object_Item **next_item)
85 {
86    Eina_List *items = NULL;
87    Evas_Object *ao;
88
89    if (!sd)
90      return EINA_FALSE;
91
92    if (_elm_config->access_mode)
93      {
94         Eina_Bool ret;
95
96         ao = _access_object_get(obj, ACCESS_OUTLINE_PART);
97         if (ao) items = eina_list_append(items, ao);
98
99         /* scroller exists when ctxpopup has an item */
100         if (sd->scr)
101            items = eina_list_append(items, sd->scr);
102         else
103            items = eina_list_append(items, sd->box);
104
105         _elm_access_auto_highlight_set(EINA_TRUE);
106         ret = elm_widget_focus_list_next_get
107                  (obj, items, eina_list_data_get, dir, next, next_item);
108         _elm_access_auto_highlight_set(EINA_FALSE);
109         return ret;
110      }
111    else
112      {
113         elm_widget_focus_next_get(sd->box, dir, next, next_item);
114         if (!*next) *next = (Evas_Object *)obj;
115         return EINA_TRUE;
116      }
117 }
118
119 EOLIAN static Eina_Bool
120 _elm_ctxpopup_elm_widget_focus_next_manager_is(Eo *obj EINA_UNUSED, Elm_Ctxpopup_Data *_pd EINA_UNUSED)
121 {
122    return EINA_TRUE;
123 }
124
125 EOLIAN static Eina_Bool
126 _elm_ctxpopup_elm_widget_focus_direction_manager_is(Eo *obj EINA_UNUSED, Elm_Ctxpopup_Data *_pd EINA_UNUSED)
127 {
128    return EINA_TRUE;
129 }
130
131 EOLIAN static Eina_Bool
132 _elm_ctxpopup_elm_widget_focus_direction(Eo *obj EINA_UNUSED, Elm_Ctxpopup_Data *sd, const Evas_Object *base, double degree, Evas_Object **direction, Elm_Object_Item **direction_item, double *weight)
133 {
134    Eina_List *l = NULL;
135    void *(*list_data_get)(const Eina_List *list);
136
137    if (!sd)
138      return EINA_FALSE;
139
140    list_data_get = eina_list_data_get;
141
142    l = eina_list_append(l, sd->box);
143
144    elm_widget_focus_list_direction_get
145       (obj, base, l, list_data_get, degree, direction, direction_item, weight);
146    eina_list_free(l);
147
148    return EINA_TRUE;
149 }
150
151 static Eina_Bool
152 _key_action_move(Evas_Object *obj, const char *params)
153 {
154    ELM_CTXPOPUP_DATA_GET(obj, sd);
155    const char *dir = params;
156
157    if (!sd->box) return EINA_FALSE;
158
159    if (!strcmp(dir, "previous"))
160      elm_widget_focus_cycle(sd->box, ELM_FOCUS_PREVIOUS);
161    else if (!strcmp(dir, "next"))
162      elm_widget_focus_cycle(sd->box, ELM_FOCUS_NEXT);
163    else if (!strcmp(dir, "left"))
164      elm_widget_focus_cycle(sd->box, ELM_FOCUS_LEFT);
165    else if (!strcmp(dir, "right"))
166      elm_widget_focus_cycle(sd->box, ELM_FOCUS_RIGHT);
167    else if (!strcmp(dir, "up"))
168      elm_widget_focus_cycle(sd->box, ELM_FOCUS_UP);
169    else if (!strcmp(dir, "down"))
170      elm_widget_focus_cycle(sd->box, ELM_FOCUS_DOWN);
171    else return EINA_FALSE;
172
173    return EINA_TRUE;
174 }
175
176 static void
177 _x_pos_adjust(Evas_Coord_Point *pos,
178               Evas_Coord_Point *base_size,
179               Evas_Coord_Rectangle *hover_area)
180 {
181    pos->x -= (base_size->x / 2);
182
183    if (pos->x < hover_area->x)
184      pos->x = hover_area->x;
185    else if ((pos->x + base_size->x) > (hover_area->x + hover_area->w))
186      pos->x = (hover_area->x + hover_area->w) - base_size->x;
187
188    if (base_size->x > hover_area->w)
189      base_size->x -= (base_size->x - hover_area->w);
190
191    if (pos->x < hover_area->x)
192      pos->x = hover_area->x;
193 }
194
195 static void
196 _y_pos_adjust(Evas_Coord_Point *pos,
197               Evas_Coord_Point *base_size,
198               Evas_Coord_Rectangle *hover_area)
199 {
200    pos->y -= (base_size->y / 2);
201
202    if (pos->y < hover_area->y)
203      pos->y = hover_area->y;
204    else if ((pos->y + base_size->y) > (hover_area->y + hover_area->h))
205      pos->y = hover_area->y + hover_area->h - base_size->y;
206
207    if (base_size->y > hover_area->h)
208      base_size->y -= (base_size->y - hover_area->h);
209
210    if (pos->y < hover_area->y)
211      pos->y = hover_area->y;
212 }
213
214 static void
215 _item_select_cb(void *data,
216                 Evas_Object *obj EINA_UNUSED,
217                 void *event_info EINA_UNUSED)
218 {
219    Elm_Ctxpopup_Item_Data *item = data;
220    Eina_Bool tmp;
221
222    if (!item) return;
223    if (eo_do_ret(EO_OBJ(item), tmp, elm_wdg_item_disabled_get()))
224      {
225         if (_elm_config->access_mode)
226           elm_access_say(E_("Disabled"));
227         return;
228      }
229
230    if (item->wcb.org_func_cb)
231      item->wcb.org_func_cb((void*)item->wcb.org_data, WIDGET(item), EO_OBJ(item));
232 }
233
234 static char *
235 _access_info_cb(void *data, Evas_Object *obj EINA_UNUSED)
236 {
237    Elm_Ctxpopup_Item_Data *it = (Elm_Ctxpopup_Item_Data *)data;
238    const char *txt = NULL;
239    Evas_Object *icon = NULL;
240
241    if (!it) return NULL;
242
243    txt = it->label;
244    icon = it->icon;
245
246    if (txt) return strdup(txt);
247    if (icon) return strdup(E_("icon"));
248    return NULL;
249 }
250
251 static char *
252 _access_state_cb(void *data, Evas_Object *obj EINA_UNUSED)
253 {
254    Elm_Ctxpopup_Item_Data *it = (Elm_Ctxpopup_Item_Data *)data;
255    Eina_Bool tmp;
256    if (!it) return NULL;
257
258    if (eo_do_ret(EO_OBJ(it), tmp, elm_wdg_item_disabled_get()))
259      return strdup(E_("Disabled"));
260
261    return NULL;
262 }
263
264 static void
265 _access_focusable_button_register(Evas_Object *obj, Elm_Ctxpopup_Item_Data *it)
266 {
267    Elm_Access_Info *ai;
268
269    ai = _elm_access_info_get(obj);
270
271    _elm_access_callback_set(ai, ELM_ACCESS_INFO, _access_info_cb, it);
272    _elm_access_callback_set(ai, ELM_ACCESS_STATE, _access_state_cb, it);
273    _elm_access_callback_set(ai, ELM_ACCESS_TYPE, NULL, NULL);
274
275    it->base->access_obj = obj;
276 }
277
278 static void
279 _mouse_down_cb(Elm_Ctxpopup_Item_Data *it,
280                Evas *evas EINA_UNUSED,
281                Evas_Object *obj EINA_UNUSED,
282                Evas_Event_Mouse_Down *ev)
283 {
284    ELM_CTXPOPUP_DATA_GET(WIDGET(it), sd);
285
286    if (ev->button != 1) return;
287
288    //If counter is not zero, it means all other multi down is not released.
289    if (sd->multi_down != 0) return;
290    sd->mouse_down = EINA_TRUE;
291 //******************** TIZEN Only
292    sd->pressed = EINA_TRUE;
293 //****************************
294 }
295
296 //******************** TIZEN Only
297 static void
298 _mouse_move_cb(Elm_Ctxpopup_Item_Data *it,
299                Evas *evas EINA_UNUSED,
300                Evas_Object *obj,
301                void *event_info)
302 {
303    ELM_CTXPOPUP_DATA_GET(WIDGET(it), sd);
304    Evas_Event_Mouse_Move *ev = event_info;
305
306    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD)
307      {
308         if (sd->pressed)
309           {
310              edje_object_signal_emit(obj,"elm,action,unpressed", "elm");
311              sd->pressed = EINA_FALSE;
312           }
313      }
314    else
315      {
316         Evas_Coord x, y, w, h;
317         evas_object_geometry_get(obj, &x, &y, &w, &h);
318         if ((sd->pressed) && (ELM_RECTS_POINT_OUT(x, y, w, h, ev->cur.canvas.x, ev->cur.canvas.y)))
319           {
320              edje_object_signal_emit(obj,"elm,action,unpressed", "elm");
321              sd->pressed = EINA_FALSE;
322           }
323      }
324 }
325 //****************************
326
327 static void
328 _mouse_up_cb(Elm_Ctxpopup_Item_Data *it,
329              Evas *evas EINA_UNUSED,
330              Evas_Object *obj EINA_UNUSED,
331              Evas_Event_Mouse_Up *ev)
332 {
333    ELM_CTXPOPUP_DATA_GET(WIDGET(it), sd);
334
335    if (ev->button != 1) return;
336
337    if (!sd->mouse_down) return;
338    sd->mouse_down = EINA_FALSE;
339 //******************** TIZEN Only
340    sd->pressed = EINA_FALSE;
341 //****************************
342 }
343
344 static void
345 _multi_down_cb(void *data,
346                     Evas *evas EINA_UNUSED,
347                     Evas_Object *obj EINA_UNUSED,
348                     void *event_info EINA_UNUSED)
349 {
350    Elm_Ctxpopup_Item_Data *it = data;
351    ELM_CTXPOPUP_DATA_GET(WIDGET(it), sd);
352
353    //Emitting signal to inform edje about multi down event.
354    edje_object_signal_emit(VIEW(it), "elm,action,multi,down", "elm");
355    sd->multi_down++;
356 }
357
358 static void
359 _multi_up_cb(void *data,
360                     Evas *evas EINA_UNUSED,
361                     Evas_Object *obj EINA_UNUSED,
362                     void *event_info EINA_UNUSED)
363 {
364    Elm_Ctxpopup_Item_Data *it = data;
365    ELM_CTXPOPUP_DATA_GET(WIDGET(it), sd);
366
367    sd->multi_down--;
368    if(sd->multi_down == 0)
369      {
370         //Emitting signal to inform edje about last multi up event.
371         edje_object_signal_emit(VIEW(it), "elm,action,multi,up", "elm");
372      }
373 }
374
375 static void
376 _item_new(Elm_Ctxpopup_Item_Data *item,
377           char *group_name)
378 {
379    ELM_CTXPOPUP_DATA_GET(WIDGET(item), sd);
380    if (!sd) return;
381
382    VIEW(item) = edje_object_add(evas_object_evas_get(sd->box));
383    edje_object_mirrored_set(VIEW(item), elm_widget_mirrored_get(WIDGET(item)));
384    _elm_theme_object_set(WIDGET(item), VIEW(item), "ctxpopup", group_name,
385                          elm_widget_style_get(WIDGET(item)));
386    evas_object_size_hint_align_set(VIEW(item), EVAS_HINT_FILL, EVAS_HINT_FILL);
387    evas_object_show(VIEW(item));
388
389    evas_object_event_callback_add
390      (VIEW(item), EVAS_CALLBACK_MOUSE_DOWN, (Evas_Object_Event_Cb)_mouse_down_cb,
391      item);
392 //******************** TIZEN Only
393    evas_object_event_callback_add
394      (VIEW(item), EVAS_CALLBACK_MOUSE_MOVE, (Evas_Object_Event_Cb)_mouse_move_cb,
395      item);
396 //****************************
397    evas_object_event_callback_add
398      (VIEW(item), EVAS_CALLBACK_MOUSE_UP, (Evas_Object_Event_Cb)_mouse_up_cb, item);
399
400    /*Registering Multi down/up events to ignore mouse down/up events untill all
401      multi down/up events are released.*/
402    evas_object_event_callback_add
403      (VIEW(item), EVAS_CALLBACK_MULTI_DOWN, (Evas_Object_Event_Cb)_multi_down_cb,
404      item);
405    evas_object_event_callback_add
406      (VIEW(item), EVAS_CALLBACK_MULTI_UP, (Evas_Object_Event_Cb)_multi_up_cb,
407      item);
408 }
409
410 static void
411 _item_icon_set(Elm_Ctxpopup_Item_Data *item,
412                Evas_Object *icon)
413 {
414    if (item->icon)
415      evas_object_del(item->icon);
416
417    item->icon = icon;
418    if (!icon) return;
419
420    edje_object_part_swallow(VIEW(item), "elm.swallow.icon", item->icon);
421 }
422
423 static void
424 _item_label_set(Elm_Ctxpopup_Item_Data *item,
425                 const char *label)
426 {
427    if (!eina_stringshare_replace(&item->label, label))
428      return;
429
430    ELM_CTXPOPUP_DATA_GET(WIDGET(item), sd);
431
432    edje_object_part_text_set(VIEW(item), "elm.text", label);
433    if (sd->visible) _item_sizing_eval(item);
434 }
435
436 static Evas_Object *
437 _item_in_focusable_button(Elm_Ctxpopup_Item_Data *item)
438 {
439    Evas_Object *bt;
440
441    bt = elm_button_add(WIDGET(item));
442    elm_object_style_set(bt, "focus");
443    evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
444    elm_object_part_content_set(bt, "elm.swallow.content", VIEW(item));
445    evas_object_smart_callback_add(bt, "clicked", _item_select_cb, item);
446    evas_object_show(bt);
447
448    return bt;
449 }
450
451 EOLIAN static Eina_Bool
452 _elm_ctxpopup_item_elm_widget_item_del_pre(Eo *eo_item EINA_UNUSED, Elm_Ctxpopup_Item_Data *item)
453 {
454    Evas_Object *btn;
455
456    ELM_CTXPOPUP_DATA_GET(WIDGET(item), sd);
457    if (!sd) return EINA_FALSE;
458
459    btn = item->btn;
460    elm_box_unpack(sd->box, btn);
461    evas_object_smart_callback_del_full(btn, "clicked", _item_select_cb, item);
462    evas_object_del(btn);
463
464    sd->dir = ELM_CTXPOPUP_DIRECTION_UNKNOWN;
465
466    if (item->icon)
467      evas_object_del(item->icon);
468    if (VIEW(item))
469      evas_object_del(VIEW(item));
470
471    eina_stringshare_del(item->label);
472    sd->items = eina_list_remove(sd->items, item);
473
474    if (eina_list_count(sd->items) < 1)
475      {
476         evas_object_hide(WIDGET(item));
477         return EINA_TRUE;
478      }
479    if (sd->visible) elm_layout_sizing_eval(WIDGET(item));
480
481    return EINA_TRUE;
482 }
483
484 static void
485 _items_remove(Elm_Ctxpopup_Data *sd)
486 {
487    Eina_List *l, *l_next;
488    Elm_Ctxpopup_Item_Data *item;
489
490    if (!sd->items) return;
491
492    EINA_LIST_FOREACH_SAFE(sd->items, l, l_next, item)
493       eo_do(EO_OBJ(item), elm_wdg_item_del());
494
495    sd->items = NULL;
496 }
497
498 static void
499 _item_sizing_eval(Elm_Ctxpopup_Item_Data *item)
500 {
501    Evas_Coord min_w = -1, min_h = -1, max_w = -1, max_h = -1;
502
503    if (!item) return;
504
505    edje_object_signal_emit(VIEW(item), "elm,state,text,default", "elm");
506    edje_object_message_signal_process(VIEW(item));
507    edje_object_size_min_restricted_calc(VIEW(item), &min_w, &min_h, min_w,
508                                         min_h);
509    evas_object_size_hint_min_set(VIEW(item), min_w, min_h);
510    evas_object_size_hint_max_set(VIEW(item), max_w, max_h);
511 }
512
513 static Elm_Ctxpopup_Direction
514 _base_geometry_calc(Evas_Object *obj,
515                     Evas_Coord_Rectangle *rect)
516 {
517    Elm_Ctxpopup_Direction dir = ELM_CTXPOPUP_DIRECTION_UNKNOWN;
518    Evas_Coord_Rectangle hover_area;
519    Evas_Coord_Point pos = {0, 0};
520    Evas_Coord_Point arrow_size;
521    Evas_Coord_Point base_size;
522    Evas_Coord_Point max_size;
523    Evas_Coord_Point min_size;
524    Evas_Coord_Point temp;
525    int idx;
526    const char *str;
527
528    ELM_CTXPOPUP_DATA_GET(obj, sd);
529    ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd, ELM_CTXPOPUP_DIRECTION_DOWN);
530
531    if (!rect) return ELM_CTXPOPUP_DIRECTION_DOWN;
532
533    edje_object_part_geometry_get
534      (sd->arrow, "ctxpopup_arrow", NULL, NULL, &arrow_size.x, &arrow_size.y);
535    evas_object_resize(sd->arrow, arrow_size.x, arrow_size.y);
536
537    //Initialize Area Rectangle.
538    evas_object_geometry_get
539      (sd->parent, &hover_area.x, &hover_area.y, &hover_area.w,
540      &hover_area.h);
541
542    evas_object_geometry_get(obj, &pos.x, &pos.y, NULL, NULL);
543
544    //recalc the edje
545    edje_object_size_min_calc
546      (wd->resize_obj, &base_size.x, &base_size.y);
547    evas_object_smart_calculate(wd->resize_obj);
548
549    //Limit to Max Size
550    evas_object_size_hint_max_get(obj, &max_size.x, &max_size.y);
551    if ((max_size.x == -1) || (max_size.y == -1))
552      {
553         str = edje_object_data_get(sd->layout, "visible_maxw");
554         if (str)
555           max_size.x = (int)(atoi(str)
556                              * elm_config_scale_get()
557                              * elm_object_scale_get(obj)
558                              / edje_object_base_scale_get(sd->layout));
559         str = edje_object_data_get(sd->layout, "visible_maxh");
560         if (str)
561           max_size.y = (int)(atoi(str)
562                              * elm_config_scale_get()
563                              * elm_object_scale_get(obj)
564                              / edje_object_base_scale_get(sd->layout));
565      }
566
567    if ((max_size.y > 0) && (base_size.y > max_size.y))
568      base_size.y = max_size.y;
569
570    if ((max_size.x > 0) && (base_size.x > max_size.x))
571      base_size.x = max_size.x;
572
573    //Limit to Min Size
574    evas_object_size_hint_min_get(obj, &min_size.x, &min_size.y);
575    if ((min_size.x == 0) || (min_size.y == 0))
576      edje_object_size_min_get(sd->layout, &min_size.x, &min_size.y);
577
578    if ((min_size.y > 0) && (base_size.y < min_size.y))
579      base_size.y = min_size.y;
580
581    if ((min_size.x > 0) && (base_size.x < min_size.x))
582      base_size.x = min_size.x;
583
584    //Check the Which direction is available.
585    //If find a avaialble direction, it adjusts position and size.
586    for (idx = 0; idx < 4; idx++)
587      {
588         switch (sd->dir_priority[idx])
589           {
590            case ELM_CTXPOPUP_DIRECTION_UNKNOWN:
591
592            case ELM_CTXPOPUP_DIRECTION_UP:
593              temp.y = (pos.y - base_size.y);
594              if ((temp.y - arrow_size.y) < hover_area.y)
595                continue;
596
597              _x_pos_adjust(&pos, &base_size, &hover_area);
598              pos.y -= base_size.y;
599              dir = ELM_CTXPOPUP_DIRECTION_UP;
600              break;
601
602            case ELM_CTXPOPUP_DIRECTION_LEFT:
603              temp.x = (pos.x - base_size.x);
604              if ((temp.x - arrow_size.x) < hover_area.x)
605                continue;
606
607              _y_pos_adjust(&pos, &base_size, &hover_area);
608              pos.x -= base_size.x;
609              dir = ELM_CTXPOPUP_DIRECTION_LEFT;
610              break;
611
612            case ELM_CTXPOPUP_DIRECTION_RIGHT:
613              temp.x = (pos.x + base_size.x);
614              if ((temp.x + arrow_size.x) >
615                  (hover_area.x + hover_area.w))
616                continue;
617
618              _y_pos_adjust(&pos, &base_size, &hover_area);
619              dir = ELM_CTXPOPUP_DIRECTION_RIGHT;
620              break;
621
622            case ELM_CTXPOPUP_DIRECTION_DOWN:
623              temp.y = (pos.y + base_size.y);
624              if ((temp.y + arrow_size.y) >
625                  (hover_area.y + hover_area.h))
626                continue;
627
628              _x_pos_adjust(&pos, &base_size, &hover_area);
629              dir = ELM_CTXPOPUP_DIRECTION_DOWN;
630              break;
631
632            default:
633              continue;
634           }
635         break;
636      }
637
638    //In this case, all directions are invalid because of lack of space.
639    if (idx == 4)
640      {
641         Evas_Coord length[2];
642
643         if (!sd->horizontal)
644           {
645              length[0] = pos.y - hover_area.y;
646              length[1] = (hover_area.y + hover_area.h) - pos.y;
647
648              // ELM_CTXPOPUP_DIRECTION_UP
649              if (length[0] > length[1])
650                {
651                   _x_pos_adjust(&pos, &base_size, &hover_area);
652                   pos.y -= base_size.y;
653                   dir = ELM_CTXPOPUP_DIRECTION_UP;
654                   if (pos.y < (hover_area.y + arrow_size.y))
655                     {
656                        base_size.y -= ((hover_area.y + arrow_size.y) - pos.y);
657                        pos.y = hover_area.y + arrow_size.y;
658                     }
659                }
660              //ELM_CTXPOPUP_DIRECTION_DOWN
661              else
662                {
663                   _x_pos_adjust(&pos, &base_size, &hover_area);
664                   dir = ELM_CTXPOPUP_DIRECTION_DOWN;
665                   if ((pos.y + arrow_size.y + base_size.y) >
666                       (hover_area.y + hover_area.h))
667                     base_size.y -=
668                       ((pos.y + arrow_size.y + base_size.y) -
669                        (hover_area.y + hover_area.h));
670                }
671           }
672         else
673           {
674              length[0] = pos.x - hover_area.x;
675              length[1] = (hover_area.x + hover_area.w) - pos.x;
676
677              //ELM_CTXPOPUP_DIRECTION_LEFT
678              if (length[0] > length[1])
679                {
680                   _y_pos_adjust(&pos, &base_size, &hover_area);
681                   pos.x -= base_size.x;
682                   dir = ELM_CTXPOPUP_DIRECTION_LEFT;
683                   if (pos.x < (hover_area.x + arrow_size.x))
684                     {
685                        base_size.x -= ((hover_area.x + arrow_size.x) - pos.x);
686                        pos.x = hover_area.x + arrow_size.x;
687                     }
688                }
689              //ELM_CTXPOPUP_DIRECTION_RIGHT
690              else
691                {
692                   _y_pos_adjust(&pos, &base_size, &hover_area);
693                   dir = ELM_CTXPOPUP_DIRECTION_RIGHT;
694                   if (pos.x + (arrow_size.x + base_size.x) >
695                       hover_area.x + hover_area.w)
696                     base_size.x -=
697                       ((pos.x + arrow_size.x + base_size.x) -
698                        (hover_area.x + hover_area.w));
699                }
700           }
701      }
702
703    //Final position and size.
704    rect->x = pos.x;
705    rect->y = pos.y;
706    rect->w = base_size.x;
707    rect->h = base_size.y;
708
709    return dir;
710 }
711
712 static void
713 _arrow_update(Evas_Object *obj,
714               Elm_Ctxpopup_Direction dir,
715               Evas_Coord_Rectangle base_size)
716 {
717    Evas_Coord_Rectangle arrow_size;
718    Evas_Coord x, y;
719    double drag;
720    Evas_Coord_Rectangle shadow_left_top, shadow_right_bottom, arrow_padding;
721
722    ELM_CTXPOPUP_DATA_GET(obj, sd);
723    ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
724
725    evas_object_geometry_get(obj, &x, &y, NULL, NULL);
726    evas_object_geometry_get
727      (sd->arrow, NULL, NULL, &arrow_size.w, &arrow_size.h);
728
729    /* tizen only : since ctxpopup of tizen has shadow, start and end padding of arrow, it should be put together when updating arrow
730     * so there are some differences between open source and tizen */
731    edje_object_part_geometry_get(wd->resize_obj, "frame_shadow_left_top_padding", NULL, NULL, &shadow_left_top.w, &shadow_left_top.h);
732    edje_object_part_geometry_get(wd->resize_obj, "frame_shadow_right_bottom_padding", NULL, NULL, &shadow_right_bottom.w, &shadow_right_bottom.h);
733    edje_object_part_geometry_get(wd->resize_obj, "ctxpopup_frame_left_top", NULL, NULL, &arrow_padding.w, &arrow_padding.h);
734
735    /* arrow is not being kept as sub-object on purpose, here. the
736     * design of the widget does not help with the contrary */
737
738    switch (dir)
739      {
740       case ELM_CTXPOPUP_DIRECTION_RIGHT:
741         edje_object_signal_emit(sd->arrow, "elm,state,left", "elm");
742         edje_object_part_swallow
743            (wd->resize_obj,
744             (elm_widget_mirrored_get(obj) ? "elm.swallow.arrow_right" :
745              "elm.swallow.arrow_left"), sd->arrow);
746
747         if (base_size.h > 0)
748           {
749              if (y <= ((arrow_size.h * 0.5) + base_size.y + shadow_left_top.h + arrow_padding.h))
750                y = 0;
751              else if (y >= (base_size.y + base_size.h - ((arrow_size.h * 0.5) + shadow_right_bottom.h + arrow_padding.h)))
752                y = base_size.h - (arrow_size.h + shadow_right_bottom.h + shadow_left_top.h + (arrow_padding.h * 2));
753              else
754                y = y - base_size.y - ((arrow_size.h * 0.5) + shadow_left_top.h + arrow_padding.h);
755              drag = (double)(y) / (double)(base_size.h - (arrow_size.h + shadow_right_bottom.h + shadow_left_top.h + (arrow_padding.h * 2)));
756              edje_object_part_drag_value_set
757                 (wd->resize_obj,
758                  (elm_widget_mirrored_get(obj) ? "elm.swallow.arrow_right" :
759                   "elm.swallow.arrow_left"), 1, drag);
760           }
761         break;
762
763       case ELM_CTXPOPUP_DIRECTION_LEFT:
764         edje_object_signal_emit(sd->arrow, "elm,state,right", "elm");
765         edje_object_part_swallow
766            (wd->resize_obj,
767             (elm_widget_mirrored_get(obj) ? "elm.swallow.arrow_left" :
768              "elm.swallow.arrow_right"), sd->arrow);
769
770         if (base_size.h > 0)
771           {
772              if (y <= ((arrow_size.h * 0.5) + base_size.y + shadow_left_top.h + arrow_padding.h))
773                y = 0;
774              else if (y >= (base_size.y + base_size.h - ((arrow_size.h * 0.5) + shadow_right_bottom.h + arrow_padding.h)))
775                y = base_size.h - (arrow_size.h + shadow_right_bottom.h + shadow_left_top.h + (arrow_padding.h * 2));
776              else
777                y = y - base_size.y - ((arrow_size.h * 0.5) + shadow_left_top.h + arrow_padding.h);
778              drag = (double)(y) / (double)(base_size.h - (arrow_size.h + shadow_right_bottom.h + shadow_left_top.h + (arrow_padding.h * 2)));
779              edje_object_part_drag_value_set
780                 (wd->resize_obj,
781                  (elm_widget_mirrored_get(obj) ? "elm.swallow.arrow_left" :
782                   "elm.swallow.arrow_right"), 0, drag);
783           }
784         break;
785
786       case ELM_CTXPOPUP_DIRECTION_DOWN:
787         edje_object_signal_emit(sd->arrow, "elm,state,top", "elm");
788         edje_object_part_swallow
789           (wd->resize_obj, "elm.swallow.arrow_up",
790           sd->arrow);
791
792         if (base_size.w > 0)
793           {
794              if (x <= ((arrow_size.w * 0.5) + base_size.x + shadow_left_top.w + arrow_padding.w))
795                x = 0;
796              else if (x >= (base_size.x + base_size.w - ((arrow_size.w * 0.5) + shadow_right_bottom.w + arrow_padding.w)))
797                x = base_size.w - (arrow_size.w + shadow_right_bottom.w + shadow_left_top.w + (arrow_padding.w * 2));
798              else
799                x = x - base_size.x - ((arrow_size.w * 0.5) + shadow_left_top.w + arrow_padding.w);
800              drag = (double)(x) / (double)(base_size.w - (arrow_size.w + shadow_right_bottom.w + shadow_left_top.w + (arrow_padding.w * 2)));
801              edje_object_part_drag_value_set
802                (wd->resize_obj, "elm.swallow.arrow_up",
803                drag, 1);
804           }
805         break;
806
807       case ELM_CTXPOPUP_DIRECTION_UP:
808         edje_object_signal_emit(sd->arrow, "elm,state,bottom", "elm");
809         edje_object_part_swallow
810           (wd->resize_obj, "elm.swallow.arrow_down",
811           sd->arrow);
812
813         if (base_size.w > 0)
814           {
815              if (x <= ((arrow_size.w * 0.5) + base_size.x + shadow_left_top.w + arrow_padding.w))
816                x = 0;
817              else if (x >= (base_size.x + base_size.w - ((arrow_size.w * 0.5) + shadow_right_bottom.w + arrow_padding.w)))
818                x = base_size.w - (arrow_size.w + shadow_right_bottom.w + shadow_left_top.w + (arrow_padding.w * 2));
819              else
820                x = x - base_size.x - ((arrow_size.w * 0.5) + shadow_left_top.w + arrow_padding.w);
821              drag = (double)(x) / (double)(base_size.w - (arrow_size.w + shadow_right_bottom.w + shadow_left_top.w + (arrow_padding.w * 2)));
822              edje_object_part_drag_value_set
823                (wd->resize_obj, "elm.swallow.arrow_down",
824                drag, 0);
825           }
826         break;
827
828       default:
829         break;
830      }
831
832    //should be here for getting accurate geometry value
833    evas_object_smart_calculate(wd->resize_obj);
834 }
835
836 static void
837 _show_signals_emit(Evas_Object *obj,
838                    Elm_Ctxpopup_Direction dir)
839 {
840    ELM_CTXPOPUP_DATA_GET(obj, sd);
841
842    if (!sd->visible) return;
843
844    switch (dir)
845      {
846       case ELM_CTXPOPUP_DIRECTION_UP:
847         edje_object_signal_emit(sd->layout, "elm,state,show,up", "elm");
848         break;
849
850       case ELM_CTXPOPUP_DIRECTION_LEFT:
851         edje_object_signal_emit(sd->layout, (elm_widget_mirrored_get(obj) ? "elm,state,show,right" :
852                "elm,state,show,left"), "elm");
853         break;
854
855       case ELM_CTXPOPUP_DIRECTION_RIGHT:
856         edje_object_signal_emit(sd->layout, (elm_widget_mirrored_get(obj) ? "elm,state,show,left" :
857                "elm,state,show,right"), "elm");
858         break;
859
860       case ELM_CTXPOPUP_DIRECTION_DOWN:
861         edje_object_signal_emit(sd->layout, "elm,state,show,down", "elm");
862         break;
863
864       default:
865         break;
866      }
867
868    edje_object_signal_emit(sd->bg, "elm,state,show", "elm");
869 }
870
871 static void
872 _hide_signals_emit(Evas_Object *obj,
873                    Elm_Ctxpopup_Direction dir)
874 {
875    ELM_CTXPOPUP_DATA_GET(obj, sd);
876
877    if (!sd->visible) return;
878
879    switch (dir)
880      {
881       case ELM_CTXPOPUP_DIRECTION_UP:
882         edje_object_signal_emit(sd->layout, "elm,state,hide,up", "elm");
883         break;
884
885       case ELM_CTXPOPUP_DIRECTION_LEFT:
886         edje_object_signal_emit(sd->layout, (elm_widget_mirrored_get(obj) ? "elm,state,hide,right" :
887                "elm,state,hide,left"), "elm");
888         break;
889
890       case ELM_CTXPOPUP_DIRECTION_RIGHT:
891         edje_object_signal_emit(sd->layout, (elm_widget_mirrored_get(obj) ? "elm,state,hide,left" :
892                "elm,state,hide,right"), "elm");
893         break;
894
895       case ELM_CTXPOPUP_DIRECTION_DOWN:
896         edje_object_signal_emit(sd->layout, "elm,state,hide,down", "elm");
897         break;
898
899       default:
900         break;
901      }
902
903    edje_object_signal_emit(sd->bg, "elm,state,hide", "elm");
904 }
905
906 static void
907 _base_shift_by_arrow(Evas_Object *obj,
908                      Evas_Object *arrow,
909                      Elm_Ctxpopup_Direction dir,
910                      Evas_Coord_Rectangle *rect)
911 {
912    ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
913
914    Evas_Coord arrow_w, arrow_h, diff_w, diff_h;
915    Evas_Coord_Rectangle shadow_left_top, shadow_right_bottom;
916
917    evas_object_geometry_get(arrow, NULL, NULL, &arrow_w, &arrow_h);
918    /* tizen only: since ctxpopup of tizen has shadow parts, start and end padding of arrow, it should be put together when shifting ctxpopup by arrow
919     * so there are some differences between opensource and tizen*/
920    edje_object_part_geometry_get(wd->resize_obj, "frame_shadow_left_top_padding", NULL, NULL, &shadow_left_top.w, &shadow_left_top.h);
921    edje_object_part_geometry_get(wd->resize_obj, "frame_shadow_right_bottom_padding", NULL, NULL, &shadow_right_bottom.w, &shadow_right_bottom.h);
922    //
923
924    switch (dir)
925      {
926       case ELM_CTXPOPUP_DIRECTION_RIGHT:
927         diff_w = arrow_w - shadow_right_bottom.w;
928         rect->x += diff_w;
929         break;
930
931       case ELM_CTXPOPUP_DIRECTION_LEFT:
932         diff_w = arrow_w - shadow_left_top.w;
933         rect->x -= diff_w;
934         break;
935
936       case ELM_CTXPOPUP_DIRECTION_DOWN:
937         diff_h = arrow_h - shadow_left_top.h;
938         rect->y += diff_h;
939         break;
940
941       case ELM_CTXPOPUP_DIRECTION_UP:
942         diff_h = arrow_h - shadow_right_bottom.h;
943         rect->y -= diff_h;
944         break;
945
946       default:
947          break;
948      }
949 }
950
951 EOLIAN static Eina_Bool
952 _elm_ctxpopup_elm_layout_sub_object_add_enable(Eo *obj EINA_UNUSED, Elm_Ctxpopup_Data *_pd EINA_UNUSED)
953 {
954    return EINA_FALSE;
955 }
956
957 EOLIAN static Eina_Bool
958 _elm_ctxpopup_elm_widget_sub_object_add(Eo *obj, Elm_Ctxpopup_Data *_pd EINA_UNUSED, Evas_Object *sobj)
959 {
960    Eina_Bool int_ret = EINA_FALSE;
961
962    eo_do_super(obj, MY_CLASS, int_ret = elm_obj_widget_sub_object_add(sobj));
963
964    return int_ret;
965 }
966
967 EOLIAN static void
968 _elm_ctxpopup_elm_layout_sizing_eval(Eo *obj, Elm_Ctxpopup_Data *sd)
969 {
970    Eina_List *elist;
971    Elm_Ctxpopup_Item_Data *item;
972    Evas_Coord_Rectangle rect = { 0, 0, 1, 1 };
973    Evas_Coord_Point box_size = { 0, 0 };
974    Evas_Coord_Point _box_size = { 0, 0 };
975    Evas_Coord maxw = 0;
976    Evas_Coord x, y, w, h;
977    const char *str;
978
979    ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
980
981    if (!sd->parent || !(sd->items || sd->content)) return;
982
983    //Box, Scroller
984    EINA_LIST_FOREACH(sd->items, elist, item)
985      {
986         _item_sizing_eval(item);
987         evas_object_size_hint_min_get(VIEW(item), &_box_size.x, &_box_size.y);
988
989         str = edje_object_data_get(VIEW(item), "item_max_size");
990         if (str)
991           {
992              maxw = atoi(str);
993              maxw = maxw * elm_config_scale_get()
994                              * elm_widget_scale_get(obj)
995                              / edje_object_base_scale_get(VIEW(item));
996
997              if (_box_size.x > maxw)
998                {
999                   edje_object_signal_emit(VIEW(item), "elm,state,text,ellipsis", "elm");
1000                   edje_object_message_signal_process(VIEW(item));
1001                }
1002           }
1003
1004         if (!sd->horizontal)
1005           {
1006              if (_box_size.x > box_size.x)
1007                box_size.x = _box_size.x;
1008              if (_box_size.y != -1)
1009                box_size.y += _box_size.y;
1010           }
1011         else
1012           {
1013              if (_box_size.x != -1)
1014                box_size.x += _box_size.x;
1015              if (_box_size.y > box_size.y)
1016                box_size.y = _box_size.y;
1017           }
1018      }
1019
1020 //   if (!sd->arrow) return;  /* simple way to flag "under deletion" */
1021
1022    if ((!sd->content) && (sd->scr))
1023      {
1024         evas_object_size_hint_min_set(sd->box, box_size.x, box_size.y);
1025         elm_scroller_content_min_limit(sd->scr, EINA_TRUE, EINA_TRUE);
1026         evas_object_size_hint_min_set(sd->scr, box_size.x, box_size.y);
1027      }
1028
1029    //Base
1030    sd->dir = _base_geometry_calc(obj, &rect);
1031
1032    _arrow_update(obj, sd->dir, rect);
1033    _base_shift_by_arrow(obj, sd->arrow, sd->dir, &rect);
1034
1035    //resize scroller according to final size
1036    if ((!sd->content) && (sd->scr))
1037      {
1038         elm_scroller_content_min_limit(sd->scr, EINA_FALSE, EINA_FALSE);
1039         evas_object_smart_calculate(sd->scr);
1040      }
1041
1042    evas_object_resize(obj, rect.w, rect.h);
1043    evas_object_size_hint_min_set(wd->resize_obj, rect.w, rect.h);
1044
1045    evas_object_resize(sd->layout, rect.w, rect.h);
1046    evas_object_move(sd->layout, rect.x, rect.y);
1047
1048    evas_object_geometry_get(sd->parent, &x, &y, &w, &h);
1049    evas_object_move(sd->bg, x, y);
1050    evas_object_resize(sd->bg, w, h);
1051 }
1052
1053 static void
1054 _on_parent_del(void *data,
1055                Evas *e EINA_UNUSED,
1056                Evas_Object *obj EINA_UNUSED,
1057                void *event_info EINA_UNUSED)
1058 {
1059    evas_object_del(data);
1060 }
1061
1062 static void
1063 _on_parent_move(void *data,
1064                 Evas *e EINA_UNUSED,
1065                 Evas_Object *obj EINA_UNUSED,
1066                 void *event_info EINA_UNUSED)
1067 {
1068    ELM_CTXPOPUP_DATA_GET(data, sd);
1069
1070
1071    sd->dir = ELM_CTXPOPUP_DIRECTION_UNKNOWN;
1072
1073    if (sd->visible)
1074      elm_layout_sizing_eval(data);
1075 }
1076
1077 static void
1078 _on_parent_resize(void *data,
1079                   Evas *e EINA_UNUSED,
1080                   Evas_Object *obj EINA_UNUSED,
1081                   void *event_info EINA_UNUSED)
1082 {
1083    ELM_CTXPOPUP_DATA_GET(data, sd);
1084    ELM_WIDGET_DATA_GET_OR_RETURN(data, wd);
1085
1086    if (sd->auto_hide)
1087      {
1088         sd->dir = ELM_CTXPOPUP_DIRECTION_UNKNOWN;
1089
1090         evas_object_hide(data);
1091         eo_do(data, eo_event_callback_call(ELM_CTXPOPUP_EVENT_DISMISSED, NULL));
1092      }
1093    else
1094      {
1095         if (wd->orient_mode == 90 || wd->orient_mode == 270)
1096          elm_widget_theme_object_set
1097            (data, sd->layout, "ctxpopup", "layout/landscape", elm_widget_style_get(data));
1098         else
1099          elm_widget_theme_object_set
1100            (data, sd->layout, "ctxpopup", "layout", elm_widget_style_get(data));
1101         edje_object_part_swallow(sd->layout, "swallow", wd->resize_obj);
1102
1103         if (sd->visible)
1104           elm_layout_sizing_eval(data);
1105
1106         _show_signals_emit(data, sd->dir);
1107      }
1108 }
1109
1110 static void
1111 _parent_detach(Evas_Object *obj)
1112 {
1113    ELM_CTXPOPUP_DATA_GET(obj, sd);
1114
1115    if (!sd->parent) return;
1116
1117    evas_object_event_callback_del_full
1118      (sd->parent, EVAS_CALLBACK_DEL, _on_parent_del, obj);
1119    evas_object_event_callback_del_full
1120      (sd->parent, EVAS_CALLBACK_MOVE, _on_parent_move, obj);
1121    evas_object_event_callback_del_full
1122      (sd->parent, EVAS_CALLBACK_RESIZE, _on_parent_resize, obj);
1123 }
1124
1125 static void
1126 _on_content_resized(void *data,
1127                     Evas *e EINA_UNUSED,
1128                     Evas_Object *obj EINA_UNUSED,
1129                     void *event_info EINA_UNUSED)
1130 {
1131    elm_layout_sizing_eval(data);
1132 }
1133
1134 static void
1135 _access_outline_activate_cb(void *data,
1136                         Evas_Object *part_obj EINA_UNUSED,
1137                         Elm_Object_Item *item EINA_UNUSED)
1138 {
1139    evas_object_hide(data);
1140    eo_do(data, eo_event_callback_call(ELM_CTXPOPUP_EVENT_DISMISSED, NULL));
1141 }
1142
1143 static void
1144 _access_obj_process(Evas_Object *obj, Eina_Bool is_access)
1145 {
1146    Evas_Object *ao;
1147    ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
1148
1149    if (is_access)
1150      {
1151         ao = _access_object_get(obj, ACCESS_OUTLINE_PART);
1152         if (!ao)
1153           {
1154              ao = _elm_access_edje_object_part_object_register
1155                 (obj, wd->resize_obj, ACCESS_OUTLINE_PART);
1156
1157              const char *style = elm_widget_style_get(obj);
1158              if (!strcmp(style, "more/default"))
1159                {
1160                   elm_access_info_set(ao, ELM_ACCESS_TYPE, TTS_STR_MENU_POPUP);
1161                   elm_access_info_set(ao, ELM_ACCESS_CONTEXT_INFO, TTS_STR_MENU_CLOSE);
1162                }
1163              else
1164                {
1165                   elm_access_info_set(ao, ELM_ACCESS_TYPE, E_("Contextual popup"));
1166                   elm_access_info_set(ao, ELM_ACCESS_CONTEXT_INFO, E_("Double tap to close popup"));
1167                }
1168              _elm_access_activate_callback_set
1169                 (_elm_access_info_get(ao), _access_outline_activate_cb, obj);
1170           }
1171      }
1172    else
1173      {
1174         _elm_access_edje_object_part_object_unregister
1175                (obj, wd->resize_obj, ACCESS_OUTLINE_PART);
1176      }
1177 }
1178
1179 static void
1180 _mirrored_set(Evas_Object *obj, Eina_Bool rtl)
1181 {
1182    ELM_CTXPOPUP_DATA_GET(obj, sd);
1183    ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
1184
1185    edje_object_mirrored_set(sd->layout, rtl);
1186    edje_object_mirrored_set(sd->arrow, rtl);
1187    edje_object_mirrored_set(wd->resize_obj, rtl);
1188 }
1189
1190 EOLIAN static Eina_Bool
1191 _elm_ctxpopup_elm_widget_event(Eo *obj, Elm_Ctxpopup_Data *sd, Evas_Object *src EINA_UNUSED, Evas_Callback_Type type, void *event_info)
1192 {
1193    Evas_Event_Key_Down *ev = event_info;
1194
1195    // TIZEN ONLY(20131221) : When access mode, focused ui is disabled.
1196    if (_elm_config->access_mode) return EINA_FALSE;
1197
1198    if (elm_widget_disabled_get(obj)) return EINA_FALSE;
1199    if (type != EVAS_CALLBACK_KEY_DOWN) return EINA_FALSE;
1200    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return EINA_FALSE;
1201
1202    //FIXME: for this key event, _elm_ctxpopup_smart_focus_next should be done first
1203    if ((!strcmp(ev->key, "Tab")) ||
1204        (!strcmp(ev->key, "ISO_Left_Tab")))
1205      {
1206         Eina_Bool ret;
1207         Evas_Object *target = NULL;
1208         Elm_Object_Item *target_item = NULL;
1209         Elm_Focus_Direction dir;
1210
1211         if (evas_key_modifier_is_set(ev->modifiers, "Control") ||
1212             evas_key_modifier_is_set(ev->modifiers, "Alt"))
1213           return EINA_FALSE;
1214         if (evas_key_modifier_is_set(ev->modifiers, "Shift"))
1215           dir = ELM_FOCUS_PREVIOUS;
1216         else
1217           dir = ELM_FOCUS_NEXT;
1218
1219         ret = elm_widget_focus_next_get(sd->box, dir, &target, &target_item);
1220         if (ret) elm_widget_focus_steal(target, target_item);
1221
1222         ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1223         return EINA_TRUE;
1224      }
1225    /////
1226    if (((!strcmp(ev->key, "Left")) ||
1227         (!strcmp(ev->key, "KP_Left")) ||
1228         (!strcmp(ev->key, "Right")) ||
1229         (!strcmp(ev->key, "KP_Right")) ||
1230         (!strcmp(ev->key, "Up")) ||
1231         (!strcmp(ev->key, "KP_Up")) ||
1232         (!strcmp(ev->key, "Down")) ||
1233         (!strcmp(ev->key, "KP_Down"))) && (!ev->string))
1234      {
1235         double degree = 0.0;
1236
1237         if ((!strcmp(ev->key, "Left")) ||
1238             (!strcmp(ev->key, "KP_Left")))
1239           degree = 270.0;
1240         else if ((!strcmp(ev->key, "Right")) ||
1241                  (!strcmp(ev->key, "KP_Right")))
1242           degree = 90.0;
1243         else if ((!strcmp(ev->key, "Up")) ||
1244                  (!strcmp(ev->key, "KP_Up")))
1245           degree = 0.0;
1246         else if ((!strcmp(ev->key, "Down")) ||
1247                  (!strcmp(ev->key, "KP_Down")))
1248           degree = 180.0;
1249
1250         elm_widget_focus_direction_go(sd->box, degree);
1251         ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1252         return EINA_TRUE;
1253      }
1254    else if (((!strcmp(ev->key, "Home")) ||
1255              (!strcmp(ev->key, "KP_Home")) ||
1256              (!strcmp(ev->key, "Prior")) ||
1257              (!strcmp(ev->key, "KP_Prior"))) && (!ev->string))
1258      {
1259         Elm_Ctxpopup_Item_Data *it = eina_list_data_get(sd->items);
1260         Evas_Object *btn = it->btn;
1261         elm_object_focus_set(btn, EINA_TRUE);
1262         ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1263         return EINA_TRUE;
1264      }
1265    else if (((!strcmp(ev->key, "End")) ||
1266              (!strcmp(ev->key, "KP_End")) ||
1267              (!strcmp(ev->key, "Next")) ||
1268              (!strcmp(ev->key, "KP_Next"))) && (!ev->string))
1269      {
1270         Elm_Ctxpopup_Item_Data *it = eina_list_data_get(eina_list_last(sd->items));
1271         Evas_Object *btn = it->btn;
1272         elm_object_focus_set(btn, EINA_TRUE);
1273         ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1274         return EINA_TRUE;
1275      }
1276
1277    // TIZEN ONLY : 20130530 : ctxpopup will be dismissed by user
1278    //if (strcmp(ev->keyname, "Escape")) return EINA_FALSE;
1279    return EINA_FALSE;
1280
1281 /*
1282    _hide_signals_emit(obj, sd->dir);
1283
1284    ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1285    return EINA_TRUE;
1286 */
1287 }
1288
1289 //FIXME: lost the content size when theme hook is called.
1290 EOLIAN static Elm_Theme_Apply
1291 _elm_ctxpopup_elm_widget_theme_apply(Eo *obj, Elm_Ctxpopup_Data *sd)
1292 {
1293    Eina_List *elist;
1294    Elm_Ctxpopup_Item_Data *item;
1295    int idx = 0;
1296    Eina_Bool rtl;
1297    Eina_Bool tmp;
1298    Elm_Theme_Apply int_ret = ELM_THEME_APPLY_FAILED;
1299
1300    ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd, ELM_THEME_APPLY_FAILED);
1301
1302    eo_do_super(obj, MY_CLASS, int_ret = elm_obj_widget_theme_apply());
1303    if (!int_ret) return ELM_THEME_APPLY_FAILED;
1304
1305    rtl = elm_widget_mirrored_get(obj);
1306
1307    elm_widget_theme_object_set
1308      (obj, sd->bg, "ctxpopup", "bg", elm_widget_style_get(obj));
1309
1310    elm_widget_theme_object_set
1311      (obj, sd->arrow, "ctxpopup", "arrow", elm_widget_style_get(obj));
1312
1313    if (wd->orient_mode == 90 || wd->orient_mode == 270)
1314      elm_widget_theme_object_set
1315        (obj, sd->layout, "ctxpopup", "layout/landscape", elm_widget_style_get(obj));
1316    else
1317      elm_widget_theme_object_set
1318        (obj, sd->layout, "ctxpopup", "layout", elm_widget_style_get(obj));
1319    edje_object_part_swallow(sd->layout, "swallow", wd->resize_obj);
1320
1321    _mirrored_set(obj, rtl);
1322
1323    //Items
1324    EINA_LIST_FOREACH(sd->items, elist, item)
1325      {
1326         edje_object_mirrored_set(VIEW(item), rtl);
1327
1328         if (item->label && item->icon)
1329           {
1330              if (!sd->horizontal)
1331                _elm_theme_object_set(obj, VIEW(item), "ctxpopup",
1332                                      "icon_text_style_item",
1333                                      elm_widget_style_get(obj));
1334              else
1335                _elm_theme_object_set(obj, VIEW(item), "ctxpopup",
1336                                      "icon_text_style_item_horizontal",
1337                                      elm_widget_style_get(obj));
1338           }
1339         else if (item->label)
1340           {
1341              if (!sd->horizontal)
1342                _elm_theme_object_set(obj, VIEW(item), "ctxpopup",
1343                                      "text_style_item",
1344                                      elm_widget_style_get(obj));
1345              else
1346                _elm_theme_object_set(obj, VIEW(item), "ctxpopup",
1347                                      "text_style_item_horizontal",
1348                                      elm_widget_style_get(obj));
1349           }
1350         else if (item->icon)
1351           {
1352              if (!sd->horizontal)
1353                _elm_theme_object_set(obj, VIEW(item), "ctxpopup",
1354                                      "icon_style_item",
1355                                      elm_widget_style_get(obj));
1356              else
1357                _elm_theme_object_set(obj, VIEW(item), "ctxpopup",
1358                                      "icon_style_item_horizontal",
1359                                      elm_widget_style_get(obj));
1360           }
1361
1362         if (item->label)
1363           edje_object_part_text_set(VIEW(item), "elm.text", item->label);
1364
1365         if (eo_do_ret(EO_OBJ(item), tmp, elm_wdg_item_disabled_get()))
1366           edje_object_signal_emit(VIEW(item), "elm,state,disabled", "elm");
1367
1368        /*
1369         *  For separator, if the first item has visible separator,
1370         *  then it should be aligned with edge of the base part.
1371         *  In some cases, it gives improper display. Ex) rounded corner
1372         *  So the first item separator should be invisible.
1373         */
1374         if ((idx++) == 0)
1375           edje_object_signal_emit(VIEW(item), "elm,state,default", "elm");
1376         else
1377           edje_object_signal_emit(VIEW(item), "elm,state,separator", "elm");
1378
1379         // reset state of text to be default
1380         edje_object_signal_emit(VIEW(item), "elm,state,text,default", "elm");
1381         edje_object_message_signal_process(VIEW(item));
1382      }
1383
1384    if (evas_object_visible_get(sd->bg))
1385      edje_object_signal_emit(sd->bg, "elm,state,show", "elm");
1386
1387    if (sd->scr)
1388      {
1389         elm_layout_theme_set(sd->scr, "scroller", "ctxpopup", elm_widget_style_get(obj));
1390
1391         if (sd->horizontal)
1392           elm_scroller_policy_set(sd->scr, ELM_SCROLLER_POLICY_AUTO, ELM_SCROLLER_POLICY_OFF);
1393         else
1394           elm_scroller_policy_set(sd->scr, ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_AUTO);
1395      }
1396
1397    sd->dir = ELM_CTXPOPUP_DIRECTION_UNKNOWN;
1398
1399    if (sd->visible)
1400      elm_layout_sizing_eval(obj);
1401
1402    /* access */
1403   if (_elm_config->access_mode) _access_obj_process(obj, EINA_TRUE);
1404
1405    return int_ret;
1406 }
1407
1408 /* kind of a big and tricky override here: an internal box will hold
1409  * the actual content. content aliases won't be of much help here */
1410 EOLIAN static Eina_Bool
1411 _elm_ctxpopup_elm_container_content_set(Eo *obj, Elm_Ctxpopup_Data *sd, const char *part, Evas_Object *content)
1412 {
1413    Evas_Coord min_w = -1, min_h = -1;
1414    Eina_Bool int_ret = EINA_TRUE;
1415
1416    if ((part) && (strcmp(part, "default")))
1417      {
1418         eo_do_super(obj, MY_CLASS, int_ret = elm_obj_container_content_set(part, content));
1419         return int_ret;
1420      }
1421
1422    if (!content) return EINA_FALSE;
1423
1424    if (content == sd->content) return EINA_TRUE;
1425
1426    if (sd->items) elm_ctxpopup_clear(obj);
1427    if (sd->content) evas_object_del(sd->content);
1428
1429    ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd, EINA_FALSE);
1430
1431    evas_object_event_callback_add
1432       (sd->box, EVAS_CALLBACK_RESIZE, _on_content_resized, obj);
1433    edje_object_part_swallow(wd->resize_obj, "elm.swallow.content", sd->box);
1434
1435    evas_object_size_hint_weight_set
1436      (content, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
1437    evas_object_size_hint_fill_set
1438      (content, EVAS_HINT_FILL, EVAS_HINT_FILL);
1439
1440    /* since it's going to be a box content, not a layout's... */
1441    evas_object_show(content);
1442
1443    evas_object_size_hint_min_get(content, &min_w, &min_h);
1444    evas_object_size_hint_min_set(sd->box, min_w, min_h);
1445    elm_box_pack_end(sd->box, content);
1446
1447    sd->content = content;
1448    sd->dir = ELM_CTXPOPUP_DIRECTION_UNKNOWN;
1449
1450    if (sd->visible) elm_layout_sizing_eval(obj);
1451
1452    return EINA_TRUE;
1453 }
1454
1455 EOLIAN static Evas_Object*
1456 _elm_ctxpopup_elm_container_content_get(Eo *obj, Elm_Ctxpopup_Data *sd, const char *part)
1457 {
1458
1459    if ((part) && (strcmp(part, "default")))
1460      {
1461         Evas_Object *ret = NULL;
1462         eo_do_super(obj, MY_CLASS, ret = elm_obj_container_content_get(part));
1463         return ret;
1464      }
1465
1466    return sd->content;
1467 }
1468
1469 EOLIAN static Evas_Object*
1470 _elm_ctxpopup_elm_container_content_unset(Eo *obj, Elm_Ctxpopup_Data *sd, const char *part)
1471 {
1472    Evas_Object *content = NULL;
1473
1474    if ((part) && (strcmp(part, "default")))
1475      {
1476         eo_do_super(obj, MY_CLASS, content = elm_obj_container_content_unset(part));
1477         return content;
1478      }
1479
1480    content = sd->content;
1481    if (!content) return content;
1482
1483    elm_box_unpack(sd->box, content);
1484    sd->content = NULL;
1485    sd->dir = ELM_CTXPOPUP_DIRECTION_UNKNOWN;
1486
1487    if (sd->visible) elm_layout_sizing_eval(obj);
1488
1489    return content;
1490 }
1491
1492 EOLIAN static void
1493 _elm_ctxpopup_item_elm_widget_item_part_text_set(Eo *eo_ctxpopup_it EINA_UNUSED,
1494                                                  Elm_Ctxpopup_Item_Data *ctxpopup_it,
1495                                                  const char *part,
1496                                                  const char *label)
1497 {
1498    if ((part) && (strcmp(part, "default"))) return;
1499
1500    _item_label_set(ctxpopup_it, label);
1501 }
1502
1503 EOLIAN static const char *
1504 _elm_ctxpopup_item_elm_widget_item_part_text_get(Eo *eo_ctxpopup_it EINA_UNUSED,
1505                                                  Elm_Ctxpopup_Item_Data *ctxpopup_it,
1506                                                  const char *part)
1507 {
1508    if (part && strcmp(part, "default")) return NULL;
1509
1510    return ctxpopup_it->label;
1511 }
1512
1513 EOLIAN static void
1514 _elm_ctxpopup_item_elm_widget_item_part_content_set(Eo *eo_ctxpopup_it EINA_UNUSED,
1515                                                     Elm_Ctxpopup_Item_Data *ctxpopup_it,
1516                                                     const char *part,
1517                                                     Evas_Object *content)
1518 {
1519    if ((part) && (strcmp(part, "icon"))) return;
1520
1521    ELM_CTXPOPUP_DATA_GET(WIDGET(ctxpopup_it), sd);
1522
1523    _item_icon_set(ctxpopup_it, content);
1524    sd->dir = ELM_CTXPOPUP_DIRECTION_UNKNOWN;
1525
1526    if (sd->visible)
1527      elm_layout_sizing_eval(WIDGET(ctxpopup_it));
1528 }
1529
1530 EOLIAN static Evas_Object *
1531 _elm_ctxpopup_item_elm_widget_item_part_content_get(Eo *eo_ctxpopup_it EINA_UNUSED,
1532                                                     Elm_Ctxpopup_Item_Data *ctxpopup_it,
1533                                                     const char *part)
1534 {
1535    if (part && strcmp(part, "icon")) return NULL;
1536
1537    return ctxpopup_it->icon;
1538 }
1539
1540 EOLIAN static void
1541 _elm_ctxpopup_item_elm_widget_item_disable(Eo *eo_ctxpopup_it,
1542                                            Elm_Ctxpopup_Item_Data *ctxpopup_it)
1543 {
1544    ELM_CTXPOPUP_DATA_GET(WIDGET(ctxpopup_it), sd);
1545    Eina_Bool tmp;
1546    if (!sd) return;
1547
1548    if (eo_do_ret(eo_ctxpopup_it, tmp, elm_wdg_item_disabled_get()))
1549      edje_object_signal_emit(VIEW(ctxpopup_it), "elm,state,disabled", "elm");
1550    else
1551      edje_object_signal_emit(VIEW(ctxpopup_it), "elm,state,enabled", "elm");
1552 }
1553
1554 EOLIAN static void
1555 _elm_ctxpopup_item_elm_widget_item_signal_emit(Eo *eo_ctxpopup_it EINA_UNUSED,
1556                                                Elm_Ctxpopup_Item_Data *ctxpopup_it,
1557                                                const char *emission,
1558                                                const char *source)
1559 {
1560    edje_object_signal_emit(VIEW(ctxpopup_it), emission, source);
1561 }
1562
1563 EOLIAN static void
1564 _elm_ctxpopup_item_elm_widget_item_style_set(Eo *eo_item EINA_UNUSED,
1565                                              Elm_Ctxpopup_Item_Data *item,
1566                                              const char *style)
1567 {
1568    ELM_CTXPOPUP_DATA_GET(WIDGET(item), sd);
1569
1570    if (item->icon && item->label)
1571      {
1572         if (sd->horizontal)
1573           _elm_theme_object_set(WIDGET(item), VIEW(item), "ctxpopup", "icon_text_style_item_horizontal", style);
1574         else
1575           _elm_theme_object_set(WIDGET(item), VIEW(item), "ctxpopup", "icon_text_style_item", style);
1576      }
1577    else if (item->label)
1578      {
1579         if (sd->horizontal)
1580           _elm_theme_object_set(WIDGET(item), VIEW(item), "ctxpopup", "text_style_item_horizontal", style);
1581         else
1582           _elm_theme_object_set(WIDGET(item), VIEW(item), "ctxpopup", "text_style_item", style);
1583      }
1584    else if (item->icon)
1585      {
1586         if (sd->horizontal)
1587           _elm_theme_object_set(WIDGET(item), VIEW(item), "ctxpopup", "icon_style_item_horizontal", style);
1588         else
1589           _elm_theme_object_set(WIDGET(item), VIEW(item), "ctxpopup", "icon_style_item", style);
1590      }
1591
1592    if (sd->visible) elm_layout_sizing_eval(WIDGET(item));
1593 }
1594
1595 static void
1596 _bg_clicked_cb(void *data,
1597                Evas_Object *obj EINA_UNUSED,
1598                const char *emission EINA_UNUSED,
1599                const char *source EINA_UNUSED)
1600 {
1601    ELM_CTXPOPUP_DATA_GET(data, sd);
1602
1603    _hide_signals_emit(data, sd->dir);
1604 }
1605
1606 static void
1607 _on_show(void *data EINA_UNUSED,
1608          Evas *e EINA_UNUSED,
1609          Evas_Object *obj,
1610          void *event_info EINA_UNUSED)
1611 {
1612    Eina_List *elist;
1613    Elm_Ctxpopup_Item_Data *item;
1614    int idx = 0;
1615
1616    ELM_CTXPOPUP_DATA_GET(obj, sd);
1617    ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
1618
1619    if ((!sd->items) && (!sd->content)) return;
1620
1621    sd->visible = EINA_TRUE;
1622
1623    elm_layout_signal_emit(obj, "elm,state,show", "elm");
1624
1625    if (wd->orient_mode == 90 || wd->orient_mode == 270)
1626      elm_widget_theme_object_set
1627        (obj, sd->layout, "ctxpopup", "layout/landscape", elm_widget_style_get(obj));
1628    else
1629      elm_widget_theme_object_set
1630        (obj, sd->layout, "ctxpopup", "layout", elm_widget_style_get(obj));
1631    edje_object_part_swallow(sd->layout, "swallow", wd->resize_obj);
1632
1633    EINA_LIST_FOREACH(sd->items, elist, item)
1634      {
1635         if (item->label && !item->icon)
1636           {
1637              if (!sd->horizontal)
1638                _elm_theme_object_set(obj, VIEW(item), "ctxpopup",
1639                                      "text_style_item",
1640                                      elm_widget_style_get(obj));
1641              else
1642                _elm_theme_object_set(obj, VIEW(item), "ctxpopup",
1643                                      "text_style_item_horizontal",
1644                                      elm_widget_style_get(obj));
1645           }
1646         else if (item->label)
1647           {
1648              if (!sd->horizontal)
1649                _elm_theme_object_set(obj, VIEW(item), "ctxpopup",
1650                                      "label_style_item",
1651                                      elm_widget_style_get(obj));
1652              else
1653                _elm_theme_object_set(obj, VIEW(item), "ctxpopup",
1654                                      "label_style_item_horizontal",
1655                                      elm_widget_style_get(obj));
1656           }
1657         else if (item->icon)
1658           {
1659              if (!sd->horizontal)
1660                _elm_theme_object_set(obj, VIEW(item), "ctxpopup",
1661                                      "icon_style_item",
1662                                      elm_widget_style_get(obj));
1663              else
1664                _elm_theme_object_set(obj, VIEW(item), "ctxpopup",
1665                                      "icon_style_item_horizontal",
1666                                      elm_widget_style_get(obj));
1667           }
1668
1669         if (idx++ == 0)
1670           edje_object_signal_emit(VIEW(item), "elm,state,default", "elm");
1671         else
1672           edje_object_signal_emit(VIEW(item), "elm,state,separator", "elm");
1673      }
1674
1675    elm_layout_sizing_eval(obj);
1676
1677    elm_object_focus_set(obj, EINA_TRUE);
1678    _show_signals_emit(obj, sd->dir);
1679 }
1680
1681 EOLIAN static void
1682 _elm_ctxpopup_item_elm_widget_item_focus_set(Eo *eo_ctxpopup_it EINA_UNUSED,
1683                                              Elm_Ctxpopup_Item_Data *ctxpopup_it,
1684                                              Eina_Bool focused)
1685 {
1686    elm_object_focus_set(ctxpopup_it->btn, focused);
1687 }
1688
1689 EOLIAN static Eina_Bool
1690 _elm_ctxpopup_item_elm_widget_item_focus_get(Eo *eo_ctxpopup_it EINA_UNUSED,
1691                                              Elm_Ctxpopup_Item_Data *ctxpopup_it)
1692 {
1693    return elm_object_focus_get(ctxpopup_it->btn);
1694 }
1695
1696 static void
1697 _on_hide(void *data EINA_UNUSED,
1698          Evas *e EINA_UNUSED,
1699          Evas_Object *obj,
1700          void *event_info EINA_UNUSED)
1701 {
1702    ELM_CTXPOPUP_DATA_GET(obj, sd);
1703
1704    if (!sd->visible) return;
1705
1706    sd->visible = EINA_FALSE;
1707 }
1708
1709 static void
1710 _on_move(void *data EINA_UNUSED,
1711          Evas *e EINA_UNUSED,
1712          Evas_Object *obj,
1713          void *event_info EINA_UNUSED)
1714 {
1715    ELM_CTXPOPUP_DATA_GET(obj, sd);
1716
1717    if (sd->visible) elm_layout_sizing_eval(obj);
1718 }
1719
1720 static void
1721 _hide_finished_cb(void *data,
1722                   Evas_Object *obj EINA_UNUSED,
1723                   const char *emission EINA_UNUSED,
1724                   const char *source EINA_UNUSED)
1725 {
1726    evas_object_hide(data);
1727    eo_do(data, eo_event_callback_call(ELM_CTXPOPUP_EVENT_DISMISSED, NULL));
1728 }
1729
1730 /* TIZEN_ONLY(20161207): add show finished callback */
1731 static void
1732 _show_finished_cb(void *data,
1733                   Evas_Object *obj EINA_UNUSED,
1734                   const char *emission EINA_UNUSED,
1735                   const char *source EINA_UNUSED)
1736 {
1737    elm_object_focus_set(data, EINA_TRUE);
1738 }
1739 /* END */
1740
1741 static void
1742 _list_del(Eo *obj, Elm_Ctxpopup_Data *sd)
1743 {
1744    if (!sd->scr) return;
1745
1746    ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
1747
1748    edje_object_part_unswallow(wd->resize_obj, sd->scr);
1749    evas_object_del(sd->scr);
1750    sd->scr = NULL;
1751    evas_object_del(sd->box);
1752    sd->box = NULL;
1753 }
1754
1755 static void
1756 _list_new(Evas_Object *obj)
1757 {
1758    ELM_CTXPOPUP_DATA_GET(obj, sd);
1759    if (!sd) return;
1760
1761    ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
1762    //scroller
1763    sd->scr = elm_scroller_add(obj);
1764    elm_layout_theme_set(sd->scr, "scroller", "ctxpopup", elm_widget_style_get(obj));
1765    evas_object_size_hint_align_set(sd->scr, EVAS_HINT_FILL, EVAS_HINT_FILL);
1766    _elm_widget_color_class_parent_set(sd->scr, obj);
1767
1768    if (sd->horizontal)
1769      elm_scroller_policy_set(sd->scr, ELM_SCROLLER_POLICY_AUTO, ELM_SCROLLER_POLICY_OFF);
1770    else
1771      elm_scroller_policy_set(sd->scr, ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_AUTO);
1772
1773    edje_object_part_swallow(wd->resize_obj, "elm.swallow.content", sd->scr);
1774    //TIZEN ONLY(20161014) : Accessibility: scroll the content when highlight frame goes out of view port
1775    evas_object_smart_callback_add(sd->scr, "scroll,down", _content_move_down_cb, (void*)obj);
1776    evas_object_smart_callback_add(sd->scr, "scroll,up", _content_move_up_cb, (void*)obj);
1777    //
1778    elm_object_content_set(sd->scr, sd->box);
1779    elm_ctxpopup_horizontal_set(obj, sd->horizontal);
1780 }
1781
1782 EOLIAN static Eina_Bool
1783 _elm_ctxpopup_elm_widget_disable(Eo *obj, Elm_Ctxpopup_Data *sd)
1784 {
1785    Eina_List *l;
1786    Elm_Ctxpopup_Item_Data *it;
1787    Eina_Bool int_ret = EINA_FALSE;
1788
1789    eo_do_super(obj, MY_CLASS, int_ret = elm_obj_widget_disable());
1790    if (!int_ret) return EINA_FALSE;
1791
1792    EINA_LIST_FOREACH(sd->items, l, it)
1793      elm_object_item_disabled_set(EO_OBJ(it), elm_widget_disabled_get(obj));
1794
1795    return EINA_TRUE;
1796 }
1797
1798 EOLIAN static void
1799 _elm_ctxpopup_evas_object_smart_add(Eo *obj, Elm_Ctxpopup_Data *priv)
1800 {
1801    ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
1802
1803    eo_do_super(obj, MY_CLASS, evas_obj_smart_add());
1804
1805    if (!elm_widget_sub_object_parent_add(obj))
1806      ERR("could not add %p as sub object of %p", obj, elm_object_parent_widget_get(obj));
1807
1808    elm_layout_theme_set(obj, "ctxpopup", "base", elm_widget_style_get(obj));
1809
1810    //Background
1811    priv->bg = edje_object_add(evas_object_evas_get(obj));
1812    elm_widget_theme_object_set(obj, priv->bg, "ctxpopup", "bg", "default");
1813    edje_object_signal_callback_add
1814      (priv->bg, "elm,action,click", "", _bg_clicked_cb, obj);
1815    evas_object_smart_member_add(priv->bg, obj);
1816    evas_object_stack_below(priv->bg, wd->resize_obj);
1817    _elm_widget_color_class_parent_set(priv->bg, obj);
1818
1819    //Arrow
1820    priv->arrow = edje_object_add(evas_object_evas_get(obj));
1821    elm_widget_theme_object_set
1822      (obj, priv->arrow, "ctxpopup", "arrow", "default");
1823    _elm_widget_color_class_parent_set(priv->arrow, obj);
1824
1825    priv->dir_priority[0] = ELM_CTXPOPUP_DIRECTION_UP;
1826    priv->dir_priority[1] = ELM_CTXPOPUP_DIRECTION_LEFT;
1827    priv->dir_priority[2] = ELM_CTXPOPUP_DIRECTION_RIGHT;
1828    priv->dir_priority[3] = ELM_CTXPOPUP_DIRECTION_DOWN;
1829    priv->dir = ELM_CTXPOPUP_DIRECTION_UNKNOWN;
1830
1831    priv->auto_hide = EINA_TRUE;
1832    priv->mouse_down = EINA_FALSE;
1833    priv->multi_down = 0;
1834
1835    priv->box = elm_box_add(obj);
1836    evas_object_size_hint_weight_set
1837      (priv->box, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
1838
1839    priv->layout = edje_object_add(evas_object_evas_get(obj));
1840    if (wd->orient_mode == 90 || wd->orient_mode == 270)
1841      elm_widget_theme_object_set(obj, priv->layout, "ctxpopup", "layout/landscape", "default");
1842    else
1843      elm_widget_theme_object_set(obj, priv->layout, "ctxpopup", "layout", "default");
1844    evas_object_smart_member_add(priv->layout, obj);
1845    _elm_widget_color_class_parent_set(priv->layout, obj);
1846
1847    edje_object_signal_callback_add
1848      (priv->layout, "elm,action,hide,finished", "", _hide_finished_cb, obj);
1849    /* TIZEN_ONLY(20161207): Add show finished callback */
1850    edje_object_signal_callback_add
1851      (priv->layout, "elm,action,show,finished", "", _show_finished_cb, obj);
1852    /* END */
1853
1854    edje_object_part_swallow(priv->layout, "swallow", wd->resize_obj);
1855    evas_object_size_hint_weight_set
1856      (priv->layout, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
1857
1858    evas_object_event_callback_add(obj, EVAS_CALLBACK_SHOW, _on_show, NULL);
1859    evas_object_event_callback_add(obj, EVAS_CALLBACK_HIDE, _on_hide, NULL);
1860    evas_object_event_callback_add(obj, EVAS_CALLBACK_MOVE, _on_move, NULL);
1861
1862    _mirrored_set(obj, elm_widget_mirrored_get(obj));
1863
1864    elm_widget_can_focus_set(obj, EINA_TRUE);
1865    elm_ctxpopup_hover_parent_set(obj, elm_object_parent_widget_get(obj));
1866    /* access */
1867    if (_elm_config->access_mode) _access_obj_process(obj, EINA_TRUE);
1868
1869    /* access: parent could be any object such as elm_list which does
1870       not know elc_ctxpopup as its child object in the focus_next(); */
1871
1872    wd->highlight_root = EINA_TRUE;
1873
1874    //Tizen Only: This should be removed when eo is applied.
1875    wd->on_create = EINA_FALSE;
1876 }
1877
1878 EOLIAN static void
1879 _elm_ctxpopup_evas_object_smart_del(Eo *obj, Elm_Ctxpopup_Data *sd)
1880 {
1881    evas_object_event_callback_del_full
1882      (sd->box, EVAS_CALLBACK_RESIZE, _on_content_resized, obj);
1883    _parent_detach(obj);
1884
1885    if (sd->items)
1886      {
1887         _items_remove(sd);
1888         _list_del(obj, sd);
1889      }
1890    else
1891      {
1892         evas_object_del(sd->box);
1893         sd->box = NULL;
1894      }
1895
1896    evas_object_del(sd->arrow);
1897    sd->arrow = NULL; /* stops _sizing_eval() from going on on deletion */
1898
1899    evas_object_del(sd->bg);
1900    sd->bg = NULL;
1901
1902    evas_object_del(sd->layout);
1903    sd->layout = NULL;
1904
1905    eo_do_super(obj, MY_CLASS, evas_obj_smart_del());
1906 }
1907
1908 EOLIAN static void
1909 _elm_ctxpopup_elm_widget_parent_set(Eo *obj, Elm_Ctxpopup_Data *_pd EINA_UNUSED, Evas_Object *parent)
1910 {
1911    //default parent is to be hover parent
1912    elm_ctxpopup_hover_parent_set(obj, parent);
1913 }
1914
1915 /*
1916 static void
1917 _elm_ctxpopup_smart_access(Evas_Object *obj, Eina_Bool is_access)
1918 {
1919    ELM_CTXPOPUP_CHECK(obj);
1920
1921    _access_obj_process(obj, is_access);
1922
1923    evas_object_smart_callback_call(obj, SIG_ACCESS_CHANGED, NULL);
1924 }
1925
1926 static Evas_Object *
1927 _elm_ctxpopup_smart_access_object_get(Evas_Object *obj, char *part)
1928 {
1929    ELM_CTXPOPUP_CHECK(obj) NULL;
1930
1931    return _access_object_get(obj, part);
1932 }
1933 */
1934
1935 EOLIAN static void
1936 _elm_ctxpopup_class_constructor(Eo_Class *klass)
1937 {
1938    evas_smart_legacy_type_register(MY_CLASS_NAME_LEGACY, klass);
1939 }
1940
1941 EAPI Evas_Object *
1942 elm_ctxpopup_add(Evas_Object *parent)
1943 {
1944    EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
1945    Evas_Object *obj = eo_add(MY_CLASS, parent);
1946
1947    /* access: parent could be any object such as elm_list which does
1948       not know elc_ctxpopup as its child object in the focus_next(); */
1949    ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd, NULL);
1950    wd->highlight_root = EINA_TRUE;
1951
1952    return obj;
1953 }
1954
1955 EOLIAN static Eo *
1956 _elm_ctxpopup_eo_base_constructor(Eo *obj, Elm_Ctxpopup_Data *_pd EINA_UNUSED)
1957 {
1958    obj = eo_do_super_ret(obj, MY_CLASS, obj, eo_constructor());
1959    eo_do(obj,
1960          evas_obj_type_set(MY_CLASS_NAME_LEGACY),
1961          evas_obj_smart_callbacks_descriptions_set(_smart_callbacks),
1962          elm_interface_atspi_accessible_role_set(ELM_ATSPI_ROLE_POPUP_MENU));
1963
1964    return obj;
1965 }
1966
1967
1968 EOLIAN static void
1969 _elm_ctxpopup_hover_parent_set(Eo *obj, Elm_Ctxpopup_Data *sd, Evas_Object *parent)
1970 {
1971    Evas_Coord x, y, w, h;
1972
1973    if (!parent) return;
1974
1975    _parent_detach(obj);
1976
1977    evas_object_event_callback_add
1978      (parent, EVAS_CALLBACK_DEL, _on_parent_del, obj);
1979    evas_object_event_callback_add
1980      (parent, EVAS_CALLBACK_MOVE, _on_parent_move, obj);
1981    evas_object_event_callback_add
1982      (parent, EVAS_CALLBACK_RESIZE, _on_parent_resize, obj);
1983
1984    sd->parent = parent;
1985
1986    //Update Background
1987    evas_object_geometry_get(parent, &x, &y, &w, &h);
1988    evas_object_move(sd->bg, x, y);
1989    evas_object_resize(sd->bg, w, h);
1990
1991    if (sd->visible) elm_layout_sizing_eval(obj);
1992 }
1993
1994 EOLIAN static Evas_Object*
1995 _elm_ctxpopup_hover_parent_get(Eo *obj EINA_UNUSED, Elm_Ctxpopup_Data *sd)
1996 {
1997    return sd->parent;
1998 }
1999
2000 EOLIAN static void
2001 _elm_ctxpopup_clear(Eo *obj, Elm_Ctxpopup_Data *sd)
2002 {
2003    _items_remove(sd);
2004
2005    ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
2006
2007    elm_object_content_unset(sd->scr);
2008    edje_object_part_unswallow(wd->resize_obj, sd->scr);
2009    evas_object_del(sd->scr);
2010    sd->scr = NULL;
2011    sd->dir = ELM_CTXPOPUP_DIRECTION_UNKNOWN;
2012 }
2013
2014 EOLIAN static void
2015 _elm_ctxpopup_horizontal_set(Eo *obj, Elm_Ctxpopup_Data *sd, Eina_Bool horizontal)
2016 {
2017    Eina_List *elist;
2018    Elm_Ctxpopup_Item_Data *item;
2019    int idx = 0;
2020
2021    sd->horizontal = !!horizontal;
2022
2023    if (!sd->scr)
2024       return;
2025
2026   if (!horizontal)
2027      {
2028         elm_box_horizontal_set(sd->box, EINA_FALSE);
2029         elm_scroller_bounce_set(sd->scr, EINA_FALSE, EINA_TRUE);
2030         elm_scroller_policy_set(sd->scr, ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_AUTO);
2031      }
2032    else
2033      {
2034         elm_box_horizontal_set(sd->box, EINA_TRUE);
2035         elm_scroller_bounce_set(sd->scr, EINA_TRUE, EINA_FALSE);
2036         elm_scroller_policy_set(sd->scr, ELM_SCROLLER_POLICY_AUTO, ELM_SCROLLER_POLICY_OFF);
2037      }
2038
2039    EINA_LIST_FOREACH(sd->items, elist, item)
2040      {
2041         if (item->label && !item->icon)
2042           {
2043              if (!sd->horizontal)
2044                _elm_theme_object_set(obj, VIEW(item), "ctxpopup",
2045                                      "text_style_item",
2046                                      elm_widget_style_get(obj));
2047              else
2048                _elm_theme_object_set(obj, VIEW(item), "ctxpopup",
2049                                      "text_style_item_horizontal",
2050                                      elm_widget_style_get(obj));
2051           }
2052         else if (item->label)
2053           {
2054              if (!sd->horizontal)
2055                _elm_theme_object_set(obj, VIEW(item), "ctxpopup",
2056                                      "label_style_item",
2057                                      elm_widget_style_get(obj));
2058              else
2059                _elm_theme_object_set(obj, VIEW(item), "ctxpopup",
2060                                      "label_style_item_horizontal",
2061                                      elm_widget_style_get(obj));
2062           }
2063         else if (item->icon)
2064           {
2065              if (!sd->horizontal)
2066                _elm_theme_object_set(obj, VIEW(item), "ctxpopup",
2067                                      "icon_style_item",
2068                                      elm_widget_style_get(obj));
2069              else
2070                _elm_theme_object_set(obj, VIEW(item), "ctxpopup",
2071                                      "icon_style_item_horizontal",
2072                                      elm_widget_style_get(obj));
2073           }
2074         if (idx++ == 0)
2075           edje_object_signal_emit(VIEW(item), "elm,state,default", "elm");
2076         else
2077           edje_object_signal_emit(VIEW(item), "elm,state,separator", "elm");
2078
2079         eo_do(EO_OBJ(item), elm_wdg_item_disable());
2080      }
2081
2082    sd->dir = ELM_CTXPOPUP_DIRECTION_UNKNOWN;
2083
2084    if (sd->visible) elm_layout_sizing_eval(obj);
2085 }
2086
2087 EOLIAN static Eina_Bool
2088 _elm_ctxpopup_horizontal_get(Eo *obj EINA_UNUSED, Elm_Ctxpopup_Data *sd)
2089 {
2090    return sd->horizontal;
2091 }
2092
2093 EOLIAN static Eo *
2094 _elm_ctxpopup_item_eo_base_constructor(Eo *obj, Elm_Ctxpopup_Item_Data *it)
2095 {
2096    obj = eo_do_super_ret(obj, ELM_CTXPOPUP_ITEM_CLASS, obj, eo_constructor());
2097    it->base = eo_data_scope_get(obj, ELM_WIDGET_ITEM_CLASS);
2098 //TIZEN ONLY(20150710)ctxpopup: Accessible methods for children_get, extents_get and item name_get
2099    eo_do(obj, elm_interface_atspi_accessible_role_set(ELM_ATSPI_ROLE_MENU_ITEM));
2100 //
2101    return obj;
2102 }
2103
2104 EOLIAN static void
2105 _elm_ctxpopup_item_eo_base_destructor(Eo *eo_ctxpopup_it,
2106                                       Elm_Ctxpopup_Item_Data *ctxpopup_it EINA_UNUSED)
2107 {
2108    eo_do_super(eo_ctxpopup_it, ELM_CTXPOPUP_ITEM_CLASS, eo_destructor());
2109 }
2110
2111 EOLIAN static Elm_Object_Item*
2112 _elm_ctxpopup_item_append(Eo *obj, Elm_Ctxpopup_Data *sd, const char *label, Evas_Object *icon, Evas_Smart_Cb func, const void *data)
2113 {
2114    Elm_Ctxpopup_Item_Data *it;
2115    Evas_Object *content, *focus_bt;
2116    int idx = 0;
2117    Eina_List *elist;
2118    Eo *eo_item;
2119
2120    eo_item = eo_add(ELM_CTXPOPUP_ITEM_CLASS, obj, elm_obj_ctxpopup_item_init(func, data));
2121    if (!eo_item) return NULL;
2122
2123    ELM_CTXPOPUP_ITEM_DATA_GET(eo_item, item);
2124
2125    //The first item is appended.
2126    content = elm_object_content_unset(obj);
2127    if (content) evas_object_del(content);
2128
2129    if (!sd->items)
2130      _list_new(obj);
2131
2132    if (icon && label)
2133      {
2134         if (!sd->horizontal)
2135           _item_new(item, "icon_text_style_item");
2136         else
2137           _item_new(item, "icon_text_style_item_horizontal");
2138      }
2139    else if (label)
2140      {
2141         if (!sd->horizontal)
2142           _item_new(item, "text_style_item");
2143         else
2144           _item_new(item, "text_style_item_horizontal");
2145      }
2146    else
2147      {
2148         if (!sd->horizontal)
2149           _item_new(item, "icon_style_item");
2150         else
2151           _item_new(item, "icon_style_item_horizontal");
2152      }
2153
2154    _item_icon_set(item, icon);
2155    _item_label_set(item, label);
2156    focus_bt = _item_in_focusable_button(item);
2157    elm_box_pack_end(sd->box, focus_bt);
2158    sd->items = eina_list_append(sd->items, item);
2159    item->btn = focus_bt;
2160    _elm_widget_color_class_parent_set(VIEW(item), obj);
2161
2162    sd->dir = ELM_CTXPOPUP_DIRECTION_UNKNOWN;
2163
2164    if (sd->visible)
2165      {
2166         EINA_LIST_FOREACH(sd->items, elist, it)
2167           {
2168              if (idx++ == 0)
2169                edje_object_signal_emit(VIEW(it), "elm,state,default", "elm");
2170              else
2171                edje_object_signal_emit(VIEW(it), "elm,state,separator", "elm");
2172           }
2173         elm_layout_sizing_eval(obj);
2174      }
2175
2176    if (_elm_config->access_mode) _access_focusable_button_register(focus_bt, item);
2177
2178    return EO_OBJ(item);
2179 }
2180
2181 EOLIAN static void
2182 _elm_ctxpopup_direction_priority_set(Eo *obj, Elm_Ctxpopup_Data *sd, Elm_Ctxpopup_Direction first, Elm_Ctxpopup_Direction second, Elm_Ctxpopup_Direction third, Elm_Ctxpopup_Direction fourth)
2183 {
2184    sd->dir_priority[0] = first;
2185    sd->dir_priority[1] = second;
2186    sd->dir_priority[2] = third;
2187    sd->dir_priority[3] = fourth;
2188
2189    if (sd->visible) elm_layout_sizing_eval(obj);
2190 }
2191
2192 EOLIAN static void
2193 _elm_ctxpopup_direction_priority_get(Eo *obj EINA_UNUSED, Elm_Ctxpopup_Data *sd, Elm_Ctxpopup_Direction *first, Elm_Ctxpopup_Direction *second, Elm_Ctxpopup_Direction *third, Elm_Ctxpopup_Direction *fourth)
2194 {
2195    if (first) *first = sd->dir_priority[0];
2196    if (second) *second = sd->dir_priority[1];
2197    if (third) *third = sd->dir_priority[2];
2198    if (fourth) *fourth = sd->dir_priority[3];
2199 }
2200
2201 EOLIAN static Elm_Ctxpopup_Direction
2202 _elm_ctxpopup_direction_get(Eo *obj EINA_UNUSED, Elm_Ctxpopup_Data *sd)
2203 {
2204    return sd->dir;
2205 }
2206
2207 EAPI Eina_Bool
2208 elm_ctxpopup_direction_available_get(Evas_Object *obj, Elm_Ctxpopup_Direction direction)
2209 {
2210    ELM_CTXPOPUP_CHECK(obj) EINA_FALSE;
2211    ELM_CTXPOPUP_DATA_GET(obj, sd);
2212
2213    elm_layout_sizing_eval(obj);
2214
2215    if (sd->dir == direction) return EINA_TRUE;
2216    return EINA_FALSE;
2217 }
2218
2219 EOLIAN static void
2220 _elm_ctxpopup_dismiss(Eo *obj, Elm_Ctxpopup_Data *sd)
2221 {
2222    _hide_signals_emit(obj, sd->dir);
2223 }
2224
2225 EOLIAN static void
2226 _elm_ctxpopup_auto_hide_disabled_set(Eo *obj EINA_UNUSED, Elm_Ctxpopup_Data *sd, Eina_Bool disabled)
2227 {
2228    disabled = !!disabled;
2229    if (sd->auto_hide == !disabled) return;
2230    sd->auto_hide = !disabled;
2231 }
2232
2233 EOLIAN static Eina_Bool
2234 _elm_ctxpopup_auto_hide_disabled_get(Eo *obj EINA_UNUSED, Elm_Ctxpopup_Data *sd)
2235 {
2236    return !sd->auto_hide;
2237 }
2238
2239 EOLIAN static void
2240 _elm_ctxpopup_item_init(Eo *eo_item,
2241           Elm_Ctxpopup_Item_Data *item,
2242           Evas_Smart_Cb func,
2243           const void *data)
2244 {
2245    Eo *obj;
2246    eo_do(eo_item, obj = eo_parent_get());
2247
2248    item->wcb.org_func_cb = func;
2249    item->wcb.org_data = data;
2250    item->wcb.cobj = obj;
2251 }
2252
2253 //TIZEN ONLY(20160918): name interface added
2254 EOLIAN static const char*
2255 _elm_ctxpopup_elm_interface_atspi_accessible_name_get(Eo *obj, Elm_Ctxpopup_Data *sd EINA_UNUSED)
2256 {
2257    Eina_Strbuf *buf;
2258    char *accessible_name = NULL;
2259    const char *style = elm_widget_style_get(obj);
2260
2261    ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd, NULL);
2262    buf = eina_strbuf_new();
2263    if (!strcmp(style, "more/default"))
2264      eina_strbuf_append_printf(buf, "%s", N_("More menu popup"));
2265    else
2266      eina_strbuf_append_printf(buf, "%s", N_("Alert"));
2267    accessible_name = eina_strbuf_string_steal(buf);
2268    eina_strbuf_free(buf);
2269
2270    eina_stringshare_del(wd->accessible_name);
2271    wd->accessible_name =  eina_stringshare_add(accessible_name);
2272    free(accessible_name);
2273    return wd->accessible_name;
2274 }
2275 //
2276
2277 EOLIAN static const Elm_Atspi_Action*
2278 _elm_ctxpopup_elm_interface_atspi_widget_action_elm_actions_get(Eo *obj EINA_UNUSED, Elm_Ctxpopup_Data *sd EINA_UNUSED)
2279 {
2280    static Elm_Atspi_Action atspi_actions[] = {
2281           { "escape", "escape", NULL, _key_action_escape},
2282           { "move,previous", "move", "previous", _key_action_move},
2283           { "move,next", "move", "next", _key_action_move},
2284           { "move,left", "move", "left", _key_action_move},
2285           { "move,right", "move", "right", _key_action_move},
2286           { "move,up", "move", "up", _key_action_move},
2287           { "move,down", "move", "down", _key_action_move},
2288           { NULL, NULL, NULL, NULL }
2289    };
2290    return &atspi_actions[0];
2291 }
2292
2293 EOLIAN static Elm_Atspi_State_Set
2294 _elm_ctxpopup_elm_interface_atspi_accessible_state_set_get(Eo *obj, Elm_Ctxpopup_Data *sd)
2295 {
2296    Elm_Atspi_State_Set ret;
2297    eo_do_super(obj, MY_CLASS, ret = elm_interface_atspi_accessible_state_set_get());
2298
2299    STATE_TYPE_SET(ret, ELM_ATSPI_STATE_MODAL);
2300
2301    if (_elm_object_accessibility_currently_highlighted_get() == (void*)sd->scr)
2302      STATE_TYPE_SET(ret, ELM_ATSPI_STATE_HIGHLIGHTED);
2303
2304    return ret;
2305 }
2306 //TIZEN ONLY(20150710): ctxpopup: Accessible methods for children_get, extents_get and item name_get
2307 EOLIAN Eina_List*
2308 _elm_ctxpopup_elm_interface_atspi_accessible_children_get(Eo *eo_item EINA_UNUSED, Elm_Ctxpopup_Data *sd)
2309 {
2310    Eina_List *ret = NULL;
2311    Eina_List *l = NULL;
2312    Elm_Ctxpopup_Item_Data *it;
2313
2314    EINA_LIST_FOREACH(sd->items, l, it)
2315       ret = eina_list_append(ret, EO_OBJ(it));
2316
2317    return ret;
2318 }
2319
2320 EOLIAN static void
2321 _elm_ctxpopup_elm_interface_atspi_component_extents_get(Eo *obj EINA_UNUSED, Elm_Ctxpopup_Data *sd, Eina_Bool screen_coords, int *x, int *y, int *w, int *h)
2322 {
2323    int ee_x, ee_y;
2324
2325    if (!sd->scr)
2326      {
2327         if (x) *x = -1;
2328         if (y) *y = -1;
2329         if (w) *w = -1;
2330         if (h) *h = -1;
2331         return;
2332      }
2333    evas_object_geometry_get(sd->scr, x, y, w, h);
2334
2335    if (screen_coords)
2336      {
2337         Ecore_Evas *ee = ecore_evas_ecore_evas_get(evas_object_evas_get(sd->scr));
2338         if (!ee) return;
2339         ecore_evas_geometry_get(ee, &ee_x, &ee_y, NULL, NULL);
2340         if (x) *x += ee_x;
2341         if (y) *y += ee_y;
2342      }
2343
2344 }
2345 //
2346 //TIZEN ONLY(20150708): popup and ctxpopup accessibility highlight impementation
2347 EOLIAN static Eina_Bool
2348 _elm_ctxpopup_elm_interface_atspi_component_highlight_grab(Eo *obj EINA_UNUSED, Elm_Ctxpopup_Data *sd)
2349 {
2350    if (sd->scr)
2351      {
2352         elm_object_accessibility_highlight_set(sd->scr, EINA_TRUE);
2353         ///TIZEN_ONLY(20170717) : expose highlight information on atspi
2354         elm_interface_atspi_accessible_state_changed_signal_emit(obj, ELM_ATSPI_STATE_HIGHLIGHTED, EINA_TRUE);
2355         ///
2356         return EINA_TRUE;
2357      }
2358    return EINA_FALSE;
2359 }
2360
2361 EOLIAN static Eina_Bool
2362 _elm_ctxpopup_elm_interface_atspi_component_highlight_clear(Eo *obj EINA_UNUSED, Elm_Ctxpopup_Data *sd)
2363 {
2364    if (sd->scr)
2365      {
2366         elm_object_accessibility_highlight_set(sd->scr, EINA_FALSE);
2367         ///TIZEN_ONLY(20170717) : expose highlight information on atspi
2368         elm_interface_atspi_accessible_state_changed_signal_emit(obj, ELM_ATSPI_STATE_HIGHLIGHTED, EINA_FALSE);
2369         ///
2370         return EINA_TRUE;
2371      }
2372    return EINA_FALSE;
2373 }
2374 //
2375
2376 //TIZEN ONLY(20150710)ctxpopup: Accessible methods for children_get, extents_get and item name_get
2377 EOLIAN const char *
2378 _elm_ctxpopup_item_elm_interface_atspi_accessible_name_get(Eo *eo_it EINA_UNUSED, Elm_Ctxpopup_Item_Data *item)
2379 {
2380    if(item->icon && !item->label)
2381      {
2382         const char *icon_name = NULL;
2383         eo_do(item->icon, icon_name = elm_interface_atspi_accessible_name_get());
2384         return icon_name;
2385      }
2386    else
2387      return item->label;
2388 }
2389 //
2390
2391 static Eina_Bool
2392 _key_action_escape(Evas_Object *obj, const char *params EINA_UNUSED)
2393 {
2394    elm_ctxpopup_dismiss(obj);
2395    return EINA_TRUE;
2396 }
2397
2398 static Eina_Bool
2399 _item_action_activate(Evas_Object *obj, const char *params EINA_UNUSED)
2400 {
2401    ELM_CTXPOPUP_ITEM_DATA_GET(obj, item);
2402
2403    if (item->wcb.org_func_cb)
2404      item->wcb.org_func_cb((void*)item->wcb.org_data, WIDGET(item), EO_OBJ(item));
2405    return EINA_TRUE;
2406 }
2407
2408 EOLIAN static const Elm_Atspi_Action*
2409 _elm_ctxpopup_item_elm_interface_atspi_widget_action_elm_actions_get(Eo *obj EINA_UNUSED, Elm_Ctxpopup_Item_Data *sd EINA_UNUSED)
2410 {
2411    static Elm_Atspi_Action atspi_actions[] = {
2412           { "activate", "activate", NULL, _item_action_activate},
2413           { NULL, NULL, NULL, NULL }
2414    };
2415    return &atspi_actions[0];
2416 }
2417
2418 //TIZEN ONLY(20161014) : Accessibility: scroll the content when highlight frame goes out of view port
2419 static int
2420 _is_item_in_viewport(int viewport_y, int viewport_h, int obj_y, int obj_h)
2421 {
2422    if ((obj_y + obj_h/2) < viewport_y)
2423      return 1;
2424    else if ((obj_y + obj_h/2) > viewport_y + viewport_h)
2425      return -1;
2426    return 0;
2427 }
2428
2429 EOLIAN static Eina_Bool
2430 _elm_ctxpopup_item_elm_interface_atspi_component_highlight_grab(Eo *eo_it, Elm_Ctxpopup_Item_Data *it)
2431 {
2432    Evas_Coord wy, wh, x, y, w, h, bx, by;
2433    ELM_CTXPOPUP_DATA_GET_OR_RETURN_VAL(WIDGET(it), sd, EINA_FALSE);
2434
2435    evas_object_geometry_get(VIEW(it), &x, &y, &w, &h);
2436    eo_do(sd->scr, elm_interface_scrollable_content_viewport_geometry_get(NULL, &wy, NULL, &wh));
2437    int res = _is_item_in_viewport(wy, wh, y, h);
2438
2439    if (res != 0)
2440      {
2441         evas_object_geometry_get(sd->box, &bx, &by, NULL, NULL);
2442         evas_smart_objects_calculate(evas_object_evas_get(sd->box));
2443         x -= bx;
2444         y -= by;
2445         if (res > 0)
2446           {
2447              y -= wh - h;
2448              eo_do(sd->scr, elm_interface_scrollable_content_region_show(x, y, w, h));
2449           }
2450         else if (res < 0)
2451           {
2452              y += wh - h;
2453              eo_do(sd->scr, elm_interface_scrollable_content_region_show(x, y, w, h));
2454           }
2455      }
2456
2457    elm_object_accessibility_highlight_set(eo_it, EINA_TRUE);
2458    elm_interface_atspi_accessible_state_changed_signal_emit(eo_it, ELM_ATSPI_STATE_HIGHLIGHTED, EINA_TRUE);
2459    return EINA_TRUE;
2460 }
2461
2462 EOLIAN static Eina_Bool
2463 _elm_ctxpopup_item_elm_interface_atspi_component_highlight_clear(Eo *eo_it, Elm_Ctxpopup_Item_Data *it EINA_UNUSED)
2464 {
2465    elm_object_accessibility_highlight_set(eo_it, EINA_FALSE);
2466    elm_interface_atspi_accessible_state_changed_signal_emit(eo_it, ELM_ATSPI_STATE_HIGHLIGHTED, EINA_FALSE);
2467
2468    return EINA_TRUE;
2469 }
2470
2471 static void
2472 _content_move_down_cb(void *data, Evas_Object *obj, void *ev EINA_UNUSED)
2473 {
2474    if (!_elm_atspi_enabled())
2475      return ;
2476    ELM_CTXPOPUP_DATA_GET(data, pd);
2477    Elm_Ctxpopup_Item_Data *it_data;
2478    Evas_Object *highlighted_obj = _elm_object_accessibility_currently_highlighted_get();
2479
2480    if (eo_isa(highlighted_obj, ELM_WIDGET_ITEM_CLASS))
2481      {
2482         Elm_Widget_Item_Data *id = eo_data_scope_get(highlighted_obj, ELM_WIDGET_ITEM_CLASS);
2483         highlighted_obj = id->view;
2484      }
2485
2486    Evas_Object *parent = highlighted_obj;
2487
2488    if (eo_isa(highlighted_obj, ELM_WIDGET_CLASS))
2489      {
2490         while ((parent = elm_widget_parent_get(parent)))
2491           if (parent == obj)
2492             break;
2493      }
2494    else if (eo_isa(highlighted_obj, EDJE_OBJECT_CLASS))
2495      {
2496         while ((parent = evas_object_smart_parent_get(parent)))
2497           if (parent == obj)
2498             break;
2499      }
2500    // TIZEN_ONLY(20160805): set _accessibility_currently_highlighted_obj to NULL in object delete callback
2501    else
2502      {
2503         WRN("Improper highlighted object: %p", highlighted_obj);
2504         return;
2505      }
2506    //
2507
2508    if (parent)
2509      {
2510         int obj_x, obj_y, w, h, hx, hy, hw, hh;
2511         eo_do(pd->scr, elm_interface_scrollable_content_viewport_geometry_get(&obj_x, &obj_y, &w, &h));
2512         evas_object_geometry_get(highlighted_obj, &hx, &hy, &hw, &hh);
2513
2514         Elm_Ctxpopup_Item_Data *next_previous_item = NULL;
2515         int viewport_position_result = _is_item_in_viewport(obj_y, h, hy, hh);
2516         if (viewport_position_result > 0)
2517           {
2518              Eina_List *l = pd->items;
2519              while(l)
2520               {
2521                  it_data = eina_list_data_get(l);
2522                  next_previous_item = it_data;
2523                  evas_object_geometry_get(VIEW(next_previous_item), &hx, &hy, &hw, &hh);
2524
2525                  if (_is_item_in_viewport(obj_y, h, hy, hh) == 0)
2526                     break;
2527                  next_previous_item = NULL;
2528
2529                  l = eina_list_next(l);
2530               }
2531           }
2532         if (next_previous_item)
2533           {
2534              elm_object_accessibility_highlight_set(EO_OBJ(next_previous_item), EINA_TRUE);
2535              elm_interface_atspi_accessible_state_changed_signal_emit(EO_OBJ(next_previous_item), ELM_ATSPI_STATE_HIGHLIGHTED, EINA_TRUE);
2536           }
2537      }
2538
2539 }
2540
2541 static void
2542 _content_move_up_cb(void *data, Evas_Object *obj, void *ev EINA_UNUSED)
2543 {
2544    if (!_elm_atspi_enabled())
2545      return ;
2546    ELM_CTXPOPUP_DATA_GET(data, pd);
2547    Elm_Ctxpopup_Item_Data *it_data;
2548    Evas_Object *highlighted_obj = _elm_object_accessibility_currently_highlighted_get();
2549
2550    if (eo_isa(highlighted_obj, ELM_WIDGET_ITEM_CLASS))
2551      {
2552         Elm_Widget_Item_Data *id = eo_data_scope_get(highlighted_obj, ELM_WIDGET_ITEM_CLASS);
2553         highlighted_obj = id->view;
2554      }
2555
2556    Evas_Object *parent = highlighted_obj;
2557
2558    if (eo_isa(highlighted_obj, ELM_WIDGET_CLASS))
2559      {
2560         while ((parent = elm_widget_parent_get(parent)))
2561           if (parent == obj)
2562             break;
2563      }
2564    else if (eo_isa(highlighted_obj, EDJE_OBJECT_CLASS))
2565      {
2566         while ((parent = evas_object_smart_parent_get(parent)))
2567           if (parent == obj)
2568             break;
2569      }
2570    // TIZEN_ONLY(20160805): set _accessibility_currently_highlighted_obj to NULL in object delete callback
2571    else
2572      {
2573         WRN("Improper highlighted object: %p", highlighted_obj);
2574         return;
2575      }
2576    //
2577
2578    if (parent)
2579      {
2580         int obj_x, obj_y, w, h, hx, hy, hw, hh;
2581         eo_do(pd->scr, elm_interface_scrollable_content_viewport_geometry_get(&obj_x, &obj_y, &w, &h));
2582         evas_object_geometry_get(highlighted_obj, &hx, &hy, &hw, &hh);
2583
2584         Elm_Ctxpopup_Item_Data *next_previous_item = NULL;
2585         int viewport_position_result = _is_item_in_viewport(obj_y, h, hy, hh);
2586         if (viewport_position_result < 0)
2587           {
2588              Eina_List *l = eina_list_last(pd->items);
2589              while(l)
2590               {
2591                  it_data = eina_list_data_get(l);
2592                  next_previous_item = it_data;
2593                  evas_object_geometry_get(VIEW(next_previous_item), &hx, &hy, &hw, &hh);
2594
2595                  if (_is_item_in_viewport(obj_y, h, hy, hh) == 0)
2596                     break;
2597                  next_previous_item = NULL;
2598
2599                  l = eina_list_prev(l);
2600               }
2601           }
2602         if (next_previous_item)
2603           {
2604              elm_object_accessibility_highlight_set(EO_OBJ(next_previous_item), EINA_TRUE);
2605              elm_interface_atspi_accessible_state_changed_signal_emit(EO_OBJ(next_previous_item), ELM_ATSPI_STATE_HIGHLIGHTED, EINA_TRUE);
2606           }
2607      }
2608
2609 }
2610 //
2611
2612 //TIZEN_ONLY ctx_popup: fix accessibility states
2613 EOLIAN static Elm_Atspi_State_Set
2614 _elm_ctxpopup_item_elm_interface_atspi_accessible_state_set_get(Eo *obj, Elm_Ctxpopup_Item_Data *it)
2615 {
2616    Elm_Atspi_State_Set states;
2617    Eina_Rectangle r1, r2;
2618    Eina_Bool is_showing = EINA_FALSE;
2619
2620    eo_do_super(obj, ELM_CTXPOPUP_ITEM_CLASS, states = elm_interface_atspi_accessible_state_set_get());
2621
2622    // evaluate showing state
2623    if (VIEW(it) &&
2624        WIDGET(it) &&
2625        evas_object_visible_get(VIEW(it)) &&
2626        _elm_widget_onscreen_is(WIDGET(it)))
2627      {
2628         ELM_CTXPOPUP_DATA_GET(WIDGET(it), sd);
2629
2630         evas_object_geometry_get(VIEW(it), &r1.x, &r1.y, &r1.w, &r1.h);
2631         evas_object_geometry_get(sd->scr, &r2.x, &r2.y, &r2.w, &r2.h);
2632
2633         if (eina_rectangles_intersect(&r1, &r2))
2634           is_showing = EINA_TRUE;
2635      }
2636
2637    if (is_showing)
2638      STATE_TYPE_SET(states, ELM_ATSPI_STATE_SHOWING);
2639    else
2640      STATE_TYPE_UNSET(states, ELM_ATSPI_STATE_SHOWING);
2641
2642    return states;
2643 }
2644 //
2645 #include "elm_ctxpopup_item.eo.c"
2646 #include "elm_ctxpopup.eo.c"