rewrite efl cnp and dnd handling
authorMarcel Hollerbach <mail@marcel-hollerbach.de>
Sun, 19 Jan 2020 12:58:26 +0000 (13:58 +0100)
committerTaehyub Kim <taehyub.kim@samsung.com>
Tue, 10 Mar 2020 11:01:20 +0000 (20:01 +0900)
the previous commits introduced a abstraction for drag in drop which can
be now used for this here. With this commit all the direct protocol
handling in efl.ui is removed, and only the ecore evas API is used.

Additionally, this lead to a giant refactor of how APIs do work. All
Efl.Ui. interfaces have been removed except Efl.Ui.Selection and
Efl.Ui.Dnd, these two have been restructored.
A small list of what is new:
- In general no function pointers are used anymore. They feel very
  uncompftable in bindings and in C. For us its a lot easier to just
listen to a event when a drop enters or leaves, there is no need to
register custom functions for that.
- Asynchronous data transphere is handled via futures, which proved to
  be more error safe.
- Formats and actions are handled as mime types / strings.
- 0 is the default seat if you do not know what else to take.
- Content is in general passes as a content container from eina, this
  also allows applications to pass custom types

The legacy dnd and cnp API is implemented based on that.
All cnp related things are in elm_cnp.c the dnd parts are in elm_dnd.c

Reviewed-by: Mike Blumenkrantz <michael.blumenkrantz@gmail.com>
Differential Revision: https://phab.enlightenment.org/D11190

22 files changed:
src/lib/elementary/Efl_Ui.h
src/lib/elementary/efl_ui_dnd.c
src/lib/elementary/efl_ui_dnd.eo
src/lib/elementary/efl_ui_dnd_container.eo [deleted file]
src/lib/elementary/efl_ui_dnd_types.eot [deleted file]
src/lib/elementary/efl_ui_selection.c
src/lib/elementary/efl_ui_selection.eo
src/lib/elementary/efl_ui_selection_types.eot [deleted file]
src/lib/elementary/efl_ui_tags.c
src/lib/elementary/efl_ui_textbox.c
src/lib/elementary/efl_ui_textbox.eo
src/lib/elementary/efl_ui_win.c
src/lib/elementary/elm_cnp.c [new file with mode: 0644]
src/lib/elementary/elm_cnp.h
src/lib/elementary/elm_dnd.c [new file with mode: 0644]
src/lib/elementary/elm_entry.c
src/lib/elementary/elm_main.c
src/lib/elementary/elm_priv.h
src/lib/elementary/meson.build
src/lib/eo/eina_types.eot
src/lib/evas/canvas/evas_main.c
src/tests/elementary/efl_ui_test_text.c

index c010581..1020d9e 100644 (file)
@@ -119,8 +119,6 @@ extern EAPI Eina_Error EFL_UI_THEME_APPLY_ERROR_NONE;
 
 // EO types. Defined for legacy-only builds as legacy uses typedef of EO types.
 #include "efl_ui.eot.h"
-#include "efl_ui_selection_types.eot.h"
-#include "efl_ui_dnd_types.eot.h"
 
 //define focus manager earlier since focus object and manager is circular
 typedef Eo Efl_Ui_Focus_Manager;
@@ -323,7 +321,6 @@ typedef Eo Efl_Ui_Spotlight_Indicator;
 # include <efl_ui_widget_focus_manager.eo.h>
 # include <efl_ui_selection.eo.h>
 # include <efl_ui_dnd.eo.h>
-# include <efl_ui_dnd_container.eo.h>
 
 # include <efl_ui_timepicker.eo.h>
 # include <efl_ui_datepicker.eo.h>
index 256de65..2774d24 100644 (file)
 #include <Elementary_Cursor.h>
 #include "elm_priv.h"
 
-typedef struct _Efl_Ui_Dnd_Container_Data Efl_Ui_Dnd_Container_Data;
-struct _Efl_Ui_Dnd_Container_Data
-{
-    unsigned int drag_delay_time;
-};
+typedef struct {
+   Ecore_Evas *ee;
+   Eina_Bool registered;
+} Efl_Ui_Dnd_Data;
 
-extern int _wl_default_seat_id_get(Evas_Object *obj);
-#ifdef HAVE_ELEMENTARY_WL2
-Ecore_Wl2_Window *_wl_window_get(const Evas_Object *obj);
-#endif
+typedef struct {
+   Eo *win;
+   Efl_Ui_Dnd *obj;
+} Efl_Ui_Drag_Start;
 
-Eo*
-_efl_ui_selection_manager_get(Eo *obj)
+static void
+_ecore_evas_drag_terminated(Ecore_Evas *ee EINA_UNUSED, unsigned int seat, void *data, Eina_Bool accepted)
 {
-   if (!efl_isa(obj, EFL_UI_WIDGET_CLASS)) return NULL;
-   Eo *app = efl_app_main_get();
-   Eo *sel_man = efl_key_data_get(app, "__selection_manager");
-   if (!sel_man)
-     {
-        sel_man = efl_add(EFL_UI_SELECTION_MANAGER_CLASS, app);
-        efl_key_data_set(app, "__selection_manager", sel_man);
-     }
-   return sel_man;
+   Efl_Ui_Drag_Start *start = data;
+   Efl_Ui_Drag_Finished_Event ev = {seat, accepted};
+   efl_event_callback_call(start->obj, EFL_UI_DND_EVENT_DRAG_FINISHED, &ev);
+   efl_del(start->win);
+   free(start);
 }
 
-void
-_efl_ui_dnd_shutdown(void)
+EOLIAN static Efl_Content*
+_efl_ui_dnd_drag_start(Eo *obj, Efl_Ui_Dnd_Data *pd, Eina_Content *content, const char* action, unsigned int seat)
 {
-   Eo *app = efl_app_main_get();
-   Eo *sel_man = efl_key_data_get(app, "__selection_manager");
+   Eo *drag_win;
+   Efl_Ui_Drag_Start *start;
+   Efl_Ui_Drag_Started_Event ev = {seat};
+   Ecore_Evas *drag_ee;
+   EINA_SAFETY_ON_NULL_RETURN_VAL(pd->ee, NULL);
 
-   efl_del(sel_man);
-}
+   start = calloc(1, sizeof(Efl_Ui_Drag_Start));
+   start->obj = obj;
+   start->win = drag_win = elm_win_add(NULL, "Elm-Drag", ELM_WIN_DND);
+   elm_win_alpha_set(drag_win, EINA_TRUE);
+   elm_win_override_set(drag_win, EINA_TRUE);
+   elm_win_borderless_set(drag_win, EINA_TRUE);
+   drag_ee = ecore_evas_ecore_evas_get(evas_object_evas_get(drag_win));
 
-EOLIAN static void
-_efl_ui_dnd_drag_start(Eo *obj, void *pd EINA_UNUSED, Efl_Ui_Selection_Format format, Eina_Slice data,
-                       Efl_Ui_Selection_Action action, void *icon_func_data, Efl_Dnd_Drag_Icon_Create icon_func, Eina_Free_Cb icon_func_free_cb,
-                       unsigned int seat)
-{
-   Eo *sel_man = _efl_ui_selection_manager_get(obj);
-   efl_ui_selection_manager_drag_start(sel_man, obj, format, data, action,
-                                    icon_func_data, icon_func, icon_func_free_cb,
-                                    seat);
-}
+   ecore_evas_drag_start(pd->ee, seat, content, drag_ee, action, _ecore_evas_drag_terminated, start);
 
-EOLIAN static void
-_efl_ui_dnd_drag_cancel(Eo *obj, void *pd EINA_UNUSED, unsigned int seat)
-{
-   Eo *sel_man = _efl_ui_selection_manager_get(obj);
-   efl_ui_selection_manager_drag_cancel(sel_man, obj, seat);
-}
-
-EOLIAN static void
-_efl_ui_dnd_drag_action_set(Eo *obj, void *pd EINA_UNUSED, Efl_Ui_Selection_Action action, unsigned int seat)
-{
-   Eo *sel_man = _efl_ui_selection_manager_get(obj);
-   efl_ui_selection_manager_drag_action_set(sel_man, obj, action, seat);
-}
+   evas_object_show(drag_win);
 
+   efl_event_callback_call(obj, EFL_UI_DND_EVENT_DRAG_STARTED, &ev);
 
-EOLIAN static void
-_efl_ui_dnd_drop_target_add(Eo *obj, void *pd EINA_UNUSED, Efl_Ui_Selection_Format format, unsigned int seat)
-{
-   Eo *sel_man = _efl_ui_selection_manager_get(obj);
-   efl_ui_selection_manager_drop_target_add(sel_man, obj, format, seat);
+   return drag_win;
 }
 
 EOLIAN static void
-_efl_ui_dnd_drop_target_del(Eo *obj, void *pd EINA_UNUSED, Efl_Ui_Selection_Format format, unsigned int seat)
+_efl_ui_dnd_drag_cancel(Eo *obj EINA_UNUSED, Efl_Ui_Dnd_Data *pd, unsigned int seat)
 {
-   Eo *sel_man = _efl_ui_selection_manager_get(obj);
-   efl_ui_selection_manager_drop_target_del(sel_man, obj, format, seat);
+   ecore_evas_drag_cancel(pd->ee, seat);
 }
 
-EOLIAN static double
-_efl_ui_dnd_container_drag_delay_time_get(const Eo *obj EINA_UNUSED, Efl_Ui_Dnd_Container_Data *pd)
+EOLIAN static Eina_Future*
+_efl_ui_dnd_drop_data_get(Eo *obj EINA_UNUSED, Efl_Ui_Dnd_Data *pd, unsigned int seat, Eina_Iterator *acceptable_types)
 {
-    return pd->drag_delay_time;
+   return ecore_evas_selection_get(pd->ee, seat, ECORE_EVAS_SELECTION_BUFFER_DRAG_AND_DROP_BUFFER, acceptable_types);
 }
 
-EOLIAN static void
-_efl_ui_dnd_container_drag_delay_time_set(Eo *obj EINA_UNUSED, Efl_Ui_Dnd_Container_Data *pd, double drag_delay_time)
+EOLIAN static Efl_Object *
+_efl_ui_dnd_efl_object_constructor(Eo *obj, Efl_Ui_Dnd_Data *pd)
 {
-    pd->drag_delay_time = drag_delay_time;
-}
+   if (!efl_constructor(efl_super(obj, EFL_UI_DND_MIXIN)))
+     return NULL;
 
-EOLIAN static void
-_efl_ui_dnd_container_drag_item_add(Eo *obj, Efl_Ui_Dnd_Container_Data *pd,
-                                    void *data_func_data, Efl_Dnd_Drag_Data_Get data_func, Eina_Free_Cb data_func_free_cb,
-                                    void *item_func_data, Efl_Dnd_Item_Get item_func, Eina_Free_Cb item_func_free_cb,
-                                    void *icon_func_data, Efl_Dnd_Drag_Icon_Create icon_func, Eina_Free_Cb icon_func_free_cb,
-                                    void *icon_list_func_data, Efl_Dnd_Drag_Icon_List_Create icon_list_func, Eina_Free_Cb icon_list_func_free_cb,
-                                    unsigned int seat)
-{
-   double drag_delay_time = pd->drag_delay_time;
-   double anim_time = elm_config_drag_anim_duration_get();
-   Eo *sel_man = _efl_ui_selection_manager_get(obj);
-   efl_ui_selection_manager_container_drag_item_add(sel_man, obj, drag_delay_time, anim_time,
-                                                 data_func_data, data_func, data_func_free_cb,
-                                                 item_func_data, item_func, item_func_free_cb,
-                                                 icon_func_data, icon_func, icon_func_free_cb,
-                                                 icon_list_func_data, icon_list_func, icon_list_func_free_cb,
-                                                 seat);
-}
+   pd->ee = ecore_evas_ecore_evas_get(evas_object_evas_get(obj));
 
-static void
-_efl_ui_dnd_container_drag_item_del(Eo *obj, Efl_Ui_Dnd_Container_Data *pd EINA_UNUSED, unsigned int seat)
-{
-   Eo *sel_man = _efl_ui_selection_manager_get(obj);
-   efl_ui_selection_manager_container_drag_item_del(sel_man, obj, seat);
-}
-EOLIAN static void
-_efl_ui_dnd_container_drop_item_add(Eo *obj, Efl_Ui_Dnd_Container_Data *pd EINA_UNUSED,
-                                    Efl_Ui_Selection_Format format,
-                                    void *item_func_data, Efl_Dnd_Item_Get item_func, Eina_Free_Cb item_func_free_cb,
-                                    unsigned int seat)
-{
-   Eo *sel_man = _efl_ui_selection_manager_get(obj);
-   efl_ui_selection_manager_container_drop_item_add(sel_man, obj, format, item_func_data, item_func, item_func_free_cb, seat);
+   return obj;
 }
 
 EOLIAN static void
-_efl_ui_dnd_container_drop_item_del(Eo *obj, Efl_Ui_Dnd_Container_Data *pd EINA_UNUSED, unsigned int seat)
-{
-   Eo *sel_man = _efl_ui_selection_manager_get(obj);
-   efl_ui_selection_manager_container_drop_item_del(sel_man, obj, seat);
-}
-
-
-///////////
-typedef struct _Dnd_Icon_Create Dnd_Icon_Create;
-typedef struct _Dnd_Drag_Pos Dnd_Drag_Pos;
-typedef struct _Dnd_Drag_Accept Dnd_Drag_Accept;
-typedef struct _Dnd_Drag_Done Dnd_Drag_Done;
-typedef struct _Dnd_Drag_State Dnd_Drag_State;
-typedef struct _Dnd_Drop Dnd_Drop;
-typedef struct _Dnd_Cont_Drag_Pos Dnd_Cont_Drag_Pos;
-typedef struct _Dnd_Cont_Drop Dnd_Cont_Drop;
-typedef struct _Item_Container_Drag_Info Item_Container_Drag_Info;
-
-struct _Dnd_Icon_Create
-{
-   void *icon_data;
-   Elm_Drag_Icon_Create_Cb icon_cb;
-};
-
-struct _Dnd_Drag_Pos
-{
-   void *pos_data;
-   Elm_Drag_Pos pos_cb;
-};
-
-struct _Dnd_Drag_Accept
-{
-   void *accept_data;
-   Elm_Drag_Accept accept_cb;
-};
-
-struct _Dnd_Drag_Done
-{
-   void *done_data;
-   Elm_Drag_State done_cb;
-
-   //for deleting
-   Dnd_Drag_Pos *pos;
-   Dnd_Drag_Accept *accept;
-};
-
-struct _Dnd_Drag_State
-{
-   void *state_data;
-   Elm_Drag_State state_cb;
-};
-
-struct _Dnd_Drop
-{
-   Efl_Object *obj;
-   Elm_Sel_Format format;
-   void *drop_data;
-   Elm_Drop_Cb drop_cb;
-
-   //for deleting
-   Dnd_Drag_State *enter;
-   Dnd_Drag_State *leave;
-   Dnd_Drag_Pos *pos;
-};
-
-struct _Dnd_Cont_Drag_Pos
-{
-   void *pos_data;
-   Elm_Drag_Item_Container_Pos pos_cb;
-   Elm_Xy_Item_Get_Cb item_get_cb;
-};
-
-struct _Dnd_Cont_Drop
-{
-   Efl_Object *obj;
-   Elm_Sel_Format format;
-   void *drop_data;
-   Elm_Drop_Item_Container_Cb drop_cb;
-   Elm_Xy_Item_Get_Cb item_get_cb;
-
-   //for deleting
-   Dnd_Drag_State *enter;
-   Dnd_Drag_State *leave;
-   Dnd_Cont_Drag_Pos *pos;
-};
-
-struct _Item_Container_Drag_Info
-{
-   Elm_Drag_User_Info user_info;
-   Elm_Object_Item *it;
-   Elm_Item_Container_Data_Get_Cb data_get_cb;
-   Elm_Xy_Item_Get_Cb item_get_cb;
-};
-
-static Efl_Object *
-_dnd_icon_create_cb(void *data, Efl_Object *win, Efl_Object *drag_obj EINA_UNUSED, Eina_Position2D *pos_ret)
-{
-   Dnd_Icon_Create *ic = data;
-   Efl_Object *ret = NULL;
-   if (ic->icon_cb)
-     ret = ic->icon_cb(ic->icon_data, win, &pos_ret->x, &pos_ret->y);
-
-   free(ic);
-   return ret;
-}
-
-static void
-_dnd_drag_pos_cb(void *data, const Efl_Event *event)
-{
-   Dnd_Drag_Pos *pos = data;
-   Efl_Dnd_Drag_Pos *ddata = event->info;
-
-   if (pos->pos_cb)
-     pos->pos_cb(pos->pos_data, event->object, ddata->pos.x, ddata->pos.y,
-                 (Elm_Xdnd_Action)ddata->action);
-}
-
-static void
-_dnd_drag_accept_cb(void *data, const Efl_Event *event)
-{
-   Dnd_Drag_Accept *accept = data;
-
-   if (accept->accept_cb)
-     accept->accept_cb(accept->accept_data, event->object, *(Eina_Bool *)event->info);
-}
-
-static void
-_dnd_drag_done_cb(void *data, const Efl_Event *event)
-{
-   Dnd_Drag_Done *done = data;
-
-   if (done->done_cb)
-     done->done_cb(done->done_data, event->object);
-
-   efl_event_callback_del(event->object, EFL_UI_DND_EVENT_DRAG_POS,
-                          _dnd_drag_pos_cb, done->pos);
-   efl_event_callback_del(event->object, EFL_UI_DND_EVENT_DRAG_ACCEPT,
-                          _dnd_drag_accept_cb, done->accept);
-   efl_event_callback_del(event->object, EFL_UI_DND_EVENT_DRAG_DONE,
-                          _dnd_drag_done_cb, done);
-   free(done->pos);
-   free(done->accept);
-   free(done);
-}
-
-static void
-_dnd_drag_enter_leave_cb(void *data, const Efl_Event *event)
-{
-   Dnd_Drag_State *state = data;
-
-   if (state->state_cb)
-     state->state_cb(state->state_data, event->object);
-}
-
-static void
-_dnd_drop_cb(void *data, const Efl_Event *event)
-{
-   Dnd_Drop *drop = data;
-   Efl_Ui_Selection_Data *org_ddata = event->info;
-   Elm_Selection_Data ddata;
-
-   ddata.x = org_ddata->pos.x;
-   ddata.y = org_ddata->pos.y;
-   ddata.format = (Elm_Sel_Format)org_ddata->format;
-   ddata.action = (Elm_Xdnd_Action)org_ddata->action;
-   ddata.data = calloc(1, org_ddata->content.len);
-   if (!ddata.data) return;
-   ddata.data = memcpy(ddata.data, org_ddata->content.mem, org_ddata->content.len);
-   ddata.len = org_ddata->content.len;
-   if (drop->drop_cb)
-     drop->drop_cb(drop->drop_data, event->object, &ddata);
-   free(ddata.data);
-}
-
-EAPI Eina_Bool
-elm_drag_start(Evas_Object *obj, Elm_Sel_Format format, const char *data,
-               Elm_Xdnd_Action action,
-               Elm_Drag_Icon_Create_Cb icon_create_cb, void *icon_create_data,
-               Elm_Drag_Pos drag_pos_cb, void *drag_pos_data,
-               Elm_Drag_Accept drag_accept_cb, void *drag_accept_data,
-               Elm_Drag_State drag_done_cb, void *drag_done_data)
-{
-   if (!obj) return EINA_FALSE;
-   Eo *sel_man = _efl_ui_selection_manager_get(obj);
-   int seatid = 1;
-   Eina_Slice sl;
-   sl.mem = NULL;
-   sl.len = 0;
-
-   Dnd_Drag_Pos *pos = calloc(1, sizeof(Dnd_Drag_Pos));
-   Dnd_Drag_Accept *accept = calloc(1, sizeof(Dnd_Drag_Accept));
-   Dnd_Drag_Done *done = calloc(1, sizeof(Dnd_Drag_Done));
-   Dnd_Icon_Create *ic = calloc(1, sizeof(Dnd_Icon_Create));
-   if (!pos || !accept || !done || !ic) goto on_error;
-
-   pos->pos_data = drag_pos_data;
-   pos->pos_cb = drag_pos_cb;
-
-   accept->accept_data = drag_accept_data;
-   accept->accept_cb = drag_accept_cb;
-
-   done->done_data = drag_done_data;
-   done->done_cb = drag_done_cb;
-   done->pos = pos;
-   done->accept = accept;
-
-   efl_event_callback_add(obj, EFL_UI_DND_EVENT_DRAG_POS, _dnd_drag_pos_cb, pos);
-   efl_event_callback_add(obj, EFL_UI_DND_EVENT_DRAG_ACCEPT, _dnd_drag_accept_cb, accept);
-   efl_event_callback_add(obj, EFL_UI_DND_EVENT_DRAG_DONE, _dnd_drag_done_cb, done);
-
-   if (data)
-     {
-        sl.mem = data;
-        sl.len = strlen(data);
-     }
-#ifdef HAVE_ELEMENTARY_WL2
-   if (_wl_window_get(obj)) seatid = _wl_default_seat_id_get(obj);
-#endif
-
-   ic->icon_data = icon_create_data;
-   ic->icon_cb = icon_create_cb;
-   efl_ui_selection_manager_drag_start(sel_man, obj, (Efl_Ui_Selection_Format)format, sl,
-                                    (Efl_Ui_Selection_Action)action,
-                                    ic, _dnd_icon_create_cb, NULL, seatid);
-
-   return EINA_TRUE;
-
-on_error:
-   if (pos) free(pos);
-   if (accept) free(accept);
-   if (done) free(done);
-   if (ic) free(ic);
-
-   return EINA_FALSE;
-}
-
-EAPI Eina_Bool
-elm_drag_action_set(Evas_Object *obj, Elm_Xdnd_Action action)
-{
-   if (!obj) return EINA_FALSE;
-   Eo *sel_man = _efl_ui_selection_manager_get(obj);
-   int seatid = 1;
-
-#ifdef HAVE_ELEMENTARY_WL2
-   if (_wl_window_get(obj)) seatid = _wl_default_seat_id_get(obj);
-#endif
-   efl_ui_selection_manager_drag_action_set(sel_man, obj, (Efl_Ui_Selection_Action)action, seatid);
-
-   return EINA_TRUE;
-}
-
-EAPI Eina_Bool
-elm_drag_cancel(Evas_Object *obj)
+_efl_ui_dnd_efl_object_invalidate(Eo *obj, Efl_Ui_Dnd_Data *pd)
 {
-   Eo *sel_man = _efl_ui_selection_manager_get(obj);
-   int seatid = 1;
-
-#ifdef HAVE_ELEMENTARY_WL2
-   if (_wl_window_get(obj)) seatid = _wl_default_seat_id_get(obj);
-#endif
-
-   efl_ui_selection_manager_drag_cancel(sel_man, obj, seatid);
-
-   return EINA_TRUE;
-}
-
-static void
-_drop_obj_del_cb(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
-{
-   Eina_List *drop_list;
-   Dnd_Drop *drop;
-
-   drop_list = efl_key_data_get(obj, "__drop_list");
-   EINA_LIST_FREE(drop_list, drop)
+   if (pd->registered)
      {
-        efl_event_callback_del(drop->obj, EFL_UI_DND_EVENT_DRAG_ENTER,
-                               _dnd_drag_enter_leave_cb, drop->enter);
-        efl_event_callback_del(drop->obj, EFL_UI_DND_EVENT_DRAG_LEAVE,
-                               _dnd_drag_enter_leave_cb, drop->leave);
-        efl_event_callback_del(drop->obj, EFL_UI_DND_EVENT_DRAG_POS,
-                               _dnd_drag_pos_cb, drop->pos);
-        efl_event_callback_del(drop->obj, EFL_UI_DND_EVENT_DRAG_DROP,
-                               _dnd_drop_cb, drop);
-        free(drop->enter);
-        free(drop->leave);
-        free(drop->pos);
-        free(drop);
+        _drop_event_unregister(obj);
      }
-   efl_key_data_set(obj, "__drop_list", NULL);
-}
-
-EAPI Eina_Bool
-elm_drop_target_add(Evas_Object *obj, Elm_Sel_Format format,
-                    Elm_Drag_State enter_cb, void *enter_data,
-                    Elm_Drag_State leave_cb, void *leave_data,
-                    Elm_Drag_Pos pos_cb, void *pos_data,
-                    Elm_Drop_Cb drop_cb, void *drop_data)
-{
-   if (!obj) return EINA_FALSE;
-   Eo *sel_man = _efl_ui_selection_manager_get(obj);
-   int seatid = 1;
-   Dnd_Drag_State *enter = NULL, *leave = NULL;
-   Dnd_Drag_Pos *pos = NULL;
-   Dnd_Drop *drop = NULL;
-   Eina_List *drop_list;
-
-   enter = calloc(1, sizeof(Dnd_Drag_State));
-   leave = calloc(1, sizeof(Dnd_Drag_State));
-   pos = calloc(1, sizeof(Dnd_Drag_Pos));
-   drop = calloc(1, sizeof(Dnd_Drop));
-   if (!enter || !leave || !pos || !drop) goto on_error;
-#ifdef HAVE_ELEMENTARY_WL2
-   if (_wl_window_get(obj)) seatid = _wl_default_seat_id_get(obj);
-#endif
-   enter->state_cb = enter_cb;
-   enter->state_data = enter_data;
-   leave->state_cb = leave_cb;
-   leave->state_data = leave_data;
-   pos->pos_cb = pos_cb;
-   pos->pos_data = pos_data;
-   drop->obj = obj;
-   drop->format = format;
-   drop->drop_cb = drop_cb;
-   drop->drop_data = drop_data;
-   drop->enter = enter;
-   drop->leave = leave;
-   drop->pos = pos;
 
-   drop_list = efl_key_data_get(obj, "__drop_list");
-   drop_list = eina_list_append(drop_list, drop);
-   efl_key_data_set(obj, "__drop_list", drop_list);
-   evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL,
-                                  _drop_obj_del_cb, NULL);
-   efl_event_callback_add(obj, EFL_UI_DND_EVENT_DRAG_ENTER,
-                          _dnd_drag_enter_leave_cb, enter);
-   efl_event_callback_add(obj, EFL_UI_DND_EVENT_DRAG_LEAVE,
-                          _dnd_drag_enter_leave_cb, leave);
-   efl_event_callback_add(obj, EFL_UI_DND_EVENT_DRAG_POS,
-                          _dnd_drag_pos_cb, pos);
-   efl_event_callback_add(obj, EFL_UI_DND_EVENT_DRAG_DROP,
-                          _dnd_drop_cb, drop);
-   efl_ui_selection_manager_drop_target_add(sel_man, obj, (Efl_Ui_Selection_Format)format, seatid);
-
-   return EINA_TRUE;
-
-on_error:
-   if (enter) free(enter);
-   if (leave) free(leave);
-   if (pos) free(pos);
-   if (drop) free(drop);
-
-   return EINA_FALSE;
+   efl_invalidate(efl_super(obj, EFL_UI_DND_MIXIN));
 }
 
