diff --git a/legacy/elementary/src/bin/test.c b/legacy/elementary/src/bin/test.c index 88a22ec2c6..e6c3707688 100644 --- a/legacy/elementary/src/bin/test.c +++ b/legacy/elementary/src/bin/test.c @@ -228,6 +228,7 @@ void test_web_mobile(void *data, Evas_Object *obj, void *event_info); void test_dnd_genlist_default_anim(void *data, Evas_Object *obj, void *event_info); void test_dnd_genlist_user_anim(void *data, Evas_Object *obj, void *event_info); void test_dnd_genlist_gengrid(void *data, Evas_Object *obj, void *event_info); +void test_dnd_overlapping(void *data, Evas_Object *obj, void *event_info); void test_task_switcher(void *data, Evas_Object *obj, void *event_info); void test_application_server_message(void *data, Evas_Object *obj, void *event_info); void test_application_server_phone(void *data, Evas_Object *obj, void *event_info); @@ -791,6 +792,7 @@ add_tests: ADD_TEST(NULL, "Drag & Drop", "Genlist DnD Dflt Anim", test_dnd_genlist_default_anim); ADD_TEST(NULL, "Drag & Drop", "Genlist DnD User Anim", test_dnd_genlist_user_anim); ADD_TEST(NULL, "Drag & Drop", "Genlist-Gengrid DnD", test_dnd_genlist_gengrid); + ADD_TEST(NULL, "Drag & Drop", "Overlapping DnD", test_dnd_overlapping); //------------------------------// ADD_TEST(NULL, "Miscellaneous", "Copy And Paste", test_cnp); diff --git a/legacy/elementary/src/bin/test_dnd.c b/legacy/elementary/src/bin/test_dnd.c index c17d8de401..443970dddc 100644 --- a/legacy/elementary/src/bin/test_dnd.c +++ b/legacy/elementary/src/bin/test_dnd.c @@ -89,7 +89,7 @@ _gl_item_getcb(Evas_Object *obj, Evas_Coord x, Evas_Coord y, int *xposret EINA_U gli = elm_genlist_at_xy_item_get(obj, x, y, yposret); if (gli) printf("over <%s>, gli=<%p> yposret %i\n", - elm_object_item_part_text_get(gli, "elm.text"), gli, *yposret); + (char *)elm_object_item_data_get(gli), gli, *yposret); else printf("over none, yposret %i\n", *yposret); return gli; @@ -103,7 +103,7 @@ _grid_item_getcb(Evas_Object *obj, Evas_Coord x, Evas_Coord y, int *xposret, int item = elm_gengrid_at_xy_item_get(obj, x, y, xposret, yposret); if (item) printf("over <%s>, item=<%p> xposret %i yposret %i\n", - elm_object_item_part_text_get(item, "elm.text"), item, *xposret, *yposret); + (char *)elm_object_item_data_get(item), item, *xposret, *yposret); else printf("over none, xposret %i yposret %i\n", *xposret, *yposret); return item; @@ -490,7 +490,7 @@ _gl_get_drag_data(Evas_Object *obj, Elm_Object_Item *it, Eina_List **items) EINA_LIST_FOREACH(*items, l, it) { - t = elm_object_item_part_text_get(it, "elm.text"); + t = (char *)elm_object_item_data_get(it); if (t) len += strlen(t); } @@ -500,7 +500,7 @@ _gl_get_drag_data(Evas_Object *obj, Elm_Object_Item *it, Eina_List **items) EINA_LIST_FOREACH(*items, l, it) { - t = elm_object_item_part_text_get(it, "elm.text"); + t = (char *)elm_object_item_data_get(it); if (t) { strcat((char *) drag_data, "#"); @@ -537,7 +537,7 @@ _grid_get_drag_data(Evas_Object *obj, Elm_Object_Item *it, Eina_List **items) EINA_LIST_FOREACH(*items, l, it) { - t = elm_object_item_part_text_get(it, "elm.text"); + t = (char *)elm_object_item_data_get(it); if (t) len += strlen(t); } @@ -547,7 +547,7 @@ _grid_get_drag_data(Evas_Object *obj, Elm_Object_Item *it, Eina_List **items) EINA_LIST_FOREACH(*items, l, it) { - t = elm_object_item_part_text_get(it, "elm.text"); + t = (char *)elm_object_item_data_get(it); if (t) { strcat((char *) drag_data, "#"); @@ -892,3 +892,144 @@ test_dnd_genlist_gengrid(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, v evas_object_show(win); } +static Eina_Bool _drop_box_button_new_cb(void *data, Evas_Object *obj, Elm_Selection_Data *ev) +{ + Evas_Object *win = data; + char *p = strchr(ev->data, '#'); + while(p) + { + p++; + char *p2 = strchr(p, '#'); + if (p2) + { + *p2 = '\0'; + Evas_Object *ic = elm_icon_add(win); + elm_image_file_set(ic, p, NULL); + evas_object_size_hint_aspect_set(ic, EVAS_ASPECT_CONTROL_VERTICAL, 1, 1); + Evas_Object *bt = elm_button_add(win); + elm_object_text_set(bt, "Dropped button"); + elm_object_part_content_set(bt, "icon", ic); + elm_box_pack_end(obj, bt); + evas_object_show(bt); + evas_object_show(ic); + p = p2; + } + else p = NULL; + } + return EINA_TRUE; +} + +static Eina_Bool _drop_but_icon_change_cb(void *data, Evas_Object *obj, Elm_Selection_Data *ev) +{ + Evas_Object *win = data; + Evas_Object *ic = elm_icon_add(win); + char *p = strchr(ev->data, '#'); + p++; + char *p2 = strchr(p, '#'); + *p2 = '\0'; + elm_image_file_set(ic, p, NULL); + evas_object_size_hint_aspect_set(ic, EVAS_ASPECT_CONTROL_VERTICAL, 1, 1); + evas_object_del(elm_object_part_content_get(obj, "icon")); + elm_object_part_content_set(obj, "icon", ic); + evas_object_show(ic); + return EINA_TRUE; +} + +static Eina_Bool _drop_bg_change_cb(void *data EINA_UNUSED, Evas_Object *obj, Elm_Selection_Data *ev) +{ + char *p = strchr(ev->data, '#'); + p++; + char *p2 = strchr(p, '#'); + *p2 = '\0'; + elm_bg_file_set(obj, p, NULL); + return EINA_TRUE; +} + +void +test_dnd_overlapping(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) +{ + char buf[PATH_MAX]; + Evas_Object *win, *bxx, *bg; + int i; + + win = elm_win_util_standard_add("dnd-overlapping", "DnD-Overlapping"); + elm_win_autodel_set(win, EINA_TRUE); + + bg = elm_bg_add(win); + evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + elm_drop_target_add(bg, ELM_SEL_FORMAT_TARGETS, NULL, NULL, NULL, NULL, NULL, NULL, _drop_bg_change_cb, NULL); + elm_win_resize_object_add(win, bg); + + /* And show the background. */ + evas_object_show(bg); + bxx = elm_box_add(win); + elm_box_horizontal_set(bxx, EINA_TRUE); + evas_object_size_hint_weight_set(bxx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + elm_win_resize_object_add(win, bxx); + evas_object_show(bxx); + + { + Evas_Object *grid = elm_gengrid_add(bxx); + evas_object_smart_callback_add(win, "delete,request", _win_del, grid); + elm_gengrid_item_size_set(grid, + elm_config_scale_get() * 100, + elm_config_scale_get() * 100); + elm_gengrid_horizontal_set(grid, EINA_FALSE); + elm_gengrid_reorder_mode_set(grid, EINA_FALSE); + elm_gengrid_multi_select_set(grid, EINA_TRUE); /* We allow multi drag */ + evas_object_size_hint_weight_set(grid, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + evas_object_size_hint_align_set(grid, EVAS_HINT_FILL, EVAS_HINT_FILL); + + gic = elm_gengrid_item_class_new(); + gic->item_style = "default"; + gic->func.text_get = gl_text_get; + gic->func.content_get = gl_content_get; + + elm_drag_item_container_add(grid, ANIM_TIME, DRAG_TIMEOUT, + _grid_item_getcb, _grid_data_getcb); + for (i = 0; i < 10; i++) + { + snprintf(buf, sizeof(buf), "%s/images/%s", elm_app_data_dir_get(), img[(i % 9)]); + const char *path = eina_stringshare_add(buf); + elm_gengrid_item_append(grid, gic, path, NULL, NULL); + } + elm_box_pack_end(bxx, grid); + evas_object_show(grid); + } + + { + Evas_Object *ic, *bt; + Evas_Object *vert_box = elm_box_add(bxx); + evas_object_size_hint_weight_set(vert_box, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + elm_box_pack_end(bxx, vert_box); + evas_object_show(vert_box); + elm_drop_target_add(vert_box, ELM_SEL_FORMAT_TARGETS, NULL, NULL, NULL, NULL, NULL, NULL, _drop_box_button_new_cb, win); + + ic = elm_icon_add(win); + snprintf(buf, sizeof(buf), "%s/images/logo_small.png", elm_app_data_dir_get()); + elm_image_file_set(ic, buf, NULL); + evas_object_size_hint_aspect_set(ic, EVAS_ASPECT_CONTROL_VERTICAL, 1, 1); + bt = elm_button_add(win); + elm_object_text_set(bt, "Drop into me to change my icon"); + elm_drop_target_add(bt, ELM_SEL_FORMAT_TARGETS, NULL, NULL, NULL, NULL, NULL, NULL, _drop_but_icon_change_cb, win); + elm_object_part_content_set(bt, "icon", ic); + elm_box_pack_end(vert_box, bt); + evas_object_show(bt); + evas_object_show(ic); + + ic = elm_icon_add(win); + snprintf(buf, sizeof(buf), "%s/images/logo_small.png", elm_app_data_dir_get()); + elm_image_file_set(ic, buf, NULL); + evas_object_size_hint_aspect_set(ic, EVAS_ASPECT_CONTROL_VERTICAL, 1, 1); + bt = elm_button_add(win); + elm_object_text_set(bt, "No action on drop"); + elm_object_part_content_set(bt, "icon", ic); + elm_object_disabled_set(bt, EINA_TRUE); + elm_box_pack_end(vert_box, bt); + evas_object_show(bt); + evas_object_show(ic); + } + evas_object_resize(win, 680, 800); + evas_object_show(win); +} + diff --git a/legacy/elementary/src/lib/elm_cnp.c b/legacy/elementary/src/lib/elm_cnp.c index 5d02dcce0b..ee6497e6ee 100644 --- a/legacy/elementary/src/lib/elm_cnp.c +++ b/legacy/elementary/src/lib/elm_cnp.c @@ -7,9 +7,9 @@ # include #endif -//#define DEBUGON 1 +#define DEBUGON 1 #ifdef DEBUGON -# define cnp_debug(x...) fprintf(stderr, __FILE__": " x) +# define cnp_debug(fmt, args...) fprintf(stderr, __FILE__":%s : " fmt , __FUNCTION__, ##args) #else # define cnp_debug(x...) do { } while (0) #endif @@ -1136,21 +1136,52 @@ _x11_dropable_find(Ecore_X_Window win) static Dropable * _x11_dropable_geom_find(Ecore_X_Window win, Evas_Coord px, Evas_Coord py) { - Eina_List *l; - Dropable *dropable; - Evas_Coord x, y, w, h; + Eina_List *itr, *top_objects_list = NULL; + Evas *evas = NULL; + Evas_Object *top_obj; + Dropable *dropable = NULL; if (!drops) return NULL; - EINA_LIST_FOREACH(drops, l, dropable) + /* Find the Evas connected to the window */ + EINA_LIST_FOREACH(drops, itr, dropable) { if (_x11_elm_widget_xwin_get(dropable->obj) == win) { - evas_object_geometry_get(dropable->obj, &x, &y, &w, &h); - if ((px >= x) && (py >= y) && (px < (x + w)) && (py < (y + h))) - return dropable; + evas = evas_object_evas_get(dropable->obj); + break; } } - return NULL; + if (!evas) return NULL; + + /* We retrieve the (non-smart) objects pointed by (px, py) */ + top_objects_list = evas_tree_objects_at_xy_get(evas, NULL, px, py); + /* We walk on this list from the last because if the list contains more than one + * element, all but the last will repeat events. The last one can repeat events + * or not. Anyway, this last one is the first that has to be taken into account + * for the determination of the drop target. + */ + EINA_LIST_REVERSE_FOREACH(top_objects_list, itr, top_obj) + { + Evas_Object *object = top_obj; + /* We search for the dropable data into the object. If not found, we search into its parent. + * For example, if a button is a drop target, the first object will be an (internal) image. + * The drop target is attached to the button, i.e to image's parent. That's why we need to + * walk on the parents until NULL. + * If we find this dropable data, we found our drop target. + */ + while (object) + { + eo_do(object, eo_base_data_get("__elm_dropable", (void **)&dropable)); + if (dropable) + goto end; + else + object = evas_object_smart_parent_get(object); + } + } +end: + eina_list_free(top_objects_list); + if (dropable) cnp_debug("Drop target %p of type %s found\n", dropable->obj, eo_class_name_get(eo_class_get(dropable->obj))); + return dropable; } static void @@ -1352,7 +1383,7 @@ _x11_dnd_position(void *data __UNUSED__, int etype __UNUSED__, void *ev) else { ecore_x_dnd_send_status(EINA_FALSE, EINA_FALSE, rect, pos->action); - cnp_debug("dnd position not in obj\n"); + cnp_debug("dnd position (%d, %d) not in obj\n", x, y); _x11_dnd_dropable_handle(dropable_old, 0, 0, EINA_FALSE, act); // CCCCCCC: call dnd exit on last obj @@ -1459,7 +1490,7 @@ found: snprintf(entrytag, len + 1, tagstring, savedtypes.imgfile); ddata.data = entrytag; cnp_debug("Insert %s\n", (char *)ddata.data); - dropable->dropcb(dropable->cbdata, dropable->obj, &ddata); + if (dropable->dropcb) dropable->dropcb(dropable->cbdata, dropable->obj, &ddata); ecore_x_dnd_send_finished(); if (savedtypes.imgfile) free(savedtypes.imgfile); savedtypes.imgfile = NULL; @@ -1810,6 +1841,7 @@ _x11_elm_drop_target_add(Evas_Object *obj, Elm_Sel_Format format, /* Create new drop */ drop = calloc(1, sizeof(Dropable)); if (!drop) return EINA_FALSE; + /* FIXME: Check for eina's deranged error method */ drops = eina_list_append(drops, drop); @@ -1829,6 +1861,7 @@ _x11_elm_drop_target_add(Evas_Object *obj, Elm_Sel_Format format, drop->types = format; drop->obj = obj; + eo_do(obj, eo_base_data_set("__elm_dropable", drop, NULL)); evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL, /* I love C and varargs */ (Evas_Object_Event_Cb)elm_drop_target_del, @@ -1856,28 +1889,25 @@ _x11_elm_drop_target_add(Evas_Object *obj, Elm_Sel_Format format, static Eina_Bool _x11_elm_drop_target_del(Evas_Object *obj) { - Dropable *drop, *del, *dropable; - Eina_List *item, *l; + Dropable *dropable; + Eina_List *l; Ecore_X_Window xwin; Eina_Bool have_drops = EINA_FALSE; _x11_elm_cnp_init(); - del = NULL; - EINA_LIST_FOREACH(drops, item, drop) + eo_do(obj, eo_base_data_get("__elm_dropable", (void **)&dropable)); + if (dropable) { - if (drop->obj == obj) - { - drops = eina_list_remove_list(drops, item); - del = drop; - break; - } + drops = eina_list_remove(drops, dropable); + eo_do(obj, eo_base_data_del("__elm_dropable")); + free(dropable); + dropable = NULL; } - if (!del) return EINA_FALSE; + else return EINA_FALSE; evas_object_event_callback_del(obj, EVAS_CALLBACK_FREE, (Evas_Object_Event_Cb)elm_drop_target_del); - if (del) free(del); /* TODO BUG: we should handle dnd-aware per window, not just the last that reelased it */ @@ -3589,7 +3619,7 @@ _cont_drag_done_cb(void *data, Evas_Object *obj __UNUSED__) static Eina_Bool _cont_obj_drag_start(void *data) { /* Start a drag-action when timer expires */ - cnp_debug("%s In\n", __FUNCTION__); + cnp_debug("In\n"); Item_Container_Drag_Info *st = data; st->tm = NULL; Elm_Drag_User_Info *info = &st->user_info; @@ -3646,7 +3676,7 @@ _anim_icons_make(Eina_List *icons) static Eina_Bool _drag_anim_play(void *data, double pos) { /* Impl of the animation of icons, called on frame time */ - cnp_debug("%s In\n", __FUNCTION__); + cnp_debug("In\n"); Item_Container_Drag_Info *st = data; Eina_List *l; Anim_Icon *sti; @@ -3685,7 +3715,7 @@ _drag_anim_play(void *data, double pos) static inline Eina_Bool _drag_anim_start(void *data) { /* Start default animation */ - cnp_debug("%s In\n", __FUNCTION__); + cnp_debug("In\n"); Item_Container_Drag_Info *st = data; st->tm = NULL; @@ -3707,7 +3737,7 @@ _drag_anim_start(void *data) static Eina_Bool _cont_obj_anim_start(void *data) { /* Start a drag-action when timer expires */ - cnp_debug("%s In\n", __FUNCTION__); + cnp_debug("In\n"); Item_Container_Drag_Info *st = data; int xposret, yposret; /* Unused */ Elm_Object_Item *it = (st->itemgetcb) ? @@ -3753,7 +3783,7 @@ static void _cont_obj_mouse_down(void *data, Evas *e, Evas_Object *obj __UNUSED__, void *event_info) { /* Launch a timer to start dragging */ Evas_Event_Mouse_Down *ev = event_info; - cnp_debug("%s In - event %X\n", __FUNCTION__, ev->event_flags); + cnp_debug("In - event %X\n", ev->event_flags); if (ev->button != 1) return; /* We only process left-click at the moment */ @@ -3778,10 +3808,10 @@ static Eina_Bool elm_drag_item_container_del_internal(Evas_Object *obj, Eina_Boo static void _cont_obj_mouse_move(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info) { /* Cancel any drag waiting to start on timeout */ - cnp_debug("%s In\n", __FUNCTION__); + cnp_debug("In\n"); if (((Evas_Event_Mouse_Move *)event_info)->event_flags & EVAS_EVENT_FLAG_ON_HOLD) { - cnp_debug("%s event on hold - have to cancel DnD\n", __FUNCTION__); + cnp_debug("event on hold - have to cancel DnD\n"); Item_Container_Drag_Info *st = data; evas_object_event_callback_del_full @@ -3794,7 +3824,7 @@ _cont_obj_mouse_move(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__ _anim_st_free(st); } - cnp_debug("%s Out\n", __FUNCTION__); + cnp_debug("Out\n"); } static void @@ -3802,7 +3832,7 @@ _cont_obj_mouse_up(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, { /* Cancel any drag waiting to start on timeout */ Item_Container_Drag_Info *st = data; - cnp_debug("%s In\n", __FUNCTION__); + cnp_debug("In\n"); if (((Evas_Event_Mouse_Up *)event_info)->button != 1) return; /* We only process left-click at the moment */