yakov pushed a commit to branch master. http://git.enlightenment.org/tools/erigo.git/commit/?id=7eaa75641d59abf9b0e934a792e288f94fbc4881
commit 7eaa75641d59abf9b0e934a792e288f94fbc4881 Author: Yakov Goldberg <yako...@samsung.com> Date: Thu Dec 3 10:16:12 2015 +0200 Fixing segv when dragging between factory and window Add reference counting for enter/leave on Editor's level to properly delete Eo and Gui_Widget instances in DnD. --- src/bin/gui/dnd.c | 45 +++++++++++++++++++++------------------------ src/bin/gui/editor.c | 16 +++++++++++++++- 2 files changed, 36 insertions(+), 25 deletions(-) diff --git a/src/bin/gui/dnd.c b/src/bin/gui/dnd.c index f6a169b..57590db 100644 --- a/src/bin/gui/dnd.c +++ b/src/bin/gui/dnd.c @@ -220,21 +220,23 @@ _dropleave(void *data, Evas_Object *obj) { Drop_Target_Info *main_wdg_ti = data; - /* if ti->drop_target is not current main widget, then it means, - * that prev drop target, box for example wasn't leaved properly. - * For example moving mouse fast from one window to another will cause "jump". - * So need to call leave properly. - * */ - if (main_wdg_ti->drop_target != main_wdg_ti->wdg) + /* Main object can be leaved straight from internal container. + * T.e. not from window, but from the box + * In this case callback for this cantainer will be called. + * + * Else callback for main wdg will be called. */ + if (main_wdg_ti->drop_target) { Drop_Target_Info *ti = wdg_data_get(main_wdg_ti->drop_target, DROP_TARGET); if (ti->drop_target_leave) ti->drop_target_leave(ti->leavedata, obj); + main_wdg_ti->drop_target = NULL; + } + else + { + if (main_wdg_ti->drop_target_leave) + main_wdg_ti->drop_target_leave(main_wdg_ti->leavedata, obj); } - main_wdg_ti->drop_target = NULL; - - if (main_wdg_ti->drop_target_leave) - main_wdg_ti->drop_target_leave(main_wdg_ti->leavedata, obj); } if (!_drop_info_global._enter_leave_counter) @@ -355,34 +357,29 @@ _droppos(void *data, Eo *obj, Evas_Coord x, Evas_Coord y, Elm_Xdnd_Action action Gui_Session *session = (Gui_Session *) gui_context_editor_session_get(ctx); _drop_target_iterate(&drop_candidate, session, x / scale, y / scale); + dnd_debug("--->Drop Candidate: %s; Coords within: %d %d", wdg_name_get(drop_candidate), x, y); if (main_wdg_ti->drop_target != drop_candidate) { - /* Call leave callback for previous target widget. - * If prev wdg is MainWdg, don't call leave. */ - //if (main_wdg_ti->drop_target != wdg) + /* Call enter callback for new target widget. */ { - Drop_Target_Info *ti = wdg_data_get(main_wdg_ti->drop_target, DROP_TARGET); - if (ti->drop_target_leave) + Drop_Target_Info *ti = wdg_data_get(drop_candidate, DROP_TARGET); + if (ti->drop_target_enter) { - ti->drop_target_leave(ti->leavedata, NULL); + ti->drop_target_enter(ti->enterdata, NULL); } } - /* Call enter callback for new target widget. - * If new wdg is MainWdg, don't call enter. */ - //if (drop_candidate != wdg) + /* Call leave callback for previous target widget. */ { - Drop_Target_Info *ti = wdg_data_get(drop_candidate, DROP_TARGET); - if (ti->drop_target_enter) + Drop_Target_Info *ti = wdg_data_get(main_wdg_ti->drop_target, DROP_TARGET); + if (ti->drop_target_leave) { - ti->drop_target_enter(ti->enterdata, NULL); + ti->drop_target_leave(ti->leavedata, NULL); } } main_wdg_ti->drop_target = drop_candidate; } - dnd_debug("--->Drop Candidate: %s; Coords within: %d %d", wdg_name_get(drop_candidate), x, y); - /* Simulate poscb inside drop candidate. * Get callbacks from drop candidate and call. */ Drop_Target_Info *ti = wdg_data_get(drop_candidate, DROP_TARGET); diff --git a/src/bin/gui/editor.c b/src/bin/gui/editor.c index 68bf2ac..a5eb8f9 100644 --- a/src/bin/gui/editor.c +++ b/src/bin/gui/editor.c @@ -41,6 +41,7 @@ typedef struct { Eo *eo_cur; + int eo_ref_count; Eina_Bool packed; /* Need this, because no API to check if object is packed into table and unpack causes error message. */ /* Box packing data. */ @@ -1506,6 +1507,7 @@ _drop_target_enter(void *data, Evas_Object *obj) di = wdg_data_get(main_wdg, EDITOR_DND_DATA); } _wdg_border_draw(drop_target_wdg, EINA_TRUE, BORDER_DROP_TARGET); + di->eo_ref_count++; } else if (canvas_drop_target != NULL) { @@ -1561,6 +1563,7 @@ _drop_target_leave(void *data, Evas_Object *obj) else di = wdg_data_get(wdg_main_wdg_get(drop_target_wdg), EDITOR_DND_DATA); drop_target_wdg_eo = session_eo_get(session, drop_target_wdg); + di->eo_ref_count--; } else if (canvas_drop_target != NULL) { @@ -1623,7 +1626,7 @@ _drop_target_leave(void *data, Evas_Object *obj) di->drop_instead_item_obj = NULL; } - if (di->eo_cur && IS_MAIN(drop_target_wdg) && (di->eo_cur != session_eo_get(session, dnd_drag_wdg_get()))) + if (drop_target_wdg && !di->eo_ref_count && di->eo_cur && (di->eo_cur != session_eo_get(session, dnd_drag_wdg_get()))) { eo_del(di->eo_cur); di->eo_cur = NULL; @@ -1632,6 +1635,17 @@ _drop_target_leave(void *data, Evas_Object *obj) { if (di->eo_cur) eo_do(di->eo_cur, efl_gfx_visible_set(EINA_FALSE)); } + + if (!dnd_counter_get()) + { + /* If drag was started in factory or outside Erigo - delete widget */ + if (!dnd_is_source() && _dragged_wdg) + { + wdg_del(_dragged_wdg); + } + /* ... if started on canvas - NULL pointer */ + _dragged_wdg = NULL; + } } /* In the beginning of drop handler we want to determine, --