-EAPI Eina_Bool
-elm_drop_target_del(Evas_Object *obj, Elm_Sel_Format format,
-                    Elm_Drag_State enter_cb, void *enter_data,
-                    Elm_Drag_State leave_cb, void *leave_data,
-                    Elm_Drag_Pos pos_cb, void *pos_data,
-                    Elm_Drop_Cb drop_cb, void *drop_data)
-{
-   if(!obj) return EINA_FALSE;
-   Eo *sel_man = _efl_ui_selection_manager_get(obj);
-   int seatid = 1;
-   //Eina_List *l, *l2;
-   Eina_List *drop_list;
-   Dnd_Drop *drop;
+#define IS_DROP_EVENT(D) ( \
+(D == EFL_UI_DND_EVENT_DROP_POSITION_CHANGED) || \
+(D == EFL_UI_DND_EVENT_DROP_DROPPED) || \
+(D == EFL_UI_DND_EVENT_DROP_LEFT) || \
+(D == EFL_UI_DND_EVENT_DROP_ENTERED) \
+)
 
-#ifdef HAVE_ELEMENTARY_WL2
-   if (_wl_window_get(obj)) seatid = _wl_default_seat_id_get(obj);
-#endif
-
-   drop_list = efl_key_data_get(obj, "__drop_list");
-   drop = eina_list_data_get(drop_list);
-   if (drop &&
-       (drop->format == format) &&
-       (drop->enter->state_cb == enter_cb) &&
-       (drop->enter->state_data == enter_data) &&
-       (drop->leave->state_cb == leave_cb) &&
-       (drop->leave->state_data == leave_data) &&
-       (drop->pos->pos_cb == pos_cb) &&
-       (drop->pos->pos_data == pos_data) &&
-       (drop->drop_cb == drop_cb) &&
-       (drop->drop_data == drop_data))
-     {
-        drop_list = eina_list_remove(drop_list, drop);
-        efl_key_data_set(obj, "__drop_list", drop_list);
-        evas_object_event_callback_del(obj, EVAS_CALLBACK_DEL, _drop_obj_del_cb);
-        efl_event_callback_del(drop->obj, EFL_UI_DND_EVENT_DRAG_ENTER,
-                               _dnd_drag_enter_leave_cb, drop->enter);
-        efl_event_callback_del(drop->obj, EFL_UI_DND_EVENT_DRAG_LEAVE,
-                               _dnd_drag_enter_leave_cb, drop->leave);
-        efl_event_callback_del(drop->obj, EFL_UI_DND_EVENT_DRAG_POS,
-                               _dnd_drag_pos_cb, drop->pos);
-        efl_event_callback_del(drop->obj, EFL_UI_DND_EVENT_DRAG_DROP,
-                               _dnd_drop_cb, drop);
-        free(drop->enter);
-        free(drop->leave);
-        free(drop->pos);
-        free(drop);
-     }
-   efl_ui_selection_manager_drop_target_del(sel_man, obj, (Efl_Ui_Selection_Format)format, seatid);
-
-   return EINA_TRUE;
-}
-
-static Efl_Object *
-_dnd_item_func(void *data, Efl_Canvas_Object *item, Eina_Position2D pos, Eina_Position2D *pos_ret)
+EOLIAN static Efl_Object*
+_efl_ui_dnd_efl_object_finalize(Eo *obj, Efl_Ui_Dnd_Data *pd)
 {
-   Elm_Xy_Item_Get_Cb item_get_cb = data;
-   Evas_Coord x, y;
-   Efl_Object *obj = NULL;
-
-   x = y = 0;
-   if (item_get_cb)
-     obj = item_get_cb(item, pos.x, pos.y, &x, &y);
-   if (pos_ret)
-     {
-        pos_ret->x = x;
-        pos_ret->y = y;
-     }
+   if (pd->registered)
+     _drop_event_register(obj);
 
-   return obj;
+   return efl_finalize(efl_super(obj, EFL_UI_DND_MIXIN));
 }
 
-static void
-_dnd_cont_drag_pos_cb(void *data, const Efl_Event *event)
-{
-   Dnd_Cont_Drag_Pos *pos = data;
-   Efl_Dnd_Drag_Pos *ddata = event->info;
-   Evas_Coord xret = 0, yret = 0;
-
-   if (pos->item_get_cb)
-     {
-        Evas_Coord x, y;
-        evas_object_geometry_get(event->object, &x, &y, NULL, NULL);
-        pos->item_get_cb(event->object, ddata->pos.x + x, ddata->pos.y + y,
-                         &xret, &yret);
-     }
-   if (pos->pos_cb)
-     pos->pos_cb(pos->pos_data, event->object, ddata->item, ddata->pos.x, ddata->pos.y,
-                 xret, yret, (Elm_Xdnd_Action)ddata->action);
-}
 
-static void
-_dnd_cont_drop_cb(void *data, const Efl_Event *event)
+EOLIAN static Eina_Bool
+_efl_ui_dnd_efl_object_event_callback_priority_add(Eo *obj, Efl_Ui_Dnd_Data *pd,
+                                        const Efl_Event_Description *desc,
+                                        Efl_Callback_Priority priority,
+                                        Efl_Event_Cb func,
+                                        const void *user_data)
 {
-   Dnd_Cont_Drop *drop = data;
-   Efl_Ui_Selection_Data *org_ddata = event->info;
-   Elm_Selection_Data ddata;
-   Evas_Coord xret = 0, yret = 0;
+  if (IS_DROP_EVENT(desc) && !pd->registered)
+    {
+       pd->registered = EINA_TRUE;
+       if (efl_finalized_get(obj))
+         _drop_event_register(obj);
+    }
 
-   ddata.x = org_ddata->pos.x;
-   ddata.y = org_ddata->pos.y;
-   ddata.format = (Elm_Sel_Format)org_ddata->format;
-   ddata.action = (Elm_Xdnd_Action)org_ddata->action;
-   ddata.data = calloc(1, org_ddata->content.len);
-   if (!ddata.data) return;
-   ddata.data = memcpy(ddata.data, org_ddata->content.mem, org_ddata->content.len);
-   ddata.len = org_ddata->content.len;
-
-   if (drop->item_get_cb)
-     {
-        Evas_Coord x, y;
-        evas_object_geometry_get(event->object, &x, &y, NULL, NULL);
-        drop->item_get_cb(event->object, ddata.x + x, ddata.y + y,
-                          &xret, &yret);
-     }
-
-   if (drop->drop_cb)
-     drop->drop_cb(drop->drop_data, event->object, org_ddata->item,
-                   &ddata, xret, yret);
-   free(ddata.data);
+  return efl_event_callback_priority_add(efl_super(obj, EFL_UI_DND_MIXIN), desc, priority, func, user_data);
 }
 
-static void
-_cont_drop_free_data(Evas_Object *obj)
+EOLIAN static Eina_Bool
+_efl_ui_dnd_efl_object_event_callback_array_priority_add(Eo *obj, Efl_Ui_Dnd_Data *pd,
+                                              const Efl_Callback_Array_Item *array,
+                                              Efl_Callback_Priority priority,
+                                              const void *user_data)
 {
-   Eina_List *cont_drop_list;
-   Dnd_Cont_Drop *drop;
-
-   cont_drop_list = efl_key_data_get(obj, "__cont_drop_item");
-   drop = eina_list_data_get(cont_drop_list);
-   if (drop)
+   for (int i = 0; array[i].desc; ++i)
      {
-        efl_event_callback_del(drop->obj, EFL_UI_DND_EVENT_DRAG_ENTER,
-                               _dnd_drag_enter_leave_cb, drop->enter);
-        efl_event_callback_del(drop->obj, EFL_UI_DND_EVENT_DRAG_LEAVE,
-                               _dnd_drag_enter_leave_cb, drop->leave);
-        efl_event_callback_del(drop->obj, EFL_UI_DND_EVENT_DRAG_POS,
-                               _dnd_cont_drag_pos_cb, drop->pos);
-        efl_event_callback_del(drop->obj, EFL_UI_DND_EVENT_DRAG_DROP,
-                               _dnd_cont_drop_cb, drop);
-        free(drop->enter);
-        free(drop->leave);
-        free(drop->pos);
-        cont_drop_list = eina_list_remove(cont_drop_list, drop);
-        efl_key_data_set(obj, "__cont_drop_item", cont_drop_list);
-        free(drop);
-     }
-}
-
-static void
-_cont_drop_obj_del_cb(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj, void *info EINA_UNUSED)
-{
-   _cont_drop_free_data(obj);
-}
-
-EAPI Eina_Bool
-elm_drop_item_container_add(Evas_Object *obj,
-                            Elm_Sel_Format format,
-                            Elm_Xy_Item_Get_Cb item_get_cb,
-                            Elm_Drag_State enter_cb, void *enter_data,
-                            Elm_Drag_State leave_cb, void *leave_data,
-                            Elm_Drag_Item_Container_Pos pos_cb, void *pos_data,
-                            Elm_Drop_Item_Container_Cb drop_cb, void *drop_data)
-{
-   Eo *sel_man = _efl_ui_selection_manager_get(obj);
-   int seatid = 1;
-   Dnd_Drag_State *enter = NULL, *leave = NULL;
-   Dnd_Cont_Drag_Pos *pos = NULL;
-   Dnd_Cont_Drop *drop = NULL;
-   Eina_List *cont_drop_list;
-
-   enter = calloc(1, sizeof(Dnd_Drag_State));
-   leave = calloc(1, sizeof(Dnd_Drag_State));
-   pos = calloc(1, sizeof(Dnd_Cont_Drag_Pos));
-   drop = calloc(1, sizeof(Dnd_Cont_Drop));
-   if (!enter || !leave || !pos || !drop) goto on_error;
-#ifdef HAVE_ELEMENTARY_WL2
-   if (_wl_window_get(obj)) seatid = _wl_default_seat_id_get(obj);
-#endif
-
-   enter->state_cb = enter_cb;
-   enter->state_data = enter_data;
-   leave->state_cb = leave_cb;
-   leave->state_data = leave_data;
-   pos->pos_cb = pos_cb;
-   pos->pos_data = pos_data;
-   pos->item_get_cb = item_get_cb;
-   drop->obj = obj;
-   drop->format = format;
-   drop->drop_cb = drop_cb;
-   drop->drop_data = drop_data;
-   drop->enter = enter;
-   drop->leave = leave;
-   drop->pos = pos;
-
-   cont_drop_list = efl_key_data_get(obj, "__cont_drop_item");
-   cont_drop_list = eina_list_append(cont_drop_list, drop);
-   efl_key_data_set(obj, "__cont_drop_item", cont_drop_list);
-   evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL,
-                                  _cont_drop_obj_del_cb, NULL);
-   efl_event_callback_add(obj, EFL_UI_DND_EVENT_DRAG_ENTER,
-                          _dnd_drag_enter_leave_cb, enter);
-   efl_event_callback_add(obj, EFL_UI_DND_EVENT_DRAG_LEAVE,
-                          _dnd_drag_enter_leave_cb, leave);
-   efl_event_callback_add(obj, EFL_UI_DND_EVENT_DRAG_POS,
-                          _dnd_cont_drag_pos_cb, pos);
-   efl_event_callback_add(obj, EFL_UI_DND_EVENT_DRAG_DROP,
-                          _dnd_cont_drop_cb, drop);
-   efl_ui_selection_manager_container_drop_item_add(sel_man, obj, (Efl_Ui_Selection_Format)format,
-                                                 item_get_cb, _dnd_item_func, NULL,
-                                                 seatid);
-
-   return EINA_TRUE;
-
-on_error:
-    if (enter) free(enter);
-    if (leave) free(leave);
-    if (pos) free(pos);
-    if (drop) free(drop);
-
-   return EINA_FALSE;
-}
-
-EAPI Eina_Bool
-elm_drop_item_container_del(Evas_Object *obj)
-{
-   if (!obj) return EINA_FALSE;
-   Eo *sel_man = _efl_ui_selection_manager_get(obj);
-   int seatid = 1;
-
-#ifdef HAVE_ELEMENTARY_WL2
-   if (_wl_window_get(obj)) seatid = _wl_default_seat_id_get(obj);
-#endif
-
-   _cont_drop_free_data(obj);
-   evas_object_event_callback_del(obj, EVAS_CALLBACK_DEL, _cont_drop_obj_del_cb);
-//TIZEN_ONLY(20190104) Fix failed TC
-/*
-//
-   efl_ui_selection_manager_container_drop_item_del(sel_man, obj, seatid);
-
-   return EINA_TRUE;
-//TIZEN_ONLY(20190104) Fix failed TC
-*/
-   return efl_ui_selection_manager_container_drop_item_del(sel_man, obj, seatid);
-//
-}
-
-static void
-_cont_drag_data_func(void *data, Efl_Object *obj, Efl_Ui_Selection_Format *format,
-                     Eina_Rw_Slice *drag_data, Efl_Ui_Selection_Action *action)
-{
-   Item_Container_Drag_Info *di;
-
-   di = data;
-   if (!di) return;
-   di->data_get_cb(obj, di->it, &di->user_info);
-   if (format) *format = (Efl_Ui_Selection_Format)di->user_info.format;
-   if (drag_data)
-     {
-        if (di->user_info.data)
+        if (IS_DROP_EVENT(array[i].desc) && !pd->registered)
           {
-             drag_data->mem = (void *)di->user_info.data;
-             drag_data->len = strlen(di->user_info.data);
+             pd->registered = EINA_TRUE;
+             if (efl_finalized_get(obj))
+               _drop_event_register(obj);
           }
      }
-   if (action) *action = (Efl_Ui_Selection_Action)di->user_info.action;
+   return efl_event_callback_array_priority_add(efl_super(obj, EFL_UI_DND_MIXIN), array, priority, user_data);
 }
 
-static Eina_List *
-_cont_drag_icon_list_create(void *data, Efl_Object *obj EINA_UNUSED)
-{
-   Item_Container_Drag_Info *di;
-
-   di = data;
-   return di->user_info.icons;
-}
-
-static Efl_Object *
-_cont_drag_icon_create(void *data, Efl_Object *win, Efl_Object *drag_obj EINA_UNUSED, Eina_Position2D *pos_ret)
-{
-   Item_Container_Drag_Info *di;
-   Elm_Object_Item *it = NULL;
-
-   di = data;
-   if (!di) return NULL;
-   if (!di->user_info.createicon) return NULL;
-   it = di->user_info.createicon(di->user_info.createdata, win, &pos_ret->x, &pos_ret->y);
-   di->it = it;
-   return it;
-}
-
-static Efl_Object *
-_cont_drag_item_func(void *data, Efl_Canvas_Object *item, Eina_Position2D pos, Eina_Position2D *pos_ret)
-{
-   Item_Container_Drag_Info *di = data;
-   Evas_Coord x, y;
-   Efl_Object *obj = NULL;
-
-   x = y = 0;
-   if (di->item_get_cb)
-     obj = di->item_get_cb(item, pos.x, pos.y, &x, &y);
-   if (pos_ret)
-     {
-        pos_ret->x = x;
-        pos_ret->y = y;
-     }
-   di->it = obj;
-
-   return obj;
-}
-
-static void
-_cont_drag_free_data(Evas_Object *obj)
-{
-   Eina_List *di_list;
-   Item_Container_Drag_Info *di;
-
-   di_list = efl_key_data_get(obj, "__cont_drag_item");
-   di = eina_list_data_get(di_list);
-   di_list = eina_list_remove(di_list, di);
-   efl_key_data_set(obj, "__cont_drag_item", di_list);
-   free(di);
-}
-
-static void
-_cont_drag_obj_del_cb(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj, void *event EINA_UNUSED)
-{
-   _cont_drag_free_data(obj);
-}
-
-EAPI Eina_Bool
-elm_drag_item_container_add(Evas_Object *obj, double anim_tm, double tm_to_drag,
-                            Elm_Xy_Item_Get_Cb item_get_cb, Elm_Item_Container_Data_Get_Cb data_get_cb)
-{
-   Eo *sel_man = _efl_ui_selection_manager_get(obj);
-   int seatid = 1;
-   Eina_List *di_list;
-   Item_Container_Drag_Info *di;
-
-#ifdef HAVE_ELEMENTARY_WL2
-   if (_wl_window_get(obj)) seatid = _wl_default_seat_id_get(obj);
-#endif
-
-   di = calloc(1, sizeof(Item_Container_Drag_Info));
-   if (!di) return EINA_FALSE;
-   di->data_get_cb = data_get_cb;
-   di->item_get_cb = item_get_cb;
-   di_list = efl_key_data_get(obj, "__cont_drag_item");
-   di_list = eina_list_append(di_list, di);
-   efl_key_data_set(obj, "__cont_drag_item", di_list);
-   evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL, _cont_drag_obj_del_cb, NULL);
-   efl_ui_selection_manager_container_drag_item_add(sel_man, obj, tm_to_drag, anim_tm,
-                                                 di, _cont_drag_data_func, NULL,
-                                                 di, _cont_drag_item_func, NULL,
-                                                 di, _cont_drag_icon_create, NULL,
-                                                 di, _cont_drag_icon_list_create, NULL,
-                                                 seatid);
-   return EINA_TRUE;
-}
-
-EAPI Eina_Bool
-elm_drag_item_container_del(Evas_Object *obj)
-{
-   Eo *sel_man = _efl_ui_selection_manager_get(obj);
-   int seatid = 1;
-
-#ifdef HAVE_ELEMENTARY_WL2
-   if (_wl_window_get(obj)) seatid = _wl_default_seat_id_get(obj);
-#endif
-
-   _cont_drag_free_data(obj);
-   evas_object_event_callback_del(obj, EVAS_CALLBACK_DEL, _cont_drag_obj_del_cb);
-//TIZEN_ONLY(20190104) Fix failed TC
-/*
-//
-   efl_ui_selection_manager_container_drag_item_del(sel_man, obj, seatid);
-
-   return EINA_TRUE;
-//TIZEN_ONLY(20190104) Fix failed TC
-*/
-   return efl_ui_selection_manager_container_drag_item_del(sel_man, obj, seatid);
-//
-}
+#define EFL_UI_DND_EXTRA_OPS \
+   EFL_OBJECT_OP_FUNC(efl_event_callback_priority_add, _efl_ui_dnd_efl_object_event_callback_priority_add), \
+   EFL_OBJECT_OP_FUNC(efl_event_callback_array_priority_add, _efl_ui_dnd_efl_object_event_callback_array_priority_add), \
 
 #include "efl_ui_dnd.eo.c"
