cedric pushed a commit to branch master. http://git.enlightenment.org/core/efl.git/commit/?id=590304d5972dc0141cd3b46767c72336e68b9bc5
commit 590304d5972dc0141cd3b46767c72336e68b9bc5 Author: Cedric BAIL <[email protected]> Date: Fri May 4 16:15:18 2018 -0700 eio: properly handle Eio.Model lifecycle inside Elm.Fileselector. Differential Revision: https://phab.enlightenment.org/D6107 --- src/lib/elementary/elc_fileselector.c | 77 ++++++++++++++++++++++++----------- 1 file changed, 54 insertions(+), 23 deletions(-) diff --git a/src/lib/elementary/elc_fileselector.c b/src/lib/elementary/elc_fileselector.c index e4dd5cdeb0..e53b46d06e 100644 --- a/src/lib/elementary/elc_fileselector.c +++ b/src/lib/elementary/elc_fileselector.c @@ -149,6 +149,27 @@ _monitoring_stop(Elm_Fileselector *fs, Elm_Fileselector_Data *sd, Efl_Model *mod efl_event_callback_array_del(model, monitoring_callbacks(), fs); } +static void _noref_death(void *data EINA_UNUSED, const Efl_Event *event); +static void _invalidated(void *data EINA_UNUSED, const Efl_Event *event); + +EFL_CALLBACKS_ARRAY_DEFINE(noref_death, + { EFL_EVENT_NOREF, _noref_death }, + { EFL_EVENT_INVALIDATE, _invalidated }); + +static void +_noref_death(void *data EINA_UNUSED, const Efl_Event *event) +{ + efl_event_callback_array_del(event->object, noref_death(), NULL); + efl_del(event->object); +} + +static void +_invalidated(void *data EINA_UNUSED, const Efl_Event *event) +{ + // This means our parent is dying, EFL_EVENT_NOREF can be called after invalidated + efl_event_callback_array_del(event->object, noref_death(), NULL); +} + static void _elm_fileselector_replace_model(Elm_Fileselector *fs, Elm_Fileselector_Data *sd, Efl_Model *model, const char *path) { @@ -265,9 +286,12 @@ _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); + Efl_Model *tmp = NULL; + + tmp = sd->prev_model; sd->prev_model = NULL; + _populate(obj, sd->prev_model, NULL, NULL); + efl_unref(tmp); } else _on_dir_up(obj, NULL); @@ -950,7 +974,7 @@ _populate(Evas_Object *obj, sd->current_populate_lreq = NULL; } - if (sd->model) + if (sd->monitoring) _monitoring_stop(obj, sd, sd->model); lreq = calloc(1, sizeof (Listing_Request)); @@ -1038,10 +1062,8 @@ _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); + efl_replace(&sdata->model, NULL); + efl_replace(&sdata->selected, NULL); sd->populate_idler = NULL; @@ -1061,17 +1083,15 @@ _schedule_populate(Evas_Object *fs, if (!sdata) return; sdata->fs = fs; - sdata->model = model ? efl_ref(model) : NULL; - sdata->selected = selected ? efl_ref(selected) : NULL; + efl_replace(&sdata->model, model); + efl_replace(&sdata->selected, 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); + efl_replace(&old_sdata->model, NULL); + efl_replace(&old_sdata->selected, NULL); free(old_sdata); } sd->populate_idler = ecore_idler_add(_populate_do, sdata); @@ -1341,7 +1361,8 @@ _ok(void *data, const Efl_Event *event) else selection = eina_stringshare_printf("%s/%s", sd->path, name); - selected_model = efl_add(efl_class_get(sd->model), event->object); + selected_model = efl_add_ref(efl_class_get(sd->model), event->object, + efl_event_callback_array_add(efl_added, noref_death(), NULL)); _model_str_property_set(selected_model, "path", selection); _model_event_call @@ -1429,6 +1450,7 @@ _on_text_activated_set_path_then(void *data, const Eina_Value v, const Eina_Futu end: _text_activated_free_fs_data(fs); + efl_unref(model); return v; } @@ -1446,7 +1468,8 @@ _on_text_activated(void *data, const Efl_Event *event) if (!sd->model) return; path = elm_widget_part_text_get(event->object, NULL); - model = efl_add(efl_class_get(sd->model), event->object); + model = efl_add_ref(efl_class_get(sd->model), event->object, + efl_event_callback_array_add(efl_added, noref_death(), NULL)); if (!model) return; future = _model_str_property_set(model, "path", path); @@ -1456,7 +1479,6 @@ _on_text_activated(void *data, const Efl_Event *event) efl_ref(fs); eina_future_then(future, _on_text_activated_set_path_then, fs); - efl_unref(model); elm_object_focus_set(event->object, EINA_FALSE); } @@ -1501,7 +1523,8 @@ _anchor_clicked(void *data, const Efl_Event *event) if (!sd->model) return; - model = efl_add(efl_class_get(sd->model), event->object); + model = efl_add_ref(efl_class_get(sd->model), event->object, + efl_event_callback_array_add(efl_added, noref_death(), NULL)); if (!model) return; _model_str_property_set(model, "path", info->name); @@ -1934,13 +1957,14 @@ _from_legacy_event_call(Elm_Fileselector *fs, Elm_Fileselector_Data *sd, const E else model_cls = efl_class_get(sd->model); - Efl_Model *model = efl_add(model_cls, fs); + Efl_Model *model = efl_add_ref(model_cls, fs, + efl_event_callback_array_add(efl_added, noref_death(), NULL)); _model_str_property_set(model, "path", path); // Call Eo event with model efl_event_callback_call(fs, evt_desc, model); - efl_del(model); + efl_unref(model); // Call legacy smart callback with path return efl_event_callback_call(fs, legacy_desc, (void *)path); @@ -2143,13 +2167,15 @@ elm_fileselector_path_set(Evas_Object *obj, void _elm_fileselector_path_set_internal(Evas_Object *obj, const char *_path) { - Eio_Model *model = efl_add(EIO_MODEL_CLASS, obj, eio_model_path_set(efl_added, _path)); + Eio_Model *model = efl_add_ref(EIO_MODEL_CLASS, obj, eio_model_path_set(efl_added, _path), + efl_event_callback_array_add(efl_added, noref_death(), NULL)); if (!model) { ERR("Efl.Model allocation error"); return; } efl_ui_view_model_set(obj, model); + efl_unref(model); } EOLIAN static void @@ -2423,7 +2449,8 @@ _properties_ready(void *data, const Efl_Event *ev) const char *path = eio_model_path_get(pd->target); char *dir = ecore_file_dir_get(path); - parent = efl_add(EIO_MODEL_CLASS, obj, eio_model_path_set(efl_added, dir)); + parent = efl_add_ref(EIO_MODEL_CLASS, obj, eio_model_path_set(efl_added, dir), + efl_event_callback_array_add(efl_added, noref_death(), NULL)); if (!parent) { ERR("Could not create model for '%s'.", dir); @@ -2434,6 +2461,7 @@ _properties_ready(void *data, const Efl_Event *ev) efl_model_children_count_get(parent); _schedule_populate(obj, pd, parent, pd->target); + efl_unref(parent); free(dir); } else @@ -2458,7 +2486,8 @@ _elm_fileselector_selected_set_internal(Evas_Object *obj, const char *path) if (stat(path, &st)) return EINA_FALSE; - pd->target = efl_add(EIO_MODEL_CLASS, obj, eio_model_path_set(efl_added, path)); + pd->target = efl_add_ref(EIO_MODEL_CLASS, obj, eio_model_path_set(efl_added, path), + efl_event_callback_array_add(efl_added, noref_death(), NULL)); if (!pd->target) { ERR("Could not create model for '%s'.", path); @@ -2532,7 +2561,8 @@ _elm_fileselector_elm_interface_fileselector_selected_model_set(Eo *obj, Elm_Fil const char *path = eio_model_path_get(pd->target); char *d = ecore_file_dir_get(path); - parent = efl_add(EIO_MODEL_CLASS, obj, eio_model_path_set(efl_added, d)); + parent = efl_add_ref(EIO_MODEL_CLASS, obj, eio_model_path_set(efl_added, d), + efl_event_callback_array_add(efl_added, noref_death(), NULL)); if (!parent) { ERR("Could not create model for '%s'.", d); @@ -2542,6 +2572,7 @@ _elm_fileselector_elm_interface_fileselector_selected_model_set(Eo *obj, Elm_Fil efl_model_children_count_get(parent); _schedule_populate(obj, pd, parent, pd->target); + efl_unref(parent); free(d); } else --
