summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Hacohen <tom@stosb.com>2014-10-20 17:10:02 +0100
committerTom Hacohen <tom@stosb.com>2014-10-20 17:24:07 +0100
commit49179a03878256b1f09ea0622d404de73d792b1c (patch)
tree8b5b713f8770580e153b75440d4782e509e961c7
parent1adff0ae3cd43bf7ffedf5c923ffad0726e2d994 (diff)
Elm cnp: Fix infinite loop on drop target deletions in some cases.
In some cases, like having a drop target inside an inwin (looks like it can be other containers too) can cause an infinite loop (as described in the report). The reason for that is that while the drop target was added when there was an X window available, the X window ws now gone, so the non X path was being called which didn't have the code to remove the item from the list being iterated. Yes, definition of spaghetti and false assumptions. Elm dnd/cnp need a massive overhaul, they are disgusting. See the ticket for more information on the issue. Fixes T1702
-rw-r--r--src/lib/elm_cnp.c116
1 files changed, 58 insertions, 58 deletions
diff --git a/src/lib/elm_cnp.c b/src/lib/elm_cnp.c
index 6aadc71c9..0e98d8ee1 100644
--- a/src/lib/elm_cnp.c
+++ b/src/lib/elm_cnp.c
@@ -184,6 +184,11 @@ static void _all_drop_targets_cbs_del(void *data, Evas *e, Evas_Object *obj, voi
184#ifdef HAVE_ELEMENTARY_X 184#ifdef HAVE_ELEMENTARY_X
185static Ecore_X_Window _x11_elm_widget_xwin_get(const Evas_Object *obj); 185static Ecore_X_Window _x11_elm_widget_xwin_get(const Evas_Object *obj);
186#endif 186#endif
187static Eina_Bool _local_elm_drop_target_del(Evas_Object *obj, Elm_Sel_Format format,
188 Elm_Drag_State entercb, void *enterdata,
189 Elm_Drag_State leavecb, void *leavedata,
190 Elm_Drag_Pos poscb, void *posdata,
191 Elm_Drop_Cb dropcb, void *dropdata);
187 192
188static Eina_Bool 193static Eina_Bool
189_drag_cancel_animate(void *data EINA_UNUSED, double pos) 194_drag_cancel_animate(void *data EINA_UNUSED, double pos)
@@ -2096,35 +2101,11 @@ _x11_elm_drop_target_del(Evas_Object *obj, Elm_Sel_Format format,
2096 2101
2097 _x11_elm_cnp_init(); 2102 _x11_elm_cnp_init();
2098 2103
2099 eo_do(obj, dropable = eo_key_data_get("__elm_dropable")); 2104 if (!_local_elm_drop_target_del(obj, format, entercb, enterdata,
2100 if (dropable) 2105 leavecb, leavedata, poscb, posdata, dropcb, dropdata))
2101 { 2106 {
2102 Eina_Inlist *itr; 2107 return EINA_FALSE;
2103 Dropable_Cbs *cbs_info;
2104 /* Look for the callback in the list */
2105 EINA_INLIST_FOREACH_SAFE(dropable->cbs_list, itr, cbs_info)
2106 if (cbs_info->entercb == entercb && cbs_info->enterdata == enterdata &&
2107 cbs_info->leavecb == leavecb && cbs_info->leavedata == leavedata &&
2108 cbs_info->poscb == poscb && cbs_info->posdata == posdata &&
2109 cbs_info->dropcb == dropcb && cbs_info->dropdata == dropdata &&
2110 cbs_info->types == format)
2111 {
2112 dropable->cbs_list = eina_inlist_remove(dropable->cbs_list,
2113 EINA_INLIST_GET(cbs_info));
2114 free(cbs_info);
2115 }
2116 /* In case no more callbacks are listed for the object */
2117 if (!dropable->cbs_list)
2118 {
2119 drops = eina_list_remove(drops, dropable);
2120 eo_do(obj, eo_key_data_del("__elm_dropable"));
2121 free(dropable);
2122 dropable = NULL;
2123 evas_object_event_callback_del(obj, EVAS_CALLBACK_DEL,
2124 _all_drop_targets_cbs_del);
2125 }
2126 } 2108 }
2127 else return EINA_FALSE;
2128 2109
2129 /* TODO BUG: we should handle dnd-aware per window, not just the last that released it */ 2110 /* TODO BUG: we should handle dnd-aware per window, not just the last that released it */
2130 2111
@@ -2843,36 +2824,12 @@ _wl_elm_drop_target_del(Evas_Object *obj, Elm_Sel_Format format,
2843 Elm_Drag_Pos poscb, void *posdata, 2824 Elm_Drag_Pos poscb, void *posdata,
2844 Elm_Drop_Cb dropcb, void *dropdata) 2825 Elm_Drop_Cb dropcb, void *dropdata)
2845{ 2826{
2846 Dropable *dropable = NULL;
2847 2827
2848 eo_do(obj, dropable = eo_key_data_get("__elm_dropable")); 2828 if (!_local_elm_drop_target_del(obj, format, entercb, enterdata,
2849 if (dropable) 2829 leavecb, leavedata, poscb, posdata, dropcb, dropdata))
2850 { 2830 {
2851 Eina_Inlist *itr; 2831 return EINA_FALSE;
2852 Dropable_Cbs *cbs_info;
2853 /* Look for the callback in the list */
2854 EINA_INLIST_FOREACH_SAFE(dropable->cbs_list, itr, cbs_info)
2855 if (cbs_info->entercb == entercb && cbs_info->enterdata == enterdata &&
2856 cbs_info->leavecb == leavecb && cbs_info->leavedata == leavedata &&
2857 cbs_info->poscb == poscb && cbs_info->posdata == posdata &&
2858 cbs_info->dropcb == dropcb && cbs_info->dropdata == dropdata &&
2859 cbs_info->types == format)
2860 {
2861 dropable->cbs_list = eina_inlist_remove(dropable->cbs_list,
2862 EINA_INLIST_GET(cbs_info));
2863 free(cbs_info);
2864 }
2865 /* In case no more callbacks are listed for the object */
2866 if (!dropable->cbs_list)
2867 {
2868 drops = eina_list_remove(drops, dropable);
2869 eo_do(obj, eo_key_data_del("__elm_dropable"));
2870 ELM_SAFE_FREE(dropable, free);
2871 evas_object_event_callback_del(obj, EVAS_CALLBACK_DEL,
2872 _all_drop_targets_cbs_del);
2873 }
2874 } 2832 }
2875 else return EINA_FALSE;
2876 2833
2877 if (!drops) 2834 if (!drops)
2878 { 2835 {
@@ -3538,7 +3495,6 @@ static Eina_Bool _local_elm_drop_target_add(Evas_Object *obj EINA_UNUSED, Elm_S
3538 Elm_Drag_State leavecb EINA_UNUSED, void *leavedata EINA_UNUSED, 3495 Elm_Drag_State leavecb EINA_UNUSED, void *leavedata EINA_UNUSED,
3539 Elm_Drag_Pos poscb EINA_UNUSED, void *posdata EINA_UNUSED, 3496 Elm_Drag_Pos poscb EINA_UNUSED, void *posdata EINA_UNUSED,
3540 Elm_Drop_Cb dropcb EINA_UNUSED, void *dropdata EINA_UNUSED); 3497 Elm_Drop_Cb dropcb EINA_UNUSED, void *dropdata EINA_UNUSED);
3541static Eina_Bool _local_elm_drop_target_del(Evas_Object *obj EINA_UNUSED);
3542static Eina_Bool _local_elm_drag_start(Evas_Object *obj EINA_UNUSED, 3498static Eina_Bool _local_elm_drag_start(Evas_Object *obj EINA_UNUSED,
3543 Elm_Sel_Format format EINA_UNUSED, 3499 Elm_Sel_Format format EINA_UNUSED,
3544 const char *data EINA_UNUSED, 3500 const char *data EINA_UNUSED,
@@ -3657,10 +3613,46 @@ _local_elm_drop_target_add(Evas_Object *obj EINA_UNUSED,
3657} 3613}
3658 3614
3659static Eina_Bool 3615static Eina_Bool
3660_local_elm_drop_target_del(Evas_Object *obj EINA_UNUSED) 3616_local_elm_drop_target_del(Evas_Object *obj, Elm_Sel_Format format,
3617 Elm_Drag_State entercb, void *enterdata,
3618 Elm_Drag_State leavecb, void *leavedata,
3619 Elm_Drag_Pos poscb, void *posdata,
3620 Elm_Drop_Cb dropcb, void *dropdata)
3661{ 3621{
3662 // XXX: implement me 3622 Dropable *dropable = NULL;
3623
3663 _local_elm_cnp_init(); 3624 _local_elm_cnp_init();
3625
3626 eo_do(obj, dropable = eo_key_data_get("__elm_dropable"));
3627 if (dropable)
3628 {
3629 Eina_Inlist *itr;
3630 Dropable_Cbs *cbs_info;
3631 /* Look for the callback in the list */
3632 EINA_INLIST_FOREACH_SAFE(dropable->cbs_list, itr, cbs_info)
3633 if (cbs_info->entercb == entercb && cbs_info->enterdata == enterdata &&
3634 cbs_info->leavecb == leavecb && cbs_info->leavedata == leavedata &&
3635 cbs_info->poscb == poscb && cbs_info->posdata == posdata &&
3636 cbs_info->dropcb == dropcb && cbs_info->dropdata == dropdata &&
3637 cbs_info->types == format)
3638 {
3639 dropable->cbs_list = eina_inlist_remove(dropable->cbs_list,
3640 EINA_INLIST_GET(cbs_info));
3641 free(cbs_info);
3642 }
3643 /* In case no more callbacks are listed for the object */
3644 if (!dropable->cbs_list)
3645 {
3646 drops = eina_list_remove(drops, dropable);
3647 eo_do(obj, eo_key_data_del("__elm_dropable"));
3648 free(dropable);
3649 dropable = NULL;
3650 evas_object_event_callback_del(obj, EVAS_CALLBACK_DEL,
3651 _all_drop_targets_cbs_del);
3652 }
3653 return EINA_TRUE;
3654 }
3655
3664 return EINA_FALSE; 3656 return EINA_FALSE;
3665} 3657}
3666 3658
@@ -3944,7 +3936,15 @@ elm_drop_target_del(Evas_Object *obj, Elm_Sel_Format format,
3944 return _wl_elm_drop_target_del(obj, format, entercb, enterdata, 3936 return _wl_elm_drop_target_del(obj, format, entercb, enterdata,
3945 leavecb, leavedata, poscb, posdata, dropcb, dropdata); 3937 leavecb, leavedata, poscb, posdata, dropcb, dropdata);
3946#endif 3938#endif
3947 return _local_elm_drop_target_del(obj); 3939 /* FIXME: Not the best place for an error message, but meh.
3940 * This code path is actually valid if running in framebuffer, but it still shouldn't
3941 * be getting here because the drop target shouldn't be added. This is an error
3942 * and it's because of some stupid handling in both the X11 and the wayland backends
3943 * as seen in the commit that introduced this comment.
3944 * Window check is probably not the best idea, you should be doing engine check instead. */
3945 ERR("Please contact developers, you should probably not get here.");
3946 return _local_elm_drop_target_del(obj, format, entercb, enterdata,
3947 leavecb, leavedata, poscb, posdata, dropcb, dropdata);
3948} 3948}
3949 3949
3950EAPI Eina_Bool 3950EAPI Eina_Bool