// 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;
# 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>
#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"
-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]]
@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;
}
}
+++ /dev/null
-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.]]
- }
- }
- }
-}
+++ /dev/null
-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)]]
-}
#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"
-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;
+ }
}
+++ /dev/null
-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]]
-}
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));
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.
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 {
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;
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"
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);
}
}
-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))
{
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 */
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)
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);
}
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);
}
{
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)))
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,
{
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);
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;
{
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);
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);
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);
}
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);
/*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);
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
}
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
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);
}
+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
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.
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 {
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;
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)
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;
}
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);
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))
* 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)
--- /dev/null
+#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;
+}
* @{
*/
-# include <efl_ui_selection_types.eot.h>
-
/**
* Event notifying that the selection has changed
* @see Elm_Cnp_Event_Selection_Changed
--- /dev/null
+#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;
+}
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);
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);
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 */
_elm_module_shutdown();
if (_elm_prefs_initted)
_elm_prefs_shutdown();
- _efl_ui_dnd_shutdown();
elm_color_class_shutdown();
}
# 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;
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,
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
'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',
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
'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',
'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',
'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',
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.
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)
/* 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
}
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;
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;
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);
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);
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*/
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;
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");