diff --git a/src/lib/efl/interfaces/efl_ui_base.eo b/src/lib/efl/interfaces/efl_ui_base.eo index b4bd11d2c0..7ddcbf0336 100644 --- a/src/lib/efl/interfaces/efl_ui_base.eo +++ b/src/lib/efl/interfaces/efl_ui_base.eo @@ -1,82 +1,90 @@ /* FIXME: Any better name? Efl.Ui? Efl.Ui.Common? */ interface Efl.Ui.Base { [[A common interface for UI objects.]] eo_prefix: efl_ui; methods { @property mirrored { [[Whether this object should be mirrored. If mirrored, an object is in RTL (right to left) mode instead of LTR (left to right). ]] - set { - [[Sets the RTL orientation for this object.]] - } - get { - [[Gets the RTL orientation for this object.]] - } values { rtl: bool(false); [[$true for RTL, $false for LTR (default).]] } } + @property mirrored_automatic { + [[Whether the property @.mirrored should be set automatically. + + If enabled, the system or application configuration will be used + to set the value of @.mirrored. + + This property may be implemented by high-level widgets (in $Efl.Ui) + but not by low-level widgets (in $Efl.Canvas) as the configuration + should affect only high-level widgets. + ]] + values { + automatic: bool(true); [[Whether the widget uses automatic mirroring]] + } + } @property language { [[The (human) language for this object.]] set { [[Sets the language for this object.]] } get { [[Gets the language for this object.]] } values { language: string; [[The current language.]] } } @property scale { [[The scaling factor of an object. This property is an individual scaling factor on the object (Edje or UI widget). This property (or Edje's global scaling factor, when applicable), will affect this object's part sizes. If scale is not zero, than the individual scaling will override any global scaling set, for the object obj's parts. Set it back to zero to get the effects of the global scaling again. Warning: In Edje, only parts which, at EDC level, had the "scale" property set to 1, will be affected by this function. Check the complete "syntax reference" for EDC files. ]] set { [[Sets the scaling factor of an object.]] } get { [[Gets an object's scaling factor.]] } values { scale: double(0.0); [[The scaling factor (the default value is 0.0, meaning individual scaling is not set)]] } } @property base_scale { [[The base scale of a layout object (read-only). The base scale refers to the scale for which the backing EDC file was designed. By default it is 1.0 which means the EDC file was designed for a scale of 1.0. This base scale can be specified in an EDC file as the collections' "base_scale" field. If the object is not a layout, this will return 1.0. ]] get { [[Gets a given layout object's base_scale factor.]] } values { base_scale: double(1.0); [[The base_scale factor (the default value is 1.0, meaning that the edc file was designed based on scale 1.0).]] } } } } diff --git a/src/lib/elementary/elc_combobox.c b/src/lib/elementary/elc_combobox.c index 606e735ff0..df06061058 100644 --- a/src/lib/elementary/elc_combobox.c +++ b/src/lib/elementary/elc_combobox.c @@ -1,568 +1,568 @@ #ifdef HAVE_CONFIG_H # include "elementary_config.h" #endif #define ELM_INTERFACE_ATSPI_ACCESSIBLE_PROTECTED #define ELM_INTERFACE_ATSPI_WIDGET_ACTION_PROTECTED #include #include "elm_priv.h" #include "elm_widget_combobox.h" #define MY_CLASS ELM_COMBOBOX_CLASS #define MY_CLASS_NAME "Elm_Combobox" #define MY_CLASS_NAME_LEGACY "elm_combobox" static const char SIG_DISMISSED[] = "dismissed"; static const char SIG_EXPANDED[] = "expanded"; static const char SIG_ITEM_SELECTED[] = "item,selected"; static const char SIG_ITEM_PRESSED[] = "item,pressed"; static const char SIG_FILTER_DONE[] = "filter,done"; static const char SIG_CLICKED[] = "clicked"; static const Evas_Smart_Cb_Description _smart_callbacks[] = { {SIG_DISMISSED, ""}, {SIG_EXPANDED, ""}, {SIG_ITEM_SELECTED, ""}, {SIG_ITEM_PRESSED, ""}, {SIG_FILTER_DONE, ""}, {SIG_CLICKED, ""}, /**< handled by parent button class */ {SIG_WIDGET_LANG_CHANGED, ""}, /**< handled by elm_widget */ {SIG_WIDGET_ACCESS_CHANGED, ""}, /**< handled by elm_widget */ {NULL, NULL} }; static void _table_resize(void *data); static Eina_Bool _key_action_move(Evas_Object *obj, const char *params); static Eina_Bool _key_action_activate(Evas_Object *obj, const char *params); static const Elm_Action key_actions[] = { {"activate", _key_action_activate}, {"move", _key_action_move}, {NULL, NULL} }; EOLIAN static Eina_Bool _elm_combobox_elm_widget_translate(Eo *obj EINA_UNUSED, Elm_Combobox_Data *sd) { elm_obj_widget_translate(efl_super(obj, MY_CLASS)); elm_obj_widget_translate(sd->genlist); elm_obj_widget_translate(sd->entry); if (sd->hover) elm_obj_widget_translate(sd->hover); return EINA_TRUE; } EOLIAN static Elm_Theme_Apply _elm_combobox_elm_widget_theme_apply(Eo *obj, Elm_Combobox_Data *sd) { const char *style; Elm_Theme_Apply int_ret = ELM_THEME_APPLY_FAILED; Eina_Bool mirrored; char buf[128]; ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd, ELM_THEME_APPLY_FAILED); style = eina_stringshare_add(elm_widget_style_get(obj)); snprintf(buf, sizeof(buf), "combobox_vertical/%s", style); /* combobox's style has no extra bit for orientation but could have... */ eina_stringshare_replace(&(wd->style), buf); int_ret = elm_obj_widget_theme_apply(efl_super(obj, MY_CLASS)); if (!int_ret) return ELM_THEME_APPLY_FAILED; eina_stringshare_replace(&(wd->style), style); mirrored = efl_ui_mirrored_get(obj); if (sd->hover) { efl_ui_mirrored_set(sd->hover, mirrored); elm_widget_style_set(sd->hover, buf); } efl_ui_mirrored_set(sd->genlist, mirrored); efl_ui_mirrored_set(sd->entry, mirrored); elm_widget_style_set(sd->genlist, buf); elm_widget_style_set(sd->entry, buf); eina_stringshare_del(style); return int_ret; } static void _on_hover_clicked(void *data, const Efl_Event *event) { const char *dismissstr; dismissstr = elm_layout_data_get(event->object, "dismiss"); if (!dismissstr || strcmp(dismissstr, "on")) elm_combobox_hover_end(data); // for backward compatibility } static void _hover_end_finished(void *data, Evas_Object *obj EINA_UNUSED, const char *emission EINA_UNUSED, const char *source EINA_UNUSED) { const char *dismissstr; ELM_COMBOBOX_DATA_GET(data, sd); dismissstr = elm_layout_data_get(sd->hover, "dismiss"); if (dismissstr && !strcmp(dismissstr, "on")) { sd->expanded = EINA_FALSE; evas_object_hide(sd->hover); efl_event_callback_legacy_call(data, ELM_COMBOBOX_EVENT_DISMISSED, NULL); } } static void count_items_genlist(void *data) { ELM_COMBOBOX_DATA_GET(data, sd); Eina_Iterator *filter_iter; int count = 0; Elm_Object_Item *item; filter_iter = elm_genlist_filter_iterator_new(sd->genlist); if (!filter_iter) return; EINA_ITERATOR_FOREACH(filter_iter, item) if (item) count++; sd->count = count; eina_iterator_free(filter_iter); } static void _item_realized(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) { _table_resize(data); } static void _table_resize(void *data) { ELM_COMBOBOX_DATA_GET(data, sd); if (sd->count > 0) { int hover_parent_w, hover_parent_h, obj_h, obj_w, obj_y, win_y_offset; int current_height, h; Eina_List *realized; sd->item = elm_genlist_first_item_get(sd->genlist); if (!(realized = elm_genlist_realized_items_get(sd->genlist))) { //nothing realized and wait until at least one item is realized h = 1; evas_object_smart_callback_add(sd->genlist, "realized", _item_realized, data); } else { // take the first, and update according to that evas_object_geometry_get(elm_object_item_track(eina_list_data_get(realized)), NULL, NULL, NULL, &h); } sd->item_height = h; evas_object_geometry_get(sd->entry, NULL, NULL, &obj_w, NULL); evas_object_geometry_get(data, NULL, &obj_y, NULL, &obj_h); evas_object_geometry_get(sd->hover_parent, NULL, NULL, &hover_parent_w, &hover_parent_h); current_height = sd->item_height * sd->count; sd->best_location = elm_hover_best_content_location_get(sd->hover, ELM_HOVER_AXIS_VERTICAL); if (sd->best_location && !strcmp(sd->best_location , "bottom")) win_y_offset = hover_parent_h - obj_y - obj_h; else win_y_offset = obj_y; if (current_height < win_y_offset) evas_object_size_hint_min_set(sd->spacer, obj_w * elm_config_scale_get(), current_height + (2 * elm_config_scale_get())); else evas_object_size_hint_min_set(sd->spacer, obj_w * elm_config_scale_get(), win_y_offset * elm_config_scale_get()); } } static void _activate(Evas_Object *obj) { ELM_COMBOBOX_DATA_GET(obj, sd); if (elm_widget_disabled_get(obj)) return; if (sd->expanded) { elm_combobox_hover_end(obj); return; } sd->expanded = EINA_TRUE; count_items_genlist(obj); if (sd->count <= 0) return; _table_resize(obj); elm_object_part_content_set(sd->hover, sd->best_location, sd->tbl); evas_object_show(sd->genlist); elm_genlist_item_selected_set(sd->item, EINA_TRUE); evas_object_show(sd->hover); efl_event_callback_legacy_call(obj, ELM_COMBOBOX_EVENT_EXPANDED, NULL); } static void _on_item_selected(void *data , Evas_Object *obj EINA_UNUSED, void *event) { ELM_COMBOBOX_DATA_GET(data, sd); elm_object_focus_set(sd->entry, EINA_TRUE); efl_event_callback_legacy_call(data, ELM_COMBOBOX_EVENT_ITEM_SELECTED, event); } static void _on_item_pressed(void *data , Evas_Object *obj EINA_UNUSED, void *event) { efl_event_callback_legacy_call(data, ELM_COMBOBOX_EVENT_ITEM_PRESSED, event); } static void _gl_filter_finished_cb(void *data, const Efl_Event *event) { char buf[1024]; ELM_COMBOBOX_DATA_GET(data, sd); count_items_genlist(data); if (sd->first_filter) { sd->first_filter = EINA_FALSE; return; } efl_event_callback_legacy_call(data, ELM_COMBOBOX_EVENT_FILTER_DONE, event->info); if (sd->count > 0) { if (!sd->expanded) _activate(data); else _table_resize(data); elm_genlist_item_selected_set(sd->item, EINA_TRUE); } else { sd->expanded = EINA_FALSE; elm_layout_signal_emit(sd->hover, "elm,action,hide,no_animate", "elm"); snprintf(buf, sizeof(buf), "elm,action,slot,%s,hide", sd->best_location); elm_layout_signal_emit(sd->hover, buf, "elm"); edje_object_message_signal_process(elm_layout_edje_get(sd->hover)); } } static void _on_aborted(void *data, const Efl_Event *event EINA_UNUSED) { ELM_COMBOBOX_DATA_GET(data, sd); if (sd->expanded) elm_combobox_hover_end(data); } static void _on_changed(void *data, const Efl_Event *event EINA_UNUSED) { efl_event_callback_legacy_call(data, ELM_ENTRY_EVENT_CHANGED, NULL); } static void _on_clicked(void *data, const Efl_Event *event EINA_UNUSED) { elm_combobox_hover_begin(data); } EOLIAN static void _elm_combobox_efl_canvas_group_group_add(Eo *obj, Elm_Combobox_Data *sd EINA_UNUSED) { efl_canvas_group_add(efl_super(obj, MY_CLASS)); elm_widget_sub_object_parent_add(obj); - elm_widget_mirrored_automatic_set(obj, EINA_FALSE); + efl_ui_mirrored_automatic_set(obj, EINA_FALSE); efl_event_callback_add(obj, EFL_UI_EVENT_CLICKED, _on_clicked, obj); //What are you doing here? elm_obj_widget_theme_apply(obj); } EOLIAN static void _elm_combobox_efl_canvas_group_group_del(Eo *obj, Elm_Combobox_Data *sd) { sd->hover_parent = NULL; efl_canvas_group_del(efl_super(obj, MY_CLASS)); } EOLIAN static void _elm_combobox_efl_gfx_visible_set(Eo *obj, Elm_Combobox_Data *sd, Eina_Bool vis) { if (_evas_object_intercept_call(obj, EVAS_OBJECT_INTERCEPT_CB_VISIBLE, 0, vis)) return; efl_gfx_visible_set(efl_super(obj, MY_CLASS), vis); if (vis) { if (sd->expanded) evas_object_show(sd->hover); } else { if (sd->hover) evas_object_hide(sd->hover); } } EOLIAN static Eina_Bool _elm_combobox_efl_ui_autorepeat_autorepeat_supported_get(Eo *obj EINA_UNUSED, Elm_Combobox_Data *sd EINA_UNUSED) { return EINA_FALSE; } EAPI Evas_Object * elm_combobox_add(Evas_Object *parent) { EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL); Evas_Object *obj = efl_add(MY_CLASS, parent); return obj; } EOLIAN static Eo * _elm_combobox_efl_object_constructor(Eo *obj, Elm_Combobox_Data *sd) { Evas_Object *gl; Evas_Object *entry; char buf[128]; obj = efl_constructor(efl_super(obj, MY_CLASS)); sd->first_filter = EINA_TRUE; efl_canvas_object_type_set(obj, MY_CLASS_NAME_LEGACY); evas_object_smart_callbacks_descriptions_set(obj, _smart_callbacks); elm_interface_atspi_accessible_role_set(obj, ELM_ATSPI_ROLE_GLASS_PANE); //hover-parent sd->hover_parent = elm_object_top_widget_get(obj); //hover sd->hover = efl_add(ELM_HOVER_CLASS, sd->hover_parent); evas_object_layer_set(sd->hover, EVAS_LAYER_MAX); - elm_widget_mirrored_automatic_set(sd->hover, EINA_FALSE); + efl_ui_mirrored_automatic_set(sd->hover, EINA_FALSE); elm_hover_target_set(sd->hover, obj); elm_widget_sub_object_add(obj, sd->hover); snprintf(buf, sizeof(buf), "combobox_vertical/%s", elm_widget_style_get(obj)); elm_object_style_set(sd->hover, buf); efl_event_callback_add (sd->hover, EFL_UI_EVENT_CLICKED, _on_hover_clicked, obj); elm_layout_signal_callback_add (sd->hover, "elm,action,hide,finished", "elm", _hover_end_finished, obj); //table sd->tbl = elm_table_add(obj); evas_object_size_hint_weight_set(sd->tbl, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); evas_object_size_hint_align_set(sd->tbl, EVAS_HINT_FILL, EVAS_HINT_FILL); //spacer sd->spacer = evas_object_rectangle_add(evas_object_evas_get(sd->hover_parent)); evas_object_size_hint_weight_set(sd->spacer, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); evas_object_size_hint_align_set(sd->spacer, EVAS_HINT_FILL, EVAS_HINT_FILL); evas_object_color_set(sd->spacer, 0, 0, 0, 0); elm_table_pack(sd->tbl, sd->spacer, 0, 0, 1, 1); // This is the genlist object that will take over the genlist call sd->genlist = gl = efl_add(ELM_GENLIST_CLASS, obj); elm_genlist_filter_set(gl, NULL); - elm_widget_mirrored_automatic_set(gl, EINA_FALSE); + efl_ui_mirrored_automatic_set(gl, EINA_FALSE); efl_ui_mirrored_set(gl, efl_ui_mirrored_get(obj)); evas_object_size_hint_weight_set(gl, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); evas_object_size_hint_align_set(gl, EVAS_HINT_FILL, EVAS_HINT_FILL); evas_object_smart_callback_add(gl, "selected", _on_item_selected, obj); evas_object_smart_callback_add(gl, "pressed", _on_item_pressed, obj); efl_event_callback_add(gl, ELM_GENLIST_EVENT_FILTER_DONE, _gl_filter_finished_cb, obj); elm_genlist_homogeneous_set(gl, EINA_TRUE); elm_genlist_mode_set(gl, ELM_LIST_COMPRESS); elm_table_pack(sd->tbl, gl, 0, 0, 1, 1); elm_object_style_set(gl, buf); // This is the entry object that will take over the entry call sd->entry = entry = efl_add(ELM_ENTRY_CLASS, obj); - elm_widget_mirrored_automatic_set(entry, EINA_FALSE); + efl_ui_mirrored_automatic_set(entry, EINA_FALSE); efl_ui_mirrored_set(entry, efl_ui_mirrored_get(obj)); elm_scroller_policy_set(entry, ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_OFF); elm_entry_scrollable_set(entry, EINA_TRUE); elm_entry_single_line_set(entry, EINA_TRUE); efl_event_callback_add(entry, ELM_ENTRY_EVENT_CHANGED_USER, _on_changed, obj); efl_event_callback_add(entry, ELM_ENTRY_EVENT_ABORTED, _on_aborted, obj); evas_object_show(entry); elm_object_part_content_set(obj, "elm.swallow.content", entry); elm_object_style_set(entry, buf); efl_composite_attach(obj, gl); efl_composite_attach(obj, entry); return obj; } EOLIAN static void _elm_combobox_hover_begin(Eo *obj, Elm_Combobox_Data *sd) { if (!sd->hover) return; elm_object_focus_set(sd->entry, EINA_TRUE); _activate(obj); } EOLIAN static void _elm_combobox_hover_end(Eo *obj, Elm_Combobox_Data *sd) { const char *dismissstr; if (!sd->hover) return; dismissstr = elm_layout_data_get(sd->hover, "dismiss"); if (dismissstr && !strcmp(dismissstr, "on")) elm_hover_dismiss(sd->hover); else { sd->expanded = EINA_FALSE; evas_object_hide(sd->hover); efl_event_callback_legacy_call(obj, ELM_COMBOBOX_EVENT_DISMISSED, NULL); } // for backward compatibility } EOLIAN static Eina_Bool _elm_combobox_expanded_get(Eo *obj EINA_UNUSED, Elm_Combobox_Data *sd) { return sd->expanded; } static Eina_Bool _key_action_move(Evas_Object *obj, const char *params) { ELM_COMBOBOX_DATA_GET(obj, sd); Elm_Object_Item *it = NULL; const char *dir = params; if (!sd->hover) return EINA_FALSE; if (!strcmp(dir, "up")) { it = sd->item; it = elm_genlist_item_prev_get(it); if (!it) sd->item = elm_genlist_last_item_get(sd->genlist); else sd->item = it; elm_genlist_item_selected_set(sd->item, EINA_TRUE); } else if (!strcmp(dir, "down")) { it = sd->item; it = elm_genlist_item_next_get(it); if (!it) sd->item = elm_genlist_first_item_get(sd->genlist); else sd->item = it; elm_genlist_item_selected_set(sd->item, EINA_TRUE); } else return EINA_FALSE; return EINA_TRUE; } static Eina_Bool _key_action_activate(Evas_Object *obj, const char *params EINA_UNUSED) { ELM_COMBOBOX_DATA_GET(obj, sd); if (!sd->expanded) elm_combobox_hover_begin(obj); else { efl_event_callback_legacy_call(sd->genlist, EFL_UI_EVENT_PRESSED, sd->item); elm_entry_cursor_end_set(sd->entry); } return EINA_TRUE; } EOLIAN static Eina_Bool _elm_combobox_elm_widget_widget_event(Eo *obj, Elm_Combobox_Data *sd, Evas_Object *src EINA_UNUSED, Evas_Callback_Type type, void *event_info) { Evas_Event_Key_Down *ev = event_info; if (!sd || !sd->hover) return EINA_FALSE; if (type != EVAS_CALLBACK_KEY_DOWN) return EINA_FALSE; if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return EINA_FALSE; if (!_elm_config_key_binding_call(obj, MY_CLASS_NAME, ev, key_actions)) return EINA_FALSE; ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD; return EINA_TRUE; } static void _elm_combobox_class_constructor(Efl_Class *klass) { evas_smart_legacy_type_register(MY_CLASS_NAME_LEGACY, klass); } EOLIAN const Elm_Atspi_Action * _elm_combobox_elm_interface_atspi_widget_action_elm_actions_get(Eo *obj EINA_UNUSED, Elm_Combobox_Data *pd EINA_UNUSED) { static Elm_Atspi_Action atspi_actions[] = { {"activate", "activate", "return", _key_action_activate}, {"move,up", "move", "up", _key_action_move}, {"move,down", "move", "down", _key_action_move}, {NULL, NULL, NULL, NULL} }; return &atspi_actions[0]; } EOLIAN void _elm_combobox_elm_genlist_filter_set(Eo *obj EINA_UNUSED, Elm_Combobox_Data *pd, void *key) { pd->first_filter = EINA_FALSE; elm_obj_genlist_filter_set(pd->genlist, key); } EOLIAN void _elm_combobox_elm_widget_part_text_set(Eo *obj EINA_UNUSED, Elm_Combobox_Data *pd, const char * part, const char *label) { elm_object_part_text_set(pd->entry, part, label); } EOLIAN const char * _elm_combobox_elm_widget_part_text_get(Eo *obj EINA_UNUSED, Elm_Combobox_Data *pd, const char * part) { return elm_object_part_text_get(pd->entry, part); } EOLIAN static void _elm_combobox_efl_gfx_size_set(Eo *obj, Elm_Combobox_Data *pd, Evas_Coord w, Evas_Coord h) { if (_evas_object_intercept_call(obj, EVAS_OBJECT_INTERCEPT_CB_RESIZE, 0, w, h)) return; if (pd->count > 0) _table_resize(obj); efl_gfx_size_set(efl_super(obj, MY_CLASS), w, h); } /* Internal EO APIs and hidden overrides */ #define ELM_COMBOBOX_EXTRA_OPS \ EFL_CANVAS_GROUP_ADD_DEL_OPS(elm_combobox) #include "elm_combobox.eo.c" diff --git a/src/lib/elementary/elc_fileselector.c b/src/lib/elementary/elc_fileselector.c index 795a2f9abf..ffdc8444d2 100644 --- a/src/lib/elementary/elc_fileselector.c +++ b/src/lib/elementary/elc_fileselector.c @@ -1,3208 +1,3208 @@ /* * TODO: * - child elements focusing support * - user defined icon/label cb * - show/hide/add buttons ??? * - Pattern Filter support */ #ifdef HAVE_CONFIG_H # include "elementary_config.h" #endif #define ELM_INTERFACE_ATSPI_ACCESSIBLE_PROTECTED #define ELM_INTERFACE_ATSPI_WIDGET_ACTION_PROTECTED #include #include "elm_priv.h" #include "elm_fileselector_button.eo.h" #include "elm_fileselector_entry.eo.h" #include "elm_interface_fileselector.h" #include "elm_widget_fileselector.h" #include "elm_fileselector_internal_part.eo.h" #include "elm_part_helper.h" #define MY_CLASS ELM_FILESELECTOR_CLASS #define MY_CLASS_NAME "Elm_Fileselector" #define MY_CLASS_NAME_LEGACY "elm_fileselector" /* FIXME: need a way to find a gap between the size of item and thumbnail */ #define ITEM_SIZE_DEFAULT 70 typedef struct _Legacy_Event_Path_Then_Data { Eo *eo_obj; const Efl_Event_Description *evt_desc; } Legacy_Event_Path_Then_Data; static Elm_Genlist_Item_Class *list_itc[ELM_FILE_LAST]; static Elm_Gengrid_Item_Class *grid_itc[ELM_FILE_LAST]; static const char _text_activated_model_key[] = "__fs_text_activated_model"; static const char _text_activated_path_key[] = "__fs_text_activated_path"; static const char _selected_model_set_promise_owner_key[] = "__fs_selected_model_set_promise_owner"; static const char _selected_model_set_model_key[] = "__fs_selected_model_set_model"; EAPI Eina_Error ELM_FILESELECTOR_ERROR_UNKNOWN = 0; EAPI Eina_Error ELM_FILESELECTOR_ERROR_INVALID_MODEL = 0; static const char ELM_FILESELECTOR_ERROR_UNKNOWN_STR[] = "Unknown Error"; static const char ELM_FILESELECTOR_ERROR_INVALID_MODEL_STR[] = "Model not set"; #define ELM_PRIV_FILESELECTOR_SIGNALS(cmd) \ cmd(SIG_ACTIVATED, "activated", "s") \ cmd(SIG_DIRECTORY_OPEN, "directory,open", "s") \ cmd(SIG_DONE, "done", "s") \ cmd(SIG_SELECTED, "selected", "s") \ cmd(SIG_SELECTED_INVALID, "selected,invalid", "s") ELM_PRIV_FILESELECTOR_SIGNALS(ELM_PRIV_STATIC_VARIABLE_DECLARE); static const Evas_Smart_Cb_Description _smart_callbacks[] = { ELM_PRIV_FILESELECTOR_SIGNALS(ELM_PRIV_SMART_CALLBACKS_DESC) {SIG_LAYOUT_FOCUSED, ""}, /**< handled by elm_layout */ {SIG_LAYOUT_UNFOCUSED, ""}, /**< handled by elm_layout */ {NULL, NULL} }; #undef ELM_PRIV_FILESELECTOR_SIGNALS static Eina_Bool _key_action_select(Evas_Object *obj, const char *params); static Eina_Bool _key_action_escape(Evas_Object *obj, const char *params); static Eina_Bool _key_action_backspace(Evas_Object *obj, const char *params); static const Elm_Action key_actions[] = { {"select", _key_action_select}, {"escape", _key_action_escape}, {"backspace", _key_action_backspace}, {NULL, NULL} }; static void _ok(void *data, const Efl_Event *event); static void _canc(void *data, const Efl_Event *event); static void _on_dir_up(void *data, const Efl_Event *event); static void _populate(Evas_Object *obj, Efl_Model *model, Elm_Object_Item *parent_it, Efl_Model *selected); static Elm_Fileselector_Item_Data *_selected_item_data_get(Elm_Fileselector_Data *sd); static void _resource_created(void *, const Efl_Event *); static void _resource_deleted(void *, const Efl_Event *); static void _listing_request_cleanup(Listing_Request *); EFL_CALLBACKS_ARRAY_DEFINE(monitoring_callbacks, { EFL_MODEL_EVENT_CHILD_ADDED, _resource_created }, { EFL_MODEL_EVENT_CHILD_REMOVED, _resource_deleted }); static void _model_free_eo_cb(void *data) { Eo *eo = data; efl_unref(eo); } void _event_to_legacy_call(Eo *obj, const Efl_Event_Description *evt_desc, void *event_info) { const Efl_Event_Description *legacy_desc = efl_object_legacy_only_event_description_get(evt_desc->name); efl_event_callback_call(obj, legacy_desc, event_info); } void _model_event_call(Eo *obj, const Efl_Event_Description *evt_desc, Efl_Model *model, const char *path) { _event_to_legacy_call(obj, evt_desc, (void *)path); efl_event_callback_call(obj, evt_desc, model); } static void _monitoring_start(Elm_Fileselector *fs, Elm_Fileselector_Data *sd, Efl_Model *model) { sd->monitoring = EINA_TRUE; efl_event_callback_array_add(model, monitoring_callbacks(), fs); } static void _monitoring_stop(Elm_Fileselector *fs, Elm_Fileselector_Data *sd, Efl_Model *model) { sd->monitoring = EINA_FALSE; efl_event_callback_array_del(model, monitoring_callbacks(), fs); } static void _elm_fileselector_replace_model(Elm_Fileselector *fs, Elm_Fileselector_Data *sd, Efl_Model *model, const char *path) { if (sd->model) { _monitoring_stop(fs, sd, sd->model); efl_unref(sd->model); } if (model && path) { sd->model = efl_ref(model); eina_stringshare_replace(&sd->path, path); _monitoring_start(fs, sd, sd->model); /* TODO: sub directory should be monitored for expand mode */ } else { sd->model = NULL; eina_stringshare_replace(&sd->path, NULL); } } /* final routine on deletion */ static void _elm_fileselector_smart_del_do(Elm_Fileselector *fs, Elm_Fileselector_Data *sd) { _elm_fileselector_replace_model(fs, sd, NULL, NULL); if (sd->prev_model) efl_unref(sd->prev_model); free(ecore_idler_del(sd->populate_idler)); ecore_idler_del(sd->path_entry_idler); efl_canvas_group_del(efl_super(sd->obj, MY_CLASS)); } static void _mirrored_set(Evas_Object *obj, Eina_Bool rtl) { ELM_FILESELECTOR_DATA_GET(obj, sd); efl_ui_mirrored_set(sd->cancel_button, rtl); efl_ui_mirrored_set(sd->ok_button, rtl); efl_ui_mirrored_set(sd->files_view, rtl); efl_ui_mirrored_set(sd->up_button, rtl); efl_ui_mirrored_set(sd->home_button, rtl); } static Eina_Bool _accessor_value_get(Eina_Accessor *acc, int id, void *res) { Eina_Value *v = NULL; if (!eina_accessor_data_get(acc, id, (void **) &v)) return EINA_FALSE; eina_value_get(v, res); return EINA_TRUE; } static Efl_Future* _model_str_property_set(Efl_Model *model, const char *property_name, const char *property_value) { Efl_Future* r; Eina_Value v; eina_value_setup(&v, EINA_VALUE_TYPE_STRING); eina_value_set(&v, property_value); r = efl_model_property_set(model, property_name, &v); eina_value_flush(&v); return r; } EOLIAN static Elm_Theme_Apply _elm_fileselector_elm_widget_theme_apply(Eo *obj, Elm_Fileselector_Data *sd) { const char *style; const char *data; char buf[1024]; Elm_Theme_Apply int_ret = ELM_THEME_APPLY_FAILED; int_ret = elm_obj_widget_theme_apply(efl_super(obj, MY_CLASS)); if (!int_ret) return ELM_THEME_APPLY_FAILED; style = elm_widget_style_get(obj); _mirrored_set(obj, efl_ui_mirrored_get(obj)); ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd, EINA_FALSE); data = edje_object_data_get (wd->resize_obj, "path_separator"); if (data) sd->path_separator = data; else sd->path_separator = "/"; snprintf(buf, sizeof(buf), "fileselector/%s", style); elm_widget_style_set(sd->up_button, buf); elm_widget_style_set(sd->home_button, buf); elm_widget_style_set(sd->spinner, buf); elm_widget_style_set(sd->files_view, buf); elm_widget_style_set(sd->path_entry, buf); elm_widget_style_set(sd->name_entry, buf); elm_widget_style_set(sd->search_entry, buf); snprintf(buf, sizeof(buf), "fileselector/actions/%s", style); if (sd->filter_hoversel) elm_widget_style_set(sd->filter_hoversel, buf); if (sd->ok_button) { elm_widget_style_set(sd->cancel_button, buf); elm_widget_style_set(sd->ok_button, buf); } return int_ret; } static Eina_Bool _key_action_select(Evas_Object *obj, const char *params EINA_UNUSED) { Efl_Event event = {}; _ok(obj, &event); return EINA_TRUE; } static Eina_Bool _key_action_escape(Evas_Object *obj, const char *params EINA_UNUSED) { Efl_Event event = {}; _canc(obj, &event); return EINA_TRUE; } static Eina_Bool _key_action_backspace(Evas_Object *obj, const char *params EINA_UNUSED) { ELM_FILESELECTOR_DATA_GET(obj, sd); if (sd->prev_model) { _populate(obj, sd->prev_model, NULL, NULL); efl_unref(sd->prev_model); sd->prev_model = NULL; } else _on_dir_up(obj, NULL); return EINA_TRUE; } EOLIAN static Eina_Bool _elm_fileselector_elm_widget_widget_event(Eo *obj, Elm_Fileselector_Data *sd EINA_UNUSED, Evas_Object *src, Evas_Callback_Type type, void *event_info) { Evas_Event_Key_Down *ev = event_info; (void) src; if (type != EVAS_CALLBACK_KEY_DOWN) return EINA_FALSE; if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return EINA_FALSE; if (!_elm_config_key_binding_call(obj, MY_CLASS_NAME, ev, key_actions)) return EINA_FALSE; ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD; return EINA_TRUE; } /*** GENLIST/GENGRID "MODEL" ***/ static char * _itc_text_get(void *data, Evas_Object *obj EINA_UNUSED, const char *source EINA_UNUSED) { Elm_Fileselector_Item_Data *it_data = data; return elm_entry_utf8_to_markup (it_data->filename); /* NOTE this will be free()'d by * the caller */ } static Evas_Object * _itc_icon_folder_get(void *data EINA_UNUSED, Evas_Object *obj, const char *source) { Evas_Object *ic, *grid; if (strcmp(source, "elm.swallow.icon")) return NULL; ic = elm_icon_add(obj); elm_icon_standard_set(ic, "folder"); evas_object_size_hint_aspect_set(ic, EVAS_ASPECT_CONTROL_VERTICAL, 1, 1); evas_object_show(ic); grid = elm_grid_add(obj); elm_grid_size_set(grid, 1, 1); elm_grid_pack(grid, ic, 0, 0, 1, 1); evas_object_show(grid); return grid; } static Evas_Object * _itc_icon_image_get(void *data, Evas_Object *obj, const char *source) { Elm_Fileselector_Item_Data *it_data = data; Evas_Object *ic, *grid; if (strcmp(source, "elm.swallow.icon")) return NULL; ic = elm_icon_add(obj); elm_icon_standard_set(ic, "image"); // FIXME: maybe use Efl.Model.connect elm_icon_thumb_set(ic, it_data->path, NULL); evas_object_size_hint_aspect_set(ic, EVAS_ASPECT_CONTROL_VERTICAL, 1, 1); evas_object_show(ic); grid = elm_grid_add(obj); elm_grid_size_set(grid, 1, 1); elm_grid_pack(grid, ic, 0, 0, 1, 1); evas_object_show(grid); return grid; } static Evas_Object * _itc_icon_file_get(void *data EINA_UNUSED, Evas_Object *obj, const char *source) { Evas_Object *ic, *grid; if (strcmp(source, "elm.swallow.icon")) return NULL; ic = elm_icon_add(obj); elm_icon_standard_set(ic, "file"); evas_object_size_hint_aspect_set(ic, EVAS_ASPECT_CONTROL_VERTICAL, 1, 1); evas_object_show(ic); grid = elm_grid_add(obj); elm_grid_size_set(grid, 1, 1); elm_grid_pack(grid, ic, 0, 0, 1, 1); evas_object_show(grid); return grid; } static Eina_Bool _itc_state_get(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, const char *source EINA_UNUSED) { return EINA_FALSE; } static void _itc_del(void *data, Evas_Object *obj EINA_UNUSED) { Elm_Fileselector_Item_Data *it_data = data; efl_unref(it_data->model); eina_stringshare_del(it_data->path); eina_stringshare_del(it_data->filename); eina_stringshare_del(it_data->mime_type); efl_unref(it_data->parent_model); eina_stringshare_del(it_data->parent_path); free(it_data); } static void _anchors_do(Evas_Object *obj, const char *path) { char **tok, buf[PATH_MAX * 3], *s; int i, j; ELM_FILESELECTOR_DATA_GET(obj, sd); s = elm_entry_utf8_to_markup(path); if (!s) return; buf[0] = '\0'; tok = eina_str_split(s, "/", 0); free(s); eina_strlcat(buf, "root", sizeof(buf)); for (i = 0; tok[i]; i++) { if ((!tok[i]) || (!tok[i][0])) continue; eina_strlcat(buf, sd->path_separator, sizeof(buf)); eina_strlcat(buf, "", sizeof(buf)); eina_strlcat(buf, tok[i], sizeof(buf)); eina_strlcat(buf, "", sizeof(buf)); } free(tok[0]); free(tok); elm_object_text_set(sd->path_entry, buf); } static Eina_Bool _mime_type_matched(const char *mime_filter, const char *mime_type) { int i = 0; while (mime_filter[i] != '\0') { if (mime_filter[i] != mime_type[i]) { if (mime_filter[i] == '*' && mime_filter[i + 1] == '\0') return EINA_TRUE; return EINA_FALSE; } i++; } if (mime_type[i] != '\0') return EINA_FALSE; return EINA_TRUE; } static Eina_Bool _is_in_filter(const Elm_Fileselector_Filter *filter, const char *mime_type) { int i; if (!mime_type) return EINA_FALSE; for (i = 0; filter->filter.mime_types[i]; ++i) { if (_mime_type_matched(filter->filter.mime_types[i], mime_type)) return EINA_TRUE; } return EINA_FALSE; } static Eina_Bool _filter_child(Elm_Fileselector_Data* sd, const char *path, const char *filename, Eina_Bool dir, const char *mime_type) { Elm_Fileselector_Filter *cf; char *pch = NULL, *temp = NULL; char temp_path[EINA_PATH_MAX]; if (!sd) return EINA_FALSE; if (!sd->hidden_visible && filename[0] == '.') return EINA_FALSE; if (sd->only_folder && !dir) return EINA_FALSE; //Search entry filter if ((sd->search_string) && (sd->search_string[0] != '\0')) { strncpy(temp_path, path, sizeof(temp_path) - 1); temp_path[sizeof(temp_path) - 1] = 0; pch = strchr(temp_path, EINA_PATH_SEP_C); while (pch != NULL) { temp = pch; pch = strchr(pch + 1, EINA_PATH_SEP_C); } temp++; if ((temp) && (sd->search_string) && (!strstr(temp, sd->search_string))) return EINA_FALSE; } cf = sd->current_filter; if (!cf) return EINA_TRUE; switch (cf->filter_type) { case ELM_FILESELECTOR_MIME_FILTER: return dir || _is_in_filter(cf, mime_type); case ELM_FILESELECTOR_CUSTOM_FILTER: return cf->filter.custom->func(path, dir, cf->filter.custom->data); default: return EINA_FALSE; } return EINA_FALSE; } static const char * _file_type(const char *a) { char *p = strrchr(a, '.'); if (!p) return ""; return p; } static int _filename_cmp(const Elm_Fileselector_Item_Data *a, const Elm_Fileselector_Item_Data *b) { return strcoll(a->filename, b->filename); } static int _filename_cmp_rev(const Elm_Fileselector_Item_Data *a, const Elm_Fileselector_Item_Data *b) { return _filename_cmp(b, a); } static int _type_cmp(const Elm_Fileselector_Item_Data *a, const Elm_Fileselector_Item_Data *b) { return strcoll(_file_type(a->filename), _file_type(b->filename)); } static int _type_cmp_rev(const Elm_Fileselector_Item_Data *a, const Elm_Fileselector_Item_Data *b) { return _type_cmp(b, a); } static int _size_cmp(const Elm_Fileselector_Item_Data *a, const Elm_Fileselector_Item_Data *b) { return a->size - b->size; } static int _size_cmp_rev(const Elm_Fileselector_Item_Data *a, const Elm_Fileselector_Item_Data *b) { return _size_cmp(b, a); } static int _modified_cmp(const Elm_Fileselector_Item_Data *a, const Elm_Fileselector_Item_Data *b) { if (a->mtime > b->mtime) return 1; return -1; } static int _modified_cmp_rev(const Elm_Fileselector_Item_Data *a, const Elm_Fileselector_Item_Data *b) { return _modified_cmp(b, a); } static int _file_grid_cmp(const void *a, const void *b) { Evas_Object *f; const Elm_Object_Item *ga = a; const Elm_Object_Item *gb = b; const Elm_Gengrid_Item_Class *ca = elm_gengrid_item_item_class_get(ga); const Elm_Gengrid_Item_Class *cb = elm_gengrid_item_item_class_get(gb); if (ca == grid_itc[ELM_DIRECTORY]) { if (cb != grid_itc[ELM_DIRECTORY]) return -1; } else if (cb == grid_itc[ELM_DIRECTORY]) { return 1; } f = evas_object_data_get(elm_object_item_widget_get(ga), "parent"); ELM_FILESELECTOR_DATA_GET(f, sd); return sd->sort_method(elm_object_item_data_get(ga), elm_object_item_data_get(gb)); } static int _file_list_cmp(const void *a, const void *b) { Evas_Object *f; const Elm_Object_Item *la = a; const Elm_Object_Item *lb = b; const Elm_Genlist_Item_Class *ca = elm_genlist_item_item_class_get(la); const Elm_Genlist_Item_Class *cb = elm_genlist_item_item_class_get(lb); if (ca == list_itc[ELM_DIRECTORY]) { if (cb != list_itc[ELM_DIRECTORY]) return -1; } else if (cb == list_itc[ELM_DIRECTORY]) { return 1; } f = evas_object_data_get(elm_object_item_widget_get(la), "parent"); ELM_FILESELECTOR_DATA_GET(f, sd); return sd->sort_method(elm_object_item_data_get(la), elm_object_item_data_get(lb)); } static void _signal_first(Listing_Request *lreq) { Elm_Fileselector_Data *sd = lreq->sd; if (!lreq->first) return; if (!sd) return; if (sd->multi) { sd->multi_selection = eina_list_free(sd->multi_selection); } _model_event_call (lreq->obj, ELM_FILESELECTOR_EVENT_DIRECTORY_OPEN, lreq->model, lreq->path); if (!lreq->parent_it) { if (sd->mode == ELM_FILESELECTOR_LIST) elm_genlist_clear(sd->files_view); else elm_gengrid_clear(sd->files_view); _elm_fileselector_replace_model(lreq->obj, sd, lreq->model, lreq->path); _anchors_do(lreq->obj, lreq->path); } lreq->first = EINA_FALSE; } static void _process_last(Listing_Request *lreq) { Elm_Fileselector_Data *sd = lreq->sd; elm_progressbar_pulse(sd->spinner, EINA_FALSE); elm_layout_signal_emit(lreq->obj, "elm,action,spinner,hide", "elm"); _listing_request_cleanup(lreq); sd->current_populate_lreq = NULL; } static Eina_Bool _process_child(Elm_Fileselector_Item_Data *it_data, Eina_Accessor *values_acc) { Elm_Object_Item *item; Listing_Request *lreq = it_data->user_data; int itcn = ELM_FILE_UNKNOW; const char *path = NULL; const char *filename = NULL; const char *mime_type = NULL; int64_t size = 0; double mtime = 0; Eina_Bool dir = EINA_FALSE; Elm_Fileselector_Data *sd = lreq->sd; it_data->user_data = NULL; if (!sd->files_view) return EINA_FALSE; if (!_accessor_value_get(values_acc, 0, &path) || !path || !_accessor_value_get(values_acc, 1, &filename) || !filename || !_accessor_value_get(values_acc, 2, &dir) || !_accessor_value_get(values_acc, 3, &size) || !_accessor_value_get(values_acc, 4, &mtime) || !_accessor_value_get(values_acc, 5, &mime_type)) { ERR("missing child Efl.Model data"); return EINA_FALSE; } if (!_filter_child(sd, path, filename, dir, mime_type)) return EINA_FALSE; _signal_first(lreq); it_data->path = eina_stringshare_add(path); it_data->filename = eina_stringshare_add(filename); it_data->size = size; it_data->mtime = mtime; it_data->mime_type = eina_stringshare_add(mime_type); it_data->parent_model = efl_ref(lreq->model); it_data->parent_path = eina_stringshare_add(lreq->path); it_data->is_dir = dir; if (it_data->is_dir) itcn = ELM_DIRECTORY; else { if (evas_object_image_extension_can_load_get(it_data->filename)) itcn = ELM_FILE_IMAGE; } if (sd->mode == ELM_FILESELECTOR_LIST) { item = elm_genlist_item_sorted_insert(sd->files_view, list_itc[itcn], it_data, lreq->parent_it, ((sd->expand) && (itcn == ELM_DIRECTORY)) ? ELM_GENLIST_ITEM_TREE : ELM_GENLIST_ITEM_NONE, _file_list_cmp, NULL, NULL); if (lreq->selected_path && it_data->path == lreq->selected_path) { elm_genlist_item_selected_set(item, EINA_TRUE); elm_object_text_set(sd->name_entry, it_data->filename); } } else if (sd->mode == ELM_FILESELECTOR_GRID) { item = elm_gengrid_item_sorted_insert(sd->files_view, grid_itc[itcn], it_data, _file_grid_cmp, NULL, NULL); if (lreq->selected_path && it_data->path == lreq->selected_path) { elm_gengrid_item_selected_set(item, EINA_TRUE); elm_object_text_set(sd->name_entry, it_data->filename); } } return EINA_TRUE; } static void _process_child_cb(void *data, Efl_Event const*event) { Elm_Fileselector_Item_Data *it_data = data; Listing_Request *lreq = it_data->user_data; Efl_Future_Event_Success *ev = event->info; Eina_Accessor *values_acc = ev->value; if (!lreq->valid || !_process_child(it_data, values_acc)) { efl_unref(it_data->model); free(it_data); } ++(lreq->item_processed_count); if (lreq->item_processed_count >= lreq->item_total) { if (!lreq->valid) { _listing_request_cleanup(lreq); return; } _signal_first(lreq); _process_last(lreq); } } static void _process_child_error_cb(void *data, Efl_Event const* event EINA_UNUSED) { Elm_Fileselector_Item_Data *it_data = data; Listing_Request *lreq = it_data->user_data; efl_unref(it_data->model); free(it_data); ERR("Failed to access to a model property"); ++(lreq->item_processed_count); if (lreq->item_processed_count >= lreq->item_total) { if (!lreq->valid) { _listing_request_cleanup(lreq); return; } _signal_first(lreq); _process_last(lreq); } } static void _listing_request_cleanup(Listing_Request *lreq) { if (lreq->parent_it) efl_unref(lreq->parent_it); efl_unref(lreq->obj); efl_unref(lreq->model); if (lreq->selected) efl_unref(lreq->selected); eina_stringshare_del(lreq->path); eina_stringshare_del(lreq->selected_path); free(lreq); } static void _process_children_cb(void *data, Efl_Event const *event) { Listing_Request *lreq = data; Efl_Future_Event_Success *ev = event->info; Eina_Accessor *all_promises = ev->value; Eina_Accessor *children_accessor = NULL; Elm_Fileselector_Item_Data *it_data = NULL; const char *path = NULL; const char *selected_path = NULL; unsigned int count = 0; Elm_Fileselector_Data *sd = lreq->sd; if (!lreq->valid) { _listing_request_cleanup(lreq); return; } if (_accessor_value_get(all_promises, 0, &path) && path && eina_accessor_data_get(all_promises, 1, (void **) &children_accessor)) { if (lreq->selected) { if (!_accessor_value_get(all_promises, 2, &selected_path) || !selected_path) { ERR("missing selected Efl.Model path information"); _listing_request_cleanup(lreq); sd->current_populate_lreq = NULL; return; } lreq->selected_path = eina_stringshare_add(selected_path); } lreq->path = eina_stringshare_add(path); if (children_accessor) { Eina_List *children = NULL; void *child = NULL; EINA_ACCESSOR_FOREACH(children_accessor, count, child) { children = eina_list_append(children, child); } lreq->item_total = count; EINA_LIST_FREE(children, child) { Efl_Future *futures[7]; Efl_Future *future_all = NULL; const char *prop[6] = { "path", "filename", "is_dir", "size", "mtime", "mime_type" }; unsigned int i; it_data = calloc(1, sizeof(Elm_Fileselector_Item_Data)); if (!it_data) { ERR("insufficient memory"); break; } it_data->model = efl_ref(child); it_data->user_data = lreq; for (i = 0; i != 6; i++) { futures[i] = efl_model_property_get(child, prop[i]); } future_all = efl_future_all(futures[0], futures[1], futures[2], futures[3], futures[4], futures[5]); efl_future_then(future_all, _process_child_cb, _process_child_error_cb, NULL, it_data); } // NOTE: lreq may have been deallocated in the previous loop lreq = NULL; } if (count == 0) { _signal_first(lreq); _process_last(lreq); } } else { ERR("missing Efl.Model information"); _listing_request_cleanup(lreq); sd->current_populate_lreq = NULL; } } static void _process_children_error_cb(void *data, Efl_Event const* event) { Eina_Error error = ((Efl_Future_Event_Failure*)event->info)->error; Listing_Request *lreq = data; Elm_Fileselector_Data *sd = lreq->sd; if (error != EINA_ERROR_FUTURE_CANCEL) { ERR("failed to get information from Efl.Model"); } if (lreq->valid) { elm_progressbar_pulse(sd->spinner, EINA_FALSE); elm_layout_signal_emit(lreq->obj, "elm,action,spinner,hide", "elm"); sd->current_populate_lreq = NULL; } _listing_request_cleanup(lreq); } static void _populate(Evas_Object *obj, Efl_Model *model, Elm_Object_Item *parent_it, Efl_Model *selected) { ELM_FILESELECTOR_DATA_GET(obj, sd); if (!model) return; Listing_Request *lreq; if (sd->expand && sd->current_populate_lreq) return; if (sd->current_populate_lreq) { sd->current_populate_lreq->valid = EINA_FALSE; sd->current_populate_lreq = NULL; } if (sd->model) _monitoring_stop(obj, sd, sd->model); lreq = calloc(1, sizeof (Listing_Request)); if (!lreq) return; lreq->sd = sd; lreq->parent_it = (parent_it ? efl_ref(parent_it) : NULL); lreq->obj = efl_ref(obj); lreq->model = efl_ref(model); lreq->selected = (selected ? efl_ref(selected) : NULL); lreq->path = NULL; lreq->selected_path = NULL; lreq->item_total = 0; lreq->item_processed_count = 0; lreq->first = EINA_TRUE; lreq->valid = EINA_TRUE; sd->current_populate_lreq = lreq; elm_progressbar_pulse(sd->spinner, EINA_TRUE); elm_layout_signal_emit(lreq->obj, "elm,action,spinner,show", "elm"); // Clear name entry not in case of save mode. if (elm_object_disabled_get(sd->name_entry)) elm_object_text_set(sd->name_entry, ""); Efl_Future *futures[4] = {NULL,}; Efl_Future *future_all = NULL; futures[0] = efl_model_property_get(model, "path"); futures[1] = efl_model_children_slice_get(model, 0, 0); if (selected) futures[2] = efl_model_property_get(selected, "path"); future_all = efl_future_all(futures[0], futures[1], futures[2]); efl_future_then(future_all, _process_children_cb, _process_children_error_cb, NULL, lreq); } static void _on_list_expanded(void *data, const Efl_Event *event) { Elm_Object_Item *it = event->info; const Elm_Fileselector_Item_Data *it_data = elm_object_item_data_get(it); _populate(data, it_data->model, it, NULL); } static void _on_list_contracted(void *data EINA_UNUSED, const Efl_Event *event) { Elm_Object_Item *it = event->info; elm_genlist_item_subitems_clear(it); } static void _on_list_expand_req(void *data EINA_UNUSED, const Efl_Event *event) { Elm_Object_Item *it = event->info; elm_genlist_item_expanded_set(it, EINA_TRUE); } static void _on_list_contract_req(void *data EINA_UNUSED, const Efl_Event *event) { Elm_Object_Item *it = event->info; elm_genlist_item_expanded_set(it, EINA_FALSE); } static Eina_Bool _populate_do(void *data) { struct sel_data *sdata = data; ELM_FILESELECTOR_DATA_GET(sdata->fs, sd); _populate(sdata->fs, sdata->model, NULL, sdata->selected); if (sdata->model) efl_unref(sdata->model); if (sdata->selected) efl_unref(sdata->selected); sd->populate_idler = NULL; free(sdata); return ECORE_CALLBACK_CANCEL; } static void _schedule_populate(Evas_Object *fs, Elm_Fileselector_Data *sd, Efl_Model *model, Efl_Model *selected) { struct sel_data *sdata; sdata = calloc(1, sizeof(*sdata)); if (!sdata) return; sdata->fs = fs; sdata->model = model; sdata->selected = selected; if (model) efl_ref(model); if (selected) efl_ref(selected); if (sd->populate_idler) { struct sel_data *old_sdata; old_sdata = ecore_idler_del(sd->populate_idler); if (old_sdata->model) efl_unref(old_sdata->model); if (old_sdata->selected) efl_unref(old_sdata->selected); free(old_sdata); } sd->populate_idler = ecore_idler_add(_populate_do, sdata); } static void _on_item_activated(void *data, const Efl_Event *event) { //This event_info could be a list or gengrid item Elm_Object_Item *it = event->info; const Elm_Fileselector_Item_Data *it_data; ELM_FILESELECTOR_DATA_GET(data, sd); it_data = elm_object_item_data_get(it); if (!it_data) return; if (!it_data->is_dir) { _model_event_call (data, ELM_FILESELECTOR_EVENT_ACTIVATED, it_data->model, it_data->path); return; } if (!sd->double_tap_navigation) return; _schedule_populate(data, sd, it_data->model, NULL); } static void _clear_selections(Elm_Fileselector_Data *sd, Elm_Object_Item *last_selected) { Eina_List *items; Elm_Object_Item *sel; if (sd->mode == ELM_FILESELECTOR_LIST) { items = eina_list_clone(elm_genlist_selected_items_get(sd->files_view)); EINA_LIST_FREE(items, sel) { if (sel == last_selected) continue; elm_genlist_item_selected_set(sel, EINA_FALSE); } } else if (sd->mode == ELM_FILESELECTOR_GRID) { items = eina_list_clone(elm_gengrid_selected_items_get(sd->files_view)); EINA_LIST_FREE(items, sel) { if (sel == last_selected) continue; elm_gengrid_item_selected_set(sel, EINA_FALSE); } } } static void _on_item_selected(void *data, const Efl_Event *event) { //This event_info could be a list or gengrid item Elm_Object_Item *it = event->info; Elm_Fileselector_Item_Data *it_data = NULL; ELM_FILESELECTOR_DATA_GET(data, sd); it_data = elm_object_item_data_get(it); if (!it_data) return; /* We need to send callback when: * - path is dir and mode is ONLY FOLDER * - path is file and mode is NOT ONLY FOLDER */ if (it_data->is_dir == sd->only_folder) { if (sd->multi) { Eina_List *li; Elm_Object_Item *it2; Eina_Strbuf *buf; if (sd->dir_selected) { _clear_selections(sd, it); sd->dir_selected = EINA_FALSE; } buf = eina_strbuf_new(); EINA_LIST_FOREACH(sd->multi_selection, li, it2) { Elm_Fileselector_Item_Data *it2_data = elm_object_item_data_get(it2); eina_strbuf_append(buf, it2_data->filename); eina_strbuf_append_length(buf, ", ", 2); } sd->multi_selection = eina_list_append(sd->multi_selection, it); eina_strbuf_append(buf, it_data->filename); elm_object_text_set(sd->name_entry, eina_strbuf_string_get(buf)); eina_strbuf_free(buf); } else elm_object_text_set(sd->name_entry, it_data->filename); _model_event_call (data, EFL_UI_EVENT_SELECTED, it_data->model, it_data->path); } else if (sd->multi && it_data->is_dir && sd->double_tap_navigation) { _clear_selections(sd, it); sd->dir_selected = EINA_TRUE; } /* We need to populate, if path is directory and: * - mode is GRID; * - mode is LIST and 'not expand mode'; * in other cases update anchors. */ if (sd->expand && sd->mode == ELM_FILESELECTOR_LIST) { if (!it_data->is_dir) { _elm_fileselector_replace_model(data, sd, it_data->parent_model, it_data->parent_path); _anchors_do(data, it_data->parent_path); return; } if (sd->only_folder) { _elm_fileselector_replace_model(data, sd, it_data->parent_model, it_data->parent_path); _anchors_do(data, it_data->parent_path); } else { _elm_fileselector_replace_model(data, sd, it_data->model, it_data->path); _anchors_do(data, it_data->path); } // Clear name entry not in case of save mode. if (elm_object_disabled_get(sd->name_entry)) elm_object_text_set(sd->name_entry, ""); return; } if (!it_data->is_dir) return; if (sd->double_tap_navigation) return; _schedule_populate(data, sd, it_data->model, NULL); } static void _on_item_unselected(void *data, const Efl_Event *event) { Eina_List *li, *l; const Elm_Fileselector_Item_Data *it_data; Eina_Strbuf *buf; Elm_Object_Item *it = event->info; Elm_Object_Item *it2 = NULL; Eina_Bool first = EINA_TRUE; ELM_FILESELECTOR_DATA_GET(data, sd); if (!sd->multi) return; it_data = elm_object_item_data_get(it); if (!it_data) return; buf = eina_strbuf_new(); EINA_LIST_FOREACH_SAFE(sd->multi_selection, li, l, it2) { if (it2 == it) { sd->multi_selection = eina_list_remove_list(sd->multi_selection, li); } else { Elm_Fileselector_Item_Data *it2_data = elm_object_item_data_get(it2); if (!it2_data) continue; if (!first) eina_strbuf_append_length(buf, ", ", 2); else first = EINA_FALSE; eina_strbuf_append(buf, it2_data->path); } } elm_object_text_set(sd->name_entry, eina_strbuf_string_get(buf)); eina_strbuf_free(buf); } static void _on_dir_up(void *data, const Efl_Event *event EINA_UNUSED) { Evas_Object *fs = data; Efl_Model *parent = NULL; ELM_FILESELECTOR_DATA_GET(fs, sd); parent = efl_parent_get(sd->model); if (!parent) return; _populate(fs, parent, NULL, NULL); } static void _home(void *data, const Efl_Event *event EINA_UNUSED) { Evas_Object *fs = data; ELM_FILESELECTOR_DATA_GET(fs, sd); // FIXME: maybe use vpath if (!sd->model || efl_isa(sd->model, EIO_MODEL_CLASS)) { Eio_Model *model = efl_add(EIO_MODEL_CLASS, NULL, eio_model_path_set(efl_added, eina_environment_home_get())); _populate(fs, model, NULL, NULL); efl_unref(model); } } static void _current_filter_changed(void *data, Evas_Object *obj, void *event_info EINA_UNUSED) { Elm_Fileselector_Filter *filter = data; if (filter->sd->current_filter == filter) return; elm_object_text_set(obj, filter->filter_name); filter->sd->current_filter = filter; _populate(filter->sd->obj, filter->sd->model, NULL, NULL); } static void _ok(void *data, const Efl_Event *event EINA_UNUSED) { const char *name; const char *selection = NULL; Evas_Object *fs = data; ELM_FILESELECTOR_DATA_GET(fs, sd); if (!sd->model || !sd->path) { _model_event_call(fs, ELM_FILESELECTOR_EVENT_DONE, NULL, NULL); return; } name = elm_object_text_get(sd->name_entry); if (name && name[0] != '\0') { Efl_Model *selected_model = NULL; int len = eina_stringshare_strlen(sd->path); if (sd->path[len - 1] == '/') selection = eina_stringshare_printf("%s%s", sd->path, name); else selection = eina_stringshare_printf("%s/%s", sd->path, name); selected_model = efl_add(efl_class_get(sd->model), NULL); _model_str_property_set(selected_model, "path", selection); _model_event_call (fs, ELM_FILESELECTOR_EVENT_DONE, selected_model, selection); efl_unref(selected_model); eina_stringshare_del(selection); } else { Elm_Fileselector_Item_Data *it_data = _selected_item_data_get(sd); if (it_data) { _model_event_call (fs, ELM_FILESELECTOR_EVENT_DONE, it_data->model, it_data->path); } else { _model_event_call (fs, ELM_FILESELECTOR_EVENT_DONE, sd->model, sd->path); } } } static void _canc(void *data, const Efl_Event *event EINA_UNUSED) { Evas_Object *fs = data; _model_event_call(fs, ELM_FILESELECTOR_EVENT_DONE, NULL, NULL); } static void _text_activated_free_fs_data(Elm_Fileselector *fs) { Eina_Stringshare *str = efl_key_data_get(fs, _text_activated_path_key); eina_stringshare_del(str); efl_key_data_set(fs, _text_activated_path_key, NULL); efl_key_ref_set(fs, _text_activated_model_key, NULL); efl_unref(fs); } static void _text_activated_is_dir_then(void *data, Efl_Event const *event) { Evas_Object *fs = data; Eina_Bool is_dir = EINA_FALSE; ELM_FILESELECTOR_DATA_GET(fs, sd); Efl_Model *model = efl_key_ref_get(fs, _text_activated_model_key); Eina_Stringshare *str = efl_key_data_get(fs, _text_activated_path_key); eina_value_get((Eina_Value*)((Efl_Future_Event_Success*)event->info)->value, &is_dir); if (is_dir) { // keep previous path for backspace key action if (sd->prev_model) efl_unref(sd->prev_model); sd->prev_model = efl_ref(sd->model); _populate(fs, model, NULL, NULL); if (sd->only_folder) { _model_event_call (fs, EFL_UI_EVENT_SELECTED, model, str); } } else { Efl_Model *parent = efl_parent_get(model); if (!parent) { ERR("Efl.Model allocation error"); } else { _populate(fs, parent, NULL, model); if (sd->only_folder) { _model_event_call (fs, EFL_UI_EVENT_SELECTED, model, str); } } } _text_activated_free_fs_data(fs); } static void _text_activated_is_dir_then_error(void *data, Efl_Event const* event EINA_UNUSED) { ERR("could not get information from Efl.Model"); _text_activated_free_fs_data(data); } static void _on_text_activated_set_path_then(void *data, Efl_Event const * event EINA_UNUSED) { Evas_Object *fs = data; Efl_Future *future = NULL; ELM_FILESELECTOR_DATA_GET(fs, sd); if (!sd->model) return ; future = efl_model_property_get(sd->model, "is_dir"); efl_future_then (future, _text_activated_is_dir_then, _text_activated_is_dir_then_error, NULL, data); } static void _on_text_activated_set_path_then_error(void *data, Efl_Event const* event EINA_UNUSED) { Evas_Object *fs = data; Efl_Model *model = efl_key_data_get(fs, _text_activated_model_key); Eina_Stringshare *str = efl_key_data_get(fs, _text_activated_path_key); _model_event_call (fs, EFL_UI_EVENT_SELECTED, model, str); _model_event_call (fs, ELM_FILESELECTOR_EVENT_SELECTED_INVALID, model, str); _text_activated_free_fs_data(fs); } static void _on_text_activated(void *data, const Efl_Event *event) { Evas_Object *fs = data; const char *path; Efl_Model *model; Efl_Future *future = NULL; ELM_FILESELECTOR_DATA_GET(fs, sd); if (!sd->model) return; path = elm_widget_part_text_get(event->object, NULL); model = efl_add(efl_class_get(sd->model), NULL); if (!model) return; future = _model_str_property_set(model, "path", path); efl_key_data_set(fs, _text_activated_path_key, eina_stringshare_add(path)); efl_key_ref_set(fs, _text_activated_model_key, model); efl_ref(fs); efl_future_then(future, _on_text_activated_set_path_then, _on_text_activated_set_path_then_error, NULL, fs); efl_unref(model); elm_object_focus_set(event->object, EINA_FALSE); } static Eina_Bool _anchors_undo(void *data) { ELM_FILESELECTOR_DATA_GET(data, sd); elm_entry_entry_set(sd->path_entry, sd->path); elm_entry_cursor_pos_set(sd->path_entry, eina_stringshare_strlen(sd->path)); sd->path_entry_idler = NULL; return ECORE_CALLBACK_CANCEL; } static void _on_text_focused(void *data, const Efl_Event *event EINA_UNUSED) { ELM_FILESELECTOR_DATA_GET(data, sd); if (!sd->path_entry_idler) sd->path_entry_idler = ecore_idler_add(_anchors_undo, data); } static void _on_text_unfocused(void *data, const Efl_Event *event EINA_UNUSED) { ELM_FILESELECTOR_DATA_GET(data, sd); _anchors_do(data, sd->path); } static void _anchor_clicked(void *data, const Efl_Event *event) { Elm_Entry_Anchor_Info *info = event->info; Evas_Object *fs = data; Efl_Model *model = NULL; ELM_FILESELECTOR_DATA_GET(fs, sd); if (!sd->model) return; model = efl_add(efl_class_get(sd->model), NULL); if (!model) return; _model_str_property_set(model, "path", info->name); _populate(fs, model, NULL, NULL); efl_unref(model); /* After anchor was clicked, entry will be focused, and will be editable. * It's wrong. So remove focus. */ elm_object_focus_set(event->object, EINA_FALSE); if (sd->path_entry_idler) { ecore_idler_del(sd->path_entry_idler); sd->path_entry_idler = NULL; } } static void _files_key_down(void *data, const Efl_Event *event) { Efl_Input_Key *ev = event->info; Evas_Object *par, *searchbar; const char *string, *key; par = data; searchbar = evas_object_data_get(par, "search"); if (!searchbar) return; key = efl_input_key_get(ev); string = efl_input_key_string_get(ev); if (string && *(string) && (isalpha(*string) || isdigit(*string))) { elm_entry_entry_append(searchbar, string); efl_input_processed_set(ev, EINA_TRUE); } else if (key && *(key) && !strcmp(key, "BackSpace")) { char buf[PATH_MAX]; const char *en; en = elm_entry_entry_get(searchbar); if (en && strlen(en) > 0) { memmove(buf, en, strlen(en) -1); buf[strlen(en) -1] = '\0'; elm_entry_entry_set(searchbar, buf); efl_input_processed_set(ev, EINA_TRUE); } } } static Evas_Object * _files_list_add(Evas_Object *obj) { Evas_Object *li; li = elm_genlist_add(obj); evas_object_data_set(li, "parent", obj); - elm_widget_mirrored_automatic_set(li, EINA_FALSE); + efl_ui_mirrored_automatic_set(li, EINA_FALSE); efl_event_callback_add (li, EFL_UI_EVENT_SELECTED, _on_item_selected, obj); efl_event_callback_add (li, EFL_UI_EVENT_UNSELECTED, _on_item_unselected, obj); efl_event_callback_add (li, ELM_GENLIST_EVENT_ACTIVATED, _on_item_activated, obj); efl_event_callback_add (li, ELM_GENLIST_EVENT_EXPAND_REQUEST, _on_list_expand_req, obj); efl_event_callback_add (li, ELM_GENLIST_EVENT_CONTRACT_REQUEST, _on_list_contract_req, obj); efl_event_callback_add (li, ELM_GENLIST_EVENT_EXPANDED, _on_list_expanded, obj); efl_event_callback_add (li, ELM_GENLIST_EVENT_CONTRACTED, _on_list_contracted, obj); efl_event_callback_add (li, EFL_EVENT_KEY_DOWN, _files_key_down, obj); return li; } static Evas_Object * _files_grid_add(Evas_Object *obj) { Evas_Object *grid; ELM_FILESELECTOR_DATA_GET(obj, sd); grid = elm_gengrid_add(obj); evas_object_data_set(grid, "parent", obj); - elm_widget_mirrored_automatic_set(grid, EINA_FALSE); + efl_ui_mirrored_automatic_set(grid, EINA_FALSE); evas_object_size_hint_align_set(grid, EVAS_HINT_FILL, EVAS_HINT_FILL); evas_object_size_hint_weight_set(grid, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); elm_gengrid_item_size_set(grid, sd->thumbnail_size.w, sd->thumbnail_size.h); elm_gengrid_align_set(grid, 0.0, 0.0); efl_event_callback_add (grid, EFL_UI_EVENT_SELECTED, _on_item_selected, obj); efl_event_callback_add (grid, EFL_UI_EVENT_UNSELECTED, _on_item_unselected, obj); efl_event_callback_add (grid, ELM_GENGRID_EVENT_ACTIVATED, _on_item_activated, obj); efl_event_callback_add (grid, EFL_EVENT_KEY_DOWN, _files_key_down, obj); return grid; } static void _resource_then_error(void *data, Efl_Event const* event EINA_UNUSED) { Elm_Fileselector_Item_Data *it_data = data; WRN("could not get information from Efl.Model"); efl_unref(it_data->user_data); efl_unref(it_data->model); free(it_data); } static void _resource_created_then(void *data, Efl_Event const*event) { Elm_Fileselector_Item_Data *it_data = data; Evas_Object *obj = it_data->user_data; Efl_Future_Event_Success *ev = event->info; Eina_Accessor *values_acc = ev->value; int itcn = ELM_FILE_UNKNOW; const char *path = NULL; const char *filename = NULL; const char *mime_type = NULL; int64_t size = 0; double mtime = 0; Eina_Bool dir = EINA_FALSE; it_data->user_data = NULL; ELM_FILESELECTOR_DATA_GET(obj, sd); if (!sd || !sd->monitoring || sd->model != it_data->parent_model) goto cancel; if (!_accessor_value_get(values_acc, 0, &path) || !path || !_accessor_value_get(values_acc, 1, &filename) || !filename || !_accessor_value_get(values_acc, 2, &dir) || !_accessor_value_get(values_acc, 3, &size) || !_accessor_value_get(values_acc, 4, &mtime) || !_accessor_value_get(values_acc, 5, &mime_type)) { ERR("missing Efl.Model data"); goto cancel; } if (!_filter_child(sd, path, filename, dir, mime_type)) goto cancel; it_data->path = eina_stringshare_add(path); it_data->filename = eina_stringshare_add(filename); it_data->size = size; it_data->mtime = mtime; it_data->mime_type = eina_stringshare_add(mime_type); it_data->is_dir = dir; if (dir) itcn = ELM_DIRECTORY; else { if (evas_object_image_extension_can_load_get(filename)) itcn = ELM_FILE_IMAGE; } if (sd->mode == ELM_FILESELECTOR_LIST) elm_genlist_item_sorted_insert(sd->files_view, list_itc[itcn], it_data, NULL, (sd->expand && itcn == ELM_DIRECTORY) ? ELM_GENLIST_ITEM_TREE : ELM_GENLIST_ITEM_NONE, _file_list_cmp, NULL, NULL); else elm_gengrid_item_sorted_insert(sd->files_view, grid_itc[itcn], it_data, _file_grid_cmp, NULL, NULL); efl_unref(obj); return; cancel: efl_unref(obj); efl_unref(it_data->model); efl_unref(it_data->parent_model); eina_stringshare_del(it_data->parent_path); free(it_data); } static void _resource_created(void *data, const Efl_Event *event) { Elm_Fileselector *fs = data; Efl_Model_Children_Event* evt = event->info; Efl_Model *child = evt->child; Efl_Future *futures[7] = {NULL,}; Efl_Future *future_all = NULL; Elm_Fileselector_Item_Data *it_data = NULL; ELM_FILESELECTOR_DATA_GET(fs, sd); if (!sd || !sd->monitoring || sd->model != event->object) return; it_data = calloc(1, sizeof(Elm_Fileselector_Item_Data)); if (!it_data) return; it_data->model = efl_ref(child); it_data->user_data = efl_ref(fs); it_data->parent_model = efl_ref(sd->model); it_data->parent_path = eina_stringshare_add(sd->path); future_all = efl_future_all ( futures[0] = efl_model_property_get(child, "path"), futures[1] = efl_model_property_get(child, "filename"), futures[2] = efl_model_property_get(child, "is_dir"), futures[3] = efl_model_property_get(child, "size"), futures[4] = efl_model_property_get(child, "mtime"), futures[5] = efl_model_property_get(child, "mime_type") ); efl_future_then(future_all, _resource_created_then, _resource_then_error, NULL, it_data); return; } static void _resource_deleted(void *data, const Efl_Event *event) { Evas_Object *obj = data; Efl_Model_Children_Event* evt = event->info; Efl_Model *child = evt->child; Elm_Object_Item *it = NULL; Eina_Bool selected = EINA_FALSE; ELM_FILESELECTOR_DATA_GET(obj, sd); if (!sd || !sd->monitoring || sd->model != event->object) return; if (sd->mode == ELM_FILESELECTOR_LIST) { it = elm_genlist_first_item_get(sd->files_view); while (it) { Elm_Fileselector_Item_Data *it_data = elm_object_item_data_get(it); if (child == it_data->model) { selected = elm_genlist_item_selected_get(it); break; } it = elm_genlist_item_next_get(it); } } else { it = elm_gengrid_first_item_get(sd->files_view); while (it) { Elm_Fileselector_Item_Data *it_data = elm_object_item_data_get(it); if (child == it_data->model) { selected = elm_genlist_item_selected_get(it); break; } it = elm_gengrid_item_next_get(it); } } if (it) elm_wdg_item_del(it); if (selected) { if (sd->multi) { Eina_List *li, *l; Elm_Object_Item *item; Eina_Strbuf *buf; Eina_Bool first = EINA_TRUE; buf = eina_strbuf_new(); EINA_LIST_FOREACH_SAFE(sd->multi_selection, li, l, item) { Elm_Fileselector_Item_Data *it_data = elm_object_item_data_get(item); if (child == it_data->model) { sd->multi_selection = eina_list_remove_list(sd->multi_selection, li); } else { if (!first) eina_strbuf_append_length(buf, ", ", 2); else first = EINA_FALSE; eina_strbuf_append(buf, it_data->filename); } } elm_object_text_set(sd->name_entry, eina_strbuf_string_get(buf)); eina_strbuf_free(buf); } else elm_object_text_set(sd->name_entry, ""); } return; } static void _preedit_cb(void *data, const Efl_Event *event) { ELM_FILESELECTOR_DATA_GET(data, sd); sd->search_string = elm_entry_entry_get(event->object); if (sd->search_string && sd->model) _populate(data, sd->model, NULL, NULL); } EOLIAN static void _elm_fileselector_efl_canvas_group_group_add(Eo *obj, Elm_Fileselector_Data *priv) { Evas_Object *ic, *bt, *en, *pb; const char *data; char buf[1024]; efl_canvas_group_add(efl_super(obj, MY_CLASS)); elm_widget_sub_object_parent_add(obj); elm_widget_can_focus_set(obj, EINA_FALSE); priv->expand = !!_elm_config->fileselector_expand_enable; priv->double_tap_navigation = !!_elm_config->fileselector_double_tap_navigation_enable; if (!elm_layout_theme_set (obj, "fileselector", "base", elm_widget_style_get(obj))) CRI("Failed to set layout!"); ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd); data = edje_object_data_get (wd->resize_obj, "path_separator"); if (data) priv->path_separator = data; else priv->path_separator = "/"; snprintf(buf, sizeof(buf), "fileselector/%s", elm_widget_style_get(obj)); // up btn ic = elm_icon_add(obj); elm_icon_standard_set(ic, "go-up"); bt = elm_button_add(obj); - elm_widget_mirrored_automatic_set(bt, EINA_FALSE); + efl_ui_mirrored_automatic_set(bt, EINA_FALSE); elm_object_part_content_set(bt, "icon", ic); elm_object_domain_translatable_text_set(bt, PACKAGE, N_("Up")); efl_event_callback_add (bt, EFL_UI_EVENT_CLICKED, _on_dir_up, obj); priv->up_button = bt; elm_object_style_set(priv->up_button, buf); elm_object_part_content_set(obj, "elm.swallow.up", priv->up_button); // home btn ic = elm_icon_add(obj); elm_icon_standard_set(ic, "go-home"); bt = elm_button_add(obj); - elm_widget_mirrored_automatic_set(bt, EINA_FALSE); + efl_ui_mirrored_automatic_set(bt, EINA_FALSE); elm_object_part_content_set(bt, "icon", ic); elm_object_domain_translatable_text_set(bt, PACKAGE, N_("Home")); efl_event_callback_add (bt, EFL_UI_EVENT_CLICKED, _home, obj); priv->home_button = bt; elm_object_style_set(priv->home_button, buf); elm_object_part_content_set(obj, "elm.swallow.home", priv->home_button); // search entry ic = elm_icon_add(obj); elm_icon_standard_set(ic, "edit-find"); evas_object_size_hint_aspect_set(ic, EVAS_ASPECT_CONTROL_VERTICAL, 1, 1); en = elm_entry_add(obj); elm_entry_scrollable_set(en, EINA_TRUE); - elm_widget_mirrored_automatic_set(en, EINA_FALSE); + efl_ui_mirrored_automatic_set(en, EINA_FALSE); elm_entry_editable_set(en, EINA_TRUE); elm_entry_single_line_set(en, EINA_TRUE); elm_entry_line_wrap_set(en, ELM_WRAP_CHAR); elm_object_domain_translatable_part_text_set(en, "guide", PACKAGE, N_("Search")); elm_object_part_content_set(en, "icon", ic); elm_entry_icon_visible_set(en, EINA_TRUE); efl_event_callback_add (en, ELM_ENTRY_EVENT_CHANGED, _preedit_cb, obj); evas_object_data_set(obj, "search", en); priv->search_entry = en; elm_object_style_set(priv->search_entry, buf); elm_object_part_content_set(obj, "elm.swallow.search", priv->search_entry); // spinner pb = elm_progressbar_add(obj); priv->spinner = pb; elm_progressbar_pulse_set(priv->spinner, EINA_TRUE); elm_object_style_set(priv->spinner, "wheel"); elm_object_part_content_set(obj, "elm.swallow.spinner", priv->spinner); priv->thumbnail_size.w = ITEM_SIZE_DEFAULT; priv->thumbnail_size.h = ITEM_SIZE_DEFAULT; priv->sort_type = ELM_FILESELECTOR_SORT_BY_FILENAME_ASC; priv->sort_method = _filename_cmp; // path entry en = elm_entry_add(obj); elm_entry_scrollable_set(en, EINA_TRUE); - elm_widget_mirrored_automatic_set(en, EINA_FALSE); + efl_ui_mirrored_automatic_set(en, EINA_FALSE); elm_entry_single_line_set(en, EINA_TRUE); elm_entry_line_wrap_set(en, ELM_WRAP_CHAR); efl_event_callback_add (en, ELM_ENTRY_EVENT_ANCHOR_CLICKED, _anchor_clicked, obj); efl_event_callback_add (en, ELM_WIDGET_EVENT_FOCUSED, _on_text_focused, obj); efl_event_callback_add (en, ELM_WIDGET_EVENT_UNFOCUSED, _on_text_unfocused, obj); efl_event_callback_add (en, ELM_ENTRY_EVENT_ACTIVATED, _on_text_activated, obj); priv->path_entry = en; elm_object_style_set(priv->path_entry, buf); elm_object_part_content_set(obj, "elm.swallow.path", priv->path_entry); // name entry en = elm_entry_add(obj); elm_entry_scrollable_set(en, EINA_TRUE); - elm_widget_mirrored_automatic_set(en, EINA_FALSE); + efl_ui_mirrored_automatic_set(en, EINA_FALSE); elm_entry_editable_set(en, EINA_TRUE); elm_entry_single_line_set(en, EINA_TRUE); elm_entry_line_wrap_set(en, ELM_WRAP_CHAR); priv->name_entry = en; elm_object_style_set(priv->name_entry, buf); elm_object_part_content_set(obj, "elm.swallow.filename", priv->name_entry); // ok cancel button elm_fileselector_buttons_ok_cancel_set(obj, EINA_TRUE); elm_fileselector_is_save_set(obj, EINA_FALSE); // files_view priv->files_view = _files_list_add(obj); elm_object_part_content_set(obj, "elm.swallow.files", priv->files_view); elm_obj_layout_sizing_eval(obj); } EOLIAN static void _elm_fileselector_efl_canvas_group_group_del(Eo *obj, Elm_Fileselector_Data *sd) { Elm_Fileselector_Filter *filter; if (sd->current_populate_lreq) sd->current_populate_lreq->valid = EINA_FALSE; sd->current_populate_lreq = NULL; if (sd->model) _monitoring_stop(obj, sd, sd->model); EINA_LIST_FREE(sd->filter_list, filter) { eina_stringshare_del(filter->filter_name); if (filter->filter_type == ELM_FILESELECTOR_MIME_FILTER) { free(filter->filter.mime_types[0]); free(filter->filter.mime_types); } else free(filter->filter.custom); free(filter); } sd->multi_selection = eina_list_free(sd->multi_selection); sd->multi_selection_tmp = eina_list_free(sd->multi_selection_tmp); sd->files_view = NULL; _elm_fileselector_smart_del_do(obj, sd); } EAPI Evas_Object * elm_fileselector_add(Evas_Object *parent) { EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL); Evas_Object *obj = efl_add(MY_CLASS, parent); return obj; } EOLIAN static Eo * _elm_fileselector_efl_object_constructor(Eo *obj, Elm_Fileselector_Data *sd) { obj = efl_constructor(efl_super(obj, MY_CLASS)); sd->obj = obj; efl_canvas_object_type_set(obj, MY_CLASS_NAME_LEGACY); evas_object_smart_callbacks_descriptions_set(obj, _smart_callbacks); elm_interface_atspi_accessible_role_set(obj, ELM_ATSPI_ROLE_FILE_CHOOSER); return obj; } static void _legacy_smart_callback_caller_path_then(void *data, Efl_Event const *event) { Legacy_Event_Path_Then_Data *evt_data = data; _event_to_legacy_call(evt_data->eo_obj, evt_data->evt_desc, ((Efl_Future_Event_Success*)event->info)->value); free(data); } static void _legacy_smart_callback_caller_path_then_error(void *data, Efl_Event const* event) { Eina_Error err = ((Efl_Future_Event_Failure*)event->info)->error; ERR("Efl.Model property \"path\" error: %s", eina_error_msg_get(err)); free(data); } static Eina_Bool _from_efl_event_call(Elm_Fileselector *fs, const Efl_Event_Description *evt_desc, Efl_Model *model) { Efl_Future *future; Legacy_Event_Path_Then_Data *evt_data; evt_data = calloc(1, sizeof(Legacy_Event_Path_Then_Data)); evt_data->eo_obj = fs; evt_data->evt_desc = evt_desc; // Call legacy smart callback with path future = efl_model_property_get(model, "path"); efl_future_then(future, _legacy_smart_callback_caller_path_then, _legacy_smart_callback_caller_path_then_error, NULL, evt_data); // Call Eo event with model return efl_event_callback_call(fs, evt_desc, model); } static Eina_Bool _from_legacy_event_call(Elm_Fileselector *fs, Elm_Fileselector_Data *sd, const Efl_Event_Description *legacy_desc, const Efl_Event_Description *evt_desc, const char *path) { const Efl_Class *model_cls = NULL; if (!sd->model) model_cls = EIO_MODEL_CLASS; else model_cls = efl_class_get(sd->model); Efl_Model *model = efl_add(model_cls, NULL); _model_str_property_set(model, "path", path); // Call Eo event with model efl_event_callback_call(fs, evt_desc, model); efl_unref(model); // Call legacy smart callback with path return efl_event_callback_call(fs, legacy_desc, (void *)path); } EOLIAN static Eina_Bool _elm_fileselector_efl_object_event_callback_legacy_call(Eo *obj, Elm_Fileselector_Data *sd, const Efl_Event_Description *desc, void *event_info) { if (desc->legacy_is) { const Efl_Event_Description *evt_desc = NULL; if (strcmp(desc->name, "selected") == 0) evt_desc = EFL_UI_EVENT_SELECTED; else if (strcmp(desc->name, "activated") == 0) evt_desc = ELM_FILESELECTOR_EVENT_ACTIVATED; else if (strcmp(desc->name, "directory,open") == 0) evt_desc = ELM_FILESELECTOR_EVENT_DIRECTORY_OPEN; else if (strcmp(desc->name, "done") == 0) evt_desc = ELM_FILESELECTOR_EVENT_DONE; else if (strcmp(desc->name, "selected,invalid") == 0) evt_desc = ELM_FILESELECTOR_EVENT_SELECTED_INVALID; else return efl_event_callback_legacy_call(efl_super(obj, MY_CLASS), desc, event_info); return _from_legacy_event_call(obj, sd, desc, evt_desc, event_info); } if (desc == EFL_UI_EVENT_SELECTED || desc == ELM_FILESELECTOR_EVENT_ACTIVATED || desc == ELM_FILESELECTOR_EVENT_DIRECTORY_OPEN || desc == ELM_FILESELECTOR_EVENT_DONE || desc == ELM_FILESELECTOR_EVENT_SELECTED_INVALID) { return _from_efl_event_call(obj, desc, event_info); } return efl_event_callback_legacy_call(efl_super(obj, MY_CLASS), desc, event_info); } EAPI void elm_fileselector_is_save_set(Evas_Object *obj, Eina_Bool is_save) { ELM_FILESELECTOR_INTERFACE_CHECK(obj); elm_interface_fileselector_is_save_set(obj, is_save); } EOLIAN static void _elm_fileselector_elm_interface_fileselector_is_save_set(Eo *obj, Elm_Fileselector_Data *sd, Eina_Bool is_save) { elm_object_disabled_set(sd->name_entry, !is_save); if (is_save) elm_layout_signal_emit(obj, "elm,state,save,on", "elm"); else elm_layout_signal_emit(obj, "elm,state,save,off", "elm"); } EAPI Eina_Bool elm_fileselector_is_save_get(const Evas_Object *obj) { ELM_FILESELECTOR_INTERFACE_CHECK(obj, EINA_FALSE); return elm_interface_fileselector_is_save_get((Eo *) obj); } EOLIAN static Eina_Bool _elm_fileselector_elm_interface_fileselector_is_save_get(Eo *obj EINA_UNUSED, Elm_Fileselector_Data *sd) { return !elm_object_disabled_get(sd->name_entry); } EAPI void elm_fileselector_folder_only_set(Evas_Object *obj, Eina_Bool only) { ELM_FILESELECTOR_INTERFACE_CHECK(obj); elm_interface_fileselector_folder_only_set(obj, only); } EOLIAN static void _elm_fileselector_elm_interface_fileselector_folder_only_set(Eo *obj, Elm_Fileselector_Data *sd, Eina_Bool only) { if (sd->only_folder == only) return; sd->only_folder = !!only; if (sd->model) { _schedule_populate(obj, sd, sd->model, NULL); } } EAPI Eina_Bool elm_fileselector_folder_only_get(const Evas_Object *obj) { ELM_FILESELECTOR_INTERFACE_CHECK(obj, EINA_FALSE); return elm_interface_fileselector_folder_only_get((Eo *) obj); } EOLIAN static Eina_Bool _elm_fileselector_elm_interface_fileselector_folder_only_get(Eo *obj EINA_UNUSED, Elm_Fileselector_Data *sd) { return sd->only_folder; } EOLIAN static void _elm_fileselector_buttons_ok_cancel_set(Eo *obj, Elm_Fileselector_Data *sd, Eina_Bool visible) { Evas_Object *bt; visible = !!visible; if (!visible == !sd->ok_button) return; if (visible) { // cancel btn bt = elm_button_add(obj); - elm_widget_mirrored_automatic_set(bt, EINA_FALSE); + efl_ui_mirrored_automatic_set(bt, EINA_FALSE); elm_object_domain_translatable_text_set(bt, PACKAGE, N_("Cancel")); efl_event_callback_add(bt, EFL_UI_EVENT_CLICKED, _canc, obj); sd->cancel_button = bt; elm_object_part_content_set(obj, "elm.swallow.cancel", sd->cancel_button); // ok btn bt = elm_button_add(obj); - elm_widget_mirrored_automatic_set(bt, EINA_FALSE); + efl_ui_mirrored_automatic_set(bt, EINA_FALSE); elm_object_domain_translatable_text_set(bt, PACKAGE, N_("OK")); efl_event_callback_add(bt, EFL_UI_EVENT_CLICKED, _ok, obj); sd->ok_button = bt; elm_object_part_content_set(obj, "elm.swallow.ok", sd->ok_button); } else { ELM_SAFE_FREE(sd->cancel_button, evas_object_del); ELM_SAFE_FREE(sd->ok_button, evas_object_del); } } EOLIAN static Eina_Bool _elm_fileselector_buttons_ok_cancel_get(Eo *obj EINA_UNUSED, Elm_Fileselector_Data *sd) { return sd->ok_button ? EINA_TRUE : EINA_FALSE; } EAPI void elm_fileselector_expandable_set(Evas_Object *obj, Eina_Bool expand) { ELM_FILESELECTOR_INTERFACE_CHECK(obj); elm_interface_fileselector_expandable_set(obj, expand); } EOLIAN static void _elm_fileselector_elm_interface_fileselector_expandable_set(Eo *obj, Elm_Fileselector_Data *sd, Eina_Bool expand) { sd->expand = !!expand; if (sd->model) { _schedule_populate(obj, sd, sd->model, NULL); } } EAPI Eina_Bool elm_fileselector_expandable_get(const Evas_Object *obj) { ELM_FILESELECTOR_INTERFACE_CHECK(obj, EINA_FALSE); return elm_interface_fileselector_expandable_get((Eo *) obj); } EOLIAN static Eina_Bool _elm_fileselector_elm_interface_fileselector_expandable_get(Eo *obj EINA_UNUSED, Elm_Fileselector_Data *sd) { return sd->expand; } EAPI void elm_fileselector_path_set(Evas_Object *obj, const char *_path) { ELM_FILESELECTOR_INTERFACE_CHECK(obj); const Efl_Class *cls = efl_class_get(obj); if (cls == ELM_FILESELECTOR_CLASS) _elm_fileselector_path_set_internal(obj, _path); else if (cls == ELM_FILESELECTOR_ENTRY_CLASS) _elm_fileselector_entry_path_set_internal(obj, _path); else if (cls == ELM_FILESELECTOR_BUTTON_CLASS) _elm_fileselector_button_path_set_internal(obj, _path); else ERR("Unknown Elm.Fileselector class"); } void _elm_fileselector_path_set_internal(Evas_Object *obj, const char *_path) { Eio_Model *model = efl_add(EIO_MODEL_CLASS, NULL, eio_model_path_set(efl_added, _path)); if (!model) { ERR("Efl.Model allocation error"); return; } elm_interface_fileselector_model_set(obj, model); efl_unref(model); } EOLIAN static void _elm_fileselector_elm_interface_fileselector_model_set(Eo *obj, Elm_Fileselector_Data *sd, Efl_Model *model) { _schedule_populate(obj, sd, model, NULL); } EAPI const char * elm_fileselector_path_get(const Evas_Object *obj) { ELM_FILESELECTOR_INTERFACE_CHECK(obj, NULL); const Efl_Class *cls = efl_class_get(obj); if (cls == ELM_FILESELECTOR_CLASS) return _elm_fileselector_path_get_internal(obj); else if (cls == ELM_FILESELECTOR_ENTRY_CLASS) return _elm_fileselector_entry_path_get_internal(obj); else if (cls == ELM_FILESELECTOR_BUTTON_CLASS) return _elm_fileselector_button_path_get_internal(obj); else { ERR("Unknown Elm.Fileselector class"); return NULL; } } const char * _elm_fileselector_path_get_internal(const Evas_Object *obj) { ELM_FILESELECTOR_DATA_GET(obj, sd); return sd->path; } EOLIAN static Efl_Model * _elm_fileselector_elm_interface_fileselector_model_get(Eo *obj EINA_UNUSED, Elm_Fileselector_Data *sd) { return sd->model; } EAPI void elm_fileselector_mode_set(Evas_Object *obj, Elm_Fileselector_Mode mode) { ELM_FILESELECTOR_INTERFACE_CHECK(obj); elm_interface_fileselector_mode_set(obj, mode); } EOLIAN static void _elm_fileselector_elm_interface_fileselector_mode_set(Eo *obj, Elm_Fileselector_Data *sd, Elm_Fileselector_Mode mode) { Evas_Object *old; if (mode == sd->mode) return; old = elm_layout_content_unset(obj, "elm.swallow.files"); if (mode == ELM_FILESELECTOR_LIST) { sd->files_view = _files_list_add(obj); if (sd->multi) elm_genlist_multi_select_set(sd->files_view, EINA_TRUE); } else { sd->files_view = _files_grid_add(obj); if (sd->multi) elm_gengrid_multi_select_set(sd->files_view, EINA_TRUE); } elm_layout_content_set(obj, "elm.swallow.files", sd->files_view); evas_object_del(old); sd->mode = mode; elm_obj_widget_theme_apply(obj); if (sd->model) { _schedule_populate(obj, sd, sd->model, NULL); } } EAPI Elm_Fileselector_Mode elm_fileselector_mode_get(const Evas_Object *obj) { ELM_FILESELECTOR_INTERFACE_CHECK(obj, ELM_FILESELECTOR_LAST); return elm_interface_fileselector_mode_get((Eo *) obj); } EOLIAN static Elm_Fileselector_Mode _elm_fileselector_elm_interface_fileselector_mode_get(Eo *obj EINA_UNUSED, Elm_Fileselector_Data *sd) { return sd->mode; } EAPI void elm_fileselector_multi_select_set(Evas_Object *obj, Eina_Bool multi) { ELM_FILESELECTOR_INTERFACE_CHECK(obj); elm_interface_fileselector_multi_select_set(obj, multi); } EOLIAN static void _elm_fileselector_elm_interface_fileselector_multi_select_set(Eo *obj EINA_UNUSED, Elm_Fileselector_Data *sd, Eina_Bool multi) { multi = !!multi; if (sd->multi == multi) return; sd->multi = multi; if (sd->mode == ELM_FILESELECTOR_LIST) elm_genlist_multi_select_set(sd->files_view, multi); else elm_gengrid_multi_select_set(sd->files_view, multi); if (!sd->multi) { _clear_selections(sd, NULL); sd->multi_selection = eina_list_free(sd->multi_selection); } else { const Eina_List *selected_items, *li; const Elm_Object_Item *it; if (sd->mode == ELM_FILESELECTOR_LIST) selected_items = elm_genlist_selected_items_get(sd->files_view); else selected_items = elm_gengrid_selected_items_get(sd->files_view); EINA_LIST_FOREACH(selected_items, li, it) { sd->multi_selection = eina_list_append(sd->multi_selection, it); } } } EAPI Eina_Bool elm_fileselector_multi_select_get(const Evas_Object *obj) { ELM_FILESELECTOR_INTERFACE_CHECK(obj, EINA_FALSE); return elm_interface_fileselector_multi_select_get((Eo *) obj); } EOLIAN static Eina_Bool _elm_fileselector_elm_interface_fileselector_multi_select_get(Eo *obj EINA_UNUSED, Elm_Fileselector_Data *sd) { return sd->multi; } static Elm_Fileselector_Item_Data * _selected_item_data_get(Elm_Fileselector_Data *sd) { if (sd->mode == ELM_FILESELECTOR_LIST) { Elm_Object_Item *gl_it = elm_genlist_selected_item_get(sd->files_view); if (gl_it) return elm_object_item_data_get(gl_it); } else { Elm_Object_Item *gg_it = elm_gengrid_selected_item_get(sd->files_view); if (gg_it) return elm_object_item_data_get(gg_it); } return NULL; } EAPI const char * elm_fileselector_selected_get(const Evas_Object *obj) { ELM_FILESELECTOR_INTERFACE_CHECK(obj, NULL); const Efl_Class *cls = efl_class_get(obj); if (cls == ELM_FILESELECTOR_CLASS) return _elm_fileselector_selected_get_internal(obj); else if (cls == ELM_FILESELECTOR_ENTRY_CLASS) return _elm_fileselector_entry_selected_get_internal(obj); else if (cls == ELM_FILESELECTOR_BUTTON_CLASS) return _elm_fileselector_button_selected_get_internal(obj); else { ERR("Unknown Elm.Fileselector class"); return NULL; } } const char * _elm_fileselector_selected_get_internal(const Evas_Object *obj) { ELM_FILESELECTOR_DATA_GET(obj, sd); if (!sd->path) return NULL; Elm_Fileselector_Item_Data *it_data = _selected_item_data_get(sd); if (it_data) return it_data->path; return sd->path; } EOLIAN static Efl_Model * _elm_fileselector_elm_interface_fileselector_selected_model_get(Eo *fs EINA_UNUSED, Elm_Fileselector_Data *sd) { if (!sd->model) { return NULL; } Elm_Fileselector_Item_Data *it_data = _selected_item_data_get(sd); if (it_data) return it_data->model; return sd->model; } EAPI Eina_Bool elm_fileselector_selected_set(Evas_Object *obj, const char *_path) { ELM_FILESELECTOR_INTERFACE_CHECK(obj, EINA_FALSE); const Efl_Class *cls = efl_class_get(obj); if (cls == ELM_FILESELECTOR_CLASS) return _elm_fileselector_selected_set_internal(obj, _path); else if (cls == ELM_FILESELECTOR_ENTRY_CLASS) return _elm_fileselector_entry_selected_set_internal(obj, _path); else if (cls == ELM_FILESELECTOR_BUTTON_CLASS) return _elm_fileselector_button_selected_set_internal(obj, _path); else { ERR("Unknown Elm.Fileselector class"); return EINA_FALSE; } } Eina_Bool _elm_fileselector_selected_set_internal(Evas_Object *obj, const char *_path) { ELM_FILESELECTOR_INTERFACE_CHECK(obj, EINA_FALSE); Eina_Bool ret = EINA_FALSE; char *dir; char *path; Eio_Model *model = NULL; Eio_Model *parent = NULL; ELM_FILESELECTOR_DATA_GET(obj, sd); path = ecore_file_realpath(_path); if (ecore_file_is_dir(path)) { model = efl_add(EIO_MODEL_CLASS, NULL, eio_model_path_set(efl_added, path)); if (!model) { ERR("Efl.Model allocation error"); goto clean_up; } _schedule_populate(obj, sd, model, NULL); efl_unref(model); ret = EINA_TRUE; } else { if (!ecore_file_exists(path)) { goto clean_up; } model = efl_add(EIO_MODEL_CLASS, NULL, eio_model_path_set(efl_added, path)); if (!model) { ERR("Efl.Model allocation error"); goto clean_up; } dir = ecore_file_dir_get(path); parent = efl_add(EIO_MODEL_CLASS, NULL, eio_model_path_set(efl_added, dir)); if (parent) { _schedule_populate(obj, sd, parent, model); efl_unref(parent); ret = EINA_TRUE; } free(dir); efl_unref(model); } clean_up: free(path); return ret; } static void _selected_model_set_free_fs_data(Elm_Fileselector *fs) { efl_key_ref_set(fs, _selected_model_set_model_key, NULL); efl_key_data_set(fs, _selected_model_set_promise_owner_key, NULL); efl_unref(fs); } static void _selected_model_set_then_error(void *data, Efl_Event const* event) { Eina_Error err = ((Efl_Future_Event_Failure*)event->info)->error; Efl_Promise *promise_owner = efl_key_data_get(data, _selected_model_set_promise_owner_key); if (promise_owner) efl_promise_failed_set(promise_owner, err); _selected_model_set_free_fs_data(data); } static void _selected_model_set_is_dir_then(void *data, Efl_Event const *event) { Elm_Fileselector *fs = data; Eina_Bool is_dir = EINA_FALSE; Efl_Model *model = efl_key_ref_get(fs, _selected_model_set_model_key); Efl_Promise *promise_owner = efl_key_data_get(fs, _selected_model_set_promise_owner_key); ELM_FILESELECTOR_DATA_GET(fs, sd); eina_value_get((Eina_Value*)((Efl_Future_Event_Success*)event->info)->value, &is_dir); if (is_dir) { _schedule_populate(fs, sd, model, NULL); if (promise_owner) { efl_ref(model); efl_promise_value_set(promise_owner, model, _model_free_eo_cb); } } else { Efl_Model *parent = efl_parent_get(model); if (parent) { _schedule_populate(fs, sd, parent, model); if (promise_owner) { efl_ref(model); efl_promise_value_set(promise_owner, model, _model_free_eo_cb); } } else { if (promise_owner) efl_promise_failed_set(promise_owner, ELM_FILESELECTOR_ERROR_UNKNOWN); } } _selected_model_set_free_fs_data(fs); } EOLIAN static Efl_Future* _elm_fileselector_elm_interface_fileselector_selected_model_set(Eo *obj, Elm_Fileselector_Data *sd EINA_UNUSED, Efl_Model *model) { Efl_Future *future = NULL; Efl_Promise* promise = efl_add(EFL_PROMISE_CLASS, obj); if (!model) { efl_promise_failed_set(promise, ELM_FILESELECTOR_ERROR_INVALID_MODEL); return efl_promise_future_get(promise); } future = efl_model_property_get(model, "is_dir"); efl_key_ref_set(obj, _selected_model_set_model_key, model); efl_key_data_set(obj, _selected_model_set_promise_owner_key, promise); efl_future_then(future, _selected_model_set_is_dir_then, _selected_model_set_then_error, NULL, efl_ref(obj)); return efl_promise_future_get(promise); } EAPI const Eina_List * elm_fileselector_selected_paths_get(const Evas_Object* obj) { ELM_FILESELECTOR_INTERFACE_CHECK(obj, NULL); const Efl_Class *cls = efl_class_get(obj); if (cls == ELM_FILESELECTOR_CLASS) return _elm_fileselector_selected_paths_get_internal(obj); else if (cls == ELM_FILESELECTOR_BUTTON_CLASS) return _elm_fileselector_button_selected_paths_get_internal(obj); else ERR("Unknown Elm.Fileselector class"); return NULL; } const Eina_List * _elm_fileselector_selected_paths_get_internal(const Evas_Object* obj) { ELM_FILESELECTOR_INTERFACE_CHECK(obj, NULL); Eina_List *l; Elm_Object_Item *item; ELM_FILESELECTOR_DATA_GET(obj, sd); if (!sd->multi) return NULL; if (sd->multi_selection_tmp) { sd->multi_selection_tmp = eina_list_free(sd->multi_selection_tmp); } EINA_LIST_FOREACH(sd->multi_selection, l, item) { Elm_Fileselector_Item_Data *it_data = elm_object_item_data_get(item); sd->multi_selection_tmp = eina_list_append(sd->multi_selection_tmp, it_data->path); } return sd->multi_selection_tmp; } EOLIAN static const Eina_List* _elm_fileselector_elm_interface_fileselector_selected_models_get(Eo *obj EINA_UNUSED, Elm_Fileselector_Data *sd) { Eina_List *l; Elm_Object_Item *item; if (!sd->multi) return NULL; if (sd->multi_selection_tmp) { sd->multi_selection_tmp = eina_list_free(sd->multi_selection_tmp); } EINA_LIST_FOREACH(sd->multi_selection, l, item) { Elm_Fileselector_Item_Data *it_data = elm_object_item_data_get(item); sd->multi_selection_tmp = eina_list_append(sd->multi_selection_tmp, it_data->model); } return sd->multi_selection_tmp; } EAPI const char * elm_fileselector_current_name_get(const Evas_Object *obj) { ELM_FILESELECTOR_INTERFACE_CHECK(obj, NULL); const char *ret = NULL; ret = elm_interface_fileselector_current_name_get((Eo *) obj); return ret; } EOLIAN static const char * _elm_fileselector_elm_interface_fileselector_current_name_get(Eo *obj EINA_UNUSED, Elm_Fileselector_Data *sd) { return elm_object_text_get(sd->name_entry); } EAPI void elm_fileselector_current_name_set(Evas_Object *obj, const char *name) { ELM_FILESELECTOR_INTERFACE_CHECK(obj); elm_interface_fileselector_current_name_set((Eo *) obj, name); } EOLIAN static void _elm_fileselector_elm_interface_fileselector_current_name_set(Eo *obj EINA_UNUSED, Elm_Fileselector_Data *sd, const char *name) { elm_object_text_set(sd->name_entry, name); } static Elm_Fileselector_Filter * _filter_add(Elm_Fileselector_Data *sd, const char *filter_name) { Elm_Fileselector_Filter *ff; ff = calloc(1, sizeof(Elm_Fileselector_Filter)); if (!ff) return NULL; ff->filter_name = eina_stringshare_add(filter_name); ff->sd = sd; return ff; } EAPI Eina_Bool elm_fileselector_mime_types_filter_append(Evas_Object *obj, const char *mime_type, const char *filter_name) { ELM_FILESELECTOR_CHECK(obj) EINA_FALSE; return elm_interface_fileselector_mime_types_filter_append(obj, mime_type, filter_name); } EOLIAN static Eina_Bool _elm_fileselector_elm_interface_fileselector_mime_types_filter_append(Eo *obj, Elm_Fileselector_Data *sd, const char *mime_types, const char *filter_name) { Elm_Fileselector_Filter *ff; char buf[1024]; if (!mime_types) return EINA_FALSE; ff = _filter_add(sd, filter_name ? filter_name : mime_types); if (!ff) return EINA_FALSE; ff->filter_type = ELM_FILESELECTOR_MIME_FILTER; ff->filter.mime_types = eina_str_split(mime_types, ",", 0); if (!sd->filter_list) { sd->current_filter = ff; sd->filter_hoversel = elm_hoversel_add(obj); elm_object_text_set(sd->filter_hoversel, ff->filter_name); snprintf(buf, sizeof(buf), "fileselector/actions/%s", elm_widget_style_get(obj)); elm_widget_style_set(sd->filter_hoversel, buf); elm_object_part_content_set(obj, "elm.swallow.filters", sd->filter_hoversel); } elm_hoversel_item_add(sd->filter_hoversel, ff->filter_name, NULL, ELM_ICON_NONE, _current_filter_changed, ff); sd->filter_list = eina_list_append(sd->filter_list, ff); if (sd->model) { _schedule_populate(obj, sd, sd->model, NULL); } return EINA_TRUE; } EAPI Eina_Bool elm_fileselector_custom_filter_append(Evas_Object *obj, Elm_Fileselector_Filter_Func func, void *data, const char *filter_name) { ELM_FILESELECTOR_INTERFACE_CHECK(obj, EINA_FALSE); return elm_interface_fileselector_custom_filter_append(obj, func, data, filter_name); } EOLIAN static Eina_Bool _elm_fileselector_elm_interface_fileselector_custom_filter_append(Eo *obj, Elm_Fileselector_Data *sd, Elm_Fileselector_Filter_Func func, void *data, const char *filter_name) { Elm_Fileselector_Filter *ff; Elm_Fileselector_Custom_Filter *custom_filter; char buf[1024]; if (!func) return EINA_FALSE; custom_filter = calloc(1, sizeof(Elm_Fileselector_Custom_Filter)); if (!custom_filter) return EINA_FALSE; ff = _filter_add(sd, filter_name ? filter_name : "custom"); if (!ff) { free(custom_filter); return EINA_FALSE; } ff->filter_type = ELM_FILESELECTOR_CUSTOM_FILTER; ff->filter.custom = custom_filter; ff->filter.custom->func = func; ff->filter.custom->data = data; if (!sd->filter_list) { sd->current_filter = ff; sd->filter_hoversel = elm_hoversel_add(obj); elm_object_text_set(sd->filter_hoversel, ff->filter_name); snprintf(buf, sizeof(buf), "fileselector/actions/%s", elm_widget_style_get(obj)); elm_widget_style_set(sd->filter_hoversel, buf); elm_object_part_content_set(obj, "elm.swallow.filters", sd->filter_hoversel); } elm_hoversel_item_add(sd->filter_hoversel, ff->filter_name, NULL, ELM_ICON_NONE, _current_filter_changed, ff); sd->filter_list = eina_list_append(sd->filter_list, ff); if (sd->model) { _schedule_populate(obj, sd, sd->model, NULL); } return EINA_TRUE; } EAPI void elm_fileselector_filters_clear(Evas_Object *obj) { ELM_FILESELECTOR_INTERFACE_CHECK(obj); elm_interface_fileselector_filters_clear(obj); } EOLIAN static void _elm_fileselector_elm_interface_fileselector_filters_clear(Eo *obj, Elm_Fileselector_Data *sd) { Elm_Fileselector_Filter *filter; EINA_LIST_FREE(sd->filter_list, filter) { eina_stringshare_del(filter->filter_name); if (filter->filter_type == ELM_FILESELECTOR_MIME_FILTER) { free(filter->filter.mime_types[0]); free(filter->filter.mime_types); } else free(filter->filter.custom); free(filter); } ELM_SAFE_FREE(sd->filter_hoversel, evas_object_del); if (sd->model) { _schedule_populate(obj, sd, sd->model, NULL); } } EAPI void elm_fileselector_hidden_visible_set(Evas_Object *obj, Eina_Bool visible) { ELM_FILESELECTOR_INTERFACE_CHECK(obj); elm_interface_fileselector_hidden_visible_set(obj, visible); } EOLIAN static void _elm_fileselector_elm_interface_fileselector_hidden_visible_set(Eo *obj EINA_UNUSED, Elm_Fileselector_Data *sd, Eina_Bool visible) { visible = !!visible; if (sd->hidden_visible == visible) return; sd->hidden_visible = visible; _clear_selections(sd, NULL); if (sd->model) { _schedule_populate(obj, sd, sd->model, NULL); } } EAPI Eina_Bool elm_fileselector_hidden_visible_get(const Evas_Object *obj) { ELM_FILESELECTOR_INTERFACE_CHECK(obj, EINA_FALSE); return elm_interface_fileselector_hidden_visible_get((Eo *) obj); } EOLIAN static Eina_Bool _elm_fileselector_elm_interface_fileselector_hidden_visible_get(Eo *obj EINA_UNUSED, Elm_Fileselector_Data *sd) { return sd->hidden_visible; } EAPI void elm_fileselector_thumbnail_size_set(Evas_Object *obj, Evas_Coord w, Evas_Coord h) { ELM_FILESELECTOR_INTERFACE_CHECK(obj); elm_interface_fileselector_thumbnail_size_set(obj, w, h); } EOLIAN static void _elm_fileselector_elm_interface_fileselector_thumbnail_size_set(Eo *obj EINA_UNUSED, Elm_Fileselector_Data *sd, Evas_Coord w, Evas_Coord h) { if (sd->thumbnail_size.w == w && sd->thumbnail_size.h == h) return; if (!w || !h) w = h = ITEM_SIZE_DEFAULT; sd->thumbnail_size.w = w; sd->thumbnail_size.h = h; if (sd->mode == ELM_FILESELECTOR_GRID) elm_gengrid_item_size_set(sd->files_view, w, h); if (sd->model) { _schedule_populate(obj, sd, sd->model, NULL); } } EAPI void elm_fileselector_thumbnail_size_get(const Evas_Object *obj, Evas_Coord *w, Evas_Coord *h) { ELM_FILESELECTOR_INTERFACE_CHECK(obj); elm_interface_fileselector_thumbnail_size_get((Eo *) obj, w, h); } EOLIAN static void _elm_fileselector_elm_interface_fileselector_thumbnail_size_get(Eo *obj EINA_UNUSED, Elm_Fileselector_Data *sd, Evas_Coord *w, Evas_Coord *h) { if (w) *w = sd->thumbnail_size.w; if (h) *h = sd->thumbnail_size.h; } EAPI void elm_fileselector_sort_method_set(Evas_Object *obj, Elm_Fileselector_Sort sort) { ELM_FILESELECTOR_INTERFACE_CHECK(obj); elm_interface_fileselector_sort_method_set(obj, sort); } EOLIAN static void _elm_fileselector_elm_interface_fileselector_sort_method_set(Eo *obj EINA_UNUSED, Elm_Fileselector_Data *sd, Elm_Fileselector_Sort sort) { if (sd->sort_type == sort) return; sd->sort_type = sort; switch (sd->sort_type) { case ELM_FILESELECTOR_SORT_BY_FILENAME_ASC: sd->sort_method = _filename_cmp; break; case ELM_FILESELECTOR_SORT_BY_FILENAME_DESC: sd->sort_method = _filename_cmp_rev; break; case ELM_FILESELECTOR_SORT_BY_TYPE_ASC: sd->sort_method = _type_cmp; break; case ELM_FILESELECTOR_SORT_BY_TYPE_DESC: sd->sort_method = _type_cmp_rev; break; case ELM_FILESELECTOR_SORT_BY_SIZE_ASC: sd->sort_method = _size_cmp; break; case ELM_FILESELECTOR_SORT_BY_SIZE_DESC: sd->sort_method = _size_cmp_rev; break; case ELM_FILESELECTOR_SORT_BY_MODIFIED_ASC: sd->sort_method = _modified_cmp; break; case ELM_FILESELECTOR_SORT_BY_MODIFIED_DESC: sd->sort_method = _modified_cmp_rev; break; case ELM_FILESELECTOR_SORT_LAST: default: sd->sort_method = _filename_cmp; } if (sd->model) { _schedule_populate(obj, sd, sd->model, NULL); } } EAPI Elm_Fileselector_Sort elm_fileselector_sort_method_get(const Evas_Object *obj) { ELM_FILESELECTOR_INTERFACE_CHECK(obj, ELM_FILESELECTOR_SORT_LAST); return elm_interface_fileselector_sort_method_get((Eo *) obj); } EOLIAN static Elm_Fileselector_Sort _elm_fileselector_elm_interface_fileselector_sort_method_get(Eo *obj EINA_UNUSED, Elm_Fileselector_Data *sd) { return sd->sort_type; } EOLIAN static Eina_Bool _elm_fileselector_elm_widget_focus_next_manager_is(Eo *obj EINA_UNUSED, Elm_Fileselector_Data *sd EINA_UNUSED) { return EINA_TRUE; } EOLIAN static Eina_Bool _elm_fileselector_elm_widget_focus_next(Eo *obj EINA_UNUSED, Elm_Fileselector_Data *sd, Elm_Focus_Direction dir, Evas_Object **next, Elm_Object_Item **next_item) { Eina_List *items = NULL; if (sd->up_button) items = eina_list_append(items, sd->up_button); if (sd->home_button) items = eina_list_append(items, sd->home_button); if (sd->files_view) items = eina_list_append(items, sd->files_view); if (sd->path_entry) items = eina_list_append(items, sd->path_entry); if (sd->name_entry) items = eina_list_append(items, sd->name_entry); if (sd->filter_hoversel) items = eina_list_append(items, sd->filter_hoversel); if (sd->cancel_button) items = eina_list_append(items, sd->cancel_button); if (sd->ok_button) items = eina_list_append(items, sd->ok_button); if (_elm_config->access_mode) return elm_widget_focus_list_next_get(obj, items, eina_list_data_get, dir, next, next_item); if (!elm_widget_focus_list_next_get(obj, items, eina_list_data_get, dir, next, next_item)) *next = (Evas_Object *)obj; eina_list_free(items); return EINA_TRUE; } EOLIAN static Eina_Bool _elm_fileselector_elm_widget_focus_direction_manager_is(Eo *obj EINA_UNUSED, Elm_Fileselector_Data *sd EINA_UNUSED) { return EINA_TRUE; } EOLIAN static Eina_Bool _elm_fileselector_elm_widget_focus_direction(Eo *obj EINA_UNUSED, Elm_Fileselector_Data *sd, const Evas_Object *base, double degree, Evas_Object **direction, Elm_Object_Item **direction_item, double *weight) { Eina_List *items = NULL; if (sd->up_button) items = eina_list_append(items, sd->up_button); if (sd->home_button) items = eina_list_append(items, sd->home_button); if (sd->files_view) items = eina_list_append(items, sd->files_view); if (sd->path_entry) items = eina_list_append(items, sd->path_entry); if (sd->name_entry) items = eina_list_append(items, sd->name_entry); if (sd->filter_hoversel) items = eina_list_append(items, sd->filter_hoversel); if (sd->cancel_button) items = eina_list_append(items, sd->cancel_button); if (sd->ok_button) items = eina_list_append(items, sd->ok_button); elm_widget_focus_list_direction_get (obj, base, items, eina_list_data_get, degree, direction, direction_item, weight); eina_list_free(items); return EINA_TRUE; } EOLIAN static Eina_Bool _elm_fileselector_text_set(Eo *obj EINA_UNUSED, Elm_Fileselector_Data *sd, const char *part, const char *label) { if (!part) return EINA_FALSE; if (sd->ok_button && !strcmp(part, "ok")) { elm_object_text_set(sd->ok_button, label); return EINA_TRUE; } else if (sd->cancel_button && !strcmp(part, "cancel")) { elm_object_text_set(sd->cancel_button, label); return EINA_TRUE; } else { Eina_Bool int_ret = EINA_TRUE; efl_text_set(efl_part(efl_super(obj, MY_CLASS), part), label); return int_ret; } return EINA_FALSE; } EOLIAN static void _elm_fileselector_class_constructor(Efl_Class *klass) { unsigned int i; evas_smart_legacy_type_register(MY_CLASS_NAME_LEGACY, klass); ELM_FILESELECTOR_ERROR_UNKNOWN = eina_error_msg_static_register(ELM_FILESELECTOR_ERROR_UNKNOWN_STR); ELM_FILESELECTOR_ERROR_INVALID_MODEL = eina_error_msg_static_register(ELM_FILESELECTOR_ERROR_INVALID_MODEL_STR); for (i = 0; i < ELM_FILE_LAST; ++i) { list_itc[i] = elm_genlist_item_class_new(); grid_itc[i] = elm_gengrid_item_class_new(); list_itc[i]->item_style = "default"; list_itc[i]->func.text_get = grid_itc[i]->func.text_get = _itc_text_get; list_itc[i]->func.state_get = grid_itc[i]->func.state_get = _itc_state_get; list_itc[i]->func.del = grid_itc[i]->func.del = _itc_del; } list_itc[ELM_DIRECTORY]->func.content_get = grid_itc[ELM_DIRECTORY]->func.content_get = _itc_icon_folder_get; list_itc[ELM_FILE_IMAGE]->func.content_get = grid_itc[ELM_FILE_IMAGE]->func.content_get = _itc_icon_image_get; list_itc[ELM_FILE_UNKNOW]->func.content_get = grid_itc[ELM_FILE_UNKNOW]->func.content_get = _itc_icon_file_get; } EOLIAN static void _elm_fileselector_class_destructor(Efl_Class *klass EINA_UNUSED) { unsigned int i; for (i = 0; i < ELM_FILE_LAST; ++i) { elm_genlist_item_class_free(list_itc[i]); elm_gengrid_item_class_free(grid_itc[i]); } } EOLIAN const Elm_Atspi_Action * _elm_fileselector_elm_interface_atspi_widget_action_elm_actions_get(Eo *obj EINA_UNUSED, Elm_Fileselector_Data *pd EINA_UNUSED) { static Elm_Atspi_Action atspi_actions[] = { { "select", "select", NULL, _key_action_select }, { "escape", "escape", NULL, _key_action_escape}, { "backspace", "backspace", NULL, _key_action_backspace}, { NULL, NULL, NULL, NULL} }; return &atspi_actions[0]; } /* Efl.Part begin */ ELM_PART_OVERRIDE(elm_fileselector, ELM_FILESELECTOR, ELM_LAYOUT, Elm_Fileselector_Data, Elm_Part_Data) ELM_PART_OVERRIDE_TEXT_SET(elm_fileselector, ELM_FILESELECTOR, ELM_LAYOUT, Elm_Fileselector_Data, Elm_Part_Data) #include "elm_fileselector_internal_part.eo.c" /* Efl.Part end */ /* Internal EO APIs and hidden overrides */ #define ELM_FILESELECTOR_EXTRA_OPS \ EFL_CANVAS_GROUP_ADD_DEL_OPS(elm_fileselector), \ EFL_OBJECT_OP_FUNC(efl_event_callback_legacy_call, _elm_fileselector_efl_object_event_callback_legacy_call) #include "elm_fileselector.eo.c" diff --git a/src/lib/elementary/elc_fileselector_button.c b/src/lib/elementary/elc_fileselector_button.c index 48fc60a408..dc224a277e 100644 --- a/src/lib/elementary/elc_fileselector_button.c +++ b/src/lib/elementary/elc_fileselector_button.c @@ -1,671 +1,671 @@ #ifdef HAVE_CONFIG_H # include "elementary_config.h" #endif #define ELM_INTERFACE_ATSPI_ACCESSIBLE_PROTECTED #include #include "elm_priv.h" #include "elm_fileselector_button.eo.h" #include "elm_fileselector_entry.eo.h" #include "elm_interface_fileselector.h" #include "elm_widget_fileselector_button.h" #define MY_CLASS ELM_FILESELECTOR_BUTTON_CLASS #define MY_CLASS_NAME "Elm_Fileselector_Button" #define MY_CLASS_NAME_LEGACY "elm_fileselector_button" /* FIXME: need a way to find a gap between the size of item and thumbnail */ #define GENGRID_PADDING 16 #define DEFAULT_WINDOW_TITLE "Select a file" #define ELM_PRIV_FILESELECTOR_BUTTON_SIGNALS(cmd) \ cmd(SIG_FILE_CHOSEN, "file,chosen", "s") \ ELM_PRIV_FILESELECTOR_BUTTON_SIGNALS(ELM_PRIV_STATIC_VARIABLE_DECLARE); static const Evas_Smart_Cb_Description _smart_callbacks[] = { ELM_PRIV_FILESELECTOR_BUTTON_SIGNALS(ELM_PRIV_SMART_CALLBACKS_DESC) {SIG_WIDGET_LANG_CHANGED, ""}, /**style), buf); int_ret = elm_obj_widget_theme_apply(efl_super(obj, MY_CLASS)); if (!int_ret) return ELM_THEME_APPLY_FAILED; eina_stringshare_replace(&(wd->style), style); eina_stringshare_del(style); return int_ret; } static void _replace_path_then(void *data, Efl_Event const *event) { Elm_Fileselector_Button_Data *sd = data; Efl_Future_Event_Success *ev = event->info; Eina_Value *v = ev->value; const char *path = NULL; eina_value_get(v, &path); eina_stringshare_replace(&sd->fsd.path, path); _event_to_legacy_call (sd->obj, ELM_FILESELECTOR_BUTTON_EVENT_FILE_CHOSEN, (void *)path); } static void _replace_path_then_error(void *data, Efl_Event const* event EINA_UNUSED) { Elm_Fileselector_Button_Data *sd = data; ERR("could not get information from Efl.Model"); eina_stringshare_replace(&sd->fsd.path, NULL); _event_to_legacy_call (sd->obj, ELM_FILESELECTOR_BUTTON_EVENT_FILE_CHOSEN, NULL); } static void _selection_done(void *data, const Efl_Event *event) { Elm_Fileselector_Button_Data *sd = data; Efl_Model *model = event->info; Evas_Object *del; if (model) { Efl_Future *future = NULL; if (sd->fsd.model) efl_unref(sd->fsd.model); sd->fsd.model = efl_ref(model); future = efl_model_property_get(model, "path"); efl_future_then(future, _replace_path_then, _replace_path_then_error, NULL, sd); efl_event_callback_call (sd->obj, ELM_FILESELECTOR_BUTTON_EVENT_FILE_CHOSEN, model); } else { _model_event_call (sd->obj, ELM_FILESELECTOR_BUTTON_EVENT_FILE_CHOSEN, NULL, NULL); } del = sd->fsw; sd->fs = NULL; sd->fsw = NULL; evas_object_del(del); } static Evas_Object * _new_window_add(Elm_Fileselector_Button_Data *sd) { Evas_Object *win, *bg; win = elm_win_add(NULL, "fileselector_button", ELM_WIN_DIALOG_BASIC); elm_win_title_set(win, sd->window_title); elm_win_autodel_set(win, EINA_TRUE); efl_event_callback_add (win, EFL_UI_WIN_EVENT_DELETE_REQUEST, _selection_done, sd); bg = elm_bg_add(win); evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); elm_win_resize_object_add(win, bg); evas_object_show(bg); evas_object_resize(win, sd->w, sd->h); return win; } static Evas_Object * _parent_win_get(Evas_Object *obj) { while (!efl_isa(obj, EFL_UI_WIN_CLASS)) obj = elm_object_parent_widget_get(obj); return obj; } static void _activate(Elm_Fileselector_Button_Data *sd) { Eina_Bool is_inwin = EINA_FALSE; if (sd->fs) return; if (sd->inwin_mode) { sd->fsw = _parent_win_get(sd->obj); if (!sd->fsw) sd->fsw = _new_window_add(sd); else { sd->fsw = elm_win_inwin_add(sd->fsw); is_inwin = EINA_TRUE; } } else sd->fsw = _new_window_add(sd); sd->fs = elm_fileselector_add(sd->fsw); efl_ui_mirrored_set (sd->fs, efl_ui_mirrored_get(sd->obj)); - elm_widget_mirrored_automatic_set(sd->fs, EINA_FALSE); + efl_ui_mirrored_automatic_set(sd->fs, EINA_FALSE); elm_fileselector_expandable_set(sd->fs, sd->fsd.expandable); elm_fileselector_folder_only_set(sd->fs, sd->fsd.folder_only); elm_fileselector_is_save_set(sd->fs, sd->fsd.is_save); elm_interface_fileselector_selected_model_set(sd->fs, sd->fsd.model); evas_object_size_hint_weight_set (sd->fs, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); evas_object_size_hint_align_set(sd->fs, EVAS_HINT_FILL, EVAS_HINT_FILL); efl_event_callback_add (sd->fs, ELM_FILESELECTOR_EVENT_DONE, _selection_done, sd); evas_object_show(sd->fs); if (is_inwin) { elm_win_inwin_content_set(sd->fsw, sd->fs); elm_win_inwin_activate(sd->fsw); } else { elm_win_resize_object_add(sd->fsw, sd->fs); evas_object_show(sd->fsw); } } static void _button_clicked(void *data, const Efl_Event *event EINA_UNUSED) { _activate(data); } EOLIAN static void _elm_fileselector_button_efl_canvas_group_group_add(Eo *obj, Elm_Fileselector_Button_Data *priv) { const char *path; efl_canvas_group_add(efl_super(obj, MY_CLASS)); elm_widget_sub_object_parent_add(obj); priv->window_title = eina_stringshare_add(DEFAULT_WINDOW_TITLE); path = eina_environment_home_get(); if (path) priv->fsd.path = eina_stringshare_add(path); else priv->fsd.path = eina_stringshare_add("/"); priv->fsd.model = efl_add(EIO_MODEL_CLASS, NULL, eio_model_path_set(efl_added, priv->fsd.path)); priv->fsd.expandable = _elm_config->fileselector_expand_enable; priv->inwin_mode = _elm_config->inwin_dialogs_enable; priv->w = 400; priv->h = 400; - elm_widget_mirrored_automatic_set(obj, EINA_FALSE); + efl_ui_mirrored_automatic_set(obj, EINA_FALSE); efl_event_callback_add(obj, EFL_UI_EVENT_CLICKED, _button_clicked, priv); elm_obj_widget_theme_apply(obj); elm_widget_can_focus_set(obj, EINA_TRUE); } EOLIAN static void _elm_fileselector_button_efl_canvas_group_group_del(Eo *obj, Elm_Fileselector_Button_Data *sd) { if (sd->fsd.model) efl_unref(sd->fsd.model); eina_stringshare_del(sd->window_title); eina_stringshare_del(sd->fsd.path); if (sd->fsd.selection) efl_unref(sd->fsd.selection); eina_stringshare_del(sd->fsd.selection_path); evas_object_del(sd->fsw); efl_canvas_group_del(efl_super(obj, MY_CLASS)); } EOLIAN static Eina_Bool _elm_fileselector_button_efl_ui_autorepeat_autorepeat_supported_get(Eo *obj EINA_UNUSED, Elm_Fileselector_Button_Data *sd EINA_UNUSED) { return EINA_FALSE; } EAPI Evas_Object * elm_fileselector_button_add(Evas_Object *parent) { EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL); Evas_Object *obj = efl_add(MY_CLASS, parent); return obj; } EOLIAN static Eo * _elm_fileselector_button_efl_object_constructor(Eo *obj, Elm_Fileselector_Button_Data *sd) { obj = efl_constructor(efl_super(obj, MY_CLASS)); sd->obj = obj; efl_canvas_object_type_set(obj, MY_CLASS_NAME_LEGACY); evas_object_smart_callbacks_descriptions_set(obj, _smart_callbacks); elm_interface_atspi_accessible_role_set(obj, ELM_ATSPI_ROLE_PUSH_BUTTON); return obj; } EAPI void elm_fileselector_button_window_title_set(Eo *obj, const char *title) { ELM_FILESELECTOR_BUTTON_CHECK(obj); ELM_FILESELECTOR_BUTTON_DATA_GET_OR_RETURN(obj, sd); eina_stringshare_replace(&sd->window_title, title); if (sd->fsw) elm_win_title_set(sd->fsw, sd->window_title); } EAPI const char * elm_fileselector_button_window_title_get(const Eo *obj) { ELM_FILESELECTOR_BUTTON_CHECK(obj) NULL; ELM_FILESELECTOR_BUTTON_DATA_GET_OR_RETURN_VAL(obj, sd, NULL); return sd->window_title; } EAPI void elm_fileselector_button_window_size_set(Eo *obj, Evas_Coord width, Evas_Coord height) { ELM_FILESELECTOR_BUTTON_CHECK(obj); ELM_FILESELECTOR_BUTTON_DATA_GET_OR_RETURN(obj, sd); sd->w = width; sd->h = height; if (sd->fsw) evas_object_resize(sd->fsw, sd->w, sd->h); } EAPI void elm_fileselector_button_window_size_get(const Eo *obj, Evas_Coord *width, Evas_Coord *height) { if (width) *width = 0; if (height) *height = 0; ELM_FILESELECTOR_BUTTON_CHECK(obj); ELM_FILESELECTOR_BUTTON_DATA_GET_OR_RETURN(obj, sd); if (width) *width = sd->w; if (height) *height = sd->h; } void _elm_fileselector_button_path_set_internal(Evas_Object *obj, const char *path) { ELM_FILESELECTOR_BUTTON_DATA_GET_OR_RETURN(obj, sd); Efl_Model *model = efl_add(EIO_MODEL_CLASS, NULL, eio_model_path_set(efl_added, path)); if (!model) { ERR("Efl.Model allocation error"); return; } if (sd->fsd.model) efl_unref(sd->fsd.model); sd->fsd.model = efl_ref(model); eina_stringshare_replace(&sd->fsd.path, path); if (sd->fs) elm_interface_fileselector_selected_model_set(sd->fs, model); } EINA_DEPRECATED EAPI void elm_fileselector_button_path_set(Evas_Object *obj, const char *path) { ELM_FILESELECTOR_INTERFACE_CHECK(obj); elm_fileselector_path_set(obj, path); } EOLIAN static void _elm_fileselector_button_elm_interface_fileselector_model_set(Eo *obj EINA_UNUSED, Elm_Fileselector_Button_Data *sd, Efl_Model *model) { if (sd->fsd.model) efl_unref(sd->fsd.model); if (model) { sd->fsd.model = efl_ref(model); efl_future_then(efl_model_property_get(model, "path"), _replace_path_then, _replace_path_then_error, NULL, sd); } else { sd->fsd.model = NULL; eina_stringshare_replace(&sd->fsd.path, NULL); } if (sd->fs) elm_interface_fileselector_selected_model_set(sd->fs, model); } const char * _elm_fileselector_button_path_get_internal(const Evas_Object *obj) { ELM_FILESELECTOR_BUTTON_DATA_GET_OR_RETURN_VAL(obj, sd, NULL); return sd->fsd.path; } EINA_DEPRECATED EAPI const char * elm_fileselector_button_path_get(const Evas_Object *obj) { ELM_FILESELECTOR_INTERFACE_CHECK(obj, NULL); return elm_fileselector_path_get(obj); } EOLIAN static Efl_Model * _elm_fileselector_button_elm_interface_fileselector_model_get(Eo *obj EINA_UNUSED, Elm_Fileselector_Button_Data *sd) { return sd->fsd.model; } EINA_DEPRECATED EAPI void elm_fileselector_button_expandable_set(Evas_Object *obj, Eina_Bool value) { ELM_FILESELECTOR_INTERFACE_CHECK(obj); elm_interface_fileselector_expandable_set(obj, value); } EOLIAN static void _elm_fileselector_button_elm_interface_fileselector_expandable_set(Eo *obj EINA_UNUSED, Elm_Fileselector_Button_Data *sd, Eina_Bool value) { sd->fsd.expandable = value; if (sd->fs) elm_fileselector_expandable_set(sd->fs, sd->fsd.expandable); } EINA_DEPRECATED EAPI Eina_Bool elm_fileselector_button_expandable_get(const Evas_Object *obj) { ELM_FILESELECTOR_INTERFACE_CHECK(obj, EINA_FALSE); Eina_Bool ret = EINA_FALSE; ret = elm_interface_fileselector_expandable_get((Eo *) obj); return ret; } EOLIAN static Eina_Bool _elm_fileselector_button_elm_interface_fileselector_expandable_get(Eo *obj EINA_UNUSED, Elm_Fileselector_Button_Data *sd) { return sd->fsd.expandable; } EINA_DEPRECATED EAPI void elm_fileselector_button_folder_only_set(Evas_Object *obj, Eina_Bool value) { ELM_FILESELECTOR_INTERFACE_CHECK(obj); elm_interface_fileselector_folder_only_set(obj, value); } EOLIAN static void _elm_fileselector_button_elm_interface_fileselector_folder_only_set(Eo *obj EINA_UNUSED, Elm_Fileselector_Button_Data *sd, Eina_Bool value) { sd->fsd.folder_only = value; if (sd->fs) elm_fileselector_folder_only_set(sd->fs, sd->fsd.folder_only); } EINA_DEPRECATED EAPI Eina_Bool elm_fileselector_button_folder_only_get(const Evas_Object *obj) { ELM_FILESELECTOR_INTERFACE_CHECK(obj, EINA_FALSE); Eina_Bool ret = EINA_FALSE; ret = elm_interface_fileselector_folder_only_get((Eo *) obj); return ret; } EOLIAN static Eina_Bool _elm_fileselector_button_elm_interface_fileselector_folder_only_get(Eo *obj EINA_UNUSED, Elm_Fileselector_Button_Data *sd) { return sd->fsd.folder_only; } EINA_DEPRECATED EAPI void elm_fileselector_button_is_save_set(Evas_Object *obj, Eina_Bool value) { ELM_FILESELECTOR_INTERFACE_CHECK(obj); elm_interface_fileselector_is_save_set(obj, value); } EOLIAN static void _elm_fileselector_button_elm_interface_fileselector_is_save_set(Eo *obj EINA_UNUSED, Elm_Fileselector_Button_Data *sd, Eina_Bool value) { sd->fsd.is_save = value; if (sd->fs) elm_fileselector_is_save_set(sd->fs, sd->fsd.is_save); } EINA_DEPRECATED EAPI Eina_Bool elm_fileselector_button_is_save_get(const Evas_Object *obj) { ELM_FILESELECTOR_INTERFACE_CHECK(obj, EINA_FALSE); Eina_Bool ret = EINA_FALSE; ret = elm_interface_fileselector_is_save_get((Eo *) obj); return ret; } EOLIAN static Eina_Bool _elm_fileselector_button_elm_interface_fileselector_is_save_get(Eo *obj EINA_UNUSED, Elm_Fileselector_Button_Data *sd) { return sd->fsd.is_save; } EOLIAN static void _elm_fileselector_button_elm_interface_fileselector_mode_set(Eo *obj EINA_UNUSED, Elm_Fileselector_Button_Data *sd, Elm_Fileselector_Mode mode) { sd->fsd.mode = mode; if (sd->fs) elm_fileselector_mode_set(sd->fs, mode); } EOLIAN static Elm_Fileselector_Mode _elm_fileselector_button_elm_interface_fileselector_mode_get(Eo *obj EINA_UNUSED, Elm_Fileselector_Button_Data *sd) { return sd->fsd.mode; } EOLIAN static void _elm_fileselector_button_elm_interface_fileselector_sort_method_set(Eo *obj EINA_UNUSED, Elm_Fileselector_Button_Data *sd, Elm_Fileselector_Sort sort) { sd->fsd.sort_type = sort; if (sd->fs) elm_fileselector_sort_method_set(sd->fs, sort); } EOLIAN static Elm_Fileselector_Sort _elm_fileselector_button_elm_interface_fileselector_sort_method_get(Eo *obj EINA_UNUSED, Elm_Fileselector_Button_Data *sd) { return sd->fsd.sort_type; } EOLIAN static void _elm_fileselector_button_elm_interface_fileselector_multi_select_set(Eo *obj EINA_UNUSED, Elm_Fileselector_Button_Data *sd, Eina_Bool value) { sd->fsd.multi = value; if (sd->fs) elm_fileselector_multi_select_set(sd->fs, sd->fsd.multi); } EOLIAN static Eina_Bool _elm_fileselector_button_elm_interface_fileselector_multi_select_get(Eo *obj EINA_UNUSED, Elm_Fileselector_Button_Data *sd) { return sd->fsd.multi; } const Eina_List * _elm_fileselector_button_selected_paths_get_internal(const Evas_Object *obj) { ELM_FILESELECTOR_BUTTON_DATA_GET_OR_RETURN_VAL(obj, sd, NULL); if (sd->fs) return elm_fileselector_selected_paths_get(sd->fs); return NULL; } EOLIAN static const Eina_List* _elm_fileselector_button_elm_interface_fileselector_selected_models_get(Eo *obj EINA_UNUSED, Elm_Fileselector_Button_Data *sd) { if (sd->fs) return elm_interface_fileselector_selected_models_get(sd->fs); return NULL; } const char * _elm_fileselector_button_selected_get_internal(const Evas_Object *obj) { ELM_FILESELECTOR_BUTTON_DATA_GET_OR_RETURN_VAL(obj, sd, NULL); if (sd->fs) return elm_fileselector_selected_get(sd->fs); return sd->fsd.selection_path; } EOLIAN static Efl_Model * _elm_fileselector_button_elm_interface_fileselector_selected_model_get(Eo *obj EINA_UNUSED, Elm_Fileselector_Button_Data *sd) { if (sd->fs) return elm_interface_fileselector_selected_model_get(sd->fs); return sd->fsd.selection; } Eina_Bool _elm_fileselector_button_selected_set_internal(Evas_Object *obj, const char *_path) { ELM_FILESELECTOR_BUTTON_DATA_GET_OR_RETURN_VAL(obj, sd, EINA_FALSE); Eina_Bool ret = EINA_TRUE; if (sd->fs) ret = elm_fileselector_selected_set(sd->fs, _path); else { char *path = ecore_file_realpath(_path); if (!ecore_file_is_dir(path) && !ecore_file_exists(path)) { free(path); return EINA_FALSE; } free(path); } eina_stringshare_replace(&sd->fsd.selection_path, _path); return ret; } static void _selected_model_then(void *data, Efl_Event const *event) { Eo* v = (Eo*)((Efl_Future_Event_Success*)event->info)->value; Efl_Promise *owner = data; efl_promise_value_set(owner, efl_ref(v), _model_free_eo_cb); } static void _selected_model_then_error(void *data, Efl_Event const* event) { Efl_Promise *owner = data; efl_promise_failed_set(owner, ((Efl_Future_Event_Failure*)event->info)->error); } EOLIAN static Efl_Future* _elm_fileselector_button_elm_interface_fileselector_selected_model_set(Eo *obj EINA_UNUSED, Elm_Fileselector_Button_Data *sd, Efl_Model *model) { Efl_Promise* promise = efl_add(EFL_PROMISE_CLASS, obj); if (sd->fs) { efl_future_then(elm_interface_fileselector_selected_model_set(sd->fs, model), _selected_model_then, _selected_model_then_error, NULL, promise); } else efl_promise_failed_set(promise, EINA_ERROR_FUTURE_CANCEL); if (sd->fsd.selection) efl_unref(sd->fsd.selection); sd->fsd.selection = model ? efl_ref(model) : NULL; return efl_promise_future_get(promise); } EOLIAN static void _elm_fileselector_button_elm_interface_fileselector_thumbnail_size_set(Eo *obj EINA_UNUSED, Elm_Fileselector_Button_Data *sd, Evas_Coord w, Evas_Coord h) { if (sd->fs) { elm_fileselector_thumbnail_size_set(sd->fs, w, h); elm_fileselector_thumbnail_size_get(sd->fs, &w, &h); } else if (!w || !h) w = h = elm_config_finger_size_get() * 2 - GENGRID_PADDING; sd->fsd.thumbnail_size.w = w; sd->fsd.thumbnail_size.h = h; } EOLIAN static void _elm_fileselector_button_elm_interface_fileselector_thumbnail_size_get(Eo *obj EINA_UNUSED, Elm_Fileselector_Button_Data *sd, Evas_Coord *w, Evas_Coord *h) { if (w) *w = sd->fsd.thumbnail_size.w; if (h) *h = sd->fsd.thumbnail_size.h; } EOLIAN static void _elm_fileselector_button_elm_interface_fileselector_hidden_visible_set(Eo *obj EINA_UNUSED, Elm_Fileselector_Button_Data *sd, Eina_Bool visible) { sd->fsd.hidden_visible = visible; if (sd->fs) elm_fileselector_hidden_visible_set(sd->fs, visible); } EOLIAN static Eina_Bool _elm_fileselector_button_elm_interface_fileselector_hidden_visible_get(Eo *obj EINA_UNUSED, Elm_Fileselector_Button_Data *sd) { return sd->fsd.hidden_visible; } EAPI void elm_fileselector_button_inwin_mode_set(Eo *obj, Eina_Bool value) { ELM_FILESELECTOR_BUTTON_CHECK(obj); ELM_FILESELECTOR_BUTTON_DATA_GET_OR_RETURN(obj, sd); sd->inwin_mode = value; } EAPI Eina_Bool elm_fileselector_button_inwin_mode_get(const Eo *obj) { ELM_FILESELECTOR_BUTTON_CHECK(obj) EINA_FALSE; ELM_FILESELECTOR_BUTTON_DATA_GET_OR_RETURN_VAL(obj, sd, EINA_FALSE); return sd->inwin_mode; } /* Internal EO APIs and hidden overrides */ #define ELM_FILESELECTOR_BUTTON_EXTRA_OPS \ EFL_CANVAS_GROUP_ADD_DEL_OPS(elm_fileselector_button) #include "elm_fileselector_button.eo.c" diff --git a/src/lib/elementary/elc_fileselector_entry.c b/src/lib/elementary/elc_fileselector_entry.c index 18f1ac70d6..25183fe05f 100644 --- a/src/lib/elementary/elc_fileselector_entry.c +++ b/src/lib/elementary/elc_fileselector_entry.c @@ -1,693 +1,693 @@ //FIXME this widget should inherit from file selector button #ifdef HAVE_CONFIG_H # include "elementary_config.h" #endif #define ELM_INTERFACE_ATSPI_ACCESSIBLE_PROTECTED #include #include "elm_priv.h" #include "elm_fileselector_button.eo.h" #include "elm_fileselector_entry.eo.h" #include "elm_interface_fileselector.h" #include "elm_widget_fileselector_entry.h" #include "elm_fileselector_entry_internal_part.eo.h" #include "elm_part_helper.h" #define MY_CLASS ELM_FILESELECTOR_ENTRY_CLASS #define MY_CLASS_NAME "Elm_Fileselector_Entry" #define MY_CLASS_NAME_LEGACY "elm_fileselector_entry" #define ELM_PRIV_FILESELECTOR_ENTRY_SIGNALS(cmd) \ cmd(SIG_CHANGED, "changed", "") \ cmd(SIG_ACTIVATED, "activated", "") \ cmd(SIG_PRESS, "press", "") \ cmd(SIG_LONGPRESSED, "longpressed", "") \ cmd(SIG_CLICKED, "clicked", "") \ cmd(SIG_CLICKED_DOUBLE, "clicked,double", "") \ cmd(SIG_FOCUSED, "focused", "") \ cmd(SIG_UNFOCUSED, "unfocused", "") \ cmd(SIG_SELECTION_PASTE, "selection,paste", "") \ cmd(SIG_SELECTION_COPY, "selection,copy", "") \ cmd(SIG_SELECTION_CUT, "selection,cut", "") \ cmd(SIG_UNPRESSED, "unpressed", "") \ cmd(SIG_FILE_CHOSEN, "file,chosen", "s") \ ELM_PRIV_FILESELECTOR_ENTRY_SIGNALS(ELM_PRIV_STATIC_VARIABLE_DECLARE); static const Evas_Smart_Cb_Description _smart_callbacks[] = { ELM_PRIV_FILESELECTOR_ENTRY_SIGNALS(ELM_PRIV_SMART_CALLBACKS_DESC) {SIG_WIDGET_LANG_CHANGED, ""}, /**< handled by elm_widget */ {SIG_WIDGET_ACCESS_CHANGED, ""}, /**< handled by elm_widget */ {NULL, NULL} }; #undef ELM_PRIV_FILESELECTOR_ENTRY_SIGNALS #define SIG_FWD(name, event) \ static void \ _##name##_fwd(void *data, const Efl_Event *ev EINA_UNUSED) \ { \ efl_event_callback_legacy_call(data, event, ev->info); \ } SIG_FWD(CHANGED, ELM_FILESELECTOR_ENTRY_EVENT_CHANGED) SIG_FWD(PRESS, ELM_FILESELECTOR_ENTRY_EVENT_PRESS) SIG_FWD(LONGPRESSED, EFL_UI_EVENT_LONGPRESSED) SIG_FWD(CLICKED, EFL_UI_EVENT_CLICKED) SIG_FWD(CLICKED_DOUBLE, EFL_UI_EVENT_CLICKED_DOUBLE) SIG_FWD(FOCUSED, ELM_WIDGET_EVENT_FOCUSED) SIG_FWD(UNFOCUSED, ELM_WIDGET_EVENT_UNFOCUSED) SIG_FWD(SELECTION_PASTE, EFL_UI_EVENT_SELECTION_PASTE) SIG_FWD(SELECTION_COPY, EFL_UI_EVENT_SELECTION_COPY) SIG_FWD(SELECTION_CUT, EFL_UI_EVENT_SELECTION_CUT) SIG_FWD(UNPRESSED, EFL_UI_EVENT_UNPRESSED) #undef SIG_FWD static void _file_chosen_path_then(void *data, Efl_Event const* event) { Eina_Array *args = data; const char *file = NULL; char *s; Eo *fs = eina_array_data_get(args, 0); Efl_Model *model = eina_array_data_get(args, 1); eina_array_free(args); eina_value_get((Eina_Value*)((Efl_Future_Event_Success*)event->info)->value, &file); if (!file) return; ELM_FILESELECTOR_ENTRY_DATA_GET(fs, sd); s = elm_entry_utf8_to_markup(file); elm_object_text_set(sd->entry, s); free(s); _model_event_call (fs, ELM_FILESELECTOR_ENTRY_EVENT_FILE_CHOSEN, model, file); } static void _file_chosen_path_then_error(void *data, Efl_Event const* event) { Eina_Error err = ((Efl_Future_Event_Failure*)event->info)->error; ERR("Efl.Model property \"path\" error: %s", eina_error_msg_get(err)); eina_array_free(data); } static void _FILE_CHOSEN_fwd(void *data, const Efl_Event *event) { Efl_Model *model = event->info; Efl_Future *future = NULL; Eina_Array *args = NULL; if (!model) return; args = eina_array_new(2); eina_array_push(args, data); eina_array_push(args, model); future = efl_model_property_get(model, "path"); efl_future_then (future, _file_chosen_path_then, _file_chosen_path_then_error, NULL, args); } static void _ACTIVATED_fwd(void *data, const Efl_Event *event) { const char *file; Efl_Model *bmodel, *model; Eina_Value path; ELM_FILESELECTOR_ENTRY_DATA_GET(data, sd); file = elm_object_text_get(sd->entry); bmodel = elm_interface_fileselector_model_get(sd->button); if (bmodel) { model = efl_add(efl_class_get(bmodel), NULL); eina_value_setup(&path, EINA_VALUE_TYPE_STRING); eina_value_set(&path, file); efl_model_property_set(model, "path", &path); eina_value_flush(&path); elm_interface_fileselector_model_set(sd->button, model); } efl_event_callback_legacy_call (data, ELM_FILESELECTOR_ENTRY_EVENT_ACTIVATED, event->info); } static void _model_free_eo_cb(void *eo) { efl_unref(eo); } EOLIAN static void _elm_fileselector_entry_elm_layout_sizing_eval(Eo *obj, Elm_Fileselector_Entry_Data *sd EINA_UNUSED) { Evas_Coord minw = -1, minh = -1; ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd); edje_object_size_min_calc(wd->resize_obj, &minw, &minh); evas_object_size_hint_min_set(obj, minw, minh); evas_object_size_hint_max_set(obj, -1, -1); } EOLIAN static Eina_Bool _elm_fileselector_entry_elm_widget_focus_next_manager_is(Eo *obj EINA_UNUSED, Elm_Fileselector_Entry_Data *sd EINA_UNUSED) { return EINA_TRUE; } EOLIAN static Eina_Bool _elm_fileselector_entry_elm_widget_focus_direction_manager_is(Eo *obj EINA_UNUSED, Elm_Fileselector_Entry_Data *sd EINA_UNUSED) { return EINA_FALSE; } EOLIAN static Eina_Bool _elm_fileselector_entry_elm_widget_focus_next(Eo *obj EINA_UNUSED, Elm_Fileselector_Entry_Data *sd, Elm_Focus_Direction dir, Evas_Object **next, Elm_Object_Item **next_item) { Evas_Object *chain[2]; Evas_Object *to_focus; unsigned char i; /* Direction */ if (dir == ELM_FOCUS_PREVIOUS) { chain[0] = sd->button; chain[1] = sd->entry; } else if (dir == ELM_FOCUS_NEXT) { chain[0] = sd->entry; chain[1] = sd->button; } else return EINA_FALSE; i = elm_widget_focus_get(chain[1]); if (elm_widget_focus_next_get(chain[i], dir, next, next_item)) return EINA_TRUE; i = !i; if (elm_widget_focus_next_get(chain[i], dir, &to_focus, next_item)) { *next = to_focus; return !!i; } return EINA_FALSE; } EOLIAN static Elm_Theme_Apply _elm_fileselector_entry_elm_widget_theme_apply(Eo *obj, Elm_Fileselector_Entry_Data *sd) { const char *style; char buf[1024]; ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd, ELM_THEME_APPLY_FAILED); Elm_Theme_Apply int_ret = ELM_THEME_APPLY_FAILED; int_ret = elm_obj_widget_theme_apply(efl_super(obj, MY_CLASS)); if (!int_ret) return ELM_THEME_APPLY_FAILED; style = elm_widget_style_get(obj); efl_ui_mirrored_set(sd->button, efl_ui_mirrored_get(obj)); if (elm_object_disabled_get(obj)) elm_layout_signal_emit(obj, "elm,state,disabled", "elm"); if (!style) style = "default"; snprintf(buf, sizeof(buf), "fileselector_entry/%s", style); elm_widget_style_set(sd->button, buf); elm_widget_style_set(sd->entry, buf); edje_object_message_signal_process(wd->resize_obj); elm_layout_sizing_eval(obj); return int_ret; } EOLIAN static Eina_Bool _elm_fileselector_entry_elm_widget_disable(Eo *obj, Elm_Fileselector_Entry_Data *sd) { Eina_Bool val; Eina_Bool int_ret = EINA_FALSE; int_ret = elm_obj_widget_disable(efl_super(obj, MY_CLASS)); if (!int_ret) return EINA_FALSE; val = elm_widget_disabled_get(obj); elm_widget_disabled_set(sd->button, val); elm_widget_disabled_set(sd->entry, val); return EINA_TRUE; } EOLIAN static Eina_Bool _elm_fileselector_entry_text_set(Eo *obj, Elm_Fileselector_Entry_Data *sd, const char *part, const char *label) { if (part && strcmp(part, "default")) { efl_text_set(efl_part(efl_super(obj, MY_CLASS), part), label); } elm_object_text_set(sd->button, label); return EINA_TRUE; } EOLIAN static const char * _elm_fileselector_entry_text_get(Eo *obj, Elm_Fileselector_Entry_Data *sd, const char *part) { if (part && strcmp(part, "default")) { const char *text = NULL; text = efl_text_get(efl_part(efl_super(obj, MY_CLASS), part)); return text; } return elm_object_text_get(sd->button); } static Eina_Bool _elm_fileselector_entry_content_set(Eo *obj, Elm_Fileselector_Entry_Data *sd, const char *part, Evas_Object *content) { if (part && strcmp(part, "button icon")) { return efl_content_set(efl_part(efl_super(obj, MY_CLASS), part), content); } elm_layout_content_set(sd->button, NULL, content); return EINA_TRUE; } static Evas_Object * _elm_fileselector_entry_content_get(Eo *obj, Elm_Fileselector_Entry_Data *sd, const char *part) { if (part && strcmp(part, "button icon")) { return efl_content_get(efl_part(efl_super(obj, MY_CLASS), part)); } return elm_layout_content_get(sd->button, NULL); } static Evas_Object * _elm_fileselector_entry_content_unset(Eo *obj, Elm_Fileselector_Entry_Data *sd, const char *part) { if (part && strcmp(part, "button icon")) { return efl_content_unset(efl_part(efl_super(obj, MY_CLASS), part)); } return elm_layout_content_unset(sd->button, NULL); } EOLIAN static void _elm_fileselector_entry_efl_canvas_group_group_add(Eo *obj, Elm_Fileselector_Entry_Data *priv) { efl_canvas_group_add(efl_super(obj, MY_CLASS)); elm_widget_sub_object_parent_add(obj); priv->button = elm_fileselector_button_add(obj); - elm_widget_mirrored_automatic_set(priv->button, EINA_FALSE); + efl_ui_mirrored_automatic_set(priv->button, EINA_FALSE); efl_ui_mirrored_set(priv->button, efl_ui_mirrored_get(obj)); elm_widget_style_set(priv->button, "fileselector_entry/default"); elm_fileselector_expandable_set (priv->button, _elm_config->fileselector_expand_enable); #define SIG_FWD(name, event) \ efl_event_callback_add(priv->button, event, _##name##_fwd, obj) SIG_FWD(CLICKED, EFL_UI_EVENT_CLICKED); SIG_FWD(UNPRESSED, EFL_UI_EVENT_UNPRESSED); SIG_FWD(FILE_CHOSEN, ELM_FILESELECTOR_BUTTON_EVENT_FILE_CHOSEN); #undef SIG_FWD priv->entry = elm_entry_add(obj); elm_entry_scrollable_set(priv->entry, EINA_TRUE); - elm_widget_mirrored_automatic_set(priv->entry, EINA_FALSE); + efl_ui_mirrored_automatic_set(priv->entry, EINA_FALSE); elm_widget_style_set(priv->entry, "fileselector_entry/default"); elm_entry_single_line_set(priv->entry, EINA_TRUE); elm_entry_editable_set(priv->entry, EINA_TRUE); #define SIG_FWD(name, event) \ efl_event_callback_add(priv->entry, event, _##name##_fwd, obj) SIG_FWD(CHANGED, ELM_ENTRY_EVENT_CHANGED); SIG_FWD(ACTIVATED, ELM_ENTRY_EVENT_ACTIVATED); SIG_FWD(PRESS, ELM_ENTRY_EVENT_PRESS); SIG_FWD(LONGPRESSED, EFL_UI_EVENT_LONGPRESSED); SIG_FWD(CLICKED, EFL_UI_EVENT_CLICKED); SIG_FWD(CLICKED_DOUBLE, EFL_UI_EVENT_CLICKED_DOUBLE); SIG_FWD(FOCUSED, ELM_WIDGET_EVENT_FOCUSED); SIG_FWD(UNFOCUSED, ELM_WIDGET_EVENT_UNFOCUSED); SIG_FWD(SELECTION_PASTE, EFL_UI_EVENT_SELECTION_PASTE); SIG_FWD(SELECTION_COPY, EFL_UI_EVENT_SELECTION_COPY); SIG_FWD(SELECTION_CUT, EFL_UI_EVENT_SELECTION_CUT); #undef SIG_FWD if (!elm_layout_theme_set (obj, "fileselector_entry", "base", elm_widget_style_get(obj))) CRI("Failed to set layout!"); else { elm_layout_content_set(obj, "elm.swallow.button", priv->button); elm_layout_content_set(obj, "elm.swallow.entry", priv->entry); } elm_layout_sizing_eval(obj); } EOLIAN static void _elm_fileselector_entry_efl_canvas_group_group_del(Eo *obj, Elm_Fileselector_Entry_Data *sd) { free(sd->path); efl_canvas_group_del(efl_super(obj, MY_CLASS)); } EAPI Evas_Object * elm_fileselector_entry_add(Evas_Object *parent) { EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL); return efl_add(MY_CLASS, parent); } EOLIAN static Eo * _elm_fileselector_entry_efl_object_constructor(Eo *obj, Elm_Fileselector_Entry_Data *sd EINA_UNUSED) { obj = efl_constructor(efl_super(obj, MY_CLASS)); efl_canvas_object_type_set(obj, MY_CLASS_NAME_LEGACY); evas_object_smart_callbacks_descriptions_set(obj, _smart_callbacks); elm_interface_atspi_accessible_role_set(obj, ELM_ATSPI_ROLE_GROUPING); return obj; } EINA_DEPRECATED EAPI void elm_fileselector_entry_selected_set(Evas_Object *obj, const char *path) { ELM_FILESELECTOR_INTERFACE_CHECK(obj); elm_fileselector_selected_set(obj, path); } Eina_Bool _elm_fileselector_entry_selected_set_internal(Evas_Object *obj, const char *path) { ELM_FILESELECTOR_ENTRY_DATA_GET_OR_RETURN_VAL(obj, sd, EINA_FALSE); elm_fileselector_path_set(sd->button, path); return EINA_TRUE; } EOLIAN static Efl_Future* _elm_fileselector_entry_elm_interface_fileselector_selected_model_set(Eo *obj EINA_UNUSED, Elm_Fileselector_Entry_Data *sd, Efl_Model *model) { Efl_Promise* promise = efl_add(EFL_PROMISE_CLASS, obj); Efl_Future* future = efl_promise_future_get(promise); elm_interface_fileselector_model_set(sd->button, model); efl_promise_value_set(promise, efl_ref(model), _model_free_eo_cb); return future; } EINA_DEPRECATED EAPI const char * elm_fileselector_entry_selected_get(const Evas_Object *obj) { ELM_FILESELECTOR_INTERFACE_CHECK(obj, NULL); return elm_fileselector_selected_get((Eo *) obj); } const char * _elm_fileselector_entry_selected_get_internal(const Evas_Object *obj) { ELM_FILESELECTOR_ENTRY_DATA_GET_OR_RETURN_VAL(obj, sd, NULL); return elm_fileselector_path_get(sd->button); } EOLIAN static Efl_Model * _elm_fileselector_entry_elm_interface_fileselector_selected_model_get(Eo *obj EINA_UNUSED, Elm_Fileselector_Entry_Data *sd) { return elm_interface_fileselector_model_get(sd->button); } EAPI void elm_fileselector_entry_window_title_set(Eo *obj, const char *title) { ELM_FILESELECTOR_ENTRY_CHECK(obj); ELM_FILESELECTOR_ENTRY_DATA_GET_OR_RETURN(obj, sd); elm_fileselector_button_window_title_set(sd->button, title); } EAPI const char * elm_fileselector_entry_window_title_get(const Eo *obj) { ELM_FILESELECTOR_ENTRY_CHECK(obj) NULL; ELM_FILESELECTOR_ENTRY_DATA_GET_OR_RETURN_VAL(obj, sd, NULL); return elm_fileselector_button_window_title_get(sd->button); } EAPI void elm_fileselector_entry_window_size_set(Eo *obj, Evas_Coord width, Evas_Coord height) { ELM_FILESELECTOR_ENTRY_CHECK(obj); ELM_FILESELECTOR_ENTRY_DATA_GET_OR_RETURN(obj, sd); elm_fileselector_button_window_size_set(sd->button, width, height); } EAPI void elm_fileselector_entry_window_size_get(const Eo *obj, Evas_Coord *width, Evas_Coord *height) { if (width) *width = 0; if (height) *height = 0; ELM_FILESELECTOR_ENTRY_CHECK(obj); ELM_FILESELECTOR_ENTRY_DATA_GET_OR_RETURN(obj, sd); elm_fileselector_button_window_size_get(sd->button, width, height); } EINA_DEPRECATED EAPI void elm_fileselector_entry_path_set(Evas_Object *obj, const char *path) { ELM_FILESELECTOR_INTERFACE_CHECK(obj); elm_fileselector_path_set(obj, path); } void _elm_fileselector_entry_path_set_internal(Evas_Object *obj, const char *path) { ELM_FILESELECTOR_ENTRY_DATA_GET_OR_RETURN(obj, sd); char *s; elm_fileselector_path_set(sd->button, path); s = elm_entry_utf8_to_markup(path); if (s) { elm_object_text_set(sd->entry, s); free(s); } } static void _fs_entry_model_path_get_then(void *data, Efl_Event const *event) { Elm_Fileselector_Entry_Data *sd = data; char *path = NULL; char *s; Eina_Value* v = (Eina_Value*)((Efl_Future_Event_Success*)event->info)->value; if (!v) return; eina_value_get(v, &path); s = elm_entry_utf8_to_markup(path); if (s) { elm_object_text_set(sd->entry, s); free(s); } } EOLIAN static void _elm_fileselector_entry_elm_interface_fileselector_model_set(Eo *obj EINA_UNUSED, Elm_Fileselector_Entry_Data *sd, Efl_Model *model) { Efl_Future *p = NULL; elm_interface_fileselector_model_set(sd->button, model); p = efl_model_property_get(model, "path"); efl_future_then(p, _fs_entry_model_path_get_then, NULL, NULL, sd); } EINA_DEPRECATED EAPI const char * elm_fileselector_entry_path_get(const Evas_Object *obj) { ELM_FILESELECTOR_INTERFACE_CHECK(obj, NULL); return elm_fileselector_path_get(obj); } const char * _elm_fileselector_entry_path_get_internal(const Evas_Object *obj) { ELM_FILESELECTOR_ENTRY_DATA_GET_OR_RETURN_VAL(obj, sd, NULL); free(sd->path); sd->path = elm_entry_markup_to_utf8(elm_object_text_get(sd->entry)); return sd->path; } EOLIAN static Efl_Model * _elm_fileselector_entry_elm_interface_fileselector_model_get(Eo *obj EINA_UNUSED, Elm_Fileselector_Entry_Data *sd) { Efl_Model *bmodel, *ret; Eina_Value path; bmodel = elm_interface_fileselector_model_get(sd->button); if (!bmodel) { WRN("no base Efl.Model"); return NULL; } ret = efl_add(efl_class_get(bmodel), NULL); free(sd->path); sd->path = elm_entry_markup_to_utf8(elm_object_text_get(sd->entry)); eina_value_setup(&path, EINA_VALUE_TYPE_STRING); eina_value_set(&path, sd->path); efl_model_property_set(ret, "path", &path); eina_value_flush(&path); return ret; } EINA_DEPRECATED EAPI void elm_fileselector_entry_expandable_set(Evas_Object *obj, Eina_Bool value) { ELM_FILESELECTOR_INTERFACE_CHECK(obj); elm_interface_fileselector_expandable_set(obj, value); } EOLIAN static void _elm_fileselector_entry_elm_interface_fileselector_expandable_set(Eo *obj EINA_UNUSED, Elm_Fileselector_Entry_Data *sd, Eina_Bool value) { elm_fileselector_expandable_set(sd->button, value); } EINA_DEPRECATED EAPI Eina_Bool elm_fileselector_entry_expandable_get(const Evas_Object *obj) { ELM_FILESELECTOR_INTERFACE_CHECK(obj, EINA_FALSE); return elm_interface_fileselector_expandable_get((Eo *) obj); } EOLIAN static Eina_Bool _elm_fileselector_entry_elm_interface_fileselector_expandable_get(Eo *obj EINA_UNUSED, Elm_Fileselector_Entry_Data *sd) { return elm_fileselector_expandable_get(sd->button); } EINA_DEPRECATED EAPI void elm_fileselector_entry_folder_only_set(Evas_Object *obj, Eina_Bool value) { ELM_FILESELECTOR_INTERFACE_CHECK(obj); elm_interface_fileselector_folder_only_set(obj, value); } EOLIAN static void _elm_fileselector_entry_elm_interface_fileselector_folder_only_set(Eo *obj EINA_UNUSED, Elm_Fileselector_Entry_Data *sd, Eina_Bool value) { elm_fileselector_folder_only_set(sd->button, value); } EINA_DEPRECATED EAPI Eina_Bool elm_fileselector_entry_folder_only_get(const Evas_Object *obj) { ELM_FILESELECTOR_INTERFACE_CHECK(obj, EINA_FALSE); return elm_interface_fileselector_folder_only_get((Eo *) obj); } EOLIAN static Eina_Bool _elm_fileselector_entry_elm_interface_fileselector_folder_only_get(Eo *obj EINA_UNUSED, Elm_Fileselector_Entry_Data *sd) { return elm_fileselector_folder_only_get(sd->button); } EINA_DEPRECATED EAPI void elm_fileselector_entry_is_save_set(Evas_Object *obj, Eina_Bool value) { ELM_FILESELECTOR_INTERFACE_CHECK(obj); elm_interface_fileselector_is_save_set(obj, value); } EOLIAN static void _elm_fileselector_entry_elm_interface_fileselector_is_save_set(Eo *obj EINA_UNUSED, Elm_Fileselector_Entry_Data *sd, Eina_Bool value) { elm_fileselector_is_save_set(sd->button, value); } EINA_DEPRECATED EAPI Eina_Bool elm_fileselector_entry_is_save_get(const Evas_Object *obj) { ELM_FILESELECTOR_INTERFACE_CHECK(obj, EINA_FALSE); return elm_interface_fileselector_is_save_get((Eo *) obj); } EOLIAN static Eina_Bool _elm_fileselector_entry_elm_interface_fileselector_is_save_get(Eo *obj EINA_UNUSED, Elm_Fileselector_Entry_Data *sd) { return elm_fileselector_is_save_get(sd->button); } EAPI void elm_fileselector_entry_inwin_mode_set(Eo *obj, Eina_Bool value) { ELM_FILESELECTOR_ENTRY_CHECK(obj); ELM_FILESELECTOR_ENTRY_DATA_GET_OR_RETURN(obj, sd); elm_fileselector_button_inwin_mode_set(sd->button, value); } EAPI Eina_Bool elm_fileselector_entry_inwin_mode_get(const Eo *obj) { ELM_FILESELECTOR_ENTRY_CHECK(obj) EINA_FALSE; ELM_FILESELECTOR_ENTRY_DATA_GET_OR_RETURN_VAL(obj, sd, EINA_FALSE); return elm_fileselector_button_inwin_mode_get(sd->button); } EOLIAN static void _elm_fileselector_entry_class_constructor(Efl_Class *klass) { evas_smart_legacy_type_register(MY_CLASS_NAME_LEGACY, klass); } /* Efl.Part begin */ ELM_PART_OVERRIDE(elm_fileselector_entry, ELM_FILESELECTOR_ENTRY, ELM_LAYOUT, Elm_Fileselector_Entry_Data, Elm_Part_Data) ELM_PART_OVERRIDE_CONTENT_SET(elm_fileselector_entry, ELM_FILESELECTOR_ENTRY, ELM_LAYOUT, Elm_Fileselector_Entry_Data, Elm_Part_Data) ELM_PART_OVERRIDE_CONTENT_GET(elm_fileselector_entry, ELM_FILESELECTOR_ENTRY, ELM_LAYOUT, Elm_Fileselector_Entry_Data, Elm_Part_Data) ELM_PART_OVERRIDE_CONTENT_UNSET(elm_fileselector_entry, ELM_FILESELECTOR_ENTRY, ELM_LAYOUT, Elm_Fileselector_Entry_Data, Elm_Part_Data) ELM_PART_OVERRIDE_TEXT_SET(elm_fileselector_entry, ELM_FILESELECTOR_ENTRY, ELM_LAYOUT, Elm_Fileselector_Entry_Data, Elm_Part_Data) ELM_PART_OVERRIDE_TEXT_GET(elm_fileselector_entry, ELM_FILESELECTOR_ENTRY, ELM_LAYOUT, Elm_Fileselector_Entry_Data, Elm_Part_Data) #include "elm_fileselector_entry_internal_part.eo.c" /* Efl.Part end */ /* Internal EO APIs and hidden overrides */ #define ELM_FILESELECTOR_ENTRY_EXTRA_OPS \ EFL_CANVAS_GROUP_ADD_DEL_OPS(elm_fileselector_entry) #include "elm_fileselector_entry.eo.c" diff --git a/src/lib/elementary/elc_player.c b/src/lib/elementary/elc_player.c index bde0f04657..c2204462ed 100644 --- a/src/lib/elementary/elc_player.c +++ b/src/lib/elementary/elc_player.c @@ -1,721 +1,721 @@ #ifdef HAVE_CONFIG_H # include "elementary_config.h" #endif #include #define ELM_INTERFACE_ATSPI_ACCESSIBLE_PROTECTED #define ELM_INTERFACE_ATSPI_WIDGET_ACTION_PROTECTED #include #include "elm_priv.h" #include "elm_widget_layout.h" #include "elm_widget_player.h" #include "elm_player_internal_part.eo.h" #include "elm_part_helper.h" #define MY_CLASS ELM_PLAYER_CLASS #define MY_CLASS_NAME "Elm_Player" #define MY_CLASS_NAME_LEGACY "elm_player" static const char SIG_FORWARD_CLICKED[] = "forward,clicked"; static const char SIG_INFO_CLICKED[] = "info,clicked"; static const char SIG_NEXT_CLICKED[] = "next,clicked"; static const char SIG_PAUSE_CLICKED[] = "pause,clicked"; static const char SIG_PLAY_CLICKED[] = "play,clicked"; static const char SIG_PREV_CLICKED[] = "prev,clicked"; static const char SIG_REWIND_CLICKED[] = "rewind,clicked"; static const char SIG_STOP_CLICKED[] = "stop,clicked"; static const char SIG_EJECT_CLICKED[] = "eject,clicked"; static const char SIG_VOLUME_CLICKED[] = "volume,clicked"; static const char SIG_MUTE_CLICKED[] = "mute,clicked"; /* static const char SIG_STOP_CLICKED[] = "repeat,clicked"; static const char SIG_STOP_CLICKED[] = "shuffle,clicked"; static const char SIG_STOP_CLICKED[] = "record,clicked"; static const char SIG_STOP_CLICKED[] = "replay,clicked"; static const char SIG_STOP_CLICKED[] = "power,clicked"; static const char SIG_STOP_CLICKED[] = "fullscreen,clicked"; static const char SIG_STOP_CLICKED[] = "normal,clicked"; static const char SIG_STOP_CLICKED[] = "quality,clicked"; */ static const Evas_Smart_Cb_Description _smart_callbacks[] = { { SIG_FORWARD_CLICKED, "" }, { SIG_INFO_CLICKED, "" }, { SIG_NEXT_CLICKED, "" }, { SIG_PAUSE_CLICKED, "" }, { SIG_PLAY_CLICKED, "" }, { SIG_PREV_CLICKED, "" }, { SIG_REWIND_CLICKED, "" }, { SIG_STOP_CLICKED, "" }, { SIG_EJECT_CLICKED, "" }, { SIG_VOLUME_CLICKED, "" }, { SIG_MUTE_CLICKED, "" }, { SIG_WIDGET_LANG_CHANGED, ""}, /**< handled by elm_widget */ { SIG_LAYOUT_FOCUSED, ""}, /**< handled by elm_layout */ { SIG_LAYOUT_UNFOCUSED, ""}, /**< handled by elm_layout */ { NULL, NULL } }; static void _update_frame(void *data, const Efl_Event *event); static void _update_slider(void *data, const Efl_Event *event); static void _play_started(void *data, const Efl_Event *event); static void _play_finished(void *data, const Efl_Event *event); static void _update_position(void *data, const Efl_Event *event); static void _drag_start(void *data, const Efl_Event *event); static void _drag_stop(void *data, const Efl_Event *event); static Eina_Bool _key_action_move(Evas_Object *obj, const char *params); static Eina_Bool _key_action_play(Evas_Object *obj, const char *params); static const Elm_Action key_actions[] = { {"move", _key_action_move}, {"play", _key_action_play}, {NULL, NULL} }; EFL_CALLBACKS_ARRAY_DEFINE(_emotion_cb, { EFL_CANVAS_VIDEO_EVENT_FRAME_DECODE, _update_frame }, { EFL_CANVAS_VIDEO_EVENT_FRAME_RESIZE, _update_slider }, { EFL_CANVAS_VIDEO_EVENT_LENGTH_CHANGE, _update_slider }, { EFL_CANVAS_VIDEO_EVENT_POSITION_CHANGE, _update_frame }, { EFL_CANVAS_VIDEO_EVENT_PLAYBACK_START, _play_started }, { EFL_CANVAS_VIDEO_EVENT_PLAYBACK_STOP, _play_finished } ); EFL_CALLBACKS_ARRAY_DEFINE(_slider_cb, { EFL_UI_SLIDER_EVENT_CHANGED, _update_position }, { EFL_UI_SLIDER_EVENT_SLIDER_DRAG_START, _drag_start }, { EFL_UI_SLIDER_EVENT_SLIDER_DRAG_STOP, _drag_stop } ); static Eina_Bool _key_action_move(Evas_Object *obj, const char *params) { ELM_PLAYER_DATA_GET(obj, sd); const char *dir = params; _elm_widget_focus_auto_show(obj); if (!strcmp(dir, "left")) { double current, last; current = elm_video_play_position_get(sd->video); last = elm_video_play_length_get(sd->video); if (current < last) { current -= last / 100; elm_video_play_position_set(sd->video, current); } } else if (!strcmp(dir, "right")) { double current, last; current = elm_video_play_position_get(sd->video); last = elm_video_play_length_get(sd->video); if (current > 0) { current += last / 100; if (current < 0) current = 0; elm_video_play_position_set(sd->video, current); } } else return EINA_FALSE; return EINA_TRUE; } static Eina_Bool _key_action_play(Evas_Object *obj, const char *params EINA_UNUSED) { ELM_PLAYER_DATA_GET(obj, sd); if (elm_video_is_playing_get(sd->video)) elm_video_pause(sd->video); else elm_video_play(sd->video); return EINA_TRUE; } EOLIAN static Eina_Bool _elm_player_elm_widget_widget_event(Eo *obj, Elm_Player_Data *sd, Evas_Object *src, Evas_Callback_Type type, void *event_info) { Evas_Event_Key_Down *ev = event_info; (void) src; if (type != EVAS_CALLBACK_KEY_DOWN) return EINA_FALSE; if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return EINA_FALSE; if (!sd->video) return EINA_FALSE; if (!_elm_config_key_binding_call(obj, MY_CLASS_NAME, ev, key_actions)) return EINA_FALSE; ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD; return EINA_TRUE; } static void _update_theme_button(Evas_Object *obj, Evas_Object *bt, const char *name) { Evas_Object *ic; char buf[256]; if (!bt) return; ic = evas_object_data_get(bt, "icon"); if (ic) { snprintf(buf, sizeof(buf), "media_player/%s/%s", name, elm_widget_style_get(obj)); elm_icon_standard_set(ic, buf); } snprintf(buf, sizeof(buf), "media_player/%s/%s", name, elm_widget_style_get(obj)); elm_object_style_set(bt, buf); snprintf(buf, sizeof(buf), "elm.swallow.media_player.%s", name); if (!elm_layout_content_set(obj, buf, bt)) evas_object_hide(bt); elm_object_disabled_set(bt, elm_widget_disabled_get(obj)); } static void _update_theme_slider(Evas_Object *obj, Evas_Object *sl, const char *name, const char *name2) { char buf[256]; if (!sl) return; snprintf(buf, sizeof(buf), "media_player/%s/%s", name, elm_widget_style_get(obj)); elm_object_style_set(sl, buf); snprintf(buf, sizeof(buf), "elm.swallow.media_player.%s", name2); if (!elm_layout_content_set(obj, buf, sl)) evas_object_hide(sl); elm_object_disabled_set(sl, elm_widget_disabled_get(obj)); } EOLIAN static Elm_Theme_Apply _elm_player_elm_widget_theme_apply(Eo *obj, Elm_Player_Data *sd) { Elm_Theme_Apply int_ret = ELM_THEME_APPLY_FAILED; int_ret = elm_obj_widget_theme_apply(efl_super(obj, MY_CLASS)); if (!int_ret) return ELM_THEME_APPLY_FAILED; _update_theme_button(obj, sd->forward, "forward"); _update_theme_button(obj, sd->info, "info"); _update_theme_button(obj, sd->next, "next"); _update_theme_button(obj, sd->pause, "pause"); _update_theme_button(obj, sd->play, "play"); _update_theme_button(obj, sd->prev, "prev"); _update_theme_button(obj, sd->rewind, "rewind"); _update_theme_button(obj, sd->next, "next"); _update_theme_button(obj, sd->stop, "stop"); _update_theme_button(obj, sd->eject, "eject"); _update_theme_button(obj, sd->volume, "volume"); _update_theme_button(obj, sd->mute, "mute"); _update_theme_slider(obj, sd->slider, "position", "positionslider"); _update_theme_slider(obj, sd->vslider, "volume", "volumeslider"); elm_layout_sizing_eval(obj); return int_ret; } EOLIAN static void _elm_player_elm_layout_sizing_eval(Eo *obj, Elm_Player_Data *sd EINA_UNUSED) { Evas_Coord w, h; ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd); edje_object_size_min_get(wd->resize_obj, &w, &h); edje_object_size_min_restricted_calc (wd->resize_obj, &w, &h, w, h); evas_object_size_hint_min_set(obj, w, h); } static void _update_slider(void *data, const Efl_Event *event EINA_UNUSED) { double pos, length; Eina_Bool seekable; ELM_PLAYER_DATA_GET(data, sd); if (!sd) return; seekable = elm_video_is_seekable_get(sd->video); length = elm_video_play_length_get(sd->video); pos = elm_video_play_position_get(sd->video); elm_object_disabled_set(sd->slider, (!seekable) | elm_widget_disabled_get(data)); elm_slider_min_max_set(sd->slider, 0, length); if ((!EINA_DBL_EQ(elm_slider_value_get(sd->slider), pos)) && (!sd->dragging)) elm_slider_value_set(sd->slider, pos); } static void _update_frame(void *data, const Efl_Event *event) { ELM_PLAYER_DATA_GET(data, sd); if (!sd) return; _update_slider(data, event); } static void _update_position(void *data, const Efl_Event *event EINA_UNUSED) { double pos; ELM_PLAYER_DATA_GET(data, sd); pos = elm_slider_value_get(sd->slider); if (!EINA_FLT_EQ(pos, elm_video_play_position_get(sd->video))) elm_video_play_position_set(sd->video, pos); } static void _drag_start(void *data, const Efl_Event *event EINA_UNUSED) { ELM_PLAYER_DATA_GET(data, sd); sd->dragging = EINA_TRUE; } static void _drag_stop(void *data, const Efl_Event *event EINA_UNUSED) { ELM_PLAYER_DATA_GET(data, sd); sd->dragging = EINA_FALSE; } static void _update_volume(void *data, const Efl_Event *event EINA_UNUSED) { double vol; ELM_PLAYER_DATA_GET(data, sd); vol = elm_slider_value_get(sd->vslider) / 100.0; if (!EINA_DBL_EQ(vol, elm_video_audio_level_get(sd->video))) elm_video_audio_level_set(sd->video, vol); } static void _forward(void *data, const Efl_Event *event EINA_UNUSED) { double pos, length; ELM_PLAYER_DATA_GET(data, sd); length = elm_video_play_length_get(sd->video); pos = elm_video_play_position_get(sd->video); pos += 30.0; if (pos > length) pos = length; elm_video_play_position_set(sd->video, pos); elm_layout_signal_emit(data, "elm,button,forward", "elm"); efl_event_callback_legacy_call(data, ELM_PLAYER_EVENT_FORWARD_CLICKED, NULL); } static void _info(void *data, const Efl_Event *event EINA_UNUSED) { elm_layout_signal_emit(data, "elm,button,info", "elm"); efl_event_callback_legacy_call(data, ELM_PLAYER_EVENT_INFO_CLICKED, NULL); } static void _next(void *data, const Efl_Event *event EINA_UNUSED) { elm_layout_signal_emit(data, "elm,button,next", "elm"); efl_event_callback_legacy_call(data, ELM_PLAYER_EVENT_NEXT_CLICKED, NULL); } static void _pause(void *data, const Efl_Event *event EINA_UNUSED) { ELM_PLAYER_DATA_GET(data, sd); elm_layout_signal_emit(data, "elm,player,pause", "elm"); elm_video_pause(sd->video); efl_event_callback_legacy_call(data, ELM_PLAYER_EVENT_PAUSE_CLICKED, NULL); } static void _play(void *data, const Efl_Event *event EINA_UNUSED) { ELM_PLAYER_DATA_GET(data, sd); elm_layout_signal_emit(data, "elm,player,play", "elm"); elm_video_play(sd->video); efl_event_callback_legacy_call(data, ELM_PLAYER_EVENT_PLAY_CLICKED, NULL); } static void _prev(void *data, const Efl_Event *event EINA_UNUSED) { efl_event_callback_legacy_call(data, ELM_PLAYER_EVENT_PREV_CLICKED, NULL); elm_layout_signal_emit(data, "elm,button,prev", "elm"); } static void _rewind(void *data, const Efl_Event *event EINA_UNUSED) { double pos; ELM_PLAYER_DATA_GET(data, sd); pos = elm_video_play_position_get(sd->video); pos -= 30.0; if (pos < 0.0) pos = 0.0; elm_video_play_position_set(sd->video, pos); elm_layout_signal_emit(data, "elm,button,rewind", "elm"); efl_event_callback_legacy_call(data, ELM_PLAYER_EVENT_REWIND_CLICKED, NULL); } static void _stop(void *data, const Efl_Event *event EINA_UNUSED) { elm_layout_signal_emit(data, "elm,button,stop", "elm"); efl_event_callback_legacy_call(data, ELM_PLAYER_EVENT_QUALITY_CLICKED, NULL); } static void _eject(void *data, const Efl_Event *event EINA_UNUSED) { ELM_PLAYER_DATA_GET(data, sd); elm_layout_signal_emit(data, "elm,button,eject", "elm"); emotion_object_eject(elm_video_emotion_get(sd->video)); efl_event_callback_legacy_call(data, ELM_PLAYER_EVENT_EJECT_CLICKED, NULL); } static void _mute_toggle(Evas_Object *obj) { ELM_PLAYER_DATA_GET(obj, sd); if (!elm_video_audio_mute_get(sd->video)) { elm_video_audio_mute_set(sd->video, EINA_TRUE); elm_layout_signal_emit(obj, "elm,player,mute", "elm"); } else { elm_video_audio_mute_set(sd->video, EINA_FALSE); elm_layout_signal_emit(obj, "elm,player,unmute", "elm"); } } static void _volume(void *data, const Efl_Event *event EINA_UNUSED) { elm_layout_signal_emit(data, "elm,button,volume", "elm"); _mute_toggle(data); efl_event_callback_legacy_call(data, ELM_PLAYER_EVENT_VOLUME_CLICKED, NULL); } static void _mute(void *data, const Efl_Event *event EINA_UNUSED) { elm_layout_signal_emit(data, "elm,button,mute", "elm"); _mute_toggle(data); efl_event_callback_legacy_call(data, ELM_PLAYER_EVENT_MUTE_CLICKED, NULL); } static void _play_started(void *data, const Efl_Event *event EINA_UNUSED) { elm_layout_signal_emit(data, "elm,player,play", "elm"); } static void _play_finished(void *data, const Efl_Event *event EINA_UNUSED) { elm_layout_signal_emit(data, "elm,player,pause", "elm"); } static void _on_video_del(Elm_Player_Data *sd) { elm_object_disabled_set(sd->forward, EINA_TRUE); elm_object_disabled_set(sd->info, EINA_TRUE); elm_object_disabled_set(sd->next, EINA_TRUE); elm_object_disabled_set(sd->pause, EINA_TRUE); elm_object_disabled_set(sd->play, EINA_TRUE); elm_object_disabled_set(sd->prev, EINA_TRUE); elm_object_disabled_set(sd->rewind, EINA_TRUE); elm_object_disabled_set(sd->next, EINA_TRUE); elm_object_disabled_set(sd->stop, EINA_TRUE); elm_object_disabled_set(sd->volume, EINA_TRUE); elm_object_disabled_set(sd->mute, EINA_TRUE); elm_object_disabled_set(sd->slider, EINA_TRUE); elm_object_disabled_set(sd->vslider, EINA_TRUE); sd->video = NULL; sd->emotion = NULL; } static void _video_del(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) { _on_video_del(data); } static Evas_Object * _player_button_add(Evas_Object *obj, const char *name, Efl_Event_Cb func) { Evas_Object *ic; Evas_Object *bt; char buf[256]; ic = elm_icon_add(obj); snprintf(buf, sizeof(buf), "media_player/%s/%s", name, elm_widget_style_get(obj)); elm_icon_standard_set(ic, buf); bt = elm_button_add(obj); if (ic) evas_object_data_set(bt, "icon", ic); - elm_widget_mirrored_automatic_set(bt, EINA_FALSE); + efl_ui_mirrored_automatic_set(bt, EINA_FALSE); elm_object_content_set(bt, ic); evas_object_show(ic); snprintf(buf, sizeof(buf), "media_player/%s/%s", name, elm_widget_style_get(obj)); elm_object_style_set(bt, buf); efl_event_callback_add (bt, EFL_UI_EVENT_CLICKED, func, obj); snprintf(buf, sizeof(buf), "elm.swallow.media_player.%s", name); if (!elm_layout_content_set(obj, buf, bt)) { elm_widget_sub_object_add(obj, bt); evas_object_hide(bt); } evas_object_show(bt); return bt; } static char * _double_to_time(double value) { char buf[256]; int ph, pm, ps, pf; ph = value / 3600; pm = value / 60 - (ph * 60); ps = value - (pm * 60) - (ph * 3600); pf = value * 100 - (ps * 100) - (pm * 60 * 100) - (ph * 60 * 60 * 100); if (ph) snprintf(buf, sizeof(buf), "%i:%02i:%02i.%02i", ph, pm, ps, pf); else if (pm) snprintf(buf, sizeof(buf), "%02i:%02i.%02i", pm, ps, pf); else snprintf(buf, sizeof(buf), "%02i.%02i", ps, pf); return (char *)eina_stringshare_add(buf); } static void _str_free(char *data) { eina_stringshare_del(data); } /* a video object is never parented by a player one, just tracked. * treating this special case here and delegating other objects to own * layout */ static Eina_Bool _elm_player_content_set(Eo *obj, Elm_Player_Data *sd, const char *part, Evas_Object *content) { Eina_Bool int_ret = EINA_FALSE; double pos, length; Eina_Bool seekable; if (part && strcmp(part, "video")) { int_ret = efl_content_set(efl_part(efl_super(obj, MY_CLASS), part), content); return int_ret; } if ((!part) || (!strcmp(part, "video"))) part = "elm.swallow.content"; int_ret = efl_content_set(efl_part(efl_super(obj, MY_CLASS), part), content); if (!_elm_video_check(content)) return EINA_FALSE; if (sd->video == content) goto end; evas_object_del(sd->video); sd->video = content; if (!content) goto end; elm_object_disabled_set(sd->forward, EINA_FALSE); elm_object_disabled_set(sd->info, EINA_FALSE); elm_object_disabled_set(sd->next, EINA_FALSE); elm_object_disabled_set(sd->pause, EINA_FALSE); elm_object_disabled_set(sd->play, EINA_FALSE); elm_object_disabled_set(sd->prev, EINA_FALSE); elm_object_disabled_set(sd->rewind, EINA_FALSE); elm_object_disabled_set(sd->next, EINA_FALSE); elm_object_disabled_set(sd->stop, EINA_FALSE); elm_object_disabled_set(sd->volume, EINA_FALSE); elm_object_disabled_set(sd->mute, EINA_FALSE); elm_object_disabled_set(sd->slider, EINA_FALSE); elm_object_disabled_set(sd->vslider, EINA_FALSE); sd->emotion = elm_video_emotion_get(sd->video); emotion_object_priority_set(sd->emotion, EINA_TRUE); evas_object_event_callback_add (sd->video, EVAS_CALLBACK_DEL, _video_del, sd); seekable = elm_video_is_seekable_get(sd->video); length = elm_video_play_length_get(sd->video); pos = elm_video_play_position_get(sd->video); elm_object_disabled_set(sd->slider, !seekable); elm_slider_min_max_set(sd->slider, 0, length); elm_slider_value_set(sd->slider, pos); elm_slider_value_set(sd->vslider, elm_video_audio_level_get(sd->video) * 100.0); // XXX: get mute if (elm_video_is_playing_get(sd->video)) elm_layout_signal_emit(obj, "elm,player,play", "elm"); else elm_layout_signal_emit(obj, "elm,player,pause", "elm"); efl_event_callback_array_add(sd->emotion, _emotion_cb(), obj); /* FIXME: track info from video */ end: return EINA_TRUE; } EOLIAN static void _elm_player_efl_canvas_group_group_add(Eo *obj, Elm_Player_Data *priv) { char buf[256]; efl_canvas_group_add(efl_super(obj, MY_CLASS)); elm_widget_sub_object_parent_add(obj); if (!elm_layout_theme_set(obj, "player", "base", elm_widget_style_get(obj))) CRI("Failed to set layout!"); priv->forward = _player_button_add(obj, "forward", _forward); priv->info = _player_button_add(obj, "info", _info); priv->next = _player_button_add(obj, "next", _next); priv->pause = _player_button_add(obj, "pause", _pause); priv->play = _player_button_add(obj, "play", _play); priv->prev = _player_button_add(obj, "prev", _prev); priv->rewind = _player_button_add(obj, "rewind", _rewind); priv->stop = _player_button_add(obj, "stop", _stop); priv->eject = _player_button_add(obj, "eject", _eject); priv->volume = _player_button_add(obj, "volume", _volume); priv->mute = _player_button_add(obj, "mute", _mute); priv->slider = elm_slider_add(obj); snprintf(buf, sizeof(buf), "media_player/position/%s", elm_widget_style_get(obj)); elm_object_style_set(priv->slider, buf); elm_slider_indicator_show_set(priv->slider, EINA_TRUE); elm_slider_indicator_format_function_set (priv->slider, _double_to_time, _str_free); elm_slider_units_format_function_set (priv->slider, _double_to_time, _str_free); elm_slider_min_max_set(priv->slider, 0, 0); elm_slider_value_set(priv->slider, 0); elm_object_disabled_set(priv->slider, EINA_TRUE); evas_object_size_hint_align_set(priv->slider, EVAS_HINT_FILL, 0.5); evas_object_size_hint_weight_set (priv->slider, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); elm_layout_content_set(obj, "elm.swallow.media_player.positionslider", priv->slider); efl_event_callback_array_add(priv->slider, _slider_cb(), obj); priv->vslider = elm_slider_add(obj); elm_slider_indicator_show_set(priv->vslider, EINA_FALSE); snprintf(buf, sizeof(buf), "media_player/volume/%s", elm_widget_style_get(obj)); elm_object_style_set(priv->vslider, buf); elm_slider_min_max_set(priv->vslider, 0, 100); elm_slider_value_set(priv->vslider, 100); elm_slider_horizontal_set(priv->vslider, EINA_FALSE); elm_slider_inverted_set(priv->vslider, EINA_TRUE); evas_object_size_hint_align_set(priv->vslider, 0.5, EVAS_HINT_FILL); evas_object_size_hint_weight_set (priv->vslider, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); elm_layout_content_set(obj, "elm.swallow.media_player.volumeslider", priv->vslider); efl_event_callback_add (priv->vslider, EFL_UI_SLIDER_EVENT_CHANGED, _update_volume, obj); elm_layout_sizing_eval(obj); elm_widget_can_focus_set(obj, EINA_TRUE); } EOLIAN static void _elm_player_efl_canvas_group_group_del(Eo *obj, Elm_Player_Data *sd EINA_UNUSED) { efl_canvas_group_del(efl_super(obj, MY_CLASS)); } EAPI Evas_Object * elm_player_add(Evas_Object *parent) { EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL); return efl_add(MY_CLASS, parent); } EOLIAN static Eo * _elm_player_efl_object_constructor(Eo *obj, Elm_Player_Data *sd EINA_UNUSED) { obj = efl_constructor(efl_super(obj, MY_CLASS)); efl_canvas_object_type_set(obj, MY_CLASS_NAME_LEGACY); evas_object_smart_callbacks_descriptions_set(obj, _smart_callbacks); elm_interface_atspi_accessible_role_set(obj, ELM_ATSPI_ROLE_ANIMATION); return obj; } EOLIAN static void _elm_player_class_constructor(Efl_Class *klass) { evas_smart_legacy_type_register(MY_CLASS_NAME_LEGACY, klass); } EOLIAN const Elm_Atspi_Action * _elm_player_elm_interface_atspi_widget_action_elm_actions_get(Eo *obj EINA_UNUSED, Elm_Player_Data *pd EINA_UNUSED) { static Elm_Atspi_Action atspi_actions[] = { { "move,left", "move", "left", _key_action_move}, { "move,right", "move", "right", _key_action_move}, { "play", "play", NULL, _key_action_play}, { NULL, NULL, NULL, NULL} }; return &atspi_actions[0]; } /* Efl.Part implementation */ ELM_PART_OVERRIDE(elm_player, ELM_PLAYER, ELM_LAYOUT, Elm_Player_Data, Elm_Part_Data) ELM_PART_OVERRIDE_CONTENT_SET(elm_player, ELM_PLAYER, ELM_LAYOUT, Elm_Player_Data, Elm_Part_Data) #include "elm_player_internal_part.eo.c" /* End of Efl.Part */ /* Internal EO APIs and hidden overrides */ #define ELM_PLAYER_EXTRA_OPS \ EFL_CANVAS_GROUP_ADD_DEL_OPS(elm_player) #include "elm_player.eo.c" diff --git a/src/lib/elementary/elc_popup.c b/src/lib/elementary/elc_popup.c index 0691eaba08..a14773c93e 100644 --- a/src/lib/elementary/elc_popup.c +++ b/src/lib/elementary/elc_popup.c @@ -1,1938 +1,1938 @@ #ifdef HAVE_CONFIG_H # include "elementary_config.h" #endif #define ELM_INTERFACE_ATSPI_ACCESSIBLE_PROTECTED #define ELM_INTERFACE_ATSPI_WIDGET_ACTION_PROTECTED #define ELM_WIDGET_PROTECTED #define ELM_WIDGET_ITEM_PROTECTED #include #include "elm_priv.h" #include "elm_widget_popup.h" #include "elm_popup_item.eo.h" #include "elm_popup_internal_part.eo.h" #include "elm_part_helper.h" #define MY_CLASS ELM_POPUP_CLASS #define MY_CLASS_NAME "Elm_Popup" #define MY_CLASS_NAME_LEGACY "elm_popup" static void _button_remove(Evas_Object *, int, Eina_Bool); static const char ACCESS_TITLE_PART[] = "access.title"; static const char ACCESS_BODY_PART[] = "access.body"; static const char CONTENT_PART[] = "elm.swallow.content"; static const char SIG_BLOCK_CLICKED[] = "block,clicked"; static const char SIG_TIMEOUT[] = "timeout"; static const char SIG_ITEM_FOCUSED[] = "item,focused"; static const char SIG_ITEM_UNFOCUSED[] = "item,unfocused"; static const Evas_Smart_Cb_Description _smart_callbacks[] = { {SIG_BLOCK_CLICKED, ""}, {SIG_TIMEOUT, ""}, {SIG_ITEM_FOCUSED, ""}, {SIG_ITEM_UNFOCUSED, ""}, {SIG_WIDGET_LANG_CHANGED, ""}, /**< handled by elm_widget */ {SIG_WIDGET_ACCESS_CHANGED, ""}, /**< handled by elm_widget */ {SIG_LAYOUT_FOCUSED, ""}, /**< handled by elm_layout */ {SIG_LAYOUT_UNFOCUSED, ""}, /**< handled by elm_layout */ {NULL, NULL} }; static Eina_Bool _key_action_move(Evas_Object *obj, const char *params); static Eina_Bool _key_action_escape(Evas_Object *obj, const char *params); static void _parent_geom_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED); static void _block_clicked_cb(void *data, const Efl_Event *event); static void _timeout_cb(void *data, const Efl_Event *event); static void _hide_effect_finished_cb(void *data, const Efl_Event *event); static const Elm_Action key_actions[] = { {"move", _key_action_move}, {"escape", _key_action_escape}, {NULL, NULL} }; EFL_CALLBACKS_ARRAY_DEFINE(_notify_cb, { ELM_NOTIFY_EVENT_BLOCK_CLICKED, _block_clicked_cb }, { ELM_NOTIFY_EVENT_TIMEOUT, _timeout_cb }, { ELM_NOTIFY_EVENT_DISMISSED, _hide_effect_finished_cb } ); static void _on_content_del(void *data, Evas *e, Evas_Object *obj, void *event_info); EOLIAN static Eina_Bool _elm_popup_elm_widget_translate(Eo *obj EINA_UNUSED, Elm_Popup_Data *sd) { Elm_Popup_Item_Data *it; Eina_List *l; EINA_LIST_FOREACH(sd->items, l, it) elm_wdg_item_translate(EO_OBJ(it)); elm_obj_widget_translate(efl_super(obj, MY_CLASS)); elm_obj_widget_translate(sd->main_layout); return EINA_TRUE; } static void _visuals_set(Evas_Object *obj) { ELM_POPUP_DATA_GET(obj, sd); if (!sd->title_text && !sd->title_icon) elm_layout_signal_emit(sd->main_layout, "elm,state,title_area,hidden", "elm"); else elm_layout_signal_emit(sd->main_layout, "elm,state,title_area,visible", "elm"); if (sd->action_area) { elm_layout_signal_emit(sd->main_layout, "elm,state,action_area,visible", "elm"); evas_object_show(sd->action_area); } else elm_layout_signal_emit(sd->main_layout, "elm,state,action_area,hidden", "elm"); edje_object_message_signal_process(elm_layout_edje_get(sd->main_layout)); } static void _block_clicked_cb(void *data, const Efl_Event *event EINA_UNUSED) { efl_event_callback_legacy_call(data, ELM_POPUP_EVENT_BLOCK_CLICKED, NULL); } static void _timeout_cb(void *data, const Efl_Event *event EINA_UNUSED) { evas_object_hide(data); efl_event_callback_legacy_call(data, ELM_POPUP_EVENT_TIMEOUT, NULL); } static void _hide_effect_finished_cb(void *data, const Efl_Event *event EINA_UNUSED) { efl_gfx_visible_set(data, EINA_FALSE); efl_event_callback_legacy_call(data, ELM_POPUP_EVENT_DISMISSED, NULL); } static Evas_Object * _access_object_get(const Evas_Object *obj, const char* part) { Evas_Object *po, *ao; ELM_POPUP_DATA_GET(obj, sd); po = (Evas_Object *)edje_object_part_object_get (elm_layout_edje_get(sd->main_layout), part); ao = evas_object_data_get(po, "_part_access_obj"); return ao; } static void _on_show(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED) { elm_object_focus_set(obj, EINA_TRUE); } static void _scroller_size_calc(Evas_Object *obj) { Evas_Coord h; Evas_Coord h_title = 0; Evas_Coord h_action_area = 0; const char *action_area_height; ELM_POPUP_DATA_GET(obj, sd); if (!sd->scroll && !sd->items) return; sd->scr_size_recalc = EINA_FALSE; sd->max_sc_h = -1; evas_object_geometry_get(sd->notify, NULL, NULL, NULL, &h); if (sd->title_text || sd->title_icon) edje_object_part_geometry_get(elm_layout_edje_get(sd->main_layout), "elm.bg.title", NULL, NULL, NULL, &h_title); if (sd->action_area) { action_area_height = edje_object_data_get( elm_layout_edje_get(sd->action_area), "action_area_height"); if (action_area_height) h_action_area = (int)(atoi(action_area_height) * elm_config_scale_get() * elm_object_scale_get(obj)) / edje_object_base_scale_get(elm_layout_edje_get(sd->action_area)); } sd->max_sc_h = h - (h_title + h_action_area); } static void _size_hints_changed_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) { elm_layout_sizing_eval(data); } static void _notify_resize_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) { Evas_Object *popup = data; ELM_POPUP_CHECK(popup); elm_layout_sizing_eval(popup); } static void _list_del(Elm_Popup_Data *sd) { if (!sd->scr) return; evas_object_event_callback_del (sd->scr, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _size_hints_changed_cb); ELM_SAFE_FREE(sd->tbl, evas_object_del); sd->scr = NULL; sd->box = NULL; sd->spacer = NULL; } static void _items_remove(Elm_Popup_Data *sd) { Elm_Popup_Item_Data *it; if (!sd->items) return; EINA_LIST_FREE(sd->items, it) elm_wdg_item_del(EO_OBJ(it)); sd->items = NULL; } EOLIAN static void _elm_popup_efl_canvas_group_group_del(Eo *obj, Elm_Popup_Data *sd) { unsigned int i; evas_object_event_callback_del_full(sd->parent, EVAS_CALLBACK_RESIZE, _parent_geom_cb, obj); evas_object_event_callback_del_full(sd->parent, EVAS_CALLBACK_MOVE, _parent_geom_cb, obj); evas_object_event_callback_del_full(sd->notify, EVAS_CALLBACK_RESIZE, _notify_resize_cb, obj); efl_event_callback_array_del(sd->notify, _notify_cb(), obj); evas_object_event_callback_del (sd->content, EVAS_CALLBACK_DEL, _on_content_del); evas_object_event_callback_del(obj, EVAS_CALLBACK_SHOW, _on_show); sd->last_button_number = 0; for (i = 0; i < ELM_POPUP_ACTION_BUTTON_MAX; i++) { if (sd->buttons[i]) { evas_object_del(sd->buttons[i]->btn); ELM_SAFE_FREE(sd->buttons[i], free); } } if (sd->items) { _items_remove(sd); _list_del(sd); } // XXX? delete other objects? just to be sure. ELM_SAFE_FREE(sd->main_layout, evas_object_del); ELM_SAFE_FREE(sd->notify, evas_object_del); ELM_SAFE_FREE(sd->title_icon, evas_object_del); ELM_SAFE_FREE(sd->content_area, evas_object_del); ELM_SAFE_FREE(sd->text_content_obj, evas_object_del); ELM_SAFE_FREE(sd->action_area, evas_object_del); ELM_SAFE_FREE(sd->box, evas_object_del); ELM_SAFE_FREE(sd->tbl, evas_object_del); ELM_SAFE_FREE(sd->spacer, evas_object_del); ELM_SAFE_FREE(sd->scr, evas_object_del); ELM_SAFE_FREE(sd->content, evas_object_del); ELM_SAFE_FREE(sd->title_text, eina_stringshare_del); efl_canvas_group_del(efl_super(obj, MY_CLASS)); } static void _mirrored_set(Evas_Object *obj, Eina_Bool rtl) { ELM_POPUP_DATA_GET(obj, sd); elm_object_mirrored_set(sd->notify, rtl); elm_object_mirrored_set(sd->main_layout, rtl); if (sd->scr) elm_object_mirrored_set(sd->scr, rtl); if (sd->action_area) elm_object_mirrored_set(sd->action_area, rtl); if (sd->items) { Elm_Popup_Item_Data *it; Eina_List *l; EINA_LIST_FOREACH(sd->items, l, it) elm_object_mirrored_set(VIEW(it), rtl); } } static void _access_obj_process(Eo *obj, Eina_Bool is_access) { Evas_Object *ao; ELM_POPUP_DATA_GET(obj, sd); if (is_access) { if (sd->title_text) { ao = _elm_access_edje_object_part_object_register (obj, elm_layout_edje_get(sd->main_layout), ACCESS_TITLE_PART); _elm_access_text_set(_elm_access_info_get(ao), ELM_ACCESS_TYPE, E_("Popup Title")); _elm_access_text_set(_elm_access_info_get(ao), ELM_ACCESS_INFO, sd->title_text); } if (sd->text_content_obj) { ao = _elm_access_edje_object_part_object_register (obj, elm_layout_edje_get(sd->main_layout), ACCESS_BODY_PART); _elm_access_text_set(_elm_access_info_get(ao), ELM_ACCESS_TYPE, E_("Popup Body Text")); _elm_access_text_set(_elm_access_info_get(ao), ELM_ACCESS_INFO, elm_object_text_get(sd->text_content_obj)); } } else { if (sd->title_text) { _elm_access_edje_object_part_object_unregister (obj, elm_layout_edje_get(sd->main_layout), ACCESS_TITLE_PART); } if (sd->text_content_obj) { _elm_access_edje_object_part_object_unregister (obj, elm_layout_edje_get(sd->main_layout), ACCESS_BODY_PART); } } } static void _populate_theme_scroll(Elm_Popup_Data *sd) { if (sd->content_area) { const char *content_area_width = edje_object_data_get(elm_layout_edje_get(sd->content_area), "scroller_enable"); if ((content_area_width) && (!strcmp(content_area_width, "on"))) { sd->theme_scroll = EINA_TRUE; return; } } sd->theme_scroll = EINA_FALSE; } EOLIAN static Elm_Theme_Apply _elm_popup_elm_widget_theme_apply(Eo *obj, Elm_Popup_Data *sd) { Elm_Popup_Item_Data *it; Eina_List *elist; char buf[1024], style[1024]; _mirrored_set(obj, efl_ui_mirrored_get(obj)); snprintf(style, sizeof(style), "popup/%s", elm_widget_style_get(obj)); elm_widget_style_set(sd->notify, style); if (!elm_layout_theme_set(sd->main_layout, "popup", "base", elm_widget_style_get(obj))) CRI("Failed to set layout!"); if (sd->action_area) { snprintf(buf, sizeof(buf), "buttons%i", sd->last_button_number); if (!elm_layout_theme_set(sd->action_area, "popup", buf, style)) CRI("Failed to set layout!"); } if (!elm_layout_theme_set(sd->content_area, "popup", "content", style)) CRI("Failed to set layout!"); if (sd->text_content_obj) elm_object_style_set(sd->text_content_obj, style); else if (sd->items) { EINA_LIST_FOREACH(sd->items, elist, it) { if (!elm_layout_theme_set(VIEW(it), "popup", "item", style)) CRI("Failed to set layout!"); else { if (it->label) { elm_layout_text_set(VIEW(it), "elm.text", it->label); elm_layout_signal_emit(VIEW(it), "elm,state,item,text,visible", "elm"); } if (it->icon) elm_layout_signal_emit(VIEW(it), "elm,state,item,icon,visible", "elm"); if (it->disabled) elm_layout_signal_emit(VIEW(it), "elm,state,item,disabled", "elm"); evas_object_show(VIEW(it)); edje_object_message_signal_process( elm_layout_edje_get(VIEW(it))); } } } if (sd->title_text) { elm_layout_text_set(sd->main_layout, "elm.text.title", sd->title_text); elm_layout_signal_emit(sd->main_layout, "elm,state,title,text,visible", "elm"); } if (sd->title_icon) elm_layout_signal_emit(sd->main_layout, "elm,state,title,icon,visible", "elm"); _populate_theme_scroll(sd); if (!sd->scroll && sd->theme_scroll) elm_layout_signal_emit(sd->content_area, "elm,scroll,disable", "elm"); else if (sd->scroll && sd->theme_scroll) elm_layout_signal_emit(sd->content_area, "elm,scroll,enable", "elm"); _visuals_set(obj); elm_layout_sizing_eval(obj); /* access */ if (_elm_config->access_mode) _access_obj_process(obj, EINA_TRUE); return ELM_THEME_APPLY_SUCCESS; } static void _item_sizing_eval(Elm_Popup_Item_Data *it) { Evas_Coord min_w = -1, min_h = -1, max_w = -1, max_h = -1; Evas_Object *edje = elm_layout_edje_get(VIEW(it)); edje_object_size_min_restricted_calc (edje, &min_w, &min_h, min_w, min_h); evas_object_size_hint_min_set(edje, min_w, min_h); evas_object_size_hint_max_set(edje, max_w, max_h); } EOLIAN static void _elm_popup_elm_layout_sizing_eval(Eo *obj, Elm_Popup_Data *sd) { Eina_List *elist; Elm_Popup_Item_Data *it; Evas_Coord h_box = 0, minh_box = 0; Evas_Coord minw = -1, minh = -1; _scroller_size_calc(obj); if (sd->items) { EINA_LIST_FOREACH(sd->items, elist, it) { _item_sizing_eval(it); efl_gfx_size_hint_combined_min_get(elm_layout_edje_get(VIEW(it)), NULL, &minh_box); if (minh_box != -1) h_box += minh_box; } evas_object_size_hint_min_set(sd->spacer, 0, MIN(h_box, sd->max_sc_h)); evas_object_size_hint_max_set(sd->spacer, -1, sd->max_sc_h); efl_gfx_size_hint_combined_min_get(sd->scr, &minw, &minh); evas_object_size_hint_max_get(sd->scr, &minw, &minh); } else if (sd->scroll && (sd->content || sd->text_content_obj)) { double horizontal, vertical; Evas_Coord w, h; edje_object_message_signal_process(elm_layout_edje_get(sd->content_area)); elm_popup_align_get(obj, &horizontal, &vertical); evas_object_geometry_get(sd->parent, NULL, NULL, &w, &h); if (EINA_DBL_EQ(horizontal, ELM_NOTIFY_ALIGN_FILL)) minw = w; if (EINA_DBL_EQ(vertical, ELM_NOTIFY_ALIGN_FILL)) minh = h; edje_object_size_min_restricted_calc(elm_layout_edje_get(sd->content_area), &minw, &minh, minw, minh); evas_object_size_hint_min_set(sd->content_area, minw, minh); if (minh > sd->max_sc_h) evas_object_size_hint_min_set(sd->spacer, minw, sd->max_sc_h); else evas_object_size_hint_min_set(sd->spacer, minw, minh); return; } edje_object_size_min_calc(elm_layout_edje_get(sd->main_layout), &minw, &minh); evas_object_size_hint_min_set(obj, minw, minh); evas_object_size_hint_max_set(obj, -1, -1); } EOLIAN static void _elm_popup_elm_layout_signal_emit(Eo *obj EINA_UNUSED, Elm_Popup_Data *sd, const char *emission, const char *source) { elm_layout_signal_emit(sd->main_layout, emission, source); } EOLIAN static Eina_Bool _elm_popup_elm_widget_sub_object_del(Eo *obj, Elm_Popup_Data *sd, Evas_Object *sobj) { Elm_Popup_Item_Data *it; Eina_Bool int_ret = EINA_FALSE; int_ret = elm_obj_widget_sub_object_del(efl_super(obj, MY_CLASS), sobj); if (!int_ret) return EINA_FALSE; if (sobj == sd->title_icon) { elm_layout_signal_emit(sd->main_layout, "elm,state,title,icon,hidden", "elm"); } else if ((it = evas_object_data_get(sobj, "_popup_icon_parent_item")) != NULL) { if (sobj == it->icon) { efl_content_unset(efl_part(VIEW(it), CONTENT_PART)); elm_layout_signal_emit(VIEW(it), "elm,state,item,icon,hidden", "elm"); it->icon = NULL; } } return EINA_TRUE; } static void _on_content_del(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) { ELM_POPUP_DATA_GET(data, sd); sd->content = NULL; elm_layout_sizing_eval(data); } static void _on_text_content_del(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) { ELM_POPUP_DATA_GET(data, sd); sd->text_content_obj = NULL; elm_layout_sizing_eval(data); } static void _on_table_del(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) { ELM_POPUP_DATA_GET(data, sd); sd->tbl = NULL; sd->spacer = NULL; sd->scr = NULL; sd->box = NULL; elm_layout_sizing_eval(data); } static void _on_button_del(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED) { int i; ELM_POPUP_DATA_GET(data, sd); for (i = 0; i < ELM_POPUP_ACTION_BUTTON_MAX; i++) { if (sd->buttons[i] && obj == sd->buttons[i]->btn && sd->buttons[i]->delete_me == EINA_TRUE) { _button_remove(data, i, EINA_FALSE); break; } } } static void _button_remove(Evas_Object *obj, int pos, Eina_Bool delete) { int i = 0; char buf[128]; ELM_POPUP_DATA_GET(obj, sd); if (!sd->last_button_number) return; if (!sd->buttons[pos]) return; if (delete) { evas_object_del(sd->buttons[pos]->btn); } else { evas_object_event_callback_del (sd->buttons[pos]->btn, EVAS_CALLBACK_DEL, _on_button_del); snprintf(buf, sizeof(buf), "elm.swallow.content.button%i", pos + 1); elm_object_part_content_unset(sd->action_area, buf); } ELM_SAFE_FREE(sd->buttons[pos], free); sd->last_button_number = 0; for (i = ELM_POPUP_ACTION_BUTTON_MAX - 1; i >= 0; i--) { if (sd->buttons[i]) { sd->last_button_number = i + 1; break; } } if (!sd->last_button_number) { _visuals_set(obj); ELM_SAFE_FREE(sd->action_area, evas_object_del); } else { char style[1024]; snprintf(style, sizeof(style), "popup/%s", elm_widget_style_get(obj)); snprintf(buf, sizeof(buf), "buttons%i", sd->last_button_number); if (!elm_layout_theme_set(sd->action_area, "popup", buf, style)) CRI("Failed to set layout!"); } } static void _layout_change_cb(void *data EINA_UNUSED, Evas_Object *obj, const char *emission EINA_UNUSED, const char *source EINA_UNUSED) { elm_layout_sizing_eval(obj); } static void _create_scroller(Evas_Object *obj) { char style[1024]; ELM_POPUP_DATA_GET(obj, sd); //table sd->tbl = elm_table_add(sd->main_layout); evas_object_event_callback_add(sd->tbl, EVAS_CALLBACK_DEL, _on_table_del, obj); if (!sd->scroll) { if (sd->content || sd->text_content_obj) efl_content_unset(efl_part(sd->content_area, CONTENT_PART)); efl_content_set(efl_part(sd->content_area, CONTENT_PART), sd->tbl); efl_content_set(efl_part(sd->main_layout, CONTENT_PART), sd->content_area); } //spacer sd->spacer = evas_object_rectangle_add(evas_object_evas_get(obj)); evas_object_color_set(sd->spacer, 0, 0, 0, 0); elm_table_pack(sd->tbl, sd->spacer, 0, 0, 1, 1); //Scroller sd->scr = elm_scroller_add(sd->tbl); if (!sd->scroll) { snprintf(style, sizeof(style), "popup/%s", elm_widget_style_get(obj)); elm_object_style_set(sd->scr, style); } else elm_object_style_set(sd->scr, "popup/no_inset_shadow"); evas_object_size_hint_weight_set(sd->scr, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); evas_object_size_hint_align_set(sd->scr, EVAS_HINT_FILL, EVAS_HINT_FILL); elm_scroller_policy_set(sd->scr, ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_AUTO); elm_scroller_content_min_limit(sd->scr, EINA_TRUE, EINA_FALSE); elm_scroller_bounce_set(sd->scr, EINA_FALSE, EINA_TRUE); evas_object_event_callback_add(sd->scr, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _size_hints_changed_cb, obj); - elm_widget_mirrored_automatic_set(sd->scr, EINA_FALSE); + efl_ui_mirrored_automatic_set(sd->scr, EINA_FALSE); elm_object_mirrored_set(sd->scr, elm_object_mirrored_get(obj)); elm_table_pack(sd->tbl, sd->scr, 0, 0, 1, 1); evas_object_show(sd->scr); } static void _list_add(Evas_Object *obj) { ELM_POPUP_DATA_GET(obj, sd); if (!sd->scr) _create_scroller(obj); //Box sd->box = elm_box_add(sd->scr); evas_object_size_hint_weight_set(sd->box, EVAS_HINT_EXPAND, 0.0); evas_object_size_hint_align_set(sd->box, EVAS_HINT_FILL, 0.0); elm_object_content_set(sd->scr, sd->box); evas_object_show(sd->box); } static void _item_select_cb(void *data, Evas_Object *obj EINA_UNUSED, const char *emission EINA_UNUSED, const char *source EINA_UNUSED) { Elm_Popup_Item_Data *it = data; if (!it || it->disabled) return; if (it->func) it->func((void *)WIDGET_ITEM_DATA_GET(EO_OBJ(it)), WIDGET(it), EO_OBJ(it)); } static void _item_text_set(Elm_Popup_Item_Data *it, const char *label) { if (!eina_stringshare_replace(&it->label, label)) return; elm_layout_text_set(VIEW(it), "elm.text", label); if (it->label) elm_layout_signal_emit(VIEW(it), "elm,state,item,text,visible", "elm"); else elm_layout_signal_emit(VIEW(it), "elm,state,item,text,hidden", "elm"); edje_object_message_signal_process(elm_layout_edje_get(VIEW(it))); } EOLIAN static void _elm_popup_item_elm_widget_item_part_text_set(Eo *eo_it EINA_UNUSED, Elm_Popup_Item_Data *it, const char *part, const char *label) { ELM_POPUP_ITEM_CHECK_OR_RETURN(it); if ((!part) || (!strcmp(part, "default"))) { _item_text_set(it, label); return; } WRN("The part name is invalid! : popup=%p", WIDGET(it)); } EOLIAN static const char * _elm_popup_item_elm_widget_item_part_text_get(Eo *eo_it EINA_UNUSED, Elm_Popup_Item_Data *it, const char *part) { ELM_POPUP_ITEM_CHECK_OR_RETURN(it, NULL); if ((!part) || (!strcmp(part, "default"))) return it->label; WRN("The part name is invalid! : popup=%p", WIDGET(it)); return NULL; } static void _item_icon_set(Elm_Popup_Item_Data *it, Evas_Object *icon) { if (it->icon == icon) return; evas_object_del(it->icon); it->icon = icon; if (it->icon) { elm_widget_sub_object_add(WIDGET(it), it->icon); evas_object_data_set(it->icon, "_popup_icon_parent_item", it); efl_content_set(efl_part(VIEW(it), CONTENT_PART), it->icon); elm_layout_signal_emit(VIEW(it), "elm,state,item,icon,visible", "elm"); } else elm_layout_signal_emit(VIEW(it), "elm,state,item,icon,hidden", "elm"); edje_object_message_signal_process(elm_layout_edje_get(VIEW(it))); } EOLIAN static void _elm_popup_item_elm_widget_item_part_content_set(Eo *eo_it EINA_UNUSED, Elm_Popup_Item_Data *it, const char *part, Evas_Object *content) { ELM_POPUP_ITEM_CHECK_OR_RETURN(it); if ((!(part)) || (!strcmp(part, "default"))) _item_icon_set(it, content); else WRN("The part name is invalid! : popup=%p", WIDGET(it)); } EOLIAN static Evas_Object * _elm_popup_item_elm_widget_item_part_content_get(Eo *eo_it EINA_UNUSED, Elm_Popup_Item_Data *it, const char *part) { ELM_POPUP_ITEM_CHECK_OR_RETURN(it, NULL); if ((!(part)) || (!strcmp(part, "default"))) return it->icon; WRN("The part name is invalid! : popup=%p", WIDGET(it)); return NULL; } static Evas_Object * _item_icon_unset(Elm_Popup_Item_Data *it) { Evas_Object *icon = it->icon; if (!it->icon) return NULL; _elm_widget_sub_object_redirect_to_top(WIDGET(it), icon); evas_object_data_del(icon, "_popup_icon_parent_item"); efl_content_unset(efl_part(VIEW(it), CONTENT_PART)); elm_layout_signal_emit(VIEW(it), "elm,state,item,icon,hidden", "elm"); it->icon = NULL; return icon; } EOLIAN static Evas_Object * _elm_popup_item_elm_widget_item_part_content_unset(Eo *eo_it EINA_UNUSED, Elm_Popup_Item_Data *it, const char *part) { Evas_Object *content = NULL; ELM_POPUP_ITEM_CHECK_OR_RETURN(it, NULL); if ((!(part)) || (!strcmp(part, "default"))) content = _item_icon_unset(it); else WRN("The part name is invalid! : popup=%p", WIDGET(it)); return content; } EOLIAN static void _elm_popup_item_elm_widget_item_disable(Eo *eo_it, Elm_Popup_Item_Data *it) { ELM_POPUP_ITEM_CHECK_OR_RETURN(it); if (elm_wdg_item_disabled_get(eo_it)) elm_layout_signal_emit(VIEW(it), "elm,state,item,disabled", "elm"); else elm_layout_signal_emit(VIEW(it), "elm,state,item,enabled", "elm"); } EOLIAN static void _elm_popup_item_efl_object_destructor(Eo *eo_it, Elm_Popup_Item_Data *it) { ELM_POPUP_ITEM_CHECK_OR_RETURN(it); ELM_POPUP_DATA_GET(WIDGET(it), sd); evas_object_del(it->icon); eina_stringshare_del(it->label); sd->items = eina_list_remove(sd->items, it); if (!eina_list_count(sd->items)) { sd->items = NULL; _list_del(sd); } efl_destructor(efl_super(eo_it, ELM_POPUP_ITEM_CLASS)); } EOLIAN static void _elm_popup_item_elm_widget_item_signal_emit(Eo *eo_it EINA_UNUSED, Elm_Popup_Item_Data *it, const char *emission, const char *source) { elm_layout_signal_emit(VIEW(it), emission, source); } static void _item_focused_cb(void *data, const Efl_Event *event EINA_UNUSED) { Elm_Popup_Item_Data *it = data; efl_event_callback_legacy_call(WIDGET(it), ELM_POPUP_EVENT_ITEM_FOCUSED, EO_OBJ(it)); } static void _item_unfocused_cb(void *data, const Efl_Event *event EINA_UNUSED) { Elm_Popup_Item_Data *it = data; efl_event_callback_legacy_call(WIDGET(it), ELM_POPUP_EVENT_ITEM_UNFOCUSED, EO_OBJ(it)); } EOLIAN static Eo * _elm_popup_item_efl_object_constructor(Eo *eo_it, Elm_Popup_Item_Data *it) { eo_it = efl_constructor(efl_super(eo_it, ELM_POPUP_ITEM_CLASS)); it->base = efl_data_scope_get(eo_it, ELM_WIDGET_ITEM_CLASS); return eo_it; } static void _item_new(Elm_Popup_Item_Data *it) { char style[1024]; VIEW(it) = elm_layout_add(WIDGET(it)); elm_object_focus_allow_set(VIEW(it), EINA_TRUE); - elm_widget_mirrored_automatic_set(VIEW(it), EINA_FALSE); + efl_ui_mirrored_automatic_set(VIEW(it), EINA_FALSE); elm_object_mirrored_set(VIEW(it), elm_object_mirrored_get(WIDGET(it))); snprintf(style, sizeof(style), "popup/%s", elm_widget_style_get(WIDGET(it))); if (!elm_layout_theme_set(VIEW(it), "popup", "item", style)) CRI("Failed to set layout!"); else { elm_layout_signal_callback_add(VIEW(it), "elm,action,click", "*", _item_select_cb, it); evas_object_size_hint_align_set(VIEW(it), EVAS_HINT_FILL, EVAS_HINT_FILL); efl_event_callback_add (VIEW(it), ELM_WIDGET_EVENT_FOCUSED, _item_focused_cb, it); efl_event_callback_add (VIEW(it), ELM_WIDGET_EVENT_UNFOCUSED, _item_unfocused_cb, it); evas_object_show(VIEW(it)); } } static Eina_Bool _title_text_set(Evas_Object *obj, const char *text) { Evas_Object *ao; Eina_Bool title_visibility_old, title_visibility_current; ELM_POPUP_DATA_GET(obj, sd); if (sd->title_text == text) return EINA_TRUE; title_visibility_old = (sd->title_text) || (sd->title_icon); eina_stringshare_replace(&sd->title_text, text); elm_layout_text_set(sd->main_layout, "elm.text.title", text); /* access */ if (_elm_config->access_mode) { ao = _access_object_get(obj, ACCESS_TITLE_PART); if (!ao) { ao = _elm_access_edje_object_part_object_register (obj, elm_layout_edje_get(sd->main_layout), ACCESS_TITLE_PART); _elm_access_text_set(_elm_access_info_get(ao), ELM_ACCESS_TYPE, E_("Popup Title")); } _elm_access_text_set(_elm_access_info_get(ao), ELM_ACCESS_INFO, text); } if (sd->title_text) elm_layout_signal_emit(sd->main_layout, "elm,state,title,text,visible", "elm"); else elm_layout_signal_emit(sd->main_layout, "elm,state,title,text,hidden", "elm"); title_visibility_current = (sd->title_text) || (sd->title_icon); if (title_visibility_old != title_visibility_current) _visuals_set(obj); return EINA_TRUE; } static Eina_Bool _content_text_set(Evas_Object *obj, const char *text) { Evas_Object *ao; char style[1024]; ELM_POPUP_DATA_GET(obj, sd); if (sd->items) { _items_remove(sd); _list_del(sd); } else { if (!sd->scroll) efl_content_set(efl_part(sd->main_layout, CONTENT_PART), sd->content_area); else elm_object_content_set(sd->scr, sd->content_area); } if (!text) goto end; if (sd->text_content_obj) { sd->text_content_obj = efl_content_unset(efl_part(sd->content_area, CONTENT_PART)); evas_object_del(sd->text_content_obj); sd->text_content_obj = NULL; } sd->text_content_obj = elm_label_add(sd->content_area); snprintf(style, sizeof(style), "popup/%s", elm_widget_style_get(obj)); elm_object_style_set(sd->text_content_obj, style); evas_object_event_callback_add (sd->text_content_obj, EVAS_CALLBACK_DEL, _on_text_content_del, obj); elm_label_line_wrap_set(sd->text_content_obj, sd->content_text_wrap_type); elm_object_text_set(sd->text_content_obj, text); evas_object_size_hint_weight_set (sd->text_content_obj, EVAS_HINT_EXPAND, 0.0); evas_object_size_hint_align_set (sd->text_content_obj, EVAS_HINT_FILL, EVAS_HINT_FILL); efl_content_set (efl_part(sd->content_area, CONTENT_PART), sd->text_content_obj); /* access */ if (_elm_config->access_mode) { /* unregister label, ACCESS_BODY_PART will register */ elm_access_object_unregister(sd->text_content_obj); ao = _access_object_get(obj, ACCESS_BODY_PART); if (!ao) { ao = _elm_access_edje_object_part_object_register (obj, elm_layout_edje_get(sd->main_layout), ACCESS_BODY_PART); _elm_access_text_set(_elm_access_info_get(ao), ELM_ACCESS_TYPE, E_("Popup Body Text")); } _elm_access_text_set(_elm_access_info_get(ao), ELM_ACCESS_INFO, text); } end: return EINA_TRUE; } EOLIAN static Eina_Bool _elm_popup_text_set(Eo *obj, Elm_Popup_Data *_pd, const char *part, const char *label) { Eina_Bool int_ret = EINA_FALSE; if (!part || !strcmp(part, "default")) int_ret = _content_text_set(obj, label); else if (!strcmp(part, "title,text")) int_ret = _title_text_set(obj, label); else int_ret = elm_layout_text_set(_pd->main_layout, part, label); elm_layout_sizing_eval(obj); return int_ret; } static const char * _title_text_get(const Elm_Popup_Data *sd) { return sd->title_text; } static const char * _content_text_get(const Elm_Popup_Data *sd) { const char *str = NULL; if (sd->text_content_obj) str = elm_object_text_get(sd->text_content_obj); return str; } EOLIAN static const char* _elm_popup_text_get(Eo *obj EINA_UNUSED, Elm_Popup_Data *_pd, const char *part) { const char *text = NULL; if (!part || !strcmp(part, "default")) text = _content_text_get(_pd); else if (!strcmp(part, "title,text")) text = _title_text_get(_pd); else text = elm_layout_text_get(_pd->main_layout, part); return text; } static Eina_Bool _title_icon_set(Evas_Object *obj, Evas_Object *icon) { Eina_Bool title_visibility_old, title_visibility_current; ELM_POPUP_DATA_GET(obj, sd); if (sd->title_icon == icon) return EINA_TRUE; title_visibility_old = (sd->title_text) || (sd->title_icon); evas_object_del(sd->title_icon); sd->title_icon = icon; title_visibility_current = (sd->title_text) || (sd->title_icon); efl_content_set (efl_part(sd->main_layout, "elm.swallow.title.icon"), sd->title_icon); if (sd->title_icon) elm_layout_signal_emit(sd->main_layout, "elm,state,title,icon,visible", "elm"); if (title_visibility_old != title_visibility_current) _visuals_set(obj); return EINA_TRUE; } static Eina_Bool _content_set(Evas_Object *obj, Evas_Object *content) { ELM_POPUP_DATA_GET(obj, sd); if (sd->content && sd->content == content) return EINA_TRUE; if (sd->items) { _items_remove(sd); _list_del(sd); } evas_object_del(sd->content); sd->content = content; if (content) { if (!sd->scroll) efl_content_set(efl_part(sd->main_layout, CONTENT_PART), sd->content_area); else elm_object_content_set(sd->scr, sd->content_area); evas_object_show(content); efl_content_set(efl_part(sd->content_area, CONTENT_PART), content); evas_object_event_callback_add (content, EVAS_CALLBACK_DEL, _on_content_del, obj); } return EINA_TRUE; } static void _action_button_set(Evas_Object *obj, Evas_Object *btn, unsigned int idx) { char buf[128], style[1024]; unsigned int i; ELM_POPUP_DATA_GET(obj, sd); if (idx >= ELM_POPUP_ACTION_BUTTON_MAX) return; if (!btn) { _button_remove(obj, idx, EINA_TRUE); return; } if (sd->buttons[idx]) { evas_object_del(sd->buttons[idx]->btn); free(sd->buttons[idx]); } sd->buttons[idx] = ELM_NEW(Action_Area_Data); sd->buttons[idx]->obj = obj; sd->buttons[idx]->btn = btn; evas_object_event_callback_add (btn, EVAS_CALLBACK_DEL, _on_button_del, obj); for (i = ELM_POPUP_ACTION_BUTTON_MAX - 1; i >= idx; i--) { if (sd->buttons[i]) { sd->last_button_number = i + 1; break; } } if (!sd->action_area) { sd->action_area = elm_layout_add(sd->main_layout); evas_object_event_callback_add (sd->action_area, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _size_hints_changed_cb, sd->main_layout); - elm_widget_mirrored_automatic_set(sd->action_area, EINA_FALSE); + efl_ui_mirrored_automatic_set(sd->action_area, EINA_FALSE); elm_object_mirrored_set(sd->action_area, elm_object_mirrored_get(obj)); efl_content_set(efl_part(sd->main_layout, "elm.swallow.action_area"), sd->action_area); _visuals_set(obj); } snprintf(buf, sizeof(buf), "buttons%i", sd->last_button_number); snprintf(style, sizeof(style), "popup/%s", elm_widget_style_get(obj)); if (!elm_layout_theme_set(sd->action_area, "popup", buf, style)) CRI("Failed to set layout!"); snprintf(buf, sizeof(buf), "elm.swallow.content.button%i", idx + 1); evas_object_show(sd->buttons[idx]->btn); elm_object_part_content_set (sd->action_area, buf, sd->buttons[idx]->btn); } static Eina_Bool _elm_popup_content_set(Eo *obj, Elm_Popup_Data *_pd EINA_UNUSED, const char *part, Evas_Object *content) { unsigned int i; Eina_Bool ret = EINA_TRUE; if (!part || !strcmp(part, "default")) ret = _content_set(obj, content); else if (!strcmp(part, "title,icon")) ret = _title_icon_set(obj, content); else if (!strncmp(part, "button", 6)) { i = atoi(part + 6) - 1; if (i >= ELM_POPUP_ACTION_BUTTON_MAX) { ERR("The part name is invalid! : popup=%p", obj); return EINA_FALSE; } _action_button_set(obj, content, i); } else ret = efl_content_set(efl_part(_pd->main_layout, part), content); elm_layout_sizing_eval(obj); return ret; } static Evas_Object * _title_icon_get(const Elm_Popup_Data *sd) { return sd->title_icon; } static Evas_Object * _content_get(const Elm_Popup_Data *sd) { return sd->content; } static Evas_Object * _action_button_get(const Evas_Object *obj, unsigned int idx) { Evas_Object *button = NULL; ELM_POPUP_DATA_GET(obj, sd); if (!sd->action_area) return NULL; if (sd->buttons[idx]) button = sd->buttons[idx]->btn; return button; } static Evas_Object* _elm_popup_content_get(Eo *obj, Elm_Popup_Data *_pd, const char *part) { Evas_Object *content = NULL; unsigned int i; if (!part || !strcmp(part, "default")) content = _content_get(_pd); else if (!strcmp(part, "title,text")) content = _title_icon_get(_pd); else if (!strncmp(part, "button", 6)) { i = atoi(part + 6) - 1; if (i >= ELM_POPUP_ACTION_BUTTON_MAX) goto err; content = _action_button_get(obj, i); } else content = efl_content_get(efl_part(_pd->main_layout, part)); if (!content) goto err; return content; err: WRN("The part name is invalid! : popup=%p", obj); return NULL; } static Evas_Object * _content_unset(Evas_Object *obj) { Evas_Object *content; ELM_POPUP_DATA_GET(obj, sd); if (!sd->content) return NULL; evas_object_event_callback_del (sd->content, EVAS_CALLBACK_DEL, _on_content_del); content = efl_content_unset(efl_part(sd->content_area, CONTENT_PART)); sd->content = NULL; elm_layout_sizing_eval(obj); return content; } static Evas_Object * _title_icon_unset(Evas_Object *obj) { Evas_Object *icon; ELM_POPUP_DATA_GET(obj, sd); if (!sd->title_icon) return NULL; icon = sd->title_icon; efl_content_unset(efl_part(sd->main_layout, "elm.swallow.title.icon")); sd->title_icon = NULL; return icon; } static Evas_Object* _elm_popup_content_unset(Eo *obj, Elm_Popup_Data *_pd EINA_UNUSED, const char *part) { Evas_Object *content = NULL; unsigned int i; if (!part || !strcmp(part, "default")) content = _content_unset(obj); else if (!strcmp(part, "title,icon")) content = _title_icon_unset(obj); else if (!strncmp(part, "button", 6)) { i = atoi(part + 6) - 1; if (i >= ELM_POPUP_ACTION_BUTTON_MAX) goto err; _button_remove(obj, i, EINA_FALSE); } else goto err; return content; err: ERR("The part name is invalid! : popup=%p", obj); return NULL; } EOLIAN static Eina_Bool _elm_popup_elm_widget_focus_next_manager_is(Eo *obj EINA_UNUSED, Elm_Popup_Data *_pd EINA_UNUSED) { return EINA_TRUE; } EOLIAN static Eina_Bool _elm_popup_elm_widget_focus_next(Eo *obj EINA_UNUSED, Elm_Popup_Data *sd, Elm_Focus_Direction dir, Evas_Object **next, Elm_Object_Item **next_item) { Evas_Object *ao; Eina_List *items = NULL; Eina_Iterator *base_it; /* access */ if (_elm_config->access_mode) { if (sd->title_text) { ao = _access_object_get(obj, ACCESS_TITLE_PART); items = eina_list_append(items, ao); } ao = _access_object_get(obj, ACCESS_BODY_PART); if (ao) items = eina_list_append(items, ao); } base_it = efl_content_iterate(sd->main_layout); EINA_ITERATOR_FOREACH(base_it, ao) if (ao) items = eina_list_append(items, ao); eina_iterator_free(base_it); if (!elm_widget_focus_list_next_get(sd->main_layout, items, eina_list_data_get, dir, next, next_item)) *next = sd->main_layout; eina_list_free(items); return EINA_TRUE; } EOLIAN static Eina_Bool _elm_popup_elm_widget_focus_direction_manager_is(Eo *obj EINA_UNUSED, Elm_Popup_Data *_pd EINA_UNUSED) { return EINA_TRUE; } EOLIAN static Eina_Bool _elm_popup_elm_widget_focus_direction(Eo *obj EINA_UNUSED, Elm_Popup_Data *sd, const Evas_Object *base, double degree, Evas_Object **direction, Elm_Object_Item **direction_item, double *weight) { Evas_Object *ao; Eina_List *items = NULL; Eina_Iterator *base_it; /* access */ if (_elm_config->access_mode) { if (sd->title_text) { ao = _access_object_get(obj, ACCESS_TITLE_PART); items = eina_list_append(items, ao); } ao = _access_object_get(obj, ACCESS_BODY_PART); if (ao) items = eina_list_append(items, ao); } base_it = efl_content_iterate(sd->main_layout); EINA_ITERATOR_FOREACH(base_it, ao) if (ao) items = eina_list_append(items, ao); eina_iterator_free(base_it); elm_widget_focus_list_direction_get (sd->main_layout, base, items, eina_list_data_get, degree, direction, direction_item, weight); eina_list_free(items); return EINA_TRUE; } static Eina_Bool _key_action_move(Evas_Object *obj, const char *params) { const char *dir = params; _elm_widget_focus_auto_show(obj); if (!strcmp(dir, "previous")) elm_widget_focus_cycle(obj, ELM_FOCUS_PREVIOUS); else if (!strcmp(dir, "next")) elm_widget_focus_cycle(obj, ELM_FOCUS_NEXT); else if (!strcmp(dir, "left")) elm_widget_focus_cycle(obj, ELM_FOCUS_LEFT); else if (!strcmp(dir, "right")) elm_widget_focus_cycle(obj, ELM_FOCUS_RIGHT); else if (!strcmp(dir, "up")) elm_widget_focus_cycle(obj, ELM_FOCUS_UP); else if (!strcmp(dir, "down")) elm_widget_focus_cycle(obj, ELM_FOCUS_DOWN); else return EINA_FALSE; return EINA_TRUE; } static Eina_Bool _key_action_escape(Evas_Object *obj, const char *params EINA_UNUSED) { ELM_POPUP_DATA_GET(obj, pd); elm_layout_signal_emit(pd->main_layout, "elm,state,hide", "elm"); elm_notify_dismiss(pd->notify); return EINA_TRUE; } EOLIAN static Eina_Bool _elm_popup_elm_widget_widget_event(Eo *obj, Elm_Popup_Data *_pd EINA_UNUSED, Evas_Object *src, Evas_Callback_Type type, void *event_info) { (void)src; Evas_Event_Key_Down *ev = event_info; if (type != EVAS_CALLBACK_KEY_DOWN) return EINA_FALSE; if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return EINA_FALSE; if (!_elm_config_key_binding_call(obj, MY_CLASS_NAME, ev, key_actions)) return EINA_FALSE; ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD; return EINA_TRUE; } EOLIAN static void _elm_popup_efl_canvas_group_group_add(Eo *obj, Elm_Popup_Data *priv) { char style[1024]; efl_canvas_group_add(efl_super(obj, MY_CLASS)); elm_widget_sub_object_parent_add(obj); snprintf(style, sizeof(style), "popup/%s", elm_widget_style_get(obj)); priv->notify = elm_notify_add(obj); elm_object_style_set(priv->notify, style); elm_notify_align_set(priv->notify, _elm_config->popup_horizontal_align, _elm_config->popup_vertical_align); elm_notify_allow_events_set(priv->notify, EINA_FALSE); evas_object_size_hint_weight_set (priv->notify, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); evas_object_size_hint_align_set (priv->notify, EVAS_HINT_FILL, EVAS_HINT_FILL); evas_object_smart_member_add(priv->notify, obj); - elm_widget_mirrored_automatic_set(priv->notify, EINA_FALSE); + efl_ui_mirrored_automatic_set(priv->notify, EINA_FALSE); elm_object_mirrored_set(priv->notify, elm_object_mirrored_get(obj)); evas_object_event_callback_add(priv->notify, EVAS_CALLBACK_RESIZE, _notify_resize_cb, obj); priv->main_layout = elm_layout_add(obj); if (!elm_layout_theme_set(priv->main_layout, "popup", "base", elm_widget_style_get(obj))) CRI("Failed to set layout!"); elm_object_content_set(priv->notify, priv->main_layout); evas_object_event_callback_add(obj, EVAS_CALLBACK_SHOW, _on_show, NULL); - elm_widget_mirrored_automatic_set(priv->main_layout, EINA_FALSE); + efl_ui_mirrored_automatic_set(priv->main_layout, EINA_FALSE); elm_object_mirrored_set(priv->main_layout, elm_object_mirrored_get(obj)); elm_layout_signal_callback_add (priv->main_layout, "elm,state,title_area,visible", "elm", _layout_change_cb, NULL); elm_layout_signal_callback_add (priv->main_layout, "elm,state,title_area,hidden", "elm", _layout_change_cb, NULL); elm_layout_signal_callback_add (priv->main_layout, "elm,state,action_area,visible", "elm", _layout_change_cb, NULL); elm_layout_signal_callback_add (priv->main_layout, "elm,state,action_area,hidden", "elm", _layout_change_cb, NULL); priv->content_area = elm_layout_add(priv->main_layout); if (!elm_layout_theme_set(priv->content_area, "popup", "content", style)) CRI("Failed to set layout!"); else evas_object_event_callback_add (priv->content_area, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _size_hints_changed_cb, priv->main_layout); priv->content_text_wrap_type = ELM_WRAP_MIXED; efl_event_callback_array_add(priv->notify, _notify_cb(), obj); elm_widget_can_focus_set(obj, EINA_TRUE); elm_widget_can_focus_set(priv->main_layout, EINA_TRUE); _populate_theme_scroll(priv); _visuals_set(obj); if (_elm_config->popup_scrollable) elm_popup_scrollable_set(obj, _elm_config->popup_scrollable); } static void _parent_geom_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED) { Evas_Coord x, y, w, h; Evas_Object *popup = data; evas_object_geometry_get(obj, &x, &y, &w, &h); if (efl_isa(obj, EFL_UI_WIN_CLASS)) { x = 0; y = 0; } evas_object_move(popup, x, y); evas_object_resize(popup, w, h); } EOLIAN static void _elm_popup_elm_widget_widget_parent_set(Eo *obj, Elm_Popup_Data *sd, Evas_Object *parent) { Evas_Coord x, y, w, h; evas_object_geometry_get(parent, &x, &y, &w, &h); if (efl_isa(parent, EFL_UI_WIN_CLASS)) { x = 0; y = 0; } evas_object_move(obj, x, y); evas_object_resize(obj, w, h); sd->parent = parent; evas_object_event_callback_add(parent, EVAS_CALLBACK_RESIZE, _parent_geom_cb, obj); evas_object_event_callback_add(parent, EVAS_CALLBACK_MOVE, _parent_geom_cb, obj); } EOLIAN static void _elm_popup_elm_widget_access(Eo *obj, Elm_Popup_Data *_pd EINA_UNUSED, Eina_Bool is_access) { _access_obj_process(obj, is_access); } EAPI Evas_Object * elm_popup_add(Evas_Object *parent) { EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL); Evas_Object *obj = efl_add(MY_CLASS, parent); ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd, NULL); wd->highlight_root = EINA_TRUE; return obj; } EOLIAN static Eo * _elm_popup_efl_object_constructor(Eo *obj, Elm_Popup_Data *_pd EINA_UNUSED) { obj = efl_constructor(efl_super(obj, MY_CLASS)); efl_canvas_object_type_set(obj, MY_CLASS_NAME_LEGACY); evas_object_smart_callbacks_descriptions_set(obj, _smart_callbacks); elm_interface_atspi_accessible_role_set(obj, ELM_ATSPI_ROLE_NOTIFICATION); return obj; } EOLIAN static void _elm_popup_content_text_wrap_type_set(Eo *obj EINA_UNUSED, Elm_Popup_Data *sd, Elm_Wrap_Type wrap) { //Need to wrap the content text, so not allowing ELM_WRAP_NONE if (wrap == ELM_WRAP_NONE) return; sd->content_text_wrap_type = wrap; if (sd->text_content_obj) elm_label_line_wrap_set(sd->text_content_obj, wrap); } EOLIAN static Elm_Wrap_Type _elm_popup_content_text_wrap_type_get(Eo *obj EINA_UNUSED, Elm_Popup_Data *sd) { return sd->content_text_wrap_type; } /* keeping old externals orient api for notify, but taking away the * introduced deprecation warning by copying the deprecated code * here */ static Elm_Notify_Orient _elm_notify_orient_get(const Evas_Object *obj) { Elm_Notify_Orient orient; double horizontal, vertical; elm_notify_align_get(obj, &horizontal, &vertical); if ((EINA_DBL_EQ(horizontal, 0.5)) && (EINA_DBL_EQ(vertical, 0.0))) orient = ELM_NOTIFY_ORIENT_TOP; else if ((EINA_DBL_EQ(horizontal, 0.5)) && (EINA_DBL_EQ(vertical, 0.5))) orient = ELM_NOTIFY_ORIENT_CENTER; else if ((EINA_DBL_EQ(horizontal, 0.5)) && (EINA_DBL_EQ(vertical, 1.0))) orient = ELM_NOTIFY_ORIENT_BOTTOM; else if ((EINA_DBL_EQ(horizontal, 0.0)) && (EINA_DBL_EQ(vertical, 0.5))) orient = ELM_NOTIFY_ORIENT_LEFT; else if ((EINA_DBL_EQ(horizontal, 1.0)) && (EINA_DBL_EQ(vertical, 0.5))) orient = ELM_NOTIFY_ORIENT_RIGHT; else if ((EINA_DBL_EQ(horizontal, 0.0)) && (EINA_DBL_EQ(vertical, 0.0))) orient = ELM_NOTIFY_ORIENT_TOP_LEFT; else if ((EINA_DBL_EQ(horizontal, 1.0)) && (EINA_DBL_EQ(vertical, 0.0))) orient = ELM_NOTIFY_ORIENT_TOP_RIGHT; else if ((EINA_DBL_EQ(horizontal, 0.0)) && (EINA_DBL_EQ(vertical, 1.0))) orient = ELM_NOTIFY_ORIENT_BOTTOM_LEFT; else if ((EINA_DBL_EQ(horizontal, 1.0)) && (EINA_DBL_EQ(vertical, 1.0))) orient = ELM_NOTIFY_ORIENT_BOTTOM_RIGHT; else orient = ELM_NOTIFY_ORIENT_TOP; return orient; } static void _elm_notify_orient_set(Evas_Object *obj, Elm_Notify_Orient orient) { double horizontal = 0, vertical = 0; switch (orient) { case ELM_NOTIFY_ORIENT_TOP: horizontal = 0.5; vertical = 0.0; break; case ELM_NOTIFY_ORIENT_CENTER: horizontal = 0.5; vertical = 0.5; break; case ELM_NOTIFY_ORIENT_BOTTOM: horizontal = 0.5; vertical = 1.0; break; case ELM_NOTIFY_ORIENT_LEFT: horizontal = 0.0; vertical = 0.5; break; case ELM_NOTIFY_ORIENT_RIGHT: horizontal = 1.0; vertical = 0.5; break; case ELM_NOTIFY_ORIENT_TOP_LEFT: horizontal = 0.0; vertical = 0.0; break; case ELM_NOTIFY_ORIENT_TOP_RIGHT: horizontal = 1.0; vertical = 0.0; break; case ELM_NOTIFY_ORIENT_BOTTOM_LEFT: horizontal = 0.0; vertical = 1.0; break; case ELM_NOTIFY_ORIENT_BOTTOM_RIGHT: horizontal = 1.0; vertical = 1.0; break; case ELM_NOTIFY_ORIENT_LAST: break; } elm_notify_align_set(obj, horizontal, vertical); } EOLIAN static void _elm_popup_orient_set(Eo *obj EINA_UNUSED, Elm_Popup_Data *sd, Elm_Popup_Orient orient) { if (orient >= ELM_POPUP_ORIENT_LAST) return; _elm_notify_orient_set(sd->notify, (Elm_Notify_Orient)orient); } EOLIAN static Elm_Popup_Orient _elm_popup_orient_get(Eo *obj EINA_UNUSED, Elm_Popup_Data *sd) { return (Elm_Popup_Orient)_elm_notify_orient_get(sd->notify); } EOLIAN static void _elm_popup_align_set(Eo *obj EINA_UNUSED, Elm_Popup_Data *sd, double horizontal, double vertical) { elm_notify_align_set(sd->notify, horizontal, vertical); } EOLIAN static void _elm_popup_align_get(Eo *obj EINA_UNUSED, Elm_Popup_Data *sd, double *horizontal, double *vertical) { elm_notify_align_get(sd->notify, horizontal, vertical); } EOLIAN static void _elm_popup_timeout_set(Eo *obj EINA_UNUSED, Elm_Popup_Data *sd, double timeout) { elm_notify_timeout_set(sd->notify, timeout); } EOLIAN static double _elm_popup_timeout_get(Eo *obj EINA_UNUSED, Elm_Popup_Data *sd) { return elm_notify_timeout_get(sd->notify); } EOLIAN static void _elm_popup_allow_events_set(Eo *obj EINA_UNUSED, Elm_Popup_Data *sd, Eina_Bool allow) { Eina_Bool allow_events = !!allow; elm_notify_allow_events_set(sd->notify, allow_events); } EOLIAN static Eina_Bool _elm_popup_allow_events_get(Eo *obj EINA_UNUSED, Elm_Popup_Data *sd) { return elm_notify_allow_events_get(sd->notify); } EOLIAN static Elm_Object_Item* _elm_popup_item_append(Eo *obj, Elm_Popup_Data *sd, const char *label, Evas_Object *icon, Evas_Smart_Cb func, const void *data) { Evas_Object *prev_content; Eo *eo_it; eo_it = efl_add(ELM_POPUP_ITEM_CLASS, obj); if (!eo_it) return NULL; ELM_POPUP_ITEM_DATA_GET(eo_it, it); if (sd->content || sd->text_content_obj) { prev_content = efl_content_get(efl_part(sd->content_area, CONTENT_PART)); evas_object_del(prev_content); } //The first item is appended. if (!sd->items) _list_add(obj); it->func = func; WIDGET_ITEM_DATA_SET(eo_it, data); _item_new(it); _item_icon_set(it, icon); _item_text_set(it, label); elm_box_pack_end(sd->box, VIEW(it)); sd->items = eina_list_append(sd->items, it); elm_layout_sizing_eval(obj); return eo_it; } EOLIAN void _elm_popup_scrollable_set(Eo *obj, Elm_Popup_Data *pd, Eina_Bool scroll) { scroll = !!scroll; if (pd->scroll == scroll) return; pd->scroll = scroll; if (!pd->scr) _create_scroller(obj); else { elm_object_content_unset(pd->scr); ELM_SAFE_FREE(pd->tbl, evas_object_del); _create_scroller(obj); } if (!pd->scroll) { efl_content_set(efl_part(pd->content_area, CONTENT_PART), pd->tbl); efl_content_set(efl_part(pd->main_layout, CONTENT_PART), pd->content_area); if (pd->content) efl_content_set(efl_part(pd->content_area, CONTENT_PART), pd->content); else if (pd->text_content_obj) efl_content_set(efl_part(pd->content_area, CONTENT_PART), pd->text_content_obj); if (pd->theme_scroll) elm_layout_signal_emit(pd->content_area, "elm,scroll,disable", "elm"); } else { if (pd->content || pd->text_content_obj) { efl_content_unset(efl_part(pd->main_layout, CONTENT_PART)); elm_object_content_set(pd->scr, pd->content_area); } efl_content_set(efl_part(pd->main_layout, CONTENT_PART), pd->tbl); if (pd->theme_scroll) elm_layout_signal_emit(pd->content_area, "elm,scroll,enable", "elm"); } elm_layout_sizing_eval(obj); } EOLIAN Eina_Bool _elm_popup_scrollable_get(Eo *obj EINA_UNUSED, Elm_Popup_Data *pd) { return pd->scroll; } EOLIAN static void _elm_popup_dismiss(Eo *obj EINA_UNUSED, Elm_Popup_Data *pd) { elm_layout_signal_emit(pd->main_layout, "elm,state,hide", "elm"); elm_notify_dismiss(pd->notify); } static void _elm_popup_class_constructor(Efl_Class *klass) { evas_smart_legacy_type_register(MY_CLASS_NAME_LEGACY, klass); } static Eina_Bool _action_dismiss(Evas_Object *obj, const char *params EINA_UNUSED) { efl_event_callback_legacy_call(obj, ELM_POPUP_EVENT_BLOCK_CLICKED, NULL); return EINA_TRUE; } EOLIAN const Elm_Atspi_Action * _elm_popup_elm_interface_atspi_widget_action_elm_actions_get(Eo *obj EINA_UNUSED, Elm_Popup_Data *pd EINA_UNUSED) { static Elm_Atspi_Action atspi_actions[] = { { "dismiss", NULL, NULL, _action_dismiss}, { NULL, NULL, NULL, NULL } }; return &atspi_actions[0]; } EOLIAN static Elm_Atspi_State_Set _elm_popup_elm_interface_atspi_accessible_state_set_get(Eo *obj, Elm_Popup_Data *sd EINA_UNUSED) { Elm_Atspi_State_Set ret; ret = elm_interface_atspi_accessible_state_set_get(efl_super(obj, MY_CLASS)); STATE_TYPE_SET(ret, ELM_ATSPI_STATE_MODAL); return ret; } /* Efl.Part begin */ ELM_PART_OVERRIDE(elm_popup, ELM_POPUP, ELM_LAYOUT, Elm_Popup_Data, Elm_Part_Data) ELM_PART_OVERRIDE_CONTENT_SET(elm_popup, ELM_POPUP, ELM_LAYOUT, Elm_Popup_Data, Elm_Part_Data) ELM_PART_OVERRIDE_CONTENT_GET(elm_popup, ELM_POPUP, ELM_LAYOUT, Elm_Popup_Data, Elm_Part_Data) ELM_PART_OVERRIDE_CONTENT_UNSET(elm_popup, ELM_POPUP, ELM_LAYOUT, Elm_Popup_Data, Elm_Part_Data) ELM_PART_OVERRIDE_TEXT_SET(elm_popup, ELM_POPUP, ELM_LAYOUT, Elm_Popup_Data, Elm_Part_Data) ELM_PART_OVERRIDE_TEXT_GET(elm_popup, ELM_POPUP, ELM_LAYOUT, Elm_Popup_Data, Elm_Part_Data) #include "elm_popup_internal_part.eo.c" /* Efl.Part end */ /* Internal EO APIs and hidden overrides */ #define ELM_POPUP_EXTRA_OPS \ EFL_CANVAS_GROUP_ADD_DEL_OPS(elm_popup) #include "elm_popup.eo.c" #include "elm_popup_item.eo.c" diff --git a/src/lib/elementary/elm_main.c b/src/lib/elementary/elm_main.c index 774b04e568..743a9820fd 100644 --- a/src/lib/elementary/elm_main.c +++ b/src/lib/elementary/elm_main.c @@ -1,2016 +1,2016 @@ #ifdef HAVE_CONFIG_H # include "elementary_config.h" #endif #ifndef _WIN32 # include /* dlopen,dlclose,etc */ #endif #ifdef HAVE_CRT_EXTERNS_H # include #endif #ifdef HAVE_EVIL # include #endif #include #include #include "elm_priv.h" #include "ecore_internal.h" #define SEMI_BROKEN_QUICKLAUNCH 1 #ifdef __CYGWIN__ # define LIBEXT ".dll" #else # define LIBEXT ".so" #endif static Elm_Version _version = { VMAJ, VMIN, VMIC, VREV }; EAPI Elm_Version *elm_version = &_version; void _efl_ui_focus_manager_redirect_events_del(Efl_Ui_Focus_Manager *manager, Eo *obj) { efl_event_callback_forwarder_del(manager, EFL_UI_FOCUS_MANAGER_EVENT_FLUSH_PRE, obj); efl_event_callback_forwarder_del(manager, EFL_UI_FOCUS_MANAGER_EVENT_REDIRECT_CHANGED, obj); efl_event_callback_forwarder_del(manager, EFL_UI_FOCUS_MANAGER_EVENT_FOCUSED , obj); efl_event_callback_forwarder_del(manager, EFL_UI_FOCUS_MANAGER_EVENT_COORDS_DIRTY, obj); } void _efl_ui_focus_manager_redirect_events_add(Efl_Ui_Focus_Manager *manager, Eo *obj) { efl_event_callback_forwarder_add(manager, EFL_UI_FOCUS_MANAGER_EVENT_FLUSH_PRE, obj); efl_event_callback_forwarder_add(manager, EFL_UI_FOCUS_MANAGER_EVENT_REDIRECT_CHANGED, obj); efl_event_callback_forwarder_add(manager, EFL_UI_FOCUS_MANAGER_EVENT_FOCUSED , obj); efl_event_callback_forwarder_add(manager, EFL_UI_FOCUS_MANAGER_EVENT_COORDS_DIRTY, obj); } Eina_Bool _elm_dangerous_call_check(const char *call) { char buf[256]; const char *eval; snprintf(buf, sizeof(buf), "%i.%i.%i.%i", VMAJ, VMIN, VMIC, VREV); eval = getenv("ELM_NO_FINGER_WAGGLING"); if ((eval) && (!strcmp(eval, buf))) return 0; ERR("ELEMENTARY FINGER WAGGLE!!!!!!!!!!\n" "\n" " %s() used.\n" "PLEASE see the API documentation for this function. This call\n" "should almost never be used. Only in very special cases.\n" "\n" "To remove this warning please set the environment variable:\n" " ELM_NO_FINGER_WAGGLING\n" "To the value of the Elementary version + revision number. e.g.:\n" " 1.2.5.40295\n" "\n" , call); return 1; } static Eina_Bool _elm_signal_exit(void *data, int ev_type, void *ev); static Eina_Prefix *pfx = NULL; char *_elm_appname = NULL; const char *_elm_data_dir = NULL; const char *_elm_lib_dir = NULL; int _elm_log_dom = -1; EAPI int ELM_EVENT_POLICY_CHANGED = 0; EAPI int ELM_EVENT_PROCESS_BACKGROUND = 0; EAPI int ELM_EVENT_PROCESS_FOREGROUND = 0; static int _elm_init_count = 0; static int _elm_sub_init_count = 0; static int _elm_ql_init_count = 0; static Eina_Bool _elm_prefs_initted = EINA_FALSE; static int _elm_policies[ELM_POLICY_LAST]; static Ecore_Event_Handler *_elm_exit_handler = NULL; static Eina_Bool quicklaunch_on = 0; static Eina_Bool _elm_signal_exit(void *data EINA_UNUSED, int ev_type EINA_UNUSED, void *ev EINA_UNUSED) { elm_exit(); return ECORE_CALLBACK_PASS_ON; } void _elm_rescale(void) { edje_scale_set(_elm_config->scale); _elm_win_rescale(NULL, EINA_FALSE); _elm_ews_wm_rescale(NULL, EINA_FALSE); } static Eina_Bool _emotion_inited = EINA_FALSE; void _elm_emotion_init(void) { if (_emotion_inited) return ; emotion_init(); _emotion_inited = EINA_TRUE; } void _elm_emotion_shutdown(void) { if (!_emotion_inited) return ; emotion_shutdown(); _emotion_inited = EINA_FALSE; } static void *app_mainfunc = NULL; static const char *app_name = NULL; static const char *app_desktop_entry = NULL; static const char *app_domain = NULL; static const char *app_checkfile = NULL; static const char *app_compile_bin_dir = NULL; static const char *app_compile_lib_dir = NULL; static const char *app_compile_data_dir = NULL; static const char *app_compile_locale_dir = NULL; static const char *app_prefix_dir = NULL; static const char *app_bin_dir = NULL; static const char *app_lib_dir = NULL; static const char *app_data_dir = NULL; static const char *app_locale_dir = NULL; static double app_base_scale = 1.0; static Eina_Prefix *app_pfx = NULL; static Ecore_Event_Handler *system_handlers[2] = { NULL, NULL }; static void _prefix_check(void) { int argc = 0; char **argv = NULL; const char *dirs[4] = { NULL, NULL, NULL, NULL }; char *caps = NULL, *p1, *p2; char buf[PATH_MAX]; Efl_Vpath_Core *vpath; if (app_pfx) return; if (!app_domain) return; ecore_app_args_get(&argc, &argv); if (argc < 1) return; dirs[0] = app_compile_bin_dir; dirs[1] = app_compile_lib_dir; dirs[2] = app_compile_data_dir; dirs[3] = app_compile_locale_dir; if (!dirs[0]) dirs[0] = "/usr/local/bin"; if (!dirs[1]) dirs[1] = "/usr/local/lib"; if (!dirs[2]) { snprintf(buf, sizeof(buf), "/usr/local/share/%s", app_domain); dirs[2] = buf; } if (!dirs[3]) dirs[3] = dirs[2]; if (app_domain) { caps = alloca(eina_stringshare_strlen(app_domain) + 1); for (p1 = (char *)app_domain, p2 = caps; *p1; p1++, p2++) *p2 = toupper(*p1); *p2 = 0; } app_pfx = eina_prefix_new(argv[0], app_mainfunc, caps, app_domain, app_checkfile, dirs[0], dirs[1], dirs[2], dirs[3]); vpath = efl_vpath_core_get(EFL_VPATH_CORE_CLASS); efl_vpath_core_meta_set(vpath, "app.dir", eina_prefix_get(app_pfx)); efl_vpath_core_meta_set(vpath, "app.bin", eina_prefix_bin_get(app_pfx)); efl_vpath_core_meta_set(vpath, "app.lib", eina_prefix_lib_get(app_pfx)); efl_vpath_core_meta_set(vpath, "app.data", eina_prefix_data_get(app_pfx)); efl_vpath_core_meta_set(vpath, "app.locale", eina_prefix_locale_get(app_pfx)); snprintf(buf, sizeof(buf), "%s/%s", efl_vpath_core_meta_get(vpath, "config"), app_domain); efl_vpath_core_meta_set(vpath, "app.config", buf); snprintf(buf, sizeof(buf), "%s/%s", efl_vpath_core_meta_get(vpath, "cache"), app_domain); efl_vpath_core_meta_set(vpath, "app.cache", buf); snprintf(buf, sizeof(buf), "%s/%s", efl_vpath_core_meta_get(vpath, "data"), app_domain); efl_vpath_core_meta_set(vpath, "app.local", buf); } static void _prefix_shutdown(void) { if (app_pfx) eina_prefix_free(app_pfx); ELM_SAFE_FREE(app_domain, eina_stringshare_del); ELM_SAFE_FREE(app_checkfile, eina_stringshare_del); ELM_SAFE_FREE(app_compile_bin_dir, eina_stringshare_del); ELM_SAFE_FREE(app_compile_lib_dir, eina_stringshare_del); ELM_SAFE_FREE(app_compile_data_dir, eina_stringshare_del); ELM_SAFE_FREE(app_compile_locale_dir, eina_stringshare_del); app_mainfunc = NULL; app_prefix_dir = NULL; app_bin_dir = NULL; app_lib_dir = NULL; app_data_dir = NULL; app_locale_dir = NULL; app_pfx = NULL; } static struct { Eina_Module *handle; void (*init)(void); void (*shutdown)(void); Eina_Bool (*app_connect)(const char *appname); Eina_Bool is_init; } _clouseau_old_info; static struct { Eina_Module *handle; Eina_Bool (*init)(void); Eina_Bool (*shutdown)(void); Eina_Bool is_init; } _clouseau_info; #define _CLOUSEAU_OLD_LOAD_SYMBOL(cls_struct, sym) \ do \ { \ if ((cls_struct).handle) \ (cls_struct).sym = eina_module_symbol_get((cls_struct).handle, "clouseau_" #sym); \ if (!(cls_struct).sym) \ { \ WRN("Failed loading symbol '%s' from the clouseau library.", "clouseau_" #sym); \ if ((cls_struct).handle) eina_module_free((cls_struct).handle); \ (cls_struct).handle = NULL; \ } \ } \ while (0) #define _CLOUSEAU_LOAD_SYMBOL(cls_struct, sym) \ do \ { \ if ((cls_struct).handle) \ (cls_struct).sym = eina_module_symbol_get((cls_struct).handle, "clouseau_debug_" #sym); \ if (!(cls_struct).sym) \ { \ WRN("Failed loading symbol '%s' from the clouseau library.", "clouseau_debug_" #sym); \ if ((cls_struct).handle) eina_module_free((cls_struct).handle); \ (cls_struct).handle = NULL; \ return EINA_FALSE; \ } \ } \ while (0) static void _elm_clouseau_unload() { if (_clouseau_old_info.is_init) { if (_clouseau_old_info.shutdown) { _clouseau_old_info.shutdown(); } if (_clouseau_old_info.handle) { eina_module_free(_clouseau_old_info.handle); _clouseau_old_info.handle = NULL; } _clouseau_old_info.is_init = EINA_FALSE; } if (_clouseau_info.is_init) { if (_clouseau_info.shutdown) { _clouseau_info.shutdown(); } if (_clouseau_info.handle) { eina_module_free(_clouseau_info.handle); _clouseau_info.handle = NULL; } _clouseau_info.is_init = EINA_FALSE; } } Eina_Bool _elm_clouseau_reload() { if (!_elm_config->clouseau_enable) { _elm_clouseau_unload(); return EINA_TRUE; } if (!_clouseau_old_info.is_init) { _clouseau_old_info.handle = eina_module_new( PACKAGE_LIB_DIR "/libclouseau" LIBEXT); if (!_clouseau_old_info.handle || !eina_module_load(_clouseau_old_info.handle)) { WRN("Failed loading the clouseau_old library."); if (_clouseau_old_info.handle) eina_module_free(_clouseau_old_info.handle); _clouseau_old_info.handle = NULL; } _CLOUSEAU_OLD_LOAD_SYMBOL(_clouseau_old_info, init); _CLOUSEAU_OLD_LOAD_SYMBOL(_clouseau_old_info, shutdown); _CLOUSEAU_OLD_LOAD_SYMBOL(_clouseau_old_info, app_connect); if (_clouseau_old_info.handle) { _clouseau_old_info.init(); if (!_clouseau_old_info.app_connect(elm_app_name_get())) { ERR("Failed connecting to the clouseau server."); } _clouseau_old_info.is_init = EINA_TRUE; } } if (!_clouseau_info.is_init) { _clouseau_info.handle = eina_module_new( PACKAGE_LIB_DIR "/libclouseau_debug" LIBEXT); if (!_clouseau_info.handle || !eina_module_load(_clouseau_info.handle)) { WRN("Failed loading the clouseau library."); if (_clouseau_info.handle) eina_module_free(_clouseau_info.handle); _clouseau_info.handle = NULL; return EINA_FALSE; } _CLOUSEAU_LOAD_SYMBOL(_clouseau_info, init); _CLOUSEAU_LOAD_SYMBOL(_clouseau_info, shutdown); if (_clouseau_info.handle) { _clouseau_info.init(); _clouseau_info.is_init = EINA_TRUE; } } return EINA_TRUE; } static Eina_Bool _sys_memory_changed(void *data EINA_UNUSED, int type EINA_UNUSED, void *event EINA_UNUSED) { Ecore_Memory_State state = ecore_memory_state_get(); if (state != ECORE_MEMORY_STATE_LOW) return ECORE_CALLBACK_PASS_ON; elm_cache_all_flush(); return ECORE_CALLBACK_PASS_ON; } static Eina_Bool _sys_lang_changed(void *data EINA_UNUSED, int type EINA_UNUSED, void *event EINA_UNUSED) { char *lang; lang = getenv("LANG"); if (!lang) lang = getenv("LC_MESSAGES"); if (!lang) lang = getenv("LC_ALL"); if (lang) elm_language_set(lang); else ERR("Language not set in environment"); return ECORE_CALLBACK_PASS_ON; } EAPI int elm_init(int argc, char **argv) { _elm_init_count++; if (_elm_init_count > 1) return _elm_init_count; elm_quicklaunch_init(argc, argv); elm_quicklaunch_sub_init(argc, argv); ecore_loop_arguments_send(argc - 1, (argc > 1) ? ((const char **)argv + 1) : NULL); _prefix_shutdown(); system_handlers[0] = ecore_event_handler_add(ECORE_EVENT_MEMORY_STATE, _sys_memory_changed, NULL); system_handlers[1] = ecore_event_handler_add(ECORE_EVENT_LOCALE_CHANGED, _sys_lang_changed, NULL); if (_elm_config->atspi_mode != ELM_ATSPI_MODE_OFF) _elm_atspi_bridge_init(); if (!_elm_config->web_backend) _elm_config->web_backend = "none"; if (!_elm_web_init(_elm_config->web_backend)) _elm_config->web_backend = "none"; _elm_code_parse_setup(); return _elm_init_count; } EAPI int elm_shutdown(void) { if (_elm_init_count <= 0) return 0; _elm_init_count--; if (_elm_init_count > 0) return _elm_init_count; ecore_event_handler_del(system_handlers[0]); ecore_event_handler_del(system_handlers[1]); _elm_win_shutdown(); _elm_atspi_bridge_shutdown(); while (_elm_win_deferred_free) ecore_main_loop_iterate(); _elm_clouseau_unload(); // wrningz :( // _prefix_shutdown(); ELM_SAFE_FREE(app_name, eina_stringshare_del); ELM_SAFE_FREE(app_desktop_entry, eina_stringshare_del); elm_quicklaunch_sub_shutdown(); elm_quicklaunch_shutdown(); return _elm_init_count; } EAPI void elm_app_info_set(void *mainfunc, const char *dom, const char *checkfile) { app_mainfunc = mainfunc; eina_stringshare_replace(&app_domain, dom); eina_stringshare_replace(&app_checkfile, checkfile); } EAPI void elm_app_name_set(const char *name) { eina_stringshare_replace(&app_name, name); } EAPI void elm_app_desktop_entry_set(const char *path) { eina_stringshare_replace(&app_desktop_entry, path); } EAPI void elm_app_compile_bin_dir_set(const char *dir) { eina_stringshare_replace(&app_compile_bin_dir, dir); } EAPI void elm_app_compile_lib_dir_set(const char *dir) { eina_stringshare_replace(&app_compile_lib_dir, dir); } EAPI void elm_app_compile_data_dir_set(const char *dir) { eina_stringshare_replace(&app_compile_data_dir, dir); } EAPI void elm_app_compile_locale_set(const char *dir) { eina_stringshare_replace(&app_compile_locale_dir, dir); } EAPI const char * elm_app_name_get(void) { if (app_name) return app_name; return ""; } EAPI const char * elm_app_desktop_entry_get(void) { if (app_desktop_entry) return app_desktop_entry; return ""; } EAPI const char * elm_app_prefix_dir_get(void) { if (app_prefix_dir) return app_prefix_dir; _prefix_check(); if (!app_pfx) return ""; app_prefix_dir = eina_prefix_get(app_pfx); return app_prefix_dir; } EAPI const char * elm_app_bin_dir_get(void) { if (app_bin_dir) return app_bin_dir; _prefix_check(); if (!app_pfx) return ""; app_bin_dir = eina_prefix_bin_get(app_pfx); return app_bin_dir; } EAPI const char * elm_app_lib_dir_get(void) { if (app_lib_dir) return app_lib_dir; _prefix_check(); if (!app_pfx) return ""; app_lib_dir = eina_prefix_lib_get(app_pfx); return app_lib_dir; } EAPI const char * elm_app_data_dir_get(void) { if (app_data_dir) return app_data_dir; _prefix_check(); if (!app_pfx) return ""; app_data_dir = eina_prefix_data_get(app_pfx); return app_data_dir; } EAPI const char * elm_app_locale_dir_get(void) { if (app_locale_dir) return app_locale_dir; _prefix_check(); if (!app_pfx) return ""; app_locale_dir = eina_prefix_locale_get(app_pfx); return app_locale_dir; } EAPI void elm_app_base_scale_set(double base_scale) { if (base_scale < 0.0) return; if (fabs(base_scale) < DBL_EPSILON) return; app_base_scale = base_scale; } EAPI double elm_app_base_scale_get(void) { if (app_base_scale > 0.0) return app_base_scale; return 1.0; } static Eina_Bool _elm_need_e_dbus = EINA_FALSE; static void *e_dbus_handle = NULL; EAPI Eina_Bool elm_need_e_dbus(void) { int (*init_func)(void) = NULL; if (_elm_need_e_dbus) return EINA_TRUE; /* We use RTLD_NOLOAD when available, so we are sure to use the 'libeldbus' that was linked to the binary */ #ifndef RTLD_NOLOAD # define RTLD_NOLOAD RTLD_GLOBAL #endif if (!e_dbus_handle) e_dbus_handle = dlopen("libedbus.so", RTLD_LAZY | RTLD_NOLOAD); if (!e_dbus_handle) e_dbus_handle = dlopen("libedbus.so.1", RTLD_LAZY | RTLD_NOLOAD); if (!e_dbus_handle) return EINA_FALSE; init_func = dlsym(e_dbus_handle, "e_dbus_init"); if (!init_func) return EINA_FALSE; _elm_need_e_dbus = EINA_TRUE; init_func(); return EINA_TRUE; } static void _elm_unneed_e_dbus(void) { int (*shutdown_func)(void) = NULL; if (!_elm_need_e_dbus) return; shutdown_func = dlsym(e_dbus_handle, "e_dbus_shutdown"); if (!shutdown_func) return; _elm_need_e_dbus = EINA_FALSE; shutdown_func(); dlclose(e_dbus_handle); e_dbus_handle = NULL; } static Eina_Bool _elm_need_eldbus = EINA_FALSE; EAPI Eina_Bool elm_need_eldbus(void) { if (_elm_need_eldbus) return EINA_TRUE; _elm_need_eldbus = EINA_TRUE; eldbus_init(); return EINA_TRUE; } static void _elm_unneed_eldbus(void) { if (!_elm_need_eldbus) return; _elm_need_eldbus = EINA_FALSE; eldbus_shutdown(); } #ifdef ELM_ELOCATION static Eina_Bool _elm_need_elocation = EINA_FALSE; #endif EAPI Eina_Bool elm_need_elocation(void) { #ifdef ELM_ELOCATION if (_elm_need_elocation) return EINA_TRUE; _elm_need_elocation = EINA_TRUE; elocation_init(); return EINA_TRUE; #else return EINA_FALSE; #endif } static void _elm_unneed_elocation(void) { #ifdef ELM_ELOCATION if (!_elm_need_elocation) return; _elm_need_elocation = EINA_FALSE; eldbus_shutdown(); #endif } static Eina_Bool _elm_need_efreet = EINA_FALSE; EAPI Eina_Bool elm_need_efreet(void) { if (_elm_need_efreet) return EINA_TRUE; if (!efreet_init()) return EINA_FALSE; if (!efreet_mime_init()) { efreet_shutdown(); return EINA_FALSE; } if (!efreet_trash_init()) { efreet_mime_shutdown(); efreet_shutdown(); return EINA_FALSE; } _elm_need_efreet = EINA_TRUE; /* { Eina_List **list; list = efreet_icon_extra_list_get(); if (list) { e_user_dir_concat_static(buf, "icons"); *list = eina_list_prepend(*list, (void *)eina_stringshare_add(buf)); e_prefix_data_concat_static(buf, "data/icons"); *list = eina_list_prepend(*list, (void *)eina_stringshare_add(buf)); } } */ return EINA_TRUE; } static void _elm_unneed_efreet(void) { if (!_elm_need_efreet) return; _elm_need_efreet = EINA_FALSE; efreet_trash_shutdown(); efreet_mime_shutdown(); efreet_shutdown(); } EAPI void elm_quicklaunch_mode_set(Eina_Bool ql_on) { quicklaunch_on = ql_on; } EAPI Eina_Bool elm_quicklaunch_mode_get(void) { return quicklaunch_on; } EAPI int elm_quicklaunch_init(int argc, char **argv) { _elm_ql_init_count++; if (_elm_ql_init_count > 1) return _elm_ql_init_count; eina_init(); _elm_log_dom = eina_log_domain_register("elementary", EINA_COLOR_LIGHTBLUE); if (!_elm_log_dom) { EINA_LOG_ERR("could not register elementary log domain."); _elm_log_dom = EINA_LOG_DOMAIN_GLOBAL; } eet_init(); ecore_init(); edje_init(); #ifdef HAVE_ELEMENTARY_EMAP emap_init(); #endif ecore_app_args_set(argc, (const char **)argv); memset(_elm_policies, 0, sizeof(_elm_policies)); if (!ELM_EVENT_POLICY_CHANGED) { ELM_EVENT_POLICY_CHANGED = ecore_event_type_new(); ELM_EVENT_PROCESS_BACKGROUND = ecore_event_type_new(); ELM_EVENT_PROCESS_FOREGROUND = ecore_event_type_new(); } if (!ecore_file_init()) ERR("Elementary cannot init ecore_file"); eio_init(); _elm_exit_handler = ecore_event_handler_add(ECORE_EVENT_SIGNAL_EXIT, _elm_signal_exit, NULL); if (argv) { _elm_appname = strdup(ecore_file_file_get(argv[0])); elm_app_name_set(_elm_appname); } pfx = eina_prefix_new(argv ? argv[0] : NULL, elm_quicklaunch_init, "ELM", "elementary", "config/profile.cfg", PACKAGE_LIB_DIR, /* don't have a bin dir currently */ PACKAGE_LIB_DIR, PACKAGE_DATA_DIR, LOCALE_DIR); if (pfx) { _elm_data_dir = eina_stringshare_add(eina_prefix_data_get(pfx)); _elm_lib_dir = eina_stringshare_add(eina_prefix_lib_get(pfx)); } if (!_elm_data_dir) _elm_data_dir = eina_stringshare_add("/"); if (!_elm_lib_dir) _elm_lib_dir = eina_stringshare_add("/"); eina_log_timing(_elm_log_dom, EINA_LOG_STATE_STOP, EINA_LOG_STATE_INIT); if (quicklaunch_on) _elm_init_count++; return _elm_ql_init_count; } EAPI int elm_quicklaunch_sub_init(int argc, char **argv) { _elm_sub_init_count++; if (_elm_sub_init_count > 1) return _elm_sub_init_count; if (quicklaunch_on) { _elm_config_init(); #ifdef SEMI_BROKEN_QUICKLAUNCH return _elm_sub_init_count; #endif } if (!quicklaunch_on) { ecore_app_args_set(argc, (const char **)argv); evas_init(); _elm_module_init(); _elm_config_init(); _elm_config_sub_init(); ecore_evas_init(); // FIXME: check errors ecore_imf_init(); ecore_con_init(); ecore_con_url_init(); _elm_prefs_initted = _elm_prefs_init(); _elm_ews_wm_init(); elm_color_class_init(); } return _elm_sub_init_count; } EAPI int elm_quicklaunch_sub_shutdown(void) { _elm_sub_init_count--; if (_elm_sub_init_count > 0) return _elm_sub_init_count; if (quicklaunch_on) { #ifdef SEMI_BROKEN_QUICKLAUNCH return _elm_sub_init_count; #endif } if (!quicklaunch_on) { _elm_win_shutdown(); _elm_module_shutdown(); if (_elm_prefs_initted) _elm_prefs_shutdown(); _elm_ews_wm_shutdown(); ecore_con_url_shutdown(); ecore_con_shutdown(); ecore_imf_shutdown(); ecore_evas_shutdown(); _elm_config_sub_shutdown(); evas_shutdown(); } return _elm_sub_init_count; } EAPI int elm_quicklaunch_shutdown(void) { _elm_ql_init_count--; if (_elm_ql_init_count > 0) return _elm_ql_init_count; eina_log_timing(_elm_log_dom, EINA_LOG_STATE_STOP, EINA_LOG_STATE_SHUTDOWN); ecore_event_type_flush(ELM_EVENT_POLICY_CHANGED, ELM_EVENT_PROCESS_BACKGROUND, ELM_EVENT_PROCESS_FOREGROUND); if (pfx) eina_prefix_free(pfx); pfx = NULL; ELM_SAFE_FREE(_elm_data_dir, eina_stringshare_del); ELM_SAFE_FREE(_elm_lib_dir, eina_stringshare_del); ELM_SAFE_FREE(_elm_appname, free); _elm_config_shutdown(); elm_color_class_shutdown(); ELM_SAFE_FREE(_elm_exit_handler, ecore_event_handler_del); _elm_theme_shutdown(); _elm_unneed_systray(); _elm_unneed_sys_notify(); _elm_unneed_efreet(); _elm_unneed_e_dbus(); _elm_unneed_eldbus(); _elm_unneed_elocation(); _elm_unneed_ethumb(); _elm_unneed_web(); eio_shutdown(); ecore_file_shutdown(); #ifdef HAVE_ELEMENTARY_EMAP emap_shutdown(); #endif _elm_emotion_shutdown(); edje_shutdown(); ecore_shutdown(); eet_shutdown(); if ((_elm_log_dom > -1) && (_elm_log_dom != EINA_LOG_DOMAIN_GLOBAL)) { eina_log_domain_unregister(_elm_log_dom); _elm_log_dom = -1; } eina_shutdown(); return _elm_ql_init_count; } EAPI void elm_quicklaunch_seed(void) { #ifndef SEMI_BROKEN_QUICKLAUNCH if (quicklaunch_on) { Evas_Object *win, *bg, *bt; win = elm_win_add(NULL, "seed", ELM_WIN_BASIC); bg = elm_bg_add(win); elm_win_resize_object_add(win, bg); evas_object_show(bg); bt = elm_button_add(win); elm_object_text_set(bt, " abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789~-_=+\\|]}[{;:'\",<.>/?"); elm_win_resize_object_add(win, bt); ecore_main_loop_iterate(); evas_object_del(win); ecore_main_loop_iterate(); # ifdef HAVE_ELEMENTARY_X if (ecore_x_display_get()) ecore_x_sync(); # endif ecore_main_loop_iterate(); } #endif } #ifdef HAVE_FORK static void *qr_handle = NULL; #endif static int (*qr_main)(int argc, char **argv) = NULL; static void (*qre_main)(void *data, const Efl_Event *ev) = NULL; EAPI Eina_Bool elm_quicklaunch_prepare(int argc, char **argv, const char *cwd) { #ifdef HAVE_FORK char *exe, *exe2, *p; char *exename; if (argc <= 0 || argv == NULL) return EINA_FALSE; exe = elm_quicklaunch_exe_path_get(argv[0], cwd); if (!exe) { ERR("requested quicklaunch binary '%s' does not exist\n", argv[0]); return EINA_FALSE; } exe2 = malloc(strlen(exe) + 1 + 7 + strlen(LIBEXT)); strcpy(exe2, exe); p = strrchr(exe2, '/'); if (p) p++; else p = exe2; exename = alloca(strlen(p) + 1); strcpy(exename, p); *p = 0; strcat(p, "../lib/"); strcat(p, exename); strcat(p, LIBEXT); if (access(exe2, R_OK | X_OK) != 0) ELM_SAFE_FREE(exe2, free); /* Try linking to executable first. Works with PIE files. */ qr_handle = dlopen(exe, RTLD_NOW | RTLD_GLOBAL); if (qr_handle) { INF("dlopen('%s') = %p", exe, qr_handle); qr_main = dlsym(qr_handle, "elm_main"); if (qr_main) { INF("dlsym(%p, 'elm_main') = %p", qr_handle, qr_main); free(exe2); free(exe); return EINA_TRUE; } dlclose(qr_handle); qr_handle = NULL; } if (!exe2) { WRN("not quicklauncher capable: '%s'", exe); free(exe); return EINA_FALSE; } free(exe); /* Open companion .so file. * Support for legacy quicklaunch apps with separate library. */ qr_handle = dlopen(exe2, RTLD_NOW | RTLD_GLOBAL); if (!qr_handle) { fprintf(stderr, "dlerr: %s\n", dlerror()); WRN("dlopen('%s') failed: %s", exe2, dlerror()); free(exe2); return EINA_FALSE; } INF("dlopen('%s') = %p", exe2, qr_handle); qr_main = dlsym(qr_handle, "elm_main"); INF("dlsym(%p, 'elm_main') = %p", qr_handle, qr_main); if (!qr_main) { WRN("not quicklauncher capable: no elm_main in '%s'", exe2); dlclose(qr_handle); qr_handle = NULL; free(exe2); return EINA_FALSE; } free(exe2); return EINA_TRUE; #else (void)argc; (void)argv; (void)cwd; return EINA_FALSE; #endif } EAPI Eina_Bool efl_quicklaunch_prepare(int argc, char **argv, const char *cwd) { #ifdef HAVE_FORK char *exe, *exe2, *p; char *exename; if (argc <= 0 || argv == NULL) return EINA_FALSE; exe = elm_quicklaunch_exe_path_get(argv[0], cwd); if (!exe) { ERR("requested quicklaunch binary '%s' does not exist\n", argv[0]); return EINA_FALSE; } exe2 = malloc(strlen(exe) + 1 + 7 + strlen(LIBEXT)); strcpy(exe2, exe); p = strrchr(exe2, '/'); if (p) p++; else p = exe2; exename = alloca(strlen(p) + 1); strcpy(exename, p); *p = 0; strcat(p, "../lib/"); strcat(p, exename); strcat(p, LIBEXT); if (access(exe2, R_OK | X_OK) != 0) ELM_SAFE_FREE(exe2, free); /* Try linking to executable first. Works with PIE files. */ qr_handle = dlopen(exe, RTLD_NOW | RTLD_GLOBAL); if (qr_handle) { INF("dlopen('%s') = %p", exe, qr_handle); qre_main = dlsym(qr_handle, "efl_main"); if (qre_main) { INF("dlsym(%p, 'elm_main') = %p", qr_handle, qre_main); free(exe2); free(exe); return EINA_TRUE; } dlclose(qr_handle); qr_handle = NULL; } if (!exe2) { WRN("not quicklauncher capable: '%s'", exe); free(exe); return EINA_FALSE; } free(exe); /* Open companion .so file. * Support for legacy quicklaunch apps with separate library. */ qr_handle = dlopen(exe2, RTLD_NOW | RTLD_GLOBAL); if (!qr_handle) { fprintf(stderr, "dlerr: %s\n", dlerror()); WRN("dlopen('%s') failed: %s", exe2, dlerror()); free(exe2); return EINA_FALSE; } INF("dlopen('%s') = %p", exe2, qr_handle); qre_main = dlsym(qr_handle, "efl_main"); INF("dlsym(%p, 'elm_main') = %p", qr_handle, qre_main); if (!qre_main) { WRN("not quicklauncher capable: no efl_main in '%s'", exe2); dlclose(qr_handle); qr_handle = NULL; free(exe2); return EINA_FALSE; } free(exe2); return EINA_TRUE; #else (void)argc; (void)argv; (void)cwd; return EINA_FALSE; #endif } EAPI Eina_Bool elm_quicklaunch_fork(int argc, char **argv, char *cwd, void (*postfork_func) (void *data), void *postfork_data) { #ifdef HAVE_FORK pid_t child; int ret; if (!qr_main && !qre_main) { int i; char **args; child = fork(); if (child > 0) return EINA_TRUE; else if (child < 0) { perror("could not fork"); return EINA_FALSE; } setsid(); if (chdir(cwd) != 0) perror("could not chdir"); args = alloca((argc + 1) * sizeof(char *)); for (i = 0; i < argc; i++) args[i] = argv[i]; args[argc] = NULL; WRN("%s not quicklaunch capable, fallback...", argv[0]); execvp(argv[0], args); ERR("failed to execute '%s': %s", argv[0], strerror(errno)); exit(-1); } child = fork(); if (child > 0) return EINA_TRUE; else if (child < 0) { perror("could not fork"); return EINA_FALSE; } if (postfork_func) postfork_func(postfork_data); ecore_fork_reset(); eina_main_loop_define(); if (quicklaunch_on) { ELM_SAFE_FREE(_elm_appname, free); if ((argv) && (argv[0])) _elm_appname = strdup(ecore_file_file_get(argv[0])); #ifdef SEMI_BROKEN_QUICKLAUNCH ecore_app_args_set(argc, (const char **)argv); evas_init(); _elm_module_init(); _elm_config_sub_init(); # ifdef HAVE_ELEMENTARY_X { Eina_Bool init_x; const char *ev = getenv("ELM_DISPLAY"); Eina_Bool have_display = !!getenv("DISPLAY"); if (ev) /* If ELM_DISPLAY is specified */ { if (!strcmp(ev, "x11")) /* and it is X11 */ { if (!have_display) /* if there is no $DISPLAY */ { ERR("$ELM_DISPLAY is set to x11 but $DISPLAY" " is not set"); init_x = EINA_FALSE; } else /* if there is */ init_x = EINA_TRUE; } else /* not X11 */ init_x = EINA_FALSE; } else /* ELM_DISPLAY not specified */ { if (have_display) /* If there is a $DISPLAY */ init_x = EINA_TRUE; else /* No $DISPLAY */ init_x = EINA_FALSE; } if (init_x) ecore_x_init(NULL); } # endif ecore_evas_init(); // FIXME: check errors ecore_imf_init(); #endif } setsid(); if (chdir(cwd) != 0) perror("could not chdir"); ecore_app_args_set(argc, (const char **)argv); if (_elm_config->atspi_mode != ELM_ATSPI_MODE_OFF) _elm_atspi_bridge_init(); if (qre_main) { efl_event_callback_add(ecore_main_loop_get(), EFL_LOOP_EVENT_ARGUMENTS, qre_main, NULL); ret = efl_loop_begin(ecore_main_loop_get()); elm_shutdown(); exit(ret); } else { ret = qr_main(argc, argv); exit(ret); } return EINA_TRUE; #else return EINA_FALSE; (void)argc; (void)argv; (void)cwd; (void)postfork_func; (void)postfork_data; #endif } EAPI void elm_quicklaunch_cleanup(void) { #ifdef HAVE_FORK if (qr_handle) { dlclose(qr_handle); qr_handle = NULL; qr_main = NULL; } #endif } EAPI int elm_quicklaunch_fallback(int argc, char **argv) { int ret; char cwd[PATH_MAX]; elm_quicklaunch_init(argc, argv); elm_quicklaunch_sub_init(argc, argv); elm_quicklaunch_prepare(argc, argv, getcwd(cwd, sizeof(cwd))); ret = qr_main(argc, argv); exit(ret); return ret; } EAPI int efl_quicklaunch_fallback(int argc, char **argv) { /* int ret; */ char cwd[PATH_MAX]; elm_quicklaunch_init(argc, argv); elm_quicklaunch_sub_init(argc, argv); if (efl_quicklaunch_prepare(argc, argv, getcwd(cwd, sizeof(cwd)))) { efl_event_callback_add(ecore_main_loop_get(), EFL_LOOP_EVENT_ARGUMENTS, qre_main, NULL); return efl_loop_begin(ecore_main_loop_get()); } return 255; } EAPI char * elm_quicklaunch_exe_path_get(const char *exe, const char *cwd) { static char *path = NULL; static Eina_List *pathlist = NULL; const char *pathitr; const Eina_List *l; char buf[PATH_MAX]; if (exe[0] == '/') return strdup(exe); if (cwd) pathlist = eina_list_append(pathlist, eina_stringshare_add(cwd)); else { if ((exe[0] == '.') && (exe[1] == '/')) return strdup(exe); if ((exe[0] == '.') && (exe[1] == '.') && (exe[2] == '/')) return strdup(exe); } if (!path) { const char *p, *pp; char *buf2; path = getenv("PATH"); buf2 = alloca(strlen(path) + 1); p = path; pp = p; for (;; ) { if ((*p == ':') || (!*p)) { int len; len = p - pp; strncpy(buf2, pp, len); buf2[len] = 0; pathlist = eina_list_append(pathlist, eina_stringshare_add(buf2)); if (!*p) break; p++; pp = p; } else { if (!*p) break; p++; } } } EINA_LIST_FOREACH(pathlist, l, pathitr) { snprintf(buf, sizeof(buf), "%s/%s", pathitr, exe); if (!access(buf, R_OK | X_OK)) return strdup(buf); } return NULL; } EAPI void elm_run(void) { ecore_main_loop_begin(); } EAPI void elm_exit(void) { ecore_main_loop_quit(); if (elm_policy_get(ELM_POLICY_EXIT) == ELM_POLICY_EXIT_WINDOWS_DEL) { Eina_List *l, *l_next; Evas_Object *win; EINA_LIST_FOREACH_SAFE(_elm_win_list, l, l_next, win) evas_object_del(win); } } //FIXME: Use Elm_Policy Parameter when 2.0 is released. EAPI Eina_Bool elm_policy_set(unsigned int policy, int value) { Elm_Event_Policy_Changed *ev; if (policy >= ELM_POLICY_LAST) return EINA_FALSE; if (value == _elm_policies[policy]) return EINA_TRUE; /* TODO: validate policy? */ ev = malloc(sizeof(*ev)); ev->policy = policy; ev->new_value = value; ev->old_value = _elm_policies[policy]; _elm_policies[policy] = value; ecore_event_add(ELM_EVENT_POLICY_CHANGED, ev, NULL, NULL); return EINA_TRUE; } //FIXME: Use Elm_Policy Parameter when 2.0 is released. EAPI int elm_policy_get(unsigned int policy) { if (policy >= ELM_POLICY_LAST) return 0; return _elm_policies[policy]; } EAPI void elm_language_set(const char *lang) { setlocale(LC_ALL, lang); evas_language_reinit(); _elm_win_translate(); edje_language_set(lang); } EAPI Eina_Bool elm_object_mirrored_get(const Evas_Object *obj) { EINA_SAFETY_ON_NULL_RETURN_VAL(obj, EINA_FALSE); return efl_ui_mirrored_get(obj); } EAPI void elm_object_mirrored_set(Evas_Object *obj, Eina_Bool mirrored) { EINA_SAFETY_ON_NULL_RETURN(obj); efl_ui_mirrored_set(obj, mirrored); } EAPI Eina_Bool elm_object_mirrored_automatic_get(const Evas_Object *obj) { EINA_SAFETY_ON_NULL_RETURN_VAL(obj, EINA_FALSE); - return elm_widget_mirrored_automatic_get(obj); + return efl_ui_mirrored_automatic_get(obj); } EAPI void elm_object_mirrored_automatic_set(Evas_Object *obj, Eina_Bool automatic) { EINA_SAFETY_ON_NULL_RETURN(obj); - elm_widget_mirrored_automatic_set(obj, automatic); + efl_ui_mirrored_automatic_set(obj, automatic); } /** * @} */ EAPI void elm_object_scale_set(Evas_Object *obj, double scale) { EINA_SAFETY_ON_NULL_RETURN(obj); efl_ui_scale_set(obj, scale); } EAPI double elm_object_scale_get(const Evas_Object *obj) { EINA_SAFETY_ON_NULL_RETURN_VAL(obj, 0.0); return efl_ui_scale_get(obj); } EAPI void elm_object_part_text_set(Evas_Object *obj, const char *part, const char *label) { EINA_SAFETY_ON_NULL_RETURN(obj); elm_widget_part_text_set(obj, part, label); } EAPI const char * elm_object_part_text_get(const Evas_Object *obj, const char *part) { EINA_SAFETY_ON_NULL_RETURN_VAL(obj, NULL); return elm_widget_part_text_get(obj, part); } EAPI void elm_object_domain_translatable_part_text_set(Evas_Object *obj, const char *part, const char *domain, const char *text) { EINA_SAFETY_ON_NULL_RETURN(obj); elm_widget_domain_translatable_part_text_set(obj, part, domain, text); } EAPI const char * elm_object_translatable_part_text_get(const Evas_Object *obj, const char *part) { EINA_SAFETY_ON_NULL_RETURN_VAL(obj, NULL); return elm_widget_translatable_part_text_get(obj, part); } EAPI void elm_object_domain_part_text_translatable_set(Evas_Object *obj, const char *part, const char *domain, Eina_Bool translatable) { EINA_SAFETY_ON_NULL_RETURN(obj); elm_widget_domain_part_text_translatable_set(obj, part, domain, translatable); } EINA_DEPRECATED EAPI void elm_object_domain_translatable_text_part_set(Evas_Object *obj, const char *part, const char *domain, const char *text) { elm_object_domain_translatable_part_text_set(obj, part, domain, text); } EINA_DEPRECATED EAPI const char * elm_object_translatable_text_part_get(const Evas_Object *obj, const char *part) { return elm_object_translatable_part_text_get(obj, part); } EAPI void elm_object_part_content_set(Evas_Object *obj, const char *part, Evas_Object *content) { EINA_SAFETY_ON_NULL_RETURN(obj); elm_widget_content_part_set(obj, part, content); } EAPI Evas_Object * elm_object_part_content_get(const Evas_Object *obj, const char *part) { EINA_SAFETY_ON_NULL_RETURN_VAL(obj, NULL); return elm_widget_content_part_get(obj, part); } EAPI Evas_Object * elm_object_part_content_unset(Evas_Object *obj, const char *part) { EINA_SAFETY_ON_NULL_RETURN_VAL(obj, NULL); return elm_widget_content_part_unset(obj, part); } EAPI Eina_Bool elm_object_style_set(Evas_Object *obj, const char *style) { EINA_SAFETY_ON_NULL_RETURN_VAL(obj, EINA_FALSE); if (elm_widget_style_set(obj, style)) return EINA_TRUE; return EINA_FALSE; } EAPI Eina_Bool elm_object_focus_highlight_style_set(Evas_Object *obj, const char *style) { EINA_SAFETY_ON_NULL_RETURN_VAL(obj, EINA_FALSE); return elm_widget_focus_highlight_style_set(obj, style); } EAPI const char * elm_object_focus_highlight_style_get(const Evas_Object *obj) { EINA_SAFETY_ON_NULL_RETURN_VAL(obj, NULL); return elm_widget_focus_highlight_style_get(obj); } EAPI const char * elm_object_style_get(const Evas_Object *obj) { EINA_SAFETY_ON_NULL_RETURN_VAL(obj, NULL); return elm_widget_style_get(obj); } EAPI void elm_object_disabled_set(Evas_Object *obj, Eina_Bool disabled) { EINA_SAFETY_ON_NULL_RETURN(obj); elm_widget_disabled_set(obj, disabled); } EAPI Eina_Bool elm_object_disabled_get(const Evas_Object *obj) { EINA_SAFETY_ON_NULL_RETURN_VAL(obj, EINA_FALSE); return elm_widget_disabled_get(obj); } EAPI void elm_cache_all_flush(void) { const Eina_List *l; Evas_Object *obj; edje_file_cache_flush(); edje_collection_cache_flush(); eet_clearcache(); EINA_LIST_FOREACH(_elm_win_list, l, obj) { Evas *e = evas_object_evas_get(obj); evas_image_cache_flush(e); evas_font_cache_flush(e); // this is up for debate if we should dump as well // evas_render_dump(e); } } EAPI Eina_Bool elm_object_focus_get(const Evas_Object *obj) { EINA_SAFETY_ON_NULL_RETURN_VAL(obj, EINA_FALSE); return elm_widget_focus_get(obj); } EAPI void elm_object_focus_set(Evas_Object *obj, Eina_Bool focus) { EINA_SAFETY_ON_NULL_RETURN(obj); if (elm_widget_is(obj)) { if (focus == elm_widget_focus_get(obj)) return; // ugly, but, special case for inlined windows if (efl_isa(obj, EFL_UI_WIN_CLASS)) { Evas_Object *inlined = elm_win_inlined_image_object_get(obj); if (inlined) { evas_object_focus_set(inlined, focus); return; } } if (focus) elm_widget_focus_cycle(obj, ELM_FOCUS_NEXT); else elm_widget_focused_object_clear(obj); } else { evas_object_focus_set(obj, focus); } } EAPI void elm_object_focus_allow_set(Evas_Object *obj, Eina_Bool enable) { EINA_SAFETY_ON_NULL_RETURN(obj); elm_widget_can_focus_set(obj, enable); } EAPI Eina_Bool elm_object_focus_allow_get(const Evas_Object *obj) { EINA_SAFETY_ON_NULL_RETURN_VAL(obj, EINA_FALSE); return (elm_widget_can_focus_get(obj)) || (elm_widget_child_can_focus_get(obj)); } EAPI void elm_object_focus_custom_chain_set(Evas_Object *obj, Eina_List *objs) { EINA_SAFETY_ON_NULL_RETURN(obj); elm_widget_focus_custom_chain_set(obj, objs); } EAPI void elm_object_focus_custom_chain_unset(Evas_Object *obj) { EINA_SAFETY_ON_NULL_RETURN(obj); elm_widget_focus_custom_chain_unset(obj); } EAPI const Eina_List * elm_object_focus_custom_chain_get(const Evas_Object *obj) { EINA_SAFETY_ON_NULL_RETURN_VAL(obj, NULL); return elm_widget_focus_custom_chain_get(obj); } EAPI void elm_object_focus_custom_chain_append(Evas_Object *obj, Evas_Object *child, Evas_Object *relative_child) { EINA_SAFETY_ON_NULL_RETURN(obj); elm_widget_focus_custom_chain_append(obj, child, relative_child); } EAPI void elm_object_focus_custom_chain_prepend(Evas_Object *obj, Evas_Object *child, Evas_Object *relative_child) { EINA_SAFETY_ON_NULL_RETURN(obj); elm_widget_focus_custom_chain_prepend(obj, child, relative_child); } EINA_DEPRECATED EAPI void elm_object_focus_cycle(Evas_Object *obj, Elm_Focus_Direction dir) { elm_object_focus_next(obj, dir); } EAPI void elm_object_focus_next(Evas_Object *obj, Elm_Focus_Direction dir) { EINA_SAFETY_ON_NULL_RETURN(obj); elm_widget_focus_cycle(obj, dir); } EAPI Evas_Object * elm_object_focus_next_object_get(const Evas_Object *obj, Elm_Focus_Direction dir) { EINA_SAFETY_ON_NULL_RETURN_VAL(obj, NULL); return elm_widget_focus_next_object_get(obj, dir); } EAPI void elm_object_focus_next_object_set(Evas_Object *obj, Evas_Object *next, Elm_Focus_Direction dir) { EINA_SAFETY_ON_NULL_RETURN(obj); elm_widget_focus_next_object_set(obj, next, dir); } EAPI Elm_Object_Item * elm_object_focus_next_item_get(const Evas_Object *obj, Elm_Focus_Direction dir) { EINA_SAFETY_ON_NULL_RETURN_VAL(obj, NULL); return elm_widget_focus_next_item_get(obj, dir); } EAPI void elm_object_focus_next_item_set(Evas_Object *obj, Elm_Object_Item *next_item, Elm_Focus_Direction dir) { EINA_SAFETY_ON_NULL_RETURN(obj); elm_widget_focus_next_item_set(obj, next_item, dir); } EAPI Evas_Object * elm_object_focused_object_get(const Evas_Object *obj) { EINA_SAFETY_ON_NULL_RETURN_VAL(obj, NULL); return elm_widget_focused_object_get(obj); } EAPI void elm_object_tree_focus_allow_set(Evas_Object *obj, Eina_Bool tree_focusable) { EINA_SAFETY_ON_NULL_RETURN(obj); elm_widget_tree_unfocusable_set(obj, !tree_focusable); } EAPI Eina_Bool elm_object_tree_focus_allow_get(const Evas_Object *obj) { EINA_SAFETY_ON_NULL_RETURN_VAL(obj, EINA_FALSE); return !elm_widget_tree_unfocusable_get(obj); } EAPI void elm_object_focus_move_policy_set(Evas_Object *obj, Elm_Focus_Move_Policy policy) { EINA_SAFETY_ON_NULL_RETURN(obj); elm_widget_focus_move_policy_set(obj, policy); } EAPI Elm_Focus_Move_Policy elm_object_focus_move_policy_get(const Evas_Object *obj) { EINA_SAFETY_ON_NULL_RETURN_VAL(obj, EINA_FALSE); return elm_widget_focus_move_policy_get(obj); } EAPI Eina_Bool elm_object_focus_move_policy_automatic_get(const Evas_Object *obj) { EINA_SAFETY_ON_NULL_RETURN_VAL(obj, EINA_FALSE); return elm_widget_focus_move_policy_automatic_get(obj); } EAPI void elm_object_focus_move_policy_automatic_set(Evas_Object *obj, Eina_Bool automatic) { EINA_SAFETY_ON_NULL_RETURN(obj); elm_widget_focus_move_policy_automatic_set(obj, automatic); } EAPI void elm_object_scroll_hold_push(Evas_Object *obj) { EINA_SAFETY_ON_NULL_RETURN(obj); elm_widget_scroll_hold_push(obj); } EAPI void elm_object_scroll_hold_pop(Evas_Object *obj) { EINA_SAFETY_ON_NULL_RETURN(obj); elm_widget_scroll_hold_pop(obj); } EAPI int elm_object_scroll_hold_get(const Evas_Object *obj) { EINA_SAFETY_ON_NULL_RETURN_VAL(obj, 0); return elm_widget_scroll_hold_get(obj); } EAPI void elm_object_scroll_freeze_push(Evas_Object *obj) { EINA_SAFETY_ON_NULL_RETURN(obj); elm_widget_scroll_freeze_push(obj); } EAPI void elm_object_scroll_freeze_pop(Evas_Object *obj) { EINA_SAFETY_ON_NULL_RETURN(obj); elm_widget_scroll_freeze_pop(obj); } EAPI int elm_object_scroll_freeze_get(const Evas_Object *obj) { EINA_SAFETY_ON_NULL_RETURN_VAL(obj, 0); return elm_widget_scroll_freeze_get(obj); } EAPI void elm_object_scroll_lock_x_set(Evas_Object *obj, Eina_Bool lock) { EINA_SAFETY_ON_NULL_RETURN(obj); elm_widget_drag_lock_x_set(obj, lock); } EAPI void elm_object_scroll_lock_y_set(Evas_Object *obj, Eina_Bool lock) { EINA_SAFETY_ON_NULL_RETURN(obj); elm_widget_drag_lock_y_set(obj, lock); } EAPI Eina_Bool elm_object_scroll_lock_x_get(const Evas_Object *obj) { EINA_SAFETY_ON_NULL_RETURN_VAL(obj, EINA_FALSE); return elm_widget_drag_lock_x_get(obj); } EAPI Eina_Bool elm_object_scroll_lock_y_get(const Evas_Object *obj) { EINA_SAFETY_ON_NULL_RETURN_VAL(obj, EINA_FALSE); return elm_widget_drag_lock_y_get(obj); } EAPI void elm_object_scroll_item_loop_enabled_set(Evas_Object *obj, Eina_Bool enable) { EINA_SAFETY_ON_NULL_RETURN(obj); elm_widget_item_loop_enabled_set(obj, enable); } EAPI Eina_Bool elm_object_scroll_item_loop_enabled_get(const Evas_Object *obj) { EINA_SAFETY_ON_NULL_RETURN_VAL(obj, EINA_FALSE); return elm_widget_item_loop_enabled_get(obj); } EAPI Eina_Bool elm_object_widget_check(const Evas_Object *obj) { EINA_SAFETY_ON_NULL_RETURN_VAL(obj, EINA_FALSE); return elm_widget_is(obj); } EAPI Evas_Object * elm_object_parent_widget_get(const Evas_Object *obj) { EINA_SAFETY_ON_NULL_RETURN_VAL(obj, NULL); return elm_widget_parent_widget_get(obj); } EAPI Evas_Object * elm_object_top_widget_get(const Evas_Object *obj) { EINA_SAFETY_ON_NULL_RETURN_VAL(obj, NULL); return elm_widget_top_get(obj); } EAPI const char * elm_object_widget_type_get(const Evas_Object *obj) { EINA_SAFETY_ON_NULL_RETURN_VAL(obj, NULL); return elm_widget_type_get(obj); } EAPI void elm_object_signal_emit(Evas_Object *obj, const char *emission, const char *source) { EINA_SAFETY_ON_NULL_RETURN(obj); elm_widget_signal_emit(obj, emission, source); } EAPI void elm_object_signal_callback_add(Evas_Object *obj, const char *emission, const char *source, Edje_Signal_Cb func, void *data) { EINA_SAFETY_ON_NULL_RETURN(obj); EINA_SAFETY_ON_NULL_RETURN(func); elm_widget_signal_callback_add(obj, emission, source, func, data); } EAPI void * elm_object_signal_callback_del(Evas_Object *obj, const char *emission, const char *source, Edje_Signal_Cb func) { EINA_SAFETY_ON_NULL_RETURN_VAL(obj, NULL); EINA_SAFETY_ON_NULL_RETURN_VAL(func, NULL); return elm_widget_signal_callback_del(obj, emission, source, func); } EAPI void elm_object_event_callback_add(Evas_Object *obj, Elm_Event_Cb func, const void *data) { EINA_SAFETY_ON_NULL_RETURN(obj); EINA_SAFETY_ON_NULL_RETURN(func); elm_widget_event_callback_add(obj, func, data); } EAPI void * elm_object_event_callback_del(Evas_Object *obj, Elm_Event_Cb func, const void *data) { EINA_SAFETY_ON_NULL_RETURN_VAL(obj, NULL); EINA_SAFETY_ON_NULL_RETURN_VAL(func, NULL); return elm_widget_event_callback_del(obj, func, data); } EAPI void elm_object_tree_dump(const Evas_Object *top) { #ifdef ELM_DEBUG elm_widget_tree_dump(top); #else (void)top; return; #endif } EAPI void elm_object_tree_dot_dump(const Evas_Object *top, const char *file) { #ifdef ELM_DEBUG FILE *f = fopen(file, "wb"); elm_widget_tree_dot_dump(top, f); fclose(f); #else (void)top; (void)file; return; #endif } EAPI void elm_coords_finger_size_adjust(int times_w, Evas_Coord *w, int times_h, Evas_Coord *h) { if ((w) && (*w < (elm_config_finger_size_get() * times_w))) *w = elm_config_finger_size_get() * times_w; if ((h) && (*h < (elm_config_finger_size_get() * times_h))) *h = elm_config_finger_size_get() * times_h; } EAPI void elm_object_access_info_set(Evas_Object *obj, const char *txt) { elm_widget_access_info_set(obj, txt); } EAPI const char * elm_object_access_info_get(Evas_Object *obj) { return elm_widget_access_info_get(obj); } EAPI Evas_Object * elm_object_name_find(const Evas_Object *obj, const char *name, int recurse) { return elm_widget_name_find(obj, name, recurse); } EAPI void elm_object_orientation_mode_disabled_set(Evas_Object *obj, Eina_Bool disabled) { elm_widget_orientation_mode_disabled_set(obj, disabled); } EAPI Eina_Bool elm_object_orientation_mode_disabled_get(const Evas_Object *obj) { return elm_widget_orientation_mode_disabled_get(obj); } EAPI Elm_Object_Item * elm_object_focused_item_get(const Evas_Object *obj) { EINA_SAFETY_ON_NULL_RETURN_VAL(obj, NULL); return elm_widget_focused_item_get(obj); } EAPI void elm_object_focus_region_show_mode_set(Evas_Object *obj, Elm_Focus_Region_Show_Mode mode) { elm_widget_focus_region_show_mode_set(obj, mode); } EAPI Elm_Focus_Region_Show_Mode elm_object_focus_region_show_mode_get(const Evas_Object *obj) { return elm_widget_focus_region_show_mode_get(obj); } diff --git a/src/lib/elementary/elm_scroller.c b/src/lib/elementary/elm_scroller.c index 12739a3839..22a7b855b9 100644 --- a/src/lib/elementary/elm_scroller.c +++ b/src/lib/elementary/elm_scroller.c @@ -1,1476 +1,1476 @@ #ifdef HAVE_CONFIG_H # include "elementary_config.h" #endif #define ELM_INTERFACE_ATSPI_ACCESSIBLE_PROTECTED #define ELM_INTERFACE_ATSPI_WIDGET_ACTION_PROTECTED #include #include "elm_priv.h" #include "elm_interface_scrollable.h" #include "elm_widget_layout.h" #include "elm_widget_scroller.h" #include "elm_scroller_internal_part.eo.h" #include "elm_part_helper.h" #define MY_CLASS ELM_SCROLLER_CLASS #define MY_CLASS_NAME "Elm_Scroller" #define MY_CLASS_NAME_LEGACY "elm_scroller" #define ELM_PRIV_SCROLLER_SIGNALS(cmd) \ cmd(SIG_SCROLL, "scroll", "") \ cmd(SIG_SCROLL_LEFT, "scroll,left", "") \ cmd(SIG_SCROLL_RIGHT, "scroll,right", "") \ cmd(SIG_SCROLL_UP, "scroll,up", "") \ cmd(SIG_SCROLL_DOWN, "scroll,down", "") \ cmd(SIG_SCROLL_ANIM_START, "scroll,anim,start", "") \ cmd(SIG_SCROLL_ANIM_STOP, "scroll,anim,stop", "") \ cmd(SIG_SCROLL_DRAG_START, "scroll,drag,start", "") \ cmd(SIG_SCROLL_DRAG_STOP, "scroll,drag,stop", "") \ cmd(SIG_EDGE_LEFT, "edge,left", "") \ cmd(SIG_EDGE_RIGHT, "edge,right", "") \ cmd(SIG_EDGE_TOP, "edge,top", "") \ cmd(SIG_EDGE_BOTTOM, "edge,bottom", "") \ cmd(SIG_VBAR_DRAG, "vbar,drag", "") \ cmd(SIG_VBAR_PRESS, "vbar,press", "") \ cmd(SIG_VBAR_UNPRESS, "vbar,unpress", "") \ cmd(SIG_HBAR_DRAG, "hbar,drag", "") \ cmd(SIG_HBAR_PRESS, "hbar,press", "") \ cmd(SIG_HBAR_UNPRESS, "hbar,unpress", "") \ cmd(SIG_SCROLL_PAGE_CHANGE, "scroll,page,changed", "") \ ELM_PRIV_SCROLLER_SIGNALS(ELM_PRIV_STATIC_VARIABLE_DECLARE); static const Evas_Smart_Cb_Description _smart_callbacks[] = { ELM_PRIV_SCROLLER_SIGNALS(ELM_PRIV_SMART_CALLBACKS_DESC) {SIG_LAYOUT_FOCUSED, ""}, /**< handled by elm_layout */ {SIG_LAYOUT_UNFOCUSED, ""}, /**< handled by elm_layout */ {NULL, NULL} }; #undef ELM_PRIV_SCROLLER_SIGNALS static Eina_Bool _key_action_move(Evas_Object *obj, const char *params); static const Elm_Action key_actions[] = { {"move", _key_action_move}, {NULL, NULL} }; static void _elm_scroller_proxy_set(Evas_Object *obj, Elm_Scroller_Data *sd, Evas_Object *proxy) { Evas_Coord h_pagesize, v_pagesize; Evas_Coord cw = 0, ch = 0; Evas_Object *content = sd->content; if (!content) return; elm_interface_scrollable_paging_get(obj, NULL, NULL, &h_pagesize, &v_pagesize); elm_interface_scrollable_content_size_get(obj, &cw, &ch); /* Since Proxy has the texture size limitation problem, we set a key value for evas works in some hackish way to avoid this problem. This hackish code should be removed once evas supports a mechanism like a virtual texture. */ evas_object_image_fill_set(proxy, 0, 0, cw, ch); evas_object_size_hint_min_set(proxy, h_pagesize, v_pagesize); evas_object_image_source_clip_set(proxy, EINA_FALSE); evas_object_image_source_set(proxy, content); evas_object_show(proxy); } //describe position of rect2 relative to rect1 // 1 = top outside // 2 = left outside // 4 = bottom outside // 8 = right outside static char _intersect_direction(Eina_Rectangle *rect1, Eina_Rectangle *rect2) { char ret = 0; if (rect1->y > rect2->y) ret |= 1; if (rect1->x > rect2->x) ret |= 2; if (rect1->y + rect1->h < rect2->y + rect2->h) ret |= 4; if (rect1->x + rect1->w < rect2->x + rect2->w) ret |= 8; return ret; } static Eina_Bool _key_action_move(Evas_Object *obj, const char *params) { ELM_SCROLLER_DATA_GET(obj, sd); const char *dir = params; Evas_Coord x = 0; Evas_Coord y = 0; Evas_Coord v_x = 0; Evas_Coord v_y = 0; Evas_Coord v_w = 0; Evas_Coord v_h = 0; Evas_Coord max_x = 0; Evas_Coord max_y = 0; Evas_Coord page_x = 0; Evas_Coord page_y = 0; Evas_Coord step_x = 0; Evas_Coord step_y = 0; Evas_Coord pagesize_h = 0, pagesize_v = 0; Evas_Coord pagenumber_h = 0, pagenumber_v = 0; elm_interface_scrollable_content_pos_get(obj, &x, &y); elm_interface_scrollable_step_size_get(obj, &step_x, &step_y); elm_interface_scrollable_page_size_get(obj, &page_x, &page_y); elm_interface_scrollable_content_viewport_geometry_get (obj, &v_x, &v_y, &v_w, &v_h); evas_object_geometry_get(sd->content, NULL, NULL, &max_x, &max_y); { Efl_Ui_Focus_Object *focused; Eina_Rectangle focused_geom, viewport; focused = efl_ui_focus_manager_focused(obj); if (focused && (!strcmp(dir, "next") || !strcmp(dir, "prior"))) return EINA_FALSE; if (focused && (!strcmp(dir, "left") || !strcmp(dir, "right") || !strcmp(dir, "up") || !strcmp(dir, "down"))) { char relative; evas_object_geometry_get(focused, &focused_geom.x, &focused_geom.y, &focused_geom.w, &focused_geom.h); elm_interface_scrollable_content_viewport_geometry_get(obj, &viewport.x, &viewport.y, &viewport.w, &viewport.h); relative = _intersect_direction(&viewport, &focused_geom); //now precisly check if the direction is also lapping out if ((!strcmp(dir, "up") && !(relative & 1)) || (!strcmp(dir, "left") && !(relative & 2)) || (!strcmp(dir, "down") && !(relative & 4)) || (!strcmp(dir, "right") && !(relative & 8))) { //focus will handle that return EINA_FALSE; } } } elm_interface_scrollable_paging_get(obj, NULL, NULL, &pagesize_h, &pagesize_v); elm_interface_scrollable_current_page_get(obj, &pagenumber_h, &pagenumber_v); if (!strcmp(dir, "left")) { if ((x <= 0) && (!sd->loop_h)) return EINA_FALSE; if (pagesize_h) { elm_interface_scrollable_page_bring_in(obj, pagenumber_h - 1, pagenumber_v); return EINA_TRUE; } else x -= step_x; } else if (!strcmp(dir, "right")) { if ((x >= (max_x - v_w)) && (!sd->loop_h)) return EINA_FALSE; if (pagesize_h) { elm_interface_scrollable_page_bring_in(obj, pagenumber_h + 1, pagenumber_v); return EINA_TRUE; } else x += step_x; } else if (!strcmp(dir, "up")) { if ((y <= 0) && (!sd->loop_v)) return EINA_FALSE; if (pagesize_v) { elm_interface_scrollable_page_bring_in(obj, pagenumber_h, pagenumber_v - 1); return EINA_TRUE; } else y -= step_y; } else if (!strcmp(dir, "down")) { if ((y >= (max_y - v_h)) && (!sd->loop_v)) return EINA_FALSE; if (pagesize_v) { elm_interface_scrollable_page_bring_in(obj, pagenumber_h, pagenumber_v + 1); return EINA_TRUE; } else y += step_y; } else if (!strcmp(dir, "first")) { y = 0; } else if (!strcmp(dir, "last")) { y = max_y - v_h; } else if (!strcmp(dir, "prior")) { if (pagesize_v) { elm_interface_scrollable_page_bring_in(obj, pagenumber_h, pagenumber_v - 1); return EINA_TRUE; } else { if (page_y < 0) y -= -(page_y * v_h) / 100; else y -= page_y; } } else if (!strcmp(dir, "next")) { if (pagesize_v) { elm_interface_scrollable_page_bring_in(obj, pagenumber_h, pagenumber_v + 1); return EINA_TRUE; } else { if (page_y < 0) y += -(page_y * v_h) / 100; else y += page_y; } } else return EINA_FALSE; elm_interface_scrollable_content_pos_set(obj, x, y, EINA_TRUE); return EINA_TRUE; } EOLIAN static Eina_Bool _elm_scroller_elm_widget_widget_event(Eo *obj, Elm_Scroller_Data *sd EINA_UNUSED, Evas_Object *src, Evas_Callback_Type type, void *event_info) { (void) src; Evas_Event_Key_Down *ev = event_info; if (type != EVAS_CALLBACK_KEY_DOWN) return EINA_FALSE; if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return EINA_FALSE; if (!_elm_config_key_binding_call(obj, MY_CLASS_NAME, ev, key_actions)) return EINA_FALSE; ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD; return EINA_TRUE; } EOLIAN static Eina_Bool _elm_scroller_elm_widget_activate(Eo *obj, Elm_Scroller_Data *_pd EINA_UNUSED, Elm_Activate act) { Evas_Coord x = 0; Evas_Coord y = 0; Evas_Coord v_w = 0; Evas_Coord v_h = 0; Evas_Coord page_x = 0; Evas_Coord page_y = 0; if (elm_widget_disabled_get(obj)) return EINA_FALSE; if (act == ELM_ACTIVATE_DEFAULT) return EINA_FALSE; elm_interface_scrollable_content_pos_get(obj, &x, &y); elm_interface_scrollable_page_size_get(obj, &page_x, &page_y); elm_interface_scrollable_content_viewport_geometry_get (obj, NULL, NULL, &v_w, &v_h); if (act == ELM_ACTIVATE_UP) { if (page_y < 0) y -= -(page_y * v_h) / 100; else y -= page_y; } else if (act == ELM_ACTIVATE_DOWN) { if (page_y < 0) y += -(page_y * v_h) / 100; else y += page_y; } else if (act == ELM_ACTIVATE_LEFT) { if (page_x < 0) x -= -(page_x * v_w) / 100; else x -= page_x; } else if (act == ELM_ACTIVATE_RIGHT) { if (page_x < 0) x += -(page_x * v_w) / 100; else x += page_x; } elm_interface_scrollable_content_pos_set(obj, x, y, EINA_TRUE); return EINA_TRUE; } EOLIAN static void _elm_scroller_elm_layout_sizing_eval(Eo *obj, Elm_Scroller_Data *sd) { Evas_Coord vw = 0, vh = 0, minw = 0, minh = 0, maxw = 0, maxh = 0, w, h, vmw, vmh; Evas_Coord h_pagesize, v_pagesize; double xw = 0.0, yw = 0.0; int i; ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd); if (sd->content) { efl_gfx_size_hint_combined_min_get(sd->content, &minw, &minh); evas_object_size_hint_max_get(sd->content, &maxw, &maxh); evas_object_size_hint_weight_get(sd->content, &xw, &yw); } elm_interface_scrollable_content_viewport_geometry_get (obj, NULL, NULL, &vw, &vh); if (xw > 0.0) { if ((minw > 0) && (vw < minw)) vw = minw; else if ((maxw > 0) && (vw > maxw)) vw = maxw; } else if (minw > 0) vw = minw; if (yw > 0.0) { if ((minh > 0) && (vh < minh)) vh = minh; else if ((maxh > 0) && (vh > maxh)) vh = maxh; } else if (minh > 0) vh = minh; if (sd->content) evas_object_resize(sd->content, vw, vh); if (sd->contents) evas_object_resize(sd->contents, vw, vh); for (i = 0 ; i < 3 ; i++) { if (!sd->proxy_content[i]) continue; elm_interface_scrollable_paging_get((Eo *)obj, NULL, NULL, &h_pagesize, &v_pagesize); evas_object_image_fill_set(sd->proxy_content[i], 0, 0, vw, vh); evas_object_size_hint_min_set(sd->proxy_content[i], h_pagesize, v_pagesize); } w = -1; h = -1; vmw = vmh = 0; edje_object_size_min_calc(wd->resize_obj, &vmw, &vmh); if (sd->min_w) w = vmw + minw; if (sd->min_h) h = vmh + minh; evas_object_size_hint_max_get(obj, &maxw, &maxh); if ((maxw > 0) && (w > maxw)) w = maxw; if ((maxh > 0) && (h > maxh)) h = maxh; evas_object_size_hint_min_set(obj, w, h); } static void _mirrored_set(Evas_Object *obj, Eina_Bool mirrored) { elm_interface_scrollable_mirrored_set(obj, mirrored); } EOLIAN static Elm_Theme_Apply _elm_scroller_elm_widget_theme_apply(Eo *obj, Elm_Scroller_Data *sd EINA_UNUSED) { Elm_Theme_Apply int_ret = ELM_THEME_APPLY_FAILED; int_ret = elm_obj_widget_theme_apply(efl_super(obj, MY_CLASS)); if (!int_ret) return ELM_THEME_APPLY_FAILED; _mirrored_set(obj, efl_ui_mirrored_get(obj)); elm_layout_sizing_eval(obj); return int_ret; } EOLIAN static Eina_Bool _elm_scroller_elm_widget_focus_next_manager_is(Eo *obj EINA_UNUSED, Elm_Scroller_Data *_pd EINA_UNUSED) { return EINA_TRUE; } EOLIAN static Eina_Bool _elm_scroller_elm_widget_focus_next(Eo *obj EINA_UNUSED, Elm_Scroller_Data *sd, Elm_Focus_Direction dir, Evas_Object **next, Elm_Object_Item **next_item) { Evas_Object *cur; if (!sd->content) return EINA_FALSE; cur = sd->content; /* access */ if (_elm_config->access_mode) { if ((elm_widget_can_focus_get(cur)) || (elm_widget_child_can_focus_get(cur))) { return elm_widget_focus_next_get(cur, dir, next, next_item); } return EINA_FALSE; } /* Try focus cycle in subitem */ if ((elm_widget_can_focus_get(cur)) || (elm_widget_child_can_focus_get(cur))) { Eina_Bool ret = EINA_FALSE; ret = elm_widget_focus_next_get(cur, dir, next, next_item); if (*next) { Evas_Coord x = 0, y = 0; Evas_Coord v_w = 0, v_h = 0; Evas_Coord c_x = 0, c_y = 0; Evas_Coord f_x = 0, f_y = 0, f_w = 0, f_h = 0; Evas_Coord l_x = 0, l_y = 0, l_w = 0, l_h = 0; Evas_Coord step_x = 0, step_y = 0; elm_interface_scrollable_content_pos_get(obj, &x, &y); elm_interface_scrollable_step_size_get(obj, &step_x, &step_y); elm_interface_scrollable_content_viewport_geometry_get (obj, NULL, NULL, &v_w, &v_h); evas_object_geometry_get(sd->content, &c_x, &c_y, NULL, NULL); evas_object_geometry_get(*next, &f_x, &f_y, &f_w, &f_h); l_x = f_x - c_x - step_x; l_y = f_y - c_y - step_y; l_w = f_w + (step_x * 2); l_h = f_h + (step_y * 2); if (!ret || ELM_RECTS_INTERSECT(x, y, v_w, v_h, l_x, l_y, l_w, l_h)) return ret; } } if (!(elm_widget_can_focus_get(obj)) && !(elm_widget_can_focus_get(cur))) return EINA_FALSE; /* Return */ *next = (Evas_Object *)obj; return !elm_widget_focus_get(obj); } EOLIAN static Eina_Bool _elm_scroller_elm_widget_focus_direction_manager_is(Eo *obj EINA_UNUSED, Elm_Scroller_Data *_pd EINA_UNUSED) { return EINA_TRUE; } EOLIAN static Eina_Bool _elm_scroller_elm_widget_focus_direction(Eo *obj, Elm_Scroller_Data *sd, const Evas_Object *base, double degree, Evas_Object **direction, Elm_Object_Item **direction_item, double *weight) { Evas_Object *cur; if (!sd->content) return EINA_FALSE; cur = sd->content; /* access */ if (_elm_config->access_mode) { if ((elm_widget_can_focus_get(cur)) || (elm_widget_child_can_focus_get(cur))) { return elm_widget_focus_direction_get(cur, base, degree, direction, direction_item, weight); } return EINA_FALSE; } /* Try focus cycle in subitem */ if ((elm_widget_can_focus_get(cur)) || (elm_widget_child_can_focus_get(cur))) { Eina_Bool ret = EINA_FALSE; Evas_Coord x = 0, y = 0; Evas_Coord v_w = 0, v_h = 0; Evas_Coord c_x = 0, c_y = 0; Evas_Coord f_x = 0, f_y = 0, f_w = 0, f_h = 0; Evas_Coord l_x = 0, l_y = 0, l_w = 0, l_h = 0; Evas_Coord step_x = 0, step_y = 0; ret = elm_widget_focus_direction_get(cur, base, degree, direction, direction_item, weight); elm_interface_scrollable_content_pos_get(obj, &x, &y); elm_interface_scrollable_step_size_get(obj, &step_x, &step_y); elm_interface_scrollable_content_viewport_geometry_get (obj, NULL, NULL, &v_w, &v_h); evas_object_geometry_get(sd->content, &c_x, &c_y, NULL, NULL); evas_object_geometry_get(*direction, &f_x, &f_y, &f_w, &f_h); l_x = f_x - c_x - step_x; l_y = f_y - c_y - step_y; l_w = f_w + (step_x * 2); l_h = f_h + (step_y * 2); if (!ret || ELM_RECTS_INTERSECT(x, y, v_w, v_h, l_x, l_y, l_w, l_h)) return ret; } /* Return */ *direction = (Evas_Object *)obj; return !elm_widget_focus_get(obj); } static void _show_region_hook(void *data, Evas_Object *content_obj) { Evas_Coord x, y, w, h; elm_widget_show_region_get(content_obj, &x, &y, &w, &h); elm_interface_scrollable_content_region_show(data, x, y, w, h); } static void _changed_size_hints_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) { elm_layout_sizing_eval(data); } EOLIAN static Eina_Bool _elm_scroller_elm_widget_sub_object_del(Eo *obj, Elm_Scroller_Data *sd, Evas_Object *sobj) { Eina_Bool int_ret = EINA_FALSE; int_ret = elm_obj_widget_sub_object_del(efl_super(obj, MY_CLASS), sobj); if (!int_ret) return EINA_FALSE; if (sobj == sd->content) { if (elm_widget_is(sobj)) elm_widget_on_show_region_hook_set(sd->content, NULL, NULL); sd->content = NULL; } return EINA_TRUE; } static void _resize_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) { elm_layout_sizing_eval(data); } static void _edge_left_cb(Evas_Object *obj, void *data EINA_UNUSED) { efl_event_callback_legacy_call(obj, ELM_SCROLLER_EVENT_EDGE_LEFT, NULL); } static void _edge_right_cb(Evas_Object *obj, void *data EINA_UNUSED) { efl_event_callback_legacy_call(obj, ELM_SCROLLER_EVENT_EDGE_RIGHT, NULL); } static void _edge_top_cb(Evas_Object *obj, void *data EINA_UNUSED) { efl_event_callback_legacy_call(obj, ELM_SCROLLER_EVENT_EDGE_TOP, NULL); } static void _edge_bottom_cb(Evas_Object *obj, void *data EINA_UNUSED) { efl_event_callback_legacy_call(obj, ELM_SCROLLER_EVENT_EDGE_BOTTOM, NULL); } static void _scroll_cb(Evas_Object *obj, void *data EINA_UNUSED) { efl_event_callback_legacy_call (obj, EFL_UI_EVENT_SCROLL, NULL); } static void _scroll_left_cb(Evas_Object *obj, void *data EINA_UNUSED) { efl_event_callback_legacy_call(obj, ELM_SCROLLER_EVENT_SCROLL_LEFT, NULL); } static void _scroll_right_cb(Evas_Object *obj, void *data EINA_UNUSED) { efl_event_callback_legacy_call(obj, ELM_SCROLLER_EVENT_SCROLL_RIGHT, NULL); } static void _scroll_up_cb(Evas_Object *obj, void *data EINA_UNUSED) { efl_event_callback_legacy_call(obj, ELM_SCROLLER_EVENT_SCROLL_UP, NULL); } static void _scroll_down_cb(Evas_Object *obj, void *data EINA_UNUSED) { efl_event_callback_legacy_call(obj, ELM_SCROLLER_EVENT_SCROLL_DOWN, NULL); } static void _scroll_anim_start_cb(Evas_Object *obj, void *data EINA_UNUSED) { efl_event_callback_legacy_call (obj, EFL_UI_EVENT_SCROLL_ANIM_START, NULL); } static void _scroll_anim_stop_cb(Evas_Object *obj, void *data EINA_UNUSED) { efl_event_callback_legacy_call (obj, EFL_UI_EVENT_SCROLL_ANIM_STOP, NULL); } static void _scroll_drag_start_cb(Evas_Object *obj, void *data EINA_UNUSED) { efl_event_callback_legacy_call (obj, EFL_UI_EVENT_SCROLL_DRAG_START, NULL); } static void _scroll_drag_stop_cb(Evas_Object *obj, void *data EINA_UNUSED) { efl_event_callback_legacy_call (obj, EFL_UI_EVENT_SCROLL_DRAG_STOP, NULL); } static void _vbar_drag_cb(Evas_Object *obj, void *data EINA_UNUSED) { efl_event_callback_legacy_call(obj, ELM_SCROLLER_EVENT_VBAR_DRAG, NULL); } static void _vbar_press_cb(Evas_Object *obj, void *data EINA_UNUSED) { efl_event_callback_legacy_call(obj, ELM_SCROLLER_EVENT_VBAR_PRESS, NULL); } static void _vbar_unpress_cb(Evas_Object *obj, void *data EINA_UNUSED) { efl_event_callback_legacy_call(obj, ELM_SCROLLER_EVENT_VBAR_UNPRESS, NULL); } static void _hbar_drag_cb(Evas_Object *obj, void *data EINA_UNUSED) { efl_event_callback_legacy_call(obj, ELM_SCROLLER_EVENT_HBAR_DRAG, NULL); } static void _hbar_press_cb(Evas_Object *obj, void *data EINA_UNUSED) { efl_event_callback_legacy_call(obj, ELM_SCROLLER_EVENT_HBAR_PRESS, NULL); } static void _hbar_unpress_cb(Evas_Object *obj, void *data EINA_UNUSED) { efl_event_callback_legacy_call(obj, ELM_SCROLLER_EVENT_HBAR_UNPRESS, NULL); } static void _page_change_cb(Evas_Object *obj, void *data EINA_UNUSED) { efl_event_callback_legacy_call (obj, ELM_SCROLLER_EVENT_SCROLL_PAGE_CHANGED, NULL); } static void _loop_content_set(Evas_Object *obj, Elm_Scroller_Data *sd, Evas_Object *content) { if (!sd->contents) { sd->contents = elm_layout_add(obj); evas_object_smart_member_add(sd->contents, obj); if (!elm_layout_theme_set(sd->contents, "scroller", "contents", elm_widget_style_get(obj))) CRI("Failed to set layout!"); evas_object_size_hint_weight_set(sd->contents, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); evas_object_size_hint_align_set(sd->contents, EVAS_HINT_FILL, EVAS_HINT_FILL); elm_widget_sub_object_add(obj, sd->contents); elm_widget_on_show_region_hook_set(sd->contents, _show_region_hook, obj); - elm_widget_mirrored_automatic_set(sd->contents, EINA_FALSE); + efl_ui_mirrored_automatic_set(sd->contents, EINA_FALSE); efl_ui_mirrored_set(sd->contents, EINA_FALSE); } elm_object_part_content_set(sd->contents, "elm.swallow.content", content); sd->content = content; if (sd->loop_h) { if (!sd->proxy_content[0]) sd->proxy_content[0] = evas_object_image_add(evas_object_evas_get(sd->contents)); _elm_scroller_proxy_set(obj, sd, sd->proxy_content[0]); elm_object_part_content_set(sd->contents, "elm.swallow.content_r", sd->proxy_content[0]); } if (sd->loop_v) { if (!sd->proxy_content[1]) sd->proxy_content[1] = evas_object_image_add(evas_object_evas_get(sd->contents)); _elm_scroller_proxy_set(obj, sd, sd->proxy_content[1]); elm_object_part_content_set(sd->contents, "elm.swallow.content_b", sd->proxy_content[1]); } if (sd->loop_h && sd->loop_v) { if (!sd->proxy_content[2]) sd->proxy_content[2] = evas_object_image_add(evas_object_evas_get(sd->contents)); _elm_scroller_proxy_set(obj, sd, sd->proxy_content[2]); elm_object_part_content_set(sd->contents, "elm.swallow.content_rb", sd->proxy_content[2]); } } static Eina_Bool _elm_scroller_content_set(Eo *obj, Elm_Scroller_Data *sd, const char *part, Evas_Object *content) { if (part && strcmp(part, "default")) { return efl_content_set(efl_part(efl_super(obj, MY_CLASS), part), content); } if (sd->content == content) return EINA_TRUE; evas_object_del(sd->content); sd->content = content; if (content) { if (elm_widget_is(content)) elm_widget_on_show_region_hook_set(content, _show_region_hook, obj); elm_widget_sub_object_add(obj, content); if (sd->loop_h || sd->loop_v) { _loop_content_set(obj, sd, content); if(sd->contents) content = sd->contents; } elm_interface_scrollable_content_set(obj, content); } else { int i; for (i = 0; i < 3; i ++) { if (!sd->proxy_content[i]) continue; evas_object_del(sd->proxy_content[i]); sd->proxy_content[i] = NULL; } } elm_layout_sizing_eval(obj); return EINA_TRUE; } static Evas_Object* _elm_scroller_content_get(Eo *obj, Elm_Scroller_Data *sd, const char *part) { if (part && strcmp(part, "default")) { return efl_content_get(efl_part(efl_super(obj, MY_CLASS), part)); } return sd->content; } static Evas_Object* _elm_scroller_content_unset(Eo *obj, Elm_Scroller_Data *sd, const char *part) { Evas_Object *ret = NULL; if (part && strcmp(part, "default")) { return efl_content_unset(efl_part(efl_super(obj, MY_CLASS), part)); } if (!sd->content) return NULL; ret = sd->content; if (sd->loop_h || sd->loop_v) _elm_widget_sub_object_redirect_to_top(obj, sd->contents); else _elm_widget_sub_object_redirect_to_top(obj, sd->content); elm_interface_scrollable_content_set(obj, NULL); sd->content = NULL; return ret; } static void _elm_scroller_content_min_limit_cb(Evas_Object *obj, Eina_Bool w, Eina_Bool h) { ELM_SCROLLER_DATA_GET(obj, sd); sd->min_w = !!w; sd->min_h = !!h; elm_layout_sizing_eval(obj); } static void _elm_scroller_content_viewport_resize_cb(Evas_Object *obj, Evas_Coord w EINA_UNUSED, Evas_Coord h EINA_UNUSED) { elm_layout_sizing_eval(obj); } EOLIAN static void _elm_scroller_efl_canvas_group_group_add(Eo *obj, Elm_Scroller_Data *priv) { ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd); Evas_Coord minw, minh; efl_canvas_group_add(efl_super(obj, MY_CLASS)); elm_widget_sub_object_parent_add(obj); elm_widget_can_focus_set(obj, EINA_TRUE); if (!elm_layout_theme_set (obj, "scroller", "base", elm_widget_style_get(obj))) CRI("Failed to set layout!"); priv->hit_rect = evas_object_rectangle_add(evas_object_evas_get(obj)); evas_object_smart_member_add(priv->hit_rect, obj); elm_widget_sub_object_add(obj, priv->hit_rect); evas_object_color_set(priv->hit_rect, 0, 0, 0, 0); evas_object_show(priv->hit_rect); evas_object_repeat_events_set(priv->hit_rect, EINA_TRUE); elm_interface_scrollable_objects_set(obj, wd->resize_obj, priv->hit_rect); evas_object_event_callback_add (obj, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _changed_size_hints_cb, obj); edje_object_size_min_calc(wd->resize_obj, &minw, &minh); evas_object_size_hint_min_set(obj, minw, minh); evas_object_event_callback_add(obj, EVAS_CALLBACK_RESIZE, _resize_cb, obj); _mirrored_set(obj, efl_ui_mirrored_get(obj)); elm_interface_scrollable_edge_left_cb_set(obj, _edge_left_cb); elm_interface_scrollable_edge_right_cb_set(obj, _edge_right_cb); elm_interface_scrollable_edge_top_cb_set(obj, _edge_top_cb); elm_interface_scrollable_edge_bottom_cb_set(obj, _edge_bottom_cb); elm_interface_scrollable_scroll_cb_set(obj, _scroll_cb); elm_interface_scrollable_scroll_left_cb_set(obj, _scroll_left_cb); elm_interface_scrollable_scroll_right_cb_set(obj, _scroll_right_cb); elm_interface_scrollable_scroll_up_cb_set(obj, _scroll_up_cb); elm_interface_scrollable_scroll_down_cb_set(obj, _scroll_down_cb); elm_interface_scrollable_animate_start_cb_set(obj, _scroll_anim_start_cb); elm_interface_scrollable_animate_stop_cb_set(obj, _scroll_anim_stop_cb); elm_interface_scrollable_drag_start_cb_set(obj, _scroll_drag_start_cb); elm_interface_scrollable_drag_stop_cb_set(obj, _scroll_drag_stop_cb); elm_interface_scrollable_vbar_drag_cb_set(obj, _vbar_drag_cb); elm_interface_scrollable_vbar_press_cb_set(obj, _vbar_press_cb); elm_interface_scrollable_vbar_unpress_cb_set(obj, _vbar_unpress_cb); elm_interface_scrollable_hbar_drag_cb_set(obj, _hbar_drag_cb); elm_interface_scrollable_hbar_press_cb_set(obj, _hbar_press_cb); elm_interface_scrollable_hbar_unpress_cb_set(obj, _hbar_unpress_cb); elm_interface_scrollable_page_change_cb_set(obj, _page_change_cb); elm_interface_scrollable_content_min_limit_cb_set (obj, _elm_scroller_content_min_limit_cb); elm_interface_scrollable_content_viewport_resize_cb_set (obj, _elm_scroller_content_viewport_resize_cb); } EOLIAN static void _elm_scroller_efl_gfx_position_set(Eo *obj, Elm_Scroller_Data *sd, Evas_Coord x, Evas_Coord y) { if (_evas_object_intercept_call(obj, EVAS_OBJECT_INTERCEPT_CB_MOVE, 0, x, y)) return; efl_gfx_position_set(efl_super(obj, MY_CLASS), x, y); evas_object_move(sd->hit_rect, x, y); } EOLIAN static void _elm_scroller_efl_gfx_size_set(Eo *obj, Elm_Scroller_Data *sd, Evas_Coord w, Evas_Coord h) { if (_evas_object_intercept_call(obj, EVAS_OBJECT_INTERCEPT_CB_RESIZE, 0, w, h)) return; efl_gfx_size_set(efl_super(obj, MY_CLASS), w, h); evas_object_resize(sd->hit_rect, w, h); } EOLIAN static void _elm_scroller_efl_canvas_group_group_member_add(Eo *obj, Elm_Scroller_Data *sd, Evas_Object *member) { efl_canvas_group_member_add(efl_super(obj, MY_CLASS), member); if (sd->hit_rect) evas_object_raise(sd->hit_rect); } EAPI Evas_Object * elm_scroller_add(Evas_Object *parent) { EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL); Evas_Object *obj = efl_add(MY_CLASS, parent); return obj; } EOLIAN static Eo * _elm_scroller_efl_object_constructor(Eo *obj, Elm_Scroller_Data *_pd EINA_UNUSED) { obj = efl_constructor(efl_super(obj, MY_CLASS)); efl_canvas_object_type_set(obj, MY_CLASS_NAME_LEGACY); evas_object_smart_callbacks_descriptions_set(obj, _smart_callbacks); elm_interface_atspi_accessible_role_set(obj, ELM_ATSPI_ROLE_SCROLL_PANE); return obj; } /* deprecated */ EOLIAN static void _elm_scroller_custom_widget_base_theme_set(Eo *obj, Elm_Scroller_Data *_pd EINA_UNUSED, const char *klass, const char *group) { ELM_LAYOUT_DATA_GET(obj, ld); EINA_SAFETY_ON_NULL_RETURN(klass); EINA_SAFETY_ON_NULL_RETURN(group); if (eina_stringshare_replace(&(ld->klass), klass) || eina_stringshare_replace(&(ld->group), group)) elm_obj_widget_theme_apply(obj); } EAPI void elm_scroller_content_min_limit(Evas_Object *obj, Eina_Bool w, Eina_Bool h) { ELM_SCROLLABLE_CHECK(obj); elm_interface_scrollable_content_min_limit(obj, w, h); } EAPI void elm_scroller_region_show(Evas_Object *obj, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h) { ELM_SCROLLABLE_CHECK(obj); elm_interface_scrollable_content_region_show(obj, x, y, w, h); } EAPI void elm_scroller_policy_set(Evas_Object *obj, Elm_Scroller_Policy policy_h, Elm_Scroller_Policy policy_v) { ELM_SCROLLABLE_CHECK(obj); elm_interface_scrollable_policy_set(obj, policy_h, policy_v); } EOLIAN static void _elm_scroller_elm_interface_scrollable_policy_set(Eo *obj, Elm_Scroller_Data *sd EINA_UNUSED, Elm_Scroller_Policy policy_h, Elm_Scroller_Policy policy_v) { if ((policy_h >= ELM_SCROLLER_POLICY_LAST) || (policy_v >= ELM_SCROLLER_POLICY_LAST)) return; elm_interface_scrollable_policy_set(efl_super(obj, MY_CLASS), policy_h, policy_v); } EAPI void elm_scroller_policy_get(const Evas_Object *obj, Elm_Scroller_Policy *policy_h, Elm_Scroller_Policy *policy_v) { ELM_SCROLLABLE_CHECK(obj); elm_interface_scrollable_policy_get((Eo *) obj, policy_h, policy_v); } EAPI void elm_scroller_single_direction_set(Evas_Object *obj, Elm_Scroller_Single_Direction single_dir) { ELM_SCROLLABLE_CHECK(obj); elm_interface_scrollable_single_direction_set(obj, single_dir); } EOLIAN static void _elm_scroller_elm_interface_scrollable_single_direction_set(Eo *obj, Elm_Scroller_Data *sd EINA_UNUSED, Elm_Scroller_Single_Direction single_dir) { if (single_dir >= ELM_SCROLLER_SINGLE_DIRECTION_LAST) return; elm_interface_scrollable_single_direction_set(efl_super(obj, MY_CLASS), single_dir); } EAPI Elm_Scroller_Single_Direction elm_scroller_single_direction_get(const Evas_Object *obj) { ELM_SCROLLABLE_CHECK(obj, ELM_SCROLLER_SINGLE_DIRECTION_NONE); Elm_Scroller_Single_Direction single_dir = ELM_SCROLLER_SINGLE_DIRECTION_NONE; single_dir = elm_interface_scrollable_single_direction_get((Eo *) obj); return single_dir; } EOLIAN static Elm_Scroller_Single_Direction _elm_scroller_elm_interface_scrollable_single_direction_get(Eo *obj, Elm_Scroller_Data *sd EINA_UNUSED) { return elm_interface_scrollable_single_direction_get(efl_super(obj, MY_CLASS)); } EAPI void elm_scroller_region_get(const Evas_Object *obj, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h) { ELM_SCROLLABLE_CHECK(obj); elm_interface_scrollable_content_region_get((Eo *) obj, x, y, w, h); } EAPI void elm_scroller_child_size_get(const Evas_Object *obj, Evas_Coord *w, Evas_Coord *h) { ELM_SCROLLABLE_CHECK(obj); elm_interface_scrollable_content_size_get((Eo *) obj, w, h); } EAPI void elm_scroller_page_snap_set(Evas_Object *obj, Eina_Bool page_snap_h, Eina_Bool page_snap_v) { ELM_SCROLLABLE_CHECK(obj); elm_interface_scrollable_page_snap_allow_set (obj, page_snap_h, page_snap_v); } EAPI void elm_scroller_page_snap_get(const Evas_Object *obj, Eina_Bool *page_snap_h, Eina_Bool *page_snap_v) { ELM_SCROLLABLE_CHECK(obj); elm_interface_scrollable_page_snap_allow_get ((Eo *) obj, page_snap_h, page_snap_v); } EAPI void elm_scroller_bounce_set(Evas_Object *obj, Eina_Bool h_bounce, Eina_Bool v_bounce) { ELM_SCROLLABLE_CHECK(obj); elm_interface_scrollable_bounce_allow_set(obj, h_bounce, v_bounce); } EAPI void elm_scroller_bounce_get(const Evas_Object *obj, Eina_Bool *h_bounce, Eina_Bool *v_bounce) { ELM_SCROLLABLE_CHECK(obj); elm_interface_scrollable_bounce_allow_get((Eo *) obj, h_bounce, v_bounce); } EAPI void elm_scroller_page_relative_set(Evas_Object *obj, double h_pagerel, double v_pagerel) { ELM_SCROLLABLE_CHECK(obj); elm_interface_scrollable_page_relative_set((Eo *)obj, h_pagerel, v_pagerel); } EAPI void elm_scroller_page_relative_get(const Evas_Object *obj, double *h_pagerel, double *v_pagerel) { ELM_SCROLLABLE_CHECK(obj); elm_interface_scrollable_paging_get((Eo *)obj, h_pagerel, v_pagerel, NULL, NULL); } EAPI void elm_scroller_page_size_set(Evas_Object *obj, Evas_Coord h_pagesize, Evas_Coord v_pagesize) { ELM_SCROLLABLE_CHECK(obj); elm_interface_scrollable_page_size_set(obj, h_pagesize, v_pagesize); } EOLIAN static void _elm_scroller_elm_interface_scrollable_page_size_set(Eo *obj, Elm_Scroller_Data *sd EINA_UNUSED, Evas_Coord h_pagesize, Evas_Coord v_pagesize) { double pagerel_h = 0.0, pagerel_v = 0.0; elm_interface_scrollable_paging_get(obj, &pagerel_h, &pagerel_v, NULL, NULL); elm_interface_scrollable_paging_set(obj, pagerel_h, pagerel_v, h_pagesize, v_pagesize); } EAPI void elm_scroller_page_size_get(const Evas_Object *obj, Evas_Coord *h_pagesize, Evas_Coord *v_pagesize) { ELM_SCROLLABLE_CHECK(obj); elm_interface_scrollable_paging_get((Eo *)obj, NULL, NULL, h_pagesize, v_pagesize); } EOLIAN static void _elm_scroller_page_scroll_limit_set(const Eo *obj, Elm_Scroller_Data *_pd EINA_UNUSED, int page_limit_h, int page_limit_v) { if (page_limit_h < 1) page_limit_h = 9999; if (page_limit_v < 1) page_limit_v = 9999; elm_interface_scrollable_page_scroll_limit_set ((Eo *) obj, page_limit_h, page_limit_v); } EOLIAN static void _elm_scroller_page_scroll_limit_get(const Eo *obj, Elm_Scroller_Data *_pd EINA_UNUSED, int *page_limit_h, int *page_limit_v) { elm_interface_scrollable_page_scroll_limit_get (obj, page_limit_h, page_limit_v); } EAPI void elm_scroller_current_page_get(const Evas_Object *obj, int *h_pagenumber, int *v_pagenumber) { ELM_SCROLLABLE_CHECK(obj); elm_interface_scrollable_current_page_get((Eo *) obj, h_pagenumber, v_pagenumber); } EAPI void elm_scroller_last_page_get(const Evas_Object *obj, int *h_pagenumber, int *v_pagenumber) { ELM_SCROLLABLE_CHECK(obj); elm_interface_scrollable_last_page_get((Eo *) obj, h_pagenumber, v_pagenumber); } EAPI void elm_scroller_page_show(Evas_Object *obj, int h_pagenumber, int v_pagenumber) { ELM_SCROLLABLE_CHECK(obj); elm_interface_scrollable_page_show(obj, h_pagenumber, v_pagenumber); } EAPI void elm_scroller_page_bring_in(Evas_Object *obj, int h_pagenumber, int v_pagenumber) { ELM_SCROLLABLE_CHECK(obj); elm_interface_scrollable_page_bring_in(obj, h_pagenumber, v_pagenumber); } EAPI void elm_scroller_region_bring_in(Evas_Object *obj, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h) { ELM_SCROLLABLE_CHECK(obj); elm_interface_scrollable_region_bring_in(obj, x, y, w, h); } EAPI void elm_scroller_gravity_set(Evas_Object *obj, double x, double y) { ELM_SCROLLABLE_CHECK(obj); elm_interface_scrollable_gravity_set(obj, x, y); } EAPI void elm_scroller_gravity_get(const Evas_Object *obj, double *x, double *y) { ELM_SCROLLABLE_CHECK(obj); elm_interface_scrollable_gravity_get((Eo *) obj, x, y); } EAPI void elm_scroller_movement_block_set(Evas_Object *obj, Elm_Scroller_Movement_Block block) { ELM_SCROLLABLE_CHECK(obj); elm_interface_scrollable_movement_block_set(obj, block); } EAPI Elm_Scroller_Movement_Block elm_scroller_movement_block_get(const Evas_Object *obj) { Elm_Scroller_Movement_Block block = ELM_SCROLLER_MOVEMENT_NO_BLOCK; ELM_SCROLLABLE_CHECK(obj, ELM_SCROLLER_MOVEMENT_NO_BLOCK); block = elm_interface_scrollable_movement_block_get((Eo *) obj); return block; } EAPI void elm_scroller_step_size_set(Evas_Object *obj, Evas_Coord x, Evas_Coord y) { ELM_SCROLLABLE_CHECK(obj); elm_interface_scrollable_step_size_set(obj, x, y); } EAPI void elm_scroller_step_size_get(const Evas_Object *obj, Evas_Coord *x, Evas_Coord *y) { ELM_SCROLLABLE_CHECK(obj); elm_interface_scrollable_step_size_get((Eo *) obj, x, y); } EAPI void elm_scroller_loop_set(Evas_Object *obj, Eina_Bool loop_h, Eina_Bool loop_v) { ELM_SCROLLABLE_CHECK(obj); ELM_SCROLLER_DATA_GET(obj, sd); int i; if (sd->loop_h == loop_h && sd->loop_v == loop_v) return; sd->loop_h = loop_h; sd->loop_v = loop_v; elm_interface_scrollable_loop_set(obj, loop_h, loop_v); if (sd->content) { if (sd->loop_h || sd->loop_v) { elm_interface_scrollable_content_set(obj, NULL); _loop_content_set(obj, sd, sd->content); if (sd->contents) { elm_interface_scrollable_content_set(obj, sd->contents); elm_widget_sub_object_add(obj, sd->contents); elm_widget_on_show_region_hook_set(sd->contents, _show_region_hook, obj); } } else { for (i = 0 ; i < 3 ; i++) { if (sd->proxy_content[i]) { evas_object_del(sd->proxy_content[i]); sd->proxy_content[i]= NULL; } } } } elm_layout_sizing_eval(obj); } EAPI void elm_scroller_loop_get(const Evas_Object *obj, Eina_Bool *loop_h, Eina_Bool *loop_v) { ELM_SCROLLABLE_CHECK(obj); elm_interface_scrollable_loop_get(obj, loop_h, loop_v); } EAPI void elm_scroller_wheel_disabled_set(Evas_Object *obj, Eina_Bool disabled) { ELM_SCROLLABLE_CHECK(obj); elm_interface_scrollable_wheel_disabled_set((Eo *)obj, disabled); } EAPI Eina_Bool elm_scroller_wheel_disabled_get(const Evas_Object *obj) { ELM_SCROLLABLE_CHECK(obj, EINA_FALSE); return elm_interface_scrollable_wheel_disabled_get((Eo *) obj); } EAPI void elm_scroller_propagate_events_set(Evas_Object *obj, Eina_Bool propagation) { evas_object_propagate_events_set(elm_layout_edje_get(obj), propagation); } EAPI Eina_Bool elm_scroller_propagate_events_get(const Evas_Object *obj) { return evas_object_propagate_events_get(elm_layout_edje_get(obj)); } static void _elm_scroller_class_constructor(Efl_Class *klass) { evas_smart_legacy_type_register(MY_CLASS_NAME_LEGACY, klass); } EOLIAN static Eina_Bool _elm_scroller_elm_widget_focus_register(Eo *obj, Elm_Scroller_Data *pd EINA_UNUSED, Efl_Ui_Focus_Manager *manager, Efl_Ui_Focus_Object *logical, Eina_Bool full EINA_UNUSED) { //undepended from logical or not we always reigster as full with ourself as redirect efl_ui_focus_manager_register_logical(manager, obj, logical, obj); return EINA_FALSE; } EOLIAN const Elm_Atspi_Action * _elm_scroller_elm_interface_atspi_widget_action_elm_actions_get(Eo *obj EINA_UNUSED, Elm_Scroller_Data *pd EINA_UNUSED) { static Elm_Atspi_Action atspi_actions[] = { { "move,prior", "move", "prior", _key_action_move}, { "move,next", "move", "next", _key_action_move}, { "move,left", "move", "left", _key_action_move}, { "move,right", "move", "right", _key_action_move}, { "move,up", "move", "up", _key_action_move}, { "move,down", "move", "down", _key_action_move}, { "move,first", "move", "first", _key_action_move}, { "move,last", "move", "last", _key_action_move}, { NULL, NULL, NULL, NULL } }; return &atspi_actions[0]; } /* Efl.Part begin */ ELM_PART_OVERRIDE(elm_scroller, ELM_SCROLLER, ELM_LAYOUT, Elm_Scroller_Data, Elm_Part_Data) ELM_PART_OVERRIDE_CONTENT_SET(elm_scroller, ELM_SCROLLER, ELM_LAYOUT, Elm_Scroller_Data, Elm_Part_Data) ELM_PART_OVERRIDE_CONTENT_GET(elm_scroller, ELM_SCROLLER, ELM_LAYOUT, Elm_Scroller_Data, Elm_Part_Data) ELM_PART_OVERRIDE_CONTENT_UNSET(elm_scroller, ELM_SCROLLER, ELM_LAYOUT, Elm_Scroller_Data, Elm_Part_Data) #include "elm_scroller_internal_part.eo.c" /* Efl.Part end */ /* Internal EO APIs and hidden overrides */ #define ELM_SCROLLER_EXTRA_OPS \ EFL_CANVAS_GROUP_ADD_OPS(elm_scroller) #include "elm_scroller.eo.c" diff --git a/src/lib/elementary/elm_widget.c b/src/lib/elementary/elm_widget.c index b3b88d23c7..b83bf2772b 100644 --- a/src/lib/elementary/elm_widget.c +++ b/src/lib/elementary/elm_widget.c @@ -1,6528 +1,6528 @@ #ifdef HAVE_CONFIG_H # include "elementary_config.h" #endif #define ELM_INTERFACE_ATSPI_ACCESSIBLE_PROTECTED #define ELM_INTERFACE_ATSPI_COMPONENT_PROTECTED #define ELM_WIDGET_PROTECTED #define ELM_WIDGET_ITEM_PROTECTED #define EFL_CANVAS_OBJECT_BETA #define EFL_INPUT_EVENT_PROTECTED #include #include "elm_priv.h" #include "elm_widget_container.h" #include "elm_interface_scrollable.h" /* FIXME: remove this when we don't rely on evas event structs anymore */ #define EFL_INTERNAL_UNSTABLE #include "interfaces/efl_common_internal.h" #define MY_CLASS ELM_WIDGET_CLASS #define MY_CLASS_NAME "Elm_Widget" #define MY_CLASS_NAME_LEGACY "elm_widget" #define ELM_WIDGET_DATA_GET(o, wd) \ Elm_Widget_Smart_Data *wd = efl_data_scope_get(o, MY_CLASS) #define API_ENTRY \ Elm_Widget_Smart_Data *sd = NULL; \ if (!_elm_widget_is(obj) || \ (!(sd = efl_data_scope_get(obj, MY_CLASS)))) #define INTERNAL_ENTRY \ ELM_WIDGET_DATA_GET(obj, sd); \ if (!sd) return #define ELM_WIDGET_FOCUS_GET(obj) \ (efl_isa(obj, ELM_WIDGET_CLASS) && \ ((_elm_access_auto_highlight_get()) ? (elm_widget_highlight_get(obj)) : \ (elm_widget_focus_get(obj)))) const char SIG_WIDGET_FOCUSED[] = "focused"; const char SIG_WIDGET_UNFOCUSED[] = "unfocused"; const char SIG_WIDGET_LANG_CHANGED[] = "language,changed"; const char SIG_WIDGET_ACCESS_CHANGED[] = "access,changed"; typedef struct _Elm_Event_Cb_Data Elm_Event_Cb_Data; typedef struct _Elm_Label_Data Elm_Label_Data; typedef struct _Elm_Translate_String_Data Elm_Translate_String_Data; struct _Elm_Event_Cb_Data { Elm_Event_Cb func; const void *data; }; struct _Elm_Label_Data { const char *part; const char *text; }; struct _Elm_Translate_String_Data { EINA_INLIST; Eina_Stringshare *id; Eina_Stringshare *domain; Eina_Stringshare *string; Eina_Bool preset : 1; }; /* local subsystem globals */ static unsigned int focus_order = 0; static inline Eina_Bool _elm_widget_is(const Evas_Object *obj) { return efl_isa(obj, MY_CLASS); } static inline Eina_Bool _is_focusable(Evas_Object *obj) { API_ENTRY return EINA_FALSE; return sd->can_focus || (sd->child_can_focus); } static inline Eina_Bool _is_focused(Evas_Object *obj) { API_ENTRY return EINA_FALSE; return sd->focused; } static inline Eina_Bool _elm_scrollable_is(const Evas_Object *obj) { INTERNAL_ENTRY EINA_FALSE; return efl_isa(obj, ELM_INTERFACE_SCROLLABLE_MIXIN); } static void elm_widget_disabled_internal(Eo *obj, Eina_Bool disabled); static void _on_sub_obj_del(void *data, const Efl_Event *event); static void _on_sub_obj_hide(void *data, const Efl_Event *event); static void _propagate_event(void *data, const Efl_Event *event); EFL_CALLBACKS_ARRAY_DEFINE(elm_widget_subitems_callbacks, { EFL_EVENT_DEL, _on_sub_obj_del }, { EFL_GFX_EVENT_HIDE, _on_sub_obj_hide }); EFL_CALLBACKS_ARRAY_DEFINE(efl_subitems_callbacks, { EFL_EVENT_DEL, _on_sub_obj_del }); EFL_CALLBACKS_ARRAY_DEFINE(focus_callbacks, { EFL_EVENT_KEY_DOWN, _propagate_event }, { EFL_EVENT_KEY_UP, _propagate_event }, { EFL_EVENT_POINTER_WHEEL, _propagate_event }); static inline void _callbacks_add(Eo *widget, void *data) { if (_elm_widget_is(widget)) { efl_event_callback_array_add(widget, elm_widget_subitems_callbacks(), data); } else { efl_event_callback_array_add(widget, efl_subitems_callbacks(), data); } } static inline void _callbacks_del(Eo *widget, void *data) { if (_elm_widget_is(widget)) { efl_event_callback_array_del(widget, elm_widget_subitems_callbacks(), data); } else { efl_event_callback_array_del(widget, efl_subitems_callbacks(), data); } } void _elm_widget_item_highlight_in_theme(Evas_Object *obj, Elm_Object_Item *eo_it) { const char *str; if (!eo_it) return; if (efl_isa(eo_it, ELM_WIDGET_ITEM_CLASS)) { Elm_Widget_Item_Data *it = efl_data_scope_get(eo_it, ELM_WIDGET_ITEM_CLASS); if (efl_isa(it->view, ELM_LAYOUT_CLASS)) str = edje_object_data_get(elm_layout_edje_get(it->view), "focus_highlight"); else str = edje_object_data_get(it->view, "focus_highlight"); } else str = edje_object_data_get(((Elm_Widget_Item_Data *)eo_it)->view, "focus_highlight"); if ((str) && (!strcmp(str, "on"))) elm_widget_highlight_in_theme_set(obj, EINA_TRUE); else elm_widget_highlight_in_theme_set(obj, EINA_FALSE); } void _elm_widget_focus_highlight_start(const Evas_Object *obj) { Evas_Object *top = elm_widget_top_get(obj); if (top && efl_isa(top, EFL_UI_WIN_CLASS)) _elm_win_focus_highlight_start(top); } Evas_Object * _elm_widget_focus_highlight_object_get(const Evas_Object *obj) { Evas_Object *top = elm_widget_top_get(obj); if (top && efl_isa(top, EFL_UI_WIN_CLASS)) return _elm_win_focus_highlight_object_get(top); return NULL; } EAPI Eina_Bool elm_widget_focus_highlight_enabled_get(const Evas_Object *obj) { const Evas_Object *win = elm_widget_top_get(obj); if (win && efl_isa(win, EFL_UI_WIN_CLASS)) return elm_win_focus_highlight_enabled_get(win); return EINA_FALSE; } static Eina_Bool _tree_unfocusable(Eo *obj) { Elm_Widget *wid = obj; do { ELM_WIDGET_DATA_GET(wid, wid_pd); if (wid_pd->tree_unfocusable) return EINA_TRUE; } while((wid = elm_widget_parent_widget_get(wid))); return EINA_FALSE; } static void _full_eval(Eo *obj, Elm_Widget_Smart_Data *pd); static void _manager_changed_cb(void *data, const Efl_Event *event EINA_UNUSED) { ELM_WIDGET_DATA_GET(data, pd); _full_eval(data, pd); } static Efl_Ui_Focus_Object* _focus_manager_eval(Eo *obj, Elm_Widget_Smart_Data *pd) { Evas_Object *provider = NULL; Evas_Object *parent; Efl_Ui_Focus_Manager *new = NULL, *old = NULL; parent = elm_widget_parent_get(obj); if (efl_isa(parent, EFL_UI_FOCUS_MANAGER_CLASS)) { new = parent; } else { new = efl_ui_focus_user_manager_get(parent); provider = parent; } if (new != pd->manager.manager ) { old = pd->manager.manager; if (pd->manager.provider) efl_event_callback_del(pd->manager.provider, EFL_UI_FOCUS_USER_EVENT_MANAGER_CHANGED, _manager_changed_cb, obj); pd->manager.manager = new; pd->manager.provider = provider; if (pd->manager.provider) efl_event_callback_add(pd->manager.provider, EFL_UI_FOCUS_USER_EVENT_MANAGER_CHANGED, _manager_changed_cb, obj); } return old; } EOLIAN static Eina_Bool _elm_widget_focus_register(Eo *obj, Elm_Widget_Smart_Data *pd EINA_UNUSED, Efl_Ui_Focus_Manager *manager, Efl_Ui_Focus_Object *logical, Eina_Bool full) { if (full) efl_ui_focus_manager_register(manager, obj, logical, NULL); else efl_ui_focus_manager_register_logical(manager, obj, logical, NULL); return full; } static void _focus_state_eval(Eo *obj, Elm_Widget_Smart_Data *pd) { Eina_Bool should = EINA_FALSE; Eina_Bool want_full = EINA_FALSE; Efl_Ui_Focus_Manager *manager = efl_ui_focus_user_manager_get(obj); //there are two reasons to be registered, the child count is bigger than 0, or the widget is flagged to be able to handle focus if (pd->can_focus) { should = EINA_TRUE; //can focus can be overridden by the following properties if (pd->disabled) should = EINA_FALSE; if (_tree_unfocusable(obj)) should = EINA_FALSE; if (!evas_object_visible_get(obj)) should = EINA_FALSE; if (should) want_full = EINA_TRUE; } if (!should && pd->logical.child_count > 0) should = EINA_TRUE; if ( //check if we have changed the manager (pd->focus.manager != manager && should) || //check if we are already registered but in a different state (pd->focus.manager && should && want_full == pd->focus.logical) ) { efl_ui_focus_manager_unregister(pd->focus.manager, obj); pd->focus.manager = NULL; } //now register in the manager if (should && !pd->focus.manager) { if (manager != obj) { pd->focus.manager = manager; if (!pd->logical.parent) return; pd->focus.logical = !elm_obj_widget_focus_register(obj, pd->focus.manager, pd->logical.parent, want_full); } } else if (!should && pd->focus.manager) { efl_ui_focus_manager_unregister(pd->focus.manager, obj); pd->focus.manager = NULL; } } static Efl_Ui_Focus_Object* _logical_parent_eval(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *pd) { Elm_Widget *parent; parent = pd->parent_obj; if (pd->logical.parent != parent) { Efl_Ui_Focus_Object *old = NULL; //update old logical parent; if (pd->logical.parent) { ELM_WIDGET_DATA_GET(pd->logical.parent, logical_wd); if (!logical_wd) { ERR("Widget parent has the wrong type!"); return NULL; } logical_wd->logical.child_count --; old = pd->logical.parent; if (pd->logical.parent) efl_weak_unref(&pd->logical.parent); pd->logical.parent = NULL; } if (parent) { ELM_WIDGET_DATA_GET(parent, logical_wd); if (!logical_wd) { ERR("Widget parent has the wrong type!"); return NULL; } logical_wd->logical.child_count ++; pd->logical.parent = parent; efl_weak_ref(&pd->logical.parent); } return old; } return NULL; } static void _full_eval(Eo *obj, Elm_Widget_Smart_Data *pd) { Efl_Ui_Focus_Object *old_parent, *old_manager; old_parent = _logical_parent_eval(obj, pd); old_manager = _focus_manager_eval(obj, pd); if (old_parent) { //emit signal and focus eval old and new ELM_WIDGET_DATA_GET(old_parent, old_pd); _focus_state_eval(old_parent, old_pd); } if (pd->logical.parent) { ELM_WIDGET_DATA_GET(pd->logical.parent, new_pd); _focus_state_eval(pd->logical.parent, new_pd); } if (old_parent != pd->logical.parent) { efl_event_callback_call(obj, EFL_UI_FOCUS_USER_EVENT_LOGICAL_CHANGED, old_parent); } if (old_manager != pd->manager.manager) { //emit signal efl_event_callback_call(obj, EFL_UI_FOCUS_USER_EVENT_MANAGER_CHANGED, old_manager); } _focus_state_eval(obj, pd); } /** * @internal * * Resets the mirrored mode from the system mirror mode for widgets that are in * automatic mirroring mode. This function does not call elm_widget_theme. * * @param obj The widget. * @param mirrored EINA_TRUE to set mirrored mode. EINA_FALSE to unset. */ static void _elm_widget_mirrored_reload(Evas_Object *obj) { API_ENTRY return; Eina_Bool mirrored = elm_config_mirrored_get(); - if (elm_widget_mirrored_automatic_get(obj) && (sd->is_mirrored != mirrored)) + if (efl_ui_mirrored_automatic_get(obj) && (sd->is_mirrored != mirrored)) { sd->is_mirrored = mirrored; } } EOLIAN static Eina_Bool _elm_widget_on_focus_region(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED, Evas_Coord *x EINA_UNUSED, Evas_Coord *y EINA_UNUSED, Evas_Coord *w EINA_UNUSED, Evas_Coord *h EINA_UNUSED) { DBG("The %s widget does not implement the \"on_focus_region\" function.", efl_class_name_get(efl_class_get(obj))); return EINA_FALSE; } static void _parents_focus(Evas_Object *obj) { for (; obj; obj = elm_widget_parent_get(obj)) { INTERNAL_ENTRY; if (sd->focused) return; sd->focused = 1; } } static void _parents_unfocus(Evas_Object *obj) { for (; obj; obj = elm_widget_parent_get(obj)) { INTERNAL_ENTRY; if (!sd->focused) return; sd->focused = 0; } } static void _on_sub_obj_hide(void *data EINA_UNUSED, const Efl_Event *event) { elm_widget_focus_hide_handle(event->object); } static void _on_sub_obj_del(void *data, const Efl_Event *event) { ELM_WIDGET_DATA_GET_OR_RETURN(data, sd); if (_elm_widget_is(event->object)) { if (_is_focused(event->object)) _parents_unfocus(sd->obj); } if (event->object == sd->resize_obj) { /* already dels sub object */ elm_widget_resize_object_set(sd->obj, NULL, EINA_TRUE); } else if (event->object == sd->hover_obj) { sd->hover_obj = NULL; } else { if (!elm_widget_sub_object_del(sd->obj, event->object)) ERR("failed to remove sub object %p from %p\n", event->object, sd->obj); } } static const Evas_Smart_Cb_Description _smart_callbacks[] = { {SIG_WIDGET_FOCUSED, ""}, {SIG_WIDGET_UNFOCUSED, ""}, {SIG_WIDGET_LANG_CHANGED, ""}, {SIG_WIDGET_ACCESS_CHANGED, ""}, {NULL, NULL} }; static void _obj_mouse_down(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info) { Evas_Object *top; ELM_WIDGET_DATA_GET(data, sd); Evas_Event_Mouse_Down *ev = event_info; if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return; top = elm_widget_top_get(data); if (top && efl_isa(top, EFL_UI_WIN_CLASS)) _elm_win_focus_auto_hide(top); sd->still_in = EINA_TRUE; } static void _obj_mouse_move(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info) { ELM_WIDGET_DATA_GET(data, sd); Evas_Event_Mouse_Move *ev = event_info; if (!sd->still_in) return; if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) sd->still_in = EINA_FALSE; else { Evas_Coord x, y, w, h; evas_object_geometry_get(obj, &x, &y, &w, &h); if (ELM_RECTS_POINT_OUT(x, y, w, h, ev->cur.canvas.x, ev->cur.canvas.y)) sd->still_in = EINA_FALSE; } } static void _obj_mouse_up(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info) { ELM_WIDGET_DATA_GET(data, sd); Evas_Event_Mouse_Up *ev = event_info; if (sd->still_in && (ev->flags == EVAS_BUTTON_NONE) && (sd->focus_move_policy == ELM_FOCUS_MOVE_POLICY_CLICK)) elm_widget_focus_mouse_up_handle(obj); sd->still_in = EINA_FALSE; } static void _obj_mouse_in(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED) { ELM_WIDGET_DATA_GET(data, sd); if (sd->focus_move_policy == ELM_FOCUS_MOVE_POLICY_IN) elm_widget_focus_mouse_up_handle(obj); } EOLIAN static void _elm_widget_efl_canvas_group_group_add(Eo *obj, Elm_Widget_Smart_Data *priv) { priv->obj = obj; priv->mirrored_auto_mode = EINA_TRUE; /* will follow system locale * settings */ priv->focus_move_policy_auto_mode = EINA_TRUE; priv->focus_region_show_mode = ELM_FOCUS_REGION_SHOW_WIDGET; elm_widget_can_focus_set(obj, EINA_TRUE); priv->is_mirrored = elm_config_mirrored_get(); priv->focus_move_policy = _elm_config->focus_move_policy; evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_DOWN, _obj_mouse_down, obj); evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_MOVE, _obj_mouse_move, obj); evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_UP, _obj_mouse_up, obj); evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_IN, _obj_mouse_in, obj); } static void _if_focused_revert(Evas_Object *obj, Eina_Bool can_focus_only) { Evas_Object *top; Evas_Object *newest = NULL; unsigned int newest_focus_order = 0; INTERNAL_ENTRY; if (!sd->focused) return; if (!sd->parent_obj) return; top = elm_widget_top_get(sd->parent_obj); if (top) { newest = elm_widget_newest_focus_order_get (top, &newest_focus_order, can_focus_only); if (newest) { if (newest == top) { ELM_WIDGET_DATA_GET(newest, sd2); if (!sd2) return; if (!_is_focused(newest)) elm_widget_focus_steal(newest, NULL); else { if (sd2->resize_obj && _is_focused(sd2->resize_obj)) elm_widget_focused_object_clear(sd2->resize_obj); else { const Eina_List *l; Evas_Object *child; EINA_LIST_FOREACH(sd2->subobjs, l, child) { if (!_elm_widget_is(child)) continue; if (_is_focused(child)) { elm_widget_focused_object_clear(child); break; } } } } evas_object_focus_set(newest, EINA_TRUE); } else { elm_object_focus_set(newest, EINA_FALSE); elm_object_focus_set(newest, EINA_TRUE); } } } } EOLIAN static void _elm_widget_efl_canvas_group_group_del(Eo *obj, Elm_Widget_Smart_Data *sd) { Evas_Object *sobj; Elm_Translate_String_Data *ts; Elm_Event_Cb_Data *ecb; if (sd->hover_obj) { /* detach it from us */ _callbacks_del(sd->hover_obj, obj); sd->hover_obj = NULL; } while (sd->subobjs) { sobj = eina_list_data_get(sd->subobjs); /* let the objects clean-up themselves and get rid of this list */ if (!elm_widget_sub_object_del(obj, sobj)) { ERR("failed to remove sub object %p from %p\n", sobj, obj); sd->subobjs = eina_list_remove_list (sd->subobjs, sd->subobjs); } evas_object_del(sobj); } sd->tooltips = eina_list_free(sd->tooltips); /* should be empty anyway */ sd->cursors = eina_list_free(sd->cursors); /* should be empty anyway */ while (sd->translate_strings) { ts = EINA_INLIST_CONTAINER_GET(sd->translate_strings, Elm_Translate_String_Data); eina_stringshare_del(ts->id); eina_stringshare_del(ts->domain); eina_stringshare_del(ts->string); sd->translate_strings = eina_inlist_remove(sd->translate_strings, sd->translate_strings); free(ts); } EINA_LIST_FREE(sd->event_cb, ecb) free(ecb); eina_stringshare_del(sd->style); if (sd->theme) elm_theme_free(sd->theme); _if_focused_revert(obj, EINA_TRUE); elm_widget_focus_custom_chain_unset(obj); eina_stringshare_del(sd->access_info); eina_stringshare_del(sd->accessible_name); evas_object_smart_data_set(obj, NULL); efl_canvas_group_del(efl_super(obj, MY_CLASS)); } static void _smart_reconfigure(Elm_Widget_Smart_Data *sd) { if (sd->resize_obj) { evas_object_move(sd->resize_obj, sd->x, sd->y); evas_object_resize(sd->resize_obj, sd->w, sd->h); } if (sd->hover_obj) { evas_object_move(sd->hover_obj, sd->x, sd->y); evas_object_resize(sd->hover_obj, sd->w, sd->h); } } EOLIAN static void _elm_widget_efl_gfx_position_set(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd, Evas_Coord x, Evas_Coord y) { if (_evas_object_intercept_call(obj, EVAS_OBJECT_INTERCEPT_CB_MOVE, 0, x, y)) return; sd->x = x; sd->y = y; _smart_reconfigure(sd); efl_gfx_position_set(efl_super(obj, MY_CLASS), x, y); } EOLIAN static void _elm_widget_efl_gfx_size_set(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd, Evas_Coord w, Evas_Coord h) { if (_evas_object_intercept_call(obj, EVAS_OBJECT_INTERCEPT_CB_RESIZE, 0, w, h)) return; sd->w = w; sd->h = h; _smart_reconfigure(sd); efl_gfx_size_set(efl_super(obj, MY_CLASS), w, h); } EOLIAN static void _elm_widget_efl_gfx_visible_set(Eo *obj, Elm_Widget_Smart_Data *pd, Eina_Bool vis) { Eina_Iterator *it; Evas_Object *o; if (_evas_object_intercept_call(obj, EVAS_OBJECT_INTERCEPT_CB_VISIBLE, 0, vis)) return; efl_gfx_visible_set(efl_super(obj, MY_CLASS), vis); _focus_state_eval(obj, pd); it = evas_object_smart_iterator_new(obj); EINA_ITERATOR_FOREACH(it, o) { if (evas_object_data_get(o, "_elm_leaveme")) continue; efl_gfx_visible_set(o, vis); } eina_iterator_free(it); if (!_elm_config->atspi_mode || pd->on_destroy) return; if (vis) { elm_interface_atspi_accessible_added(obj); if (_elm_widget_onscreen_is(obj)) elm_interface_atspi_accessible_state_changed_signal_emit(obj, ELM_ATSPI_STATE_SHOWING, EINA_TRUE); } else { elm_interface_atspi_accessible_state_changed_signal_emit(obj, ELM_ATSPI_STATE_SHOWING, EINA_FALSE); } } EOLIAN static void _elm_widget_efl_gfx_color_set(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED, int r, int g, int b, int a) { Eina_Iterator *it; Evas_Object *o; if (_evas_object_intercept_call(obj, EVAS_OBJECT_INTERCEPT_CB_COLOR_SET, 0, r, g, b, a)) return; it = evas_object_smart_iterator_new(obj); EINA_ITERATOR_FOREACH(it, o) { if (evas_object_data_get(o, "_elm_leaveme")) continue; evas_object_color_set(o, r, g, b, a); } eina_iterator_free(it); } EOLIAN static void _elm_widget_efl_canvas_object_no_render_set(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED, Eina_Bool hide) { Eina_Iterator *it; Evas_Object *o; hide = !!hide; if (efl_canvas_object_no_render_get(obj) == hide) return; it = evas_object_smart_iterator_new(obj); EINA_ITERATOR_FOREACH(it, o) { if (evas_object_data_get(o, "_elm_leaveme")) continue; efl_canvas_object_no_render_set(o, hide); } eina_iterator_free(it); // bypass implementation in Efl.Canvas.Group efl_canvas_object_no_render_set(efl_super(obj, EFL_CANVAS_GROUP_CLASS), hide); } EOLIAN static void _elm_widget_efl_canvas_object_is_frame_object_set(Eo *obj, Elm_Widget_Smart_Data *pd, Eina_Bool frame) { Evas_Object *o; Eina_List *li; frame = !!frame; efl_canvas_object_is_frame_object_set(efl_super(obj, MY_CLASS), frame); EINA_LIST_FOREACH(pd->subobjs, li, o) { if (evas_object_data_get(o, "_elm_leaveme")) continue; efl_canvas_object_is_frame_object_set(o, frame); } } EOLIAN static void _elm_widget_efl_canvas_object_clip_set(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED, Evas_Object *clip) { Eina_Iterator *it; Evas_Object *o; if (_evas_object_intercept_call(obj, EVAS_OBJECT_INTERCEPT_CB_CLIP_SET, 0, clip)) return; efl_canvas_object_clip_set(efl_super(obj, MY_CLASS), clip); it = evas_object_smart_iterator_new(obj); EINA_ITERATOR_FOREACH(it, o) { if (evas_object_data_get(o, "_elm_leaveme")) continue; evas_object_clip_set(o, clip); } eina_iterator_free(it); } EOLIAN static void _elm_widget_efl_canvas_group_group_calculate(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *_pd EINA_UNUSED) { /* a NO-OP, on the base */ } EOLIAN static void _elm_widget_efl_canvas_group_group_member_add(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED, Evas_Object *child) { int r, g, b, a; efl_canvas_group_member_add(efl_super(obj, MY_CLASS), child); if (evas_object_data_get(child, "_elm_leaveme")) return; evas_object_color_get(obj, &r, &g, &b, &a); evas_object_color_set(child, r, g, b, a); efl_canvas_object_no_render_set(child, efl_canvas_object_no_render_get(obj)); evas_object_clip_set(child, evas_object_clip_get(obj)); if (evas_object_visible_get(obj)) evas_object_show(child); else evas_object_hide(child); } EOLIAN static void _elm_widget_efl_canvas_group_group_member_del(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *_pd EINA_UNUSED, Evas_Object *child) { if (!evas_object_data_get(child, "_elm_leaveme")) evas_object_clip_unset(child); efl_canvas_group_member_del(efl_super(obj, MY_CLASS), child); } // internal funcs /** * @internal * * Check if the widget has its own focus next function. * * @param obj The widget. * @return focus next function is implemented/unimplemented. * (@c EINA_TRUE = implemented/@c EINA_FALSE = unimplemented.) */ static inline Eina_Bool _elm_widget_focus_chain_manager_is(const Evas_Object *obj) { ELM_WIDGET_CHECK(obj) EINA_FALSE; Eina_Bool manager_is = EINA_FALSE; manager_is = elm_obj_widget_focus_next_manager_is((Eo *)obj); return manager_is; } static inline Eina_Bool _internal_elm_widget_focus_direction_manager_is(const Evas_Object *obj) { ELM_WIDGET_CHECK(obj) EINA_FALSE; Eina_Bool manager_is = EINA_FALSE; manager_is = elm_obj_widget_focus_direction_manager_is((Eo *)obj); return manager_is; } static void _propagate_x_drag_lock(Evas_Object *obj, int dir) { INTERNAL_ENTRY; if (sd->parent_obj) { ELM_WIDGET_DATA_GET(sd->parent_obj, sd2); if (sd2) { sd2->child_drag_x_locked += dir; _propagate_x_drag_lock(sd->parent_obj, dir); } } } static void _propagate_y_drag_lock(Evas_Object *obj, int dir) { INTERNAL_ENTRY; if (sd->parent_obj) { ELM_WIDGET_DATA_GET(sd->parent_obj, sd2); if (sd2) { sd2->child_drag_y_locked += dir; _propagate_y_drag_lock(sd->parent_obj, dir); } } } static void _propagate_event(void *data EINA_UNUSED, const Efl_Event *event) { Eo *obj = event->object; INTERNAL_ENTRY; Evas_Callback_Type type; Evas_Event_Flags *event_flags, prev_flags; union { Evas_Event_Key_Down *down; Evas_Event_Key_Up *up; Evas_Event_Mouse_Wheel *wheel; void *any; } event_info; if ((evas_focus_get(evas_object_evas_get(obj)) != elm_widget_top_get(obj)) && efl_isa(obj, EFL_UI_WIN_CLASS)) return; if (event->desc == EFL_EVENT_KEY_DOWN) { event_info.down = efl_input_legacy_info_get(event->info); EINA_SAFETY_ON_NULL_RETURN(event_info.down); type = EVAS_CALLBACK_KEY_DOWN; event_flags = &event_info.down->event_flags; } else if (event->desc == EFL_EVENT_KEY_UP) { event_info.up = efl_input_legacy_info_get(event->info); EINA_SAFETY_ON_NULL_RETURN(event_info.up); type = EVAS_CALLBACK_KEY_UP; event_flags = &event_info.up->event_flags; } else if (event->desc == EFL_EVENT_POINTER_WHEEL) { event_info.wheel = efl_input_legacy_info_get(event->info); EINA_SAFETY_ON_NULL_RETURN(event_info.wheel); type = EVAS_CALLBACK_MOUSE_WHEEL; event_flags = &event_info.wheel->event_flags; } else return; prev_flags = *event_flags; elm_widget_event_propagate(obj, type, event_info.any, event_flags); if (prev_flags != *event_flags) efl_input_event_flags_set(event->info, *event_flags); } /** * @internal * * If elm_widget_focus_region_get() returns EINA_FALSE, this function will * ignore region show action. */ EOLIAN static void _elm_widget_focus_region_show(const Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED) { Evas_Coord x, y, w, h, ox, oy; Evas_Object *o; o = elm_widget_parent_get(obj); if (!o) return; if (!elm_widget_focus_region_get(obj, &x, &y, &w, &h)) return; evas_object_geometry_get(obj, &ox, &oy, NULL, NULL); while (o) { Evas_Coord px, py; evas_object_geometry_get(o, &px, &py, NULL, NULL); if (_elm_scrollable_is(o) && !elm_widget_disabled_get(o)) { Evas_Coord sx, sy; elm_interface_scrollable_content_region_get(o, &sx, &sy, NULL, NULL); // Get the object's on_focus_region position relative to the scroller. Evas_Coord rx, ry; rx = ox + x - px + sx; ry = oy + y - py + sy; switch (_elm_config->focus_autoscroll_mode) { case ELM_FOCUS_AUTOSCROLL_MODE_SHOW: elm_interface_scrollable_content_region_show(o, rx, ry, w, h); break; case ELM_FOCUS_AUTOSCROLL_MODE_BRING_IN: elm_interface_scrollable_region_bring_in(o, rx, ry, w, h); break; default: break; } elm_widget_focus_region_get(o, &x, &y, &w, &h); evas_object_geometry_get(o, &ox, &oy, NULL, NULL); } else { x += ox - px; y += oy - py; ox = px; oy = py; } o = elm_widget_parent_get(o); } } EOLIAN static Eina_Bool _elm_widget_focus_highlight_style_set(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd, const char *style) { if (eina_stringshare_replace(&sd->focus_highlight_style, style)) return EINA_TRUE; return EINA_FALSE; } EOLIAN static const char* _elm_widget_focus_highlight_style_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd) { return sd->focus_highlight_style; } static void _parent_focus(Evas_Object *obj, Elm_Object_Item *item) { API_ENTRY return; if (sd->focused) return; Evas_Object *o = elm_widget_parent_get(obj); sd->focus_order_on_calc = EINA_TRUE; if (o) _parent_focus(o, item); if (!sd->focus_order_on_calc) return; /* we don't want to override it if by means of any of the callbacks below one gets to calculate our order first. */ focus_order++; sd->focus_order = focus_order; sd->focused = EINA_TRUE; if (sd->top_win_focused) elm_obj_widget_on_focus(obj, item); sd->focus_order_on_calc = EINA_FALSE; if (_elm_config->access_mode == ELM_ACCESS_MODE_ON) _elm_access_highlight_set(obj); } static void _elm_object_focus_chain_del_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED) { ELM_WIDGET_DATA_GET(data, sd); sd->focus_chain = eina_list_remove(sd->focus_chain, obj); } EOLIAN static void _elm_widget_widget_parent_set(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *_pd EINA_UNUSED, Evas_Object *parent EINA_UNUSED) { } EAPI Eina_Bool elm_widget_api_check(int ver) { if (ver != ELM_INTERNAL_API_VERSION) { CRI("Elementary widget api versions do not match"); return EINA_FALSE; } return EINA_TRUE; } EAPI Eina_Bool elm_widget_access(Evas_Object *obj, Eina_Bool is_access) { const Eina_List *l; Evas_Object *child; Eina_Bool ret = EINA_TRUE; API_ENTRY return EINA_FALSE; EINA_LIST_FOREACH(sd->subobjs, l, child) { if (elm_widget_is(child)) ret &= elm_widget_access(child, is_access); } elm_obj_widget_access(obj, is_access); efl_event_callback_legacy_call(obj, ELM_WIDGET_EVENT_ACCESS_CHANGED, NULL); return ret; } EOLIAN static void _elm_widget_access(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *_pd EINA_UNUSED, Eina_Bool is_access EINA_UNUSED) { } EAPI Elm_Theme_Apply elm_widget_theme(Evas_Object *obj) { const Eina_List *l; Evas_Object *child; Elm_Tooltip *tt; Elm_Cursor *cur; Elm_Theme_Apply ret = ELM_THEME_APPLY_SUCCESS; API_ENTRY return ELM_THEME_APPLY_FAILED; EINA_LIST_FOREACH(sd->subobjs, l, child) if (_elm_widget_is(child)) ret &= elm_widget_theme(child); if (sd->hover_obj) ret &= elm_widget_theme(sd->hover_obj); EINA_LIST_FOREACH(sd->tooltips, l, tt) elm_tooltip_theme(tt); EINA_LIST_FOREACH(sd->cursors, l, cur) elm_cursor_theme(cur); Elm_Theme_Apply ret2 = ELM_THEME_APPLY_FAILED; ret2 = elm_obj_widget_theme_apply(obj); ret &= ret2; return ret; } EAPI void elm_widget_theme_specific(Evas_Object *obj, Elm_Theme *th, Eina_Bool force) { const Eina_List *l; Evas_Object *child; Elm_Tooltip *tt; Elm_Cursor *cur; Elm_Theme *th2, *thdef; API_ENTRY return; thdef = elm_theme_default_get(); if (!th) th = thdef; if (!force) { th2 = sd->theme; if (!th2) th2 = thdef; while (th2) { if (th2 == th) { force = EINA_TRUE; break; } if (th2 == thdef) break; th2 = th2->ref_theme; if (!th2) th2 = thdef; } } if (!force) return; EINA_LIST_FOREACH(sd->subobjs, l, child) { if (elm_widget_is(child)) elm_widget_theme_specific(child, th, force); } if (sd->hover_obj) elm_widget_theme(sd->hover_obj); EINA_LIST_FOREACH(sd->tooltips, l, tt) elm_tooltip_theme(tt); EINA_LIST_FOREACH(sd->cursors, l, cur) elm_cursor_theme(cur); elm_obj_widget_theme_apply(obj); } EOLIAN static Elm_Theme_Apply _elm_widget_theme_apply(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED) { _elm_widget_mirrored_reload(obj); if (elm_widget_disabled_get(obj)) elm_widget_disabled_internal(obj, elm_widget_disabled_get(obj)); return ELM_THEME_APPLY_SUCCESS; } /** * @internal * * Returns the widget's mirrored mode. * * @param obj The widget. * @return mirrored mode of the object. * **/ EOLIAN static Eina_Bool _elm_widget_efl_ui_base_mirrored_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd) { return sd->is_mirrored; } /** * @internal * * Sets the widget's mirrored mode. * * @param obj The widget. * @param mirrored EINA_TRUE to set mirrored mode. EINA_FALSE to unset. */ EOLIAN static void _elm_widget_efl_ui_base_mirrored_set(Eo *obj, Elm_Widget_Smart_Data *sd, Eina_Bool mirrored) { mirrored = !!mirrored; if (sd->is_mirrored == mirrored) return; sd->is_mirrored = mirrored; elm_widget_theme(obj); } /** * Returns the widget's mirrored mode setting. * * @param obj The widget. * @return mirrored mode setting of the object. * **/ EOLIAN static Eina_Bool -_elm_widget_mirrored_automatic_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd) +_elm_widget_efl_ui_base_mirrored_automatic_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd) { return sd->mirrored_auto_mode; } /** * @internal * * Sets the widget's mirrored mode setting. * When widget in automatic mode, it follows the system mirrored mode set by * elm_mirrored_set(). * @param obj The widget. * @param automatic EINA_TRUE for auto mirrored mode. EINA_FALSE for manual. */ EOLIAN static void -_elm_widget_mirrored_automatic_set(Eo *obj, Elm_Widget_Smart_Data *sd, Eina_Bool automatic) +_elm_widget_efl_ui_base_mirrored_automatic_set(Eo *obj, Elm_Widget_Smart_Data *sd, Eina_Bool automatic) { if (sd->mirrored_auto_mode != automatic) { sd->mirrored_auto_mode = automatic; if (automatic) { efl_ui_mirrored_set(obj, elm_config_mirrored_get()); } } } EOLIAN static void _elm_widget_on_show_region_hook_set(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd, region_hook_func_type func, void *data) { sd->on_show_region = func; sd->on_show_region_data = data; } /* * @internal * * Add myself as a sub object of parent object * * @see elm_widget_sub_object_add() */ EAPI Eina_Bool elm_widget_sub_object_parent_add(Evas_Object *sobj) { Eo *parent = NULL; parent = efl_parent_get(sobj); if (!efl_isa(parent, ELM_WIDGET_CLASS)) { ERR("You passed a wrong parent parameter (%p %s). " "Elementary widget's parent should be an elementary widget.", parent, evas_object_type_get(parent)); return EINA_FALSE; } return elm_obj_widget_sub_object_add(parent, sobj); } /* * @internal * * Add sobj to obj's sub object. * * What does elementary sub object mean? This is unique in elementary, it * handles overall elementary policies between parent and sub objects. * focus, access, deletion, theme, scale, mirror, scrollable child get, * translate, name find, display mode set, orientation set, tree dump * AUTOMATICALLY. * * @see elm_widget_sub_object_parent_add() */ EOLIAN static Eina_Bool _elm_widget_sub_object_add(Eo *obj, Elm_Widget_Smart_Data *sd, Evas_Object *sobj) { Eina_Bool mirrored, pmirrored = efl_ui_mirrored_get(obj); EINA_SAFETY_ON_TRUE_RETURN_VAL(obj == sobj, EINA_FALSE); if (sobj == sd->parent_obj) { /* in this case, sobj must be an elm widget, or something * very wrong is happening */ if (!_elm_widget_is(sobj)) return EINA_FALSE; if (!elm_widget_sub_object_del(sobj, obj)) return EINA_FALSE; WRN("You passed a parent object of obj = %p as the sub object = %p!", obj, sobj); } if (_elm_widget_is(sobj)) { ELM_WIDGET_DATA_GET(sobj, sdc); if (sdc->parent_obj == obj) goto end; if (sdc->parent_obj) { if (!elm_widget_sub_object_del(sdc->parent_obj, sobj)) return EINA_FALSE; } sdc->parent_obj = obj; _full_eval(sobj, sdc); if (!sdc->on_create) elm_obj_widget_orientation_set(sobj, sd->orient_mode); else sdc->orient_mode = sd->orient_mode; if (!sdc->on_create) { if (!sdc->disabled && (elm_widget_disabled_get(obj))) { elm_widget_focus_disabled_handle(sobj); elm_obj_widget_disable(sobj); } } _elm_widget_top_win_focused_set(sobj, sd->top_win_focused); /* update child focusable-ness on self and parents, now that a * focusable child got in */ if (!sd->child_can_focus && (_is_focusable(sobj))) { Elm_Widget_Smart_Data *sdp = sd; sdp->child_can_focus = EINA_TRUE; while (sdp->parent_obj) { sdp = efl_data_scope_get(sdp->parent_obj, MY_CLASS); if (sdp->child_can_focus) break; sdp->child_can_focus = EINA_TRUE; } } } else { void *data = evas_object_data_get(sobj, "elm-parent"); if (data) { if (data == obj) goto end; if (!elm_widget_sub_object_del(data, sobj)) return EINA_FALSE; } } sd->subobjs = eina_list_append(sd->subobjs, sobj); evas_object_data_set(sobj, "elm-parent", obj); _callbacks_add(sobj, obj); if (_elm_widget_is(sobj)) { ELM_WIDGET_DATA_GET(sobj, sdc); /* NOTE: In the following two lines, 'sobj' is correct. Do not change it. * Due to elementary's scale policy, scale and pscale can be different in * some cases. This happens when sobj's previous parent and new parent have * different scale value. * For example, if sobj's previous parent's scale is 5 and new parent's scale * is 2 while sobj's scale is 0. Then 'pscale' is 5 and 'scale' is 2. So we * need to reset sobj's scale to 5. * Note that each widget's scale is 0 by default. */ double scale, pscale = efl_ui_scale_get(sobj); Elm_Theme *th, *pth = elm_widget_theme_get(sobj); scale = efl_ui_scale_get(sobj); th = elm_widget_theme_get(sobj); mirrored = efl_ui_mirrored_get(sobj); if (!sdc->on_create) { if ((scale != pscale) || (th != pth) || (pmirrored != mirrored)) elm_widget_theme(sobj); } if (_is_focused(sobj)) _parents_focus(obj); elm_widget_display_mode_set(sobj, evas_object_size_hint_display_mode_get(obj)); if (_elm_config->atspi_mode && !sd->on_create) { Elm_Interface_Atspi_Accessible *aparent; aparent = elm_interface_atspi_accessible_parent_get(sobj); if (aparent) elm_interface_atspi_accessible_children_changed_added_signal_emit(aparent, sobj); } } end: return EINA_TRUE; } EOLIAN static Eina_Bool _elm_widget_sub_object_del(Eo *obj, Elm_Widget_Smart_Data *sd, Evas_Object *sobj) { Evas_Object *sobj_parent; if (!sobj) return EINA_FALSE; EINA_SAFETY_ON_TRUE_RETURN_VAL(obj == sobj, EINA_FALSE); sobj_parent = evas_object_data_del(sobj, "elm-parent"); if (sobj_parent && sobj_parent != obj) { static int abort_on_warn = -1; ERR("removing sub object %p (%s) from parent %p (%s), " "but elm-parent is different %p (%s)!", sobj, elm_widget_type_get(sobj), obj, elm_widget_type_get(obj), sobj_parent, elm_widget_type_get(sobj_parent)); if (EINA_UNLIKELY(abort_on_warn == -1)) { if (getenv("ELM_ERROR_ABORT")) abort_on_warn = 1; else abort_on_warn = 0; } if (abort_on_warn == 1) abort(); return EINA_FALSE; } if (_elm_widget_is(sobj)) { if (_is_focused(sobj)) { elm_widget_tree_unfocusable_set(sobj, EINA_TRUE); elm_widget_tree_unfocusable_set(sobj, EINA_FALSE); } if ((sd->child_can_focus) && (_is_focusable(sobj))) { Evas_Object *parent = obj; /* update child focusable-ness on self and parents, now that a * focusable child is gone */ while (parent) { const Eina_List *l; Evas_Object *subobj; ELM_WIDGET_DATA_GET(parent, sdp); sdp->child_can_focus = EINA_FALSE; EINA_LIST_FOREACH(sdp->subobjs, l, subobj) { if ((subobj != sobj) && (_is_focusable(subobj))) { sdp->child_can_focus = EINA_TRUE; break; } } /* break again, child_can_focus went back to * original value */ if (sdp->child_can_focus) break; parent = sdp->parent_obj; } } if (_elm_config->atspi_mode && !sd->on_destroy) { Elm_Interface_Atspi_Accessible *aparent; aparent = elm_interface_atspi_accessible_parent_get(sobj); if (aparent) elm_interface_atspi_accessible_children_changed_del_signal_emit(aparent, sobj); } ELM_WIDGET_DATA_GET(sobj, sdc); sdc->parent_obj = NULL; _full_eval(sobj, sdc); } if (sd->resize_obj == sobj) sd->resize_obj = NULL; sd->subobjs = eina_list_remove(sd->subobjs, sobj); _callbacks_del(sobj, obj); return EINA_TRUE; } /* * @internal * * a resize object is added to and deleted from the smart member and the sub object * of the parent if the third argument, Eina_Bool sub_obj, is set as EINA_TRUE. */ EOLIAN static void _elm_widget_resize_object_set(Eo *obj, Elm_Widget_Smart_Data *sd, Evas_Object *sobj, Eina_Bool sub_obj) { Evas_Object *parent; if (sd->resize_obj == sobj) return; // orphan previous resize obj if (sd->resize_obj && sub_obj) { evas_object_clip_unset(sd->resize_obj); evas_object_smart_member_del(sd->resize_obj); if (_elm_widget_is(sd->resize_obj)) { if (_is_focused(sd->resize_obj)) _parents_unfocus(obj); } elm_widget_sub_object_del(obj, sd->resize_obj); } sd->resize_obj = sobj; if (!sobj) return; // orphan new resize obj parent = evas_object_data_get(sobj, "elm-parent"); if (parent && parent != obj) { ELM_WIDGET_DATA_GET(parent, sdp); /* should be there, just being paranoid */ if (sdp) { if (sdp->resize_obj == sobj) elm_widget_resize_object_set(parent, NULL, sub_obj); else if (sub_obj) elm_widget_sub_object_del(parent, sobj); } } if (sub_obj) { elm_widget_sub_object_add(obj, sobj); evas_object_smart_member_add(sobj, obj); } _smart_reconfigure(sd); } /* * @internal * * WARNING: the programmer is responsible, in the scenario of * exchanging a hover object, of cleaning the old hover "target" * before */ EOLIAN static void _elm_widget_hover_object_set(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd, Evas_Object *sobj) { if (sd->hover_obj) { _callbacks_del(sd->hover_obj, obj); } sd->hover_obj = sobj; if (sd->hover_obj) { _callbacks_add(sobj, obj); _smart_reconfigure(sd); } } EOLIAN static void _elm_widget_can_focus_set(Eo *obj, Elm_Widget_Smart_Data *sd, Eina_Bool can_focus) { can_focus = !!can_focus; if (sd->can_focus == can_focus) return; sd->can_focus = can_focus; if (sd->can_focus) { /* update child_can_focus of parents */ Evas_Object *o = obj; for (;;) { o = elm_widget_parent_get(o); if (!o) break; ELM_WIDGET_DATA_GET(o, sdp); if (!sdp || sdp->child_can_focus) break; sdp->child_can_focus = EINA_TRUE; } efl_event_callback_array_add(obj, focus_callbacks(), NULL); } else { // update child_can_focus of parents */ Evas_Object *parent = elm_widget_parent_get(obj); while (parent) { const Eina_List *l; Evas_Object *subobj; ELM_WIDGET_DATA_GET(parent, sdp); sdp->child_can_focus = EINA_FALSE; EINA_LIST_FOREACH(sdp->subobjs, l, subobj) { if (_is_focusable(subobj)) { sdp->child_can_focus = EINA_TRUE; break; } } /* break again, child_can_focus went back to * original value */ if (sdp->child_can_focus) break; parent = sdp->parent_obj; } efl_event_callback_array_del(obj, focus_callbacks(), NULL); } if (efl_finalized_get(obj)) _focus_state_eval(obj, sd); } EOLIAN static Eina_Bool _elm_widget_can_focus_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd) { return sd->can_focus; } EOLIAN static Eina_Bool _elm_widget_child_can_focus_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd) { return sd->child_can_focus; } static void _full_eval_children(Eo *obj, Elm_Widget_Smart_Data *sd) { Eina_List *l; Eo *child; _full_eval(obj, sd); EINA_LIST_FOREACH(sd->subobjs , l, child) { Elm_Widget_Smart_Data *sd_child; if (!efl_isa(child, ELM_WIDGET_CLASS)) continue; sd_child = efl_data_scope_get(child, ELM_WIDGET_CLASS); _full_eval_children(child, sd_child); } } /** * @internal * * This API makes the widget object and its children to be unfocusable. * * This API can be helpful for an object to be deleted. * When an object will be deleted soon, it and its children may not * want to get focus (by focus reverting or by other focus controls). * Then, just use this API before deleting. * * @param obj The widget root of sub-tree * @param tree_unfocusable If true, set the object sub-tree as unfocusable * * @ingroup Widget */ EOLIAN static void _elm_widget_tree_unfocusable_set(Eo *obj, Elm_Widget_Smart_Data *sd, Eina_Bool tree_unfocusable) { tree_unfocusable = !!tree_unfocusable; if (sd->tree_unfocusable == tree_unfocusable) return; sd->tree_unfocusable = tree_unfocusable; elm_widget_focus_tree_unfocusable_handle(obj); //focus state eval on all children _full_eval_children(obj, sd); } /** * @internal * * This returns true, if the object sub-tree is unfocusable. * * @param obj The widget root of sub-tree * @return EINA_TRUE if the object sub-tree is unfocusable * * @ingroup Widget */ EOLIAN static Eina_Bool _elm_widget_tree_unfocusable_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd) { return sd->tree_unfocusable; } /** * @internal * * Get the list of focusable child objects. * * This function retruns list of child objects which can get focus. * * @param obj The parent widget * @retrun list of focusable child objects. * * @ingroup Widget */ EOLIAN static Eina_List* _elm_widget_can_focus_child_list_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd) { const Eina_List *l; Eina_List *child_list = NULL; Evas_Object *child; EINA_LIST_FOREACH(sd->subobjs, l, child) { if (!_elm_widget_is(child)) continue; if ((elm_widget_can_focus_get(child)) && (evas_object_visible_get(child)) && (!elm_widget_disabled_get(child))) child_list = eina_list_append(child_list, child); else { Eina_List *can_focus_list; can_focus_list = elm_widget_can_focus_child_list_get(child); if (can_focus_list) child_list = eina_list_merge(child_list, can_focus_list); } } return child_list; } EOLIAN static void _elm_widget_highlight_ignore_set(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd, Eina_Bool ignore) { sd->highlight_ignore = !!ignore; } EOLIAN static Eina_Bool _elm_widget_highlight_ignore_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd) { return sd->highlight_ignore; } EOLIAN static void _elm_widget_highlight_in_theme_set(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd, Eina_Bool highlight) { sd->highlight_in_theme = !!highlight; /* FIXME: if focused, it should switch from one mode to the other */ } void _elm_widget_highlight_in_theme_update(Eo *obj) { Evas_Object *top = elm_widget_top_get(obj); if (top && efl_isa(top, EFL_UI_WIN_CLASS)) { _elm_win_focus_highlight_in_theme_update( top, elm_widget_highlight_in_theme_get(obj)); } } EOLIAN static Eina_Bool _elm_widget_highlight_in_theme_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd) { return sd->highlight_in_theme; } EOLIAN static void _elm_widget_access_highlight_in_theme_set(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd, Eina_Bool highlight) { sd->access_highlight_in_theme = !!highlight; } EOLIAN static Eina_Bool _elm_widget_access_highlight_in_theme_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd) { return sd->access_highlight_in_theme; } EOLIAN static Eina_Bool _elm_widget_focus_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd) { return (sd->focused && sd->top_win_focused); } EOLIAN static Eina_Bool _elm_widget_highlight_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd) { return sd->highlighted; } EOLIAN static Evas_Object* _elm_widget_focused_object_get(Eo *obj, Elm_Widget_Smart_Data *sd) { const Evas_Object *subobj; const Eina_List *l; if (!sd->focused || !sd->top_win_focused) return NULL; EINA_LIST_FOREACH(sd->subobjs, l, subobj) { Evas_Object *fobj; if (!_elm_widget_is(subobj)) continue; fobj = elm_widget_focused_object_get(subobj); if (fobj) return fobj; } return (Evas_Object *)obj; } EOLIAN static Evas_Object* _elm_widget_top_get(Eo *obj, Elm_Widget_Smart_Data *sd) { if (sd->parent_obj) { Evas_Object *ret = NULL; if (!efl_isa(sd->parent_obj, ELM_WIDGET_CLASS)) return NULL; ret = elm_obj_widget_top_get((Eo *) sd->parent_obj); return ret; } return (Evas_Object *)obj; } EAPI Eina_Bool elm_widget_is(const Evas_Object *obj) { return _elm_widget_is(obj); } EAPI Evas_Object * elm_widget_parent_widget_get(const Evas_Object *obj) { Evas_Object *parent; if (_elm_widget_is(obj)) { ELM_WIDGET_DATA_GET(obj, sd); if (!sd) return NULL; parent = sd->parent_obj; } else { parent = evas_object_data_get(obj, "elm-parent"); if (!parent) parent = evas_object_smart_parent_get(obj); } while (parent) { Evas_Object *elm_parent; if (_elm_widget_is(parent)) break; elm_parent = evas_object_data_get(parent, "elm-parent"); if (elm_parent) parent = elm_parent; else parent = evas_object_smart_parent_get(parent); } return parent; } EOLIAN static Evas_Object * _elm_widget_parent2_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd) { return sd->parent2; } EOLIAN static void _elm_widget_parent2_set(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd, Evas_Object *parent) { sd->parent2 = parent; } EAPI void elm_widget_event_callback_add(Eo *obj, Elm_Event_Cb func, const void *data) { API_ENTRY return; EINA_SAFETY_ON_NULL_RETURN(func); Elm_Event_Cb_Data *ecb = ELM_NEW(Elm_Event_Cb_Data); if (!ecb) { ERR("Failed to allocate memory"); return; } ecb->func = func; ecb->data = data; sd->event_cb = eina_list_append(sd->event_cb, ecb); } EAPI void * elm_widget_event_callback_del(Eo *obj, Elm_Event_Cb func, const void *data) { API_ENTRY return NULL; EINA_SAFETY_ON_NULL_RETURN_VAL(func, NULL); Eina_List *l; Elm_Event_Cb_Data *ecd; EINA_LIST_FOREACH(sd->event_cb, l, ecd) if ((ecd->func == func) && (ecd->data == data)) { free(ecd); sd->event_cb = eina_list_remove_list(sd->event_cb, l); return (void *)data; } return NULL; } EAPI Eina_Bool elm_widget_event_propagate(Eo *obj, Evas_Callback_Type type, void *event_info, Evas_Event_Flags *event_flags) { Evas_Object *parent = obj; Elm_Event_Cb_Data *ecd; Eina_List *l, *l_prev; while (parent && (!(event_flags && ((*event_flags) & EVAS_EVENT_FLAG_ON_HOLD)))) { ELM_WIDGET_CHECK(parent) EINA_FALSE; Elm_Widget_Smart_Data *sd = efl_data_scope_get(parent, MY_CLASS); Eina_Bool int_ret = EINA_FALSE; if (elm_widget_disabled_get(obj)) { parent = sd->parent_obj; continue; } int_ret = elm_obj_widget_event(parent, obj, type, event_info); if (int_ret) return EINA_TRUE; EINA_LIST_FOREACH_SAFE(sd->event_cb, l, l_prev, ecd) { if (ecd->func((void *)ecd->data, parent, obj, type, event_info) || (event_flags && ((*event_flags) & EVAS_EVENT_FLAG_ON_HOLD))) return EINA_TRUE; } parent = sd->parent_obj; } return EINA_FALSE; } /** * @internal * * Set custom focus chain. * * This function i set one new and overwrite any previous custom focus chain * with the list of objects. The previous list will be deleted and this list * will be managed. After setted, don't modity it. * * @note On focus cycle, only will be evaluated children of this container. * * @param obj The container widget * @param objs Chain of objects to pass focus * @ingroup Widget */ EOLIAN static void _elm_widget_focus_custom_chain_set(Eo *obj, Elm_Widget_Smart_Data *sd, Eina_List *objs) { if (!_elm_widget_focus_chain_manager_is(obj)) return; elm_widget_focus_custom_chain_unset(obj); Eina_List *l; Evas_Object *o; EINA_LIST_FOREACH(objs, l, o) { evas_object_event_callback_add(o, EVAS_CALLBACK_DEL, _elm_object_focus_chain_del_cb, obj); } sd->focus_chain = objs; } /** * @internal * * Get custom focus chain * * @param obj The container widget * @ingroup Widget */ EOLIAN static const Eina_List* _elm_widget_focus_custom_chain_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd) { return (const Eina_List *)sd->focus_chain; } /** * @internal * * Unset custom focus chain * * @param obj The container widget * @ingroup Widget */ EOLIAN static void _elm_widget_focus_custom_chain_unset(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd) { Eina_List *l, *l_next; Evas_Object *o; EINA_LIST_FOREACH_SAFE(sd->focus_chain, l, l_next, o) { evas_object_event_callback_del_full(o, EVAS_CALLBACK_DEL, _elm_object_focus_chain_del_cb, obj); sd->focus_chain = eina_list_remove_list(sd->focus_chain, l); } } /** * @internal * * Append object to custom focus chain. * * @note If relative_child equal to NULL or not in custom chain, the object * will be added in end. * * @note On focus cycle, only will be evaluated children of this container. * * @param obj The container widget * @param child The child to be added in custom chain * @param relative_child The relative object to position the child * @ingroup Widget */ EOLIAN static void _elm_widget_focus_custom_chain_append(Eo *obj, Elm_Widget_Smart_Data *sd, Evas_Object *child, Evas_Object *relative_child) { EINA_SAFETY_ON_NULL_RETURN(child); if (!_elm_widget_focus_chain_manager_is(obj)) return; evas_object_event_callback_add(child, EVAS_CALLBACK_DEL, _elm_object_focus_chain_del_cb, obj); if (!relative_child) sd->focus_chain = eina_list_append(sd->focus_chain, child); else sd->focus_chain = eina_list_append_relative(sd->focus_chain, child, relative_child); } /** * @internal * * Prepend object to custom focus chain. * * @note If relative_child equal to NULL or not in custom chain, the object * will be added in begin. * * @note On focus cycle, only will be evaluated children of this container. * * @param obj The container widget * @param child The child to be added in custom chain * @param relative_child The relative object to position the child * @ingroup Widget */ EOLIAN static void _elm_widget_focus_custom_chain_prepend(Eo *obj, Elm_Widget_Smart_Data *sd, Evas_Object *child, Evas_Object *relative_child) { EINA_SAFETY_ON_NULL_RETURN(child); if (!_elm_widget_focus_chain_manager_is(obj)) return; evas_object_event_callback_add(child, EVAS_CALLBACK_DEL, _elm_object_focus_chain_del_cb, obj); if (!relative_child) sd->focus_chain = eina_list_prepend(sd->focus_chain, child); else sd->focus_chain = eina_list_prepend_relative(sd->focus_chain, child, relative_child); } /** * @internal * * Give focus to next object in object tree. * * Give focus to next object in focus chain of one object sub-tree. * If the last object of chain already have focus, the focus will go to the * first object of chain. * * @param obj The widget root of sub-tree * @param dir Direction to cycle the focus * * @ingroup Widget */ EOLIAN static void _elm_widget_focus_cycle(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED, Elm_Focus_Direction dir) { Evas_Object *target = NULL; Elm_Object_Item *target_item = NULL; if (!_elm_widget_is(obj)) return; elm_widget_focus_next_get(obj, dir, &target, &target_item); if (target) { /* access */ if (_elm_config->access_mode) { /* highlight cycle does not steal a focus, only after window gets the ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_ACTIVATE message, target will steal focus, or focus its own job. */ if (!_elm_access_auto_highlight_get()) elm_widget_focus_steal(target, target_item); _elm_access_highlight_set(target); elm_widget_focus_region_show(target); } else elm_widget_focus_steal(target, target_item); } } /** * @internal * * Give focus to near object(in object tree) in one direction. * * Give focus to near object(in object tree) in direction of current * focused object. If none focusable object in given direction or * none focused object in object tree, the focus will not change. * * @param obj The reference widget * @param degree Degree changes clockwise. i.e. 0-degree: Up, * 90-degree: Right, 180-degree: Down, and 270-degree: Left * @return EINA_TRUE if focus is moved. * * @ingroup Widget */ EOLIAN static Eina_Bool _elm_widget_focus_direction_go(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED, double degree) { Evas_Object *target = NULL; Elm_Object_Item *target_item = NULL; Evas_Object *current_focused = NULL; double weight = 0.0; if (!_elm_widget_is(obj)) return EINA_FALSE; if (!_is_focused(obj)) return EINA_FALSE; current_focused = elm_widget_focused_object_get(obj); if (elm_widget_focus_direction_get (obj, current_focused, degree, &target, &target_item, &weight)) { elm_widget_focus_steal(target, NULL); return EINA_TRUE; } return EINA_FALSE; } double _elm_widget_focus_direction_weight_get(const Evas_Object *obj1, const Evas_Object *obj2, double degree) { Evas_Coord obj_x1, obj_y1, w1, h1, obj_x2, obj_y2, w2, h2; double x1, yy1, x2, yy2, xx1, yyy1, xx2, yyy2; double ax, ay, cx, cy; double weight = -1.0, g = 0.0; if (obj1 == obj2) return 0.0; degree -= 90.0; while (degree >= 360.0) degree -= 360.0; while (degree < 0.0) degree += 360.0; evas_object_geometry_get(obj1, &obj_x1, &obj_y1, &w1, &h1); cx = obj_x1 + (w1 / 2.0); cy = obj_y1 + (h1 / 2.0); evas_object_geometry_get(obj2, &obj_x2, &obj_y2, &w2, &h2); /* For overlapping cases. */ if (ELM_RECTS_INTERSECT(obj_x1, obj_y1, w1, h1, obj_x2, obj_y2, w2, h2)) return 0.0; /* Change all points to relative one. */ x1 = obj_x1 - cx; xx1 = x1 + w1; yy1 = obj_y1 - cy; yyy1 = yy1 + h1; x2 = obj_x2 - cx; xx2 = x2 + w2; yy2 = obj_y2 - cy; yyy2 = yy2 + h2; /* Get crossing points (ax, ay) between obj1 and a line extending * to the direction of current degree. */ if (degree == 0.0) { ax = xx1; ay = 0.0; } else if (degree == 90.0) { ax = 0.0; ay = yyy1; } else if (degree == 180.0) { ax = x1; ay = 0.0; } else if (degree == 270.0) { ax = 0.0; ay = yy1; } else { g = tan(degree * (M_PI / 180.0)); if ((degree > 0.0) && (degree < 90.0)) { ay = g * xx1; if (ay <= yyy1) ax = xx1; else { ax = yyy1 / g; ay = yyy1; } } else if ((degree > 90.0) && (degree < 180.0)) { ay = g * x1; if (ay <= yyy1) ax = x1; else { ax = yyy1 / g; ay = yyy1; } } else if ((degree > 180.0) && (degree < 270.0)) { ay = g * x1; if (ay >= yy1) ax = x1; else { ax = yy1 / g; ay = yy1; } } else { ay = g * xx1; if (ay >= yy1) ax = xx1; else { ax = yy1 / g; ay = yy1; } } } /* Filter obj2, if it is not in the specific derection. */ int i = 0; double rx[4] = {0.0, 0.0, 0.0, 0.0}, ry[4] = {0.0, 0.0, 0.0, 0.0}; double t1, t2, u1, v1, u2, v2; if ((degree == 45.0) || (degree == 225.0) || (degree == 135.0) || (degree == 315.0)) { u1 = 1.0; v1 = 0.0; u2 = 0.0; v2 = 1.0; } else { double g2 = tan((degree + 45.0) * (M_PI / 180.0)); u1 = (-1.0 * g2); u2 = (1.0 / g2); v1 = v2 = 1.0; } t1 = (u1 * ax) + (v1 * ay); t2 = (u2 * ax) + (v2 * ay); #define _R(x) (int)((x + 0.05) * 10.0) if ((_R(t1 * ((u1 * x2) + (v1 * yy2))) > 0) && (_R(t2 * ((u2 * x2) + (v2 * yy2))) > 0)) { rx[i] = x2; ry[i++] = yy2; } if ((_R(t1 * ((u1 * x2) + (v1 * yyy2))) > 0) && (_R(t2 * ((u2 * x2) + (v2 * yyy2))) > 0)) { rx[i] = x2; ry[i++] = yyy2; } if ((_R(t1 * ((u1 * xx2) + (v1 * yy2))) > 0) && (_R(t2 * ((u2 * xx2) + (v2 * yy2))) > 0)) { rx[i] = xx2; ry[i++] = yy2; } if ((_R(t1 * ((u1 * xx2) + (v1 * yyy2))) > 0) && (_R(t2 * ((u2 * xx2) + (v2 * yyy2))) > 0)) { rx[i] = xx2; ry[i++] = yyy2; } if (i == 0) { if (degree == 0.0) { if ((_R(xx2) < 0) || (_R(yy2) > 0) || (_R(yyy2) < 0)) return 0.0; } else if (degree == 90.0) { if ((_R(yyy2) < 0) || (_R(x2) > 0) || (_R(xx2) < 0)) return 0.0; } else if (degree == 180.0) { if ((_R(x2) > 0) || (_R(yy2) > 0) || (_R(yyy2) < 0)) return 0.0; } else if (degree == 270.0) { if ((_R(yy2) > 0) || (_R(x2) > 0) || (_R(xx2) < 0)) return 0.0; } else { if ((_R(g * x2) >= _R(yy2)) && (_R((g * x2)) <= _R(yyy2))) { if (!((_R(ax * x2) > 0) && (_R(ay * (g * x2)) > 0))) return 0.0; } else if ((_R(g * xx2) >= _R(yy2)) && (_R((g * xx2)) <= _R(yyy2))) { if (!((_R(ax * xx2) > 0) && (_R(ay * (g * xx2)) > 0))) return 0.0; } else if ((_R((1.0 / g) * yy2) >= _R(xx2)) && (_R((1.0 / g) * yy2) <= _R(xx2))) { if (!((_R(ax * ((1.0 / g) * yy2)) > 0) && (_R(ay * yy2) > 0))) return 0.0; } else if ((_R((1.0 / g) * yyy2) >= _R(xx2)) && (_R((1.0 / g) * yyy2) <= _R(xx2))) { if (!((_R(ax * ((1.0 / g) * yyy2)) > 0) && (_R(ay * yyy2) > 0))) return 0.0; } else return 0.0; } } /* Calculate the weight for obj2. */ if (degree == 0.0) { if (_R(xx1) > _R(x2)) weight = -1.0; else if ((_R(yy2) >= _R(yy1)) && (_R(yyy2) <= _R(yyy1))) weight = (x2 - xx1) * (x2 - xx1); else if (_R(yy2) > 0) weight = ((x2 - xx1) * (x2 - xx1)) + (yy2 * yy2); else if (_R(yyy2) < 0) weight = ((x2 - xx1) * (x2 - xx1)) + (yyy2 * yyy2); else weight = (x2 - xx1) * (x2 - xx1); } else if (degree == 90.0) { if (_R(yyy1) > _R(yy2)) weight = -1.0; else if ((_R(x2) >= _R(x1)) && (_R(xx2) <= _R(xx1))) weight = (yy2 - yyy1) * (yy2 - yyy1); else if (_R(x2) > 0) weight = (x2 * x2) + ((yy2 - yyy1) * (yy2 - yyy1)); else if (_R(xx2) < 0) weight = (xx2 * xx2) + ((yy2 - yyy1) * (yy2 - yyy1)); else weight = (yy2 - yyy1) * (yy2 - yyy1); } else if (degree == 180.0) { if (_R(x1) < _R(xx2)) weight = -1.0; else if ((_R(yy2) >= _R(yy1)) && (_R(yyy2) <= _R(yyy1))) weight = (x1 - xx2) * (x1 - xx2); else if (_R(yy2) > 0) weight = ((x1 - xx2) * (x1 - xx2)) + (yy2 * yy2); else if (_R(yyy2) < 0) weight = ((x1 - xx2) * (x1 - xx2)) + (yyy2 * yyy2); else weight = (x1 - xx2) * (x1 - xx2); } else if (degree == 270.0) { if (_R(yy1) < _R(yyy2)) weight = -1.0; else if ((_R(x2) >= _R(x1)) && (_R(xx2) <= _R(xx1))) weight = (yy1 - yyy2) * (yy1 - yyy2); else if (_R(x2) > 0) weight = (x2 * x2) + ((yy1 - yyy2) * (yy1 - yyy2)); else if (_R(xx2) < 0) weight = (xx2 * xx2) + ((yy1 - yyy2) * (yy1 - yyy2)); else weight = (yy1 - yyy2) * (yy1 - yyy2); } else { int j = 0, k = 0; double sx[4] = {0.0, 0.0, 0.0, 0.0}, sy[4] = {0.0, 0.0, 0.0, 0.0}; double t_weight[4] = {-1.0, -1.0, -1.0, -1.0}; if ((_R(g * x2) >= _R(yy2)) && (_R(g * x2) <= _R(yyy2))) { sx[j] = x2; sy[j] = g * x2; t_weight[j++] = ((ax - x2) * (ax - x2)) + ((ay - (g * x2)) * (ay - (g * x2))); } if ((_R(g * xx2) >= _R(yy2)) && (_R(g * xx2) <= _R(yyy2))) { sx[j] = xx2; sy[j] = g * xx2; t_weight[j++] = ((ax - xx2) * (ax - xx2)) + ((ay - (g * xx2)) * (ay - (g * xx2))); } if ((_R((1.0 / g) * yy2) >= _R(x2)) && (_R((1.0 / g) * yy2) <= _R(xx2))) { sx[j] = (1.0 / g) * yy2; sy[j] = yy2; t_weight[j++] = ((ax - ((1.0 / g) * yy2)) * (ax - ((1.0 / g) * yy2))) + ((ay - yy2) * (ay - yy2)); } if ((_R((1.0 / g) * yyy2) >= _R(x2)) && (_R((1.0 / g) * yyy2) <= _R(xx2))) { sx[j] = (1.0 / g) * yyy2; sy[j] = yyy2; t_weight[j++] = ((ax - ((1.0 / g) * yyy2)) * (ax - ((1.0 / g) * yyy2))) + ((ay - yyy2) * (ay - yyy2)); } if ((j > 2) || ((j == 2) && ((_R(sx[0]) != _R(sx[1])) || (_R(sy[0]) != _R(sy[1]))))) { for (; k < j; k++) { if (_R(t_weight[k]) == 0) return -1.0; if ((1 / weight) < (1 / t_weight[k])) weight = t_weight[k]; } } else { for (; k < i; k++) { double ccx, ccy, t1_weight, x_diff, y_diff; ccx = ((1.0 / g) * rx[k] + ry[k]) / (g + (1.0 / g)); ccy = g * ccx; x_diff = rx[k] - ccx; if (x_diff < 0) x_diff *= -1.0; y_diff = ry[k] - ccy; if (y_diff < 0) y_diff *= -1.0; t1_weight = (((ax - ccx) * (ax - ccx)) + ((ay - ccy) * (ay - ccy))) + ((x_diff * x_diff * x_diff) + (y_diff * y_diff * y_diff)); if ((_R(t1_weight) != 0) && ((1 / weight) < (1 / t1_weight))) weight = t1_weight; } } } /* Return the current object's weight. */ if (weight == -1.0) return 0.0; if (_R(weight) == 0) return -1.0; #undef _R return 1.0 / weight; } /** * @internal * * Get near object in one direction of base object. * * Get near object(in the object sub-tree) in one direction of * base object. Return the near object by reference. * By initializing weight, you can filter objects locating far * from base object. If object is in the specific direction, * weight is (1/(distance^2)). If object is not exactly in one * direction, some penalty will be added. * * @param obj The widget root of sub-tree * @param base The base object of the direction * @param degree Degree changes clockwise. i.e. 0-degree: Up, * 90-degree: Right, 180-degree: Down, and 270-degree: Left * @param direction The near object in one direction * @param weight The weight is bigger when the object is located near * @return EINA_TRUE if near object is updated. * * @ingroup Widget */ EOLIAN static Eina_Bool _elm_widget_focus_direction_get(const Eo *obj, Elm_Widget_Smart_Data *sd, const Evas_Object *base, double degree, Evas_Object **direction, Elm_Object_Item **direction_item, double *weight) { double c_weight; /* -1 means the best was already decided. Don't need any more searching. */ if (!direction || !weight || !base || (obj == base)) return EINA_FALSE; /* Ignore if disabled */ if ((!evas_object_visible_get(obj)) || (elm_widget_disabled_get(obj)) || (elm_widget_tree_unfocusable_get(obj))) return EINA_FALSE; /* Try use hook */ if (_internal_elm_widget_focus_direction_manager_is(obj)) { Eina_Bool int_ret = EINA_FALSE; int_ret = elm_obj_widget_focus_direction((Eo *)obj, base, degree, direction, direction_item, weight); return int_ret; } if (!elm_widget_can_focus_get(obj) || _is_focused((Eo *)obj)) return EINA_FALSE; c_weight = _elm_widget_focus_direction_weight_get(base, obj, degree); if ((c_weight == -1.0) || ((c_weight != 0.0) && (*weight != -1.0) && ((int)(*weight * 1000000) <= (int)(c_weight * 1000000)))) { if (*direction && ((int)(*weight * 1000000) == (int)(c_weight * 1000000))) { ELM_WIDGET_DATA_GET(*direction, sd1); if (sd1) { if (sd->focus_order <= sd1->focus_order) return EINA_FALSE; } } *direction = (Evas_Object *)obj; *weight = c_weight; return EINA_TRUE; } return EINA_FALSE; } /** * @internal * * Get near object in one direction of base object in list. * * Get near object in one direction of base object in the specific * object list. Return the near object by reference. * By initializing weight, you can filter objects locating far * from base object. If object is in the specific direction, * weight is (1/(distance^2)). If object is not exactly in one * direction, some penalty will be added. * * @param obj The widget root of sub-tree * @param base The base object of the direction * @param items list with ordered objects * @param list_data_get function to get the object from one item of list * @param degree Degree changes clockwise. i.e. 0-degree: Up, * 90-degree: Right, 180-degree: Down, and 270-degree: Left * @param direction The near object in one direction * @param weight The weight is bigger when the object is located near * @return EINA_TRUE if near object is updated. * * @ingroup Widget */ EOLIAN static Eina_Bool _elm_widget_focus_list_direction_get(const Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *_pd EINA_UNUSED, const Evas_Object *base, const Eina_List *items, list_data_get_func_type list_data_get, double degree, Evas_Object **direction, Elm_Object_Item **direction_item, double *weight) { if (!direction || !weight || !base || !items) return EINA_FALSE; const Eina_List *l = items; Evas_Object *current_best = *direction; for (; l; l = eina_list_next(l)) { Evas_Object *cur = list_data_get(l); if (cur && _elm_widget_is(cur)) elm_widget_focus_direction_get(cur, base, degree, direction, direction_item, weight); } if (current_best != *direction) return EINA_TRUE; return EINA_FALSE; } /** * @internal * * Get next object in focus chain of object tree. * * Get next object in focus chain of one object sub-tree. * Return the next object by reference. If don't have any candidate to receive * focus before chain end, the first candidate will be returned. * * @param obj The widget root of sub-tree * @param dir Direction of focus chain * @param next The next object in focus chain * @return EINA_TRUE if don't need focus chain restart/loop back * to use 'next' obj. * * @ingroup Widget */ EOLIAN static Eina_Bool _elm_widget_focus_next_get(const Eo *obj, Elm_Widget_Smart_Data *sd, Elm_Focus_Direction dir, Evas_Object **next, Elm_Object_Item **next_item) { Elm_Access_Info *ac; if (!next) return EINA_FALSE; *next = NULL; /* Ignore if disabled */ if (_elm_config->access_mode && _elm_access_auto_highlight_get()) { if (!evas_object_visible_get(obj) || (elm_widget_tree_unfocusable_get(obj))) return EINA_FALSE; } else { if ((!evas_object_visible_get(obj)) || (elm_widget_disabled_get(obj)) || (elm_widget_tree_unfocusable_get(obj))) return EINA_FALSE; } /* Try use hook */ if (_elm_widget_focus_chain_manager_is(obj)) { Eina_Bool int_ret = EINA_FALSE; int_ret = elm_obj_widget_focus_next((Eo *)obj, dir, next, next_item); if (!int_ret && _is_focused((Eo *)obj)) { Evas_Object *o = NULL; if (dir == ELM_FOCUS_PREVIOUS) *next_item = sd->item_focus_previous; else if (dir == ELM_FOCUS_NEXT) *next_item = sd->item_focus_next; else if (dir == ELM_FOCUS_UP) *next_item = sd->item_focus_up; else if (dir == ELM_FOCUS_DOWN) *next_item = sd->item_focus_down; else if (dir == ELM_FOCUS_RIGHT) *next_item = sd->item_focus_right; else if (dir == ELM_FOCUS_LEFT) *next_item = sd->item_focus_left; if (*next_item) o = elm_object_item_widget_get(*next_item); if (!o) { if (dir == ELM_FOCUS_PREVIOUS) o = sd->focus_previous; else if (dir == ELM_FOCUS_NEXT) o = sd->focus_next; else if (dir == ELM_FOCUS_UP) o = sd->focus_up; else if (dir == ELM_FOCUS_DOWN) o = sd->focus_down; else if (dir == ELM_FOCUS_RIGHT) o = sd->focus_right; else if (dir == ELM_FOCUS_LEFT) o = sd->focus_left; } if (o) { *next = o; return EINA_TRUE; } } return int_ret; } /* access object does not check sd->can_focus, because an object could have highlight even though the object is not focusable. */ if (_elm_config->access_mode && _elm_access_auto_highlight_get()) { ac = _elm_access_info_get(obj); if (!ac) return EINA_FALSE; /* check whether the hover object is visible or not */ if (!evas_object_visible_get(ac->hoverobj)) return EINA_FALSE; } else if (!elm_widget_can_focus_get(obj)) return EINA_FALSE; if (_is_focused((Eo *)obj)) { if (dir == ELM_FOCUS_PREVIOUS) *next_item = sd->item_focus_previous; else if (dir == ELM_FOCUS_NEXT) *next_item = sd->item_focus_next; else if (dir == ELM_FOCUS_UP) *next_item = sd->item_focus_up; else if (dir == ELM_FOCUS_DOWN) *next_item = sd->item_focus_down; else if (dir == ELM_FOCUS_RIGHT) *next_item = sd->item_focus_right; else if (dir == ELM_FOCUS_LEFT) *next_item = sd->item_focus_left; if (*next_item) *next = elm_object_item_widget_get(*next_item); if (!(*next)) { if (dir == ELM_FOCUS_PREVIOUS) *next = sd->focus_previous; else if (dir == ELM_FOCUS_NEXT) *next = sd->focus_next; else if (dir == ELM_FOCUS_UP) *next = sd->focus_up; else if (dir == ELM_FOCUS_DOWN) *next = sd->focus_down; else if (dir == ELM_FOCUS_RIGHT) *next = sd->focus_right; else if (dir == ELM_FOCUS_LEFT) *next = sd->focus_left; } if (*next) return EINA_TRUE; } /* Return */ *next = (Evas_Object *)obj; return !ELM_WIDGET_FOCUS_GET(obj); } /** * @internal * * Get next object in focus chain of object tree in list. * * Get next object in focus chain of one object sub-tree ordered by one list. * Return the next object by reference. If don't have any candidate to receive * focus before list end, the first candidate will be returned. * * @param obj The widget root of sub-tree * @param items list with ordered objects * @param list_data_get function to get the object from one item of list * @param dir Direction of focus chain * @param next The next object in focus chain * @return EINA_TRUE if don't need focus chain restart/loop back * to use 'next' obj. * * @ingroup Widget */ EOLIAN static Eina_Bool _elm_widget_focus_list_next_get(const Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED, const Eina_List *items, list_data_get_func_type list_data_get, Elm_Focus_Direction dir, Evas_Object **next, Elm_Object_Item **next_item) { Eina_List *(*list_next)(const Eina_List *list) = NULL; Evas_Object *focused_object = NULL; if (!next) return EINA_FALSE; *next = NULL; if (!_elm_widget_is(obj)) return EINA_FALSE; if (!items) return EINA_FALSE; /* When Up, Down, Right, or Left, try direction_get first. */ focused_object = elm_widget_focused_object_get(obj); if (focused_object) { if ((dir == ELM_FOCUS_UP) || (dir == ELM_FOCUS_DOWN) || (dir == ELM_FOCUS_RIGHT) || (dir == ELM_FOCUS_LEFT)) { *next_item = elm_widget_focus_next_item_get(focused_object, dir); if (*next_item) *next = elm_object_item_widget_get(*next_item); else *next = elm_widget_focus_next_object_get(focused_object, dir); if (*next) return EINA_TRUE; else { Evas_Object *n = NULL; Elm_Object_Item *n_item = NULL; double degree = 0; double weight = 0.0; if (dir == ELM_FOCUS_UP) degree = 0.0; else if (dir == ELM_FOCUS_DOWN) degree = 180.0; else if (dir == ELM_FOCUS_RIGHT) degree = 90.0; else if (dir == ELM_FOCUS_LEFT) degree = 270.0; if (elm_widget_focus_list_direction_get(obj, focused_object, items, list_data_get, degree, &n, &n_item, &weight)) { *next_item = n_item; *next = n; return EINA_TRUE; } } } } /* Direction */ if (dir == ELM_FOCUS_PREVIOUS) { items = eina_list_last(items); list_next = eina_list_prev; } else if ((dir == ELM_FOCUS_NEXT) || (dir == ELM_FOCUS_UP) || (dir == ELM_FOCUS_DOWN) || (dir == ELM_FOCUS_RIGHT) || (dir == ELM_FOCUS_LEFT)) list_next = eina_list_next; else return EINA_FALSE; const Eina_List *l = items; /* Recovery last focused sub item */ if (ELM_WIDGET_FOCUS_GET(obj)) { for (; l; l = list_next(l)) { Evas_Object *cur = list_data_get(l); if (ELM_WIDGET_FOCUS_GET(cur)) break; } /* Focused object, but no focused sub item */ if (!l) l = items; } const Eina_List *start = l; Evas_Object *to_focus = NULL; Elm_Object_Item *to_focus_item = NULL; /* Iterate sub items */ /* Go to the end of list */ for (; l; l = list_next(l)) { Evas_Object *tmp = NULL; Elm_Object_Item *tmp_item = NULL; Evas_Object *cur = list_data_get(l); if (!cur) continue; if (!_elm_widget_is(cur)) continue; if (elm_widget_parent_get(cur) != obj) continue; /* Try Focus cycle in subitem */ if (elm_widget_focus_next_get(cur, dir, &tmp, &tmp_item)) { *next = tmp; *next_item = tmp_item; return EINA_TRUE; } else if ((dir == ELM_FOCUS_UP) || (dir == ELM_FOCUS_DOWN) || (dir == ELM_FOCUS_RIGHT) || (dir == ELM_FOCUS_LEFT)) { if (tmp && _is_focused(cur)) { *next = tmp; *next_item = tmp_item; return EINA_FALSE; } } else if ((tmp) && (!to_focus)) { to_focus = tmp; to_focus_item = tmp_item; } } l = items; /* Get First possible */ for (; l != start; l = list_next(l)) { Evas_Object *tmp = NULL; Elm_Object_Item *tmp_item = NULL; Evas_Object *cur = list_data_get(l); if (elm_widget_parent_get(cur) != obj) continue; /* Try Focus cycle in subitem */ elm_widget_focus_next_get(cur, dir, &tmp, &tmp_item); if (tmp) { *next = tmp; *next_item = tmp_item; return EINA_FALSE; } } *next = to_focus; *next_item = to_focus_item; return EINA_FALSE; } /** * @internal * * Get next object which was set with specific focus direction. * * Get next object which was set by elm_widget_focus_next_object_set * with specific focus directioin. * * @param obj The widget * @param dir Direction of focus * @return Widget which was registered with sepecific focus direction. * * @ingroup Widget */ EOLIAN static Evas_Object* _elm_widget_focus_next_object_get(const Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd, Elm_Focus_Direction dir) { Evas_Object *ret = NULL; if (dir == ELM_FOCUS_PREVIOUS) ret = sd->focus_previous; else if (dir == ELM_FOCUS_NEXT) ret = sd->focus_next; else if (dir == ELM_FOCUS_UP) ret = sd->focus_up; else if (dir == ELM_FOCUS_DOWN) ret = sd->focus_down; else if (dir == ELM_FOCUS_RIGHT) ret = sd->focus_right; else if (dir == ELM_FOCUS_LEFT) ret = sd->focus_left; return ret; } /** * @internal * * Set next object with specific focus direction. * * When a widget is set with specific focus direction, this widget will be * the first candidate when finding the next focus object. * Focus next object can be registered with six directions that are previous, * next, up, down, right, and left. * * @param obj The widget * @param next Next focus object * @param dir Direction of focus * * @ingroup Widget */ EOLIAN static void _elm_widget_focus_next_object_set(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd, Evas_Object *next, Elm_Focus_Direction dir) { if (dir == ELM_FOCUS_PREVIOUS) sd->focus_previous = next; else if (dir == ELM_FOCUS_NEXT) sd->focus_next = next; else if (dir == ELM_FOCUS_UP) sd->focus_up = next; else if (dir == ELM_FOCUS_DOWN) sd->focus_down = next; else if (dir == ELM_FOCUS_RIGHT) sd->focus_right = next; else if (dir == ELM_FOCUS_LEFT) sd->focus_left = next; } EOLIAN static Elm_Object_Item* _elm_widget_focus_next_item_get(const Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd, Elm_Focus_Direction dir) { Elm_Object_Item *ret = NULL; if (dir == ELM_FOCUS_PREVIOUS) ret = sd->item_focus_previous; else if (dir == ELM_FOCUS_NEXT) ret = sd->item_focus_next; else if (dir == ELM_FOCUS_UP) ret = sd->item_focus_up; else if (dir == ELM_FOCUS_DOWN) ret = sd->item_focus_down; else if (dir == ELM_FOCUS_RIGHT) ret = sd->item_focus_right; else if (dir == ELM_FOCUS_LEFT) ret = sd->item_focus_left; return ret; } EOLIAN static void _elm_widget_focus_next_item_set(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd, Elm_Object_Item *next_item, Elm_Focus_Direction dir) { if (dir == ELM_FOCUS_PREVIOUS) sd->item_focus_previous = next_item; else if (dir == ELM_FOCUS_NEXT) sd->item_focus_next = next_item; else if (dir == ELM_FOCUS_UP) sd->item_focus_up = next_item; else if (dir == ELM_FOCUS_DOWN) sd->item_focus_down = next_item; else if (dir == ELM_FOCUS_RIGHT) sd->item_focus_right = next_item; else if (dir == ELM_FOCUS_LEFT) sd->item_focus_left = next_item; } EOLIAN static void _elm_widget_parent_highlight_set(Eo *obj, Elm_Widget_Smart_Data *sd, Eina_Bool highlighted) { highlighted = !!highlighted; Evas_Object *o = elm_widget_parent_get(obj); if (o) elm_widget_parent_highlight_set(o, highlighted); sd->highlighted = highlighted; } EOLIAN static void _elm_widget_signal_emit(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED, const char *emission, const char *source) { if (evas_object_smart_type_check(obj, "elm_layout")) elm_layout_signal_emit(obj, emission, source); else if (evas_object_smart_type_check(obj, "elm_icon")) { WRN("Deprecated function. This functionality on icon objects" " will be dropped on a next release."); _elm_icon_signal_emit(obj, emission, source); } } EOLIAN static void _elm_widget_signal_callback_add(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED, const char *emission, const char *source, Edje_Signal_Cb func, void *data) { EINA_SAFETY_ON_NULL_RETURN(func); if (evas_object_smart_type_check(obj, "elm_layout")) elm_layout_signal_callback_add(obj, emission, source, func, data); else if (evas_object_smart_type_check(obj, "elm_icon")) { WRN("Deprecated function. This functionality on icon objects" " will be dropped on a next release."); _elm_icon_signal_callback_add(obj, emission, source, func, data); } } EOLIAN static void* _elm_widget_signal_callback_del(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED, const char *emission, const char *source, Edje_Signal_Cb func) { void *data = NULL; if (evas_object_smart_type_check(obj, "elm_layout")) data = elm_layout_signal_callback_del(obj, emission, source, func); else if (evas_object_smart_type_check(obj, "elm_icon")) { WRN("Deprecated function. This functionality on icon objects" " will be dropped on a next release."); data = _elm_icon_signal_callback_del(obj, emission, source, func); } return data; } EOLIAN static void _elm_widget_focus_set(Eo *obj, Elm_Widget_Smart_Data *sd, Eina_Bool focus) { if (!sd->focused) { focus_order++; sd->focus_order = focus_order; sd->focused = EINA_TRUE; elm_obj_widget_on_focus(obj, NULL); } if (focus) { if ((_is_focusable(sd->resize_obj)) && (!elm_widget_disabled_get(sd->resize_obj))) { elm_widget_focus_set(sd->resize_obj, focus); } else { const Eina_List *l; Evas_Object *child; EINA_LIST_FOREACH(sd->subobjs, l, child) { if (!_elm_widget_is(child)) continue; if ((_is_focusable(child)) && (!elm_widget_disabled_get(child))) { elm_widget_focus_set(child, focus); break; } } } } else { const Eina_List *l; Evas_Object *child; EINA_LIST_REVERSE_FOREACH(sd->subobjs, l, child) { if (!_elm_widget_is(child)) continue; if ((_is_focusable(child)) && (!elm_widget_disabled_get(child))) { elm_widget_focus_set(child, focus); break; } } } } EOLIAN static Evas_Object* _elm_widget_widget_parent_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd) { return sd->parent_obj; } static void _focused_object_clear(Elm_Widget_Smart_Data *sd) { if (sd->resize_obj && elm_widget_is(sd->resize_obj) && _is_focused(sd->resize_obj)) { elm_obj_widget_focused_object_clear(sd->resize_obj); } else { const Eina_List *l; Evas_Object *child; EINA_LIST_FOREACH(sd->subobjs, l, child) { if (_elm_widget_is(child) && _is_focused(child)) { elm_obj_widget_focused_object_clear(child); break; } } } } EOLIAN static void _elm_widget_focused_object_clear(Eo *obj, Elm_Widget_Smart_Data *sd) { if (!sd->focused) return; _focused_object_clear(sd); sd->focused = EINA_FALSE; if (sd->top_win_focused) elm_obj_widget_on_focus(obj, NULL); } EOLIAN static void _elm_widget_focus_steal(Eo *obj, Elm_Widget_Smart_Data *sd, Elm_Object_Item *item) { Evas_Object *parent, *parent2, *o; if (sd->focused) return; if (sd->disabled) return; if (!sd->can_focus) return; if (sd->tree_unfocusable) return; parent = obj; for (;; ) { o = elm_widget_parent_get(parent); if (!o) break; sd = efl_data_scope_get(o, MY_CLASS); if (sd->disabled || sd->tree_unfocusable) return; if (sd->focused) break; parent = o; } if ((!elm_widget_parent_get(parent)) && (!elm_widget_parent2_get(parent))) elm_obj_widget_focused_object_clear(parent); else { parent2 = elm_widget_parent_get(parent); if (!parent2) parent2 = elm_widget_parent2_get(parent); parent = parent2; sd = efl_data_scope_get(parent, MY_CLASS); if (sd) _focused_object_clear(sd); } _parent_focus(obj, item); elm_widget_focus_region_show(obj); return; } static void _parents_on_focus(Evas_Object *obj) { API_ENTRY return; if (!sd->focused || !sd->top_win_focused) return; Evas_Object *o = elm_widget_parent_get(obj); if (o) _parents_on_focus(o); elm_obj_widget_on_focus(obj, NULL); } EOLIAN static void _elm_widget_focus_restore(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED) { Evas_Object *newest = NULL; unsigned int newest_focus_order = 0; newest = elm_widget_newest_focus_order_get(obj, &newest_focus_order, EINA_TRUE); if (newest) _parents_on_focus(newest); } void _elm_widget_focus_auto_show(Evas_Object *obj) { Evas_Object *top = elm_widget_top_get(obj); if (top && efl_isa(top, EFL_UI_WIN_CLASS)) _elm_win_focus_auto_show(top); } void _elm_widget_top_win_focused_set(Evas_Object *obj, Eina_Bool top_win_focused) { const Eina_List *l; Evas_Object *child; API_ENTRY return; if (sd->top_win_focused == top_win_focused) return; EINA_LIST_FOREACH(sd->subobjs, l, child) { if (elm_widget_is(child)) _elm_widget_top_win_focused_set(child, top_win_focused); } sd->top_win_focused = top_win_focused; if (sd->focused && !sd->top_win_focused) elm_obj_widget_on_focus(obj, NULL); } Eina_Bool _elm_widget_top_win_focused_get(const Evas_Object *obj) { API_ENTRY return EINA_FALSE; return sd->top_win_focused; } static void _elm_widget_disabled_eval(const Evas_Object *obj, Eina_Bool disabled) { const Eina_List *l; Evas_Object *child; ELM_WIDGET_DATA_GET(obj, sd); if (disabled) { EINA_LIST_FOREACH(sd->subobjs, l, child) { if (elm_widget_is(child)) { elm_widget_focus_disabled_handle(child); elm_obj_widget_disable(child); _elm_widget_disabled_eval(child, EINA_TRUE); } } } else { EINA_LIST_FOREACH(sd->subobjs, l, child) if (elm_widget_is(child)) { ELM_WIDGET_DATA_GET(child, sdc); if (!sdc->disabled) { elm_widget_focus_disabled_handle(child); elm_obj_widget_disable(child); _elm_widget_disabled_eval(child, EINA_FALSE); } } } } static void elm_widget_disabled_internal(Eo *obj, Eina_Bool disabled) { Eina_Bool parent_state = EINA_FALSE; if (disabled) { elm_widget_focus_disabled_handle(obj); elm_obj_widget_disable(obj); _elm_widget_disabled_eval(obj, EINA_TRUE); } else { parent_state = elm_widget_disabled_get(elm_widget_parent_get(obj)); if (parent_state) return; elm_widget_focus_disabled_handle(obj); elm_obj_widget_disable(obj); _elm_widget_disabled_eval(obj, EINA_FALSE); } } EOLIAN static void _elm_widget_disabled_set(Eo *obj, Elm_Widget_Smart_Data *sd, Eina_Bool disabled) { if (sd->disabled == disabled) return; sd->disabled = !!disabled; elm_widget_disabled_internal(obj, disabled); if (efl_finalized_get(obj)) _focus_state_eval(obj, sd); } EOLIAN static Eina_Bool _elm_widget_disabled_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd) { Eina_Bool disabled = EINA_FALSE; if (sd->disabled) disabled = EINA_TRUE; else disabled = elm_widget_disabled_get(elm_widget_parent_get(obj)); return disabled; } EOLIAN static void _elm_widget_show_region_set(Eo *obj, Elm_Widget_Smart_Data *sd, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h, Eina_Bool forceshow) { Evas_Object *parent_obj, *child_obj; Evas_Coord px, py, cx, cy, nx = 0, ny = 0; evas_smart_objects_calculate(evas_object_evas_get(obj)); if (!forceshow && (x == sd->rx) && (y == sd->ry) && (w == sd->rw) && (h == sd->rh)) return; sd->rx = x; sd->ry = y; sd->rw = w; sd->rh = h; if (sd->on_show_region) { sd->on_show_region (sd->on_show_region_data, obj); if (_elm_scrollable_is(obj)) { elm_interface_scrollable_content_pos_get(obj, &nx, &ny); x -= nx; y -= ny; } } do { parent_obj = sd->parent_obj; child_obj = sd->obj; if ((!parent_obj) || (!_elm_widget_is(parent_obj))) break; sd = efl_data_scope_get(parent_obj, MY_CLASS); if (!sd) break; evas_object_geometry_get(parent_obj, &px, &py, NULL, NULL); evas_object_geometry_get(child_obj, &cx, &cy, NULL, NULL); x += (cx - px); y += (cy - py); sd->rx = x; sd->ry = y; sd->rw = w; sd->rh = h; if (sd->on_show_region) { sd->on_show_region (sd->on_show_region_data, parent_obj); } } while (parent_obj); } EOLIAN static void _elm_widget_show_region_get(const Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h) { if (x) *x = sd->rx; if (y) *y = sd->ry; if (w) *w = sd->rw; if (h) *h = sd->rh; } /** * @internal * * Get the focus region of the given widget. * * @return show region or not * (@c EINA_TRUE = show region/@c EINA_FALSE = do not show region). Default is @c EINA_FALSE. * * The focus region is the area of a widget that should brought into the * visible area when the widget is focused. Mostly used to show the part of * an entry where the cursor is, for example. The area returned is relative * to the object @p obj. * * @param obj The widget object * @param x Where to store the x coordinate of the area * @param y Where to store the y coordinate of the area * @param w Where to store the width of the area * @param h Where to store the height of the area * * @ingroup Widget */ EOLIAN static Eina_Bool _elm_widget_focus_region_get(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h) { Eina_Bool int_ret = EINA_FALSE; int_ret = elm_obj_widget_on_focus_region((Eo *)obj, x, y, w, h); if (!int_ret) { evas_object_geometry_get(obj, NULL, NULL, w, h); if (x) *x = 0; if (y) *y = 0; } if ((*w <= 0) || (*h <= 0)) return EINA_FALSE; return EINA_TRUE; } EOLIAN static void _elm_widget_parents_bounce_get(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED, Eina_Bool *horiz, Eina_Bool *vert) { Evas_Object *parent_obj = obj; Eina_Bool h = EINA_FALSE, v = EINA_FALSE; *horiz = EINA_FALSE; *vert = EINA_FALSE; do { parent_obj = elm_widget_parent_get(parent_obj); if ((!parent_obj) || (!_elm_widget_is(parent_obj))) break; if (_elm_scrollable_is(parent_obj)) { elm_interface_scrollable_bounce_allow_get(parent_obj, &h, &v); if (h) *horiz = EINA_TRUE; if (v) *vert = EINA_TRUE; } } while (parent_obj); } EOLIAN static Eina_List* _elm_widget_scrollable_children_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd) { Eina_List *ret; ret = NULL; Eina_List *l; Evas_Object *child; EINA_LIST_FOREACH(sd->subobjs, l, child) { if (elm_widget_is(child) && _elm_scrollable_is(child)) ret = eina_list_append(ret, child); } return ret; } EOLIAN static void _elm_widget_scroll_hold_push(Eo *obj, Elm_Widget_Smart_Data *sd) { sd->scroll_hold++; if (sd->scroll_hold == 1) { if (_elm_scrollable_is(obj)) elm_interface_scrollable_hold_set(obj, EINA_TRUE); else { Eina_List *scr_children, *l; Evas_Object *child; scr_children = elm_widget_scrollable_children_get(obj); EINA_LIST_FOREACH(scr_children, l, child) { elm_interface_scrollable_hold_set(child, EINA_TRUE); } eina_list_free(scr_children); } } if (sd->parent_obj) elm_obj_widget_scroll_hold_push(sd->parent_obj); // FIXME: on delete/reparent hold pop } EOLIAN static void _elm_widget_scroll_hold_pop(Eo *obj, Elm_Widget_Smart_Data *sd) { sd->scroll_hold--; if (!sd->scroll_hold) { if (_elm_scrollable_is(obj)) elm_interface_scrollable_hold_set(obj, EINA_FALSE); else { Eina_List *scr_children, *l; Evas_Object *child; scr_children = elm_widget_scrollable_children_get(obj); EINA_LIST_FOREACH(scr_children, l, child) { elm_interface_scrollable_hold_set(child, EINA_FALSE); } eina_list_free(scr_children); } } if (sd->parent_obj) elm_obj_widget_scroll_hold_pop(sd->parent_obj); if (sd->scroll_hold < 0) sd->scroll_hold = 0; } EOLIAN static int _elm_widget_scroll_hold_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd) { return sd->scroll_hold; } EOLIAN static void _elm_widget_scroll_freeze_push(Eo *obj, Elm_Widget_Smart_Data *sd) { sd->scroll_freeze++; if (sd->scroll_freeze == 1) { if (_elm_scrollable_is(obj)) elm_interface_scrollable_freeze_set(obj, EINA_TRUE); else { Eina_List *scr_children, *l; Evas_Object *child; scr_children = elm_widget_scrollable_children_get(obj); EINA_LIST_FOREACH(scr_children, l, child) { elm_interface_scrollable_freeze_set(child, EINA_TRUE); } eina_list_free(scr_children); } } if (sd->parent_obj) elm_obj_widget_scroll_freeze_push(sd->parent_obj); // FIXME: on delete/reparent freeze pop } EOLIAN static void _elm_widget_scroll_freeze_pop(Eo *obj, Elm_Widget_Smart_Data *sd) { sd->scroll_freeze--; if (!sd->scroll_freeze) { if (_elm_scrollable_is(obj)) elm_interface_scrollable_freeze_set(obj, EINA_FALSE); else { Eina_List *scr_children, *l; Evas_Object *child; scr_children = elm_widget_scrollable_children_get(obj); EINA_LIST_FOREACH(scr_children, l, child) { elm_interface_scrollable_freeze_set(child, EINA_FALSE); } eina_list_free(scr_children); } } if (sd->parent_obj) elm_obj_widget_scroll_freeze_pop(sd->parent_obj); if (sd->scroll_freeze < 0) sd->scroll_freeze = 0; } EOLIAN static int _elm_widget_scroll_freeze_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd) { return sd->scroll_freeze; } EOLIAN static void _elm_widget_efl_ui_base_scale_set(Eo *obj, Elm_Widget_Smart_Data *sd, double scale) { if (scale < 0.0) scale = 0.0; if (sd->scale != scale) { sd->scale = scale; elm_widget_theme(obj); } } EOLIAN static double _elm_widget_efl_ui_base_scale_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd) { // FIXME: save walking up the tree by storing/caching parent scale if (sd->scale == 0.0) { if (sd->parent_obj && elm_widget_is(sd->parent_obj)) { return efl_ui_scale_get(sd->parent_obj); } else { return 1.0; } } return sd->scale; } EOLIAN static void _elm_widget_theme_set(Eo *obj, Elm_Widget_Smart_Data *sd, Elm_Theme *th) { Eina_Bool apply = EINA_FALSE; if (sd->theme != th) { if (elm_widget_theme_get(obj) != th) apply = EINA_TRUE; if (sd->theme) elm_theme_free(sd->theme); sd->theme = th; if (th) th->ref++; if (apply) elm_widget_theme(obj); } } EOLIAN static void _elm_widget_part_text_set(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED, const char *part, const char *label) { if (evas_object_smart_type_check(obj, "elm_layout")) elm_layout_text_set(obj, part, label); } EOLIAN static const char* _elm_widget_part_text_get(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED, const char *part) { if (evas_object_smart_type_check(obj, "elm_layout")) return elm_layout_text_get(obj, part); return NULL; } static Elm_Translate_String_Data * _translate_string_data_get(Eina_Inlist *translate_strings, const char *part) { Elm_Translate_String_Data *ts; Eina_Stringshare *str; if (!translate_strings) return NULL; str = eina_stringshare_add(part); EINA_INLIST_FOREACH(translate_strings, ts) { if (ts->id == str) break; } eina_stringshare_del(str); return ts; } static Elm_Translate_String_Data * _part_text_translatable_set(Eina_Inlist **translate_strings, const char *part, Eina_Bool translatable, Eina_Bool preset) { Eina_Inlist *t; Elm_Translate_String_Data *ts; t = *translate_strings; ts = _translate_string_data_get(t, part); if (translatable) { if (!ts) { ts = ELM_NEW(Elm_Translate_String_Data); if (!ts) return NULL; ts->id = eina_stringshare_add(part); t = eina_inlist_append(t, (Eina_Inlist*) ts); } if (preset) ts->preset = EINA_TRUE; } //Delete this exist one if this part has been not preset. //see elm_widget_part_text_translatable_set() else if (ts && ((preset) || (!ts->preset))) { t = eina_inlist_remove(t, EINA_INLIST_GET(ts)); eina_stringshare_del(ts->id); eina_stringshare_del(ts->domain); eina_stringshare_del(ts->string); ELM_SAFE_FREE(ts, free); } *translate_strings = t; return ts; } EOLIAN static void _elm_widget_domain_translatable_part_text_set(Eo *obj, Elm_Widget_Smart_Data *sd, const char *part, const char *domain, const char *label) { Elm_Translate_String_Data *ts; if (!label) { _part_text_translatable_set(&sd->translate_strings, part, EINA_FALSE, EINA_FALSE); } else { ts = _part_text_translatable_set(&sd->translate_strings, part, EINA_TRUE, EINA_FALSE); if (!ts) return; if (!ts->string) ts->string = eina_stringshare_add(label); else eina_stringshare_replace(&ts->string, label); if (!ts->domain) ts->domain = eina_stringshare_add(domain); else eina_stringshare_replace(&ts->domain, domain); #ifdef HAVE_GETTEXT if (label[0]) label = dgettext(domain, label); #endif } sd->on_translate = EINA_TRUE; elm_obj_widget_part_text_set(obj, part, label); sd->on_translate = EINA_FALSE; } EOLIAN static const char* _elm_widget_translatable_part_text_get(const Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd, const char *part) { Elm_Translate_String_Data *ts; ts = _translate_string_data_get(sd->translate_strings, part); if (ts) return ts->string; else return NULL; } EOLIAN static void _elm_widget_domain_part_text_translatable_set(Eo *obj, Elm_Widget_Smart_Data *sd, const char *part, const char *domain, Eina_Bool translatable) { Elm_Translate_String_Data *ts; const char *text = NULL; ts = _part_text_translatable_set(&sd->translate_strings, part, translatable, EINA_TRUE); if (!ts) return; if (!ts->domain) ts->domain = eina_stringshare_add(domain); else eina_stringshare_replace(&ts->domain, domain); text = elm_obj_widget_part_text_get(obj, part); if (!text || !text[0]) return; if (!ts->string) ts->string = eina_stringshare_add(text); //Try to translate text since we don't know the text is already translated. #ifdef HAVE_GETTEXT text = dgettext(domain, text); #endif sd->on_translate = EINA_TRUE; elm_obj_widget_part_text_set(obj, part, text); sd->on_translate = EINA_FALSE; } EAPI void elm_widget_translate(Evas_Object *obj) { ELM_WIDGET_CHECK(obj); elm_obj_widget_translate(obj); } static const char* _part_text_translate(Eina_Inlist *translate_strings, const char *part, const char *text) { Elm_Translate_String_Data *ts; ts = _translate_string_data_get(translate_strings, part); if (!ts) return text; if (!ts->string) ts->string = eina_stringshare_add(text); else eina_stringshare_replace(&ts->string, text); #ifdef HAVE_GETTEXT if (text && text[0]) text = dgettext(ts->domain, text); #endif return text; } EOLIAN static const char* _elm_widget_part_text_translate(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd, const char *part, const char *text) { if (!sd->translate_strings || sd->on_translate) return text; return _part_text_translate(sd->translate_strings, part, text); } EOLIAN static Eina_Bool _elm_widget_translate(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *_pd EINA_UNUSED) { const Eina_List *l; Evas_Object *child; API_ENTRY return EINA_FALSE; EINA_LIST_FOREACH(sd->subobjs, l, child) { if (elm_widget_is(child)) elm_widget_translate(child); } if (sd->hover_obj) elm_widget_translate(sd->hover_obj); #ifdef HAVE_GETTEXT Elm_Translate_String_Data *ts; EINA_INLIST_FOREACH(sd->translate_strings, ts) { if (!ts->string) continue; const char *s = dgettext(ts->domain, ts->string); sd->on_translate = EINA_TRUE; elm_obj_widget_part_text_set(obj, ts->id, s); sd->on_translate = EINA_FALSE; } #endif efl_event_callback_legacy_call(obj, ELM_WIDGET_EVENT_LANGUAGE_CHANGED, NULL); return EINA_TRUE; } /** * @internal * * Resets the focus_move_policy mode from the system one * for widgets that are in automatic mode. * * @param obj The widget. * */ static void _elm_widget_focus_move_policy_reload(Evas_Object *obj) { API_ENTRY return; Elm_Focus_Move_Policy focus_move_policy = elm_config_focus_move_policy_get(); if (elm_widget_focus_move_policy_automatic_get(obj) && (sd->focus_move_policy != focus_move_policy)) { sd->focus_move_policy = focus_move_policy; } } EOLIAN static void _elm_widget_focus_reconfigure(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED) { const Eina_List *l; Evas_Object *child; API_ENTRY return; EINA_LIST_FOREACH(sd->subobjs, l, child) { if (elm_widget_is(child)) elm_widget_focus_reconfigure(child); } if (sd->hover_obj) elm_widget_focus_reconfigure(sd->hover_obj); _elm_widget_focus_move_policy_reload(obj); } EAPI void elm_widget_content_part_set(Evas_Object *obj, const char *part, Evas_Object *content) { ELM_WIDGET_CHECK(obj); efl_content_set(efl_part(obj, part), content); } EAPI Evas_Object * elm_widget_content_part_get(const Evas_Object *obj, const char *part) { ELM_WIDGET_CHECK(obj) NULL; return efl_content_get(efl_part(obj, part)); } EAPI Evas_Object * elm_widget_content_part_unset(Evas_Object *obj, const char *part) { ELM_WIDGET_CHECK(obj) NULL; return efl_content_unset(efl_part(obj, part)); } EOLIAN static void _elm_widget_access_info_set(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd, const char *txt) { eina_stringshare_del(sd->access_info); if (!txt) sd->access_info = NULL; else sd->access_info = eina_stringshare_add(txt); } EOLIAN static const char* _elm_widget_access_info_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd) { return sd->access_info; } EOLIAN static Elm_Theme* _elm_widget_theme_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd) { if (!sd->theme) { if (sd->parent_obj && elm_widget_is(sd->parent_obj)) return elm_widget_theme_get(sd->parent_obj); else return NULL; } return sd->theme; } EOLIAN static Elm_Theme_Apply _elm_widget_style_set(Eo *obj, Elm_Widget_Smart_Data *sd, const char *style) { if (eina_stringshare_replace(&sd->style, style)) return elm_widget_theme(obj); return ELM_THEME_APPLY_SUCCESS; } EOLIAN static const char* _elm_widget_style_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd) { const char *ret; ret = "default"; if (sd->style) ret = sd->style; return ret; } EOLIAN static void _elm_widget_tooltip_add(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd, Elm_Tooltip *tt) { sd->tooltips = eina_list_append(sd->tooltips, tt); } EOLIAN static void _elm_widget_tooltip_del(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd, Elm_Tooltip *tt) { sd->tooltips = eina_list_remove(sd->tooltips, tt); } EAPI void elm_widget_cursor_add(Eo *obj, Elm_Cursor *cur) { Elm_Widget_Smart_Data *sd = efl_data_scope_safe_get(obj, MY_CLASS); if (!sd) return; sd->cursors = eina_list_append(sd->cursors, cur); } EAPI void elm_widget_cursor_del(Eo *obj, Elm_Cursor *cur) { Elm_Widget_Smart_Data *sd = efl_data_scope_safe_get(obj, MY_CLASS); if (!sd) return; sd->cursors = eina_list_remove(sd->cursors, cur); } EOLIAN static void _elm_widget_drag_lock_x_set(Eo *obj, Elm_Widget_Smart_Data *sd, Eina_Bool lock) { if (sd->drag_x_locked == lock) return; sd->drag_x_locked = lock; if (sd->drag_x_locked) _propagate_x_drag_lock(obj, 1); else _propagate_x_drag_lock(obj, -1); } EOLIAN static void _elm_widget_drag_lock_y_set(Eo *obj, Elm_Widget_Smart_Data *sd, Eina_Bool lock) { if (sd->drag_y_locked == lock) return; sd->drag_y_locked = lock; if (sd->drag_y_locked) _propagate_y_drag_lock(obj, 1); else _propagate_y_drag_lock(obj, -1); } EOLIAN static Eina_Bool _elm_widget_drag_lock_x_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd) { return sd->drag_x_locked; } EOLIAN static Eina_Bool _elm_widget_drag_lock_y_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd) { return sd->drag_y_locked; } EOLIAN static int _elm_widget_drag_child_locked_x_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd) { return sd->child_drag_x_locked; } EOLIAN static int _elm_widget_drag_child_locked_y_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd) { return sd->child_drag_y_locked; } EOLIAN static void _elm_widget_item_loop_enabled_set(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd EINA_UNUSED, Eina_Bool enable EINA_UNUSED) { return; } EOLIAN static Eina_Bool _elm_widget_item_loop_enabled_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd EINA_UNUSED) { return EINA_FALSE; } EOLIAN static Elm_Theme_Apply _elm_widget_theme_object_set(Eo *obj, Elm_Widget_Smart_Data *sd, Evas_Object *edj, const char *wname, const char *welement, const char *wstyle) { Elm_Theme_Apply ret = _elm_theme_object_set(obj, edj, wname, welement, wstyle); if (!ret) { return ELM_THEME_APPLY_FAILED; } if (sd->orient_mode != -1) { char buf[128]; snprintf(buf, sizeof(buf), "elm,state,orient,%d", sd->orient_mode); elm_obj_widget_signal_emit(obj, buf, "elm"); } return ret; } static void _convert(Efl_Dbg_Info *info, Eina_Iterator *ptr_list) { void *p; int i = 0; EINA_ITERATOR_FOREACH(ptr_list, p) { char name[100]; snprintf(name, sizeof(name), "Candidate %d", i); EFL_DBG_INFO_APPEND(info, name, EINA_VALUE_TYPE_UINT64, p); i++; } eina_iterator_free(ptr_list); } EOLIAN static void _elm_widget_efl_object_dbg_info_get(Eo *eo_obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED, Efl_Dbg_Info *root) { efl_dbg_info_get(efl_super(eo_obj, MY_CLASS), root); Efl_Ui_Focus_Relations *rel = NULL; Efl_Dbg_Info *focus, *group = EFL_DBG_INFO_LIST_APPEND(root, MY_CLASS_NAME); EFL_DBG_INFO_APPEND(group, "Wid-Type", EINA_VALUE_TYPE_STRING, elm_widget_type_get(eo_obj)); EFL_DBG_INFO_APPEND(group, "Style", EINA_VALUE_TYPE_STRING, elm_widget_style_get(eo_obj)); EFL_DBG_INFO_APPEND(group, "Layer", EINA_VALUE_TYPE_INT, (int) evas_object_layer_get(eo_obj)); EFL_DBG_INFO_APPEND(group, "Scale", EINA_VALUE_TYPE_DOUBLE, evas_object_scale_get(eo_obj)); EFL_DBG_INFO_APPEND(group, "Has focus", EINA_VALUE_TYPE_CHAR, elm_object_focus_get(eo_obj)); EFL_DBG_INFO_APPEND(group, "Can focus", EINA_VALUE_TYPE_CHAR, elm_widget_can_focus_get(eo_obj)); EFL_DBG_INFO_APPEND(group, "Disabled", EINA_VALUE_TYPE_CHAR, elm_widget_disabled_get(eo_obj)); EFL_DBG_INFO_APPEND(group, "Mirrored", EINA_VALUE_TYPE_CHAR, efl_ui_mirrored_get(eo_obj)); EFL_DBG_INFO_APPEND(group, "Tree Unfocusable", EINA_VALUE_TYPE_CHAR, elm_widget_tree_unfocusable_get(eo_obj)); EFL_DBG_INFO_APPEND(group, "Automatic mirroring", EINA_VALUE_TYPE_CHAR, - elm_widget_mirrored_automatic_get(eo_obj)); + efl_ui_mirrored_automatic_get(eo_obj)); rel = efl_ui_focus_manager_fetch(_pd->focus.manager, eo_obj); if (rel) { focus = EFL_DBG_INFO_LIST_APPEND(group, "Focus"); EFL_DBG_INFO_APPEND(focus, "type", EINA_VALUE_TYPE_STRING, rel->type); EFL_DBG_INFO_APPEND(focus, "manager", EINA_VALUE_TYPE_UINT64, _pd->focus.manager); EFL_DBG_INFO_APPEND(focus, "parent", EINA_VALUE_TYPE_UINT64, rel->parent); EFL_DBG_INFO_APPEND(focus, "next", EINA_VALUE_TYPE_UINT64 , rel->next); EFL_DBG_INFO_APPEND(focus, "prev", EINA_VALUE_TYPE_UINT64 , rel->prev); EFL_DBG_INFO_APPEND(focus, "redirect", EINA_VALUE_TYPE_UINT64 , rel->redirect); #define ADD_PTR_LIST(name) \ Efl_Dbg_Info* name = EFL_DBG_INFO_LIST_APPEND(focus, ""#name""); \ _convert(name, eina_list_iterator_new(rel->name)); ADD_PTR_LIST(top) ADD_PTR_LIST(down) ADD_PTR_LIST(right) ADD_PTR_LIST(left) #undef ADD_PTR_LIST } //if thats a focus manager, give useful information like the border elements if (efl_isa(eo_obj, EFL_UI_FOCUS_MANAGER_CLASS)) { Efl_Dbg_Info *border; focus = EFL_DBG_INFO_LIST_APPEND(group, "Focus Manager"); border = EFL_DBG_INFO_LIST_APPEND(focus, "Border Elements"); _convert(border, efl_ui_focus_manager_border_elements_get(eo_obj) ); EFL_DBG_INFO_APPEND(focus, "redirect", EINA_VALUE_TYPE_UINT64, efl_ui_focus_manager_redirect_get(eo_obj)); } } EAPI Eina_Bool elm_widget_is_check(const Evas_Object *obj) { static int abort_on_warn = -1; if (elm_widget_is(obj)) return EINA_TRUE; ERR("Passing Object: %p.", obj); if (abort_on_warn == -1) { if (getenv("ELM_ERROR_ABORT")) abort_on_warn = 1; else abort_on_warn = 0; } if (abort_on_warn == 1) abort(); return EINA_FALSE; } EAPI const char * elm_widget_type_get(const Evas_Object *obj) { API_ENTRY return NULL; return efl_class_name_get(efl_class_get(obj)); } EAPI Eina_Bool elm_widget_type_check(const Evas_Object *obj, const char *type, const char *func) { const char *provided, *expected = "(unknown)"; static int abort_on_warn = -1; provided = elm_widget_type_get(obj); /* TODO: eventually migrate to check_ptr version */ if (evas_object_smart_type_check(obj, type)) return EINA_TRUE; if (type) expected = type; if ((!provided) || (!provided[0])) { provided = evas_object_type_get(obj); if ((!provided) || (!provided[0])) provided = "(unknown)"; } ERR("Passing Object: %p in function: %s, of type: '%s' when expecting" " type: '%s'", obj, func, provided, expected); if (abort_on_warn == -1) { if (getenv("ELM_ERROR_ABORT")) abort_on_warn = 1; else abort_on_warn = 0; } if (abort_on_warn == 1) abort(); return EINA_FALSE; } static Evas_Object * _widget_name_find(const Evas_Object *obj, const char *name, int recurse) { Eina_List *l; Evas_Object *child; const char *s; INTERNAL_ENTRY NULL; if (!_elm_widget_is(obj)) return NULL; EINA_LIST_FOREACH(sd->subobjs, l, child) { s = evas_object_name_get(child); if ((s) && (!strcmp(s, name))) return child; if ((recurse != 0) && ((child = _widget_name_find(child, name, recurse - 1)))) return child; } if (sd->hover_obj) { s = evas_object_name_get(sd->hover_obj); if ((s) && (!strcmp(s, name))) return sd->hover_obj; if ((recurse != 0) && ((child = _widget_name_find(sd->hover_obj, name, recurse - 1)))) return child; } return NULL; } EOLIAN static Evas_Object* _elm_widget_name_find(const Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED, const char *name, int recurse) { if (!name) return NULL; return _widget_name_find(obj, name, recurse); } /** * @internal * * Split string in words * * @param str Source string * @return List of const words * * @see elm_widget_stringlist_free() * @ingroup Widget */ EAPI Eina_List * elm_widget_stringlist_get(const char *str) { Eina_List *list = NULL; const char *s, *b; if (!str) return NULL; for (b = s = str; 1; s++) { if ((*s == ' ') || (!*s)) { char *t = malloc(s - b + 1); if (t) { strncpy(t, b, s - b); t[s - b] = 0; list = eina_list_append(list, eina_stringshare_add(t)); free(t); } b = s + 1; } if (!*s) break; } return list; } EAPI void elm_widget_stringlist_free(Eina_List *list) { const char *s; EINA_LIST_FREE(list, s) eina_stringshare_del(s); } EOLIAN static void _elm_widget_focus_hide_handle(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED) { if (!_elm_widget_is(obj)) return; _if_focused_revert(obj, EINA_TRUE); } EAPI void elm_widget_focus_mouse_up_handle(Evas_Object *obj) { Evas_Object *o = obj; do { if (_elm_widget_is(o)) break; o = evas_object_smart_parent_get(o); } while (o); elm_obj_widget_focus_mouse_up_handle(o); } EOLIAN static void _elm_widget_focus_mouse_up_handle(Eo *obj, Elm_Widget_Smart_Data *pd) { if (!obj) return; if (!_is_focusable(obj)) return; elm_widget_focus_steal(obj, NULL); if (pd->focus.manager && !pd->focus.logical) { Efl_Ui_Focus_Manager *m, *m2 = obj, *old = NULL; /* * The object we have clicked could be registered in a submanager. * This means we need to look as long as possible to higher redirect managers. * And set them to the redirect manager. */ m = elm_widget_top_get(obj); m2 = efl_ui_focus_user_manager_get(obj); if (m2 != m) { //first unset all redirect properties old = m; do { Efl_Ui_Focus_Manager *tmp; tmp = efl_ui_focus_manager_redirect_get(old); if (tmp) efl_ui_focus_manager_redirect_set(old, NULL); old = tmp; } while(old); //now set the redirect path to the new object do { Efl_Ui_Focus_Manager *new_manager;; new_manager = efl_ui_focus_user_manager_get(m2); //new manager is in a higher hirarchy than m2 //so we set m2 as redirect in new_manager efl_ui_focus_manager_redirect_set(new_manager, m2); m2 = new_manager; } while(m && m2 && m != m2); } efl_ui_focus_manager_focus(pd->focus.manager, obj); } } EOLIAN static void _elm_widget_focus_tree_unfocusable_handle(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED) { if (!elm_widget_parent_get(obj)) elm_widget_focused_object_clear(obj); else _if_focused_revert(obj, EINA_TRUE); } EOLIAN static void _elm_widget_focus_disabled_handle(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED) { elm_widget_focus_tree_unfocusable_handle(obj); } EOLIAN static unsigned int _elm_widget_focus_order_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd) { return sd->focus_order; } EOLIAN static Evas_Object* _elm_widget_newest_focus_order_get(const Eo *obj, Elm_Widget_Smart_Data *sd, unsigned int *newest_focus_order, Eina_Bool can_focus_only) { const Eina_List *l; Evas_Object *child, *cur, *best; if (!evas_object_visible_get(obj) || (elm_widget_disabled_get(obj)) || (elm_widget_tree_unfocusable_get(obj))) return NULL; best = NULL; if (*newest_focus_order < sd->focus_order) { if (!can_focus_only || elm_widget_can_focus_get(obj)) { *newest_focus_order = sd->focus_order; best = (Evas_Object *)obj; } } EINA_LIST_FOREACH(sd->subobjs, l, child) { if (!_elm_widget_is(child)) continue; cur = elm_widget_newest_focus_order_get (child, newest_focus_order, can_focus_only); if (!cur) continue; best = cur; } return best; } /* * @internal * * Get the focus highlight geometry of a widget. * * @param obj Widget object for the focus highlight * @param x Focus highlight x coordinate * @param y Focus highlight y coordinate * @param w Focus highlight object width * @param h Focus highlight object height * @param is_next @c EINA_TRUE if this request is for the new focused object, * @c EINA_FALSE if this request is for the previously focused object. This * information becomes important when the focus highlight is changed inside one * widget. * * @ingroup Widget */ /* * @internal * * Get the 'focus_part' geometry if there is any * * This queries if there is a 'focus_part' request from the edc style. If edc * style offers 'focus_part' edje data item, this function requests for the * geometry of a specific part which is described in 'focus_part' edje data. * * @param obj Widget object for the focus highlight * @param x Focus highlight x coordinate * @param y Focus highlight y coordinate * @param w Focus highlight object width * @param h Focus highlight object height * * x, y, w, h already contain the object's geometry. If there is a 'focus_part' * support, these values will be updated accordingly or the values will be * remained as they were. * * @ingroup Widget */ EAPI void elm_widget_focus_highlight_focus_part_geometry_get(const Evas_Object *obj, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h) { Evas_Coord tx = 0, ty = 0, tw = 0, th = 0; const char *target_hl_part = NULL; const Evas_Object *edje_obj = NULL; if (obj && efl_isa(obj, EDJE_OBJECT_CLASS)) { edje_obj = obj; if (!(target_hl_part = edje_object_data_get(edje_obj, "focus_part"))) return; } else if (obj && efl_isa(obj, ELM_LAYOUT_CLASS)) { edje_obj = elm_layout_edje_get(obj); if (!(target_hl_part = elm_layout_data_get(obj, "focus_part"))) return; } else return; edje_object_part_geometry_get(edje_obj, target_hl_part, &tx, &ty, &tw, &th); *x += tx; *y += ty; if (tw != *w) *w = tw; if (th != *h) *h = th; } EOLIAN static void _elm_widget_focus_highlight_geometry_get(const Eo *obj, Elm_Widget_Smart_Data *sd, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h) { Evas_Coord ox = 0, oy = 0, ow = 0, oh = 0; Evas_Object *scroller = (Evas_Object *)obj; evas_object_geometry_get(obj, x, y, w, h); elm_widget_focus_highlight_focus_part_geometry_get(sd->resize_obj, x, y, w, h); if (_elm_config->focus_autoscroll_mode != ELM_FOCUS_AUTOSCROLL_MODE_BRING_IN) return; while (scroller) { if (_elm_scrollable_is(scroller)) { elm_interface_scrollable_content_viewport_geometry_get(scroller, &ox, &oy, &ow, &oh); if (*y < oy) *y = oy; else if ((oy + oh) < (*y + *h)) *y = (oy + oh - *h); else if (*x < ox) *x = ox; else if ((ox + ow) < (*x + *w)) *x = (ox + ow - *w); break; } scroller = elm_widget_parent_get(scroller); } } EOLIAN static Elm_Object_Item* _elm_widget_focused_item_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *_pd EINA_UNUSED) { return NULL; } EOLIAN static void _elm_widget_focus_region_show_mode_set(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *_pd, Elm_Focus_Region_Show_Mode mode) { _pd->focus_region_show_mode = mode; } EOLIAN static Elm_Focus_Region_Show_Mode _elm_widget_focus_region_show_mode_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *_pd) { return _pd->focus_region_show_mode; } EAPI void elm_widget_activate(Evas_Object *obj, Elm_Activate act) { Evas_Object *parent; Eina_Bool ret; ELM_WIDGET_CHECK(obj); ret = EINA_FALSE; ret = elm_obj_widget_activate(obj, act); if (ret) return; parent = elm_widget_parent_get(obj); if (parent) elm_widget_activate(parent, act); return; } /** * @internal * * Sets the widget and child widget's Evas_Display_Mode. * * @param obj The widget. * @param dispmode Evas_Display_Mode to set widget's mode. * * Widgets are resized by several reasons. * Evas_Display_Mode can help for widgets to get one more reason of resize. * For example, elm conform widget resizes it's contents when keypad state changed. * After keypad showing, conform widget can change child's Evas_Display_Mode. * @ingroup Widget */ /* Legacy only */ EAPI void elm_widget_display_mode_set(Evas_Object *obj, Evas_Display_Mode dispmode) { Evas_Display_Mode prev_dispmode; Evas_Object *child; Eina_List *l; API_ENTRY return; prev_dispmode = evas_object_size_hint_display_mode_get(obj); if ((prev_dispmode == dispmode) || (prev_dispmode == EVAS_DISPLAY_MODE_DONT_CHANGE)) return; evas_object_size_hint_display_mode_set(obj, dispmode); EINA_LIST_FOREACH (sd->subobjs, l, child) { if (elm_widget_is(child)) elm_widget_display_mode_set(child, dispmode); } } EOLIAN static void _elm_widget_orientation_mode_disabled_set(Eo *obj, Elm_Widget_Smart_Data *sd, Eina_Bool disabled) { int orient_mode = -1; if (!disabled) { //Get current orient mode from it's parent otherwise, 0. sd->orient_mode = 0; ELM_WIDGET_DATA_GET(sd->parent_obj, sd_parent); if (!sd_parent) orient_mode = 0; else orient_mode = sd_parent->orient_mode; } elm_obj_widget_orientation_set(obj, orient_mode); } EOLIAN static Eina_Bool _elm_widget_orientation_mode_disabled_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd) { if (sd->orient_mode == -1) return EINA_TRUE; else return EINA_FALSE; } EOLIAN static void _elm_widget_orientation_set(Eo *obj, Elm_Widget_Smart_Data *sd, int orient_mode) { Evas_Object *child; Eina_List *l; sd->orient_mode = orient_mode; EINA_LIST_FOREACH (sd->subobjs, l, child) { if (elm_widget_is(child)) elm_obj_widget_orientation_set(child, orient_mode); } if (orient_mode != -1) { char buf[128]; snprintf(buf, sizeof(buf), "elm,state,orient,%d", orient_mode); elm_obj_widget_signal_emit(obj, buf, "elm"); } } /** * @internal * * Returns the widget's focus move policy. * * @param obj The widget. * @return focus move policy of the object. * **/ EOLIAN static Elm_Focus_Move_Policy _elm_widget_focus_move_policy_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd) { return sd->focus_move_policy; } /** * @internal * * Sets the widget's focus move policy. * * @param obj The widget. * @param policy Elm_Focus_Move_Policy to set object's focus move policy. */ EOLIAN static void _elm_widget_focus_move_policy_set(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd, Elm_Focus_Move_Policy policy) { if (sd->focus_move_policy == policy) return; sd->focus_move_policy = policy; } /** * Returns the widget's focus_move_policy mode setting. * * @param obj The widget. * @return focus_move_policy mode setting of the object. * **/ EOLIAN static Eina_Bool _elm_widget_focus_move_policy_automatic_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd) { return sd->focus_move_policy_auto_mode; } /** * @internal * * Sets the widget's focus_move_policy mode setting. * When widget in automatic mode, it follows the system focus_move_policy mode set by * elm_config_focus_move_policy_set(). * @param obj The widget. * @param automatic EINA_TRUE for auto focus_move_policy mode. EINA_FALSE for manual. */ EOLIAN static void _elm_widget_focus_move_policy_automatic_set(Eo *obj, Elm_Widget_Smart_Data *sd, Eina_Bool automatic) { if (sd->focus_move_policy_auto_mode != automatic) { sd->focus_move_policy_auto_mode = automatic; if (automatic) { elm_widget_focus_move_policy_set(obj, elm_config_focus_move_policy_get()); } } } static void _track_obj_del(void *data, Evas *e, Evas_Object *obj, void *event_info); static void _track_obj_update(Evas_Object *track, Evas_Object *obj) { //Geometry Evas_Coord x, y, w, h; evas_object_geometry_get(obj, &x, &y, &w, &h); evas_object_move(track, x, y); evas_object_resize(track, w, h); //Visibility if (evas_object_visible_get(obj)) evas_object_show(track); else evas_object_hide(track); } static void _track_obj_view_update(void *data, const Efl_Event *event) { Elm_Widget_Item_Data *item = data; _track_obj_update(item->track_obj, event->object); } static void _track_obj_view_del(void *data, const Efl_Event *event); EFL_CALLBACKS_ARRAY_DEFINE(tracker_callbacks, { EFL_GFX_EVENT_RESIZE, _track_obj_view_update }, { EFL_GFX_EVENT_MOVE, _track_obj_view_update }, { EFL_GFX_EVENT_SHOW, _track_obj_view_update }, { EFL_GFX_EVENT_HIDE, _track_obj_view_update }, { EFL_EVENT_DEL, _track_obj_view_del }); static void _track_obj_view_del(void *data, const Efl_Event *event EINA_UNUSED) { Elm_Widget_Item_Data *item = data; while (evas_object_ref_get(item->track_obj) > 0) evas_object_unref(item->track_obj); evas_object_event_callback_del(item->track_obj, EVAS_CALLBACK_DEL, _track_obj_del); evas_object_del(item->track_obj); item->track_obj = NULL; } static void _track_obj_del(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) { Elm_Widget_Item_Data *item = data; item->track_obj = NULL; if (!item->view) return; efl_event_callback_array_del(item->view, tracker_callbacks(), item); } static void _elm_widget_item_signal_cb(void *data, Evas_Object *obj EINA_UNUSED, const char *emission, const char *source) { Elm_Widget_Item_Signal_Data *wisd = data; wisd->func(wisd->data, wisd->item, emission, source); } static void * _elm_widget_item_signal_callback_list_get(Elm_Widget_Item_Data *item, Eina_List *position) { Elm_Widget_Item_Signal_Data *wisd = eina_list_data_get(position); void *data; item->signals = eina_list_remove_list(item->signals, position); data = wisd->data; if (_elm_widget_is(item->view)) elm_object_signal_callback_del(item->view, wisd->emission, wisd->source, _elm_widget_item_signal_cb); else if (efl_isa(item->view, EDJE_OBJECT_CLASS)) edje_object_signal_callback_del_full(item->view, wisd->emission, wisd->source, _elm_widget_item_signal_cb, wisd); eina_stringshare_del(wisd->emission); eina_stringshare_del(wisd->source); free(wisd); return data; } #define ERR_NOT_SUPPORTED(item, method) ERR("%s does not support %s API.", elm_widget_type_get(item->widget), method); static void _efl_del_cb(void *data EINA_UNUSED, const Efl_Event *event) { Elm_Widget_Item_Data *item = efl_data_scope_get(event->object, ELM_WIDGET_ITEM_CLASS); ELM_WIDGET_ITEM_CHECK_OR_RETURN(item); if (item->del_func) item->del_func((void *) WIDGET_ITEM_DATA_GET(event->object), item->widget, item->eo_obj); } /** * @internal * * Allocate a new Elm_Widget_Item-derived structure. * * The goal of this structure is to provide common ground for actions * that a widget item have, such as the owner widget, callback to * notify deletion, data pointer and maybe more. * * @param widget the owner widget that holds this item, must be an elm_widget! * @param alloc_size any number greater than sizeof(Elm_Widget_Item) that will * be used to allocate memory. * * @return allocated memory that is already zeroed out, or NULL on errors. * * @see elm_widget_item_new() convenience macro. * @see elm_widget_item_del() to release memory. * @ingroup Widget */ EOLIAN static Eo * _elm_widget_item_efl_object_constructor(Eo *eo_item, Elm_Widget_Item_Data *item) { Evas_Object *widget; widget = efl_parent_get(eo_item); if (!_elm_widget_is(widget)) { ERR("Failed"); return NULL; } eo_item = efl_constructor(efl_super(eo_item, ELM_WIDGET_ITEM_CLASS)); EINA_MAGIC_SET(item, ELM_WIDGET_ITEM_MAGIC); item->widget = widget; item->eo_obj = eo_item; efl_event_callback_add(eo_item, EFL_EVENT_DEL, _efl_del_cb, NULL); return eo_item; } EOLIAN static void _elm_widget_item_efl_object_destructor(Eo *eo_item, Elm_Widget_Item_Data *item) { Elm_Translate_String_Data *ts; ELM_WIDGET_ITEM_CHECK_OR_RETURN(item); evas_object_del(item->view); eina_stringshare_del(item->access_info); eina_stringshare_del(item->accessible_name); while (item->signals) _elm_widget_item_signal_callback_list_get(item, item->signals); while (item->translate_strings) { ts = EINA_INLIST_CONTAINER_GET(item->translate_strings, Elm_Translate_String_Data); eina_stringshare_del(ts->id); eina_stringshare_del(ts->domain); eina_stringshare_del(ts->string); item->translate_strings = eina_inlist_remove(item->translate_strings, item->translate_strings); free(ts); } eina_hash_free(item->labels); elm_interface_atspi_accessible_removed(eo_item); EINA_MAGIC_SET(item, EINA_MAGIC_NONE); efl_destructor(efl_super(eo_item, ELM_WIDGET_ITEM_CLASS)); } /** * @internal * * Releases widget item memory, calling back item_del_pre_hook() and * item_del_cb() if they exist. * * @param item a valid #Elm_Widget_Item to be deleted. * * If there is an Elm_Widget_Item::del_cb, then it will be called prior * to memory release. Note that elm_widget_item_pre_notify_del() calls * this function and then unset it, thus being useful for 2 step * cleanup whenever the del_cb may use any of the data that must be * deleted from item. * * The Elm_Widget_Item::view will be deleted (evas_object_del()) if it * is presented! * * Note that if item_del_pre_hook() returns @c EINA_TRUE, item free will be * deferred, or item will be freed here if it returns @c EINA_FALSE. * * @see elm_widget_item_del() convenience macro. * @ingroup Widget */ EOLIAN static void _elm_widget_item_del(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item) { ELM_WIDGET_ITEM_CHECK_OR_RETURN(item); ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item); item->on_deletion = EINA_TRUE; //Widget item delete callback Eina_Bool del_ok; del_ok = elm_wdg_item_del_pre(item->eo_obj); if (del_ok) efl_del(item->eo_obj); return; } EOLIAN static Eina_Bool _elm_widget_item_del_pre(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item EINA_UNUSED) { return EINA_TRUE; } /** * @internal * * Notify object will be deleted without actually deleting it. * * This function will callback Elm_Widget_Item::del_cb if it is set * and then unset it so it is not called twice (ie: from * elm_widget_item_del()). * * @param item a valid #Elm_Widget_Item to be notified * @see elm_widget_item_pre_notify_del() convenience macro. * @ingroup Widget */ EOLIAN static void _elm_widget_item_pre_notify_del(Eo *eo_item, Elm_Widget_Item_Data *item) { ELM_WIDGET_ITEM_CHECK_OR_RETURN(item); if (!item->del_func) return; item->del_func((void *)WIDGET_ITEM_DATA_GET(eo_item), item->widget, item->eo_obj); item->del_func = NULL; } /** * @internal * * Set the function to notify when item is being deleted. * * This function will complain if there was a callback set already, * however it will set the new one. * * The callback will be called from elm_widget_item_pre_notify_del() * or elm_widget_item_del() will be called with: * - data: the Elm_Widget_Item::data value. * - obj: the Elm_Widget_Item::widget evas object. * - event_info: the item being deleted. * * @param item a valid #Elm_Widget_Item to be notified * @see elm_widget_item_del_cb_set() convenience macro. * @ingroup Widget */ EOLIAN static void _elm_widget_item_del_cb_set(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item, Evas_Smart_Cb func) { ELM_WIDGET_ITEM_CHECK_OR_RETURN(item); ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item); if ((item->del_func) && (item->del_func != func)) WRN("You're replacing a previously set del_cb %p of item %p with %p", item->del_func, item->eo_obj, func); item->del_func = func; } /** * @internal * * Get owner widget of this item. * * @param item a valid #Elm_Widget_Item to get data from. * @return owner widget of this item. * @ingroup Widget */ EOLIAN static Evas_Object * _elm_widget_item_widget_get(const Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item) { ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL); ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item, NULL); return item->widget; } EAPI Eina_Bool _elm_widget_onscreen_is(Evas_Object *widget) { Evas_Object *parent = widget; Eina_Rectangle r1, r2; Evas *evas = evas_object_evas_get(widget); if (!evas) return EINA_FALSE; evas_object_geometry_get(widget, &r1.x, &r1.y, &r1.w, &r1.h); if (eina_rectangle_is_empty(&r1)) return EINA_FALSE; // check if on canvas evas_output_viewport_get(evas, &r2.x, &r2.y, &r2.w, &r2.h); if (!eina_rectangles_intersect(&r1, &r2)) return EINA_FALSE; // check if inside scrollable parent viewport do { parent = elm_widget_parent_get(parent); if (parent && !evas_object_visible_get(parent)) return EINA_FALSE; if (parent && efl_isa(parent, ELM_INTERFACE_SCROLLABLE_MIXIN)) { evas_object_geometry_get(parent, &r2.x, &r2.y, &r2.w, &r2.h); if (!eina_rectangles_intersect(&r1, &r2)) return EINA_FALSE; } } while (parent && (parent != elm_widget_top_get(widget))); return EINA_TRUE; } EAPI Eina_Bool _elm_widget_item_onscreen_is(Elm_Object_Item *item) { Eina_Rectangle r1, r2; Elm_Widget_Item_Data *id = efl_data_scope_get(item, ELM_WIDGET_ITEM_CLASS); if (!id || !id->view) return EINA_FALSE; if (!evas_object_visible_get(id->view)) return EINA_FALSE; if (!_elm_widget_onscreen_is(id->widget)) return EINA_FALSE; evas_object_geometry_get(id->view, &r1.x, &r1.y, &r1.w, &r1.h); if (eina_rectangle_is_empty(&r1)) return EINA_FALSE; evas_object_geometry_get(id->widget, &r2.x, &r2.y, &r2.w, &r2.h); if (!eina_rectangles_intersect(&r1, &r2)) return EINA_FALSE; return EINA_TRUE; } EOLIAN static Elm_Atspi_State_Set _elm_widget_item_elm_interface_atspi_accessible_state_set_get(Eo *eo_item, Elm_Widget_Item_Data *item EINA_UNUSED) { Elm_Atspi_State_Set states = 0; STATE_TYPE_SET(states, ELM_ATSPI_STATE_FOCUSABLE); if (elm_object_item_focus_get(eo_item)) STATE_TYPE_SET(states, ELM_ATSPI_STATE_FOCUSED); if (!elm_object_item_disabled_get(eo_item)) { STATE_TYPE_SET(states, ELM_ATSPI_STATE_ENABLED); STATE_TYPE_SET(states, ELM_ATSPI_STATE_SENSITIVE); STATE_TYPE_SET(states, ELM_ATSPI_STATE_VISIBLE); } if (_elm_widget_item_onscreen_is(eo_item)) STATE_TYPE_SET(states, ELM_ATSPI_STATE_SHOWING); return states; } EAPI void elm_object_item_data_set(Elm_Object_Item *it, void *data) { WIDGET_ITEM_DATA_SET(it, data); } EAPI void * elm_object_item_data_get(const Elm_Object_Item *it) { return (void *) WIDGET_ITEM_DATA_GET(it); } EOLIAN static void _elm_widget_item_disabled_set(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item, Eina_Bool disabled) { ELM_WIDGET_ITEM_CHECK_OR_RETURN(item); ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item); if (item->disabled == disabled) return; item->disabled = !!disabled; elm_wdg_item_disable(item->eo_obj); } EOLIAN static Eina_Bool _elm_widget_item_disabled_get(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item) { ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, EINA_FALSE); return item->disabled; } EOLIAN static void _elm_widget_item_style_set(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item, const char *style EINA_UNUSED) { ERR_NOT_SUPPORTED(item, "elm_object_style_set()"); } EOLIAN static const char * _elm_widget_item_style_get(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item) { ERR_NOT_SUPPORTED(item, "elm_object_style_get()"); return NULL; } EOLIAN static void _elm_widget_item_disable(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item EINA_UNUSED) { } EOLIAN static void _elm_widget_item_focus_set(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item, Eina_Bool focused EINA_UNUSED) { ERR_NOT_SUPPORTED(item, "elm_object_item_focus_set"); } EOLIAN static Eina_Bool _elm_widget_item_focus_get(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item) { ERR_NOT_SUPPORTED(item, "elm_object_item_focus_get"); return EINA_FALSE; } EOLIAN static void _elm_widget_item_domain_translatable_part_text_set(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item, const char *part, const char *domain, const char *label) { ELM_WIDGET_ITEM_CHECK_OR_RETURN(item); ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item); Elm_Translate_String_Data *ts; if (!label) { _part_text_translatable_set(&item->translate_strings, part, EINA_FALSE, EINA_FALSE); } else { ts = _part_text_translatable_set(&item->translate_strings, part, EINA_TRUE, EINA_FALSE); if (!ts) return; if (!ts->string) ts->string = eina_stringshare_add(label); else eina_stringshare_replace(&ts->string, label); if (!ts->domain) ts->domain = eina_stringshare_add(domain); else eina_stringshare_replace(&ts->domain, domain); #ifdef HAVE_GETTEXT if (label[0]) label = dgettext(domain, label); #endif } item->on_translate = EINA_TRUE; elm_wdg_item_part_text_set(item->eo_obj, part, label); item->on_translate = EINA_FALSE; } EOLIAN static const char * _elm_widget_item_translatable_part_text_get(const Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item, const char *part) { ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL); ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item, NULL); Elm_Translate_String_Data *ts; ts = _translate_string_data_get(item->translate_strings, part); if (ts) return ts->string; return NULL; } EOLIAN static void _elm_widget_item_domain_part_text_translatable_set(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item, const char *part, const char *domain, Eina_Bool translatable) { ELM_WIDGET_ITEM_CHECK_OR_RETURN(item); ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item); Elm_Translate_String_Data *ts; const char *text; ts = _part_text_translatable_set(&item->translate_strings, part, translatable, EINA_TRUE); if (!ts) return; if (!ts->domain) ts->domain = eina_stringshare_add(domain); else eina_stringshare_replace(&ts->domain, domain); text = elm_wdg_item_part_text_get(item->eo_obj, part); if (!text || !text[0]) return; if (!ts->string) ts->string = eina_stringshare_add(text); //Try to translate text since we don't know the text is already translated. #ifdef HAVE_GETTEXT text = dgettext(domain, text); #endif item->on_translate = EINA_TRUE; elm_wdg_item_part_text_set(item->eo_obj, part, text); item->on_translate = EINA_FALSE; } EOLIAN static void _elm_widget_item_track_cancel(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item) { ELM_WIDGET_ITEM_CHECK_OR_RETURN(item); ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item); if (!item->track_obj) return; while (evas_object_ref_get(item->track_obj) > 0) evas_object_unref(item->track_obj); evas_object_del(item->track_obj); } EOLIAN static Evas_Object * _elm_widget_item_track(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item) { ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL); ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item, NULL); if (item->track_obj) { evas_object_ref(item->track_obj); return item->track_obj; } if (!item->view) { WRN("view obj of the item(%p) is invalid. Please make sure the view obj is created!", item); return NULL; } Evas_Object *track = evas_object_rectangle_add(evas_object_evas_get(item->widget)); evas_object_color_set(track, 0, 0, 0, 0); evas_object_pass_events_set(track, EINA_TRUE); _track_obj_update(track, item->view); evas_object_event_callback_add(track, EVAS_CALLBACK_DEL, _track_obj_del, item); efl_event_callback_array_add(item->view, tracker_callbacks(), item); evas_object_ref(track); item->track_obj = track; return track; } EOLIAN static void _elm_widget_item_untrack(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item) { ELM_WIDGET_ITEM_CHECK_OR_RETURN(item); ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item); if (!item->track_obj) return; evas_object_unref(item->track_obj); if (evas_object_ref_get(item->track_obj) == 0) evas_object_del(item->track_obj); } EOLIAN static int _elm_widget_item_track_get(const Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item) { ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, 0); ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item, 0); if (!item->track_obj) return 0; return evas_object_ref_get(item->track_obj); } typedef struct _Elm_Widget_Item_Tooltip Elm_Widget_Item_Tooltip; struct _Elm_Widget_Item_Tooltip { Elm_Widget_Item_Data *item; Elm_Tooltip_Item_Content_Cb func; Evas_Smart_Cb del_cb; const void *data; }; static Evas_Object * _elm_widget_item_tooltip_label_create(void *data, Evas_Object *obj EINA_UNUSED, Evas_Object *tooltip, void *item EINA_UNUSED) { Evas_Object *label = elm_label_add(tooltip); if (!label) return NULL; elm_object_style_set(label, "tooltip"); elm_object_text_set(label, data); return label; } static Evas_Object * _elm_widget_item_tooltip_trans_label_create(void *data, Evas_Object *obj EINA_UNUSED, Evas_Object *tooltip, void *item EINA_UNUSED) { Evas_Object *label = elm_label_add(tooltip); if (!label) return NULL; elm_object_style_set(label, "tooltip"); elm_object_translatable_text_set(label, data); return label; } static void _elm_widget_item_tooltip_label_del_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) { eina_stringshare_del(data); } /** * @internal * * Set the text to be shown in the widget item. * * @param item Target item * @param text The text to set in the content * * Setup the text as tooltip to object. The item can have only one tooltip, * so any previous tooltip data is removed. * * @ingroup Widget */ EOLIAN static void _elm_widget_item_tooltip_text_set(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item EINA_UNUSED, const char *text) { ELM_WIDGET_ITEM_CHECK_OR_RETURN(item); ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item); EINA_SAFETY_ON_NULL_RETURN(text); text = eina_stringshare_add(text); elm_wdg_item_tooltip_content_cb_set(item->eo_obj, _elm_widget_item_tooltip_label_create, text, _elm_widget_item_tooltip_label_del_cb); } EOLIAN static void _elm_widget_item_tooltip_translatable_text_set(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item EINA_UNUSED, const char *text) { ELM_WIDGET_ITEM_CHECK_OR_RETURN(item); ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item); EINA_SAFETY_ON_NULL_RETURN(text); text = eina_stringshare_add(text); elm_wdg_item_tooltip_content_cb_set(item->eo_obj, _elm_widget_item_tooltip_trans_label_create, text, _elm_widget_item_tooltip_label_del_cb); } static Evas_Object * _elm_widget_item_tooltip_create(void *data, Evas_Object *obj, Evas_Object *tooltip) { Elm_Widget_Item_Tooltip *wit = data; return wit->func((void *)wit->data, obj, tooltip, wit->item->eo_obj); } static void _elm_widget_item_tooltip_del_cb(void *data, Evas_Object *obj, void *event_info EINA_UNUSED) { Elm_Widget_Item_Tooltip *wit = data; if (wit->del_cb) wit->del_cb((void *)wit->data, obj, wit->item->eo_obj); free(wit); } /** * @internal * * Set the content to be shown in the tooltip item * * Setup the tooltip to item. The item can have only one tooltip, * so any previous tooltip data is removed. @p func(with @p data) will * be called every time that need show the tooltip and it should * return a valid Evas_Object. This object is then managed fully by * tooltip system and is deleted when the tooltip is gone. * * @param item the widget item being attached a tooltip. * @param func the function used to create the tooltip contents. * @param data what to provide to @a func as callback data/context. * @param del_cb called when data is not needed anymore, either when * another callback replaces @func, the tooltip is unset with * elm_widget_item_tooltip_unset() or the owner @a item * dies. This callback receives as the first parameter the * given @a data, and @c event_info is the item. * * @ingroup Widget */ EOLIAN static void _elm_widget_item_tooltip_content_cb_set(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item, Elm_Tooltip_Item_Content_Cb func, const void *data, Evas_Smart_Cb del_cb) { Elm_Widget_Item_Tooltip *wit; ELM_WIDGET_ITEM_CHECK_OR_GOTO(item, error_noitem); //ELM_WIDGET_ITEM_RETURN_IF_GOTO(item, error_noitem); if (!func) { elm_wdg_item_tooltip_unset(item->eo_obj); return; } wit = ELM_NEW(Elm_Widget_Item_Tooltip); if (!wit) goto error; wit->item = item; wit->func = func; wit->data = data; wit->del_cb = del_cb; elm_object_sub_tooltip_content_cb_set (item->view, item->widget, _elm_widget_item_tooltip_create, wit, _elm_widget_item_tooltip_del_cb); return; error_noitem: if (del_cb) del_cb((void *)data, NULL, item); return; error: if (del_cb) del_cb((void *)data, item->widget, item); } /** * @internal * * Unset tooltip from item * * @param item widget item to remove previously set tooltip. * * Remove tooltip from item. The callback provided as del_cb to * elm_widget_item_tooltip_content_cb_set() will be called to notify * it is not used anymore. * * @see elm_widget_item_tooltip_content_cb_set() * * @ingroup Widget */ EOLIAN static void _elm_widget_item_tooltip_unset(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item) { ELM_WIDGET_ITEM_CHECK_OR_RETURN(item); ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item); elm_object_tooltip_unset(item->view); } /** * @internal * * Sets a different style for this item tooltip. * * @note before you set a style you should define a tooltip with * elm_widget_item_tooltip_content_cb_set() or * elm_widget_item_tooltip_text_set() * * @param item widget item with tooltip already set. * @param style the theme style to use (default, transparent, ...) * * @ingroup Widget */ EOLIAN static void _elm_widget_item_tooltip_style_set(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item, const char *style) { ELM_WIDGET_ITEM_CHECK_OR_RETURN(item); ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item); elm_object_tooltip_style_set(item->view, style); } EOLIAN static Eina_Bool _elm_widget_item_tooltip_window_mode_set(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item, Eina_Bool disable) { ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, EINA_FALSE); ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item, EINA_FALSE); return elm_object_tooltip_window_mode_set(item->view, disable); } EOLIAN static Eina_Bool _elm_widget_item_tooltip_window_mode_get(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item) { ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, EINA_FALSE); ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item, EINA_FALSE); return elm_object_tooltip_window_mode_get(item->view); } /** * @internal * * Get the style for this item tooltip. * * @param item widget item with tooltip already set. * @return style the theme style in use, defaults to "default". If the * object does not have a tooltip set, then NULL is returned. * * @ingroup Widget */ EOLIAN static const char * _elm_widget_item_tooltip_style_get(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item) { ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL); return elm_object_tooltip_style_get(item->view); } EOLIAN static void _elm_widget_item_cursor_set(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item, const char *cursor) { ELM_WIDGET_ITEM_CHECK_OR_RETURN(item); ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item); elm_object_sub_cursor_set(item->view, item->widget, cursor); } EOLIAN static const char * _elm_widget_item_cursor_get(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item) { ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL); return elm_object_cursor_get(item->view); } EOLIAN static void _elm_widget_item_cursor_unset(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item) { ELM_WIDGET_ITEM_CHECK_OR_RETURN(item); ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item); elm_object_cursor_unset(item->view); } /** * @internal * * Sets a different style for this item cursor. * * @note before you set a style you should define a cursor with * elm_widget_item_cursor_set() * * @param item widget item with cursor already set. * @param style the theme style to use (default, transparent, ...) * * @ingroup Widget */ EOLIAN static void _elm_widget_item_cursor_style_set(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item, const char *style) { ELM_WIDGET_ITEM_CHECK_OR_RETURN(item); ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item); elm_object_cursor_style_set(item->view, style); } /** * @internal * * Get the style for this item cursor. * * @param item widget item with cursor already set. * @return style the theme style in use, defaults to "default". If the * object does not have a cursor set, then NULL is returned. * * @ingroup Widget */ EOLIAN static const char * _elm_widget_item_cursor_style_get(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item) { ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL); return elm_object_cursor_style_get(item->view); } /** * @internal * * Set if the cursor set should be searched on the theme or should use * the provided by the engine, only. * * @note before you set if should look on theme you should define a cursor * with elm_object_cursor_set(). By default it will only look for cursors * provided by the engine. * * @param item widget item with cursor already set. * @param engine_only boolean to define it cursors should be looked only * between the provided by the engine or searched on widget's theme as well. * * @ingroup Widget */ EOLIAN static void _elm_widget_item_cursor_engine_only_set(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item, Eina_Bool engine_only) { ELM_WIDGET_ITEM_CHECK_OR_RETURN(item); ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item); elm_object_cursor_theme_search_enabled_set(item->view, !engine_only); } /** * @internal * * Get the cursor engine only usage for this item cursor. * * @param item widget item with cursor already set. * @return engine_only boolean to define it cursors should be looked only * between the provided by the engine or searched on widget's theme as well. If * the object does not have a cursor set, then EINA_FALSE is returned. * * @ingroup Widget */ EOLIAN static Eina_Bool _elm_widget_item_cursor_engine_only_get(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item) { ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, EINA_FALSE); return !elm_object_cursor_theme_search_enabled_get(item->view); } EOLIAN static void _elm_widget_item_part_content_set(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item, const char *part EINA_UNUSED, Evas_Object *content EINA_UNUSED) { ERR_NOT_SUPPORTED(item, "elm_object_part_content_set()"); } EOLIAN static Evas_Object * _elm_widget_item_part_content_get(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item, const char *part EINA_UNUSED) { ERR_NOT_SUPPORTED(item, "elm_object_part_content_get()"); return NULL; } EOLIAN static Evas_Object * _elm_widget_item_part_content_unset(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item, const char *part EINA_UNUSED) { ERR_NOT_SUPPORTED(item, "elm_object_part_content_unset()"); return NULL; } EOLIAN static void _elm_widget_item_part_text_set(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item, const char *part EINA_UNUSED, const char *label EINA_UNUSED) { ERR_NOT_SUPPORTED(item, "elm_object_part_text_set()"); } EOLIAN static const char * _elm_widget_item_part_text_get(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item, const char *part EINA_UNUSED) { ERR_NOT_SUPPORTED(item, "elm_object_part_text_get()"); return NULL; } static void _elm_widget_item_part_text_custom_free(void *data) { Elm_Label_Data *label; label = data; eina_stringshare_del(label->part); eina_stringshare_del(label->text); free(label); } EOLIAN static void _elm_widget_item_part_text_custom_set(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item, const char *part, const char *text) { Elm_Label_Data *label; ELM_WIDGET_ITEM_CHECK_OR_RETURN(item); ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item); if (!item->labels) item->labels = eina_hash_stringshared_new(_elm_widget_item_part_text_custom_free); label = eina_hash_find(item->labels, part); if (!label) { label = malloc(sizeof(Elm_Label_Data)); if (!label) { ERR("Failed to allocate memory"); return; } label->part = eina_stringshare_add(part); label->text = eina_stringshare_add(text); eina_hash_add(item->labels, part, label); } else eina_stringshare_replace(&label->text, text); } EOLIAN static const char * _elm_widget_item_part_text_custom_get(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item, const char *part) { Elm_Label_Data *label; ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL); label = eina_hash_find(item->labels, part); return label ? label->text : NULL; } static Eina_Bool _elm_widget_item_part_text_custom_foreach(const Eina_Hash *labels EINA_UNUSED, const void *key EINA_UNUSED, void *data, void *func_data) { Elm_Label_Data *label; Elm_Widget_Item_Data *item; label = data; item = func_data; elm_wdg_item_part_text_set(item->eo_obj, label->part, label->text); return EINA_TRUE; } EOLIAN static void _elm_widget_item_part_text_custom_update(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item) { ELM_WIDGET_ITEM_CHECK_OR_RETURN(item); ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item); if (item->labels) eina_hash_foreach(item->labels, _elm_widget_item_part_text_custom_foreach, item); } EOLIAN static void _elm_widget_item_signal_emit(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item EINA_UNUSED, const char *emission EINA_UNUSED, const char *source EINA_UNUSED) { } EOLIAN static void _elm_widget_item_signal_callback_add(Eo *eo_item, Elm_Widget_Item_Data *item, const char *emission, const char *source, Elm_Object_Item_Signal_Cb func, void *data) { ELM_WIDGET_ITEM_CHECK_OR_RETURN(item); ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item); EINA_SAFETY_ON_NULL_RETURN(func); Elm_Widget_Item_Signal_Data *wisd; wisd = malloc(sizeof(Elm_Widget_Item_Signal_Data)); if (!wisd) return; wisd->item = eo_item; wisd->func = (Elm_Widget_Item_Signal_Cb)func; wisd->data = data; wisd->emission = eina_stringshare_add(emission); wisd->source = eina_stringshare_add(source); if (_elm_widget_is(item->view)) elm_object_signal_callback_add(item->view, emission, source, _elm_widget_item_signal_cb, wisd); else if (efl_isa(item->view, EDJE_OBJECT_CLASS)) edje_object_signal_callback_add(item->view, emission, source, _elm_widget_item_signal_cb, wisd); else { WRN("The %s widget item doesn't support signal callback add!", efl_class_name_get(efl_class_get(item->widget))); free(wisd); return; } item->signals = eina_list_append(item->signals, wisd); } EOLIAN static void * _elm_widget_item_signal_callback_del(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item, const char *emission, const char *source, Elm_Object_Item_Signal_Cb func) { Elm_Widget_Item_Signal_Data *wisd; Eina_List *l; ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL); ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item, NULL); EINA_SAFETY_ON_NULL_RETURN_VAL(func, NULL); EINA_LIST_FOREACH(item->signals, l, wisd) { if ((wisd->func == (Elm_Widget_Item_Signal_Cb)func) && !strcmp(wisd->emission, emission) && !strcmp(wisd->source, source)) return _elm_widget_item_signal_callback_list_get(item, l); } return NULL; } EOLIAN static void _elm_widget_item_access_info_set(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item, const char *txt) { ELM_WIDGET_ITEM_CHECK_OR_RETURN(item); ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item); eina_stringshare_del(item->access_info); if (!txt) item->access_info = NULL; else item->access_info = eina_stringshare_add(txt); } EOLIAN static void _elm_widget_item_translate(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item) { ELM_WIDGET_ITEM_CHECK_OR_RETURN(item); ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item); #ifdef HAVE_GETTEXT Elm_Translate_String_Data *ts; EINA_INLIST_FOREACH(item->translate_strings, ts) { if (!ts->string) continue; const char *s = dgettext(ts->domain, ts->string); item->on_translate = EINA_TRUE; elm_wdg_item_part_text_set(item->eo_obj, ts->id, s); item->on_translate = EINA_FALSE; } #endif } EOLIAN static void _elm_widget_item_access_order_set(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item, Eina_List *objs) { _elm_access_widget_item_access_order_set(item, objs); } EOLIAN static const Eina_List * _elm_widget_item_access_order_get(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item) { return _elm_access_widget_item_access_order_get(item); } EOLIAN static void _elm_widget_item_access_order_unset(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item) { _elm_access_widget_item_access_order_unset(item); } EOLIAN static Evas_Object* _elm_widget_item_access_register(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item) { _elm_access_widget_item_register(item); return item->access_obj; } EOLIAN static void _elm_widget_item_access_unregister(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item) { _elm_access_widget_item_unregister(item); } EOLIAN static Evas_Object* _elm_widget_item_access_object_get(const Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item) { return item->access_obj; } EOLIAN static Evas_Object * _elm_widget_item_focus_next_object_get(const Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item, Elm_Focus_Direction dir) { Evas_Object *ret = NULL; if (dir == ELM_FOCUS_PREVIOUS) ret = item->focus_previous; else if (dir == ELM_FOCUS_NEXT) ret = item->focus_next; else if (dir == ELM_FOCUS_UP) ret = item->focus_up; else if (dir == ELM_FOCUS_DOWN) ret = item->focus_down; else if (dir == ELM_FOCUS_RIGHT) ret = item->focus_right; else if (dir == ELM_FOCUS_LEFT) ret = item->focus_left; return ret; } EOLIAN static void _elm_widget_item_focus_next_object_set(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item, Evas_Object *next, Elm_Focus_Direction dir) { if (dir == ELM_FOCUS_PREVIOUS) item->focus_previous = next; else if (dir == ELM_FOCUS_NEXT) item->focus_next = next; else if (dir == ELM_FOCUS_UP) item->focus_up = next; else if (dir == ELM_FOCUS_DOWN) item->focus_down = next; else if (dir == ELM_FOCUS_RIGHT) item->focus_right = next; else if (dir == ELM_FOCUS_LEFT) item->focus_left = next; } EOLIAN static Elm_Object_Item* _elm_widget_item_focus_next_item_get(const Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item, Elm_Focus_Direction dir) { Elm_Object_Item *ret = NULL; if (dir == ELM_FOCUS_PREVIOUS) ret = item->item_focus_previous; else if (dir == ELM_FOCUS_NEXT) ret = item->item_focus_next; else if (dir == ELM_FOCUS_UP) ret = item->item_focus_up; else if (dir == ELM_FOCUS_DOWN) ret = item->item_focus_down; else if (dir == ELM_FOCUS_RIGHT) ret = item->item_focus_right; else if (dir == ELM_FOCUS_LEFT) ret = item->item_focus_left; return ret; } EOLIAN static void _elm_widget_item_focus_next_item_set(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item, Elm_Object_Item *next_item, Elm_Focus_Direction dir) { if (dir == ELM_FOCUS_PREVIOUS) item->item_focus_previous = next_item; else if (dir == ELM_FOCUS_NEXT) item->item_focus_next = next_item; else if (dir == ELM_FOCUS_UP) item->item_focus_up = next_item; else if (dir == ELM_FOCUS_DOWN) item->item_focus_down = next_item; else if (dir == ELM_FOCUS_RIGHT) item->item_focus_right = next_item; else if (dir == ELM_FOCUS_LEFT) item->item_focus_left = next_item; } /* happy debug functions */ #ifdef ELM_DEBUG static void _sub_obj_tree_dump(const Evas_Object *obj, int lvl) { int i; for (i = 0; i < lvl * 3; i++) putchar(' '); if (_elm_widget_is(obj)) { Eina_List *l; INTERNAL_ENTRY; DBG("+ %s(%p)\n", elm_widget_type_get(obj), obj); EINA_LIST_FOREACH(sd->subobjs, l, obj) _sub_obj_tree_dump(obj, lvl + 1); } else DBG("+ %s(%p)\n", evas_object_type_get(obj), obj); } static void _sub_obj_tree_dot_dump(const Evas_Object *obj, FILE *output) { if (!_elm_widget_is(obj)) return; INTERNAL_ENTRY; Eina_Bool visible = evas_object_visible_get(obj); Eina_Bool disabled = elm_widget_disabled_get(obj); Eina_Bool focused = elm_widget_focus_get(obj); Eina_Bool can_focus = elm_widget_can_focus_get(obj); if (sd->parent_obj) { fprintf(output, "\"%p\" -- \"%p\" [ color=black", sd->parent_obj, obj); if (focused) fprintf(output, ", style=bold"); if (!visible) fprintf(output, ", color=gray28"); fprintf(output, " ];\n"); } fprintf(output, "\"%p\" [ label = \"{%p|%s|%s|visible: %d|" "disabled: %d|focused: %d/%d|focus order:%d}\"", obj, obj, elm_widget_type_get(obj), evas_object_name_get(obj), visible, disabled, focused, can_focus, sd->focus_order); if (focused) fprintf(output, ", style=bold"); if (!visible) fprintf(output, ", fontcolor=gray28"); if ((disabled) || (!visible)) fprintf(output, ", color=gray"); fprintf(output, " ];\n"); Eina_List *l; Evas_Object *o; EINA_LIST_FOREACH(sd->subobjs, l, o) _sub_obj_tree_dot_dump(o, output); } #endif EAPI void elm_widget_tree_dump(const Evas_Object *top) { #ifdef ELM_DEBUG if (!_elm_widget_is(top)) return; _sub_obj_tree_dump(top, 0); #else (void)top; return; #endif } EAPI void elm_widget_tree_dot_dump(const Evas_Object *top, FILE *output) { #ifdef ELM_DEBUG if (!_elm_widget_is(top)) return; fprintf(output, "graph " " { node [shape=record];\n"); _sub_obj_tree_dot_dump(top, output); fprintf(output, "}\n"); #else (void)top; (void)output; return; #endif } EOLIAN static Eo * _elm_widget_efl_object_constructor(Eo *obj, Elm_Widget_Smart_Data *sd EINA_UNUSED) { Eo *parent = NULL; sd->on_create = EINA_TRUE; obj = efl_constructor(efl_super(obj, MY_CLASS)); efl_canvas_object_type_set(obj, MY_CLASS_NAME_LEGACY); evas_object_smart_callbacks_descriptions_set(obj, _smart_callbacks); parent = efl_parent_get(obj); elm_obj_widget_parent_set(obj, parent); sd->on_create = EINA_FALSE; elm_interface_atspi_accessible_role_set(obj, ELM_ATSPI_ROLE_UNKNOWN); return obj; } EOLIAN static Efl_Object* _elm_widget_efl_object_finalize(Eo *obj, Elm_Widget_Smart_Data *pd) { Eo *eo; eo = efl_finalize(efl_super(obj, MY_CLASS)); _focus_state_eval(obj, pd); return eo; } EOLIAN static void _elm_widget_efl_object_destructor(Eo *obj, Elm_Widget_Smart_Data *sd EINA_UNUSED) { sd->on_destroy = EINA_TRUE; efl_destructor(efl_super(obj, ELM_WIDGET_CLASS)); sd->on_destroy = EINA_FALSE; if (sd->manager.provider) efl_event_callback_del(sd->manager.provider, EFL_UI_FOCUS_USER_EVENT_MANAGER_CHANGED, _manager_changed_cb, obj); sd->manager.provider = NULL; elm_interface_atspi_accessible_removed(obj); if (sd->logical.parent) { efl_weak_unref(&sd->logical.parent); sd->logical.parent = NULL; } } EOLIAN static Eina_Bool _elm_widget_on_focus(Eo *obj, Elm_Widget_Smart_Data *sd, Elm_Object_Item *item EINA_UNUSED) { Eina_Bool focused; const Efl_Event_Description *desc; if (!elm_widget_can_focus_get(obj)) return EINA_FALSE; focused = elm_widget_focus_get(obj); desc = focused ? ELM_WIDGET_EVENT_FOCUSED : ELM_WIDGET_EVENT_UNFOCUSED; if (!sd->resize_obj) evas_object_focus_set(obj, focused); efl_event_callback_legacy_call(obj, desc, NULL); if (_elm_config->atspi_mode && !elm_widget_child_can_focus_get(obj)) elm_interface_atspi_accessible_state_changed_signal_emit(obj, ELM_ATSPI_STATE_FOCUSED, focused); return EINA_TRUE; } EOLIAN static Eina_Bool _elm_widget_disable(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *_pd EINA_UNUSED) { return EINA_FALSE; } EOLIAN static Eina_Bool _elm_widget_widget_event(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *_pd EINA_UNUSED, Evas_Object *source EINA_UNUSED, Evas_Callback_Type type EINA_UNUSED, void *event_info EINA_UNUSED) { return EINA_FALSE; } EOLIAN static Eina_Bool _elm_widget_focus_next_manager_is(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *_pd EINA_UNUSED) { WRN("The %s widget does not implement the \"focus_next/focus_next_manager_is\" functions.", efl_class_name_get(efl_class_get(obj))); return EINA_FALSE; } static Eina_Bool _elm_widget_focus_direction_manager_is(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *_pd EINA_UNUSED) { WRN("The %s widget does not implement the \"focus_direction/focus_direction_manager_is\" functions.", efl_class_name_get(efl_class_get(obj))); return EINA_FALSE; } EOLIAN static Eina_Bool _elm_widget_activate(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *_pd EINA_UNUSED, Elm_Activate act EINA_UNUSED) { WRN("The %s widget does not implement the \"activate\" functions.", efl_class_name_get(efl_class_get(obj))); return EINA_TRUE; } EOLIAN static void _elm_widget_class_constructor(Efl_Class *klass) { evas_smart_legacy_type_register(MY_CLASS_NAME_LEGACY, klass); } EOLIAN static Eina_Bool _elm_widget_elm_interface_atspi_component_focus_grab(Eo *obj, Elm_Widget_Smart_Data *pd EINA_UNUSED) { if (elm_object_focus_allow_get(obj)) { Ecore_Evas *ee = ecore_evas_ecore_evas_get(evas_object_evas_get(obj)); if (!ee) return EINA_FALSE; ecore_evas_activate(ee); elm_object_focus_set(obj, EINA_TRUE); return EINA_TRUE; } return EINA_FALSE; } EOLIAN static const char* _elm_widget_elm_interface_atspi_accessible_name_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *_pd) { const char *ret, *name; char *accessible_name; name = elm_interface_atspi_accessible_name_get(efl_super(obj, ELM_WIDGET_CLASS)); if (name) return name; ret = elm_object_text_get(obj); if (!ret) return NULL; accessible_name = _elm_util_mkup_to_text(ret); eina_stringshare_del(_pd->accessible_name); _pd->accessible_name = eina_stringshare_add(accessible_name); free(accessible_name); return _pd->accessible_name; } EOLIAN static Eina_List* _elm_widget_elm_interface_atspi_accessible_children_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *pd) { Eina_List *l, *accs = NULL; Evas_Object *widget; Elm_Atspi_Type type; EINA_LIST_FOREACH(pd->subobjs, l, widget) { if (!elm_object_widget_check(widget)) continue; if (!efl_isa(widget, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN)) continue; type = elm_interface_atspi_accessible_type_get(widget); if (type == ELM_ATSPI_TYPE_DISABLED) continue; if (type == ELM_ATSPI_TYPE_SKIPPED) { Eina_List *children; children = elm_interface_atspi_accessible_children_get(widget); accs = eina_list_merge(accs, children); continue; } accs = eina_list_append(accs, widget); } return accs; } EOLIAN static Eo* _elm_widget_elm_interface_atspi_accessible_parent_get(Eo *obj, Elm_Widget_Smart_Data *pd EINA_UNUSED) { Elm_Atspi_Type type; Elm_Interface_Atspi_Accessible *parent = obj; do { ELM_WIDGET_DATA_GET_OR_RETURN(parent, wd, NULL); parent = wd->parent_obj; type = elm_interface_atspi_accessible_type_get(parent); } while (parent && (type == ELM_ATSPI_TYPE_SKIPPED)); return efl_isa(parent, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN) ? parent : NULL; } EOLIAN static Elm_Atspi_State_Set _elm_widget_elm_interface_atspi_accessible_state_set_get(Eo *obj, Elm_Widget_Smart_Data *pd EINA_UNUSED) { Elm_Atspi_State_Set states = 0; states = elm_interface_atspi_accessible_state_set_get(efl_super(obj, ELM_WIDGET_CLASS)); if (evas_object_visible_get(obj)) { STATE_TYPE_SET(states, ELM_ATSPI_STATE_VISIBLE); if (_elm_widget_onscreen_is(obj)) STATE_TYPE_SET(states, ELM_ATSPI_STATE_SHOWING); } if (!elm_widget_child_can_focus_get(obj)) { if (elm_object_focus_allow_get(obj)) STATE_TYPE_SET(states, ELM_ATSPI_STATE_FOCUSABLE); if (elm_object_focus_get(obj)) STATE_TYPE_SET(states, ELM_ATSPI_STATE_FOCUSED); } if (!elm_object_disabled_get(obj)) { STATE_TYPE_SET(states, ELM_ATSPI_STATE_ENABLED); STATE_TYPE_SET(states, ELM_ATSPI_STATE_SENSITIVE); } return states; } EOLIAN static Eina_List* _elm_widget_elm_interface_atspi_accessible_attributes_get(Eo *obj, Elm_Widget_Smart_Data *pd EINA_UNUSED) { Eina_List *ret = NULL; Elm_Atspi_Attribute *attr = calloc(1, sizeof(Elm_Atspi_Attribute)); if (!attr) return NULL; attr->key = eina_stringshare_add("type"); attr->value = eina_stringshare_add(evas_object_type_get(obj)); ret = eina_list_append(ret, attr); return ret; } EOLIAN static void _elm_widget_item_elm_interface_atspi_component_extents_get(Eo *obj EINA_UNUSED, Elm_Widget_Item_Data *sd EINA_UNUSED, Eina_Bool screen_coords, int *x, int *y, int *w, int *h) { int ee_x, ee_y; if (!sd->view) { if (x) *x = -1; if (y) *y = -1; if (w) *w = -1; if (h) *h = -1; return; } evas_object_geometry_get(sd->view, x, y, w, h); if (screen_coords) { Ecore_Evas *ee = ecore_evas_ecore_evas_get(evas_object_evas_get(sd->view)); if (!ee) return; ecore_evas_geometry_get(ee, &ee_x, &ee_y, NULL, NULL); if (x) *x += ee_x; if (y) *y += ee_y; } } EOLIAN static Eina_Bool _elm_widget_item_elm_interface_atspi_component_extents_set(Eo *obj EINA_UNUSED, Elm_Widget_Item_Data *sd EINA_UNUSED, Eina_Bool screen_coords EINA_UNUSED, int x EINA_UNUSED, int y EINA_UNUSED, int w EINA_UNUSED, int h EINA_UNUSED) { return EINA_FALSE; } EOLIAN static int _elm_widget_item_elm_interface_atspi_component_layer_get(Eo *obj EINA_UNUSED, Elm_Widget_Item_Data *sd EINA_UNUSED) { if (!sd->view) return -1; return evas_object_layer_get(sd->view); } EOLIAN static Eina_Bool _elm_widget_item_elm_interface_atspi_component_focus_grab(Eo *obj EINA_UNUSED, Elm_Widget_Item_Data *_pd EINA_UNUSED) { elm_object_item_focus_set(obj, EINA_TRUE); return elm_object_item_focus_get(obj); } EOLIAN static double _elm_widget_item_elm_interface_atspi_component_alpha_get(Eo *obj EINA_UNUSED, Elm_Widget_Item_Data *sd EINA_UNUSED) { int alpha; if (!sd->view) return -1.0; evas_object_color_get(sd->view, NULL, NULL, NULL, &alpha); return (double)alpha / 255.0; } EOLIAN static Efl_Object * _elm_widget_efl_object_provider_find(Eo *obj, Elm_Widget_Smart_Data *pd, const Efl_Object *klass) { Efl_Object *lookup = NULL; if ((klass == EFL_CONFIG_INTERFACE) || (klass == EFL_CONFIG_GLOBAL_CLASS)) return _efl_config_obj; if (pd->provider_lookup) return NULL; pd->provider_lookup = EINA_TRUE; lookup = efl_provider_find(pd->parent_obj, klass); if (!lookup) lookup = efl_provider_find(efl_super(obj, MY_CLASS), klass); pd->provider_lookup = EINA_FALSE; return lookup; } EOLIAN static Efl_Ui_Focus_Manager* _elm_widget_efl_ui_focus_user_parent_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *pd EINA_UNUSED) { return pd->logical.parent; } EOLIAN static Efl_Ui_Focus_Manager* _elm_widget_efl_ui_focus_user_manager_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *pd EINA_UNUSED) { return pd->manager.manager; } EOLIAN static Eina_Rectangle _elm_widget_efl_ui_focus_object_focus_geometry_get(Eo *obj, Elm_Widget_Smart_Data *pd EINA_UNUSED) { Eina_Rectangle rect; efl_gfx_geometry_get(obj, &rect.x , &rect.y, &rect.w, &rect.h); return rect; } EOLIAN static void _elm_widget_efl_ui_focus_object_focus_set(Eo *obj, Elm_Widget_Smart_Data *pd, Eina_Bool focus) { pd->focused = focus; elm_obj_widget_on_focus(obj, NULL); efl_ui_focus_object_focus_set(efl_super(obj, MY_CLASS), focus); } EOLIAN static Efl_Ui_Focus_Manager* _elm_widget_focus_manager_factory(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *pd EINA_UNUSED, Efl_Ui_Focus_Object *root EINA_UNUSED) { ERR("No manager presented"); return NULL; } /* Internal EO APIs and hidden overrides */ #define ELM_WIDGET_EXTRA_OPS \ EFL_CANVAS_GROUP_ADD_DEL_OPS(elm_widget), \ EFL_OBJECT_OP_FUNC(efl_dbg_info_get, _elm_widget_efl_object_dbg_info_get) #include "elm_widget_item.eo.c" #include "elm_widget.eo.c" diff --git a/src/lib/elementary/elm_widget.eo b/src/lib/elementary/elm_widget.eo index c1348c35bc..81aabea33f 100644 --- a/src/lib/elementary/elm_widget.eo +++ b/src/lib/elementary/elm_widget.eo @@ -1,826 +1,821 @@ import edje_types; import elm_general; import efl_input_types; /* FIXME: This shouldn't be here. */ type list_data_get_func_type: __undefined_type; [[Elementary list data get function type]] type region_hook_func_type: __undefined_type; [[Elementary region hook function type]] type @extern Evas.Callback_Type: __undefined_type; [[Evas event type]] enum Elm.Activate { [[ Used in 'Virtual' function @Elm.Widget.activate. ]] default = 0, [[Activate default]] up, [[Activate up]] down, [[Activate down]] right, [[Activate right]] left, [[Activate left]] back, [[Activate back]] } enum Elm.Theme.Apply { [[Return codes when a Elementary theme is applied]] failed = 0, [[Failed to apply theme]] default = 1, [[Default return value]] success = 3 [[Success to apply theme]] } struct Elm.Tooltip; [[Elementary tooltip]] struct @extern Elm.Theme; [[Elementary theme]] abstract Elm.Widget (Efl.Canvas.Group, Elm.Interface.Atspi_Accessible, Elm.Interface.Atspi_Component, Efl.Ui.Focus.User, Efl.Ui.Focus.Object, Efl.Ui.Base) { [[Elementary widget abstract class]] legacy_prefix: elm_widget; eo_prefix: elm_obj_widget; event_prefix: elm_widget; data: Elm_Widget_Smart_Data; methods { @property focus { [[Focus property]] values { focus: bool; [[$true if the widget has focus, $false otherwise]] } } @property drag_lock_y { [[Lock the Y axis from being dragged]] values { lock: bool; [[$true if the Y axis is locked, $false otherwise]] } } @property focus_highlight_style { [[Control the widget focus highlight style.]] set { return: bool; [[$true on success, $false otherwise.]] } get { } values { style: string; [[The name of the focus highlight style.]] } } @property tree_unfocusable { [[Make the elementary object and its children to be unfocusable (or focusable). If the tree is set as unfocusable, newest focused object which is not in this tree will get focus. This API can be helpful for an object to be deleted. When an object will be deleted soon, it and its children may not want to get focus (by focus reverting or by other focus controls). Then, just use this API before deleting.]] values { tree_unfocusable: bool; [[$true for unfocusable, $false for focusable.]] } } @property theme { [[Widget theme]] values { th: ptr(Elm.Theme) @nullable; [[Elementary theme]] } } @property disabled { [[Enabled / disabled property]] values { disabled: bool; [[$true if the widget is disabled, $false otherwise]] } } @property highlight_ignore { [[Highlight ignore]] values { ignore: bool; [[$true if highlights are ignored, $false otherwise]] } } - @property mirrored_automatic { - [[Control the widget's mirrored mode setting.]] - values { - automatic: bool; [[$true if the widget uses automatic mirrored mode, $false otherwise]] - } - } @property orientation_mode_disabled { [[Orientation mode disabled or enabled]] values { disabled: bool; [[$true if orientation mode is disabled, $false otherwise]] } } @property style { [[Theme style]] set { return: Elm.Theme.Apply; [[Theme style]] } get { } values { style: string; [[Style name]] } } @property focus_custom_chain { [[A custom chain of objects to pass focus. Note: On focus cycle, only will be evaluated children of this container.]] set { [[This function overwrites any previous custom focus chain within the list of objects. The previous list will be deleted and this list will be managed by elementary. After it is set, don't modify it.]] values { objs: list; [[Chain of objects to pass focus]] } } get { values { objs: const(list); [[Chain of objects]] } } } @property can_focus { [[The ability for an Elementary object to be focused. Unfocusable objects do nothing when programmatically focused, being the nearest focusable parent object the one really getting focus. Also, when they receive mouse input, they will get the event, but not take away the focus from where it was previously. Note: Objects which are meant to be interacted with by input events are created able to be focused, by default. All the others are not.]] values { can_focus: bool; [[$true if the object can be focused, $false if not.]] } } @property highlight_in_theme { [[Highlight in theme property]] values { highlight: bool; [[$true if widget gets hightlight, $false otherwise]] } } @property widget_parent @protected { [[The internal widget parent]] set { legacy: elm_widget_parent_set; /* Needed because we don't do duplication removal for legacy names. */ } get { legacy: elm_widget_parent_get; /* Needed because we don't do duplication removal for legacy names. */ } values { parent: Efl.Canvas.Object @nullable; [[Widget parent object]] } } @property access_info { [[Accessibility information]] values { txt: string @nullable; [[Accessibility text description]] } } @property drag_lock_x { [[Drag lock on X axis]] values { lock: bool; [[$true if drag is locked on X axis, $false otherwise]] } } @property access_highlight_in_theme { [[Accessibility highlight in theme]] values { highlight: bool; [[$true if highlighted, $false otherwise]] } } @property focus_region_show_mode { [[Control the focus_region_show mode.]] values { mode: Elm.Focus.Region.Show_Mode; [[Focus region show mode]] } } @property parent_highlight { [[Parent highlight property]] set { } values { highlighted: bool; [[$true if highlighted, $false otherwise]] } } @property theme_object { [[Theme object property]] set { return: Elm.Theme.Apply; [[Theme apply]] } values { edj: Efl.Canvas.Object; [[Edje object]] wname: string; [[Widget name]] welement: string; [[Widget element]] wstyle: string; [[Widget style]] } } @property hover_object { [[Hover object property]] set { } values { sobj: Efl.Canvas.Object @nullable; [[Hover sub object]] } } @property on_show_region_hook { [[Region hook on show property]] set { } values { func: region_hook_func_type @nullable; [[Region hook function]] data: void_ptr @optional; [[Data pointer]] } } @property domain_part_text_translatable { [[Translate domain text part property]] set { } values { part: string; [[Part name]] domain: string; [[Domain]] translatable: bool; [[$true if translatable, $false otherwise]] } } @property orientation { [[Widget orientation]] set { } values { rotation: int; [[Orientation]] } } @property resize_object { [[Resize object property]] set { } values { sobj: Efl.Canvas.Object @nullable; [[Object]] sub_obj: bool; [[$true if sub object exists, $false otherwise]] } } @property domain_translatable_part_text { [[Domain translatable text part property]] set { } values { part: string; [[Part name]] domain: string; [[Domain name]] label: string; [[Label]] } } @property scrollable_children { get { [[Function to operate on a given widget's scrollable children when necessary. Warning: free the returned list with eina_list_free().]] return: free(own(list), eina_list_free) @warn_unused; [[List of scrollable children]] } } @property scroll_hold { [[Scroll hold property]] get { return: int; [[FIXME]] } } @property drag_child_locked_y { [[Drag child locked Y axis property]] get { return: int; [[FIXME]] } } @property item_loop_enabled { [[Control item loop feature.]] values { enable: bool; [[$true if item loop is enabled, $false otherwise]] } } @property child_can_focus { [[Child can focus property]] get { return: bool; [[$true if child can focus, $false otherwise]] } } @property scroll_freeze { [[Scroll freeze property]] get { return: int; [[FIXME]] } } @property focus_region { [[Focus region property]] get { return: bool; [[$true on success, $false otherwise]] } values { x: int; [[X coordinate]] y: int; [[Y coordinate]] w: int; [[Width]] h: int; [[Height]] } } @property top { [[Top widget property]] get { return: Efl.Canvas.Object; [[Top widget]] } } @property focus_order { [[Focus order property]] get { return: uint; [[FIXME]] } } @property drag_child_locked_x { [[Drag child locked X axis]] get { return: int; [[FIXME]] } } @property can_focus_child_list { [[Can focus children list]] get { return: free(own(list), eina_list_free) @warn_unused; [[List of children which can focus]] } } @property focused_item { get { [[Get the focused widget item.]] return: Elm.Widget.Item; [[Focused item]] } } @property parents_bounce { [[Parents bounce property]] get { } values { horiz: bool; [[$true if parents bounce horizontally, $false otherwise]] vert: bool; [[$true if parents bounce vertically, $false otherwise]] } } @property parent_widget { [[Parent widget property]] get @pure_virtual { return: Efl.Canvas.Object; [[Parent widget]] legacy: null; } } @property highlight { [[Highlight property]] get { return: bool; [[$true if widget is highlight, $false otherwise]] } } @property focused_object { [[Current focused object in object tree.]] get { return: Efl.Canvas.Object; [[Current focused or $null, if there is no focused object.]] } } @property parent2 { [[Second parent property]] values { parent: Efl.Canvas.Object @nullable; [[Second parent]] } } @property part_text { [[Part text property]] keys { part: string; [[Part name]] } values { label: string; [[Label]] } } newest_focus_order_get @const { [[Get newest focus in order]] return: Efl.Canvas.Object; [[Handle to focused widget]] params { @out newest_focus_order: uint; [[Newest focus order]] @in can_focus_only: bool; [[$true only us widgets which can focus, $false otherweise]] } } scroll_hold_push { [[Push scroll hold]] } focus_next_object_set { [[Set the next object with specific focus direction. @since 1.8]] params { @in next: Efl.Canvas.Object @nullable; [[Focus next object]] @in dir: Elm.Focus_Direction; [[Focus direction]] } } focus_next_object_get @const { [[Get the next object with specific focus direction. @since 1.8]] return: Efl.Canvas.Object; [[Focus next object]] params { @in dir: Elm.Focus_Direction; [[Focus direction]] } } focus_next_item_set { [[Set the next object item with specific focus direction. @since 1.16]] params { @in next_item: Elm.Widget.Item @nullable; [[Focus next object item]] @in dir: Elm.Focus_Direction; [[Focus direction]] } } focus_next_item_get @const { [[Get the next object item with specific focus direction. @since 1.16]] return: Elm.Widget.Item; [[Focus next object item]] params { @in dir: Elm.Focus_Direction; [[Focus direction]] } } focus_tree_unfocusable_handle { [[Handle focus tree unfocusable]] } focus_custom_chain_prepend { [[Prepend object to custom focus chain. Note: If @"relative_child" equal to $null or not in custom chain, the object will be added in begin. Note: On focus cycle, only will be evaluated children of this container.]] params { @in child: Efl.Canvas.Object; [[The child to be added in custom chain.]] @in relative_child: Efl.Canvas.Object @optional; [[The relative object to position the child.]] } } part_text_translate { [[Translate part text]] return: string; [[Translated text]] params { @in part: string; [[Part name]] @in text: string; [[Text]] } } focus_highlight_geometry_get @const { [[Get the focus highlight geometry of widget.]] params { @out x: int; [[X coordinate]] @out y: int; [[Y coordinate]] @out w: int; [[Width]] @out h: int; [[Height]] } } activate { [['Virtual' function to activate widget.]] params { @in act: Elm.Activate; [[Activate]] } return: bool; [[$true on success, $false otherwise]] legacy: null; /* the legacy API has not the same number of parameter to we don't generate it. */ } sub_object_add { [['Virtual' function handling sub objects being added.]] return: bool; [[$true on success, $false otherwise]] params { @in sobj: Efl.Canvas.Object; [[Sub object]] } } focus_direction_manager_is { [['Virtual' function which checks if handling of passing focus to sub-objects in given direction is supported by widget.]] return: bool; [[$true on success, $false otherwise]] legacy: null; } widget_event { [['Virtual' function handling input events on the widget.]] legacy: elm_widget_event; params { @in source: Efl.Canvas.Object; [[Source object]] @in type: Evas.Callback_Type; [[Callback type]] @in event_info: void_ptr; [[Event info]] } return: bool; [[$true on success, $false otherwise]] } access { [['Virtual' function on the widget being set access.]] params { @in acs: bool; [[$true if access is set, $false otherwise]] } legacy: null; } on_focus { [['Virtual' function handling focus in/out events on the widget]] params { @in item: Elm.Widget.Item @nullable; [[Widget]] } return: bool; [[$true if this widget can handle focus, $false otherwise]] } on_focus_region { [['Virtual' function returning an inner area of a widget that should be brought into the visible area of a broader viewport, may this context arise.]] params { @out x: int; [[X coordinate]] @out y: int; [[Y coordinate]] @out w: int; [[Width]] @out h: int; [[Height]] } return: bool; [[$true on success, $false otherwise]] } focus_cycle { [[Give focus to next object with specific focus direction in object tree.]] params { @in dir: Elm.Focus_Direction; [[Direction to move the focus.]] } } focus_direction @pure_virtual { [['Virtual' function handling passing focus to sub-objects given a direction, in degrees.]] params { @in base: const(Efl.Canvas.Object); [[Base object]] @in degree: double; [[Degree]] @out direction: Efl.Canvas.Object; [[Direction]] @out direction_item: Elm.Widget.Item; [[Direction item]] @out weight: double; [[Weight]] } return: bool; [[$true on success, $false otherwise]] } signal_callback_add { [[Add signal callback]] params { @in emission: string; [[Signal emission]] @in source: string; [[Signal source]] @in func: Edje.Signal_Cb; [[Signal callback]] @in data: void_ptr; [[Data pointer]] } } focus_next_manager_is { [['Virtual' function which checks if handling of passing focus to sub-objects is supported by widget.]] return: bool; [[$true on success, $false otherwise]] } name_find @const { [[Find widget by name]] return: Efl.Canvas.Object; [[Widget]] params { @in name: string; [[Widget name]] @in recurse: int; [[Depth in the tree to search for the widget]] } } focus_list_direction_get @const { [[Get focus list direction]] return: bool; [[$true on success, $false otherwise]] params { @in base: const(Efl.Canvas.Object); [[Base object]] @in items: const(list); [[Item list]] @in list_data_get: list_data_get_func_type; [[Data get function]] @in degree: double; [[Degree]] @out direction: Efl.Canvas.Object; [[Direction]] @out direction_item: Elm.Widget.Item; [[Direction item]] @out weight: double; [[Weight]] } } focused_object_clear { [[Clear focused object]] } focus_direction_go { [[Go in focus direction]] return: bool; [[$true on success, $false otherwise]] params { @in degree: double; [[Degree]] } } show_region_set { [[Set show region]] params { @in x: int; [[X coordinate]] @in y: int; [[Y coordinate]] @in w: int; [[Width]] @in h: int; [[Height]] @in forceshow: bool; [[$true if show should be forced, $false otherwise]] } } show_region_get @const { [[Get show region]] params { @out x: int @optional; [[X coordinate]] @out y: int @optional; [[Y coordinate]] @out w: int @optional; [[Width]] @out h: int @optional; [[Height]] } } scroll_freeze_pop { [[Pop scroller freeze]] } tooltip_del { [[Delet widget tooltip]] params { @in tt: ptr(Elm.Tooltip); [[Tooltip to be deleted]] } } focus_next_get @const { [[Get next focus item]] return: bool; [[$true on success, $false otherwise]] params { @in dir: Elm.Focus_Direction; [[Focus direction]] @out next: Efl.Canvas.Object; [[Next object]] @out next_item: Elm.Widget.Item; [[Next item]] } } translatable_part_text_get @const { [[Get translatable part text]] return: string; [[Part text]] params { @in part: string; [[Part name]] } } focus_restore { [[Restore the focus state of the sub-tree. This API will restore the focus state of the sub-tree to the latest state. If a sub-tree is unfocused and wants to get back to the latest focus state, this API will be helpful.]] } scroll_hold_pop { [[Pop scroller hold]] } translate { [['Virtual' function handling language changes on Elementary.]] return: bool; [[$true on success, $false otherwise]] legacy: null; } scroll_freeze_push { [[Push scroller freeze]] } focus_custom_chain_unset { [[Unset a custom focus chain on a given Elementary widget. Any focus chain previously set is removed entirely after this call.]] } focus_steal { [[Steal focus]] params { @in item: Elm.Widget.Item @nullable; [[Widget to steal focus from]] } } focus_hide_handle { [[Handle hide focus]] } focus_next @pure_virtual { [['Virtual' function handling passing focus to sub-objects.]] params { @in dir: Elm.Focus_Direction; [[Focus direction]] @out next: Efl.Canvas.Object; [[Next object]] @out next_item: Elm.Widget.Item; [[Next item]] } return: bool; [[$true on success, $false otherwise]] } focus_list_next_get @const { [[Get next item in focus list]] return: bool; [[$true on success, $false otherwise]] params { @in items: const(list); [[Item list]] @in list_data_get: list_data_get_func_type; [[Function type]] @in dir: Elm.Focus_Direction; [[Focus direction]] @out next: Efl.Canvas.Object; [[Next object]] @out next_item: Elm.Widget.Item; [[Next item]] } } focus_mouse_up_handle { [[Handle focus mouse up]] legacy: null; } theme_apply { [['Virtual' function on the widget being re-themed.]] return: Elm.Theme.Apply; [[Theme apply]] } focus_direction_get @const { [[Get focus direction]] return: bool; [[$true on success, $false otherwise]] params { @in base: const(Efl.Canvas.Object); [[Base]] @in degree: double; [[Degree]] @out direction: Efl.Canvas.Object; [[Direction]] @out direction_item: Elm.Widget.Item; [[Direction item]] @out weight: double; [[Weight]] } } signal_callback_del { [[Delete signal callback]] return: void_ptr; [[Handle to deleted callback]] params { @in emission: string; [[Signal emission]] @in source: string; [[Signal source]] @in func: Edje.Signal_Cb; [[Callback function]] } } signal_emit { [[Emit signal on widget]] params { @in emission: string; [[Signal string]] @in source: string; [[Signal source]] } } disable { [['Virtual' function on the widget being disabled.]] return: bool; [[$true on success, $false otherwise]] } sub_object_del { [['Virtual' function handling sub objects being removed.]] return: bool; [[$true on success, $false otherwise]] params { @in sobj: Efl.Canvas.Object; [[Object to be deleted]] } } tooltip_add { [[Add tooltip to widget]] params { @in tt: ptr(Elm.Tooltip); [[Tooltip]] } } focus_region_show @const { [[Show focus region]] } focus_disabled_handle { [[Handle disable widget focus]] } focus_custom_chain_append { [[Append object to custom focus chain. Note: If @"relative_child" equal to $null or not in custom chain, the object will be added in end. Note: On focus cycle, only will be evaluated children of this container.]] params { @in child: Efl.Canvas.Object; [[The child to be added in custom chain.]] @in relative_child: Efl.Canvas.Object @optional; [[The relative object to position the child.]] } } @property focus_move_policy { [[The widget's focus move policy.]] values { policy: Efl.Ui.Focus.Move_Policy; [[Focus move policy]] } } @property focus_move_policy_automatic { [[Control the widget's focus_move_policy mode setting. @since 1.18]] values { automatic: bool; [[$true to follow system focus move policy change, $false otherwise]] } } focus_reconfigure { [[@since 1.18]] } focus_register { [[Register focus with focus manager]] params { manager : Efl.Ui.Focus.Manager; [[The manager to register against]] logical : Efl.Ui.Focus.Object; [[The logical parent to use]] full : bool; [[flag if this should register full or just logical]] } return : bool; [[return if it registered fully or not]] } focus_manager_factory { [[If the widget needs a manager, this function is called It can be used and overriden to inject your own manager or set custom options on the manager ]] params { root : Efl.Ui.Focus.Object; [[the logical root to use in the manager.]] } return : Efl.Ui.Focus.Manager; } } implements { class.constructor; Efl.Object.constructor; Efl.Object.finalize; Efl.Object.destructor; Efl.Object.provider_find; Efl.Gfx.color { set; } Efl.Gfx.visible { set; } Efl.Gfx.position { set; } Efl.Gfx.size { set; } Efl.Canvas.Object.clip { set; } Efl.Canvas.Object.no_render { set; } Efl.Canvas.Object.is_frame_object { set; } Efl.Canvas.Group.group_calculate; Efl.Canvas.Group.group_member_del; Efl.Canvas.Group.group_member_add; Elm.Interface.Atspi_Accessible.name { get; } Elm.Interface.Atspi_Accessible.state_set { get; } Elm.Interface.Atspi_Accessible.children { get; } Elm.Interface.Atspi_Accessible.parent { get; } Elm.Interface.Atspi_Accessible.attributes { get; } Elm.Interface.Atspi_Component.focus_grab; Efl.Ui.Focus.User.manager { get; } Efl.Ui.Focus.User.parent { get; } Efl.Ui.Focus.Object.focus_geometry { get; } Efl.Ui.Focus.Object.focus { set; } Efl.Ui.Base.scale { get; set; } Efl.Ui.Base.mirrored { get; set; } + Efl.Ui.Base.mirrored_automatic { get; set; } } events { moved; [[Called when widget moved]] focused; [[Called when widget was focused]] unfocused; [[Called when widget was unfocused]] language,changed; [[Called when widget language changed]] access,changed; [[Called when accessibility changed]] } } diff --git a/src/lib/elementary/elm_widget.h b/src/lib/elementary/elm_widget.h index 953718508d..7f9fd11f72 100644 --- a/src/lib/elementary/elm_widget.h +++ b/src/lib/elementary/elm_widget.h @@ -1,872 +1,868 @@ #ifndef ELM_WIDGET_H #define ELM_WIDGET_H /* DO NOT USE THIS HEADER UNLESS YOU ARE PREPARED FOR BREAKING OF YOUR * CODE. THIS IS ELEMENTARY'S INTERNAL WIDGET API (for now) AND IS NOT * FINAL. CALL elm_widget_api_check(ELM_INTERNAL_API_VERSION) TO CHECK * IT AT RUNTIME. * * How to make your own widget? like this (where wname is your widget * name (space) and wparentname is you widget's parent widget name * (the base widget class if its a 'root' one). * * #include * #include "elm_priv.h" * * static const char ELM_WNAME_SMART_NAME[] = "elm_wname"; * * #define ELM_WNAME_DATA_GET(o, sd) \ * Elm_WName_Smart_Data * sd = evas_object_smart_data_get(o) * * #define ELM_WNAME_CHECK(obj) \ * if (!obj || !elm_widget_type_check((obj), ELM_WNAME_SMART_NAME, \ * __func__)) \ * return * * typedef struct _Elm_WName_Smart_Class * { * Elm_WParentName_Smart_Class base; * } Elm_WName_Smart_Class; * * typedef struct _Elm_WName_Smart_Data Elm_WName_Smart_Data; * struct _Elm_WName_Smart_Data * { * Elm_WParentName_Smart_Data base; * Evas_Object *sub; // or any private data needed for an instance * // add any other instance data here too * }; * * static const char SIG_CLICKED[] = "clicked"; * static const Evas_Smart_Cb_Description _smart_callbacks[] = { * {SIG_CLICKED, ""}, * {NULL, NULL} * }; * * EVAS_SMART_SUBCLASS_NEW * (ELM_WNAME_SMART_NAME, _elm_wname, Elm_WName_Smart_Class, * Elm_WParentName_Smart_Class, elm_wparentname_smart_class_get, * _smart_callbacks); * * static Eina_Bool * _elm_wname_smart_on_focus(Evas_Object *obj) * { * ELM_WNAME_DATA_GET(obj, sd); * * // handle focus going in and out - optional, but if you want to, * // define this virtual function to handle it (e.g. to emit a * // signal to an edje object) * * if (elm_widget_focus_get(obj)) * { * edje_object_signal_emit(sd->sub, "elm,action,focus", "elm"); * evas_object_focus_set(sd->sub, EINA_TRUE); * } * else * { * edje_object_signal_emit(sd->sub, "elm,action,unfocus", "elm"); * evas_object_focus_set(sd->sub, EINA_FALSE); * } * * return EINA_TRUE; * } * * static Eina_Bool * _elm_wname_smart_theme(Evas_Object *obj) * { * ELM_WNAME_DATA_GET(obj, sd); * * if (!ELM_WIDGET_CLASS(_elm_wname_parent_sc)->theme(obj)) * return EINA_FALSE; * * // handle changes in theme/scale etc here. always call the * // parent class's version, as even the base class implements it. * * elm_widget_theme_object_set(obj, sd->sub, "wname", "base", * elm_widget_style_get(obj)); * * return EINA_TRUE; * } * * static Eina_Bool * _elm_widget_smart_disable(Evas_Object *obj) * { * ELM_WNAME_DATA_GET(obj, sd); * * // optional, but handle if the widget gets disabled or not * if (elm_widget_disabled_get(obj)) * edje_object_signal_emit(sd->sub, "elm,state,disabled", "elm"); * else * edje_object_signal_emit(sd->sub, "elm,state,enabled", "elm"); * * return EINA_TRUE; * } * * static void * _elm_wname_smart_add(Evas_Object *obj) * { * EVAS_SMART_DATA_ALLOC(obj, Elm_WName_Smart_Data); * * ELM_WIDGET_CLASS(_elm_wname_parent_sc)->base.add(obj); * * priv->sub = edje_object_add(evas_object_evas_get(obj)); * // just an example having an Edje object here. if it's really the case * // you have a sub edje object as a resize object, consider inheriting * // from @ref elm-layout-class. * elm_widget_can_focus_set(obj, EINA_TRUE); * * // for this widget we will add 1 sub object that is an edje object * priv->sub = edje_object_add(e); * // set the theme. this follows a scheme for group name like this: * // "elm/WIDGETNAME/ELEMENT/STYLE" * // so here it will be: * // "elm/wname/base/default" * // changing style changes style name from default (all widgets start * // with the default style) and element is for your widget internal * // structure as you see fit * elm_widget_theme_object_set * (obj, priv->sub, "wname", "base", "default"); * // listen to a signal from the edje object to produce widget smart * // callback (like click) * edje_object_signal_callback_add * (priv->sub, "elm,action,click", "", _clicked_signal_cb, obj); * // set this sub object as the "resize object". widgets get 1 resize * // object that is resized along with the object wrapper. * elm_widget_resize_object_set(obj, priv->sub, EINA_TRUE); * } * * static void * _elm_wname_smart_del(Evas_Object *obj) * { * ELM_WNAME_DATA_GET(obj, sd); * * // deleting 'virtual' function implementation - on deletion of * // object delete object struct, etc. * * ELM_WIDGET_CLASS(_elm_wname_parent_sc)->base.del(obj); * } * * static void * _elm_wname_smart_set_user(Elm_WName_Smart_Class *sc) * { * ELM_WIDGET_CLASS(sc)->base.add = _elm_wname_smart_add; * ELM_WIDGET_CLASS(sc)->base.del = _elm_wname_smart_del; * * ELM_WIDGET_CLASS(sc)->theme = _elm_wname_smart_theme; * ELM_WIDGET_CLASS(sc)->disable = _elm_wname_smart_disable; * ELM_WIDGET_CLASS(sc)->on_focus = _elm_wname_smart_on_focus; * } * * // actual API to create your widget. add more to manipulate it as * // needed mark your calls with EAPI to make them "external api" * // calls. * * EAPI Evas_Object * * elm_wname_add(Evas_Object *parent) * { * Evas_Object *obj; * * EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL); * * obj = elm_widget_add(_elm_check_smart_class_new(), parent); * if (!obj) return NULL; * * if (!elm_widget_sub_object_add(parent, obj)) * ERR("could not add %p as sub object of %p", obj, parent); * * return obj; * } * * // example - do "whatever" to the widget (here just emit a signal) * EAPI void * elm_wname_whatever(Evas_Object *obj) * { * // check if type is correct - check will return if it fails * ELM_WNAME_CHECK(obj); * // get widget data - type is correct and sane by this point, so this * // should never fail * ELM_WNAME_DATA_GET(obj, sd); * // do whatever you like * edje_object_signal_emit(sd->sub, "elm,state,action,whatever", "elm"); * } * * // you can add more - you need to see elementary's code to know how * // to handle all cases. remember this api is not stable and may * change. it's internal */ #ifndef ELM_INTERNAL_API_ARGESFSDFEFC #warning "You are using an internal elementary API. This API is not stable" #warning "and is subject to change. You use this at your own risk." #warning "Remember to call elm_widget_api_check(ELM_INTERNAL_API_VERSION);" #warning "in your widgets before you call any other elm_widget calls to do" #warning "a correct runtime version check. Also remember - you don't NEED" #warning "to make an Elementary widget is almost ALL cases. You can easily" #warning "make a smart object with Evas's API and do everything you need" #warning "there. You only need a widget if you want to seamlessly be part" #warning "of the focus tree and want to transparently become a container" #warning "for any number of child Elementary widgets" #error "ERROR. Compile aborted." #endif #define ELM_INTERNAL_API_VERSION 7000 /** * @defgroup Widget Widgets Extension Infrastructure * * This section is intended for people willing to create @b custom * Elementary widgets or to contribute new (useful, unique) widgets * upstream. If neither is your case, this text won't be of any use * for you. * * Elementary widgets are built in a @b hierarchical fashion. The idea * is to factorize as much code as possible between widgets with * behavioral similarities, as long as to facilitate the creation of * @b custom, new widgets, may the user need them. * * It all starts with a base class, which aggregates behaviour * @b every Elementary widget is supposed to have: * #Elm_Widget_Smart_Class. Every Elementary widget will be of that * type, be it directly or by means of @b inheriting from it. * * #Elm_Widget_Smart_Class happens to be an @c Evas_Smart_Class. If * you check out Evas' documentation on it, you'll see it's how one is * supposed to create custom Evas objects, what Elementary widgets * are. * * Once one instantiates an Elementary widget, since it inherits from * #Elm_Widget_Smart_Class, the system will raise a class instance of * that type for you. But that happens only @b once: the first time * you ask for an Elementary widget (of a given type). All subsequent * ones will only point to the very same class instance. Since it's * the class which points to the functions implementing the behavior * of objects of that type, all of the live instances of Elementary * widgets (of that type) will share the same blob of code loaded in * memory to execute their routines. * * Now go and take a look at #Elm_Widget_Smart_Class's fields. Because * it inherits from Evas' base smart class, we got a field of that * type as the first member, so that Evas can handle Elementary * objects internally as if they were 'normal' Evas objects. Evas has * the Evas-only behavior function pointers in there, so it's all it * needs. * * Then, comes a version field, so that whenever we got to update or * change the fields on our base smart class, there'll be a runtime * check of the version expected by Elementary and the one provided by * any code linking with it. A mismatch will show the developer of * that code he/she needs to recompile and link its code to a newer * version of Elementary. * * The next fields are the class functions themselves. We call them * 'virtual' because, as in object-oriented languages, one is supposed * here to override them on inheriting classes. On most of * inheritances you'll probably want to call the parent's version of * the class function too: you must analyse each case to tell. * * Take a look at #Elm_Widget_Smart_Data. That's private data bound to * each Elementary object @b instance. It aggregates data needed for * all widgets, since it's meant for the #Elm_Widget_Smart_Class-typed * ones. * * When inheriting from that base type, instance data for this new * class has to have, as the first member, a field of type * #Elm_Widget_Smart_Data. This has to be respected recursively -- if * a third class is to be created inheriting from the one that is a * direct 'child' of #Elm_Widget_Smart_Class, then the private data on * this third class has to have, as its first field, a variable of the * type of the private data of the second class (its parent), direct * child of #Elm_Widget_Smart_Class. * * It is from the base private data, #Elm_Widget_Smart_Data, that we * reach an object's class functions, by the given object * instance. This is the reason of the first field of that struct: a * pointer set to point to its class when the object is instantiated. * * The following figure illustrates the widget inheritance schema. * * @image html elm-widget-hierarchy.png * @image rtf elm-widget-hierarchy.png * @image latex elm-widget-hierarchy.eps * * @section elm-hierarchy-tree Elementary Widgets Hierarchy Tree * * The following figure illustrates the Elementary widget inheritance * tree. * * @image html elm-widget-tree.png * @image rtf elm-widget-tree.png * @image latex elm-widget-tree.eps */ typedef void (*Elm_Widget_Text_Set_Cb)(void *data, const char *part, const char *text); typedef void (*Elm_Widget_Content_Set_Cb)(void *data, const char *part, Evas_Object *content); typedef const char *(*Elm_Widget_Text_Get_Cb)(const void *data, const char *part); typedef Evas_Object *(*Elm_Widget_Content_Get_Cb)(const void *data, const char *part); typedef Evas_Object *(*Elm_Widget_Content_Unset_Cb)(const void *data, const char *part); typedef void (*Elm_Widget_Signal_Emit_Cb)(void *data, const char *emission, const char *source); typedef void (*Elm_Widget_Disable_Cb)(void *data); typedef Eina_Bool (*Elm_Widget_Del_Pre_Cb)(void *data); typedef void (*Elm_Widget_Item_Signal_Cb)(void *data, Elm_Object_Item *item, const char *emission, const char *source); typedef void (*Elm_Widget_Style_Set_Cb)(void *data, const char *style); typedef const char *(*Elm_Widget_Style_Get_Cb)(const void *data); typedef void (*Elm_Widget_Focus_Set_Cb)(void *data, Eina_Bool focused); typedef Eina_Bool (*Elm_Widget_Focus_Get_Cb)(const void *data); typedef void (*Elm_Access_On_Highlight_Cb)(void *data); typedef void (*region_hook_func_type)(void *data, Evas_Object *obj); typedef void * (*list_data_get_func_type)(const Eina_List * l); #include "elm_widget.eo.h" /** * @addtogroup Widget * @{ */ /* Please, ALWAYS update the ELM_WIDGET_SMART_CLASS_INIT macro * whenever you change the following struct! */ /** * Base widget smart class. It has the 'virtual' functions for all * general, common actions on Elementary widgets. */ typedef struct _Elm_Widget_Smart_Class { Evas_Smart_Class base; /**< Base smart class struct, needed for all smart objects */ int version; /**< Version of this smart class definition */ void (*parent_set)(Evas_Object *obj, Evas_Object *parent); /**< 'Virtual' function handling parent widget attachment to new object */ Eina_Bool (*on_focus)(Evas_Object *obj); /**< 'Virtual' function handling focus in/out events on the widget */ Eina_Bool (*disable)(Evas_Object *obj); /**< 'Virtual' function on the widget being disabled */ Eina_Bool (*theme)(Evas_Object *obj); /**< 'Virtual' function on the widget being re-themed */ Eina_Bool (*translate)(Evas_Object *obj); /**< 'Virtual' function handling language changes on Elementary */ Eina_Bool (*event)(Evas_Object *obj, Evas_Object *source, Evas_Callback_Type type, void *event_info); /**< 'Virtual' function handling input events on the widget */ Eina_Bool (*on_focus_region)(const Evas_Object *obj, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h); /**< 'Virtual' function returning an inner area of a widget that should be brought into the visible area of a broader viewport, may this context arise. On the base Elementary widget class, it defaults to the object's total area, so only override it if you have to. */ Eina_Bool (*focus_next)(const Evas_Object *obj, Elm_Focus_Direction dir, Evas_Object **next, Elm_Object_Item **next_item); /**< 'Virtual' function handling passing focus to sub-objects */ Eina_Bool (*focus_direction)(const Evas_Object *obj, const Evas_Object *base, double degree, Evas_Object **target, Elm_Object_Item **target_item, double *weight); /**< 'Virtual' function handling passing focus to sub-objects given a direction, in degrees */ Eina_Bool (*sub_object_add)(Evas_Object *obj, Evas_Object *sobj); /**< 'Virtual' function handling sub objects being added */ Eina_Bool (*sub_object_del)(Evas_Object *obj, Evas_Object *sobj); /**< 'Virtual' function handling sub objects being removed */ void (*access)(Evas_Object *obj, Eina_Bool is_access); /**< 'Virtual' function on the widget being set access */ Eina_Bool (*activate)(Evas_Object *obj, Elm_Activate act); /**< 'Virtual' function to activate widget */ } Elm_Widget_Smart_Class; /** * Base widget smart data. This is data bound to an Elementary object * @b instance, so its particular to that specific object and not * shared between all objects in its class. It is here, though, that * we got a pointer to the object's class, the first field -- @c * 'api'. */ typedef struct _Elm_Widget_Smart_Data { Evas_Object *obj; /**< object pointer for this widget smart data */ Evas_Object *parent_obj; /**< parent object of a widget in the elementary tree */ Evas_Object *parent2; /**< parent object for an inlined window */ Evas_Coord x, y, w, h; Eina_List *subobjs; /**< list of widgets' sub objects in the elementary tree */ Evas_Object *resize_obj; /**< an unique object for each widget that shows the look of a widget. Resize object's geometry is same as the widget. This resize object is different from that of window's resize object. */ Evas_Object *hover_obj; Eina_List *tooltips, *cursors; Evas_Object *focus_previous, *focus_next; Evas_Object *focus_up, *focus_down, *focus_right, *focus_left; Elm_Object_Item *item_focus_previous, *item_focus_next; Elm_Object_Item *item_focus_up, *item_focus_down, *item_focus_right, *item_focus_left; /* "show region" coordinates. all widgets got those because this * info may be set and queried recursively through the widget * parenting tree */ Evas_Coord rx, ry, rw, rh; /* scrolling hold/freeze hints. all widgets got those because this * info may be set and queried recursively through the widget * parenting tree */ int scroll_hold; int scroll_freeze; double scale; Elm_Theme *theme; const char *style; const char *focus_highlight_style; /**< custom focus style for a widget */ const char *access_info; const char *accessible_name; unsigned int focus_order; Eina_Bool focus_order_on_calc; int child_drag_x_locked; int child_drag_y_locked; Eina_Inlist *translate_strings; Eina_List *focus_chain; Eina_List *event_cb; /* this is a hook to be set on-the-fly on widgets. this is code * handling the request of showing a specific region from an inner * widget (mainly issued by entries, on cursor moving) */ void *on_show_region_data; void (*on_show_region)(void *data, Evas_Object *obj); int orient_mode; /* -1 is disabled */ Elm_Focus_Move_Policy focus_move_policy; Elm_Focus_Region_Show_Mode focus_region_show_mode; struct { Efl_Ui_Focus_Manager *manager; //manager which is currently regsitered in Eina_Bool logical; } focus; struct { int child_count; Efl_Ui_Focus_Object *parent; } logical; struct { Efl_Ui_Focus_Manager *manager; Efl_Ui_Focus_User *provider; } manager; Eina_Bool drag_x_locked : 1; Eina_Bool drag_y_locked : 1; Eina_Bool can_focus : 1; Eina_Bool child_can_focus : 1; Eina_Bool focused : 1; Eina_Bool top_win_focused : 1; Eina_Bool tree_unfocusable : 1; Eina_Bool focus_move_policy_auto_mode : 1; /* This is TRUE by default */ Eina_Bool highlight_ignore : 1; Eina_Bool highlight_in_theme : 1; Eina_Bool access_highlight_in_theme : 1; Eina_Bool disabled : 1; Eina_Bool is_mirrored : 1; - Eina_Bool mirrored_auto_mode : 1; /* This is - * TRUE by - * default */ + Eina_Bool mirrored_auto_mode : 1; /* This is TRUE by default */ Eina_Bool still_in : 1; Eina_Bool highlighted : 1; Eina_Bool highlight_root : 1; Eina_Bool on_translate : 1; /**< This is true when any types of elm translate function is being called. */ Eina_Bool on_create : 1; /**< This is true when the widget is on creation(general widget constructor). */ Eina_Bool on_destroy: 1; /**< This is true when the widget is on destruction(general widget destructor). */ Eina_Bool provider_lookup : 1; /**< This is true when efl_provider_find is currently walking the tree */ } Elm_Widget_Smart_Data; /** * @} */ /**< base structure for all widget items that are not Elm_Widget themselves */ typedef struct _Elm_Widget_Item_Data Elm_Widget_Item_Data; typedef struct _Elm_Widget_Item_Signal_Data Elm_Widget_Item_Signal_Data; /**< accessibility information to be able to set and get from the access API */ typedef struct _Elm_Access_Info Elm_Access_Info; /**< accessibility info item */ typedef struct _Elm_Access_Item Elm_Access_Item; typedef struct _Elm_Action Elm_Action; /** Internal type for mouse cursors */ typedef struct _Elm_Cursor Elm_Cursor; #define ELM_ACCESS_DONE -1 /* sentence done - send done event here */ #define ELM_ACCESS_CANCEL -2 /* stop reading immediately */ struct _Elm_Access_Item { int type; const void *data; Elm_Access_Info_Cb func; }; struct _Elm_Access_Info { Evas_Object *hoverobj; Eina_List *items; Ecore_Timer *delay_timer; void *on_highlight_data; Elm_Access_On_Highlight_Cb on_highlight; void *activate_data; Elm_Access_Activate_Cb activate; /* the owner widget item that owns this access info */ Elm_Widget_Item_Data *widget_item; /* the owner part object that owns this access info */ Evas_Object *part_object; Evas_Object *next; Evas_Object *prev; }; struct _Elm_Action { const char *name; Eina_Bool (*func)(Evas_Object *obj, const char *params); }; void _elm_access_shutdown(void); void _elm_access_mouse_event_enabled_set(Eina_Bool enabled); /* if auto_higlight is EINA_TRUE, it does not steal a focus, it just moves a highlight */ void _elm_access_auto_highlight_set(Eina_Bool enabled); Eina_Bool _elm_access_auto_highlight_get(void); void _elm_access_widget_item_access_order_set(Elm_Widget_Item_Data *item, Eina_List *objs); const Eina_List *_elm_access_widget_item_access_order_get(const Elm_Widget_Item_Data *item); void _elm_access_widget_item_access_order_unset(Elm_Widget_Item_Data *item); // widget focus highlight void _elm_widget_focus_highlight_start(const Evas_Object *obj); void _elm_widget_highlight_in_theme_update(Eo *obj); // win focus highlight void _elm_win_focus_highlight_start(Evas_Object *obj); void _elm_win_focus_highlight_in_theme_update(Evas_Object *obj, Eina_Bool in_theme); Evas_Object *_elm_win_focus_highlight_object_get(Evas_Object *obj); void _elm_win_focus_auto_show(Evas_Object *obj); void _elm_win_focus_auto_hide(Evas_Object *obj); EAPI void _elm_access_clear(Elm_Access_Info *ac); EAPI void _elm_access_text_set(Elm_Access_Info *ac, int type, const char *text); EAPI void _elm_access_callback_set(Elm_Access_Info *ac, int type, Elm_Access_Info_Cb func, const void *data); EAPI char *_elm_access_text_get(const Elm_Access_Info *ac, int type, const Evas_Object *obj); /* this is ok it actually returns a strduped string - it's meant to! */ EAPI void _elm_access_read(Elm_Access_Info *ac, int type, const Evas_Object *obj); EAPI void _elm_access_say(const char *txt); EAPI Elm_Access_Info *_elm_access_info_get(const Evas_Object *obj); EAPI void _elm_access_object_highlight(Evas_Object *obj); EAPI void _elm_access_object_unhighlight(Evas_Object *obj); EAPI void _elm_access_object_highlight_disable(Evas *e); EAPI void _elm_access_object_register(Evas_Object *obj, Evas_Object *hoverobj); EAPI void _elm_access_object_unregister(Evas_Object *obj, Evas_Object *hoverobj); EAPI Eina_Bool _elm_access_2nd_click_timeout(Evas_Object *obj); EAPI void _elm_access_highlight_set(Evas_Object* obj); EAPI Evas_Object * _elm_access_edje_object_part_object_register(Evas_Object *obj, const Evas_Object *partobj, const char* part); EAPI void _elm_access_edje_object_part_object_unregister(Evas_Object* obj, const Evas_Object *eobj, const char* part); EAPI void _elm_access_widget_item_register(Elm_Widget_Item_Data *item); EAPI void _elm_access_widget_item_unregister(Elm_Widget_Item_Data *item); EAPI void _elm_access_on_highlight_hook_set(Elm_Access_Info *ac, Elm_Access_On_Highlight_Cb func, void *data); EAPI void _elm_access_activate_callback_set(Elm_Access_Info *ac, Elm_Access_Activate_Cb func, void *data); EAPI void _elm_access_highlight_object_activate(Evas_Object *obj, Elm_Activate act); EAPI void _elm_access_highlight_cycle(Evas_Object *obj, Elm_Focus_Direction dir); EINA_DEPRECATED EAPI Elm_Access_Info *_elm_access_object_get(const Evas_Object *obj); #define ELM_PREFS_DATA_MAGIC 0xe1f5da7a /**< put this as the first member in your widget item struct */ #define ELM_WIDGET_ITEM Elm_Widget_Item_Data base struct _Elm_Widget_Item_Signal_Data { Elm_Object_Item *item; Elm_Widget_Item_Signal_Cb func; const char *emission; const char *source; void *data; }; #define WIDGET_ITEM_DATA_GET(eo_obj) \ efl_key_data_get((Eo *) eo_obj, "__elm_widget_item_data") #define WIDGET_ITEM_DATA_SET(eo_obj, data) \ efl_key_data_set((Eo *) eo_obj, "__elm_widget_item_data", data) struct _Elm_Widget_Item_Data { /* ef1 ~~ efl, el3 ~~ elm */ #define ELM_WIDGET_ITEM_MAGIC 0xef1e1301 EINA_MAGIC; /* simple accessor macros */ #define VIEW(X) X->base->view #define WIDGET(X) X->base->widget #define EO_OBJ(X) ((X)?X->base->eo_obj:NULL) /**< the owner widget that owns this item */ Evas_Object *widget; /**< The Eo item, useful to invoke eo_do when only the item data is available */ Eo *eo_obj; /**< the base view object */ Evas_Object *view; /**< user delete callback function */ Evas_Smart_Cb del_func; /**< widget delete callback function. don't expose this callback call */ Elm_Widget_Del_Pre_Cb del_pre_func; Evas_Object *focus_previous, *focus_next; Evas_Object *focus_up, *focus_down, *focus_right, *focus_left; Elm_Object_Item *item_focus_previous, *item_focus_next; Elm_Object_Item *item_focus_up, *item_focus_down, *item_focus_right, *item_focus_left; Evas_Object *access_obj; const char *access_info; const char *accessible_name; Eina_List *access_order; Eina_Inlist *translate_strings; Eina_List *signals; Eina_Hash *labels; Evas_Object *track_obj; Eina_Bool disabled : 1; Eina_Bool on_deletion : 1; Eina_Bool on_translate : 1; Eina_Bool still_in : 1; }; #define ELM_NEW(t) calloc(1, sizeof(t)) EAPI Evas_Object *elm_widget_add(Evas_Smart *, Evas_Object *); EAPI void elm_widget_parent_set(Evas_Object *, Evas_Object *); EAPI Eina_Bool elm_widget_api_check(int ver); EAPI Eina_Bool elm_widget_access(Evas_Object *obj, Eina_Bool is_access); EAPI Elm_Theme_Apply elm_widget_theme(Evas_Object *obj); EAPI void elm_widget_theme_specific(Evas_Object *obj, Elm_Theme *th, Eina_Bool force); EAPI void elm_widget_translate(Evas_Object *obj); EAPI void elm_widget_on_show_region_hook_set(Evas_Object *obj, void (*func)(void *data, Evas_Object *obj), void *data); EAPI Eina_Bool elm_widget_sub_object_parent_add(Evas_Object *sobj); EAPI Eina_Bool elm_widget_sub_object_add(Evas_Object *obj, Evas_Object *sobj); EAPI Eina_Bool elm_widget_sub_object_del(Evas_Object *obj, Evas_Object *sobj); EAPI void elm_widget_resize_object_set(Evas_Object *obj, Evas_Object *sobj, Eina_Bool sub_obj); EAPI void elm_widget_hover_object_set(Evas_Object *obj, Evas_Object *sobj); EAPI void elm_widget_signal_emit(Evas_Object *obj, const char *emission, const char *source); EAPI void elm_widget_signal_callback_add(Evas_Object *obj, const char *emission, const char *source, Edje_Signal_Cb func, void *data); EAPI void *elm_widget_signal_callback_del(Evas_Object *obj, const char *emission, const char *source, Edje_Signal_Cb func); EAPI void elm_widget_can_focus_set(Evas_Object *obj, Eina_Bool can_focus); EAPI Eina_Bool elm_widget_can_focus_get(const Evas_Object *obj); EAPI Eina_Bool elm_widget_child_can_focus_get(const Evas_Object *obj); EAPI Eina_List *elm_widget_can_focus_child_list_get(const Evas_Object *obj); EAPI void elm_widget_tree_unfocusable_set(Evas_Object *obj, Eina_Bool tree_unfocusable); EAPI Eina_Bool elm_widget_tree_unfocusable_get(const Evas_Object *obj); EAPI void elm_widget_highlight_ignore_set(Evas_Object *obj, Eina_Bool ignore); EAPI Eina_Bool elm_widget_highlight_ignore_get(const Evas_Object *obj); EAPI void elm_widget_highlight_in_theme_set(Evas_Object *obj, Eina_Bool highlight); EAPI Eina_Bool elm_widget_highlight_in_theme_get(const Evas_Object *obj); EAPI void elm_widget_access_highlight_in_theme_set(Evas_Object *obj, Eina_Bool highlight); EAPI Eina_Bool elm_widget_access_highlight_in_theme_get(const Evas_Object *obj); EAPI Eina_Bool elm_widget_focus_get(const Evas_Object *obj); EAPI Eina_Bool elm_widget_highlight_get(const Evas_Object *obj); EAPI Evas_Object *elm_widget_focused_object_get(const Evas_Object *obj); EAPI Evas_Object *elm_widget_top_get(const Evas_Object *obj); EAPI Eina_Bool elm_widget_is(const Evas_Object *obj); EAPI Evas_Object *elm_widget_parent_widget_get(const Evas_Object *obj); EAPI void elm_widget_event_callback_add(Evas_Object *obj, Elm_Event_Cb func, const void *data); EAPI void *elm_widget_event_callback_del(Evas_Object *obj, Elm_Event_Cb func, const void *data); EAPI Eina_Bool elm_widget_event_propagate(Evas_Object *obj, Evas_Callback_Type type, void *event_info, Evas_Event_Flags *event_flags); EAPI void elm_widget_focus_custom_chain_set(Evas_Object *obj, Eina_List *objs); EAPI void elm_widget_focus_custom_chain_unset(Evas_Object *obj); EAPI const Eina_List *elm_widget_focus_custom_chain_get(const Evas_Object *obj); EAPI void elm_widget_focus_custom_chain_append(Evas_Object *obj, Evas_Object *child, Evas_Object *relative_child); EAPI void elm_widget_focus_custom_chain_prepend(Evas_Object *obj, Evas_Object *child, Evas_Object *relative_child); EAPI void elm_widget_focus_cycle(Evas_Object *obj, Elm_Focus_Direction dir); EAPI Eina_Bool elm_widget_focus_direction_go(Evas_Object *obj, double degree); EAPI Eina_Bool elm_widget_focus_direction_get(const Evas_Object *obj, const Evas_Object *base, double degree, Evas_Object **direction, Elm_Object_Item **direction_item, double *weight); EAPI Eina_Bool elm_widget_focus_next_get(const Evas_Object *obj, Elm_Focus_Direction dir, Evas_Object **next, Elm_Object_Item **next_item); EAPI Eina_Bool elm_widget_focus_list_direction_get(const Evas_Object *obj, const Evas_Object *base, const Eina_List *items, void *(*list_data_get)(const Eina_List *list), double degree, Evas_Object **direction, Elm_Object_Item **direction_item, double *weight); EAPI Eina_Bool elm_widget_focus_list_next_get(const Evas_Object *obj, const Eina_List *items, void *(*list_data_get)(const Eina_List *list), Elm_Focus_Direction dir, Evas_Object **next, Elm_Object_Item **next_item); EAPI Evas_Object *elm_widget_focus_next_object_get(const Evas_Object *obj, Elm_Focus_Direction dir); EAPI void elm_widget_focus_next_object_set(Evas_Object *obj, Evas_Object *next, Elm_Focus_Direction dir); EAPI Elm_Object_Item *elm_widget_focus_next_item_get(const Evas_Object *obj, Elm_Focus_Direction dir); EAPI void elm_widget_focus_next_item_set(Evas_Object *obj, Elm_Object_Item *next_item, Elm_Focus_Direction dir); EAPI Eina_Bool elm_widget_focus_highlight_style_set(Evas_Object *obj, const char *style); EAPI const char *elm_widget_focus_highlight_style_get(const Evas_Object *obj); EAPI void elm_widget_parent_highlight_set(Evas_Object *obj, Eina_Bool highlighted); EAPI void elm_widget_focus_set(Evas_Object *obj, Eina_Bool focus); EAPI void elm_widget_focused_object_clear(Evas_Object *obj); EAPI Evas_Object *elm_widget_parent_get(const Evas_Object *obj); EAPI Evas_Object *elm_widget_parent2_get(const Evas_Object *obj); EAPI void elm_widget_parent2_set(Evas_Object *obj, Evas_Object *parent); EAPI void elm_widget_focus_steal(Evas_Object *obj, Elm_Object_Item *next_item); EAPI Evas_Object *elm_widget_newest_focus_order_get(const Evas_Object *obj, unsigned int *newest_focus_order, Eina_Bool can_focus_only); EAPI void elm_widget_display_mode_set(Evas_Object *obj, Evas_Display_Mode dispmode); EAPI Eina_Bool elm_widget_focus_highlight_enabled_get(const Evas_Object *obj); EAPI void elm_widget_focus_highlight_focus_part_geometry_get(const Evas_Object *obj, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h); Evas_Object *_elm_widget_focus_highlight_object_get(const Evas_Object *obj); double _elm_widget_focus_direction_weight_get(const Evas_Object *obj1, const Evas_Object *obj2, double degree); EAPI const Elm_Widget_Smart_Class *elm_widget_smart_class_get(void); /** * @internal * * Restore the focus state of the sub-tree. * * This API will restore the focus state of the sub-tree to the latest * state. If a sub-tree is unfocused and wants to get back to the latest * focus state, this API will be helpful. * * @param obj The widget root of sub-tree * * @ingroup Widget */ EAPI void elm_widget_focus_restore(Evas_Object *obj); EAPI void elm_widget_disabled_set(Evas_Object *obj, Eina_Bool disabled); EAPI Eina_Bool elm_widget_disabled_get(const Evas_Object *obj); EAPI void elm_widget_show_region_set(Evas_Object *obj, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h, Eina_Bool forceshow); EAPI void elm_widget_show_region_get(const Evas_Object *obj, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h); EAPI Eina_Bool elm_widget_focus_region_get(const Evas_Object *obj, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h); EAPI void elm_widget_focus_region_show(const Evas_Object *obj); EAPI void elm_widget_parents_bounce_get(const Evas_Object *obj, Eina_Bool *horiz, Eina_Bool *vert); EAPI void elm_widget_scroll_hold_push(Evas_Object *obj); EAPI void elm_widget_scroll_hold_pop(Evas_Object *obj); EAPI int elm_widget_scroll_hold_get(const Evas_Object *obj); EAPI void elm_widget_scroll_freeze_push(Evas_Object *obj); EAPI void elm_widget_scroll_freeze_pop(Evas_Object *obj); EAPI int elm_widget_scroll_freeze_get(const Evas_Object *obj); -EAPI Eina_Bool elm_widget_mirrored_automatic_get(const Evas_Object *obj); -EAPI void elm_widget_mirrored_automatic_set(Evas_Object *obj, Eina_Bool automatic); EAPI void elm_widget_theme_set(Evas_Object *obj, Elm_Theme *th); EAPI Elm_Theme *elm_widget_theme_get(const Evas_Object *obj); EAPI Elm_Theme_Apply elm_widget_style_set(Evas_Object *obj, const char *style); EAPI const char *elm_widget_style_get(const Evas_Object *obj); EAPI void elm_widget_type_set(Evas_Object *obj, const char *type); EAPI const char *elm_widget_type_get(const Evas_Object *obj); EAPI void elm_widget_tooltip_add(Evas_Object *obj, Elm_Tooltip *tt); EAPI void elm_widget_tooltip_del(Evas_Object *obj, Elm_Tooltip *tt); EAPI void elm_widget_cursor_add(Evas_Object *obj, Elm_Cursor *cur); EAPI void elm_widget_cursor_del(Evas_Object *obj, Elm_Cursor *cur); EAPI void elm_widget_drag_lock_x_set(Evas_Object *obj, Eina_Bool lock); EAPI void elm_widget_drag_lock_y_set(Evas_Object *obj, Eina_Bool lock); EAPI Eina_Bool elm_widget_drag_lock_x_get(const Evas_Object *obj); EAPI Eina_Bool elm_widget_drag_lock_y_get(const Evas_Object *obj); EAPI int elm_widget_drag_child_locked_x_get(const Evas_Object *obj); EAPI int elm_widget_drag_child_locked_y_get(const Evas_Object *obj); EAPI void elm_widget_item_loop_enabled_set(Evas_Object *obj, Eina_Bool enable); EAPI Eina_Bool elm_widget_item_loop_enabled_get(const Evas_Object *obj); EAPI Elm_Theme_Apply elm_widget_theme_object_set(Evas_Object *obj, Evas_Object *edj, const char *wname, const char *welement, const char *wstyle); EAPI Eina_Bool elm_widget_type_check(const Evas_Object *obj, const char *type, const char *func); EAPI Evas_Object *elm_widget_name_find(const Evas_Object *obj, const char *name, int recurse); EAPI Eina_List *elm_widget_stringlist_get(const char *str); EAPI void elm_widget_stringlist_free(Eina_List *list); EAPI void elm_widget_focus_hide_handle(Evas_Object *obj); EAPI void elm_widget_focus_mouse_up_handle(Evas_Object *obj); EAPI void elm_widget_focus_tree_unfocusable_handle(Evas_Object *obj); EAPI void elm_widget_focus_disabled_handle(Evas_Object *obj); EAPI unsigned int elm_widget_focus_order_get(const Evas_Object *obj); EAPI void elm_widget_activate(Evas_Object *obj, Elm_Activate act); EAPI void elm_widget_part_text_set(Evas_Object *obj, const char *part, const char *label); EAPI const char *elm_widget_part_text_get(const Evas_Object *obj, const char *part); EAPI void elm_widget_domain_translatable_part_text_set(Evas_Object *obj, const char *part, const char *domain, const char *text); EAPI const char *elm_widget_translatable_part_text_get(const Evas_Object *obj, const char *part); EAPI void elm_widget_domain_part_text_translatable_set(Evas_Object *obj, const char *part, const char *domain, Eina_Bool translatable); EAPI const char * elm_widget_part_text_translate(Evas_Object *obj, const char *part, const char *text); EAPI void elm_widget_content_part_set(Evas_Object *obj, const char *part, Evas_Object *content); EAPI Evas_Object *elm_widget_content_part_get(const Evas_Object *obj, const char *part); EAPI Evas_Object *elm_widget_content_part_unset(Evas_Object *obj, const char *part); EAPI void elm_widget_access_info_set(Evas_Object *obj, const char *txt); EAPI const char *elm_widget_access_info_get(const Evas_Object *obj); EAPI void elm_widget_orientation_set(Evas_Object *obj, int rotation); EAPI Elm_Object_Item *elm_widget_focused_item_get(const Evas_Object *obj); EAPI void elm_widget_orientation_mode_disabled_set(Evas_Object *obj, Eina_Bool disabled); EAPI Eina_Bool elm_widget_orientation_mode_disabled_get(const Evas_Object *obj); EAPI void elm_widget_focus_highlight_geometry_get(const Evas_Object *obj, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h); void _elm_widget_item_highlight_in_theme(Evas_Object *obj, Elm_Object_Item *it); EAPI void elm_widget_focus_move_policy_set(Evas_Object *obj, Elm_Focus_Move_Policy policy); EAPI Elm_Focus_Move_Policy elm_widget_focus_move_policy_get(const Evas_Object *obj); EAPI Eina_Bool elm_widget_focus_move_policy_automatic_get(const Evas_Object *obj); EAPI void elm_widget_focus_move_policy_automatic_set(Evas_Object *obj, Eina_Bool automatic); EAPI void elm_widget_focus_region_show_mode_set(Evas_Object *obj, Elm_Focus_Region_Show_Mode mode); EAPI Elm_Focus_Region_Show_Mode elm_widget_focus_region_show_mode_get(const Evas_Object *obj); EAPI void elm_widget_focus_reconfigure(Evas_Object *obj); /** * Function to operate on a given widget's scrollabe children when necessary. * @warning free the returned list with eina_list_free(). */ EAPI Eina_List *elm_widget_scrollable_children_get(const Evas_Object *obj); /* debug function. don't use it unless you are tracking parenting issues */ EAPI void elm_widget_tree_dump(const Evas_Object *top); EAPI void elm_widget_tree_dot_dump(const Evas_Object *top, FILE *output); EAPI Eina_Bool _elm_widget_onscreen_is(Evas_Object *widget); EAPI Eina_Bool _elm_widget_item_onscreen_is(Elm_Object_Item *item); #define ELM_WIDGET_DATA_GET_OR_RETURN(o, ptr, ...) \ Elm_Widget_Smart_Data *ptr; \ ptr = efl_data_scope_get(o, ELM_WIDGET_CLASS); \ if (EINA_UNLIKELY(!ptr)) \ { \ CRI("no widget data for object %p (%s)", \ o, evas_object_type_get(o)); \ return __VA_ARGS__; \ } #define ELM_WIDGET_CHECK(obj) \ if (EINA_UNLIKELY(!efl_isa((obj), ELM_WIDGET_CLASS))) \ return #define ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item, ...) \ do { \ if (item && (item)->on_deletion) { \ WRN("Elm_Widget_Item " # item " is deleting"); \ return __VA_ARGS__; \ } \ } while (0) #define ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, ...) \ do { \ if (!item) { \ CRI("Elm_Widget_Item " # item " is NULL"); \ return __VA_ARGS__; \ } \ if ((item)->eo_obj && \ efl_isa((item)->eo_obj, ELM_WIDGET_ITEM_CLASS)) break; \ if (!EINA_MAGIC_CHECK(item, ELM_WIDGET_ITEM_MAGIC)) { \ EINA_MAGIC_FAIL(item, ELM_WIDGET_ITEM_MAGIC); \ return __VA_ARGS__; \ } \ } while (0) #define ELM_WIDGET_ITEM_CHECK_OR_GOTO(item, label) \ do { \ if (!item) { \ CRI("Elm_Widget_Item " # item " is NULL"); \ goto label; \ } \ if ((item)->eo_obj && \ efl_isa((item)->eo_obj, ELM_WIDGET_ITEM_CLASS)) break; \ if (!EINA_MAGIC_CHECK(item, ELM_WIDGET_ITEM_MAGIC)) { \ EINA_MAGIC_FAIL(item, ELM_WIDGET_ITEM_MAGIC); \ goto label; \ } \ } while (0) static inline Eina_Bool _elm_widget_sub_object_redirect_to_top(Evas_Object *obj, Evas_Object *sobj) { Eina_Bool ret = elm_widget_sub_object_del(obj, sobj); if (ret) ret = elm_widget_sub_object_add(elm_widget_top_get(obj), sobj); return ret; } /* to be used by INTERNAL classes on Elementary, so that the widgets * parsing script skips it */ #define ELM_INTERNAL_SMART_SUBCLASS_NEW EVAS_SMART_SUBCLASS_NEW EAPI Eina_Bool elm_selection_selection_has_owner(Evas_Object *obj); #define ELM_WIDGET_ITEM_PROTECTED #include "elm_widget_item.eo.h" #endif