-#include "efl_ui_dnd_container.eo.c"
index 08f6688..8ef1911 100644 (file)
@@ -1,29 +1,40 @@
-import efl_ui_dnd_types;
+import eina_types;
 
-mixin @beta Efl.Ui.Dnd {
-   data: null;
+struct @beta Efl.Ui.Drop_Event {
+   [[Event struct that contains information about what is avaiable at which position, in which seat]]
+   position : Eina.Position2D; [[The position of the Drop event]]
+   seat : uint; [[In which seat it is happening]]
+   available_types : accessor<string>; [[which types are avaiable, you should use one of these for a call to @Efl.Ui.Dnd.drop_data_get ]]
+}
+
+struct @beta Efl.Ui.Drop_Dropped_Event {
+   dnd : Efl.Ui.Drop_Event; [[The overall information]]
+   action : string; [[The action the client should take]]
+}
+
+struct @beta Efl.Ui.Drag_Started_Event {
+   seat : uint;
+}
+
+struct @beta Efl.Ui.Drag_Finished_Event {
+   seat : uint;
+   accepted : bool;
+}
+
+mixin @beta Efl.Ui.Dnd requires Efl.Object {
    methods {
       drag_start {
-         [[Start a drag and drop process at the drag side.
-           During dragging, there are three events emitted as belows:
-              - EFL_UI_DND_EVENT_DRAG_POS
-              - EFL_UI_DND_EVENT_DRAG_ACCEPT
-              - EFL_UI_DND_EVENT_DRAG_DONE
+         [[Start a drag from this client.
+
+           @[Efl.Ui.Dnd.drag,started] will be emitted each time a successfull drag will be started.
+           @[Efl.Ui.Dnd.drag,finished] will be emitted every time a drag is finished.
          ]]
          params {
-            @in format: Efl.Ui.Selection_Format; [[The data format]]
-            @in data: Eina.Slice; [[The drag data]]
-            @in action: Efl.Ui.Selection_Action; [[Action when data is transferred]]
-            @in icon_func: Efl.Dnd.Drag_Icon_Create; [[Function pointer to create icon]]
-            @in seat: uint; [[Specified seat for multiple seats case.]]
-         }
-      }
-      drag_action_set {
-         [[Set the action for the drag]]
-         params {
-            @in action: Efl.Ui.Selection_Action; [[Drag action]]
+            content : Eina.Content @by_ref; [[The content you want to provide via dnd]]
+            @in action: string; [[Action when data is transferred]]
             @in seat: uint; [[Specified seat for multiple seats case.]]
          }
+         return : Efl.Content; [[A UI element where you can just set your visual representation into]]
       }
       drag_cancel {
          [[Cancel the on-going drag]]
@@ -31,33 +42,26 @@ mixin @beta Efl.Ui.Dnd {
             @in seat: uint; [[Specified seat for multiple seats case.]]
          }
       }
-      drop_target_add {
-         [[Make the current object as drop target.
-           There are four events emitted:
-            - EFL_UI_DND_EVENT_DRAG_ENTER
-            - EFL_UI_DND_EVENT_DRAG_LEAVE
-            - EFL_UI_DND_EVENT_DRAG_POS
-            - EFL_UI_DND_EVENT_DRAG_DROP.]]
+      drop_data_get {
+         [[Get the data from the object that has selection]]
          params {
-            @in format: Efl.Ui.Selection_Format; [[Accepted data format]]
-            @in seat: uint; [[Specified seat for multiple seats case.]]
-         }
-      }
-      drop_target_del {
-         [[Delete the dropable status from object]]
-         params {
-            @in format: Efl.Ui.Selection_Format; [[Accepted data format]]
-            @in seat: uint; [[Specified seat for multiple seats case.]]
+           seat : uint;  [[Specified seat for multiple seats case.]]
+           acceptable_types : iterator<string>; [[The types that are acceptable for you]]
          }
+         return : future<Eina.Content> @move; [[fullfilled when the content is transmitted, and ready to use]]
       }
    }
    events {
-      /* FIXME: This is not very future-proof. Better return a struct. */
-      drag,accept: ptr(bool); [[accept drag data]]
-      drag,done: void; [[drag is done (mouse up)]]
-      drag,enter: void; [[called when the drag object enters this object]]
-      drag,leave: void; [[called when the drag object leaves this object]]
-      drag,pos: Efl.Dnd.Drag_Pos; [[called when the drag object changes drag position]]
-      drag,drop: Efl.Ui.Selection_Data; [[called when the drag object dropped on this object]]
+      drop,entered : Efl.Ui.Drop_Event;
+      drop,left : Efl.Ui.Drop_Event;
+      drop,position,changed : Efl.Ui.Drop_Event;
+      drop,dropped : Efl.Ui.Drop_Dropped_Event;
+      drag,started : Efl.Ui.Drag_Started_Event;
+      drag,finished : Efl.Ui.Drag_Finished_Event;
+   }
+   implements {
+      Efl.Object.constructor;
+      Efl.Object.invalidate;
+      Efl.Object.finalize;
    }
 }
diff --git a/src/lib/elementary/efl_ui_dnd_container.eo b/src/lib/elementary/efl_ui_dnd_container.eo
deleted file mode 100644 (file)
index 0cc1f3f..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-import efl_ui_dnd_types;
-
-mixin @beta Efl.Ui.Dnd_Container {
-   methods {
-      @property drag_delay_time {
-         [[The time since mouse down happens to drag starts.]]
-         set {
-         }
-         get {
-         }
-         values {
-            time: double; [[The drag delay time]]
-         }
-      }
-      drag_item_add {
-         [[This registers a drag for items in a container. Many items can be
-           dragged at a time. During dragging, there are three events emitted:
-           EFL_DND_EVENT_DRAG_POS, EFL_DND_EVENT_DRAG_ACCEPT, EFL_DND_EVENT_DRAG_DONE.]]
-         params {
-            @in data_func: Efl.Dnd.Drag_Data_Get; [[Data and its format]]
-            @in item_func: Efl.Dnd.Item_Get; [[Item to determine drag start]]
-            @in icon_func: Efl.Dnd.Drag_Icon_Create; [[Icon used during drag]]
-            @in icon_list_func: Efl.Dnd.Drag_Icon_List_Create; [[Icons used for animations CHECKING ]]
-            @in seat: uint; [[Specified seat for multiple seats case.]]
-         }
-      }
-      drag_item_del {
-         [[Remove drag function of items in the container object.]]
-         params {
-            @in seat: uint; [[Specified seat for multiple seats case.]]
-         }
-      }
-      drop_item_add {
-         params {
-            @in format: Efl.Ui.Selection_Format; [[Accepted data formats]]
-            @in item_func: Efl.Dnd.Item_Get; [[Get item at specific position]]
-            @in seat: uint; [[Specified seat for multiple seats case.]]
-         }
-      }
-      drop_item_del {
-         params {
-            @in seat: uint; [[Specified seat for multiple seats case.]]
-         }
-      }
-   }
-}
diff --git a/src/lib/elementary/efl_ui_dnd_types.eot b/src/lib/elementary/efl_ui_dnd_types.eot
deleted file mode 100644 (file)
index ace1c8d..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-import efl_ui_selection_types;
-
-function @beta Efl.Dnd.Drag_Icon_Create {
-   [[Function pointer for creating icon at the drag side.]]
-   params {
-      @in win: Efl.Canvas.Object; [[The window to create the objects relative to]]
-      @in drag_obj: Efl.Canvas.Object; [[The drag object]]
-      @out off: Eina.Position2D; [[Offset from the icon position to the cursor]]
-   }
-   return: Efl.Canvas.Object; [[The drag icon object]]
-};
-
-function @beta Efl.Dnd.Drag_Data_Get {
-   [[Function pointer for getting data and format at the drag side.]]
-   params {
-      @in obj: Efl.Canvas.Object; [[The container object]]
-      @out format: Efl.Ui.Selection_Format; [[Data format]]
-      @out drag_data: Eina.Rw_Slice; [[Data]]
-      @out action: Efl.Ui.Selection_Action; [[The drag action]]
-   }
-};
-
-function @beta Efl.Dnd.Item_Get {
-   [[Function pointer to find out which item is under position (x, y)]]
-   params {
-      @in obj: Efl.Canvas.Object; [[The container object]]
-      @in pos: Eina.Position2D; [[The coordinates to get item]]
-      @out posret: Eina.Position2D; [[position relative to item (left (-1), middle (0), right (1)]]
-   }
-   return: Efl.Object; [[Object under x,y coordinates or NULL if not found]]
-};
-
-function @beta Efl.Dnd.Drag_Icon_List_Create {
-   [[Function pointer to create list of icons at the drag side.
-     These icons are used for animation on combining selection icons
-     to one icon.]]
-   params {
-      @in obj: Efl.Canvas.Object; [[The container object]]
-   }
-   return: list<Efl.Canvas.Object>;
-};
-
-struct @beta Efl.Dnd.Drag_Accept {
-   accepted: bool;
-}
-
-struct @beta Efl.Dnd.Drag_Pos {
-   [[Dragging position information.]]
-   pos: Eina.Position2D; [[Evas Coordinate]]
-   action: Efl.Ui.Selection_Action; [[The drag action]]
-   format: Efl.Ui.Selection_Format; [[The drag format]]
-   item: Efl.Canvas.Object; [[The item object. It is only available for container object.]]
-}
-
-struct @beta Efl.Dnd.Drag_Item_Container_Drop {
-   [[Drop information for a drag&drop operation.]]
-   item: Efl.Canvas.Object; [[The item object]]
-   data: Efl.Ui.Selection_Data; [[The selection data]]
-   pos: Eina.Position2D; [[Position relative to item (left (-1), middle (0), right (1)]]
-}
index e6e993e..5489de1 100644 (file)
 #define MY_CLASS EFL_UI_SELECTION_MIXIN
 #define MY_CLASS_NAME "Efl.Ui.Selection"
 
-#ifdef HAVE_ELEMENTARY_WL2
-Ecore_Wl2_Window *_wl_window_get(const Evas_Object *obj);
-#endif
+typedef struct {
+   Ecore_Evas *ee;
+   Eina_Bool registered : 1;
+} Efl_Ui_Selection_Data;
 
-EOLIAN static void
-_efl_ui_selection_selection_get(Eo *obj, void *pd EINA_UNUSED, Efl_Ui_Selection_Type type, Efl_Ui_Selection_Format format,
-                                     void *data_func_data, Efl_Ui_Selection_Data_Ready data_func, Eina_Free_Cb data_func_free_cb, unsigned int seat)
+static inline Ecore_Evas_Selection_Buffer
+_ee_buffer_get(Efl_Ui_Cnp_Buffer buffer)
 {
-   Eo *sel_man = _efl_ui_selection_manager_get(obj);
-   efl_ui_selection_manager_selection_get(sel_man, obj, type, format,
-                                       data_func_data, data_func,
-                                       data_func_free_cb, seat);
+   if (buffer == EFL_UI_CNP_BUFFER_SELECTION)
+     return ECORE_EVAS_SELECTION_BUFFER_SELECTION_BUFFER;
+   else
+     return ECORE_EVAS_SELECTION_BUFFER_COPY_AND_PASTE_BUFFER;
 }
 
-EOLIAN static Eina_Future *
-_efl_ui_selection_selection_set(Eo *obj, void *pd EINA_UNUSED, Efl_Ui_Selection_Type type, Efl_Ui_Selection_Format format, Eina_Slice data, unsigned int seat)
+EOLIAN static Eina_Future*
+_efl_ui_selection_selection_get(Eo *obj EINA_UNUSED, Efl_Ui_Selection_Data *pd, Efl_Ui_Cnp_Buffer buffer, unsigned int seat, Eina_Iterator *acceptable_types)
 {
-   Eo *sel_man = _efl_ui_selection_manager_get(obj);
-   return efl_ui_selection_manager_selection_set(sel_man, obj, type, format, data, seat);
+   return ecore_evas_selection_get(pd->ee, seat, _ee_buffer_get(buffer), acceptable_types);
 }
 
 EOLIAN static void
-_efl_ui_selection_selection_clear(Eo *obj, void *pd EINA_UNUSED, Efl_Ui_Selection_Type type, unsigned int seat)
+_efl_ui_selection_selection_set(Eo *obj, Efl_Ui_Selection_Data *pd, Efl_Ui_Cnp_Buffer buffer, Eina_Content *content, unsigned int seat)
 {
-   Eo *sel_man = _efl_ui_selection_manager_get(obj);
-   efl_ui_selection_manager_selection_clear(sel_man, obj, type, seat);
+   _register_selection_changed(obj);
+   ecore_evas_selection_set(pd->ee, seat, _ee_buffer_get(buffer), content);
 }
 
-EOLIAN static Eina_Bool
-_efl_ui_selection_has_owner(Eo *obj, void *pd EINA_UNUSED, Efl_Ui_Selection_Type type, unsigned int seat)
+EOLIAN static void
+_efl_ui_selection_selection_clear(Eo *obj EINA_UNUSED, Efl_Ui_Selection_Data *pd, Efl_Ui_Cnp_Buffer buffer, unsigned int seat)
 {
-    Eo *sel_man = _efl_ui_selection_manager_get(obj);
-    return efl_ui_selection_manager_selection_has_owner(sel_man, obj, type, seat);
+   ecore_evas_selection_set(pd->ee, seat, _ee_buffer_get(buffer), NULL);
 }
 
+EOLIAN static Eina_Bool
+_efl_ui_selection_has_selection(Eo *obj EINA_UNUSED, Efl_Ui_Selection_Data *pd, Efl_Ui_Cnp_Buffer buffer, unsigned int seat)
+{
+   return ecore_evas_selection_exists(pd->ee, seat, _ee_buffer_get(buffer));
+}
 
-////////// Support legacy APIs
-
-//TODO: Clear this list (when sel_man is deleted)
-Eina_List *lost_cb_list = NULL;
-
-#ifdef HAVE_ELEMENTARY_WL2
-static Ecore_Evas *
-_wl_is_wl(const Evas_Object *obj)
+EOLIAN static Efl_Object*
+_efl_ui_selection_efl_object_constructor(Eo *obj, Efl_Ui_Selection_Data *pd)
 {
-   Ecore_Evas *ee;
-   Evas *evas;
-   const char *engine_name;
+  if (!efl_constructor(efl_super(obj, EFL_UI_SELECTION_MIXIN)))
+    return NULL;
 
-   if (!(evas = evas_object_evas_get(obj)))
-     return NULL;
-   if (!(ee = ecore_evas_ecore_evas_get(evas)))
-     return NULL;
+  pd->ee = ecore_evas_ecore_evas_get(evas_object_evas_get(obj));
 
-   engine_name = ecore_evas_engine_name_get(ee);
-   if (!strcmp(engine_name, ELM_BUFFER))
-     {
-        ee = ecore_evas_buffer_ecore_evas_parent_get(ee);
-        if (!ee) return NULL;
-        engine_name = ecore_evas_engine_name_get(ee);
-     }
-   if (!strncmp(engine_name, "wayland", sizeof("wayland") - 1))
-     return ee;
-   return NULL;
+  return obj;
 }
 
-int
-_wl_default_seat_id_get(Evas_Object *obj)
+EOLIAN static void
+_efl_ui_selection_efl_object_invalidate(Eo *obj, Efl_Ui_Selection_Data *pd)
 {
-   Ecore_Wl2_Window *win = _wl_window_get(obj);
-   Eo *seat, *parent2, *ewin;
-   Eina_Bool is_wl = EINA_FALSE;
-
-   if (obj)
+   if (pd->registered)
      {
-        if (_wl_is_wl(obj)) is_wl = EINA_TRUE;
-        if (efl_isa(obj, EFL_UI_WIDGET_CLASS))
-          {
-             Eo *top = elm_widget_top_get(obj);
-             if (efl_isa(top, EFL_UI_WIN_INLINED_CLASS))
-               {
-                  parent2 = efl_ui_win_inlined_parent_get(top);
-                  if (parent2) obj = elm_widget_top_get(parent2) ?: parent2;
-               }
-             /* fake win means canvas seat id will not match protocol seat id */
-             ewin = elm_win_get(obj);
-             if (elm_win_type_get(ewin) == ELM_WIN_FAKE) obj = NULL;
-          }
-     }
-
-   if (!obj)
-     {
-        if (is_wl)
-          {
-             Ecore_Wl2_Input *input;
-             Eina_Iterator *it;
-
-             it = ecore_wl2_display_inputs_get(ecore_wl2_window_display_get(win));
-             EINA_ITERATOR_FOREACH(it, input) break;
-             eina_iterator_free(it);
-             if (input)
-               return ecore_wl2_input_seat_id_get(input);
-          }
+        _selection_changed_event_unregister(obj);
      }
-
-   seat = evas_default_device_get(evas_object_evas_get(obj), EFL_INPUT_DEVICE_TYPE_SEAT);
-   EINA_SAFETY_ON_NULL_RETURN_VAL(seat, 1);
-   return evas_device_seat_id_get(seat);
+   efl_invalidate(efl_super(obj, EFL_UI_SELECTION_MIXIN));
 }
-#endif
 
-typedef struct _Cnp_Data_Cb_Wrapper Cnp_Data_Cb_Wrapper;
-struct _Cnp_Data_Cb_Wrapper
+EOLIAN static Eina_Bool
+_efl_ui_selection_efl_object_event_callback_priority_add(Eo *obj, Efl_Ui_Selection_Data *pd,
+                                        const Efl_Event_Description *desc,
+                                        Efl_Callback_Priority priority,
+                                        Efl_Event_Cb func,
+                                        const void *user_data)
 {
-   void *udata;
-   Elm_Drop_Cb datacb;
-};
+  if (desc == EFL_UI_SELECTION_EVENT_WM_SELECTION_CHANGED && !pd->registered)
+    {
 
-static void
-_selection_data_ready_cb(void *data, Efl_Object *obj, Efl_Ui_Selection_Data *seldata)
-{
-    Cnp_Data_Cb_Wrapper *wdata = data;
-    if (!wdata) return;
-    Elm_Selection_Data ddata;
+       pd->registered = EINA_TRUE;
+       if (efl_finalized_get(obj))
+         _selection_changed_event_register(obj);
+    }
 
-    ddata.data = calloc(1, seldata->content.len + 1);
-    if (!ddata.data) return;
-    ddata.data = memcpy(ddata.data, seldata->content.mem, seldata->content.len);
-    ddata.len = seldata->content.len;
-    ddata.x = seldata->pos.x;
-    ddata.y = seldata->pos.y;
-    ddata.format = (Elm_Sel_Format)seldata->format;
-    ddata.action = (Elm_Xdnd_Action)seldata->action;
-    wdata->datacb(wdata->udata, obj, &ddata);
-    free(ddata.data);
+  return efl_event_callback_priority_add(efl_super(obj, EFL_UI_SELECTION_MIXIN), desc, priority, func, user_data);
 }
 
-typedef struct _Sel_Lost_Data Sel_Lost_Data;
-struct _Sel_Lost_Data
-{
-   const Evas_Object *obj;
-   Elm_Sel_Type type;
-   void *udata;
-   Elm_Selection_Loss_Cb loss_cb;
-};
-
-static Eina_Value
-_selection_lost_cb(void *data, const Eina_Value value)
+EOLIAN static Eina_Bool
+_efl_ui_selection_efl_object_event_callback_array_priority_add(Eo *obj, Efl_Ui_Selection_Data *pd,
+                                              const Efl_Callback_Array_Item *array,
+                                              Efl_Callback_Priority priority,
+                                              const void *user_data)
 {
-   Eina_List *l, *l2;
-   Sel_Lost_Data *ldata, *ldata2;
-
-   ldata = data;
-   EINA_LIST_FOREACH_SAFE(lost_cb_list, l, l2, ldata2)
+   for (int i = 0; array[i].desc; ++i)
      {
-        if ((ldata->obj == ldata2->obj) &&
-            (ldata->type == ldata2->type))
+        if (array[i].desc == EFL_UI_SELECTION_EVENT_WM_SELECTION_CHANGED && !pd->registered)
           {
-             //TIZEN ONLY(20180807): check the sel lost object to prevent the invalid access
-             //ldata2->loss_cb(ldata2->udata, ldata2->type);
-             if (efl_data_scope_get(ldata2->obj, EFL_UI_WIDGET_CLASS))
-               ldata2->loss_cb(ldata2->udata, ldata2->type);
-             //
-             lost_cb_list = eina_list_remove(lost_cb_list, ldata2);
+             pd->registered = EINA_TRUE;
+             if (efl_finalized_get(obj))
+               _selection_changed_event_register(obj);
           }
      }
-   free(ldata);
-
-   return value;
-}
-
-EAPI Eina_Bool
-elm_cnp_selection_get(const Evas_Object *obj, Elm_Sel_Type type,
-                      Elm_Sel_Format format, Elm_Drop_Cb datacb, void *udata)
-{
-   int seatid = 1;
-   Eo *sel_man = _efl_ui_selection_manager_get((Evas_Object *)obj);
-   Cnp_Data_Cb_Wrapper *wdata = calloc(1, sizeof(Cnp_Data_Cb_Wrapper));
-
-   if (!wdata) return EINA_FALSE;
-
-#ifdef HAVE_ELEMENTARY_WL2
-   if (_wl_window_get(obj)) seatid = _wl_default_seat_id_get((Evas_Object *)obj);
-#endif
-   wdata->udata = udata;
-   wdata->datacb = datacb;
-   efl_ui_selection_manager_selection_get(sel_man, (Evas_Object *)obj, (Efl_Ui_Selection_Type)type,
-                                       (Efl_Ui_Selection_Format)format,
-                                       wdata, _selection_data_ready_cb, NULL, seatid);
-   return EINA_TRUE;
-}
-
-EAPI Eina_Bool
-elm_cnp_selection_set(Evas_Object *obj, Elm_Sel_Type type,
-                      Elm_Sel_Format format, const void *selbuf, size_t buflen)
-{
-   int seatid = 1;
-   Eina_Future *f;
-   Sel_Lost_Data *ldata;
-   Eo *sel_man = _efl_ui_selection_manager_get(obj);
-   Eina_Slice data;
-
-   ldata = calloc(1, sizeof(Sel_Lost_Data));
-   if (!ldata) return EINA_FALSE;
-   data.mem = selbuf;
-   data.len = buflen;
-#ifdef HAVE_ELEMENTARY_WL2
-   if (_wl_window_get(obj)) seatid = _wl_default_seat_id_get(obj);
-#endif
-   f = efl_ui_selection_manager_selection_set(sel_man, obj, (Efl_Ui_Selection_Type)type,
-                                           (Efl_Ui_Selection_Format)format, data, seatid);
-
-   ldata->obj = obj;
-   ldata->type = type;
-   eina_future_then_easy(f, _selection_lost_cb, NULL, NULL, EINA_VALUE_TYPE_UINT, ldata);
-
-   return EINA_TRUE;
-}
-
-EAPI Eina_Bool
-elm_object_cnp_selection_clear(Evas_Object *obj, Elm_Sel_Type type)
-{
-   if (type > ELM_SEL_TYPE_CLIPBOARD) return EINA_FALSE;
-
-   int seatid = 1;
-   Eo *sel_man = _efl_ui_selection_manager_get((Evas_Object *)obj);
-
-#ifdef HAVE_ELEMENTARY_WL2
-   if (_wl_window_get(obj)) seatid = _wl_default_seat_id_get(obj);
-#endif
-   efl_ui_selection_manager_selection_clear(sel_man, obj, (Efl_Ui_Selection_Type)type, seatid);
-
-   return EINA_TRUE;
+   return efl_event_callback_array_priority_add(efl_super(obj, EFL_UI_SELECTION_MIXIN), array, priority, user_data);
 }
 
-EAPI void
-elm_cnp_selection_loss_callback_set(Evas_Object *obj, Elm_Sel_Type type,
-                                    Elm_Selection_Loss_Cb func, const void *data)
-{
-   Sel_Lost_Data *ldata = calloc(1, sizeof(Sel_Lost_Data));
-#if HAVE_ELEMENTARY_COCOA
-   // Currently, we have no way to track changes in Cocoa pasteboard.
-   // Therefore, don't track this...
-   return;
-#endif
-   if (!ldata) return;
-   ldata->obj = obj;
-   ldata->type = type;
-   ldata->udata = (void *)data;
-   ldata->loss_cb = func;
-   lost_cb_list = eina_list_append(lost_cb_list, ldata);
-}
 
-EAPI Eina_Bool
-elm_selection_selection_has_owner(Evas_Object *obj)
+EOLIAN static Efl_Object*
+_efl_ui_selection_efl_object_finalize(Eo *obj, Efl_Ui_Selection_Data *pd)
 {
-   int seatid = 1;
-   Eo *sel_man = _efl_ui_selection_manager_get((Evas_Object *)obj);
-
-#ifdef HAVE_ELEMENTARY_WL2
-   if (_wl_window_get(obj)) seatid = _wl_default_seat_id_get(obj);
-#endif
+   if (pd->registered)
+     _selection_changed_event_register(obj);
 
-   return efl_ui_selection_manager_selection_has_owner(sel_man, obj,
-                                                    EFL_UI_SELECTION_TYPE_CLIPBOARD, seatid);
+   return efl_finalize(efl_super(obj, MY_CLASS));
 }
 
-EAPI Eina_Bool
-elm_cnp_clipboard_selection_has_owner(Evas_Object *obj)
-{
-   int seatid = 1;
-   Eo *sel_man = _efl_ui_selection_manager_get((Evas_Object *)obj);
-
-#ifdef HAVE_ELEMENTARY_WL2
-   if (_wl_window_get(obj)) seatid = _wl_default_seat_id_get(obj);
-#endif
-   return efl_ui_selection_manager_selection_has_owner(sel_man, obj,
-                                                    EFL_UI_SELECTION_TYPE_CLIPBOARD, seatid);
-}
+#define EFL_UI_SELECTION_EXTRA_OPS \
+   EFL_OBJECT_OP_FUNC(efl_event_callback_priority_add, _efl_ui_selection_efl_object_event_callback_priority_add), \
+   EFL_OBJECT_OP_FUNC(efl_event_callback_array_priority_add, _efl_ui_selection_efl_object_event_callback_array_priority_add), \
 
 #include "efl_ui_selection.eo.c"
index 20e4226..492e60e 100644 (file)
@@ -1,45 +1,57 @@
-import efl_ui_selection_types;
+import eina_types;
 
-mixin @beta Efl.Ui.Selection {
-   [[Efl Ui Selection class]]
-   data: null;
-   methods {
-      selection_set {
-         [[Set the selection data to the object]]
-         params {
-            @in type: Efl.Ui.Selection_Type; [[Selection Type]]
-            @in format: Efl.Ui.Selection_Format; [[Selection Format]]
-            @in data: Eina.Slice; [[Selection data]]
-            @in seat: uint;[[Specified seat for multiple seats case.]]
-         }
-         return: future<void>; [[Future for tracking when the selection is lost]]
+enum @beta Efl.Ui.Cnp_Buffer{
+   selection = 0,
+   copy_and_paste = 1,
+}
+
+struct @beta Efl.Ui.Wm_Selection_Changed {
+   buffer : Efl.Ui.Cnp_Buffer;
+   caused_by : Efl.Ui.Selection;
+   seat : uint;
+}
+
+mixin @beta Efl.Ui.Selection requires Efl.Object {
+  methods {
+    selection_set {
+      [[Set the selection data to the object]]
+      params {
+        buffer : Efl.Ui.Cnp_Buffer;
+        content : Eina.Content @by_ref;
+        seat : uint;
       }
-      selection_get {
-         [[Get the data from the object that has selection]]
-         params {
-            @in type: Efl.Ui.Selection_Type; [[Selection Type]]
-            @in format: Efl.Ui.Selection_Format; [[Selection Format]]
-            @in data_func: Efl.Ui.Selection_Data_Ready; [[Data ready function pointer]]
-            @in seat: uint;[[Specified seat for multiple seats case.]]
-         }
+    }
+    selection_clear {
+      [[Clear the selection data from the object]]
+      params {
+        buffer : Efl.Ui.Cnp_Buffer;
+        seat : uint;
       }
-      selection_clear {
-         [[Clear the selection data from the object]]
-         params {
-            @in type: Efl.Ui.Selection_Type; [[Selection Type]]
-            @in seat: uint; [[Specified seat for multiple seats case.]]
-         }
+    }
+    selection_get {
+      [[Get the data from the object that has selection]]
+      params {
+        buffer : Efl.Ui.Cnp_Buffer;
+        seat : uint;
+        acceptable_types : iterator<string>;
       }
-      has_owner {
-         [[Determine whether the selection data has owner]]
-         params {
-            @in type: Efl.Ui.Selection_Type; [[Selection type]]
-            @in seat: uint; [[Specified seat for multiple seats case.]]
-         }
-         return: bool; [[EINA_TRUE if there is object owns selection, otherwise EINA_FALSE]]
+      return : future<Eina.Content> @move;
+    }
+    has_selection {
+      [[Determine whether the selection data has owner]]
+      params {
+        buffer : Efl.Ui.Cnp_Buffer;
+        seat : uint;
       }
-   }
-   events {
-      wm_selection,changed: Efl.Ui.Selection_Changed; [[Called when display server's selection has changed]]
-   }
+      return : bool; [[$true if there is a available selection, $false if not]]
+    }
+  }
+  implements {
+    Efl.Object.constructor;
+    Efl.Object.invalidate;
+    Efl.Object.finalize;
+  }
+  events {
+    wm_selection,changed : Efl.Ui.Wm_Selection_Changed;
+  }
 }
diff --git a/src/lib/elementary/efl_ui_selection_types.eot b/src/lib/elementary/efl_ui_selection_types.eot
deleted file mode 100644 (file)
index cbe5e0d..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-enum @beta Efl.Ui.Selection_Type
-{
-   [[Selection type]]
-   primary, [[Primary text selection (highlighted or selected text)]]
-   secondary, [[Used when primary selection is in use]]
-   dnd, [[Drag and Drop]]
-   clipboard [[Clipboard selection (ctrl+C)]]
-}
-
-enum @beta Efl.Ui.Selection_Format
-{
-   [[Selection format]]
-   targets = -1, [[For matching every possible atom]]
-   none = 0x0, [[Content is from outside of EFL]]
-   text = 0x01, [[Plain unformatted text: Used for things that don't want rich markup]]
-   markup = 0x2, [[Edje textblock markup, including inline images]]
-   image = 0x4, [[Images]]
-   vcard = 0x08, [[Vcards]]
-   html = 0x10 [[Raw HTML-like data (eg. webkit)]]
-}
-
-enum @beta Efl.Ui.Selection_Action
-{
-   [[Defines the kind of action associated with the drop data]]
-   unknown, [[Action type is unknown]]
-   copy, [[Copy the data]]
-   move, [[Move the data]]
-   private, [[Private action type]]
-   ask, [[Ask the user what to do]]
-   list, [[List the data]]
-   link, [[Link the data]]
-   description [[Describe the data]]
-}
-
-struct @beta Efl.Ui.Selection_Data
-{
-   [[Structure holding the info about selected data]]
-   pos: Eina.Position2D; [[Coordinates of the drop (DND operations only)]]
-   format: Efl.Ui.Selection_Format; [[Format of the selection]]
-   content: Eina.Slice; [[Selection data]]
-   action: Efl.Ui.Selection_Action; [[Action to perform with the data]]
-   item: Efl.Object; [[Item under the drag position. It is only available for container]]
-}
-
-function @beta Efl.Ui.Selection_Data_Ready {
-   [[Function pointer for getting selection]]
-   params {
-      @in obj: Efl.Object; [[Object which requested for the selection]]
-      @in seldata: ptr(Efl.Ui.Selection_Data); [[Selection data]]
-   }
-};
-
-struct @beta Efl.Ui.Selection_Changed
-{
-   [[Selection-changed specific information.]] // TODO: This needs to be filled in.
-   type: Efl.Ui.Selection_Type; [[Selection type]]
-   seat: int; [[The seat on which the selection changed, or NULL for "default"]]
-   display: void_ptr; [[The display connection object, NULL under X11]]
-   exist: bool; [[EINA_TRUE if the selection has an owner]]
-}
index 95c5ce5..5cc37ba 100644 (file)
@@ -757,7 +757,7 @@ _view_init(Evas_Object *obj, Efl_Ui_Tags_Data *sd)
    sd->entry = efl_add(EFL_UI_TEXTBOX_CLASS, sd->box,
                        efl_text_multiline_set(efl_added, EINA_FALSE),
                        efl_text_set(efl_added, ""),
-                       efl_ui_textbox_cnp_mode_set(efl_added, EFL_UI_SELECTION_FORMAT_MARKUP),
+                       efl_ui_textbox_cnp_dnd_mode_set(efl_added, EFL_UI_TEXTBOX_CNP_CONTENT_MARKUP),
                        efl_input_text_input_panel_autoshow_set(efl_added, EINA_FALSE),
                        efl_text_interactive_editable_set(efl_added, EINA_TRUE),
                        efl_composite_attach(obj, efl_added));
index fbe5c41..a01439d 100644 (file)
@@ -22,7 +22,6 @@
 typedef struct _Efl_Ui_Textbox_Data        Efl_Ui_Textbox_Data;
 typedef struct _Efl_Ui_Text_Rectangle   Efl_Ui_Text_Rectangle;
 typedef struct _Anchor                  Anchor;
-typedef struct _Selection_Loss_Data     Selection_Loss_Data;
 
 /**
  * Base widget smart data extended with entry instance data.
@@ -69,7 +68,7 @@ struct _Efl_Ui_Textbox_Data
         const char  *hover_style; /**< style of a hover object */
      } anchor_hover;
 
-   Efl_Ui_Selection_Format               cnp_mode;
+   const char                           *cnp_mime_type;
    Elm_Sel_Format                        drop_format;
 
    struct {
@@ -81,11 +80,7 @@ struct _Efl_Ui_Textbox_Data
         Eina_Size2D                      scroll;
         Eina_Size2D                      layout;
    } last;
-   struct
-     {
-        Eina_Future                      *primary;
-        Eina_Future                      *clipboard;
-     } sel_future;
+   Efl_Ui_Textbox_Cnp_Content            content;
    Eina_Bool                             sel_handles_enabled : 1;
    Eina_Bool                             start_handler_down : 1;
    Eina_Bool                             start_handler_shown : 1;
@@ -147,12 +142,6 @@ struct _Efl_Ui_Text_Rectangle
    Evas_Object             *obj_bg, *obj_fg, *obj;
 };
 
-struct _Selection_Loss_Data
-{
-   Eo *obj;
-   Efl_Ui_Selection_Type stype;
-};
-
 #define MY_CLASS EFL_UI_TEXTBOX_CLASS
 #define MY_CLASS_PFX efl_ui_textbox
 #define MY_CLASS_NAME "Efl.Ui.Textbox"
@@ -208,7 +197,7 @@ static void _anchors_free(Efl_Ui_Textbox_Data *sd);
 static void _selection_defer(Eo *obj, Efl_Ui_Textbox_Data *sd);
 static Eina_Position2D _decoration_calc_offset(Efl_Ui_Textbox_Data *sd);
 static void _update_text_theme(Eo *obj, Efl_Ui_Textbox_Data *sd);
-static void _efl_ui_textbox_selection_paste_type(Eo *obj, Efl_Ui_Selection_Type type);
+static void _efl_ui_textbox_selection_paste_type(Eo *obj, Efl_Ui_Textbox_Data *sd, Efl_Ui_Cnp_Buffer type);
 
 static Eina_Bool _key_action_copy(Evas_Object *obj, const char *params);
 static Eina_Bool _key_action_paste(Evas_Object *obj, const char *params);
@@ -407,16 +396,19 @@ _update_selection_handler(Eo *obj)
      }
 }
 
-static void
-_selection_data_cb(void *data EINA_UNUSED, Eo *obj,
-                   Efl_Ui_Selection_Data *sel_data)
+static Eina_Value
+_selection_data_cb(Efl_Ui_Textbox *obj, void *data EINA_UNUSED, const Eina_Value value)
 {
+   Eina_Content *content;
+   Eina_Slice slice;
    Efl_Text_Cursor *cur, *start, *end;
    Efl_Text_Change_Info info = { NULL, 0, 0, 0, 0 };
 
-   char *buf = eina_slice_strdup(sel_data->content);
-   size_t len = sel_data->content.len;
+   if (eina_value_type_get(&value) != EINA_VALUE_TYPE_CONTENT)
+     return EINA_VALUE_EMPTY;
 
+   content = eina_value_to_content(&value);
+   slice = eina_content_data_get(content);
    efl_text_interactive_selection_cursors_get(obj, &start, &end);
    if (!efl_text_cursor_equal(start, end))
      {
@@ -426,83 +418,130 @@ _selection_data_cb(void *data EINA_UNUSED, Eo *obj,
    cur = efl_text_interactive_main_cursor_get(obj);
    info.type = EFL_TEXT_CHANGE_TYPE_INSERT;
    info.position = efl_text_cursor_position_get(cur);
-   info.length = len;
-   info.content = buf;
-   if (sel_data->format == EFL_UI_SELECTION_FORMAT_MARKUP)
+   info.length = slice.len;
+   info.content = slice.mem;
+   if (eina_streq(eina_content_type_get(content), "application/x-elementary-markup"))
+     {
+        efl_text_cursor_markup_insert(cur, slice.mem);
+     }
+   else if (!strncmp(eina_content_type_get(content), "image/", strlen("image/")))
      {
-        efl_text_cursor_markup_insert(cur, buf);
+        Eina_Strbuf *result = eina_strbuf_new();
+        eina_strbuf_append_printf(result, "<item absize=240x180 href=");
+        eina_strbuf_append_slice(result, slice);
+        eina_strbuf_append_printf(result, "></item>");
+        efl_text_cursor_markup_insert(cur, eina_strbuf_string_get(result));
+        eina_strbuf_free(result);
      }
    else // TEXT
      {
-        efl_text_cursor_text_insert(cur, buf);
+        efl_text_cursor_text_insert(cur, slice.mem);
      }
    efl_event_callback_call(obj, EFL_TEXT_INTERACTIVE_EVENT_CHANGED_USER, &info);
-   free(buf);
+
+   return EINA_VALUE_EMPTY;
 }
 
-static void
-_dnd_enter_cb(void *data EINA_UNUSED,
-              Evas_Object *obj)
+static Eina_Array*
+_figure_out_types(Eo *obj EINA_UNUSED, Efl_Ui_Textbox_Data *sd)
+{
+   Eina_Array *types = eina_array_new(10);
+
+   if (sd->content & EFL_UI_TEXTBOX_CNP_CONTENT_MARKUP)
+     eina_array_push(types, "application/x-elementary-markup");
+   if (sd->content & EFL_UI_TEXTBOX_CNP_CONTENT_IMAGE)
+     {
+        eina_array_push(types, "image/png");
+        eina_array_push(types, "image/jpeg");
+        eina_array_push(types, "image/x-ms-bmp");
+        eina_array_push(types, "image/gif");
+        eina_array_push(types, "image/tiff");
+        eina_array_push(types, "image/svg+xml");
+        eina_array_push(types, "image/x-xpixmap");
+        eina_array_push(types, "image/x-tga");
+        eina_array_push(types, "image/x-portable-pixmap");
+     }
+   if (sd->content & EFL_UI_TEXTBOX_CNP_CONTENT_TEXT)
+     eina_array_push(types, "text/plain;charset=utf-8");
+   return types;
+}
+
+static Eina_Bool
+_accepting_drops(Eo *obj, Efl_Ui_Textbox_Data *sd, Eina_Accessor *mime_types)
 {
-   efl_ui_focus_util_focus(obj);
+   int i = 0;
+   const char *mime_type;
+
+   if (efl_ui_widget_disabled_get(obj)) return EINA_FALSE;
+
+   EINA_ACCESSOR_FOREACH(mime_types, i, mime_type)
+     {
+        if (sd->content & EFL_UI_TEXTBOX_CNP_CONTENT_TEXT &&
+            eina_streq(mime_type, "text/plain;charset=utf-8"))
+          return EINA_TRUE;
+
+        if (sd->content & EFL_UI_TEXTBOX_CNP_CONTENT_IMAGE &&
+            strncmp(mime_type, "image/", strlen("image/")))
+          return EINA_TRUE;
+
+        if (sd->content & EFL_UI_TEXTBOX_CNP_CONTENT_MARKUP &&
+            eina_streq(mime_type, "application/x-elementary-markup"))
+          return EINA_TRUE;
+     }
+   return EINA_FALSE;
 }
 
 static void
-_dnd_leave_cb(void *data EINA_UNUSED,
-              Evas_Object *obj EINA_UNUSED)
+_dnd_enter_cb(void *data EINA_UNUSED,
+              const Efl_Event *ev)
 {
+   Efl_Ui_Drop_Event *dnd_enter = ev->info;
+   EFL_UI_TEXT_DATA_GET(ev->object, sd);
+   if (_accepting_drops(ev->object, sd, dnd_enter->available_types))
+     efl_ui_focus_util_focus(ev->object);
 }
 
 static void
-_dnd_pos_cb(void *data EINA_UNUSED,
-            Evas_Object *obj,
-            Evas_Coord x,
-            Evas_Coord y,
-            Elm_Xdnd_Action action EINA_UNUSED)
+_dnd_pos_cb(void *data EINA_UNUSED, const Efl_Event *ev)
 {
-   int pos;
-   Eina_Rect o, e;
+   Efl_Ui_Drop_Event *dnd_pos = ev->info;
+   Eina_Position2D po, pe, pos;
+   EFL_UI_TEXT_DATA_GET(ev->object, sd);
+   int cursor_pos;
 
-   EFL_UI_TEXT_DATA_GET(obj, sd);
+   if (!_accepting_drops(ev->object, sd, dnd_pos->available_types))
+     return;
 
-   o = efl_gfx_entity_geometry_get(obj);
-   e = efl_gfx_entity_geometry_get(sd->entry_edje);
-   x = x + o.x - e.x;
-   y = y + o.y - e.y;
+   po = efl_gfx_entity_position_get(ev->object);
+   pe = efl_gfx_entity_position_get(sd->entry_edje);
+   pos.x = dnd_pos->position.x + po.x - pe.x;
+   pos.y = dnd_pos->position.y + po.x - pe.y;
 
    edje_object_part_text_cursor_coord_set
-      (sd->entry_edje, "efl.text", EDJE_CURSOR_USER, x, y);
-   pos = edje_object_part_text_cursor_pos_get
+      (sd->entry_edje, "efl.text", EDJE_CURSOR_USER, pos.x, pos.y);
+   cursor_pos = edje_object_part_text_cursor_pos_get
       (sd->entry_edje, "efl.text", EDJE_CURSOR_USER);
    edje_object_part_text_cursor_pos_set(sd->entry_edje, "efl.text",
-                                        EDJE_CURSOR_MAIN, pos);
+                                        EDJE_CURSOR_MAIN, cursor_pos);
 }
 
-static Eina_Bool
-_dnd_drop_cb(void *data EINA_UNUSED,
-              Evas_Object *obj,
-              Elm_Selection_Data *drop)
+static void
+_dnd_drop_cb(void *data EINA_UNUSED, const Efl_Event *ev)
 {
-   Eina_Bool rv;
-
-   EFL_UI_TEXT_DATA_GET(obj, sd);
+   Efl_Ui_Drop_Event *drop = ev->info;
+   Eina_Future *future;
+   Eina_Array *types;
 
-   rv = edje_object_part_text_cursor_coord_set
-       (sd->entry_edje, "efl.text", EDJE_CURSOR_MAIN, drop->x, drop->y);
+   EFL_UI_TEXT_DATA_GET(ev->object, sd);
+   types = _figure_out_types(ev->object, sd);
 
-   if (!rv) WRN("Warning: Failed to position cursor: paste anyway");
+   if (!_accepting_drops(ev->object, sd, drop->available_types))
+     return;
 
-   //rv = _selection_data_cb(NULL, obj, drop);
+   future = efl_ui_dnd_drop_data_get(ev->object, 0, eina_array_iterator_new(types));
+   eina_array_free(types);
 
-   return rv;
-}
-
-static Elm_Sel_Format
-_get_drop_format(Evas_Object *obj)
-{
-   if (efl_text_interactive_editable_get(obj) && (efl_text_multiline_get(obj)) && (!efl_text_password_get(obj)) && (!efl_ui_widget_disabled_get(obj)))
-     return EFL_UI_SELECTION_FORMAT_MARKUP | EFL_UI_SELECTION_FORMAT_IMAGE;
-   return EFL_UI_SELECTION_FORMAT_MARKUP;
+   efl_future_then(ev->object, future, _selection_data_cb);
 }
 
 /* we can't reuse layout's here, because it's on entry_edje only */
@@ -516,12 +555,6 @@ _efl_ui_textbox_efl_ui_widget_disabled_set(Eo *obj, Efl_Ui_Textbox_Data *sd, Ein
 
    efl_ui_widget_disabled_set(efl_super(obj, MY_CLASS), disabled);
 
-   elm_drop_target_del(obj, sd->drop_format,
-                       _dnd_enter_cb, NULL,
-                       _dnd_leave_cb, NULL,
-                       _dnd_pos_cb, NULL,
-                       _dnd_drop_cb, NULL);
-
    emission = efl_ui_widget_disabled_get(obj) ? "efl,state,disabled" : "efl,state,enabled";
    efl_layout_signal_emit(sd->entry_edje, emission, "efl");
    if (sd->scroll)
@@ -529,15 +562,6 @@ _efl_ui_textbox_efl_ui_widget_disabled_set(Eo *obj, Efl_Ui_Textbox_Data *sd, Ein
         efl_ui_scrollable_scroll_freeze_set(obj, efl_ui_widget_disabled_get(obj));
      }
 
-   if (!efl_ui_widget_disabled_get(obj))
-     {
-        sd->drop_format = _get_drop_format(obj);
-        elm_drop_target_add(obj, sd->drop_format,
-                            _dnd_enter_cb, NULL,
-                            _dnd_leave_cb, NULL,
-                            _dnd_pos_cb, NULL,
-                            _dnd_drop_cb, NULL);
-     }
    _update_text_theme(obj, sd);
 }
 
@@ -804,83 +828,36 @@ _popup_position(Evas_Object *obj)
    efl_gfx_entity_geometry_set(sd->popup, EINA_RECT(r.x + cx, r.y + cy, m.w, m.h));
 }
 
-static Eina_Value
-_selection_lost_cb(void *data, const Eina_Value value)
+static void
+_selection_lost_cb(void *data EINA_UNUSED, const Efl_Event *ev)
 {
-   Selection_Loss_Data *sdata = data;
-    EFL_UI_TEXT_DATA_GET(sdata->obj, sd);
+   Efl_Ui_Wm_Selection_Changed *changed = ev->info;
+   EFL_UI_TEXT_DATA_GET(ev->object, sd);
 
-   efl_text_interactive_all_unselect(sdata->obj);
-   _selection_defer(sdata->obj, sd);
-   switch (sdata->stype)
+   if (changed->buffer == EFL_UI_CNP_BUFFER_SELECTION && changed->caused_by != ev->object)
      {
-      case EFL_UI_SELECTION_TYPE_CLIPBOARD:
-         sd->sel_future.clipboard = NULL;
-         break;
-      case EFL_UI_SELECTION_TYPE_PRIMARY:
-      default:
-         sd->sel_future.primary = NULL;
-         break;
+        efl_text_interactive_all_unselect(ev->object);
+        _selection_defer(ev->object, sd);
      }
-
-   return value;
 }
 
 static void
-_selection_store(Efl_Ui_Selection_Type seltype,
+_selection_store(Efl_Ui_Cnp_Buffer buffer,
                  Evas_Object *obj)
 {
    char *sel;
    Efl_Text_Cursor *start, *end;
-   Efl_Ui_Selection_Format selformat = EFL_UI_SELECTION_FORMAT_MARKUP;
-   Eina_Slice slice;
-   Selection_Loss_Data *ldata;
-   Eina_Future *f;
-
-   EFL_UI_TEXT_DATA_GET(obj, sd);
+   Eina_Content *content;
 
    efl_text_interactive_selection_cursors_get(obj, &start, &end);
    sel = efl_text_cursor_range_markup_get(start, end);
 
    if ((!sel) || (!sel[0])) return;  /* avoid deleting our own selection */
 
-   slice.len = strlen(sel);
-   slice.mem = sel;
-
-   switch (seltype)
-     {
-      case EFL_UI_SELECTION_TYPE_CLIPBOARD:
-         if (sd->sel_future.clipboard)
-           {
-              eina_future_cancel(sd->sel_future.clipboard);
-           }
-
-         f = sd->sel_future.clipboard = efl_ui_selection_set(obj, seltype,
-               selformat, slice, 1);
-         break;
-
-      case EFL_UI_SELECTION_TYPE_PRIMARY:
-      default:
-         if (sd->sel_future.primary)
-           {
-              eina_future_cancel(sd->sel_future.primary);
-           }
-
-         f = sd->sel_future.primary = efl_ui_selection_set(obj, seltype,
-               selformat, slice, 1);
-         break;
-     }
+   content = eina_content_new((Eina_Slice)EINA_SLICE_STR_FULL(sel), "application/x-elementary-markup");
 
-   ldata = calloc(1, sizeof(Selection_Loss_Data));
-   if (!ldata) goto end;
+   efl_ui_selection_set(obj, buffer, content, 0);
 
-   ldata->obj = obj;
-   eina_future_then_easy(f, _selection_lost_cb, NULL, NULL, EINA_VALUE_TYPE_UINT, ldata);
-
-   //if (seltype == EFL_UI_SELECTION_TYPE_CLIPBOARD)
-   //  eina_stringshare_replace(&sd->cut_sel, sel);
-
-end:
    free(sel);
 }
 
@@ -956,7 +933,7 @@ _menu_call(Evas_Object *obj)
      {
         Eina_Bool ownersel;
 
-        ownersel = elm_selection_selection_has_owner(obj);
+        ownersel = elm_cnp_clipboard_selection_has_owner(obj);
         /* prevent stupid blank hoversel */
         if (efl_text_interactive_have_selection_get(obj) && efl_text_password_get(obj)) return;
         if (_elm_config->desktop_entry && (!efl_text_interactive_have_selection_get(obj)) && ((!efl_text_interactive_editable_get(obj)) || (!ownersel)))
@@ -1133,7 +1110,7 @@ _mouse_down_cb(void *data, const Efl_Event *event)
 
    if (ev->button == 2)
      {
-        _efl_ui_textbox_selection_paste_type(data, EFL_UI_SELECTION_TYPE_PRIMARY);
+        _efl_ui_textbox_selection_paste_type(data, sd, EFL_UI_CNP_BUFFER_SELECTION);
      }
 
     /* If right button is pressed and context menu disabled is true,
@@ -1654,10 +1631,18 @@ _efl_ui_textbox_efl_object_constructor(Eo *obj, Efl_Ui_Textbox_Data *sd)
 {
    Eo *text_obj;
 
+   sd->content = EFL_UI_TEXTBOX_CNP_CONTENT_MARKUP;
+
    ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd, NULL);
 
    if (!elm_widget_theme_klass_get(obj))
      elm_widget_theme_klass_set(obj, "text");
+
+   efl_event_callback_add(obj, EFL_UI_SELECTION_EVENT_WM_SELECTION_CHANGED, _selection_lost_cb, NULL);
+   efl_event_callback_add(obj, EFL_UI_DND_EVENT_DROP_ENTERED, _dnd_enter_cb, NULL);
+   efl_event_callback_add(obj, EFL_UI_DND_EVENT_DROP_POSITION_CHANGED, _dnd_pos_cb, NULL);
+   efl_event_callback_add(obj, EFL_UI_DND_EVENT_DROP_DROPPED, _dnd_drop_cb, NULL);
+
    obj = efl_constructor(efl_super(obj, MY_CLASS));
    efl_event_callback_add(obj, EFL_INPUT_EVENT_LONGPRESSED, _long_press_cb, obj);
 
@@ -1674,11 +1659,9 @@ _efl_ui_textbox_efl_object_constructor(Eo *obj, Efl_Ui_Textbox_Data *sd)
    efl_composite_attach(obj, text_obj);
 
    sd->entry_edje = wd->resize_obj;
-   sd->cnp_mode = EFL_UI_SELECTION_FORMAT_TEXT;
    sd->context_menu_enabled = EINA_TRUE;
    efl_text_interactive_editable_set(obj, EINA_TRUE);
    efl_text_interactive_selection_allowed_set(obj, EINA_TRUE);
-   sd->drop_format = EFL_UI_SELECTION_FORMAT_MARKUP | EFL_UI_SELECTION_FORMAT_IMAGE;
    sd->last.scroll = EINA_SIZE2D(0, 0);
    sd->sel_handles_enabled = EINA_FALSE;
 
@@ -1691,12 +1674,6 @@ _efl_ui_textbox_efl_object_finalize(Eo *obj,
 {
    obj = efl_finalize(efl_super(obj, MY_CLASS));
 
-   elm_drop_target_add(obj, sd->drop_format,
-                       _dnd_enter_cb, NULL,
-                       _dnd_leave_cb, NULL,
-                       _dnd_pos_cb, NULL,
-                       _dnd_drop_cb, NULL);
-
    efl_access_object_role_set(obj, EFL_ACCESS_ROLE_ENTRY);
 
    _update_guide_text(obj, sd);
@@ -1805,11 +1782,6 @@ _efl_ui_textbox_efl_text_format_password_set(Eo *obj, Efl_Ui_Textbox_Data *sd, E
      efl_text_replacement_char_set(obj, ENTRY_PASSWORD_MASK_CHARACTER_UTF8);
    efl_text_password_set(sd->text_obj, password);
 
-   elm_drop_target_del(obj, sd->drop_format,
-                       _dnd_enter_cb, NULL,
-                       _dnd_leave_cb, NULL,
-                       _dnd_pos_cb, NULL,
-                       _dnd_drop_cb, NULL);
    if (password)
      {
         efl_text_multiline_set(obj, EINA_FALSE);
@@ -1819,12 +1791,6 @@ _efl_ui_textbox_efl_text_format_password_set(Eo *obj, Efl_Ui_Textbox_Data *sd, E
    else
      {
         efl_text_multiline_set(obj, EINA_TRUE);
-        sd->drop_format = _get_drop_format(obj);
-        elm_drop_target_add(obj, sd->drop_format,
-                            _dnd_enter_cb, NULL,
-                            _dnd_leave_cb, NULL,
-                            _dnd_pos_cb, NULL,
-                            _dnd_drop_cb, NULL);
         efl_input_text_input_content_type_set(obj, ((efl_input_text_input_content_type_get(obj) | EFL_INPUT_TEXT_CONTENT_TYPE_AUTO_COMPLETE) & ~EFL_INPUT_TEXT_CONTENT_TYPE_SENSITIVE_DATA));
         efl_access_object_role_set(obj, EFL_ACCESS_ROLE_ENTRY);
      }
@@ -1891,19 +1857,8 @@ _efl_ui_textbox_efl_text_interactive_editable_set(Eo *obj, Efl_Ui_Textbox_Data *
    efl_ui_widget_theme_apply(obj);
    efl_ui_widget_focus_allow_set(obj, editable);
 
-   elm_drop_target_del(obj, sd->drop_format,
-                       _dnd_enter_cb, NULL,
-                       _dnd_leave_cb, NULL,
-                       _dnd_pos_cb, NULL,
-                       _dnd_drop_cb, NULL);
    if (editable)
      {
-        sd->drop_format = _get_drop_format(obj);
-        elm_drop_target_add(obj, sd->drop_format,
-                            _dnd_enter_cb, NULL,
-                            _dnd_leave_cb, NULL,
-                            _dnd_pos_cb, NULL,
-                            _dnd_drop_cb, NULL);
         if (sd->cursor)
           {
              efl_gfx_entity_visible_set(sd->cursor, EINA_TRUE);
@@ -1961,7 +1916,7 @@ _efl_ui_textbox_selection_cut(Eo *obj, Efl_Ui_Textbox_Data *sd)
 
    /*In password mode, cut will remove text only*/
    if (!efl_text_password_get(obj))
-     _selection_store(EFL_UI_SELECTION_TYPE_CLIPBOARD, obj);
+     _selection_store(EFL_UI_CNP_BUFFER_COPY_AND_PASTE, obj);
    efl_text_interactive_selection_cursors_get(obj, &start, &end);
 
    start_pos = efl_text_cursor_position_get(start);
@@ -1993,25 +1948,27 @@ _efl_ui_textbox_selection_copy(Eo *obj, Efl_Ui_Textbox_Data *sd)
         efl_layout_signal_emit(sd->entry_edje, "efl,state,select,off", "efl");
         efl_ui_widget_scroll_hold_pop(obj);
      }
-   _selection_store(EFL_UI_SELECTION_TYPE_CLIPBOARD, obj);
+   _selection_store(EFL_UI_CNP_BUFFER_COPY_AND_PASTE, obj);
    efl_event_callback_call(obj, EFL_UI_TEXTBOX_EVENT_SELECTION_COPY, NULL);
 }
-
 static void
-_efl_ui_textbox_selection_paste_type(Eo *obj, Efl_Ui_Selection_Type type)
+_efl_ui_textbox_selection_paste_type(Eo *obj, Efl_Ui_Textbox_Data *sd, Efl_Ui_Cnp_Buffer type)
 {
-   Efl_Ui_Selection_Format formats = EFL_UI_SELECTION_FORMAT_TEXT | EFL_UI_SELECTION_FORMAT_MARKUP;
+   Eina_Future *future;
+   Eina_Array *types = _figure_out_types(obj, sd);
 
-   efl_ui_selection_get(obj, type, formats,
-         NULL, _selection_data_cb, NULL, 1);
+   future = efl_ui_selection_get(obj, type, 0, eina_array_iterator_new(types));
+
+   efl_future_then(obj, future, _selection_data_cb);
 
    efl_event_callback_call(obj, EFL_UI_TEXTBOX_EVENT_SELECTION_PASTE, NULL);
+   eina_array_free(types);
 }
 
 EOLIAN static void
-_efl_ui_textbox_selection_paste(Eo *obj, Efl_Ui_Textbox_Data *sd EINA_UNUSED)
+_efl_ui_textbox_selection_paste(Eo *obj, Efl_Ui_Textbox_Data *sd)
 {
-   _efl_ui_textbox_selection_paste_type(obj, EFL_UI_SELECTION_TYPE_CLIPBOARD);
+   _efl_ui_textbox_selection_paste_type(obj, sd, EFL_UI_CNP_BUFFER_COPY_AND_PASTE);
 }
 
 EOLIAN static void
@@ -2028,44 +1985,15 @@ _efl_ui_textbox_context_menu_enabled_get(const Eo *obj EINA_UNUSED, Efl_Ui_Textb
 }
 
 EOLIAN static void
-_efl_ui_textbox_cnp_mode_set(Eo *obj, Efl_Ui_Textbox_Data *sd, Efl_Ui_Selection_Format cnp_mode)
+_efl_ui_textbox_cnp_dnd_mode_set(Eo *obj EINA_UNUSED, Efl_Ui_Textbox_Data *sd, Efl_Ui_Textbox_Cnp_Content content)
 {
-   Elm_Sel_Format dnd_format = EFL_UI_SELECTION_FORMAT_MARKUP;
-
-   if (cnp_mode != EFL_UI_SELECTION_FORMAT_TARGETS)
-     {
-        if (cnp_mode & EFL_UI_SELECTION_FORMAT_VCARD)
-          ERR("VCARD format not supported for copy & paste!");
-        else if (cnp_mode & EFL_UI_SELECTION_FORMAT_HTML)
-          ERR("HTML format not supported for copy & paste!");
-        cnp_mode &= ~EFL_UI_SELECTION_FORMAT_VCARD;
-        cnp_mode &= ~EFL_UI_SELECTION_FORMAT_HTML;
-     }
-
-   if (sd->cnp_mode == cnp_mode) return;
-   sd->cnp_mode = cnp_mode;
-   if (sd->cnp_mode == EFL_UI_SELECTION_FORMAT_TEXT)
-     dnd_format = EFL_UI_SELECTION_FORMAT_TEXT;
-   else if (cnp_mode == EFL_UI_SELECTION_FORMAT_IMAGE)
-     dnd_format |= EFL_UI_SELECTION_FORMAT_IMAGE;
-
-   elm_drop_target_del(obj, sd->drop_format,
-                       _dnd_enter_cb, NULL,
-                       _dnd_leave_cb, NULL,
-                       _dnd_pos_cb, NULL,
-                       _dnd_drop_cb, NULL);
-   sd->drop_format = dnd_format;
-   elm_drop_target_add(obj, sd->drop_format,
-                       _dnd_enter_cb, NULL,
-                       _dnd_leave_cb, NULL,
-                       _dnd_pos_cb, NULL,
-                       _dnd_drop_cb, NULL);
+   sd->content = content;
 }
 
-EOLIAN static Efl_Ui_Selection_Format
-_efl_ui_textbox_cnp_mode_get(const Eo *obj EINA_UNUSED, Efl_Ui_Textbox_Data *sd)
+EOLIAN static Efl_Ui_Textbox_Cnp_Content
+_efl_ui_textbox_cnp_dnd_mode_get(const Eo *obj EINA_UNUSED, Efl_Ui_Textbox_Data *sd)
 {
-   return sd->cnp_mode;
+   return sd->content;
 }
 
 EOLIAN static void
@@ -3297,7 +3225,7 @@ _efl_ui_textbox_selection_changed_cb(void *data, const Efl_Event *event EINA_UNU
    Eo *obj = data;
    EFL_UI_TEXT_DATA_GET(obj, sd);
    _edje_signal_emit(sd, "selection,changed", "efl.text");
-   _selection_store(EFL_UI_SELECTION_TYPE_PRIMARY, obj);
+   _selection_store(EFL_UI_CNP_BUFFER_SELECTION, obj);
    _selection_defer(obj, sd);
 }
 
index da38f89..29f5a62 100644 (file)
@@ -1,3 +1,10 @@
+enum Efl.Ui.Textbox_Cnp_Content {
+   Nothing = 0, [[You can paste or drop nothing]]
+   Text = 1, [[You can paste normal Text]]
+   Markup = 3, [[You can paste Markup (Normal text is also just markup)]]
+   Image = 4, [[You can paste Images]]
+}
+
 class @beta Efl.Ui.Textbox extends Efl.Ui.Layout_Base implements Efl.Input.Clickable,
                  Efl.Access.Text, Efl.Access.Editable.Text
    composites
@@ -31,8 +38,7 @@ class @beta Efl.Ui.Textbox extends Efl.Ui.Layout_Base implements Efl.Input.Click
             enabled: bool; [[$true to enable the contextual menu.]]
          }
       }
-      @property cnp_mode @beta {
-         /* FIXME: Efl.Ui.Selection_Format does not allow markup without images! */
+      @property cnp_dnd_mode @beta {
          [[Control pasting of text and images for the widget.
 
            Normally the entry allows both text and images to be pasted.
@@ -44,7 +50,7 @@ class @beta Efl.Ui.Textbox extends Efl.Ui.Layout_Base implements Efl.Input.Click
          get {
          }
          values {
-            format: Efl.Ui.Selection_Format; [[Format for copy & paste.]]
+            allowed_formats : Efl.Ui.Textbox_Cnp_Content; [[Format for cnp]]
          }
       }
       @property selection_handles_enabled {
index cd84eb7..72a41bb 100644 (file)
@@ -257,6 +257,9 @@ struct _Efl_Ui_Win_Data
    int          response;
    Eina_Bool    req_wh : 1;
    Eina_Bool    req_xy : 1;
+   Eina_Array   *selection_changed;
+   Eina_Array   *planned_changes;
+   Eina_Inarray *drop_target;
 
    struct {
       short     pointer_move;
@@ -483,6 +486,8 @@ static void _elm_win_frame_style_update(Efl_Ui_Win_Data *sd, Eina_Bool force_emi
 static inline void _elm_win_need_frame_adjust(Efl_Ui_Win_Data *sd, const char *engine);
 static void _elm_win_resize_objects_eval(Evas_Object *obj, Eina_Bool force_resize);
 static void _elm_win_frame_obj_update(Efl_Ui_Win_Data *sd, Eina_Bool force);
+static void _ee_backbone_init(Efl_Ui_Win *obj, Efl_Ui_Win_Data *pd);
+static void _ee_backbone_shutdown(Efl_Ui_Win *obj, Efl_Ui_Win_Data *pd);
 
 static inline Efl_Ui_Win_Type
 _elm_win_type_to_efl_ui_win_type(Elm_Win_Type type)
@@ -6896,6 +6901,7 @@ _efl_ui_win_efl_object_finalize(Eo *obj, Efl_Ui_Win_Data *sd)
             efl_file_mmap_get(efl_super(efl_part(obj, "background"), EFL_UI_WIN_PART_CLASS)))
           efl_file_load(efl_part(obj, "background"));
      }
+   _ee_backbone_init(obj, sd);
    return obj;
 }
 
@@ -6935,6 +6941,8 @@ _efl_ui_win_efl_object_destructor(Eo *obj, Efl_Ui_Win_Data *pd EINA_UNUSED)
    if (pd->finalize_future)
      eina_future_cancel(pd->finalize_future);
 
+   _ee_backbone_shutdown(obj, pd);
+
    efl_destructor(efl_super(obj, MY_CLASS));
 
    efl_unref(pd->provider);
@@ -6951,6 +6959,7 @@ _efl_ui_win_efl_object_constructor(Eo *obj, Efl_Ui_Win_Data *pd)
    pd->provider = efl_add_ref(EFL_UI_FOCUS_PARENT_PROVIDER_STANDARD_CLASS, NULL);
    pd->profile.available = eina_array_new(4);
    pd->max_w = pd->max_h = -1;
+   pd->planned_changes = eina_array_new(10);
 
    // For bindings: if no parent, allow simple unref
    if (!efl_parent_get(obj))
@@ -10766,6 +10775,249 @@ _efl_ui_win_efl_canvas_object_paragraph_direction_set(Eo *obj, Efl_Ui_Win_Data *
  * END *
  *******/
 
+/* What here follows is code that implements the glue between ecore evas and efl_ui* side */
+typedef struct {
+   Eo *obj;
+   Eina_Bool currently_inside;
+} Ui_Dnd_Target;
+
+static inline Efl_Ui_Cnp_Buffer
+_ui_buffer_get(Ecore_Evas_Selection_Buffer buffer)
+{
+   if (buffer == ECORE_EVAS_SELECTION_BUFFER_SELECTION_BUFFER)
+     return EFL_UI_CNP_BUFFER_SELECTION;
+   else if (buffer == ECORE_EVAS_SELECTION_BUFFER_COPY_AND_PASTE_BUFFER)
+     return EFL_UI_CNP_BUFFER_COPY_AND_PASTE;
+
+   return -1;
+}
+
+void
+_register_selection_changed(Efl_Ui_Selection *selection)
+{
+   ELM_WIN_DATA_GET(efl_provider_find(selection, EFL_UI_WIN_CLASS), pd);
+
+   eina_array_push(pd->planned_changes, selection);
+}
+
+static Eina_Bool
+_remove_object(void *data, void *gdata)
+{
+   if (data == gdata)
+     return EINA_FALSE;
+   return EINA_TRUE;
+}
+
+static void
+_selection_changed_cb(Ecore_Evas *ee, unsigned int seat, Ecore_Evas_Selection_Buffer selection)
+{
+   Efl_Ui_Win_Data *pd = _elm_win_associate_get(ee);
+   Efl_Ui_Wm_Selection_Changed changed = {
+      .seat = seat,
+      .buffer = _ui_buffer_get(selection),
+      .caused_by = eina_array_count(pd->planned_changes) > 0 ? eina_array_data_get(pd->planned_changes, 0) : NULL,
+   };
+
+   for (unsigned int i = 0; i < eina_array_count(pd->selection_changed); ++i)
+     {
+        Eo *obj = eina_array_data_get(pd->selection_changed, i);
+
+        efl_event_callback_call(obj, EFL_UI_SELECTION_EVENT_WM_SELECTION_CHANGED, &changed);
+     }
+
+   if (changed.caused_by)
+     eina_array_remove(pd->planned_changes, _remove_object, changed.caused_by);
+}
+
+static void
+_motion_cb(Ecore_Evas *ee, unsigned int seat, Eina_Position2D p)
+{
+   Efl_Ui_Win_Data *pd = _elm_win_associate_get(ee);
+   for (unsigned int i = 0; i < eina_inarray_count(pd->drop_target); ++i)
+     {
+        Ui_Dnd_Target *target = eina_inarray_nth(pd->drop_target, i);
+        Eina_Rect rect = efl_gfx_entity_geometry_get(target->obj);
+        Eina_Bool inside = eina_rectangle_coords_inside(&rect.rect, p.x, p.y);
+        Efl_Ui_Drop_Event ev = {p, seat, ecore_evas_drop_available_types_get(ee, seat)};
+
+        if (target->currently_inside && !inside)
+          {
+             target->currently_inside = EINA_FALSE;
+             efl_event_callback_call(target->obj, EFL_UI_DND_EVENT_DROP_LEFT, &ev);
+          }
+        else if (!target->currently_inside && inside)
+          {
+             target->currently_inside = EINA_TRUE;
+             efl_event_callback_call(target->obj, EFL_UI_DND_EVENT_DROP_ENTERED, &ev);
+          }
+        else if (target->currently_inside && inside)
+          {
+             efl_event_callback_call(target->obj, EFL_UI_DND_EVENT_DROP_POSITION_CHANGED, &ev);
+          }
+        eina_accessor_free(ev.available_types);
+     }
+}
+
+static void
+_enter_state_change_cb(Ecore_Evas *ee, unsigned int seat EINA_UNUSED, Eina_Position2D p, Eina_Bool move_inside)
+{
+   Efl_Ui_Win_Data *pd = _elm_win_associate_get(ee);
+   for (unsigned int i = 0; i < eina_inarray_count(pd->drop_target); ++i)
+     {
+        Ui_Dnd_Target *target = eina_inarray_nth(pd->drop_target, i);
+        Eina_Rect rect = efl_gfx_entity_geometry_get(target->obj);
+        Eina_Bool inside = eina_rectangle_coords_inside(&rect.rect, p.x, p.y);
+        Efl_Ui_Drop_Event ev = {p, seat, ecore_evas_drop_available_types_get(ee, seat)};
+
+        if (inside && move_inside)
+          {
+             target->currently_inside = EINA_TRUE;
+             efl_event_callback_call(target->obj, EFL_UI_DND_EVENT_DROP_ENTERED, &ev);
+          }
+        else if (!move_inside && !target->currently_inside)
+          {
+             target->currently_inside = EINA_FALSE;
+             efl_event_callback_call(target->obj, EFL_UI_DND_EVENT_DROP_LEFT, &ev);
+          }
+     }
+}
+
+static void
+_drop_cb(Ecore_Evas *ee, unsigned int seat EINA_UNUSED, Eina_Position2D p, const char *action)
+{
+   Eina_List *itr, *top_objects_list = NULL;
+   Efl_Ui_Win_Data *pd = _elm_win_associate_get(ee);
+   Eina_Array *tmp = eina_array_new(10);
+   Eo *top_obj;
+
+   for (unsigned int i = 0; i < eina_inarray_count(pd->drop_target); ++i)
+     {
+        Ui_Dnd_Target *target = eina_inarray_nth(pd->drop_target, i);
+        Eina_Rect rect = efl_gfx_entity_geometry_get(target->obj);
+        Eina_Bool inside = eina_rectangle_coords_inside(&rect.rect, p.x, p.y);
+
+        if (inside)
+          {
+             EINA_SAFETY_ON_FALSE_GOTO(target->currently_inside, end);
+             eina_array_push(tmp, target->obj);
+          }
+     }
+
+   /* We retrieve the (non-smart) objects pointed by (px, py) */
+   top_objects_list = evas_tree_objects_at_xy_get(ecore_evas_get(ee), NULL, p.x, p.y);
+   /* 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)
+          {
+             unsigned int out_idx;
+             if (!eina_array_find(tmp, object, &out_idx))
+               {
+                  object = evas_object_smart_parent_get(object);
+               }
+             else
+               {
+                  Efl_Ui_Drop_Dropped_Event ev = {{p, seat, ecore_evas_drop_available_types_get(ee, seat)}, action};
+                  efl_event_callback_call(object, EFL_UI_DND_EVENT_DROP_DROPPED, &ev);
+                  goto end;
+               }
+          }
+     }
+end:
+   eina_list_free(top_objects_list);
+   eina_array_free(tmp);
+}
+
+static void
+_ee_backbone_init(Efl_Ui_Win *obj EINA_UNUSED, Efl_Ui_Win_Data *pd)
+{
+   pd->selection_changed = eina_array_new(1);
+   pd->drop_target = eina_inarray_new(sizeof(Ui_Dnd_Target), 1);
+
+   ecore_evas_callback_selection_changed_set(pd->ee, _selection_changed_cb);
+   ecore_evas_callback_drop_drop_set(pd->ee, _drop_cb);
+   ecore_evas_callback_drop_motion_set(pd->ee, _motion_cb);
+   ecore_evas_callback_drop_state_changed_set(pd->ee, _enter_state_change_cb);
+}
+
+static void
+_ee_backbone_shutdown(Efl_Ui_Win *obj EINA_UNUSED, Efl_Ui_Win_Data *pd)
+{
+   ecore_evas_callback_selection_changed_set(pd->ee, NULL);
+   ecore_evas_callback_drop_drop_set(pd->ee, NULL);
+   ecore_evas_callback_drop_motion_set(pd->ee, NULL);
+   ecore_evas_callback_drop_state_changed_set(pd->ee, NULL);
+
+   eina_array_free(pd->selection_changed);
+   pd->selection_changed = NULL;
+   eina_inarray_free(pd->drop_target);
+   pd->drop_target = NULL;
+
+}
+
+static Eina_Bool
+_remove(void *data, void *gdata)
+{
+   if (data == gdata)
+     return EINA_FALSE;
+   return EINA_TRUE;
+}
+
+void
+_drop_event_register(Eo *obj)
+{
+   Ui_Dnd_Target target = {obj, EINA_FALSE};
+   Efl_Ui_Win_Data *pd = efl_data_scope_safe_get(efl_provider_find(obj, MY_CLASS), MY_CLASS);
+   EINA_SAFETY_ON_NULL_RETURN(pd);
+
+   eina_inarray_push(pd->drop_target, &target);
+}
+
+void
+_drop_event_unregister(Eo *obj)
+{
+   int idx = -1;
+   Efl_Ui_Win_Data *pd = efl_data_scope_safe_get(efl_provider_find(obj, MY_CLASS), MY_CLASS);
+
+   for (unsigned int i = 0; i < eina_inarray_count(pd->drop_target); ++i)
+     {
+        Ui_Dnd_Target *target = eina_inarray_nth(pd->drop_target, i);
+        if (target->obj == obj)
+          {
+             //FIXME emit drop
+             target->currently_inside = EINA_FALSE;
+             idx = i;
+          }
+     }
+   if (idx != -1)
+     eina_inarray_remove_at(pd->drop_target, idx);
+}
+
+void
+_selection_changed_event_register(Eo *obj)
+{
+   Efl_Ui_Win_Data *pd = efl_data_scope_safe_get(efl_provider_find(obj, MY_CLASS), MY_CLASS);
+
+   eina_array_push(pd->selection_changed, obj);
+}
+void
+_selection_changed_event_unregister(Eo *obj)
+{
+   Efl_Ui_Win_Data *pd = efl_data_scope_safe_get(efl_provider_find(obj, MY_CLASS), MY_CLASS);
+
+   eina_array_remove(pd->selection_changed, _remove, obj);
+}
 /* Internal EO APIs and hidden overrides */
 
 ELM_WIDGET_KEY_DOWN_DEFAULT_IMPLEMENT(efl_ui_win, Efl_Ui_Win_Data)
diff --git a/src/lib/elementary/elm_cnp.c b/src/lib/elementary/elm_cnp.c
new file mode 100644 (file)
index 0000000..cf1f0ee
--- /dev/null
@@ -0,0 +1,244 @@
+#ifdef HAVE_CONFIG_H
+# include "elementary_config.h"
+#endif
+
+#include <Elementary.h>
+#include <Ecore_Evas.h>
+
+#include "elm_priv.h"
+#include "elm_entry_eo.h"
+
+static inline Ecore_Evas_Selection_Buffer
+_elm_sel_type_to_ee_type(Elm_Sel_Type type)
+{
+   if (type == ELM_SEL_TYPE_PRIMARY)
+     return ECORE_EVAS_SELECTION_BUFFER_SELECTION_BUFFER;
+   if (type == ELM_SEL_TYPE_XDND)
+     return ECORE_EVAS_SELECTION_BUFFER_DRAG_AND_DROP_BUFFER;
+   if (type == ELM_SEL_TYPE_CLIPBOARD)
+     return ECORE_EVAS_SELECTION_BUFFER_COPY_AND_PASTE_BUFFER;
+   return ECORE_EVAS_SELECTION_BUFFER_LAST;
+}
+
+static inline Eina_Array*
+_elm_sel_format_to_mime_type(Elm_Sel_Format format)
+{
+   Eina_Array *ret = eina_array_new(10);
+   if (format & ELM_SEL_FORMAT_TEXT)
+     eina_array_push(ret, "text/plain;charset=utf-8");
+   if (format & ELM_SEL_FORMAT_MARKUP)
+      eina_array_push(ret, "application/x-elementary-markup");
+   if (format & ELM_SEL_FORMAT_IMAGE)
+     {
+        eina_array_push(ret, "image/png");
+        eina_array_push(ret, "image/jpeg");
+        eina_array_push(ret, "image/x-ms-bmp");
+        eina_array_push(ret, "image/gif");
+        eina_array_push(ret, "image/tiff");
+        eina_array_push(ret, "image/svg+xml");
+        eina_array_push(ret, "image/x-xpixmap");
+        eina_array_push(ret, "image/x-tga");
+        eina_array_push(ret, "image/x-portable-pixmap");
+     }
+   if (format & ELM_SEL_FORMAT_VCARD)
+     eina_array_push(ret, "text/vcard");
+   if (format & ELM_SEL_FORMAT_HTML)
+     eina_array_push(ret, "application/xhtml+xml");
+
+   if (eina_array_count(ret) == 0)
+     ERR("Specified mime type is not available");
+
+   return ret;
+}
+
+static inline const Elm_Sel_Format
+_mime_type_to_elm_sel_format(const char *mime_type)
+{
+   if (eina_streq(mime_type, "text/vcard"))
+     return ELM_SEL_FORMAT_VCARD;
+   else if (eina_streq(mime_type, "application/x-elementary-markup"))
+     return ELM_SEL_FORMAT_MARKUP;
+   else if (eina_streq(mime_type, "application/xhtml+xml"))
+     return ELM_SEL_FORMAT_HTML;
+   else if (!strncmp(mime_type, "text/", strlen("text/")))
+     return ELM_SEL_FORMAT_TEXT;
+   else if (!strncmp(mime_type, "image/", strlen("image/")))
+     return ELM_SEL_FORMAT_IMAGE;
+
+   return ELM_SEL_FORMAT_NONE;
+}
+
+static int
+_default_seat(const Eo *obj)
+{
+   return evas_device_seat_id_get(evas_default_device_get(evas_object_evas_get(obj), EFL_INPUT_DEVICE_TYPE_SEAT));
+}
+
+EAPI Eina_Bool
+elm_cnp_selection_set(Evas_Object *obj, Elm_Sel_Type selection,
+                                     Elm_Sel_Format format,
+                                     const void *buf, size_t buflen)
+{
+   Eina_Content *content;
+   Ecore_Evas *ee;
+   const char *mime_type;
+   Eina_Slice data;
+   Eina_Array *tmp;
+
+   if (format == ELM_SEL_FORMAT_TEXT && ((char*)buf)[buflen - 1] != '\0')
+     {
+        data.mem = eina_memdup((unsigned char *)buf, buflen, EINA_TRUE);
+        data.len = buflen + 1;
+     }
+   else
+     {
+        data.mem = buf;
+        data.len = buflen;
+     }
+
+   ee = ecore_evas_ecore_evas_get(evas_object_evas_get(obj));
+
+   tmp = _elm_sel_format_to_mime_type(format);
+   if (eina_array_count(tmp) != 1)
+     {
+        ERR("You cannot specify more than one format when setting selection");
+     }
+   mime_type = eina_array_data_get(tmp, 0);
+   content = eina_content_new(data, mime_type);
+   _register_selection_changed(obj);
+
+   return ecore_evas_selection_set(ee, _default_seat(obj), _elm_sel_type_to_ee_type(selection), content);
+}
+
+EAPI Eina_Bool
+elm_object_cnp_selection_clear(Evas_Object *obj,
+                                              Elm_Sel_Type selection)
+{
+   Ecore_Evas *ee;
+
+   ee = ecore_evas_ecore_evas_get(evas_object_evas_get(obj));
+   return ecore_evas_selection_set(ee, _default_seat(obj), _elm_sel_type_to_ee_type(selection), NULL);
+}
+
+EAPI Eina_Bool
+elm_cnp_clipboard_selection_has_owner(Evas_Object *obj)
+{
+   Ecore_Evas *ee;
+
+   ee = ecore_evas_ecore_evas_get(evas_object_evas_get(obj));
+   return ecore_evas_selection_exists(ee, _default_seat(obj), ECORE_EVAS_SELECTION_BUFFER_COPY_AND_PASTE_BUFFER);
+
+}
+
+typedef struct _Sel_Lost_Data Sel_Lost_Data;
+struct _Sel_Lost_Data
+{
+   const Evas_Object *obj;
+   Elm_Sel_Type type;
+   void *udata;
+   Elm_Selection_Loss_Cb loss_cb;
+};
+
+static void
+_selection_changed_cb(void *data, const Efl_Event *ev)
+{
+   Sel_Lost_Data *ldata = data;
+   Efl_Ui_Wm_Selection_Changed *changed = ev->info;
+
+   if (changed->buffer == EFL_UI_CNP_BUFFER_SELECTION && ldata->type != ELM_SEL_TYPE_PRIMARY)
+     return;
+
+   if (changed->buffer == EFL_UI_CNP_BUFFER_COPY_AND_PASTE && ldata->type != ELM_SEL_TYPE_CLIPBOARD)
+     return;
+
+   if (ldata->obj == changed->caused_by)
+     return;
+
+   ldata->loss_cb(ldata->udata, ldata->type);
+   free(data);
+   efl_event_callback_del(ev->object, ev->desc, _selection_changed_cb, data);
+}
+
+EAPI void
+elm_cnp_selection_loss_callback_set(Evas_Object *obj, Elm_Sel_Type type, Elm_Selection_Loss_Cb func, const void *data)
+{
+   Sel_Lost_Data *ldata = calloc(1, sizeof(Sel_Lost_Data));
+
+   if (!ldata) return;
+   ldata->obj = obj;
+   ldata->type = type;
+   ldata->udata = (void *)data;
+   ldata->loss_cb = func;
+   efl_event_callback_add(obj, EFL_UI_SELECTION_EVENT_WM_SELECTION_CHANGED, _selection_changed_cb, ldata);
+}
+
+typedef struct {
+   Elm_Drop_Cb data_cb;
+   void *data;
+   Elm_Sel_Format format;
+} Callback_Storage;
+
+static Eina_Value
+_callback_storage_deliver(Eo *obj, void *data, const Eina_Value value)
+{
+   Callback_Storage *cb_storage = data;
+   Eina_Content *content = eina_value_to_content(&value);
+   Elm_Sel_Format format = _mime_type_to_elm_sel_format(eina_content_type_get(content));
+   Eina_Slice cdata;
+
+   cdata = eina_content_data_get(content);
+   Elm_Selection_Data d = { 0 };
+   d.data = eina_memdup((unsigned char*)cdata.bytes, cdata.len, EINA_FALSE);
+   d.len = cdata.len;
+   d.format = _mime_type_to_elm_sel_format(eina_content_type_get(content));
+
+   if (cb_storage->data_cb)
+     {
+        cb_storage->data_cb(cb_storage->data, obj, &d);
+     }
+   else
+     {
+        EINA_SAFETY_ON_FALSE_RETURN_VAL(format == ELM_SEL_FORMAT_TEXT || format == ELM_SEL_FORMAT_MARKUP || format == ELM_SEL_FORMAT_HTML, EINA_VALUE_EMPTY);
+
+        _elm_entry_entry_paste(obj, (const char *) d.data);
+     }
+   free(d.data);
+
+   return EINA_VALUE_EMPTY;
+}
+
+static Eina_Value
+_callback_storage_error(Eo *obj EINA_UNUSED, void *data EINA_UNUSED, Eina_Error error)
+{
+   ERR("Content cound not be received because of %s.", eina_error_msg_get(error));
+   return EINA_VALUE_EMPTY;
+}
+
+static void
+_callback_storage_free(Eo *obj EINA_UNUSED, void *data, const Eina_Future *dead_future EINA_UNUSED)
+{
+   free(data);
+}
+
+EAPI Eina_Bool
+elm_cnp_selection_get(const Evas_Object *obj, Elm_Sel_Type selection,
+                                     Elm_Sel_Format format,
+                                     Elm_Drop_Cb data_cb, void *udata)
+{
+   Ecore_Evas *ee;
+   Eina_Array *mime_types;
+   Eina_Future *future;
+   Callback_Storage *storage;
+
+   ee = ecore_evas_ecore_evas_get(evas_object_evas_get(obj));
+   mime_types = _elm_sel_format_to_mime_type(format);
+   future = ecore_evas_selection_get(ee, _default_seat(obj), _elm_sel_type_to_ee_type(selection), eina_array_iterator_new(mime_types));
+   storage = calloc(1,sizeof(Callback_Storage));
+   storage->data_cb = data_cb;
+   storage->data = udata;
+   storage->format = format;
+
+   efl_future_then(obj, future, _callback_storage_deliver, _callback_storage_error, _callback_storage_free, EINA_VALUE_TYPE_CONTENT, storage);
+
+   return EINA_TRUE;
+}
index 5feda3a..06346e4 100644 (file)
@@ -43,8 +43,6 @@
  * @{
  */
 
-# include <efl_ui_selection_types.eot.h>
-
 /**
  * Event notifying that the selection has changed
  * @see Elm_Cnp_Event_Selection_Changed
diff --git a/src/lib/elementary/elm_dnd.c b/src/lib/elementary/elm_dnd.c
new file mode 100644 (file)
index 0000000..699414b
--- /dev/null
@@ -0,0 +1,812 @@
+#ifdef HAVE_CONFIG_H
+# include "elementary_config.h"
+#endif
+
+
+#include <Elementary.h>
+#include "elm_priv.h"
+
+int ELM_CNP_EVENT_SELECTION_CHANGED;
+
+typedef struct {
+   void *enter_data, *leave_data, *pos_data, *drop_data;
+   Elm_Drag_State enter_cb;
+   Elm_Drag_State leave_cb;
+   Elm_Drag_Pos pos_cb;
+   Elm_Drop_Cb drop_cb;
+   Eina_Array *mime_types;
+   Elm_Sel_Format format;
+   Elm_Xdnd_Action action;
+} Elm_Drop_Target;
+
+static int
+_default_seat(const Eo *obj)
+{
+   return evas_device_seat_id_get(evas_default_device_get(evas_object_evas_get(obj), EFL_INPUT_DEVICE_TYPE_SEAT));
+}
+
+static const char*
+_action_to_string(Elm_Xdnd_Action action)
+{
+   if (action == ELM_XDND_ACTION_COPY) return "copy";
+   if (action == ELM_XDND_ACTION_MOVE) return "move";
+   if (action == ELM_XDND_ACTION_PRIVATE) return "private";
+   if (action == ELM_XDND_ACTION_ASK) return "ask";
+   if (action == ELM_XDND_ACTION_LIST) return "list";
+   if (action == ELM_XDND_ACTION_LINK) return "link";
+   if (action == ELM_XDND_ACTION_DESCRIPTION) return "description";
+   return "unknown";
+}
+
+static Elm_Xdnd_Action
+_string_to_action(const char* action)
+{
+   if (eina_streq(action, "copy")) return ELM_XDND_ACTION_COPY;
+   else if (eina_streq(action, "move")) return ELM_XDND_ACTION_MOVE;
+   else if (eina_streq(action, "private")) return ELM_XDND_ACTION_PRIVATE;
+   else if (eina_streq(action, "ask")) return ELM_XDND_ACTION_ASK;
+   else if (eina_streq(action, "list")) return ELM_XDND_ACTION_LIST;
+   else if (eina_streq(action, "link")) return ELM_XDND_ACTION_LINK;
+   else if (eina_streq(action, "description")) return ELM_XDND_ACTION_DESCRIPTION;
+   return ELM_XDND_ACTION_UNKNOWN;
+}
+
+static void
+_enter_cb(void *data, const Efl_Event *ev)
+{
+   Elm_Drop_Target *target = data;
+
+   if (target->enter_cb)
+     target->enter_cb(target->enter_data, ev->object);
+}
+
+static void
+_leave_cb(void *data, const Efl_Event *ev)
+{
+   Elm_Drop_Target *target = data;
+
+   if (target->leave_cb)
+     target->leave_cb(target->leave_data, ev->object);
+}
+
+static void
+_pos_cb(void *data, const Efl_Event *ev)
+{
+   Elm_Drop_Target *target = data;
+   Efl_Ui_Drop_Event *event = ev->info;
+
+   if (target->pos_cb)
+     target->pos_cb(target->pos_data, ev->object, event->position.x, event->position.y, target->action); //FIXME action
+}
+
+static Eina_Value
+_deliver_content(Eo *obj, void *data, const Eina_Value value)
+{
+   Elm_Drop_Target *target = data;
+   Elm_Selection_Data sel_data;
+   Eina_Content *content = eina_value_to_content(&value);
+
+   sel_data.data = (void*)eina_content_data_get(content).mem;
+   sel_data.len = eina_content_data_get(content).len;
+   sel_data.action = target->action;
+   sel_data.format = target->format;
+
+   if (target->drop_cb)
+     target->drop_cb(target->drop_data, obj, &sel_data);
+
+   return EINA_VALUE_EMPTY;
+}
+
+static void
+_drop_cb(void *data, const Efl_Event *ev)
+{
+   Efl_Ui_Drop_Dropped_Event *event = ev->info;
+   Elm_Drop_Target *target = data;
+   target->action = _string_to_action(event->action);
+   efl_future_then(ev->object, efl_ui_dnd_drop_data_get(ev->object, _default_seat(ev->object), eina_array_iterator_new(target->mime_types)),
+    .success = _deliver_content,
+    .data = target
+   );
+}
+
+static void
+_inv_cb(void *data, const Efl_Event *ev)
+{
+   Elm_Drop_Target *target = data;
+   elm_drop_target_del(ev->object, target->format, target->enter_cb, target->enter_data, target->leave_cb,
+                       target->leave_data, target->pos_cb, target->pos_data, target->drop_cb, target->drop_data);
+}
+
+EFL_CALLBACKS_ARRAY_DEFINE(drop_target_cb,
+  {EFL_UI_DND_EVENT_DROP_ENTERED, _enter_cb},
+  {EFL_UI_DND_EVENT_DROP_LEFT, _leave_cb},
+  {EFL_UI_DND_EVENT_DROP_POSITION_CHANGED, _pos_cb},
+  {EFL_UI_DND_EVENT_DROP_DROPPED, _drop_cb},
+  {EFL_EVENT_INVALIDATE, _inv_cb}
+)
+
+static Eina_Hash *target_register = NULL;
+
+static Eina_Array*
+_format_to_mime_array(Elm_Sel_Format format)
+{
+   Eina_Array *ret = eina_array_new(10);
+
+   if (format & ELM_SEL_FORMAT_TEXT)
+     eina_array_push(ret, "text/plain;charset=utf-8");
+   if (format & ELM_SEL_FORMAT_MARKUP)
+     eina_array_push(ret, "application/x-elementary-markup");
+   if (format & ELM_SEL_FORMAT_IMAGE)
+     {
+        eina_array_push(ret, "image/png");
+        eina_array_push(ret, "image/jpeg");
+        eina_array_push(ret, "image/x-ms-bmp");
+        eina_array_push(ret, "image/gif");
+        eina_array_push(ret, "image/tiff");
+        eina_array_push(ret, "image/svg+xml");
+        eina_array_push(ret, "image/x-xpixmap");
+        eina_array_push(ret, "image/x-tga");
+        eina_array_push(ret, "image/x-portable-pixmap");
+     }
+   if (format & ELM_SEL_FORMAT_VCARD)
+     eina_array_push(ret, "text/vcard");
+   if (format & ELM_SEL_FORMAT_HTML)
+     eina_array_push(ret, "text/html");
+
+   return ret;
+}
+
+EAPI Eina_Bool
+elm_drop_target_add(Evas_Object *obj, Elm_Sel_Format format,
+                    Elm_Drag_State enter_cb, void *enter_data,
+                    Elm_Drag_State leave_cb, void *leave_data,
+                    Elm_Drag_Pos pos_cb, void *pos_data,
+                    Elm_Drop_Cb drop_cb, void *drop_data)
+{
+
+   Elm_Drop_Target *target = calloc(1, sizeof(Elm_Drop_Target));
+   target->enter_cb = enter_cb;
+   target->enter_data = enter_data;
+   target->leave_cb = leave_cb;
+   target->leave_data = leave_data;
+   target->pos_cb = pos_cb;
+   target->pos_data = pos_data;
+   target->drop_cb = drop_cb;
+   target->drop_data = drop_data;
+   target->mime_types = _format_to_mime_array(format);
+   target->format = format;
+
+   efl_event_callback_array_add(obj, drop_target_cb(), target);
+
+   if (!target_register)
+     target_register = eina_hash_pointer_new(NULL);
+   eina_hash_list_append(target_register, &obj, target);
+
+   return EINA_TRUE;
+}
+
+EAPI Eina_Bool
+elm_drop_target_del(Evas_Object *obj, Elm_Sel_Format format,
+                    Elm_Drag_State enter_cb, void *enter_data,
+                    Elm_Drag_State leave_cb, void *leave_data,
+                    Elm_Drag_Pos pos_cb, void *pos_data,
+                    Elm_Drop_Cb drop_cb, void *drop_data)
+{
+   Elm_Drop_Target *target;
+   Eina_List *n, *found = NULL;
+
+   if (!target_register)
+     return EINA_TRUE;
+   Eina_List *targets = eina_hash_find(target_register, &obj);
+
+   if (!targets)
+     return EINA_TRUE;
+
+   EINA_LIST_FOREACH(targets, n, target)
+     {
+        if (target->enter_cb == enter_cb && target->enter_data == enter_data &&
+            target->leave_cb == leave_cb && target->leave_data == leave_data &&
+            target->pos_cb == pos_cb && target->pos_data == pos_data &&
+            target->drop_cb == drop_cb && target->drop_data == drop_data &&
+            target->format == format)
+          {
+
+             found = n;
+             break;
+          }
+     }
+   if (found)
+     {
+        efl_event_callback_array_del(obj, drop_target_cb(), eina_list_data_get(found));
+        eina_hash_list_remove(target_register, &obj, target);
+        eina_array_free(target->mime_types);
+        free(target);
+     }
+
+   return EINA_TRUE;
+}
+
+struct _Item_Container_Drag_Info
+{  /* Info kept for containers to support drag */
+   Evas_Object *obj;
+   Ecore_Timer *tm;    /* When this expires, start drag */
+   double anim_tm;  /* Time period to set tm         */
+   double tm_to_drag;  /* Time period to set tm         */
+   Elm_Xy_Item_Get_Cb itemgetcb;
+   Elm_Item_Container_Data_Get_Cb data_get;
+
+   Evas_Coord x_down;  /* Mouse down x cord when drag starts */
+   Evas_Coord y_down;  /* Mouse down y cord when drag starts */
+
+   /* Some extra information needed to impl default anim */
+   Evas *e;
+   Eina_List *icons;   /* List of icons to animate (Anim_Icon) */
+   int final_icon_w; /* We need the w and h of the final icon for the animation */
+   int final_icon_h;
+   Ecore_Animator *ea;
+
+   Elm_Drag_User_Info user_info;
+};
+typedef struct _Item_Container_Drag_Info Item_Container_Drag_Info;
+
+struct _Anim_Icon
+{
+   int start_x;
+   int start_y;
+   int start_w;
+   int start_h;
+   Evas_Object *o;
+};
+typedef struct _Anim_Icon Anim_Icon;
+static Eina_List *cont_drag_tg = NULL; /* List of Item_Container_Drag_Info */
+
+static Eina_Bool elm_drag_item_container_del_internal(Evas_Object *obj, Eina_Bool full);
+static void _cont_obj_mouse_move(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info);
+static void _cont_obj_mouse_up(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info);
+static void _cont_obj_mouse_down(void *data, Evas *e, Evas_Object *obj EINA_UNUSED, void *event_info);
+
+static void
+_cont_drag_done_cb(void *data, Evas_Object *obj EINA_UNUSED)
+{
+   Item_Container_Drag_Info *st = data;
+   elm_widget_scroll_freeze_pop(st->obj);
+   if (st->user_info.dragdone)
+     st->user_info.dragdone(st->user_info.donecbdata, NULL, EINA_FALSE); /*FIXME*/
+}
+
+static Eina_Bool
+_cont_obj_drag_start(void *data)
+{  /* Start a drag-action when timer expires */
+   Item_Container_Drag_Info *st = data;
+   st->tm = NULL;
+   Elm_Drag_User_Info *info = &st->user_info;
+   if (info->dragstart) info->dragstart(info->startcbdata, st->obj);
+   elm_widget_scroll_freeze_push(st->obj);
+   evas_object_event_callback_del_full
+      (st->obj, EVAS_CALLBACK_MOUSE_MOVE, _cont_obj_mouse_move, st);
+   elm_drag_start(  /* Commit the start only if data_get successful */
+         st->obj, info->format,
+         info->data, info->action,
+         info->createicon, info->createdata,
+         info->dragpos, info->dragdata,
+         info->acceptcb, info->acceptdata,
+         _cont_drag_done_cb, st);
+   ELM_SAFE_FREE(info->data, free);
+
+   return ECORE_CALLBACK_CANCEL;
+}
+
+static inline Eina_List *
+_anim_icons_make(Eina_List *icons)
+{  /* Make local copies of all icons, add them to list */
+   Eina_List *list = NULL, *itr;
+   Evas_Object *o;
+
+   EINA_LIST_FOREACH(icons, itr, o)
+     {  /* Now add icons to animation window */
+        Anim_Icon *st = calloc(1, sizeof(*st));
+
+        if (!st)
+          {
+             ERR("Failed to allocate memory for icon!");
+             continue;
+          }
+
+        evas_object_geometry_get(o, &st->start_x, &st->start_y, &st->start_w, &st->start_h);
+        evas_object_show(o);
+        st->o = o;
+        list = eina_list_append(list, st);
+     }
+
+   return list;
+}
+
+static Eina_Bool
+_drag_anim_play(void *data, double pos)
+{  /* Impl of the animation of icons, called on frame time */
+   Item_Container_Drag_Info *st = data;
+   Eina_List *l;
+   Anim_Icon *sti;
+
+   if (st->ea)
+     {
+        if (pos > 0.99)
+          {
+             st->ea = NULL;  /* Avoid deleting on mouse up */
+             EINA_LIST_FOREACH(st->icons, l, sti)
+                evas_object_hide(sti->o);
+
+             _cont_obj_drag_start(st);  /* Start dragging */
+             return ECORE_CALLBACK_CANCEL;
+          }
+
+        Evas_Coord xm, ym;
+        evas_pointer_canvas_xy_get(st->e, &xm, &ym);
+        EINA_LIST_FOREACH(st->icons, l, sti)
+          {
+             int x, y, h, w;
+             w = sti->start_w + ((st->final_icon_w - sti->start_w) * pos);
+             h = sti->start_h + ((st->final_icon_h - sti->start_h) * pos);
+             x = sti->start_x - (pos * ((sti->start_x + (w/2) - xm)));
+             y = sti->start_y - (pos * ((sti->start_y + (h/2) - ym)));
+             evas_object_move(sti->o, x, y);
+             evas_object_resize(sti->o, w, h);
+          }
+
+        return ECORE_CALLBACK_RENEW;
+     }
+
+   return ECORE_CALLBACK_CANCEL;
+}
+
+static inline Eina_Bool
+_drag_anim_start(void *data)
+{  /* Start default animation */
+   Item_Container_Drag_Info *st = data;
+
+   st->tm = NULL;
+   /* Now we need to build an (Anim_Icon *) list */
+   st->icons = _anim_icons_make(st->user_info.icons);
+   if (st->user_info.createicon)
+     {
+        Evas_Object *temp_win = elm_win_add(NULL, "Temp", ELM_WIN_DND);
+        Evas_Object *final_icon = st->user_info.createicon(st->user_info.createdata, temp_win, NULL, NULL);
+        evas_object_geometry_get(final_icon, NULL, NULL, &st->final_icon_w, &st->final_icon_h);
+        evas_object_del(final_icon);
+        evas_object_del(temp_win);
+     }
+   st->ea = ecore_animator_timeline_add(st->anim_tm, _drag_anim_play, st);
+
+   return EINA_FALSE;
+}
+
+static Eina_Bool
+_cont_obj_anim_start(void *data)
+{  /* Start a drag-action when timer expires */
+   Item_Container_Drag_Info *st = data;
+   int xposret, yposret;  /* Unused */
+   Elm_Object_Item *it = (st->itemgetcb) ?
+      (st->itemgetcb(st->obj, st->x_down, st->y_down, &xposret, &yposret))
+      : NULL;
+
+   st->tm = NULL;
+   st->user_info.format = ELM_SEL_FORMAT_TARGETS; /* Default */
+   st->icons = NULL;
+   st->user_info.data = NULL;
+   st->user_info.action = ELM_XDND_ACTION_COPY;  /* Default */
+
+   if (!it)   /* Failed to get mouse-down item, abort drag */
+     return ECORE_CALLBACK_CANCEL;
+
+   if (st->data_get)
+     {  /* collect info then start animation or start dragging */
+        if (st->data_get(    /* Collect drag info */
+                 st->obj,      /* The container object */
+                 it,           /* Drag started on this item */
+                 &st->user_info))
+          {
+             if (st->user_info.icons)
+               _drag_anim_start(st);
+             else
+               {
+                  if (st->anim_tm)
+                    {
+                       // even if we don't manage the icons animation, we have
+                       // to wait until it is finished before beginning drag.
+                       st->tm = ecore_timer_add(st->anim_tm, _cont_obj_drag_start, st);
+                    }
+                  else
+                    _cont_obj_drag_start(st);  /* Start dragging, no anim */
+               }
+          }
+     }
+
+   return ECORE_CALLBACK_CANCEL;
+}
+
+static int
+_drag_item_container_cmp(const void *d1,
+               const void *d2)
+{
+   const Item_Container_Drag_Info *st = d1;
+   return (((uintptr_t) (st->obj)) - ((uintptr_t) d2));
+}
+
+void
+_anim_st_free(Item_Container_Drag_Info *st)
+{  /* Stops and free mem of ongoing animation */
+   if (st)
+     {
+        ELM_SAFE_FREE(st->ea, ecore_animator_del);
+        Anim_Icon *sti;
+
+        EINA_LIST_FREE(st->icons, sti)
+          {
+             evas_object_del(sti->o);
+             free(sti);
+          }
+
+        st->icons = NULL;
+     }
+}
+
+static void
+_cont_obj_mouse_up(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info)
+{  /* Cancel any drag waiting to start on timeout */
+   Item_Container_Drag_Info *st = data;
+
+   if (((Evas_Event_Mouse_Up *)event_info)->button != 1)
+     return;  /* We only process left-click at the moment */
+
+   evas_object_event_callback_del_full
+      (st->obj, EVAS_CALLBACK_MOUSE_MOVE, _cont_obj_mouse_move, st);
+   evas_object_event_callback_del_full
+      (st->obj, EVAS_CALLBACK_MOUSE_UP, _cont_obj_mouse_up, st);
+
+   ELM_SAFE_FREE(st->tm, ecore_timer_del);
+
+   _anim_st_free(st);
+}
+
+static void
+_cont_obj_mouse_move(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info)
+{  /* Cancel any drag waiting to start on timeout */
+   if (((Evas_Event_Mouse_Move *)event_info)->event_flags & EVAS_EVENT_FLAG_ON_HOLD)
+     {
+        Item_Container_Drag_Info *st = data;
+
+        evas_object_event_callback_del_full
+           (st->obj, EVAS_CALLBACK_MOUSE_MOVE, _cont_obj_mouse_move, st);
+        evas_object_event_callback_del_full
+           (st->obj, EVAS_CALLBACK_MOUSE_UP, _cont_obj_mouse_up, st);
+        elm_drag_item_container_del_internal(obj, EINA_FALSE);
+
+        ELM_SAFE_FREE(st->tm, ecore_timer_del);
+
+        _anim_st_free(st);
+     }
+}
+
+static Eina_Bool
+elm_drag_item_container_del_internal(Evas_Object *obj, Eina_Bool full)
+{
+   Item_Container_Drag_Info *st =
+      eina_list_search_unsorted(cont_drag_tg, _drag_item_container_cmp, obj);
+
+   if (st)
+     {
+        ELM_SAFE_FREE(st->tm, ecore_timer_del); /* Cancel drag-start timer */
+
+        if (st->ea)  /* Cancel ongoing default animation */
+          _anim_st_free(st);
+
+        if (full)
+          {
+             st->itemgetcb = NULL;
+             st->data_get = NULL;
+             evas_object_event_callback_del_full
+                (obj, EVAS_CALLBACK_MOUSE_DOWN, _cont_obj_mouse_down, st);
+
+             cont_drag_tg = eina_list_remove(cont_drag_tg, st);
+             ELM_SAFE_FREE(st->user_info.data, free);
+             free(st);
+          }
+
+        return EINA_TRUE;
+     }
+   return EINA_FALSE;
+}
+
+static void
+_cont_obj_mouse_down(void *data, Evas *e, Evas_Object *obj EINA_UNUSED, void *event_info)
+{  /* Launch a timer to start dragging */
+   Evas_Event_Mouse_Down *ev = event_info;
+   if (ev->button != 1)
+     return;  /* We only process left-click at the moment */
+
+   Item_Container_Drag_Info *st = data;
+   evas_object_event_callback_add(st->obj, EVAS_CALLBACK_MOUSE_MOVE,
+         _cont_obj_mouse_move, st);
+
+   evas_object_event_callback_add(st->obj, EVAS_CALLBACK_MOUSE_UP,
+         _cont_obj_mouse_up, st);
+
+   ecore_timer_del(st->tm);
+
+   st->e = e;
+   st->x_down = ev->canvas.x;
+   st->y_down = ev->canvas.y;
+   st->tm = ecore_timer_add(st->tm_to_drag, _cont_obj_anim_start, st);
+}
+EAPI Eina_Bool
+elm_drag_item_container_del(Evas_Object *obj)
+{
+   return elm_drag_item_container_del_internal(obj, EINA_TRUE);
+}
+
+EAPI Eina_Bool
+elm_drag_item_container_add(Evas_Object *obj,
+                            double anim_tm,
+                            double tm_to_drag,
+                            Elm_Xy_Item_Get_Cb itemgetcb,
+                            Elm_Item_Container_Data_Get_Cb data_get)
+{
+   Item_Container_Drag_Info *st;
+
+   if (elm_drag_item_container_del_internal(obj, EINA_FALSE))
+     {  /* Updating info of existing obj */
+        st = eina_list_search_unsorted(cont_drag_tg, _drag_item_container_cmp, obj);
+        if (!st) return EINA_FALSE;
+     }
+   else
+     {
+        st = calloc(1, sizeof(*st));
+        if (!st) return EINA_FALSE;
+
+        st->obj = obj;
+        cont_drag_tg = eina_list_append(cont_drag_tg, st);
+
+        /* Register for mouse callback for container to start/abort drag */
+        evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_DOWN,
+                                       _cont_obj_mouse_down, st);
+     }
+
+   st->tm = NULL;
+   st->anim_tm = anim_tm;
+   st->tm_to_drag = tm_to_drag;
+   st->itemgetcb = itemgetcb;
+   st->data_get = data_get;
+   return EINA_TRUE;
+}
+
+static Eina_List *cont_drop_tg = NULL; /* List of Item_Container_Drop_Info */
+
+struct _Item_Container_Drop_Info
+{  /* Info kept for containers to support drop */
+   Evas_Object *obj;
+   Elm_Xy_Item_Get_Cb itemgetcb;
+   Elm_Drop_Item_Container_Cb dropcb;
+   Elm_Drag_Item_Container_Pos poscb;
+};
+typedef struct _Item_Container_Drop_Info Item_Container_Drop_Info;
+
+
+typedef struct
+{
+   Evas_Object    *obj;
+   /* FIXME: Cache window */
+   Eina_Inlist    *cbs_list; /* List of Dropable_Cbs * */
+   struct {
+      Evas_Coord      x, y;
+      Eina_Bool       in : 1;
+      const char     *type;
+      Elm_Sel_Format  format;
+   } last;
+} Dropable;
+
+static int
+_drop_item_container_cmp(const void *d1,
+               const void *d2)
+{
+   const Item_Container_Drop_Info *st = d1;
+   return (((uintptr_t) (st->obj)) - ((uintptr_t) d2));
+}
+
+static void
+_elm_item_container_pos_cb(void *data, Evas_Object *obj, Evas_Coord x, Evas_Coord y, Elm_Xdnd_Action action)
+{  /* obj is the container pointer */
+   Elm_Object_Item *it = NULL;
+   int xposret = 0;
+   int yposret = 0;
+
+   Item_Container_Drop_Info *st =
+      eina_list_search_unsorted(cont_drop_tg, _drop_item_container_cmp, obj);
+
+   if (st && st->poscb)
+     {  /* Call container drop func with specific item pointer */
+        int xo = 0;
+        int yo = 0;
+
+        evas_object_geometry_get(obj, &xo, &yo, NULL, NULL);
+        if (st->itemgetcb)
+          it = st->itemgetcb(obj, x+xo, y+yo, &xposret, &yposret);
+
+        st->poscb(data, obj, it, x, y, xposret, yposret, action);
+     }
+}
+
+static Eina_Bool
+_elm_item_container_drop_cb(void *data, Evas_Object *obj , Elm_Selection_Data *ev)
+{  /* obj is the container pointer */
+   Elm_Object_Item *it = NULL;
+   int xposret = 0;
+   int yposret = 0;
+
+   Item_Container_Drop_Info *st =
+      eina_list_search_unsorted(cont_drop_tg, _drop_item_container_cmp, obj);
+
+   if (st && st->dropcb)
+     {  /* Call container drop func with specific item pointer */
+        int xo = 0;
+        int yo = 0;
+
+        evas_object_geometry_get(obj, &xo, &yo, NULL, NULL);
+        if (st->itemgetcb)
+          it = st->itemgetcb(obj, ev->x+xo, ev->y+yo, &xposret, &yposret);
+
+        return st->dropcb(data, obj, it, ev, xposret, yposret);
+     }
+
+   return EINA_FALSE;
+}
+
+static Eina_Bool
+elm_drop_item_container_del_internal(Evas_Object *obj, Eina_Bool full)
+{
+   Item_Container_Drop_Info *st =
+      eina_list_search_unsorted(cont_drop_tg, _drop_item_container_cmp, obj);
+
+   if (st)
+     {
+        // temp until st is stored inside data of obj.
+        //FIXME delete this drop container
+        st->itemgetcb= NULL;
+        st->poscb = NULL;
+        st->dropcb = NULL;
+
+        if (full)
+          {
+             cont_drop_tg = eina_list_remove(cont_drop_tg, st);
+             free(st);
+          }
+
+        return EINA_TRUE;
+     }
+
+   return EINA_FALSE;
+}
+
+EAPI Eina_Bool
+elm_drop_item_container_add(Evas_Object *obj,
+                            Elm_Sel_Format format,
+                            Elm_Xy_Item_Get_Cb itemgetcb,
+                            Elm_Drag_State entercb, void *enterdata,
+                            Elm_Drag_State leavecb, void *leavedata,
+                            Elm_Drag_Item_Container_Pos poscb, void *posdata,
+                            Elm_Drop_Item_Container_Cb dropcb, void *dropdata)
+{
+   Item_Container_Drop_Info *st;
+
+   if (elm_drop_item_container_del_internal(obj, EINA_FALSE))
+     {  /* Updating info of existing obj */
+        st = eina_list_search_unsorted(cont_drop_tg, _drop_item_container_cmp, obj);
+        if (!st) return EINA_FALSE;
+     }
+   else
+     {
+        st = calloc(1, sizeof(*st));
+        if (!st) return EINA_FALSE;
+
+        st->obj = obj;
+        cont_drop_tg = eina_list_append(cont_drop_tg, st);
+     }
+
+   st->itemgetcb = itemgetcb;
+   st->poscb = poscb;
+   st->dropcb = dropcb;
+   elm_drop_target_add(obj, format,
+                       entercb, enterdata,
+                       leavecb, leavedata,
+                       _elm_item_container_pos_cb, posdata,
+                       _elm_item_container_drop_cb, dropdata);
+   return EINA_TRUE;
+}
+
+
+EAPI Eina_Bool
+elm_drop_item_container_del(Evas_Object *obj)
+{
+   return elm_drop_item_container_del_internal(obj, EINA_TRUE);
+}
+
+typedef struct {
+  void *dragdata, *acceptdata, *donecbdata;
+  Elm_Drag_Pos dragposcb;
+  Elm_Drag_Accept acceptcb;
+  Elm_Drag_State dragdonecb;
+} Elm_Drag_Data;
+
+static void
+_drag_finished_cb(void *data, const Efl_Event *ev)
+{
+   Elm_Drag_Data *dd = data;
+   Eina_Bool *accepted = ev->info;
+
+   if (dd->acceptcb)
+     dd->acceptcb(dd->acceptdata, ev->object, *accepted);
+
+   if (dd->dragdonecb)
+     dd->dragdonecb(dd->donecbdata, ev->object);
+
+   efl_event_callback_del(ev->object, EFL_UI_DND_EVENT_DRAG_FINISHED, _drag_finished_cb, dd);
+   free(dd);
+}
+
+EAPI Eina_Bool
+elm_drag_start(Evas_Object *obj, Elm_Sel_Format format,
+               const char *data, Elm_Xdnd_Action action,
+               Elm_Drag_Icon_Create_Cb createicon,
+               void *createdata,
+               Elm_Drag_Pos dragpos, void *dragdata,
+               Elm_Drag_Accept acceptcb, void *acceptdata,
+               Elm_Drag_State dragdone, void *donecbdata)
+{
+   Eina_Array *mime_types;
+   Eina_Content *content;
+   Efl_Content *ui;
+   int x, y, w, h;
+   Efl_Ui_Widget *widget;
+   Elm_Drag_Data *dd;
+   const char *str_action;
+
+   str_action = _action_to_string(action);
+   dd = calloc(1, sizeof(Elm_Drag_Data));
+   dd->dragposcb = dragpos;
+   dd->dragdata = dragdata;
+   dd->acceptcb = acceptcb;
+   dd->acceptdata = acceptdata;
+   dd->dragdonecb = dragdone;
+   dd->donecbdata = donecbdata;
+   mime_types = _format_to_mime_array(format);
+   if (eina_array_count(mime_types) != 1)
+     {
+        WRN("You passed more than one format, this is not going to work well");
+     }
+   content = eina_content_new((Eina_Slice) EINA_SLICE_STR_FULL(data), eina_array_data_get(mime_types, 0));
+   ui = efl_ui_dnd_drag_start(obj, content, str_action, _default_seat(obj));
+   widget = createicon(createdata, ui, &x, &y);
+   evas_object_geometry_get(widget, NULL, NULL, &w, &h);
+   evas_object_show(widget);
+   efl_content_set(ui, widget);
+   efl_gfx_entity_size_set(ui, EINA_SIZE2D(w, h));
+   eina_array_free(mime_types);
+
+   efl_event_callback_add(obj, EFL_UI_DND_EVENT_DRAG_FINISHED, _drag_finished_cb, dd);
+
+   return EINA_TRUE;
+}
+
+EAPI Eina_Bool
+elm_drag_cancel(Evas_Object *obj)
+{
+   efl_ui_dnd_drag_cancel(obj, _default_seat(obj));
+
+   return EINA_TRUE;
+}
+
+EAPI Eina_Bool
+elm_drag_action_set(Evas_Object *obj EINA_UNUSED, Elm_Xdnd_Action action EINA_UNUSED)
+{
+   ERR("This operation is not supported anymore.");
+   return EINA_FALSE;
+}
index ab2713c..4b0dc20 100644 (file)
@@ -1056,7 +1056,7 @@ _selection_data_cb(void *data EINA_UNUSED,
         char *entry_tag;
         int len;
         static const char *tag_string =
-           "<item absize=240x180 href=file://%s></item>";
+           "<item absize=240x180 href=%s></item>";
 
         len = strlen(tag_string) + strlen(buf);
         entry_tag = alloca(len + 1);
@@ -2160,7 +2160,7 @@ _selection_store(Elm_Sel_Type seltype,
    if ((!sel) || (!sel[0])) return;  /* avoid deleting our own selection */
 
    elm_cnp_selection_set
-     (obj, seltype, ELM_SEL_FORMAT_MARKUP, sel, strlen(sel));
+     (obj, seltype, ELM_SEL_FORMAT_MARKUP, sel, strlen(sel) + 1);
    elm_cnp_selection_loss_callback_set(obj, seltype, _selection_clear, obj);
    if (seltype == ELM_SEL_TYPE_CLIPBOARD)
      eina_stringshare_replace(&sd->cut_sel, sel);
@@ -2283,7 +2283,7 @@ _menu_call(Evas_Object *obj)
         const char *context_menu_orientation;
         Eina_Bool ownersel;
 
-        ownersel = elm_selection_selection_has_owner(obj);
+        ownersel = elm_cnp_clipboard_selection_has_owner(obj);
         if (!sd->items)
           {
              /* prevent stupid blank hoversel */
index 079139f..c5ed41c 100644 (file)
@@ -950,7 +950,6 @@ elm_quicklaunch_sub_shutdown(void)
         _elm_module_shutdown();
         if (_elm_prefs_initted)
           _elm_prefs_shutdown();
-        _efl_ui_dnd_shutdown();
         elm_color_class_shutdown();
      }
 
index 1474f9e..909ee0f 100644 (file)
 
 # include "efl_ui_focus_parent_provider.eo.h"
 # include "efl_ui_focus_parent_provider_standard.eo.h"
-# include "efl_ui_selection_manager.eo.h"
 # include "efl_datetime_manager.eo.h"
 
 extern const char *_efl_model_property_itemw;
@@ -686,9 +685,6 @@ void                 _elm_prefs_data_init(void);
 void                 _elm_prefs_data_shutdown(void);
 
 /* init functions for dnd and cnp */
-Eo*                  _efl_ui_selection_manager_get(Eo *obj);
-void                 _efl_ui_dnd_shutdown(void);
-
 int                  _elm_ews_wm_init(void);
 void                 _elm_ews_wm_shutdown(void);
 void                 _elm_ews_wm_rescale(Elm_Theme *th,
@@ -1209,6 +1205,12 @@ typedef struct
 
 Efl_Ui_Shared_Win_Data* efl_ui_win_shared_data_get(Efl_Ui_Win *win);
 
+void _selection_changed_event_register(Eo *obj);
+void _selection_changed_event_unregister(Eo *obj);
+void _drop_event_register(Eo *obj);
+void _drop_event_unregister(Eo *obj);
+void _register_selection_changed(Efl_Ui_Selection *selection);
+
 #endif
 
 #define ELM_FEATURE_PRODUCT_THEME
index aef856a..bf14fe7 100644 (file)
@@ -147,7 +147,6 @@ pub_eo_files = [
   'elm_code_widget.eo',
   'efl_ui_selection.eo',
   'efl_ui_dnd.eo',
-  'efl_ui_dnd_container.eo',
   'efl_ui_focus_manager_window_root.eo',
   'efl_ui_spotlight_container.eo',
   'efl_ui_spotlight_manager.eo',
@@ -227,8 +226,6 @@ endforeach
 pub_eo_types_files = [
   'elm_general.eot',
   'efl_ui.eot',
-  'efl_ui_selection_types.eot',
-  'efl_ui_dnd_types.eot'
 ]
 
 foreach eo_file : pub_eo_types_files
@@ -252,7 +249,6 @@ priv_eo_files = [
   'efl_ui_focus_parent_provider.eo',
   'efl_ui_focus_parent_provider_standard.eo',
   'efl_ui_state_model.eo',
-  'efl_ui_selection_manager.eo',
   'efl_datetime_manager.eo',
   'efl_ui_size_model.eo',
   'efl_ui_homogeneous_model.eo',
@@ -857,6 +853,8 @@ elementary_src = [
   'elm_icon.c',
   'efl_ui_image.c',
   'elm_index.c',
+  'elm_cnp.c',
+  'elm_dnd.c',
   'efl_access_object.c',
   'efl_access_action.c',
   'efl_access_component.c',
@@ -979,7 +977,6 @@ elementary_src = [
   'efl_ui_scroller.c',
   'efl_ui_scroll_manager.c',
   'efl_ui_pan.c',
-  'efl_ui_selection_manager.c',
   'efl_ui_selection_manager_private.h',
   'efl_ui_selection.c',
   'efl_datetime_manager.c',
index bff8396..106aa08 100644 (file)
@@ -60,6 +60,8 @@ struct @extern Eina.Matrix3 {
    zz: double; [[ZZ value.]]
 }
 
+struct @extern Eina.Content;
+
 struct @extern Eina.Matrix4 {
    [[A bidimensional array of floating point values with 4 rows and 4 columns.
 
index 2b31ede..bb40ace 100644 (file)
@@ -120,6 +120,21 @@ _efl_gfx_image_load_error_to_evas_load_error(Eina_Error err)
    return EVAS_LOAD_ERROR_GENERIC;
 }
 
+static Eina_Content*
+_markup_to_utf8(Eina_Content *from, const char *to_type)
+{
+   Eina_Slice slice = eina_content_data_get(from);
+   char *utf8 = evas_textblock_text_markup_to_utf8(NULL, slice.mem);
+   return eina_content_new((Eina_Slice)EINA_SLICE_STR_FULL(utf8), to_type);
+}
+
+static Eina_Content*
+_utf8_to_markup(Eina_Content *from, const char *to_type)
+{
+   Eina_Slice slice = eina_content_data_get(from);
+   char *markup = evas_textblock_text_utf8_to_markup(NULL, slice.mem);
+   return eina_content_new((Eina_Slice)EINA_SLICE_STR_FULL(markup), to_type);
+}
 
 EAPI int
 evas_init(void)
@@ -184,6 +199,9 @@ evas_init(void)
    /* TIZEN_ONLY(190509): Android style Nine-Patch feature */
    tizen_9patch_hash = eina_hash_string_superfast_new(free);
 
+   eina_content_converter_conversion_register("application/x-elementary-markup", "text/plain;charset=utf-8", _markup_to_utf8);
+   eina_content_converter_conversion_register("text/plain;charset=utf-8", "application/x-elementary-markup", _utf8_to_markup);
+
    return _evas_init_count;
 
 //TIZEN_ONLY(20171114) : support evas gl thread
index b788654..0944afa 100644 (file)
@@ -44,6 +44,12 @@ EFL_START_TEST(text_cnp)
 }
 EFL_END_TEST
 
+static void
+_stop_event_soon(void *data EINA_UNUSED, const Efl_Event *ev)
+{
+   efl_event_callback_stop(ev->object);
+}
+
 EFL_START_TEST(text_all_select_all_unselect)
 {
    Eo *txt;
@@ -57,7 +63,7 @@ EFL_START_TEST(text_all_select_all_unselect)
                 efl_event_callback_add(efl_added, EFL_TEXT_INTERACTIVE_EVENT_SELECTION_CHANGED,
                             increment_int_changed, &i_selection)
                 );
-
+   efl_event_callback_priority_add(txt, EFL_UI_SELECTION_EVENT_WM_SELECTION_CHANGED, EFL_CALLBACK_PRIORITY_BEFORE, _stop_event_soon, NULL);
    efl_text_set(txt, "Hello");
    efl_text_interactive_all_select(txt);
    Efl_Text_Cursor *c1=NULL, *c2 =NULL;
@@ -122,6 +128,7 @@ EFL_START_TEST(text_selection)
    Eo *win = win_add();
 
    txt = efl_add(EFL_UI_TEXTBOX_CLASS, win);
+   efl_event_callback_priority_add(txt, EFL_UI_SELECTION_EVENT_WM_SELECTION_CHANGED, EFL_CALLBACK_PRIORITY_BEFORE, _stop_event_soon, NULL);
    efl_gfx_entity_size_set(txt, EINA_SIZE2D(300, 300));
    efl_text_set(txt, "Hello");
    get_me_to_those_events(txt);
@@ -160,7 +167,7 @@ EFL_START_TEST(text_user_change)
    txt = efl_add(EFL_UI_TEXTBOX_CLASS, win,
                 efl_event_callback_add(efl_added, EFL_TEXT_INTERACTIVE_EVENT_CHANGED_USER, user_changed, &info)
                 );
-
+   efl_event_callback_priority_add(txt, EFL_UI_SELECTION_EVENT_WM_SELECTION_CHANGED, EFL_CALLBACK_PRIORITY_BEFORE, _stop_event_soon, NULL);
    efl_text_set(txt, "Hello");
    efl_gfx_entity_size_set(txt, EINA_SIZE2D(300, 300));
    efl_text_interactive_all_select(txt);
@@ -177,6 +184,7 @@ EFL_START_TEST(text_scroll_mode)
    Eo *txt, *win, *cur;
    win = win_add();
    txt = efl_add(EFL_UI_TEXTBOX_CLASS, win);
+   efl_event_callback_priority_add(txt, EFL_UI_SELECTION_EVENT_WM_SELECTION_CHANGED, EFL_CALLBACK_PRIORITY_BEFORE, _stop_event_soon, NULL);
    cur = efl_text_interactive_main_cursor_get(txt);
    efl_text_set(txt, "Hello");
    /*scroll mode is false by default*/
@@ -199,6 +207,7 @@ EFL_START_TEST(text_change_event)
    Eo *win = win_add();
 
    txt = efl_add(EFL_UI_TEXTBOX_CLASS, win);
+   efl_event_callback_priority_add(txt, EFL_UI_SELECTION_EVENT_WM_SELECTION_CHANGED, EFL_CALLBACK_PRIORITY_BEFORE, _stop_event_soon, NULL);
    efl_gfx_entity_size_set(txt, EINA_SIZE2D(300, 300));
    efl_text_set(txt, "Hello");
    int i_changed = 0;
@@ -223,6 +232,7 @@ EFL_START_TEST(text_keys_handler)
    Eo *win = win_add();
 
    txt = efl_add(EFL_UI_TEXTBOX_CLASS, win);
+   efl_event_callback_priority_add(txt, EFL_UI_SELECTION_EVENT_WM_SELECTION_CHANGED, EFL_CALLBACK_PRIORITY_BEFORE, _stop_event_soon, NULL);
    efl_gfx_entity_size_set(txt, EINA_SIZE2D(300, 300));
    efl_text_set(txt, "Hello");