yakov pushed a commit to branch master. http://git.enlightenment.org/tools/erigo.git/commit/?id=36759bb7f1012aaa5afea7db2aea2ad1b6476e68
commit 36759bb7f1012aaa5afea7db2aea2ad1b6476e68 Author: Yakov Goldberg <yako...@samsung.com> Date: Tue Dec 1 19:05:13 2015 +0200 Fixing segv when dragging between factory and window The bug was: segv in _obj_remove_from_session() because widget did not exist. It happened because: in _drop_target_leave() we were deleting eo_cur and deleting _dragged_wdg right after that. Because of delay in callback call, widget was already deleted in _obj_remove_from_session(), which is called by eo_del(eo_cur). I added _factory_dragdone_post_cb(), which deletes _dragged_wdg if it was not accepted or accepted outside Erigo. Virtually crash still can happen if _drop_target_leave() will be called and _dragdone will happen right after this. But practically this is almost impossible. --- src/bin/gui/dnd.c | 10 ++++++---- src/bin/gui/dnd.h | 3 +-- src/bin/gui/editor.c | 27 ++++++++++++++++----------- src/bin/gui/egui_logic.c | 4 ++-- src/bin/gui/egui_logic_private.h | 1 + 5 files changed, 26 insertions(+), 19 deletions(-) diff --git a/src/bin/gui/dnd.c b/src/bin/gui/dnd.c index 078716b..1eb9dc6 100644 --- a/src/bin/gui/dnd.c +++ b/src/bin/gui/dnd.c @@ -31,9 +31,10 @@ typedef struct Eid *wdg_id; /*Widget id*/ char *image_path; /* image for DnD icon. */ Eo *obj; /*object, where drag starts. Used to call cb on delete. */ + void (*_factory_dragdone_post_cb)(Eina_Bool accept, const Eo *wdg_eo, const Gui_Widget * drag_start_wdg); } Factory_Drag_Info; -Factory_Drag_Info _wdg_drag = {NULL, NULL, NULL}; +Factory_Drag_Info _wdg_drag = {NULL, NULL, NULL, NULL}; /* Information about Drop Target*/ typedef struct @@ -177,8 +178,7 @@ static void _dragdone(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED) { dnd_debug("In"); - - if (_drag_info_global.canvas_is_source) + if (_drag_info_global._wdg_dragdone_post_cb) { _drag_info_global._wdg_dragdone_post_cb(_drag_info_global.drag_accept, _drag_info_global.obj, _drag_info_global.drag_start_wdg); } @@ -488,6 +488,7 @@ _drag_start_from_factory(void *data) char *wdg_data = json_widget_generate(fdi->wdg_id); dnd_debug("Data %s", wdg_data); _drag_info_global._drag_data = wdg_data; + _drag_info_global._wdg_dragdone_post_cb = fdi->_factory_dragdone_post_cb; elm_drag_start(fdi->obj, ELM_SEL_FORMAT_TEXT, wdg_data, ELM_XDND_ACTION_COPY, image_create_icon_f, fdi, @@ -534,13 +535,14 @@ _factory_drag_info_free(void *data, Eo *obj EINA_UNUSED, const Eo_Event_Descript /* Function to make Eo object draggable, when mouse down/up are handled inside. * Dragging from factory. */ void -drag_add(Eo *obj, const char *image_path, Eid *wdg_id) +drag_add(Eo *obj, const char *image_path, Eid *wdg_id, void (*_factory_dragdone_post_cb)(Eina_Bool accept, const Eo *wdg_eo, const Gui_Widget * drag_start_wdg)) { Factory_Drag_Info *fdi = calloc(1, sizeof(Factory_Drag_Info)); if (image_path) fdi->image_path = strdup(image_path); fdi->wdg_id = wdg_id; fdi->obj = obj; + fdi->_factory_dragdone_post_cb = _factory_dragdone_post_cb; eo_do(obj, eo_event_callback_add(EVAS_OBJECT_EVENT_MOUSE_DOWN, _factory_drag_mouse_down, fdi)); eo_do(obj, eo_event_callback_add(EVAS_OBJECT_EVENT_DEL, _factory_drag_info_free, fdi)); } diff --git a/src/bin/gui/dnd.h b/src/bin/gui/dnd.h index 884bb3e..63e4518 100644 --- a/src/bin/gui/dnd.h +++ b/src/bin/gui/dnd.h @@ -2,8 +2,7 @@ #define _DND_H void -drag_add(Eo *obj, const char *image_path, Eid *wdg_id); - +drag_add(Eo *obj, const char *image_path, Eid *wdg_id, void (*_factory_dragdone_post_cb)(Eina_Bool accept, const Eo *wdg_eo, const Gui_Widget * drag_start_wdg)); void drag_start(Eo *obj, Eid *wdg_id, void (*_dragdone_post_cb)(Eina_Bool accept, const Eo *wdg_eo, const Gui_Widget *drag_start_wdg)); diff --git a/src/bin/gui/editor.c b/src/bin/gui/editor.c index 84e6af8..f32e3fb 100644 --- a/src/bin/gui/editor.c +++ b/src/bin/gui/editor.c @@ -1632,17 +1632,6 @@ _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, @@ -2794,6 +2783,21 @@ _drag_start_post(const Gui_Widget *wdg, const Eo *_wdg_eo) wdg_parent_set((Gui_Widget *) wdg, NULL); } +/* This callback is added for dragging object from factory. */ +static void +_factory_dragdone_post_cb(Eina_Bool accept, const Eo *wdg_eo EINA_UNUSED, const Gui_Widget *drag_start_wdg EINA_UNUSED) +{ + if (!accept || + (accept && !dnd_is_destination())) + { + if (_dragged_wdg) + { + wdg_del(_dragged_wdg); + _dragged_wdg = NULL; + } + } +} + /* This callback is added only for dragging of objects on canvas. */ static void _dragdone_post_cb(Eina_Bool accept, const Eo *wdg_eo, const Gui_Widget *drag_start_wdg) @@ -4863,6 +4867,7 @@ editor_init(GuiLogicCbs *_guilogic_cbs) _guilogic_cbs->_project_close = _project_close; _guilogic_cbs->_project_new = _project_new; _guilogic_cbs->_theme_hoversel_fill = _theme_hoversel_fill; + _guilogic_cbs->_factory_dragdone_post_cb = _factory_dragdone_post_cb; updater_completion_callback_add(_context_changed_cb, NULL); diff --git a/src/bin/gui/egui_logic.c b/src/bin/gui/egui_logic.c index 78bcfcf..b89401c 100644 --- a/src/bin/gui/egui_logic.c +++ b/src/bin/gui/egui_logic.c @@ -1066,7 +1066,7 @@ egui_start(const char *filename) eo_event_callback_add(EVAS_OBJECT_EVENT_MOUSE_DOWN, _factory_tt_mouse_down, NULL)); \ elm_object_tooltip_text_set(box, #widget); \ eo_do(eo_parent, elm_obj_table_pack(box, x, y, w, h)); \ - drag_add(box, NULL, obj_id); \ + drag_add(box, NULL, obj_id, _guilogic_cbs->_factory_dragdone_post_cb); \ _factory_widgets_list = eina_list_append(_factory_widgets_list, box); \ } #define FACTORY_IMG_CREATE(widget, image_path, parent, x, y, w, h) \ @@ -1082,7 +1082,7 @@ egui_start(const char *filename) eo_do(o, eo_event_callback_add(EVAS_OBJECT_EVENT_MOUSE_DOWN, _factory_tt_mouse_down, NULL)); \ eo_do(eo_parent, elm_obj_table_pack(o, x, y, w, h)); \ wdg_id = gui_context_eid_get_by_name(global_context_get(), #widget); \ - drag_add(o, path, wdg_id); \ + drag_add(o, path, wdg_id, _guilogic_cbs->_factory_dragdone_post_cb); \ } gui_parser_json_file_read((Gui_Context *)global_context_get(), PACKAGE_DATA_DIR"/layouts/factory.json"); diff --git a/src/bin/gui/egui_logic_private.h b/src/bin/gui/egui_logic_private.h index 84a0e77..2c856c9 100644 --- a/src/bin/gui/egui_logic_private.h +++ b/src/bin/gui/egui_logic_private.h @@ -16,6 +16,7 @@ typedef struct void (*_project_close)(const Gui_Context *ctx); Gui_Context* (*_project_new)(const char *filename); void (*_theme_hoversel_fill)(); + void (*_factory_dragdone_post_cb)(Eina_Bool accept, const Eo *wdg_eo, const Gui_Widget * drag_start_wdg); } GuiLogicCbs; Eina_Bool --