atspi: Handle default label object on toolkit side
[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_theme_set(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 Evas_Object *
411 _item_in_focusable_button(Elm_Ctxpopup_Item_Data *item)
412 {
413    Evas_Object *bt;
414
415    bt = elm_button_add(WIDGET(item));
416    elm_object_style_set(bt, "focus");
417    evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
418    elm_object_part_content_set(bt, "elm.swallow.content", VIEW(item));
419    evas_object_smart_callback_add(bt, "clicked", _item_select_cb, item);
420    evas_object_show(bt);
421
422    return bt;
423 }
424
425 EOLIAN static Eina_Bool
426 _elm_ctxpopup_item_elm_widget_item_del_pre(Eo *eo_item EINA_UNUSED, Elm_Ctxpopup_Item_Data *item)
427 {
428    Evas_Object *btn;
429
430    ELM_CTXPOPUP_DATA_GET(WIDGET(item), sd);
431    if (!sd) return EINA_FALSE;
432
433    btn = item->btn;
434    elm_box_unpack(sd->box, btn);
435    evas_object_smart_callback_del_full(btn, "clicked", _item_select_cb, item);
436    evas_object_del(btn);
437
438    sd->dir = ELM_CTXPOPUP_DIRECTION_UNKNOWN;
439
440    if (item->icon)
441      evas_object_del(item->icon);
442    if (VIEW(item))
443      evas_object_del(VIEW(item));
444
445    eina_stringshare_del(item->label);
446    sd->items = eina_list_remove(sd->items, item);
447
448    if (eina_list_count(sd->items) < 1)
449      {
450         evas_object_hide(WIDGET(item));
451         return EINA_TRUE;
452      }
453    if (sd->visible) elm_layout_sizing_eval(WIDGET(item));
454
455    return EINA_TRUE;
456 }
457
458 static void
459 _items_remove(Elm_Ctxpopup_Data *sd)
460 {
461    Eina_List *l, *l_next;
462    Elm_Ctxpopup_Item_Data *item;
463
464    if (!sd->items) return;
465
466    EINA_LIST_FOREACH_SAFE(sd->items, l, l_next, item)
467       eo_do(EO_OBJ(item), elm_wdg_item_del());
468
469    sd->items = NULL;
470 }
471
472 static void
473 _items_sizing_eval(Evas_Object *obj,
474                    Elm_Ctxpopup_Data *sd)
475 {
476    Elm_Ctxpopup_Item_Data *it;
477    Eina_List *elist;
478    int idx = 0;
479
480    sd->dir = ELM_CTXPOPUP_DIRECTION_UNKNOWN;
481
482    if (sd->visible)
483      {
484         EINA_LIST_FOREACH(sd->items, elist, it)
485           {
486              if (idx++ == 0)
487                edje_object_signal_emit(VIEW(it), "elm,state,default", "elm");
488              else
489                edje_object_signal_emit(VIEW(it), "elm,state,separator", "elm");
490           }
491         elm_layout_sizing_eval(obj);
492      }
493 }
494
495 static void
496 _item_sizing_eval(Elm_Ctxpopup_Item_Data *item)
497 {
498    Evas_Coord min_w = -1, min_h = -1, max_w = -1, max_h = -1;
499
500    if (!item) return;
501
502    edje_object_signal_emit(VIEW(item), "elm,state,text,default", "elm");
503    edje_object_message_signal_process(VIEW(item));
504    edje_object_size_min_restricted_calc(VIEW(item), &min_w, &min_h, min_w,
505                                         min_h);
506    evas_object_size_hint_min_set(VIEW(item), min_w, min_h);
507    evas_object_size_hint_max_set(VIEW(item), max_w, max_h);
508 }
509
510 static Elm_Ctxpopup_Direction
511 _base_geometry_calc(Evas_Object *obj,
512                     Evas_Coord_Rectangle *rect)
513 {
514    Elm_Ctxpopup_Direction dir = ELM_CTXPOPUP_DIRECTION_UNKNOWN;
515    Evas_Coord_Rectangle hover_area;
516    Evas_Coord_Point pos = {0, 0};
517    Evas_Coord_Point arrow_size;
518    Evas_Coord_Point base_size;
519    Evas_Coord_Point max_size;
520    Evas_Coord_Point min_size;
521    Evas_Coord_Point temp;
522    int idx;
523    const char *str;
524
525    ELM_CTXPOPUP_DATA_GET(obj, sd);
526    ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd, ELM_CTXPOPUP_DIRECTION_DOWN);
527
528    if (!rect) return ELM_CTXPOPUP_DIRECTION_DOWN;
529
530    edje_object_part_geometry_get
531      (sd->arrow, "ctxpopup_arrow", NULL, NULL, &arrow_size.x, &arrow_size.y);
532    evas_object_resize(sd->arrow, arrow_size.x, arrow_size.y);
533
534    //Initialize Area Rectangle.
535    evas_object_geometry_get
536      (sd->parent, &hover_area.x, &hover_area.y, &hover_area.w,
537      &hover_area.h);
538
539    evas_object_geometry_get(obj, &pos.x, &pos.y, NULL, NULL);
540
541    /* TIZEN_ONLY(20170524): move position in hover area */
542    if (pos.x < hover_area.x) pos.x = hover_area.x;
543    else if (pos.x > hover_area.x + hover_area.w) pos.x = hover_area.x + hover_area.w;
544
545    if (pos.y < hover_area.y) pos.y = hover_area.y;
546    else if (pos.y > hover_area.y + hover_area.h) pos.y = hover_area.y + hover_area.h;
547    /* END */
548
549    //recalc the edje
550    edje_object_size_min_calc
551      (wd->resize_obj, &base_size.x, &base_size.y);
552    evas_object_smart_calculate(wd->resize_obj);
553
554    //Limit to Max Size
555    evas_object_size_hint_max_get(obj, &max_size.x, &max_size.y);
556    if ((max_size.x == -1) || (max_size.y == -1))
557      {
558         str = edje_object_data_get(sd->layout, "visible_maxw");
559         if (str)
560           max_size.x = (int)(atoi(str)
561                              * elm_config_scale_get()
562                              * elm_object_scale_get(obj)
563                              / edje_object_base_scale_get(sd->layout) + 0.5);
564         str = edje_object_data_get(sd->layout, "visible_maxh");
565         if (str)
566           max_size.y = (int)(atoi(str)
567                              * elm_config_scale_get()
568                              * elm_object_scale_get(obj)
569                              / edje_object_base_scale_get(sd->layout) + 0.5);
570      }
571
572    if ((max_size.y > 0) && (base_size.y > max_size.y))
573      base_size.y = max_size.y;
574
575    if ((max_size.x > 0) && (base_size.x > max_size.x))
576      base_size.x = max_size.x;
577
578    //Limit to Min Size
579    evas_object_size_hint_min_get(obj, &min_size.x, &min_size.y);
580    if ((min_size.x == 0) || (min_size.y == 0))
581      edje_object_size_min_get(sd->layout, &min_size.x, &min_size.y);
582
583    if ((min_size.y > 0) && (base_size.y < min_size.y))
584      base_size.y = min_size.y;
585
586    if ((min_size.x > 0) && (base_size.x < min_size.x))
587      base_size.x = min_size.x;
588
589    //Check the Which direction is available.
590    //If find a avaialble direction, it adjusts position and size.
591    for (idx = 0; idx < 4; idx++)
592      {
593         switch (sd->dir_priority[idx])
594           {
595            case ELM_CTXPOPUP_DIRECTION_UNKNOWN:
596
597            case ELM_CTXPOPUP_DIRECTION_UP:
598              temp.y = (pos.y - base_size.y);
599              if ((temp.y - arrow_size.y) < hover_area.y)
600                continue;
601
602              _x_pos_adjust(&pos, &base_size, &hover_area);
603              pos.y -= base_size.y;
604              dir = ELM_CTXPOPUP_DIRECTION_UP;
605              break;
606
607            case ELM_CTXPOPUP_DIRECTION_LEFT:
608              temp.x = (pos.x - base_size.x);
609              if ((temp.x - arrow_size.x) < hover_area.x)
610                continue;
611
612              _y_pos_adjust(&pos, &base_size, &hover_area);
613              pos.x -= base_size.x;
614              dir = ELM_CTXPOPUP_DIRECTION_LEFT;
615              break;
616
617            case ELM_CTXPOPUP_DIRECTION_RIGHT:
618              temp.x = (pos.x + base_size.x);
619              if ((temp.x + arrow_size.x) >
620                  (hover_area.x + hover_area.w))
621                continue;
622
623              _y_pos_adjust(&pos, &base_size, &hover_area);
624              dir = ELM_CTXPOPUP_DIRECTION_RIGHT;
625              break;
626
627            case ELM_CTXPOPUP_DIRECTION_DOWN:
628              temp.y = (pos.y + base_size.y);
629              if ((temp.y + arrow_size.y) >
630                  (hover_area.y + hover_area.h))
631                continue;
632
633              _x_pos_adjust(&pos, &base_size, &hover_area);
634              dir = ELM_CTXPOPUP_DIRECTION_DOWN;
635              break;
636
637            default:
638              continue;
639           }
640         break;
641      }
642
643    //In this case, all directions are invalid because of lack of space.
644    if (idx == 4)
645      {
646         Evas_Coord length[2];
647
648         if (!sd->horizontal)
649           {
650              length[0] = pos.y - hover_area.y;
651              length[1] = (hover_area.y + hover_area.h) - pos.y;
652
653              // ELM_CTXPOPUP_DIRECTION_UP
654              if (length[0] > length[1])
655                {
656                   _x_pos_adjust(&pos, &base_size, &hover_area);
657                   pos.y -= base_size.y;
658                   dir = ELM_CTXPOPUP_DIRECTION_UP;
659                   if (pos.y < (hover_area.y + arrow_size.y))
660                     {
661                        base_size.y -= ((hover_area.y + arrow_size.y) - pos.y);
662                        pos.y = hover_area.y + arrow_size.y;
663                     }
664                }
665              //ELM_CTXPOPUP_DIRECTION_DOWN
666              else
667                {
668                   _x_pos_adjust(&pos, &base_size, &hover_area);
669                   dir = ELM_CTXPOPUP_DIRECTION_DOWN;
670                   if ((pos.y + arrow_size.y + base_size.y) >
671                       (hover_area.y + hover_area.h))
672                     base_size.y -=
673                       ((pos.y + arrow_size.y + base_size.y) -
674                        (hover_area.y + hover_area.h));
675                }
676           }
677         else
678           {
679              length[0] = pos.x - hover_area.x;
680              length[1] = (hover_area.x + hover_area.w) - pos.x;
681
682              //ELM_CTXPOPUP_DIRECTION_LEFT
683              if (length[0] > length[1])
684                {
685                   _y_pos_adjust(&pos, &base_size, &hover_area);
686                   pos.x -= base_size.x;
687                   dir = ELM_CTXPOPUP_DIRECTION_LEFT;
688                   if (pos.x < (hover_area.x + arrow_size.x))
689                     {
690                        base_size.x -= ((hover_area.x + arrow_size.x) - pos.x);
691                        pos.x = hover_area.x + arrow_size.x;
692                     }
693                }
694              //ELM_CTXPOPUP_DIRECTION_RIGHT
695              else
696                {
697                   _y_pos_adjust(&pos, &base_size, &hover_area);
698                   dir = ELM_CTXPOPUP_DIRECTION_RIGHT;
699                   if (pos.x + (arrow_size.x + base_size.x) >
700                       hover_area.x + hover_area.w)
701                     base_size.x -=
702                       ((pos.x + arrow_size.x + base_size.x) -
703                        (hover_area.x + hover_area.w));
704                }
705           }
706      }
707
708    //Final position and size.
709    rect->x = pos.x;
710    rect->y = pos.y;
711    rect->w = base_size.x;
712    rect->h = base_size.y;
713
714    return dir;
715 }
716
717 static void
718 _arrow_update(Evas_Object *obj,
719               Elm_Ctxpopup_Direction dir,
720               Evas_Coord_Rectangle base_size)
721 {
722    Evas_Coord_Rectangle arrow_size;
723    Evas_Coord x, y;
724    double drag;
725    Evas_Coord_Rectangle shadow_left_top, shadow_right_bottom, arrow_padding;
726
727    ELM_CTXPOPUP_DATA_GET(obj, sd);
728    ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
729
730    evas_object_geometry_get(obj, &x, &y, NULL, NULL);
731    evas_object_geometry_get
732      (sd->arrow, NULL, NULL, &arrow_size.w, &arrow_size.h);
733
734    /* tizen only : since ctxpopup of tizen has shadow, start and end padding of arrow, it should be put together when updating arrow
735     * so there are some differences between open source and tizen */
736    edje_object_part_geometry_get(wd->resize_obj, "frame_shadow_left_top_padding", NULL, NULL, &shadow_left_top.w, &shadow_left_top.h);
737    edje_object_part_geometry_get(wd->resize_obj, "frame_shadow_right_bottom_padding", NULL, NULL, &shadow_right_bottom.w, &shadow_right_bottom.h);
738    edje_object_part_geometry_get(wd->resize_obj, "ctxpopup_frame_left_top", NULL, NULL, &arrow_padding.w, &arrow_padding.h);
739
740    /* arrow is not being kept as sub-object on purpose, here. the
741     * design of the widget does not help with the contrary */
742
743    switch (dir)
744      {
745       case ELM_CTXPOPUP_DIRECTION_RIGHT:
746         edje_object_signal_emit(sd->arrow, "elm,state,left", "elm");
747         edje_object_part_swallow
748            (wd->resize_obj,
749             (elm_widget_mirrored_get(obj) ? "elm.swallow.arrow_right" :
750              "elm.swallow.arrow_left"), sd->arrow);
751
752         if (base_size.h > 0)
753           {
754              if (y <= ((arrow_size.h * 0.5) + base_size.y + shadow_left_top.h + arrow_padding.h))
755                y = 0;
756              else if (y >= (base_size.y + base_size.h - ((arrow_size.h * 0.5) + shadow_right_bottom.h + arrow_padding.h)))
757                y = base_size.h - (arrow_size.h + shadow_right_bottom.h + shadow_left_top.h + (arrow_padding.h * 2));
758              else
759                y = y - base_size.y - ((arrow_size.h * 0.5) + shadow_left_top.h + arrow_padding.h);
760              drag = (double)(y) / (double)(base_size.h - (arrow_size.h + shadow_right_bottom.h + shadow_left_top.h + (arrow_padding.h * 2)));
761              edje_object_part_drag_value_set
762                 (wd->resize_obj,
763                  (elm_widget_mirrored_get(obj) ? "elm.swallow.arrow_right" :
764                   "elm.swallow.arrow_left"), 1, drag);
765           }
766         break;
767
768       case ELM_CTXPOPUP_DIRECTION_LEFT:
769         edje_object_signal_emit(sd->arrow, "elm,state,right", "elm");
770         edje_object_part_swallow
771            (wd->resize_obj,
772             (elm_widget_mirrored_get(obj) ? "elm.swallow.arrow_left" :
773              "elm.swallow.arrow_right"), sd->arrow);
774
775         if (base_size.h > 0)
776           {
777              if (y <= ((arrow_size.h * 0.5) + base_size.y + shadow_left_top.h + arrow_padding.h))
778                y = 0;
779              else if (y >= (base_size.y + base_size.h - ((arrow_size.h * 0.5) + shadow_right_bottom.h + arrow_padding.h)))
780                y = base_size.h - (arrow_size.h + shadow_right_bottom.h + shadow_left_top.h + (arrow_padding.h * 2));
781              else
782                y = y - base_size.y - ((arrow_size.h * 0.5) + shadow_left_top.h + arrow_padding.h);
783              drag = (double)(y) / (double)(base_size.h - (arrow_size.h + shadow_right_bottom.h + shadow_left_top.h + (arrow_padding.h * 2)));
784              edje_object_part_drag_value_set
785                 (wd->resize_obj,
786                  (elm_widget_mirrored_get(obj) ? "elm.swallow.arrow_left" :
787                   "elm.swallow.arrow_right"), 0, drag);
788           }
789         break;
790
791       case ELM_CTXPOPUP_DIRECTION_DOWN:
792         edje_object_signal_emit(sd->arrow, "elm,state,top", "elm");
793         edje_object_part_swallow
794           (wd->resize_obj, "elm.swallow.arrow_up",
795           sd->arrow);
796
797         if (base_size.w > 0)
798           {
799              if (x <= ((arrow_size.w * 0.5) + base_size.x + shadow_left_top.w + arrow_padding.w))
800                x = 0;
801              else if (x >= (base_size.x + base_size.w - ((arrow_size.w * 0.5) + shadow_right_bottom.w + arrow_padding.w)))
802                x = base_size.w - (arrow_size.w + shadow_right_bottom.w + shadow_left_top.w + (arrow_padding.w * 2));
803              else
804                x = x - base_size.x - ((arrow_size.w * 0.5) + shadow_left_top.w + arrow_padding.w);
805              drag = (double)(x) / (double)(base_size.w - (arrow_size.w + shadow_right_bottom.w + shadow_left_top.w + (arrow_padding.w * 2)));
806              edje_object_part_drag_value_set
807                (wd->resize_obj, "elm.swallow.arrow_up",
808                drag, 1);
809           }
810         break;
811
812       case ELM_CTXPOPUP_DIRECTION_UP:
813         edje_object_signal_emit(sd->arrow, "elm,state,bottom", "elm");
814         edje_object_part_swallow
815           (wd->resize_obj, "elm.swallow.arrow_down",
816           sd->arrow);
817
818         if (base_size.w > 0)
819           {
820              if (x <= ((arrow_size.w * 0.5) + base_size.x + shadow_left_top.w + arrow_padding.w))
821                x = 0;
822              else if (x >= (base_size.x + base_size.w - ((arrow_size.w * 0.5) + shadow_right_bottom.w + arrow_padding.w)))
823                x = base_size.w - (arrow_size.w + shadow_right_bottom.w + shadow_left_top.w + (arrow_padding.w * 2));
824              else
825                x = x - base_size.x - ((arrow_size.w * 0.5) + shadow_left_top.w + arrow_padding.w);
826              drag = (double)(x) / (double)(base_size.w - (arrow_size.w + shadow_right_bottom.w + shadow_left_top.w + (arrow_padding.w * 2)));
827              edje_object_part_drag_value_set
828                (wd->resize_obj, "elm.swallow.arrow_down",
829                drag, 0);
830           }
831         break;
832
833       default:
834         break;
835      }
836
837    //should be here for getting accurate geometry value
838    evas_object_smart_calculate(wd->resize_obj);
839 }
840
841 static void
842 _show_signals_emit(Evas_Object *obj,
843                    Elm_Ctxpopup_Direction dir)
844 {
845    ELM_CTXPOPUP_DATA_GET(obj, sd);
846
847    if (!sd->visible) return;
848
849    switch (dir)
850      {
851       case ELM_CTXPOPUP_DIRECTION_UP:
852         edje_object_signal_emit(sd->layout, "elm,state,show,up", "elm");
853         break;
854
855       case ELM_CTXPOPUP_DIRECTION_LEFT:
856         edje_object_signal_emit(sd->layout, (elm_widget_mirrored_get(obj) ? "elm,state,show,right" :
857                "elm,state,show,left"), "elm");
858         break;
859
860       case ELM_CTXPOPUP_DIRECTION_RIGHT:
861         edje_object_signal_emit(sd->layout, (elm_widget_mirrored_get(obj) ? "elm,state,show,left" :
862                "elm,state,show,right"), "elm");
863         break;
864
865       case ELM_CTXPOPUP_DIRECTION_DOWN:
866         edje_object_signal_emit(sd->layout, "elm,state,show,down", "elm");
867         break;
868
869       default:
870         break;
871      }
872
873    edje_object_signal_emit(sd->bg, "elm,state,show", "elm");
874 }
875
876 static void
877 _visible_signals_emit(Evas_Object *obj,
878                    Elm_Ctxpopup_Direction dir)
879 {
880    ELM_CTXPOPUP_DATA_GET(obj, sd);
881
882    if (!sd->visible) return;
883
884    switch (dir)
885      {
886       case ELM_CTXPOPUP_DIRECTION_UP:
887         edje_object_signal_emit(sd->layout, "elm,state,visible,up", "elm");
888         break;
889
890       case ELM_CTXPOPUP_DIRECTION_LEFT:
891         edje_object_signal_emit(sd->layout, (elm_widget_mirrored_get(obj) ? "elm,state,visible,right" :
892                "elm,state,visible,left"), "elm");
893         break;
894
895       case ELM_CTXPOPUP_DIRECTION_RIGHT:
896         edje_object_signal_emit(sd->layout, (elm_widget_mirrored_get(obj) ? "elm,state,visible,left" :
897                "elm,state,visible,right"), "elm");
898         break;
899
900       case ELM_CTXPOPUP_DIRECTION_DOWN:
901         edje_object_signal_emit(sd->layout, "elm,state,visible,down", "elm");
902         break;
903
904       default:
905         break;
906      }
907
908    edje_object_signal_emit(sd->bg, "elm,state,visible", "elm");
909 }
910
911 static void
912 _hide_signals_emit(Evas_Object *obj,
913                    Elm_Ctxpopup_Direction dir)
914 {
915    ELM_CTXPOPUP_DATA_GET(obj, sd);
916
917    if (!sd->visible) return;
918
919    switch (dir)
920      {
921       case ELM_CTXPOPUP_DIRECTION_UP:
922         edje_object_signal_emit(sd->layout, "elm,state,hide,up", "elm");
923         break;
924
925       case ELM_CTXPOPUP_DIRECTION_LEFT:
926         edje_object_signal_emit(sd->layout, (elm_widget_mirrored_get(obj) ? "elm,state,hide,right" :
927                "elm,state,hide,left"), "elm");
928         break;
929
930       case ELM_CTXPOPUP_DIRECTION_RIGHT:
931         edje_object_signal_emit(sd->layout, (elm_widget_mirrored_get(obj) ? "elm,state,hide,left" :
932                "elm,state,hide,right"), "elm");
933         break;
934
935       case ELM_CTXPOPUP_DIRECTION_DOWN:
936         edje_object_signal_emit(sd->layout, "elm,state,hide,down", "elm");
937         break;
938
939       default:
940         edje_object_signal_emit(sd->layout, "elm,state,hide,default", "elm");
941         break;
942      }
943
944    edje_object_signal_emit(sd->bg, "elm,state,hide", "elm");
945 }
946
947 static void
948 _base_shift_by_arrow(Evas_Object *obj,
949                      Evas_Object *arrow,
950                      Elm_Ctxpopup_Direction dir,
951                      Evas_Coord_Rectangle *rect)
952 {
953    ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
954
955    Evas_Coord arrow_w, arrow_h, diff_w, diff_h;
956    Evas_Coord_Rectangle shadow_left_top, shadow_right_bottom;
957
958    evas_object_geometry_get(arrow, NULL, NULL, &arrow_w, &arrow_h);
959    /* 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
960     * so there are some differences between opensource and tizen*/
961    edje_object_part_geometry_get(wd->resize_obj, "frame_shadow_left_top_padding", NULL, NULL, &shadow_left_top.w, &shadow_left_top.h);
962    edje_object_part_geometry_get(wd->resize_obj, "frame_shadow_right_bottom_padding", NULL, NULL, &shadow_right_bottom.w, &shadow_right_bottom.h);
963    //
964
965    switch (dir)
966      {
967       case ELM_CTXPOPUP_DIRECTION_RIGHT:
968         diff_w = arrow_w - shadow_right_bottom.w;
969         rect->x += diff_w;
970         break;
971
972       case ELM_CTXPOPUP_DIRECTION_LEFT:
973         diff_w = arrow_w - shadow_left_top.w;
974         rect->x -= diff_w;
975         break;
976
977       case ELM_CTXPOPUP_DIRECTION_DOWN:
978         diff_h = arrow_h - shadow_left_top.h;
979         rect->y += diff_h;
980         break;
981
982       case ELM_CTXPOPUP_DIRECTION_UP:
983         diff_h = arrow_h - shadow_right_bottom.h;
984         rect->y -= diff_h;
985         break;
986
987       default:
988          break;
989      }
990 }
991
992 EOLIAN static Eina_Bool
993 _elm_ctxpopup_elm_layout_sub_object_add_enable(Eo *obj EINA_UNUSED, Elm_Ctxpopup_Data *_pd EINA_UNUSED)
994 {
995    return EINA_FALSE;
996 }
997
998 EOLIAN static Eina_Bool
999 _elm_ctxpopup_elm_widget_sub_object_add(Eo *obj, Elm_Ctxpopup_Data *_pd EINA_UNUSED, Evas_Object *sobj)
1000 {
1001    Eina_Bool int_ret = EINA_FALSE;
1002
1003    eo_do_super(obj, MY_CLASS, int_ret = elm_obj_widget_sub_object_add(sobj));
1004
1005    return int_ret;
1006 }
1007
1008 EOLIAN static void
1009 _elm_ctxpopup_elm_layout_sizing_eval(Eo *obj, Elm_Ctxpopup_Data *sd)
1010 {
1011    Eina_List *elist;
1012    Elm_Ctxpopup_Item_Data *item;
1013    Evas_Coord_Rectangle rect = { 0, 0, 1, 1 };
1014    Evas_Coord_Point box_size = { 0, 0 };
1015    Evas_Coord_Point _box_size = { 0, 0 };
1016    Evas_Coord maxw = 0;
1017    Evas_Coord x, y, w, h;
1018    const char *str;
1019
1020    ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
1021
1022    if (!sd->parent || !(sd->items || sd->content)) return;
1023
1024    //Box, Scroller
1025    EINA_LIST_FOREACH(sd->items, elist, item)
1026      {
1027         _item_sizing_eval(item);
1028         evas_object_size_hint_min_get(VIEW(item), &_box_size.x, &_box_size.y);
1029
1030         str = edje_object_data_get(VIEW(item), "item_max_size");
1031         if (str)
1032           {
1033              maxw = atoi(str);
1034              maxw = maxw * elm_config_scale_get()
1035                              * elm_widget_scale_get(obj)
1036                              / edje_object_base_scale_get(VIEW(item));
1037
1038              if (_box_size.x > maxw)
1039                {
1040                   edje_object_signal_emit(VIEW(item), "elm,state,text,ellipsis", "elm");
1041                   edje_object_message_signal_process(VIEW(item));
1042                }
1043           }
1044
1045         if (!sd->horizontal)
1046           {
1047              if (_box_size.x > box_size.x)
1048                box_size.x = _box_size.x;
1049              if (_box_size.y != -1)
1050                box_size.y += _box_size.y;
1051           }
1052         else
1053           {
1054              if (_box_size.x != -1)
1055                box_size.x += _box_size.x;
1056              if (_box_size.y > box_size.y)
1057                box_size.y = _box_size.y;
1058           }
1059      }
1060
1061 //   if (!sd->arrow) return;  /* simple way to flag "under deletion" */
1062
1063    if ((!sd->content) && (sd->scr))
1064      {
1065         evas_object_size_hint_min_set(sd->box, box_size.x, box_size.y);
1066         elm_scroller_content_min_limit(sd->scr, EINA_TRUE, EINA_TRUE);
1067         evas_object_size_hint_min_set(sd->scr, box_size.x, box_size.y);
1068      }
1069
1070    //Base
1071    sd->dir = _base_geometry_calc(obj, &rect);
1072
1073    _arrow_update(obj, sd->dir, rect);
1074    _base_shift_by_arrow(obj, sd->arrow, sd->dir, &rect);
1075
1076    //resize scroller according to final size
1077    if ((!sd->content) && (sd->scr))
1078      {
1079         elm_scroller_content_min_limit(sd->scr, EINA_FALSE, EINA_FALSE);
1080         evas_object_smart_calculate(sd->scr);
1081      }
1082
1083    evas_object_resize(obj, rect.w, rect.h);
1084    evas_object_size_hint_min_set(wd->resize_obj, rect.w, rect.h);
1085
1086    evas_object_resize(sd->layout, rect.w, rect.h);
1087    evas_object_move(sd->layout, rect.x, rect.y);
1088
1089    evas_object_geometry_get(sd->parent, &x, &y, &w, &h);
1090    evas_object_move(sd->bg, x, y);
1091    evas_object_resize(sd->bg, w, h);
1092 }
1093
1094 static void
1095 _on_parent_del(void *data,
1096                Evas *e EINA_UNUSED,
1097                Evas_Object *obj EINA_UNUSED,
1098                void *event_info EINA_UNUSED)
1099 {
1100    evas_object_del(data);
1101 }
1102
1103 static void
1104 _on_parent_move(void *data,
1105                 Evas *e EINA_UNUSED,
1106                 Evas_Object *obj EINA_UNUSED,
1107                 void *event_info EINA_UNUSED)
1108 {
1109    ELM_CTXPOPUP_DATA_GET(data, sd);
1110
1111
1112    sd->dir = ELM_CTXPOPUP_DIRECTION_UNKNOWN;
1113
1114    if (sd->visible)
1115      elm_layout_sizing_eval(data);
1116 }
1117
1118 static void
1119 _on_parent_resize(void *data,
1120                   Evas *e EINA_UNUSED,
1121                   Evas_Object *obj EINA_UNUSED,
1122                   void *event_info EINA_UNUSED)
1123 {
1124    ELM_CTXPOPUP_DATA_GET(data, sd);
1125    ELM_WIDGET_DATA_GET_OR_RETURN(data, wd);
1126
1127    if (sd->auto_hide)
1128      {
1129         sd->dir = ELM_CTXPOPUP_DIRECTION_UNKNOWN;
1130
1131         evas_object_hide(data);
1132         eo_do(data, eo_event_callback_call(ELM_CTXPOPUP_EVENT_DISMISSED, NULL));
1133      }
1134    else
1135      {
1136         if (wd->orient_mode == 90 || wd->orient_mode == 270)
1137          elm_widget_theme_object_set
1138            (data, sd->layout, "ctxpopup", "layout/landscape", elm_widget_style_get(data));
1139         else
1140          elm_widget_theme_object_set
1141            (data, sd->layout, "ctxpopup", "layout", elm_widget_style_get(data));
1142         edje_object_part_swallow(sd->layout, "swallow", wd->resize_obj);
1143
1144         if (sd->visible)
1145           elm_layout_sizing_eval(data);
1146
1147         /* TIZEN_ONLY(20170123): to avoid flickering problem when rotate device
1148         _show_signals_emit(data, sd->dir);
1149         */
1150         _visible_signals_emit(data, sd->dir);
1151         /* END */
1152      }
1153 }
1154
1155 static void
1156 _parent_detach(Evas_Object *obj)
1157 {
1158    ELM_CTXPOPUP_DATA_GET(obj, sd);
1159
1160    if (!sd->parent) return;
1161
1162    evas_object_event_callback_del_full
1163      (sd->parent, EVAS_CALLBACK_DEL, _on_parent_del, obj);
1164    evas_object_event_callback_del_full
1165      (sd->parent, EVAS_CALLBACK_MOVE, _on_parent_move, obj);
1166    evas_object_event_callback_del_full
1167      (sd->parent, EVAS_CALLBACK_RESIZE, _on_parent_resize, obj);
1168 }
1169
1170 static void
1171 _on_content_resized(void *data,
1172                     Evas *e EINA_UNUSED,
1173                     Evas_Object *obj EINA_UNUSED,
1174                     void *event_info EINA_UNUSED)
1175 {
1176    elm_layout_sizing_eval(data);
1177 }
1178
1179 static void
1180 _access_outline_activate_cb(void *data,
1181                         Evas_Object *part_obj EINA_UNUSED,
1182                         Elm_Object_Item *item EINA_UNUSED)
1183 {
1184    evas_object_hide(data);
1185    eo_do(data, eo_event_callback_call(ELM_CTXPOPUP_EVENT_DISMISSED, NULL));
1186 }
1187
1188 static void
1189 _access_obj_process(Evas_Object *obj, Eina_Bool is_access)
1190 {
1191    Evas_Object *ao;
1192    ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
1193
1194    if (is_access)
1195      {
1196         ao = _access_object_get(obj, ACCESS_OUTLINE_PART);
1197         if (!ao)
1198           {
1199              ao = _elm_access_edje_object_part_object_register
1200                 (obj, wd->resize_obj, ACCESS_OUTLINE_PART);
1201
1202              const char *style = elm_widget_style_get(obj);
1203              if (!strcmp(style, "more/default"))
1204                {
1205                   elm_access_info_set(ao, ELM_ACCESS_TYPE, TTS_STR_MENU_POPUP);
1206                   elm_access_info_set(ao, ELM_ACCESS_CONTEXT_INFO, TTS_STR_MENU_CLOSE);
1207                }
1208              else
1209                {
1210                   elm_access_info_set(ao, ELM_ACCESS_TYPE, E_("Contextual popup"));
1211                   elm_access_info_set(ao, ELM_ACCESS_CONTEXT_INFO, E_("Double tap to close popup"));
1212                }
1213              _elm_access_activate_callback_set
1214                 (_elm_access_info_get(ao), _access_outline_activate_cb, obj);
1215           }
1216      }
1217    else
1218      {
1219         _elm_access_edje_object_part_object_unregister
1220                (obj, wd->resize_obj, ACCESS_OUTLINE_PART);
1221      }
1222 }
1223
1224 static void
1225 _mirrored_set(Evas_Object *obj, Eina_Bool rtl)
1226 {
1227    ELM_CTXPOPUP_DATA_GET(obj, sd);
1228    ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
1229
1230    edje_object_mirrored_set(sd->layout, rtl);
1231    edje_object_mirrored_set(sd->arrow, rtl);
1232    edje_object_mirrored_set(wd->resize_obj, rtl);
1233 }
1234
1235 EOLIAN static Eina_Bool
1236 _elm_ctxpopup_elm_widget_event(Eo *obj, Elm_Ctxpopup_Data *sd, Evas_Object *src EINA_UNUSED, Evas_Callback_Type type, void *event_info)
1237 {
1238    Evas_Event_Key_Down *ev = event_info;
1239
1240    // TIZEN ONLY(20131221) : When access mode, focused ui is disabled.
1241    if (_elm_config->access_mode) return EINA_FALSE;
1242
1243    if (elm_widget_disabled_get(obj)) return EINA_FALSE;
1244    if (type != EVAS_CALLBACK_KEY_DOWN) return EINA_FALSE;
1245    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return EINA_FALSE;
1246
1247    //FIXME: for this key event, _elm_ctxpopup_smart_focus_next should be done first
1248    if ((!strcmp(ev->key, "Tab")) ||
1249        (!strcmp(ev->key, "ISO_Left_Tab")))
1250      {
1251         Eina_Bool ret;
1252         Evas_Object *target = NULL;
1253         Elm_Object_Item *target_item = NULL;
1254         Elm_Focus_Direction dir;
1255
1256         if (evas_key_modifier_is_set(ev->modifiers, "Control") ||
1257             evas_key_modifier_is_set(ev->modifiers, "Alt"))
1258           return EINA_FALSE;
1259         if (evas_key_modifier_is_set(ev->modifiers, "Shift"))
1260           dir = ELM_FOCUS_PREVIOUS;
1261         else
1262           dir = ELM_FOCUS_NEXT;
1263
1264         ret = elm_widget_focus_next_get(sd->box, dir, &target, &target_item);
1265         if (ret) elm_widget_focus_steal(target, target_item);
1266
1267         ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1268         return EINA_TRUE;
1269      }
1270    /////
1271    if (((!strcmp(ev->key, "Left")) ||
1272         (!strcmp(ev->key, "KP_Left")) ||
1273         (!strcmp(ev->key, "Right")) ||
1274         (!strcmp(ev->key, "KP_Right")) ||
1275         (!strcmp(ev->key, "Up")) ||
1276         (!strcmp(ev->key, "KP_Up")) ||
1277         (!strcmp(ev->key, "Down")) ||
1278         (!strcmp(ev->key, "KP_Down"))) && (!ev->string))
1279      {
1280         double degree = 0.0;
1281
1282         if ((!strcmp(ev->key, "Left")) ||
1283             (!strcmp(ev->key, "KP_Left")))
1284           degree = 270.0;
1285         else if ((!strcmp(ev->key, "Right")) ||
1286                  (!strcmp(ev->key, "KP_Right")))
1287           degree = 90.0;
1288         else if ((!strcmp(ev->key, "Up")) ||
1289                  (!strcmp(ev->key, "KP_Up")))
1290           degree = 0.0;
1291         else if ((!strcmp(ev->key, "Down")) ||
1292                  (!strcmp(ev->key, "KP_Down")))
1293           degree = 180.0;
1294
1295         elm_widget_focus_direction_go(sd->box, degree);
1296         ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1297         return EINA_TRUE;
1298      }
1299    else if (((!strcmp(ev->key, "Home")) ||
1300              (!strcmp(ev->key, "KP_Home")) ||
1301              (!strcmp(ev->key, "Prior")) ||
1302              (!strcmp(ev->key, "KP_Prior"))) && (!ev->string))
1303      {
1304         Elm_Ctxpopup_Item_Data *it = eina_list_data_get(sd->items);
1305         Evas_Object *btn = it->btn;
1306         elm_object_focus_set(btn, EINA_TRUE);
1307         ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1308         return EINA_TRUE;
1309      }
1310    else if (((!strcmp(ev->key, "End")) ||
1311              (!strcmp(ev->key, "KP_End")) ||
1312              (!strcmp(ev->key, "Next")) ||
1313              (!strcmp(ev->key, "KP_Next"))) && (!ev->string))
1314      {
1315         Elm_Ctxpopup_Item_Data *it = eina_list_data_get(eina_list_last(sd->items));
1316         Evas_Object *btn = it->btn;
1317         elm_object_focus_set(btn, EINA_TRUE);
1318         ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1319         return EINA_TRUE;
1320      }
1321
1322    // TIZEN ONLY : 20130530 : ctxpopup will be dismissed by user
1323    //if (strcmp(ev->keyname, "Escape")) return EINA_FALSE;
1324    return EINA_FALSE;
1325
1326 /*
1327    _hide_signals_emit(obj, sd->dir);
1328
1329    ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1330    return EINA_TRUE;
1331 */
1332 }
1333
1334 //FIXME: lost the content size when theme hook is called.
1335 EOLIAN static Elm_Theme_Apply
1336 _elm_ctxpopup_elm_widget_theme_apply(Eo *obj, Elm_Ctxpopup_Data *sd)
1337 {
1338    Eina_List *elist;
1339    Elm_Ctxpopup_Item_Data *item;
1340    int idx = 0;
1341    Eina_Bool rtl;
1342    Eina_Bool tmp;
1343    Elm_Theme_Apply int_ret = ELM_THEME_APPLY_FAILED;
1344
1345    ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd, ELM_THEME_APPLY_FAILED);
1346
1347    eo_do_super(obj, MY_CLASS, int_ret = elm_obj_widget_theme_apply());
1348    if (!int_ret) return ELM_THEME_APPLY_FAILED;
1349
1350    rtl = elm_widget_mirrored_get(obj);
1351
1352    elm_widget_theme_object_set
1353      (obj, sd->bg, "ctxpopup", "bg", elm_widget_style_get(obj));
1354
1355    elm_widget_theme_object_set
1356      (obj, sd->arrow, "ctxpopup", "arrow", elm_widget_style_get(obj));
1357
1358    if (wd->orient_mode == 90 || wd->orient_mode == 270)
1359      elm_widget_theme_object_set
1360        (obj, sd->layout, "ctxpopup", "layout/landscape", elm_widget_style_get(obj));
1361    else
1362      elm_widget_theme_object_set
1363        (obj, sd->layout, "ctxpopup", "layout", elm_widget_style_get(obj));
1364    edje_object_part_swallow(sd->layout, "swallow", wd->resize_obj);
1365
1366    _mirrored_set(obj, rtl);
1367
1368    //Items
1369    EINA_LIST_FOREACH(sd->items, elist, item)
1370      {
1371         edje_object_mirrored_set(VIEW(item), rtl);
1372
1373         if (item->label && item->icon)
1374           {
1375              if (!sd->horizontal)
1376                _elm_theme_object_set(obj, VIEW(item), "ctxpopup",
1377                                      "icon_text_style_item",
1378                                      elm_widget_style_get(obj));
1379              else
1380                _elm_theme_object_set(obj, VIEW(item), "ctxpopup",
1381                                      "icon_text_style_item_horizontal",
1382                                      elm_widget_style_get(obj));
1383           }
1384         else if (item->label)
1385           {
1386              if (!sd->horizontal)
1387                _elm_theme_object_set(obj, VIEW(item), "ctxpopup",
1388                                      "text_style_item",
1389                                      elm_widget_style_get(obj));
1390              else
1391                _elm_theme_object_set(obj, VIEW(item), "ctxpopup",
1392                                      "text_style_item_horizontal",
1393                                      elm_widget_style_get(obj));
1394           }
1395         else
1396           {
1397              if (!sd->horizontal)
1398                _elm_theme_object_set(obj, VIEW(item), "ctxpopup",
1399                                      "icon_style_item",
1400                                      elm_widget_style_get(obj));
1401              else
1402                _elm_theme_object_set(obj, VIEW(item), "ctxpopup",
1403                                      "icon_style_item_horizontal",
1404                                      elm_widget_style_get(obj));
1405           }
1406
1407         if (item->label)
1408           edje_object_part_text_set(VIEW(item), "elm.text", item->label);
1409
1410         if (eo_do_ret(EO_OBJ(item), tmp, elm_wdg_item_disabled_get()))
1411           edje_object_signal_emit(VIEW(item), "elm,state,disabled", "elm");
1412
1413        /*
1414         *  For separator, if the first item has visible separator,
1415         *  then it should be aligned with edge of the base part.
1416         *  In some cases, it gives improper display. Ex) rounded corner
1417         *  So the first item separator should be invisible.
1418         */
1419         if ((idx++) == 0)
1420           edje_object_signal_emit(VIEW(item), "elm,state,default", "elm");
1421         else
1422           edje_object_signal_emit(VIEW(item), "elm,state,separator", "elm");
1423
1424         // reset state of text to be default
1425         edje_object_signal_emit(VIEW(item), "elm,state,text,default", "elm");
1426         edje_object_message_signal_process(VIEW(item));
1427      }
1428
1429    if (evas_object_visible_get(sd->bg))
1430      edje_object_signal_emit(sd->bg, "elm,state,show", "elm");
1431
1432    if (sd->scr)
1433      {
1434         elm_layout_theme_set(sd->scr, "scroller", "ctxpopup", elm_widget_style_get(obj));
1435
1436         if (sd->horizontal)
1437           elm_scroller_policy_set(sd->scr, ELM_SCROLLER_POLICY_AUTO, ELM_SCROLLER_POLICY_OFF);
1438         else
1439           elm_scroller_policy_set(sd->scr, ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_AUTO);
1440      }
1441
1442    sd->dir = ELM_CTXPOPUP_DIRECTION_UNKNOWN;
1443
1444    if (sd->visible)
1445      elm_layout_sizing_eval(obj);
1446
1447    /* access */
1448   if (_elm_config->access_mode) _access_obj_process(obj, EINA_TRUE);
1449
1450    return int_ret;
1451 }
1452
1453 /* kind of a big and tricky override here: an internal box will hold
1454  * the actual content. content aliases won't be of much help here */
1455 EOLIAN static Eina_Bool
1456 _elm_ctxpopup_elm_container_content_set(Eo *obj, Elm_Ctxpopup_Data *sd, const char *part, Evas_Object *content)
1457 {
1458    Evas_Coord min_w = -1, min_h = -1;
1459    Eina_Bool int_ret = EINA_TRUE;
1460
1461    if ((part) && (strcmp(part, "default")))
1462      {
1463         eo_do_super(obj, MY_CLASS, int_ret = elm_obj_container_content_set(part, content));
1464         return int_ret;
1465      }
1466
1467    if (!content) return EINA_FALSE;
1468
1469    if (content == sd->content) return EINA_TRUE;
1470
1471    if (sd->items) elm_ctxpopup_clear(obj);
1472    if (sd->content) evas_object_del(sd->content);
1473
1474    ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd, EINA_FALSE);
1475
1476    evas_object_event_callback_add
1477       (sd->box, EVAS_CALLBACK_RESIZE, _on_content_resized, obj);
1478    edje_object_part_swallow(wd->resize_obj, "elm.swallow.content", sd->box);
1479
1480    evas_object_size_hint_weight_set
1481      (content, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
1482    evas_object_size_hint_fill_set
1483      (content, EVAS_HINT_FILL, EVAS_HINT_FILL);
1484
1485    /* since it's going to be a box content, not a layout's... */
1486    evas_object_show(content);
1487
1488    evas_object_size_hint_min_get(content, &min_w, &min_h);
1489    evas_object_size_hint_min_set(sd->box, min_w, min_h);
1490    elm_box_pack_end(sd->box, content);
1491
1492    sd->content = content;
1493    sd->dir = ELM_CTXPOPUP_DIRECTION_UNKNOWN;
1494
1495    if (sd->visible) elm_layout_sizing_eval(obj);
1496
1497    return EINA_TRUE;
1498 }
1499
1500 EOLIAN static Evas_Object*
1501 _elm_ctxpopup_elm_container_content_get(Eo *obj, Elm_Ctxpopup_Data *sd, const char *part)
1502 {
1503
1504    if ((part) && (strcmp(part, "default")))
1505      {
1506         Evas_Object *ret = NULL;
1507         eo_do_super(obj, MY_CLASS, ret = elm_obj_container_content_get(part));
1508         return ret;
1509      }
1510
1511    return sd->content;
1512 }
1513
1514 EOLIAN static Evas_Object*
1515 _elm_ctxpopup_elm_container_content_unset(Eo *obj, Elm_Ctxpopup_Data *sd, const char *part)
1516 {
1517    Evas_Object *content = NULL;
1518
1519    if ((part) && (strcmp(part, "default")))
1520      {
1521         eo_do_super(obj, MY_CLASS, content = elm_obj_container_content_unset(part));
1522         return content;
1523      }
1524
1525    content = sd->content;
1526    if (!content) return content;
1527
1528    elm_box_unpack(sd->box, content);
1529    sd->content = NULL;
1530    sd->dir = ELM_CTXPOPUP_DIRECTION_UNKNOWN;
1531
1532    if (sd->visible) elm_layout_sizing_eval(obj);
1533
1534    return content;
1535 }
1536
1537 EOLIAN static void
1538 _elm_ctxpopup_item_elm_widget_item_part_text_set(Eo *eo_ctxpopup_it EINA_UNUSED,
1539                                                  Elm_Ctxpopup_Item_Data *ctxpopup_it,
1540                                                  const char *part,
1541                                                  const char *label)
1542 {
1543    if (!ctxpopup_it) return;
1544    if (ctxpopup_it->label == label) return;
1545    if ((part) && (strcmp(part, "default"))) return;
1546
1547    ELM_CTXPOPUP_DATA_GET(WIDGET(ctxpopup_it), sd);
1548
1549    if (ctxpopup_it->label && !label)
1550      {
1551         if (!sd->horizontal)
1552           _elm_theme_object_set(WIDGET(ctxpopup_it), VIEW(ctxpopup_it), "ctxpopup",
1553                                 "icon_style_item",
1554                                 elm_widget_style_get(WIDGET(ctxpopup_it)));
1555         else
1556           _elm_theme_object_set(WIDGET(ctxpopup_it), VIEW(ctxpopup_it), "ctxpopup",
1557                                 "icon_style_item_horizontal",
1558                                 elm_widget_style_get(WIDGET(ctxpopup_it)));
1559      }
1560    else if (!ctxpopup_it->label && label)
1561      {
1562         if (!ctxpopup_it->icon)
1563           {
1564              if (!sd->horizontal)
1565                _elm_theme_object_set(WIDGET(ctxpopup_it), VIEW(ctxpopup_it), "ctxpopup",
1566                                      "text_style_item",
1567                                      elm_widget_style_get(WIDGET(ctxpopup_it)));
1568              else
1569                _elm_theme_object_set(WIDGET(ctxpopup_it), VIEW(ctxpopup_it), "ctxpopup",
1570                                      "text_style_item_horizontal",
1571                                      elm_widget_style_get(WIDGET(ctxpopup_it)));
1572           }
1573         else
1574           {
1575              if (!sd->horizontal)
1576                _elm_theme_object_set(WIDGET(ctxpopup_it), VIEW(ctxpopup_it), "ctxpopup",
1577                                     "icon_text_style_item",
1578                                     elm_widget_style_get(WIDGET(ctxpopup_it)));
1579              else
1580                _elm_theme_object_set(WIDGET(ctxpopup_it), VIEW(ctxpopup_it), "ctxpopup",
1581                                      "icon_text_style_item_horizontal",
1582                                      elm_widget_style_get(WIDGET(ctxpopup_it)));
1583           }
1584      }
1585
1586    eina_stringshare_replace(&ctxpopup_it->label, label);
1587    if (ctxpopup_it->label)
1588      edje_object_part_text_set(VIEW(ctxpopup_it), "elm.text", label);
1589
1590    sd->dir = ELM_CTXPOPUP_DIRECTION_UNKNOWN;
1591
1592    if (sd->visible)
1593      elm_layout_sizing_eval(WIDGET(ctxpopup_it));
1594 }
1595
1596 EOLIAN static const char *
1597 _elm_ctxpopup_item_elm_widget_item_part_text_get(Eo *eo_ctxpopup_it EINA_UNUSED,
1598                                                  Elm_Ctxpopup_Item_Data *ctxpopup_it,
1599                                                  const char *part)
1600 {
1601    if (part && strcmp(part, "default")) return NULL;
1602
1603    return ctxpopup_it->label;
1604 }
1605
1606 EOLIAN static void
1607 _elm_ctxpopup_item_elm_widget_item_part_content_set(Eo *eo_ctxpopup_it EINA_UNUSED,
1608                                                     Elm_Ctxpopup_Item_Data *ctxpopup_it,
1609                                                     const char *part,
1610                                                     Evas_Object *content)
1611 {
1612    if (!ctxpopup_it) return;
1613    if (ctxpopup_it->icon == content) return;
1614    if ((part) && (strcmp(part, "icon"))) return;
1615
1616    ELM_CTXPOPUP_DATA_GET(WIDGET(ctxpopup_it), sd);
1617
1618    if (ctxpopup_it->icon)
1619      evas_object_del(ctxpopup_it->icon);
1620
1621    if (ctxpopup_it->label)
1622      {
1623         if (!ctxpopup_it->icon && content)
1624           {
1625              if (!sd->horizontal)
1626                _elm_theme_object_set(WIDGET(ctxpopup_it), VIEW(ctxpopup_it), "ctxpopup",
1627                                      "icon_text_style_item",
1628                                      elm_widget_style_get(WIDGET(ctxpopup_it)));
1629              else
1630                _elm_theme_object_set(WIDGET(ctxpopup_it), VIEW(ctxpopup_it), "ctxpopup",
1631                                      "icon_text_style_item_horizontal",
1632                                      elm_widget_style_get(WIDGET(ctxpopup_it)));
1633           }
1634         else if (ctxpopup_it->icon && !content)
1635           {
1636              if (!sd->horizontal)
1637                _elm_theme_object_set(WIDGET(ctxpopup_it), VIEW(ctxpopup_it), "ctxpopup",
1638                                      "text_style_item",
1639                                      elm_widget_style_get(WIDGET(ctxpopup_it)));
1640              else
1641                _elm_theme_object_set(WIDGET(ctxpopup_it), VIEW(ctxpopup_it), "ctxpopup",
1642                                      "text_style_item_horizontal",
1643                                      elm_widget_style_get(WIDGET(ctxpopup_it)));
1644           }
1645      }
1646
1647    ctxpopup_it->icon = content;
1648    if (ctxpopup_it->icon)
1649      edje_object_part_swallow(VIEW(ctxpopup_it), "elm.swallow.icon", ctxpopup_it->icon);
1650
1651    sd->dir = ELM_CTXPOPUP_DIRECTION_UNKNOWN;
1652
1653    if (sd->visible)
1654      elm_layout_sizing_eval(WIDGET(ctxpopup_it));
1655 }
1656
1657 EOLIAN static Evas_Object *
1658 _elm_ctxpopup_item_elm_widget_item_part_content_get(Eo *eo_ctxpopup_it EINA_UNUSED,
1659                                                     Elm_Ctxpopup_Item_Data *ctxpopup_it,
1660                                                     const char *part)
1661 {
1662    if (part && strcmp(part, "icon")) return NULL;
1663
1664    return ctxpopup_it->icon;
1665 }
1666
1667 EOLIAN static Evas_Object *
1668 _elm_ctxpopup_item_elm_widget_item_part_content_unset(Eo *eo_ctxpopup_it EINA_UNUSED,
1669                                                       Elm_Ctxpopup_Item_Data *ctxpopup_it,
1670                                                       const char *part)
1671 {
1672    Evas_Object *content = NULL;
1673
1674    if (!ctxpopup_it || !ctxpopup_it->icon) return NULL;
1675    if ((part) && (strcmp(part, "icon"))) return NULL;
1676
1677    ELM_CTXPOPUP_DATA_GET(WIDGET(ctxpopup_it), sd);
1678
1679    edje_object_part_unswallow(VIEW(ctxpopup_it), ctxpopup_it->icon);
1680    evas_object_hide(ctxpopup_it->icon);
1681
1682    if (ctxpopup_it->label)
1683      {
1684         if (!sd->horizontal)
1685           _elm_theme_object_set(WIDGET(ctxpopup_it), VIEW(ctxpopup_it), "ctxpopup",
1686                                 "text_style_item",
1687                                 elm_widget_style_get(WIDGET(ctxpopup_it)));
1688         else
1689           _elm_theme_object_set(WIDGET(ctxpopup_it), VIEW(ctxpopup_it), "ctxpopup",
1690                                 "text_style_item_horizontal",
1691                                 elm_widget_style_get(WIDGET(ctxpopup_it)));
1692      }
1693
1694    content = ctxpopup_it->icon;
1695    ctxpopup_it->icon = NULL;
1696
1697    sd->dir = ELM_CTXPOPUP_DIRECTION_UNKNOWN;
1698
1699    if (sd->visible)
1700      elm_layout_sizing_eval(WIDGET(ctxpopup_it));
1701
1702    return content;
1703 }
1704
1705 EOLIAN static void
1706 _elm_ctxpopup_item_elm_widget_item_disable(Eo *eo_ctxpopup_it,
1707                                            Elm_Ctxpopup_Item_Data *ctxpopup_it)
1708 {
1709    ELM_CTXPOPUP_DATA_GET(WIDGET(ctxpopup_it), sd);
1710    Eina_Bool tmp;
1711    if (!sd) return;
1712
1713    if (eo_do_ret(eo_ctxpopup_it, tmp, elm_wdg_item_disabled_get()))
1714      edje_object_signal_emit(VIEW(ctxpopup_it), "elm,state,disabled", "elm");
1715    else
1716      edje_object_signal_emit(VIEW(ctxpopup_it), "elm,state,enabled", "elm");
1717 }
1718
1719 EOLIAN static void
1720 _elm_ctxpopup_item_elm_widget_item_signal_emit(Eo *eo_ctxpopup_it EINA_UNUSED,
1721                                                Elm_Ctxpopup_Item_Data *ctxpopup_it,
1722                                                const char *emission,
1723                                                const char *source)
1724 {
1725    edje_object_signal_emit(VIEW(ctxpopup_it), emission, source);
1726 }
1727
1728 EOLIAN static void
1729 _elm_ctxpopup_item_elm_widget_item_style_set(Eo *eo_item EINA_UNUSED,
1730                                              Elm_Ctxpopup_Item_Data *item,
1731                                              const char *style)
1732 {
1733    ELM_CTXPOPUP_DATA_GET(WIDGET(item), sd);
1734
1735    if (item->icon && item->label)
1736      {
1737         if (sd->horizontal)
1738           _elm_theme_object_set(WIDGET(item), VIEW(item), "ctxpopup", "icon_text_style_item_horizontal", style);
1739         else
1740           _elm_theme_object_set(WIDGET(item), VIEW(item), "ctxpopup", "icon_text_style_item", style);
1741      }
1742    else if (item->label)
1743      {
1744         if (sd->horizontal)
1745           _elm_theme_object_set(WIDGET(item), VIEW(item), "ctxpopup", "text_style_item_horizontal", style);
1746         else
1747           _elm_theme_object_set(WIDGET(item), VIEW(item), "ctxpopup", "text_style_item", style);
1748      }
1749    else
1750      {
1751         if (sd->horizontal)
1752           _elm_theme_object_set(WIDGET(item), VIEW(item), "ctxpopup", "icon_style_item_horizontal", style);
1753         else
1754           _elm_theme_object_set(WIDGET(item), VIEW(item), "ctxpopup", "icon_style_item", style);
1755      }
1756
1757    if (sd->visible) elm_layout_sizing_eval(WIDGET(item));
1758 }
1759
1760 static void
1761 _bg_clicked_cb(void *data,
1762                Evas_Object *obj EINA_UNUSED,
1763                const char *emission EINA_UNUSED,
1764                const char *source EINA_UNUSED)
1765 {
1766    ELM_CTXPOPUP_DATA_GET(data, sd);
1767
1768    _hide_signals_emit(data, sd->dir);
1769 }
1770
1771 static void
1772 _on_show(void *data EINA_UNUSED,
1773          Evas *e EINA_UNUSED,
1774          Evas_Object *obj,
1775          void *event_info EINA_UNUSED)
1776 {
1777    Eina_List *elist;
1778    Elm_Ctxpopup_Item_Data *item;
1779    int idx = 0;
1780
1781    ELM_CTXPOPUP_DATA_GET(obj, sd);
1782    ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
1783
1784    sd->visible = EINA_TRUE;
1785    //TIZEN_ONLY(20170919): Handle default label object
1786    _elm_win_default_label_obj_append(obj);
1787    //
1788
1789    elm_layout_signal_emit(obj, "elm,state,show", "elm");
1790
1791    if (wd->orient_mode == 90 || wd->orient_mode == 270)
1792      elm_widget_theme_object_set
1793        (obj, sd->layout, "ctxpopup", "layout/landscape", elm_widget_style_get(obj));
1794    else
1795      elm_widget_theme_object_set
1796        (obj, sd->layout, "ctxpopup", "layout", elm_widget_style_get(obj));
1797    edje_object_part_swallow(sd->layout, "swallow", wd->resize_obj);
1798
1799    EINA_LIST_FOREACH(sd->items, elist, item)
1800      {
1801         if (item->label && item->icon)
1802           {
1803              if (!sd->horizontal)
1804                _elm_theme_object_set(obj, VIEW(item), "ctxpopup",
1805                                      "icon_text_style_item",
1806                                      elm_widget_style_get(obj));
1807              else
1808                _elm_theme_object_set(obj, VIEW(item), "ctxpopup",
1809                                      "icon_text_style_item_horizontal",
1810                                      elm_widget_style_get(obj));
1811           }
1812         else if (item->label)
1813           {
1814              if (!sd->horizontal)
1815                _elm_theme_object_set(obj, VIEW(item), "ctxpopup",
1816                                      "text_style_item",
1817                                      elm_widget_style_get(obj));
1818              else
1819                _elm_theme_object_set(obj, VIEW(item), "ctxpopup",
1820                                      "text_style_item_horizontal",
1821                                      elm_widget_style_get(obj));
1822           }
1823         else
1824           {
1825              if (!sd->horizontal)
1826                _elm_theme_object_set(obj, VIEW(item), "ctxpopup",
1827                                      "icon_style_item",
1828                                      elm_widget_style_get(obj));
1829              else
1830                _elm_theme_object_set(obj, VIEW(item), "ctxpopup",
1831                                      "icon_style_item_horizontal",
1832                                      elm_widget_style_get(obj));
1833           }
1834
1835         if (idx++ == 0)
1836           edje_object_signal_emit(VIEW(item), "elm,state,default", "elm");
1837         else
1838           edje_object_signal_emit(VIEW(item), "elm,state,separator", "elm");
1839      }
1840
1841    elm_layout_sizing_eval(obj);
1842
1843    elm_object_focus_set(obj, EINA_TRUE);
1844    _show_signals_emit(obj, sd->dir);
1845 }
1846
1847 EOLIAN static void
1848 _elm_ctxpopup_item_elm_widget_item_focus_set(Eo *eo_ctxpopup_it EINA_UNUSED,
1849                                              Elm_Ctxpopup_Item_Data *ctxpopup_it,
1850                                              Eina_Bool focused)
1851 {
1852    elm_object_focus_set(ctxpopup_it->btn, focused);
1853 }
1854
1855 EOLIAN static Eina_Bool
1856 _elm_ctxpopup_item_elm_widget_item_focus_get(Eo *eo_ctxpopup_it EINA_UNUSED,
1857                                              Elm_Ctxpopup_Item_Data *ctxpopup_it)
1858 {
1859    return elm_object_focus_get(ctxpopup_it->btn);
1860 }
1861
1862 static void
1863 _on_hide(void *data EINA_UNUSED,
1864          Evas *e EINA_UNUSED,
1865          Evas_Object *obj,
1866          void *event_info EINA_UNUSED)
1867 {
1868    ELM_CTXPOPUP_DATA_GET(obj, sd);
1869
1870    if (!sd->visible) return;
1871
1872    sd->visible = EINA_FALSE;
1873    //TIZEN_ONLY(20170919): Handle default label object
1874    _elm_win_default_label_obj_remove(obj);
1875    //
1876 }
1877
1878 static void
1879 _on_move(void *data EINA_UNUSED,
1880          Evas *e EINA_UNUSED,
1881          Evas_Object *obj,
1882          void *event_info EINA_UNUSED)
1883 {
1884    ELM_CTXPOPUP_DATA_GET(obj, sd);
1885
1886    if (sd->visible) elm_layout_sizing_eval(obj);
1887 }
1888
1889 static void
1890 _hide_finished_cb(void *data,
1891                   Evas_Object *obj EINA_UNUSED,
1892                   const char *emission EINA_UNUSED,
1893                   const char *source EINA_UNUSED)
1894 {
1895    evas_object_hide(data);
1896    eo_do(data, eo_event_callback_call(ELM_CTXPOPUP_EVENT_DISMISSED, NULL));
1897 }
1898
1899 /* TIZEN_ONLY(20161207): add show finished callback */
1900 static void
1901 _show_finished_cb(void *data,
1902                   Evas_Object *obj EINA_UNUSED,
1903                   const char *emission EINA_UNUSED,
1904                   const char *source EINA_UNUSED)
1905 {
1906    elm_object_focus_set(data, EINA_TRUE);
1907 }
1908 /* END */
1909
1910 static void
1911 _list_del(Eo *obj, Elm_Ctxpopup_Data *sd)
1912 {
1913    if (!sd->scr) return;
1914
1915    ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
1916
1917    edje_object_part_unswallow(wd->resize_obj, sd->scr);
1918    evas_object_del(sd->scr);
1919    sd->scr = NULL;
1920    evas_object_del(sd->box);
1921    sd->box = NULL;
1922 }
1923
1924 static void
1925 _list_new(Evas_Object *obj)
1926 {
1927    ELM_CTXPOPUP_DATA_GET(obj, sd);
1928    if (!sd) return;
1929
1930    ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
1931    //scroller
1932    sd->scr = elm_scroller_add(obj);
1933    elm_layout_theme_set(sd->scr, "scroller", "ctxpopup", elm_widget_style_get(obj));
1934    evas_object_size_hint_align_set(sd->scr, EVAS_HINT_FILL, EVAS_HINT_FILL);
1935    _elm_widget_color_class_parent_set(sd->scr, obj);
1936
1937    if (sd->horizontal)
1938      elm_scroller_policy_set(sd->scr, ELM_SCROLLER_POLICY_AUTO, ELM_SCROLLER_POLICY_OFF);
1939    else
1940      elm_scroller_policy_set(sd->scr, ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_AUTO);
1941
1942    edje_object_part_swallow(wd->resize_obj, "elm.swallow.content", sd->scr);
1943    //TIZEN ONLY(20161014) : Accessibility: scroll the content when highlight frame goes out of view port
1944    evas_object_smart_callback_add(sd->scr, "scroll,down", _content_move_down_cb, (void*)obj);
1945    evas_object_smart_callback_add(sd->scr, "scroll,up", _content_move_up_cb, (void*)obj);
1946    //
1947    elm_object_content_set(sd->scr, sd->box);
1948    elm_ctxpopup_horizontal_set(obj, sd->horizontal);
1949 }
1950
1951 EOLIAN static Eina_Bool
1952 _elm_ctxpopup_elm_widget_disable(Eo *obj, Elm_Ctxpopup_Data *sd)
1953 {
1954    Eina_List *l;
1955    Elm_Ctxpopup_Item_Data *it;
1956    Eina_Bool int_ret = EINA_FALSE;
1957
1958    eo_do_super(obj, MY_CLASS, int_ret = elm_obj_widget_disable());
1959    if (!int_ret) return EINA_FALSE;
1960
1961    EINA_LIST_FOREACH(sd->items, l, it)
1962      elm_object_item_disabled_set(EO_OBJ(it), elm_widget_disabled_get(obj));
1963
1964    return EINA_TRUE;
1965 }
1966
1967 EOLIAN static void
1968 _elm_ctxpopup_evas_object_smart_add(Eo *obj, Elm_Ctxpopup_Data *priv)
1969 {
1970    ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
1971
1972    eo_do_super(obj, MY_CLASS, evas_obj_smart_add());
1973
1974    if (!elm_widget_sub_object_parent_add(obj))
1975      ERR("could not add %p as sub object of %p", obj, elm_object_parent_widget_get(obj));
1976
1977    elm_layout_theme_set(obj, "ctxpopup", "base", elm_widget_style_get(obj));
1978
1979    //Background
1980    priv->bg = edje_object_add(evas_object_evas_get(obj));
1981    elm_widget_theme_object_set(obj, priv->bg, "ctxpopup", "bg", "default");
1982    edje_object_signal_callback_add
1983      (priv->bg, "elm,action,click", "", _bg_clicked_cb, obj);
1984    evas_object_smart_member_add(priv->bg, obj);
1985    evas_object_stack_below(priv->bg, wd->resize_obj);
1986    _elm_widget_color_class_parent_set(priv->bg, obj);
1987
1988    //Arrow
1989    priv->arrow = edje_object_add(evas_object_evas_get(obj));
1990    elm_widget_theme_object_set
1991      (obj, priv->arrow, "ctxpopup", "arrow", "default");
1992    _elm_widget_color_class_parent_set(priv->arrow, obj);
1993
1994    priv->dir_priority[0] = ELM_CTXPOPUP_DIRECTION_UP;
1995    priv->dir_priority[1] = ELM_CTXPOPUP_DIRECTION_LEFT;
1996    priv->dir_priority[2] = ELM_CTXPOPUP_DIRECTION_RIGHT;
1997    priv->dir_priority[3] = ELM_CTXPOPUP_DIRECTION_DOWN;
1998    priv->dir = ELM_CTXPOPUP_DIRECTION_UNKNOWN;
1999
2000    priv->auto_hide = EINA_TRUE;
2001    priv->mouse_down = EINA_FALSE;
2002    priv->multi_down = 0;
2003
2004    priv->box = elm_box_add(obj);
2005    evas_object_size_hint_weight_set
2006      (priv->box, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
2007
2008    priv->layout = edje_object_add(evas_object_evas_get(obj));
2009    if (wd->orient_mode == 90 || wd->orient_mode == 270)
2010      elm_widget_theme_object_set(obj, priv->layout, "ctxpopup", "layout/landscape", "default");
2011    else
2012      elm_widget_theme_object_set(obj, priv->layout, "ctxpopup", "layout", "default");
2013    evas_object_smart_member_add(priv->layout, obj);
2014    _elm_widget_color_class_parent_set(priv->layout, obj);
2015
2016    edje_object_signal_callback_add
2017      (priv->layout, "elm,action,hide,finished", "", _hide_finished_cb, obj);
2018    /* TIZEN_ONLY(20161207): Add show finished callback */
2019    edje_object_signal_callback_add
2020      (priv->layout, "elm,action,show,finished", "", _show_finished_cb, obj);
2021    /* END */
2022
2023    edje_object_part_swallow(priv->layout, "swallow", wd->resize_obj);
2024    evas_object_size_hint_weight_set
2025      (priv->layout, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
2026
2027    evas_object_event_callback_add(obj, EVAS_CALLBACK_SHOW, _on_show, NULL);
2028    evas_object_event_callback_add(obj, EVAS_CALLBACK_HIDE, _on_hide, NULL);
2029    evas_object_event_callback_add(obj, EVAS_CALLBACK_MOVE, _on_move, NULL);
2030
2031    _mirrored_set(obj, elm_widget_mirrored_get(obj));
2032
2033    elm_widget_can_focus_set(obj, EINA_TRUE);
2034    elm_ctxpopup_hover_parent_set(obj, elm_object_parent_widget_get(obj));
2035    /* access */
2036    if (_elm_config->access_mode) _access_obj_process(obj, EINA_TRUE);
2037
2038    /* access: parent could be any object such as elm_list which does
2039       not know elc_ctxpopup as its child object in the focus_next(); */
2040
2041    wd->highlight_root = EINA_TRUE;
2042
2043    //Tizen Only: This should be removed when eo is applied.
2044    wd->on_create = EINA_FALSE;
2045 }
2046
2047 EOLIAN static void
2048 _elm_ctxpopup_evas_object_smart_del(Eo *obj, Elm_Ctxpopup_Data *sd)
2049 {
2050    evas_object_event_callback_del_full
2051      (sd->box, EVAS_CALLBACK_RESIZE, _on_content_resized, obj);
2052    _parent_detach(obj);
2053
2054    if (sd->items)
2055      {
2056         _items_remove(sd);
2057         _list_del(obj, sd);
2058      }
2059    else
2060      {
2061         evas_object_del(sd->box);
2062         sd->box = NULL;
2063      }
2064
2065    evas_object_del(sd->arrow);
2066    sd->arrow = NULL; /* stops _sizing_eval() from going on on deletion */
2067
2068    evas_object_del(sd->bg);
2069    sd->bg = NULL;
2070
2071    evas_object_del(sd->layout);
2072    sd->layout = NULL;
2073
2074    eo_do_super(obj, MY_CLASS, evas_obj_smart_del());
2075 }
2076
2077 EOLIAN static void
2078 _elm_ctxpopup_elm_widget_parent_set(Eo *obj, Elm_Ctxpopup_Data *_pd EINA_UNUSED, Evas_Object *parent)
2079 {
2080    //default parent is to be hover parent
2081    elm_ctxpopup_hover_parent_set(obj, parent);
2082 }
2083
2084 /*
2085 static void
2086 _elm_ctxpopup_smart_access(Evas_Object *obj, Eina_Bool is_access)
2087 {
2088    ELM_CTXPOPUP_CHECK(obj);
2089
2090    _access_obj_process(obj, is_access);
2091
2092    evas_object_smart_callback_call(obj, SIG_ACCESS_CHANGED, NULL);
2093 }
2094
2095 static Evas_Object *
2096 _elm_ctxpopup_smart_access_object_get(Evas_Object *obj, char *part)
2097 {
2098    ELM_CTXPOPUP_CHECK(obj) NULL;
2099
2100    return _access_object_get(obj, part);
2101 }
2102 */
2103
2104 EOLIAN static void
2105 _elm_ctxpopup_class_constructor(Eo_Class *klass)
2106 {
2107    evas_smart_legacy_type_register(MY_CLASS_NAME_LEGACY, klass);
2108 }
2109
2110 EAPI Evas_Object *
2111 elm_ctxpopup_add(Evas_Object *parent)
2112 {
2113    EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
2114    Evas_Object *obj = eo_add(MY_CLASS, parent);
2115
2116    /* access: parent could be any object such as elm_list which does
2117       not know elc_ctxpopup as its child object in the focus_next(); */
2118    ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd, NULL);
2119    wd->highlight_root = EINA_TRUE;
2120
2121    return obj;
2122 }
2123
2124 EOLIAN static Eo *
2125 _elm_ctxpopup_eo_base_constructor(Eo *obj, Elm_Ctxpopup_Data *_pd EINA_UNUSED)
2126 {
2127    obj = eo_do_super_ret(obj, MY_CLASS, obj, eo_constructor());
2128    eo_do(obj,
2129          evas_obj_type_set(MY_CLASS_NAME_LEGACY),
2130          evas_obj_smart_callbacks_descriptions_set(_smart_callbacks),
2131          elm_interface_atspi_accessible_role_set(ELM_ATSPI_ROLE_POPUP_MENU));
2132
2133    return obj;
2134 }
2135
2136
2137 EOLIAN static void
2138 _elm_ctxpopup_hover_parent_set(Eo *obj, Elm_Ctxpopup_Data *sd, Evas_Object *parent)
2139 {
2140    Evas_Coord x, y, w, h;
2141
2142    if (!parent) return;
2143
2144    _parent_detach(obj);
2145
2146    evas_object_event_callback_add
2147      (parent, EVAS_CALLBACK_DEL, _on_parent_del, obj);
2148    evas_object_event_callback_add
2149      (parent, EVAS_CALLBACK_MOVE, _on_parent_move, obj);
2150    evas_object_event_callback_add
2151      (parent, EVAS_CALLBACK_RESIZE, _on_parent_resize, obj);
2152
2153    sd->parent = parent;
2154
2155    //Update Background
2156    evas_object_geometry_get(parent, &x, &y, &w, &h);
2157    evas_object_move(sd->bg, x, y);
2158    evas_object_resize(sd->bg, w, h);
2159
2160    if (sd->visible) elm_layout_sizing_eval(obj);
2161 }
2162
2163 EOLIAN static Evas_Object*
2164 _elm_ctxpopup_hover_parent_get(Eo *obj EINA_UNUSED, Elm_Ctxpopup_Data *sd)
2165 {
2166    return sd->parent;
2167 }
2168
2169 EOLIAN static void
2170 _elm_ctxpopup_clear(Eo *obj, Elm_Ctxpopup_Data *sd)
2171 {
2172    _items_remove(sd);
2173
2174    ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
2175
2176    elm_object_content_unset(sd->scr);
2177    edje_object_part_unswallow(wd->resize_obj, sd->scr);
2178    evas_object_del(sd->scr);
2179    sd->scr = NULL;
2180    sd->dir = ELM_CTXPOPUP_DIRECTION_UNKNOWN;
2181 }
2182
2183 EOLIAN static void
2184 _elm_ctxpopup_horizontal_set(Eo *obj, Elm_Ctxpopup_Data *sd, Eina_Bool horizontal)
2185 {
2186    Eina_List *elist;
2187    Elm_Ctxpopup_Item_Data *item;
2188    int idx = 0;
2189
2190    sd->horizontal = !!horizontal;
2191
2192    if (!sd->scr)
2193       return;
2194
2195   if (!horizontal)
2196      {
2197         elm_box_horizontal_set(sd->box, EINA_FALSE);
2198         elm_scroller_bounce_set(sd->scr, EINA_FALSE, EINA_TRUE);
2199         elm_scroller_policy_set(sd->scr, ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_AUTO);
2200      }
2201    else
2202      {
2203         elm_box_horizontal_set(sd->box, EINA_TRUE);
2204         elm_scroller_bounce_set(sd->scr, EINA_TRUE, EINA_FALSE);
2205         elm_scroller_policy_set(sd->scr, ELM_SCROLLER_POLICY_AUTO, ELM_SCROLLER_POLICY_OFF);
2206      }
2207
2208    EINA_LIST_FOREACH(sd->items, elist, item)
2209      {
2210         if (item->label && item->icon)
2211           {
2212              if (!sd->horizontal)
2213                _elm_theme_object_set(obj, VIEW(item), "ctxpopup",
2214                                      "icon_text_style_item",
2215                                      elm_widget_style_get(obj));
2216              else
2217                _elm_theme_object_set(obj, VIEW(item), "ctxpopup",
2218                                      "icon_text_style_item_horizontal",
2219                                      elm_widget_style_get(obj));
2220           }
2221         else if (item->label)
2222           {
2223              if (!sd->horizontal)
2224                _elm_theme_object_set(obj, VIEW(item), "ctxpopup",
2225                                      "text_style_item",
2226                                      elm_widget_style_get(obj));
2227              else
2228                _elm_theme_object_set(obj, VIEW(item), "ctxpopup",
2229                                      "text_style_item_horizontal",
2230                                      elm_widget_style_get(obj));
2231           }
2232         else
2233           {
2234              if (!sd->horizontal)
2235                _elm_theme_object_set(obj, VIEW(item), "ctxpopup",
2236                                      "icon_style_item",
2237                                      elm_widget_style_get(obj));
2238              else
2239                _elm_theme_object_set(obj, VIEW(item), "ctxpopup",
2240                                      "icon_style_item_horizontal",
2241                                      elm_widget_style_get(obj));
2242           }
2243         if (idx++ == 0)
2244           edje_object_signal_emit(VIEW(item), "elm,state,default", "elm");
2245         else
2246           edje_object_signal_emit(VIEW(item), "elm,state,separator", "elm");
2247
2248         eo_do(EO_OBJ(item), elm_wdg_item_disable());
2249      }
2250
2251    sd->dir = ELM_CTXPOPUP_DIRECTION_UNKNOWN;
2252
2253    if (sd->visible) elm_layout_sizing_eval(obj);
2254 }
2255
2256 EOLIAN static Eina_Bool
2257 _elm_ctxpopup_horizontal_get(Eo *obj EINA_UNUSED, Elm_Ctxpopup_Data *sd)
2258 {
2259    return sd->horizontal;
2260 }
2261
2262 EOLIAN static Eo *
2263 _elm_ctxpopup_item_eo_base_constructor(Eo *obj, Elm_Ctxpopup_Item_Data *it)
2264 {
2265    obj = eo_do_super_ret(obj, ELM_CTXPOPUP_ITEM_CLASS, obj, eo_constructor());
2266    it->base = eo_data_scope_get(obj, ELM_WIDGET_ITEM_CLASS);
2267 //TIZEN ONLY(20150710)ctxpopup: Accessible methods for children_get, extents_get and item name_get
2268    eo_do(obj, elm_interface_atspi_accessible_role_set(ELM_ATSPI_ROLE_MENU_ITEM));
2269 //
2270    return obj;
2271 }
2272
2273 EOLIAN static void
2274 _elm_ctxpopup_item_eo_base_destructor(Eo *eo_ctxpopup_it,
2275                                       Elm_Ctxpopup_Item_Data *ctxpopup_it EINA_UNUSED)
2276 {
2277    eo_do_super(eo_ctxpopup_it, ELM_CTXPOPUP_ITEM_CLASS, eo_destructor());
2278 }
2279
2280 static Elm_Ctxpopup_Item_Data *
2281 _item_new(Evas_Object *obj,
2282           Elm_Ctxpopup_Data *sd,
2283           const char *label,
2284           Evas_Object *icon,
2285           Evas_Smart_Cb func,
2286           const void *data)
2287 {
2288    Evas_Object *content, *focus_bt;
2289    Eo *eo_item;
2290
2291    eo_item = eo_add(ELM_CTXPOPUP_ITEM_CLASS, obj, elm_obj_ctxpopup_item_init(func, data));
2292    if (!eo_item) return NULL;
2293
2294    ELM_CTXPOPUP_ITEM_DATA_GET(eo_item, item);
2295
2296    //The first item is appended.
2297    content = elm_object_content_unset(obj);
2298    if (content) evas_object_del(content);
2299
2300    if (!sd->items)
2301      _list_new(obj);
2302
2303    if (icon && label)
2304      {
2305         if (!sd->horizontal)
2306           _item_theme_set(item, "icon_text_style_item");
2307         else
2308           _item_theme_set(item, "icon_text_style_item_horizontal");
2309      }
2310    else if (label)
2311      {
2312         if (!sd->horizontal)
2313           _item_theme_set(item, "text_style_item");
2314         else
2315           _item_theme_set(item, "text_style_item_horizontal");
2316      }
2317    else
2318      {
2319         if (!sd->horizontal)
2320           _item_theme_set(item, "icon_style_item");
2321         else
2322           _item_theme_set(item, "icon_style_item_horizontal");
2323      }
2324
2325    if (label)
2326      {
2327         edje_object_part_text_set(VIEW(item), "elm.text", label);
2328         item->label = eina_stringshare_add(label);
2329      }
2330
2331    if (icon)
2332      {
2333         edje_object_part_swallow(VIEW(item), "elm.swallow.icon", icon);
2334         item->icon = icon;
2335      }
2336
2337    focus_bt = _item_in_focusable_button(item);
2338    item->btn = focus_bt;
2339    _elm_widget_color_class_parent_set(VIEW(item), obj);
2340
2341    if (_elm_config->access_mode) _access_focusable_button_register(focus_bt, item);
2342
2343    return item;
2344 }
2345
2346 EOLIAN static Elm_Object_Item*
2347 _elm_ctxpopup_item_insert_before(Eo *obj, Elm_Ctxpopup_Data *sd, Elm_Object_Item *eo_before, const char *label, Evas_Object *icon, Evas_Smart_Cb func, const void *data)
2348 {
2349    Elm_Ctxpopup_Item_Data *item;
2350
2351    EINA_SAFETY_ON_NULL_RETURN_VAL(eo_before, NULL);
2352    ELM_CTXPOPUP_ITEM_DATA_GET(eo_before, before_it);
2353    ELM_CTXPOPUP_ITEM_CHECK_OR_RETURN(before_it,  NULL);
2354
2355    if (!before_it->btn) return NULL;
2356
2357    item = _item_new(obj, sd, label, icon, func, data);
2358    if (!item) return NULL;
2359
2360    elm_box_pack_before(sd->box, item->btn, before_it->btn);
2361    sd->items = eina_list_prepend_relative(sd->items, item, before_it);
2362
2363    _items_sizing_eval(obj, sd);
2364
2365    return EO_OBJ(item);
2366 }
2367
2368 EOLIAN static Elm_Object_Item*
2369 _elm_ctxpopup_item_insert_after(Eo *obj, Elm_Ctxpopup_Data *sd, Elm_Object_Item *eo_after, const char *label, Evas_Object *icon, Evas_Smart_Cb func, const void *data)
2370 {
2371    Elm_Ctxpopup_Item_Data *item;
2372
2373    EINA_SAFETY_ON_NULL_RETURN_VAL(eo_after, NULL);
2374    ELM_CTXPOPUP_ITEM_DATA_GET(eo_after, after_it);
2375    ELM_CTXPOPUP_ITEM_CHECK_OR_RETURN(after_it,  NULL);
2376
2377    if (!after_it->btn) return NULL;
2378
2379    item = _item_new(obj, sd, label, icon, func, data);
2380    if (!item) return NULL;
2381
2382    elm_box_pack_after(sd->box, item->btn, after_it->btn);
2383    sd->items = eina_list_append_relative(sd->items, item, after_it);
2384
2385    _items_sizing_eval(obj, sd);
2386
2387    return EO_OBJ(item);
2388 }
2389
2390 EOLIAN static Elm_Object_Item*
2391 _elm_ctxpopup_item_append(Eo *obj, Elm_Ctxpopup_Data *sd, const char *label, Evas_Object *icon, Evas_Smart_Cb func, const void *data)
2392 {
2393    Elm_Ctxpopup_Item_Data *item;
2394
2395    item = _item_new(obj, sd, label, icon, func, data);
2396    if (!item) return NULL;
2397
2398    elm_box_pack_end(sd->box, item->btn);
2399    sd->items = eina_list_append(sd->items, item);
2400
2401    _items_sizing_eval(obj, sd);
2402
2403    return EO_OBJ(item);
2404 }
2405
2406 EOLIAN static Elm_Object_Item*
2407 _elm_ctxpopup_item_prepend(Eo *obj EINA_UNUSED, Elm_Ctxpopup_Data *sd EINA_UNUSED, const char *label EINA_UNUSED, Evas_Object *icon EINA_UNUSED, Evas_Smart_Cb func EINA_UNUSED, const void *data EINA_UNUSED)
2408 {
2409    Elm_Ctxpopup_Item_Data *item;
2410
2411    item = _item_new(obj, sd, label, icon, func, data);
2412    if (!item) return NULL;
2413
2414    elm_box_pack_start(sd->box, item->btn);
2415    sd->items = eina_list_prepend(sd->items, item);
2416
2417    _items_sizing_eval(obj, sd);
2418
2419    return EO_OBJ(item);
2420 }
2421
2422 EOLIAN static void
2423 _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)
2424 {
2425    sd->dir_priority[0] = first;
2426    sd->dir_priority[1] = second;
2427    sd->dir_priority[2] = third;
2428    sd->dir_priority[3] = fourth;
2429
2430    if (sd->visible) elm_layout_sizing_eval(obj);
2431 }
2432
2433 EOLIAN static void
2434 _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)
2435 {
2436    if (first) *first = sd->dir_priority[0];
2437    if (second) *second = sd->dir_priority[1];
2438    if (third) *third = sd->dir_priority[2];
2439    if (fourth) *fourth = sd->dir_priority[3];
2440 }
2441
2442 EOLIAN static Elm_Ctxpopup_Direction
2443 _elm_ctxpopup_direction_get(Eo *obj EINA_UNUSED, Elm_Ctxpopup_Data *sd)
2444 {
2445    return sd->dir;
2446 }
2447
2448 EAPI Eina_Bool
2449 elm_ctxpopup_direction_available_get(Evas_Object *obj, Elm_Ctxpopup_Direction direction)
2450 {
2451    ELM_CTXPOPUP_CHECK(obj) EINA_FALSE;
2452    ELM_CTXPOPUP_DATA_GET(obj, sd);
2453
2454    elm_layout_sizing_eval(obj);
2455
2456    if (sd->dir == direction) return EINA_TRUE;
2457    return EINA_FALSE;
2458 }
2459
2460 EOLIAN static void
2461 _elm_ctxpopup_dismiss(Eo *obj, Elm_Ctxpopup_Data *sd)
2462 {
2463    _hide_signals_emit(obj, sd->dir);
2464 }
2465
2466 EOLIAN static void
2467 _elm_ctxpopup_auto_hide_disabled_set(Eo *obj EINA_UNUSED, Elm_Ctxpopup_Data *sd, Eina_Bool disabled)
2468 {
2469    disabled = !!disabled;
2470    if (sd->auto_hide == !disabled) return;
2471    sd->auto_hide = !disabled;
2472 }
2473
2474 EOLIAN static Eina_Bool
2475 _elm_ctxpopup_auto_hide_disabled_get(Eo *obj EINA_UNUSED, Elm_Ctxpopup_Data *sd)
2476 {
2477    return !sd->auto_hide;
2478 }
2479
2480 // TIZEN_ONLY(20170116): merge eo & header files for different profiles
2481 EOLIAN static const Eina_List*
2482 _elm_ctxpopup_items_get(Eo *obj EINA_UNUSED, Elm_Ctxpopup_Data *sd)
2483 {
2484    return sd->items;
2485 }
2486
2487 EOLIAN static Elm_Object_Item*
2488 _elm_ctxpopup_first_item_get(Eo *obj EINA_UNUSED, Elm_Ctxpopup_Data *sd)
2489 {
2490    if (!sd->items) return NULL;
2491
2492    return eina_list_data_get(sd->items);
2493 }
2494
2495 EOLIAN static Elm_Object_Item*
2496 _elm_ctxpopup_last_item_get(Eo *obj EINA_UNUSED, Elm_Ctxpopup_Data *sd)
2497 {
2498    if (!sd->items) return NULL;
2499
2500    return eina_list_data_get(eina_list_last(sd->items));
2501 }
2502
2503 EOLIAN static Elm_Object_Item *
2504 _elm_ctxpopup_item_prev_get(Eo *eo_item EINA_UNUSED, Elm_Ctxpopup_Item_Data *item)
2505 {
2506    Eina_List *l;
2507
2508    ELM_CTXPOPUP_DATA_GET(WIDGET(item), sd);
2509
2510    if (!sd->items) return NULL;
2511
2512    l = eina_list_data_find_list(sd->items, eo_item);
2513    if (l && l->prev) return eina_list_data_get(l->prev);
2514
2515    return NULL;
2516 }
2517
2518 EOLIAN static Elm_Object_Item *
2519 _elm_ctxpopup_item_next_get(Eo *eo_item EINA_UNUSED, Elm_Ctxpopup_Item_Data *item)
2520 {
2521    Eina_List *l;
2522
2523    ELM_CTXPOPUP_DATA_GET(WIDGET(item), sd);
2524
2525    if (!sd->items) return NULL;
2526
2527    l = eina_list_data_find_list(sd->items, eo_item);
2528    if (l && l->next) return eina_list_data_get(l->next);
2529
2530    return NULL;
2531 }
2532 //
2533
2534 EOLIAN static void
2535 _elm_ctxpopup_item_init(Eo *eo_item,
2536           Elm_Ctxpopup_Item_Data *item,
2537           Evas_Smart_Cb func,
2538           const void *data)
2539 {
2540    Eo *obj;
2541    eo_do(eo_item, obj = eo_parent_get());
2542
2543    item->wcb.org_func_cb = func;
2544    item->wcb.org_data = data;
2545    item->wcb.cobj = obj;
2546 }
2547
2548 //TIZEN ONLY(20160918): name interface added
2549 EOLIAN static const char*
2550 _elm_ctxpopup_elm_interface_atspi_accessible_name_get(Eo *obj, Elm_Ctxpopup_Data *sd EINA_UNUSED)
2551 {
2552    Eina_Strbuf *buf;
2553    char *accessible_name = NULL;
2554    const char *style = elm_widget_style_get(obj);
2555
2556    eo_do_super(obj, ELM_CTXPOPUP_CLASS, accessible_name = (char *)elm_interface_atspi_accessible_name_get());
2557    if (accessible_name) return accessible_name;
2558
2559    ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd, NULL);
2560    buf = eina_strbuf_new();
2561    if (!strcmp(style, "more/default"))
2562      eina_strbuf_append_printf(buf, "%s", N_("More menu popup"));
2563    else
2564      eina_strbuf_append_printf(buf, "%s", E_("Alert"));
2565    accessible_name = eina_strbuf_string_steal(buf);
2566    eina_strbuf_free(buf);
2567
2568    eina_stringshare_del(wd->accessible_name);
2569    wd->accessible_name = eina_stringshare_add(accessible_name);
2570    free(accessible_name);
2571    return wd->accessible_name;
2572 }
2573 //
2574
2575 EOLIAN static const Elm_Atspi_Action*
2576 _elm_ctxpopup_elm_interface_atspi_widget_action_elm_actions_get(Eo *obj EINA_UNUSED, Elm_Ctxpopup_Data *sd EINA_UNUSED)
2577 {
2578    static Elm_Atspi_Action atspi_actions[] = {
2579           { "escape", "escape", NULL, _key_action_escape},
2580           { "move,previous", "move", "previous", _key_action_move},
2581           { "move,next", "move", "next", _key_action_move},
2582           { "move,left", "move", "left", _key_action_move},
2583           { "move,right", "move", "right", _key_action_move},
2584           { "move,up", "move", "up", _key_action_move},
2585           { "move,down", "move", "down", _key_action_move},
2586           { NULL, NULL, NULL, NULL }
2587    };
2588    return &atspi_actions[0];
2589 }
2590
2591 EOLIAN static Elm_Atspi_State_Set
2592 _elm_ctxpopup_elm_interface_atspi_accessible_state_set_get(Eo *obj, Elm_Ctxpopup_Data *sd)
2593 {
2594    Elm_Atspi_State_Set ret;
2595    eo_do_super(obj, MY_CLASS, ret = elm_interface_atspi_accessible_state_set_get());
2596
2597    STATE_TYPE_SET(ret, ELM_ATSPI_STATE_MODAL);
2598
2599    if (_elm_object_accessibility_currently_highlighted_get() == (void*)sd->scr)
2600      STATE_TYPE_SET(ret, ELM_ATSPI_STATE_HIGHLIGHTED);
2601
2602    return ret;
2603 }
2604 //TIZEN ONLY(20150710): ctxpopup: Accessible methods for children_get, extents_get and item name_get
2605 EOLIAN Eina_List*
2606 _elm_ctxpopup_elm_interface_atspi_accessible_children_get(Eo *eo_item EINA_UNUSED, Elm_Ctxpopup_Data *sd)
2607 {
2608    Eina_List *ret = NULL;
2609    Eina_List *l = NULL;
2610    Elm_Ctxpopup_Item_Data *it;
2611
2612    EINA_LIST_FOREACH(sd->items, l, it)
2613       ret = eina_list_append(ret, EO_OBJ(it));
2614
2615    return ret;
2616 }
2617
2618 EOLIAN static void
2619 _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)
2620 {
2621    int ee_x, ee_y;
2622
2623    if (!sd->scr)
2624      {
2625         if (x) *x = -1;
2626         if (y) *y = -1;
2627         if (w) *w = -1;
2628         if (h) *h = -1;
2629         return;
2630      }
2631    evas_object_geometry_get(sd->scr, x, y, w, h);
2632
2633    if (screen_coords)
2634      {
2635         Ecore_Evas *ee = ecore_evas_ecore_evas_get(evas_object_evas_get(sd->scr));
2636         if (!ee) return;
2637         ecore_evas_geometry_get(ee, &ee_x, &ee_y, NULL, NULL);
2638         if (x) *x += ee_x;
2639         if (y) *y += ee_y;
2640      }
2641
2642 }
2643 //
2644 //TIZEN ONLY(20150708): popup and ctxpopup accessibility highlight impementation
2645 EOLIAN static Eina_Bool
2646 _elm_ctxpopup_elm_interface_atspi_component_highlight_grab(Eo *obj EINA_UNUSED, Elm_Ctxpopup_Data *sd)
2647 {
2648    if (sd->scr)
2649      {
2650         elm_object_accessibility_highlight_set(sd->scr, EINA_TRUE);
2651         ///TIZEN_ONLY(20170717) : expose highlight information on atspi
2652         elm_interface_atspi_accessible_state_changed_signal_emit(obj, ELM_ATSPI_STATE_HIGHLIGHTED, EINA_TRUE);
2653         ///
2654         return EINA_TRUE;
2655      }
2656    return EINA_FALSE;
2657 }
2658
2659 EOLIAN static Eina_Bool
2660 _elm_ctxpopup_elm_interface_atspi_component_highlight_clear(Eo *obj EINA_UNUSED, Elm_Ctxpopup_Data *sd)
2661 {
2662    if (sd->scr)
2663      {
2664         elm_object_accessibility_highlight_set(sd->scr, EINA_FALSE);
2665         ///TIZEN_ONLY(20170717) : expose highlight information on atspi
2666         elm_interface_atspi_accessible_state_changed_signal_emit(obj, ELM_ATSPI_STATE_HIGHLIGHTED, EINA_FALSE);
2667         ///
2668         return EINA_TRUE;
2669      }
2670    return EINA_FALSE;
2671 }
2672 //
2673
2674 //TIZEN ONLY(20150710)ctxpopup: Accessible methods for children_get, extents_get and item name_get
2675 EOLIAN const char *
2676 _elm_ctxpopup_item_elm_interface_atspi_accessible_name_get(Eo *eo_it, Elm_Ctxpopup_Item_Data *item)
2677 {
2678    char *accessible_name = NULL;
2679    eo_do_super(eo_it, ELM_CTXPOPUP_ITEM_CLASS, accessible_name = (char *)elm_interface_atspi_accessible_name_get());
2680    if (accessible_name) return accessible_name;
2681
2682    if(item->icon && !item->label)
2683      {
2684         const char *icon_name = NULL;
2685         eo_do(item->icon, icon_name = elm_interface_atspi_accessible_name_get());
2686         return icon_name;
2687      }
2688    else
2689      return _elm_widget_item_accessible_plain_name_get(eo_it, item->label);
2690 }
2691 //
2692
2693 static Eina_Bool
2694 _key_action_escape(Evas_Object *obj, const char *params EINA_UNUSED)
2695 {
2696    elm_ctxpopup_dismiss(obj);
2697    return EINA_TRUE;
2698 }
2699
2700 static Eina_Bool
2701 _item_action_activate(Evas_Object *obj, const char *params EINA_UNUSED)
2702 {
2703    ELM_CTXPOPUP_ITEM_DATA_GET(obj, item);
2704
2705    if (item->wcb.org_func_cb)
2706      item->wcb.org_func_cb((void*)item->wcb.org_data, WIDGET(item), EO_OBJ(item));
2707    return EINA_TRUE;
2708 }
2709
2710 EOLIAN static const Elm_Atspi_Action*
2711 _elm_ctxpopup_item_elm_interface_atspi_widget_action_elm_actions_get(Eo *obj EINA_UNUSED, Elm_Ctxpopup_Item_Data *sd EINA_UNUSED)
2712 {
2713    static Elm_Atspi_Action atspi_actions[] = {
2714           { "activate", "activate", NULL, _item_action_activate},
2715           { NULL, NULL, NULL, NULL }
2716    };
2717    return &atspi_actions[0];
2718 }
2719
2720 //TIZEN ONLY(20161014) : Accessibility: scroll the content when highlight frame goes out of view port
2721 static int
2722 _is_item_in_viewport(int viewport_y, int viewport_h, int obj_y, int obj_h)
2723 {
2724    if ((obj_y + obj_h/2) < viewport_y)
2725      return 1;
2726    else if ((obj_y + obj_h/2) > viewport_y + viewport_h)
2727      return -1;
2728    return 0;
2729 }
2730
2731 EOLIAN static Eina_Bool
2732 _elm_ctxpopup_item_elm_interface_atspi_component_highlight_grab(Eo *eo_it, Elm_Ctxpopup_Item_Data *it)
2733 {
2734    Evas_Coord wy, wh, x, y, w, h, bx, by;
2735    ELM_CTXPOPUP_DATA_GET_OR_RETURN_VAL(WIDGET(it), sd, EINA_FALSE);
2736
2737    evas_object_geometry_get(VIEW(it), &x, &y, &w, &h);
2738    eo_do(sd->scr, elm_interface_scrollable_content_viewport_geometry_get(NULL, &wy, NULL, &wh));
2739    int res = _is_item_in_viewport(wy, wh, y, h);
2740
2741    if (res != 0)
2742      {
2743         evas_object_geometry_get(sd->box, &bx, &by, NULL, NULL);
2744         evas_smart_objects_calculate(evas_object_evas_get(sd->box));
2745         x -= bx;
2746         y -= by;
2747         if (res > 0)
2748           {
2749              y -= wh - h;
2750              eo_do(sd->scr, elm_interface_scrollable_content_region_show(x, y, w, h));
2751           }
2752         else if (res < 0)
2753           {
2754              y += wh - h;
2755              eo_do(sd->scr, elm_interface_scrollable_content_region_show(x, y, w, h));
2756           }
2757      }
2758
2759    elm_object_accessibility_highlight_set(eo_it, EINA_TRUE);
2760    elm_interface_atspi_accessible_state_changed_signal_emit(eo_it, ELM_ATSPI_STATE_HIGHLIGHTED, EINA_TRUE);
2761    //TIZEN_ONLY(20170412) Make atspi,(un)highlighted work on widget item
2762    // If you call eo_do_super, then you do NOT have to call smart callback.
2763    evas_object_smart_callback_call(WIDGET(it), "atspi,highlighted", EO_OBJ(it));
2764    //
2765    return EINA_TRUE;
2766 }
2767
2768 EOLIAN static Eina_Bool
2769 _elm_ctxpopup_item_elm_interface_atspi_component_highlight_clear(Eo *eo_it, Elm_Ctxpopup_Item_Data *it EINA_UNUSED)
2770 {
2771    elm_object_accessibility_highlight_set(eo_it, EINA_FALSE);
2772    elm_interface_atspi_accessible_state_changed_signal_emit(eo_it, ELM_ATSPI_STATE_HIGHLIGHTED, EINA_FALSE);
2773    //TIZEN_ONLY(20170412) Make atspi,(un)highlighted work on widget item
2774    // If you call eo_do_super, then you do NOT have to call smart callback.
2775    evas_object_smart_callback_call(WIDGET(it), "atspi,unhighlighted", EO_OBJ(it));
2776    //
2777    return EINA_TRUE;
2778 }
2779
2780 static void
2781 _content_move_down_cb(void *data, Evas_Object *obj, void *ev EINA_UNUSED)
2782 {
2783    if (!_elm_atspi_enabled())
2784      return ;
2785    ELM_CTXPOPUP_DATA_GET(data, pd);
2786    Elm_Ctxpopup_Item_Data *it_data;
2787    Evas_Object *highlighted_obj = _elm_object_accessibility_currently_highlighted_get();
2788
2789    if (eo_isa(highlighted_obj, ELM_WIDGET_ITEM_CLASS))
2790      {
2791         Elm_Widget_Item_Data *id = eo_data_scope_get(highlighted_obj, ELM_WIDGET_ITEM_CLASS);
2792         highlighted_obj = id->view;
2793      }
2794
2795    Evas_Object *parent = highlighted_obj;
2796
2797    if (eo_isa(highlighted_obj, ELM_WIDGET_CLASS))
2798      {
2799         while ((parent = elm_widget_parent_get(parent)))
2800           if (parent == obj)
2801             break;
2802      }
2803    else if (eo_isa(highlighted_obj, EDJE_OBJECT_CLASS))
2804      {
2805         while ((parent = evas_object_smart_parent_get(parent)))
2806           if (parent == obj)
2807             break;
2808      }
2809    // TIZEN_ONLY(20160805): set _accessibility_currently_highlighted_obj to NULL in object delete callback
2810    else
2811      {
2812         WRN("Improper highlighted object: %p", highlighted_obj);
2813         return;
2814      }
2815    //
2816
2817    if (parent)
2818      {
2819         int obj_x, obj_y, w, h, hx, hy, hw, hh;
2820         eo_do(pd->scr, elm_interface_scrollable_content_viewport_geometry_get(&obj_x, &obj_y, &w, &h));
2821         evas_object_geometry_get(highlighted_obj, &hx, &hy, &hw, &hh);
2822
2823         Elm_Ctxpopup_Item_Data *next_previous_item = NULL;
2824         int viewport_position_result = _is_item_in_viewport(obj_y, h, hy, hh);
2825         if (viewport_position_result > 0)
2826           {
2827              Eina_List *l = pd->items;
2828              while(l)
2829               {
2830                  it_data = eina_list_data_get(l);
2831                  next_previous_item = it_data;
2832                  evas_object_geometry_get(VIEW(next_previous_item), &hx, &hy, &hw, &hh);
2833
2834                  if (_is_item_in_viewport(obj_y, h, hy, hh) == 0)
2835                     break;
2836                  next_previous_item = NULL;
2837
2838                  l = eina_list_next(l);
2839               }
2840           }
2841         if (next_previous_item)
2842           {
2843              elm_object_accessibility_highlight_set(EO_OBJ(next_previous_item), EINA_TRUE);
2844              elm_interface_atspi_accessible_state_changed_signal_emit(EO_OBJ(next_previous_item), ELM_ATSPI_STATE_HIGHLIGHTED, EINA_TRUE);
2845           }
2846      }
2847
2848 }
2849
2850 static void
2851 _content_move_up_cb(void *data, Evas_Object *obj, void *ev EINA_UNUSED)
2852 {
2853    if (!_elm_atspi_enabled())
2854      return ;
2855    ELM_CTXPOPUP_DATA_GET(data, pd);
2856    Elm_Ctxpopup_Item_Data *it_data;
2857    Evas_Object *highlighted_obj = _elm_object_accessibility_currently_highlighted_get();
2858
2859    if (eo_isa(highlighted_obj, ELM_WIDGET_ITEM_CLASS))
2860      {
2861         Elm_Widget_Item_Data *id = eo_data_scope_get(highlighted_obj, ELM_WIDGET_ITEM_CLASS);
2862         highlighted_obj = id->view;
2863      }
2864
2865    Evas_Object *parent = highlighted_obj;
2866
2867    if (eo_isa(highlighted_obj, ELM_WIDGET_CLASS))
2868      {
2869         while ((parent = elm_widget_parent_get(parent)))
2870           if (parent == obj)
2871             break;
2872      }
2873    else if (eo_isa(highlighted_obj, EDJE_OBJECT_CLASS))
2874      {
2875         while ((parent = evas_object_smart_parent_get(parent)))
2876           if (parent == obj)
2877             break;
2878      }
2879    // TIZEN_ONLY(20160805): set _accessibility_currently_highlighted_obj to NULL in object delete callback
2880    else
2881      {
2882         WRN("Improper highlighted object: %p", highlighted_obj);
2883         return;
2884      }
2885    //
2886
2887    if (parent)
2888      {
2889         int obj_x, obj_y, w, h, hx, hy, hw, hh;
2890         eo_do(pd->scr, elm_interface_scrollable_content_viewport_geometry_get(&obj_x, &obj_y, &w, &h));
2891         evas_object_geometry_get(highlighted_obj, &hx, &hy, &hw, &hh);
2892
2893         Elm_Ctxpopup_Item_Data *next_previous_item = NULL;
2894         int viewport_position_result = _is_item_in_viewport(obj_y, h, hy, hh);
2895         if (viewport_position_result < 0)
2896           {
2897              Eina_List *l = eina_list_last(pd->items);
2898              while(l)
2899               {
2900                  it_data = eina_list_data_get(l);
2901                  next_previous_item = it_data;
2902                  evas_object_geometry_get(VIEW(next_previous_item), &hx, &hy, &hw, &hh);
2903
2904                  if (_is_item_in_viewport(obj_y, h, hy, hh) == 0)
2905                     break;
2906                  next_previous_item = NULL;
2907
2908                  l = eina_list_prev(l);
2909               }
2910           }
2911         if (next_previous_item)
2912           {
2913              elm_object_accessibility_highlight_set(EO_OBJ(next_previous_item), EINA_TRUE);
2914              elm_interface_atspi_accessible_state_changed_signal_emit(EO_OBJ(next_previous_item), ELM_ATSPI_STATE_HIGHLIGHTED, EINA_TRUE);
2915           }
2916      }
2917
2918 }
2919 //
2920
2921 //TIZEN_ONLY ctx_popup: fix accessibility states
2922 EOLIAN static Elm_Atspi_State_Set
2923 _elm_ctxpopup_item_elm_interface_atspi_accessible_state_set_get(Eo *obj, Elm_Ctxpopup_Item_Data *it)
2924 {
2925    Elm_Atspi_State_Set states;
2926    Eina_Rectangle r1, r2;
2927    Eina_Bool is_showing = EINA_FALSE;
2928
2929    eo_do_super(obj, ELM_CTXPOPUP_ITEM_CLASS, states = elm_interface_atspi_accessible_state_set_get());
2930
2931    // evaluate showing state
2932    if (VIEW(it) &&
2933        WIDGET(it) &&
2934        evas_object_visible_get(VIEW(it)) &&
2935        _elm_widget_onscreen_is(WIDGET(it)))
2936      {
2937         ELM_CTXPOPUP_DATA_GET(WIDGET(it), sd);
2938
2939         evas_object_geometry_get(VIEW(it), &r1.x, &r1.y, &r1.w, &r1.h);
2940         evas_object_geometry_get(sd->scr, &r2.x, &r2.y, &r2.w, &r2.h);
2941
2942         if (eina_rectangles_intersect(&r1, &r2))
2943           is_showing = EINA_TRUE;
2944      }
2945
2946    if (is_showing)
2947      STATE_TYPE_SET(states, ELM_ATSPI_STATE_SHOWING);
2948    else
2949      STATE_TYPE_UNSET(states, ELM_ATSPI_STATE_SHOWING);
2950
2951    return states;
2952 }
2953 //
2954 #include "elm_ctxpopup_item.eo.c"
2955 #include "elm_ctxpopup.eo.c"