summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarcel Hollerbach <mail@marcel-hollerbach.de>2020-01-19 13:58:26 +0100
committerMarcel Hollerbach <mail@marcel-hollerbach.de>2020-02-10 12:56:08 +0100
commit838d2c27dc853a7ae622c89b859c7275a69bc862 (patch)
tree77a45aa8ef0b411d54230643f2e86684755ac22d
parent87bc669c2b69fa71b7290be4542b5f67508596a3 (diff)
downloadefl-838d2c27dc853a7ae622c89b859c7275a69bc862.tar.gz
rewrite efl cnp and dnd handling
the previous commits introduced a abstraction for drag in drop which can be now used for this here. With this commit all the direct protocol handling in efl.ui is removed, and only the ecore evas API is used. Additionally, this lead to a giant refactor of how APIs do work. All Efl.Ui. interfaces have been removed except Efl.Ui.Selection and Efl.Ui.Dnd, these two have been restructored. A small list of what is new: - In general no function pointers are used anymore. They feel very uncompftable in bindings and in C. For us its a lot easier to just listen to a event when a drop enters or leaves, there is no need to register custom functions for that. - Asynchronous data transphere is handled via futures, which proved to be more error safe. - Formats and actions are handled as mime types / strings. - 0 is the default seat if you do not know what else to take. - Content is in general passes as a content container from eina, this also allows applications to pass custom types The legacy dnd and cnp API is implemented based on that. All cnp related things are in elm_cnp.c the dnd parts are in elm_dnd.c Differential Revision: https://phab.enlightenment.org/D11190
-rw-r--r--src/lib/elementary/Efl_Ui.h3
-rw-r--r--src/lib/elementary/efl_ui_dnd.c867
-rw-r--r--src/lib/elementary/efl_ui_dnd.eo79
-rw-r--r--src/lib/elementary/efl_ui_dnd_container.eo46
-rw-r--r--src/lib/elementary/efl_ui_dnd_types.eot60
-rw-r--r--src/lib/elementary/efl_ui_selection.c297
-rw-r--r--src/lib/elementary/efl_ui_selection.eo90
-rw-r--r--src/lib/elementary/efl_ui_selection_manager.c5678
-rw-r--r--src/lib/elementary/efl_ui_selection_manager.eo139
-rw-r--r--src/lib/elementary/efl_ui_selection_types.eot60
-rw-r--r--src/lib/elementary/efl_ui_tags.c2
-rw-r--r--src/lib/elementary/efl_ui_textbox.c358
-rw-r--r--src/lib/elementary/efl_ui_textbox.eo12
-rw-r--r--src/lib/elementary/efl_ui_win.c214
-rw-r--r--src/lib/elementary/elm_cnp.c235
-rw-r--r--src/lib/elementary/elm_cnp.h2
-rw-r--r--src/lib/elementary/elm_dnd.c806
-rw-r--r--src/lib/elementary/elm_entry.c6
-rw-r--r--src/lib/elementary/elm_main.c1
-rw-r--r--src/lib/elementary/elm_priv.h10
-rw-r--r--src/lib/elementary/meson.build7
-rw-r--r--src/lib/eo/eina_types.eot2
-rw-r--r--src/lib/evas/canvas/evas_main.c18
-rw-r--r--src/modules/ecore_evas/engines/x/ecore_evas_x.c9
-rw-r--r--src/tests/elementary/efl_ui_test_text.c14
25 files changed, 1698 insertions, 7317 deletions
diff --git a/src/lib/elementary/Efl_Ui.h b/src/lib/elementary/Efl_Ui.h
index c010581c74..1020d9e6d1 100644
--- a/src/lib/elementary/Efl_Ui.h
+++ b/src/lib/elementary/Efl_Ui.h
@@ -119,8 +119,6 @@ extern EAPI Eina_Error EFL_UI_THEME_APPLY_ERROR_NONE;
// EO types. Defined for legacy-only builds as legacy uses typedef of EO types.
#include "efl_ui.eot.h"
-#include "efl_ui_selection_types.eot.h"
-#include "efl_ui_dnd_types.eot.h"
//define focus manager earlier since focus object and manager is circular
typedef Eo Efl_Ui_Focus_Manager;
@@ -323,7 +321,6 @@ typedef Eo Efl_Ui_Spotlight_Indicator;
# include <efl_ui_widget_focus_manager.eo.h>
# include <efl_ui_selection.eo.h>
# include <efl_ui_dnd.eo.h>
-# include <efl_ui_dnd_container.eo.h>
# include <efl_ui_timepicker.eo.h>
# include <efl_ui_datepicker.eo.h>
diff --git a/src/lib/elementary/efl_ui_dnd.c b/src/lib/elementary/efl_ui_dnd.c
index df79eb9762..7d9ef2e1d1 100644
--- a/src/lib/elementary/efl_ui_dnd.c
+++ b/src/lib/elementary/efl_ui_dnd.c
@@ -12,838 +12,137 @@
#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, 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_event_callback_call(start->obj, EFL_UI_DND_EVENT_DRAG_FINISHED, &accepted);
+ 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;
+ 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);
+ 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_START, NULL);
-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 = 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 (!data) return EINA_FALSE;
- Eo *sel_man = _efl_ui_selection_manager_get(obj);
- int seatid = 1;
- Eina_Slice sl;
- 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);
- 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)
-{
- 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)
-{
- 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)
+_efl_ui_dnd_efl_object_invalidate(Eo *obj, Efl_Ui_Dnd_Data *pd)
{
- 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)
-{
- Eo *sel_man = _efl_ui_selection_manager_get(obj);
- int seatid = 1;
- Dnd_Drag_State *enter, *leave;
- Dnd_Drag_Pos *pos;
- Dnd_Drop *drop;
- 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;
+ efl_invalidate(efl_super(obj, EFL_UI_DND_MIXIN));
-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_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)
-{
- Eo *sel_man = _efl_ui_selection_manager_get(obj);
- int seatid = 1;
- //Eina_List *l, *l2;
- Eina_List *drop_list;
- Dnd_Drop *drop;
-
-#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);
+#define IS_DROP_EVENT(D) ( \
+(D == EFL_UI_DND_EVENT_DROP_POS) || \
+(D == EFL_UI_DND_EVENT_DROP_DROP) || \
+(D == EFL_UI_DND_EVENT_DROP_LEAVE) || \
+(D == EFL_UI_DND_EVENT_DROP_ENTER) \
+)
- 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)
-{
- 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);
- efl_ui_selection_manager_container_drop_item_del(sel_man, obj, seatid);
-
- return EINA_TRUE;
-}
-
-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;
-}
-
-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;
+ return efl_event_callback_array_priority_add(efl_super(obj, EFL_UI_DND_MIXIN), array, priority, user_data);
}
-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);
- efl_ui_selection_manager_container_drag_item_del(sel_man, obj, seatid);
-
- return EINA_TRUE;
-}
+#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"
diff --git a/src/lib/elementary/efl_ui_dnd.eo b/src/lib/elementary/efl_ui_dnd.eo
index 08f668856b..7fe2e8103c 100644
--- a/src/lib/elementary/efl_ui_dnd.eo
+++ b/src/lib/elementary/efl_ui_dnd.eo
@@ -1,29 +1,31 @@
-import efl_ui_dnd_types;
+import eina_types;
-mixin @beta Efl.Ui.Dnd {
- data: null;
+struct @beta Efl.Ui.Dnd_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.Dnd_Drop_Event {
+ dnd : Efl.Ui.Dnd_Event; [[The overall information]]
+ action : string; [[The action the client should take]]
+}
+
+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,start] will be emitted each time a successfull drag will be started.
+ @[Efl.Ui.Dnd.drag,finished] will be emitted every time a drag is finished.
]]
params {
- @in format: Efl.Ui.Selection_Format; [[The data format]]
- @in data: Eina.Slice; [[The drag data]]
- @in action: Efl.Ui.Selection_Action; [[Action when data is transferred]]
- @in icon_func: Efl.Dnd.Drag_Icon_Create; [[Function pointer to create icon]]
- @in seat: uint; [[Specified seat for multiple seats case.]]
- }
- }
- drag_action_set {
- [[Set the action for the drag]]
- params {
- @in action: Efl.Ui.Selection_Action; [[Drag action]]
+ content : Eina.Content @by_ref; [[The content you want to provide via dnd]]
+ @in action: string; [[Action when data is transferred]]
@in seat: uint; [[Specified seat for multiple seats case.]]
}
+ return : Efl.Content; [[A UI element where you can just set your visual representation into]]
}
drag_cancel {
[[Cancel the on-going drag]]
@@ -31,33 +33,26 @@ mixin @beta Efl.Ui.Dnd {
@in seat: uint; [[Specified seat for multiple seats case.]]
}
}
- drop_target_add {
- [[Make the current object as drop target.
- There are four events emitted:
- - EFL_UI_DND_EVENT_DRAG_ENTER
- - EFL_UI_DND_EVENT_DRAG_LEAVE
- - EFL_UI_DND_EVENT_DRAG_POS
- - EFL_UI_DND_EVENT_DRAG_DROP.]]
+ drop_data_get {
+ [[Get the data from the object that has selection]]
params {
- @in format: Efl.Ui.Selection_Format; [[Accepted data format]]
- @in seat: uint; [[Specified seat for multiple seats case.]]
- }
- }
- drop_target_del {
- [[Delete the dropable status from object]]
- params {
- @in format: Efl.Ui.Selection_Format; [[Accepted data format]]
- @in seat: uint; [[Specified seat for multiple seats case.]]
+ seat : uint; [[Specified seat for multiple seats case.]]
+ acceptable_types : iterator<string>; [[The types that are acceptable for you]]
}
+ return : future<Eina.Content> @move; [[fullfilled when the content is transmitted, and ready to use]]
}
}
events {
- /* FIXME: This is not very future-proof. Better return a struct. */
- drag,accept: ptr(bool); [[accept drag data]]
- drag,done: void; [[drag is done (mouse up)]]
- drag,enter: void; [[called when the drag object enters this object]]
- drag,leave: void; [[called when the drag object leaves this object]]
- drag,pos: Efl.Dnd.Drag_Pos; [[called when the drag object changes drag position]]
- drag,drop: Efl.Ui.Selection_Data; [[called when the drag object dropped on this object]]
+ drop,enter : Efl.Ui.Dnd_Event;
+ drop,leave : Efl.Ui.Dnd_Event;
+ drop,pos : Efl.Ui.Dnd_Event;
+ drop,drop : Efl.Ui.Dnd_Drop_Event;
+ drag,start : void;
+ drag,finished : bool;
+ }
+ implements {
+ Efl.Object.constructor;
+ Efl.Object.invalidate;
+ Efl.Object.finalize;
}
}
diff --git a/src/lib/elementary/efl_ui_dnd_container.eo b/src/lib/elementary/efl_ui_dnd_container.eo
deleted file mode 100644
index 0cc1f3f945..0000000000
--- a/src/lib/elementary/efl_ui_dnd_container.eo
+++ /dev/null
@@ -1,46 +0,0 @@
-import efl_ui_dnd_types;
-
-mixin @beta Efl.Ui.Dnd_Container {
- methods {
- @property drag_delay_time {
- [[The time since mouse down happens to drag starts.]]
- set {
- }
- get {
- }
- values {
- time: double; [[The drag delay time]]
- }
- }
- drag_item_add {
- [[This registers a drag for items in a container. Many items can be
- dragged at a time. During dragging, there are three events emitted:
- EFL_DND_EVENT_DRAG_POS, EFL_DND_EVENT_DRAG_ACCEPT, EFL_DND_EVENT_DRAG_DONE.]]
- params {
- @in data_func: Efl.Dnd.Drag_Data_Get; [[Data and its format]]
- @in item_func: Efl.Dnd.Item_Get; [[Item to determine drag start]]
- @in icon_func: Efl.Dnd.Drag_Icon_Create; [[Icon used during drag]]
- @in icon_list_func: Efl.Dnd.Drag_Icon_List_Create; [[Icons used for animations CHECKING ]]
- @in seat: uint; [[Specified seat for multiple seats case.]]
- }
- }
- drag_item_del {
- [[Remove drag function of items in the container object.]]
- params {
- @in seat: uint; [[Specified seat for multiple seats case.]]
- }
- }
- drop_item_add {
- params {
- @in format: Efl.Ui.Selection_Format; [[Accepted data formats]]
- @in item_func: Efl.Dnd.Item_Get; [[Get item at specific position]]
- @in seat: uint; [[Specified seat for multiple seats case.]]
- }
- }
- drop_item_del {
- params {
- @in seat: uint; [[Specified seat for multiple seats case.]]
- }
- }
- }
-}
diff --git a/src/lib/elementary/efl_ui_dnd_types.eot b/src/lib/elementary/efl_ui_dnd_types.eot
deleted file mode 100644
index ace1c8de7b..0000000000
--- a/src/lib/elementary/efl_ui_dnd_types.eot
+++ /dev/null
@@ -1,60 +0,0 @@
-import efl_ui_selection_types;
-
-function @beta Efl.Dnd.Drag_Icon_Create {
- [[Function pointer for creating icon at the drag side.]]
- params {
- @in win: Efl.Canvas.Object; [[The window to create the objects relative to]]
- @in drag_obj: Efl.Canvas.Object; [[The drag object]]
- @out off: Eina.Position2D; [[Offset from the icon position to the cursor]]
- }
- return: Efl.Canvas.Object; [[The drag icon object]]
-};
-
-function @beta Efl.Dnd.Drag_Data_Get {
- [[Function pointer for getting data and format at the drag side.]]
- params {
- @in obj: Efl.Canvas.Object; [[The container object]]
- @out format: Efl.Ui.Selection_Format; [[Data format]]
- @out drag_data: Eina.Rw_Slice; [[Data]]
- @out action: Efl.Ui.Selection_Action; [[The drag action]]
- }
-};
-
-function @beta Efl.Dnd.Item_Get {
- [[Function pointer to find out which item is under position (x, y)]]
- params {
- @in obj: Efl.Canvas.Object; [[The container object]]
- @in pos: Eina.Position2D; [[The coordinates to get item]]
- @out posret: Eina.Position2D; [[position relative to item (left (-1), middle (0), right (1)]]
- }
- return: Efl.Object; [[Object under x,y coordinates or NULL if not found]]
-};
-
-function @beta Efl.Dnd.Drag_Icon_List_Create {
- [[Function pointer to create list of icons at the drag side.
- These icons are used for animation on combining selection icons
- to one icon.]]
- params {
- @in obj: Efl.Canvas.Object; [[The container object]]
- }
- return: list<Efl.Canvas.Object>;
-};
-
-struct @beta Efl.Dnd.Drag_Accept {
- accepted: bool;
-}
-
-struct @beta Efl.Dnd.Drag_Pos {
- [[Dragging position information.]]
- pos: Eina.Position2D; [[Evas Coordinate]]
- action: Efl.Ui.Selection_Action; [[The drag action]]
- format: Efl.Ui.Selection_Format; [[The drag format]]
- item: Efl.Canvas.Object; [[The item object. It is only available for container object.]]
-}
-
-struct @beta Efl.Dnd.Drag_Item_Container_Drop {
- [[Drop information for a drag&drop operation.]]
- item: Efl.Canvas.Object; [[The item object]]
- data: Efl.Ui.Selection_Data; [[The selection data]]
- pos: Eina.Position2D; [[Position relative to item (left (-1), middle (0), right (1)]]
-}
diff --git a/src/lib/elementary/efl_ui_selection.c b/src/lib/elementary/efl_ui_selection.c
index 675eb0cf99..d67d1f3fef 100644
--- a/src/lib/elementary/efl_ui_selection.c
+++ b/src/lib/elementary/efl_ui_selection.c
@@ -9,278 +9,115 @@
#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)
{
- 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;
+ return efl_event_callback_array_priority_add(efl_super(obj, EFL_UI_SELECTION_MIXIN), array, priority, user_data);
}
-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)
+EOLIAN static Efl_Object*
+_efl_ui_selection_efl_object_finalize(Eo *obj, Efl_Ui_Selection_Data *pd)
{
- int seatid = 1;
- Eina_Future *f;
- Sel_Lost_Data *ldata;
- Eo *sel_man = _efl_ui_selection_manager_get(obj);
- Eina_Slice data;
+ if (pd->registered)
+ _selection_changed_event_register(obj);
- 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;
+ return efl_finalize(efl_super(obj, MY_CLASS));
}
-EAPI Eina_Bool
-elm_object_cnp_selection_clear(Evas_Object *obj, Elm_Sel_Type type)
-{
- 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;
-}
-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)
-{
- 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);
-}
-
-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"
diff --git a/src/lib/elementary/efl_ui_selection.eo b/src/lib/elementary/efl_ui_selection.eo
index 20e42261d0..492e60e117 100644
--- a/src/lib/elementary/efl_ui_selection.eo
+++ b/src/lib/elementary/efl_ui_selection.eo
@@ -1,45 +1,57 @@
-import efl_ui_selection_types;
+import eina_types;
-mixin @beta Efl.Ui.Selection {
- [[Efl Ui Selection class]]
- data: null;
- methods {
- selection_set {
- [[Set the selection data to the object]]
- params {
- @in type: Efl.Ui.Selection_Type; [[Selection Type]]
- @in format: Efl.Ui.Selection_Format; [[Selection Format]]
- @in data: Eina.Slice; [[Selection data]]
- @in seat: uint;[[Specified seat for multiple seats case.]]
- }
- return: future<void>; [[Future for tracking when the selection is lost]]
+enum @beta Efl.Ui.Cnp_Buffer{
+ selection = 0,
+ copy_and_paste = 1,
+}
+
+struct @beta Efl.Ui.Wm_Selection_Changed {
+ buffer : Efl.Ui.Cnp_Buffer;
+ caused_by : Efl.Ui.Selection;
+ seat : uint;
+}
+
+mixin @beta Efl.Ui.Selection requires Efl.Object {
+ methods {
+ selection_set {
+ [[Set the selection data to the object]]
+ params {
+ buffer : Efl.Ui.Cnp_Buffer;
+ content : Eina.Content @by_ref;
+ seat : uint;
}
- selection_get {
- [[Get the data from the object that has selection]]
- params {
- @in type: Efl.Ui.Selection_Type; [[Selection Type]]
- @in format: Efl.Ui.Selection_Format; [[Selection Format]]
- @in data_func: Efl.Ui.Selection_Data_Ready; [[Data ready function pointer]]
- @in seat: uint;[[Specified seat for multiple seats case.]]
- }
+ }
+ selection_clear {
+ [[Clear the selection data from the object]]
+ params {
+ buffer : Efl.Ui.Cnp_Buffer;
+ seat : uint;
}
- selection_clear {
- [[Clear the selection data from the object]]
- params {
- @in type: Efl.Ui.Selection_Type; [[Selection Type]]
- @in seat: uint; [[Specified seat for multiple seats case.]]
- }
+ }
+ selection_get {
+ [[Get the data from the object that has selection]]
+ params {
+ buffer : Efl.Ui.Cnp_Buffer;
+ seat : uint;
+ acceptable_types : iterator<string>;
}
- has_owner {
- [[Determine whether the selection data has owner]]
- params {
- @in type: Efl.Ui.Selection_Type; [[Selection type]]
- @in seat: uint; [[Specified seat for multiple seats case.]]
- }
- return: bool; [[EINA_TRUE if there is object owns selection, otherwise EINA_FALSE]]
+ return : future<Eina.Content> @move;
+ }
+ has_selection {
+ [[Determine whether the selection data has owner]]
+ params {
+ buffer : Efl.Ui.Cnp_Buffer;
+ seat : uint;
}
- }
- events {
- wm_selection,changed: Efl.Ui.Selection_Changed; [[Called when display server's selection has changed]]
- }
+ return : bool; [[$true if there is a available selection, $false if not]]
+ }
+ }
+ implements {
+ Efl.Object.constructor;
+ Efl.Object.invalidate;
+ Efl.Object.finalize;
+ }
+ events {
+ wm_selection,changed : Efl.Ui.Wm_Selection_Changed;
+ }
}
diff --git a/src/lib/elementary/efl_ui_selection_manager.c b/src/lib/elementary/efl_ui_selection_manager.c
deleted file mode 100644
index 3a5db9713c..0000000000
--- a/src/lib/elementary/efl_ui_selection_manager.c
+++ /dev/null
@@ -1,5678 +0,0 @@
-#ifdef HAVE_CONFIG_H
-# include "elementary_config.h"
-#endif
-
-#include <Elementary.h>
-#include "elm_priv.h"
-
-#ifdef _WIN32
-# include <evil_private.h> /* mmap */
-#else
-# include <sys/mman.h>
-#endif
-
-#include "efl_ui_selection_manager_private.h"
-
-#define MY_CLASS EFL_UI_SELECTION_MANAGER_CLASS
-
-//#define DEBUGON 1
-#ifdef DEBUGON
-# define sel_debug(fmt, args...) fprintf(stderr, __FILE__":%s:%d : " fmt "\n", __FUNCTION__, __LINE__, ##args)
-#else
-# define sel_debug(x...) do { } while (0)
-#endif
-
-static void _anim_data_free(Sel_Manager_Drag_Container *dc);
-static void _cont_obj_mouse_move_cb(void *data, Evas *e, Evas_Object *obj, void *event_info);
-static void _cont_obj_mouse_up_cb(void *data, Evas *e, Evas_Object *obj, void *event_info);
-static void _item_container_del_internal(Sel_Manager_Drag_Container *dc, Eina_Bool full);
-
-void efl_ui_selection_manager_drop_target_del(Eo *obj, Efl_Object *target_obj, Efl_Ui_Selection_Format format, unsigned int seat);
-void efl_ui_selection_manager_selection_clear(Eo *obj, Efl_Object *owner, Efl_Ui_Selection_Type type, unsigned int seat);
-void efl_ui_selection_manager_drag_start(Eo *obj, Efl_Object *drag_obj, 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);
-
-static Eina_List *managers;
-
-#ifdef HAVE_ELEMENTARY_X
-static void _set_selection_list(Sel_Manager_Selection *sel_list, Sel_Manager_Seat_Selection *seat_sel);
-static Ecore_X_Atom _x11_dnd_action_rev_map(Efl_Ui_Selection_Action action);
-static Ecore_X_Window _x11_xwin_get(const Evas_Object *obj);
-#endif
-
-#ifdef HAVE_ELEMENTARY_WL2
-Ecore_Wl2_Window *_wl_window_get(const Evas_Object *obj);
-static Ecore_Wl2_Input *_wl_seat_get(Ecore_Wl2_Window *win, Evas_Object *obj, unsigned int seat_id);
-#endif
-
-#ifdef HAVE_ELEMENTARY_WIN32
-static void _set_selection_list(Sel_Manager_Selection *sel_list, Sel_Manager_Seat_Selection *seat_sel);
-#endif
-
-EAPI int ELM_CNP_EVENT_SELECTION_CHANGED = -1;
-
-static Sel_Manager_Seat_Selection *
-_sel_manager_seat_selection_get(Efl_Ui_Selection_Manager_Data *pd, unsigned int seat)
-{
- Eina_List *l = NULL;
- Sel_Manager_Seat_Selection *seat_sel = NULL;
-
- EINA_LIST_FOREACH(pd->seat_list, l, seat_sel)
- {
- if (seat_sel->seat == seat)
- break;
- }
- if (!seat_sel)
- ERR("Could not find request seat");
-
- return seat_sel;
-}
-
-static inline void
-_owner_change_check(Efl_Ui_Selection_Manager *manager, Efl_Object *owner,
- Sel_Manager_Seat_Selection *seat_sel,
- Sel_Manager_Selection *sel,
- Efl_Ui_Selection_Type type, Eina_Bool same_win)
-{
- if (!same_win)
- {
- Eina_List *l, *l_next;
- Eo *man;
-
- EINA_LIST_FOREACH_SAFE(managers, l, l_next, man)
- {
- if (man != manager)
- {
- Eina_List *l2, *l2_next, *l3, *l3_next;
- Sel_Manager_Selection_Lost *sel_lost;
- Sel_Manager_Seat_Selection *seat_sel2;
- Efl_Ui_Selection_Manager_Data *pd = efl_data_scope_get(man, MY_CLASS);
-
- if (!pd) continue;
- EINA_LIST_FOREACH_SAFE(pd->seat_list, l3, l3_next, seat_sel2)
- {
- EINA_LIST_FOREACH_SAFE(seat_sel2->sel_lost_list, l2, l2_next, sel_lost)
- {
- if ((sel_lost->request) &&
- (sel_lost->type == type))
- {
- eina_promise_resolve(sel_lost->promise, eina_value_uint_init(sel_lost->type));
- }
- }
- seat_sel2->xwin = 0;
-#if defined(HAVE_ELEMENTARY_X) || defined(HAVE_ELEMENTARY_WIN32)
- if (seat_sel2->sel_list)
- {
- int i;
-
- for (i = 0;
- i < (EFL_UI_SELECTION_TYPE_CLIPBOARD + 1)
- ; i++)
- {
-#ifdef HAVE_ELEMENTARY_X
- seat_sel2->sel_list[i].xwin = 0;
-#elif defined (HAVE_ELEMENTARY_WIN32)
- seat_sel2->sel_list[i].win = NULL;
-#endif
- seat_sel2->sel_list[i].active = EINA_FALSE;
- }
- }
-#endif
-#if defined(HAVE_ELEMENTARY_WL2) || defined(HAVE_ELEMENTARY_COCOA)
- if (seat_sel2->sel)
- {
- seat_sel2->sel->win = 0;
- seat_sel2->sel->active = EINA_FALSE;
- }
-#endif
- }
- }
- }
- }
- if ((sel->owner != NULL) &&
- (sel->owner != owner) && same_win)
- {
- Eina_List *l, *l_next;
- Sel_Manager_Selection_Lost *sel_lost;
- EINA_LIST_FOREACH_SAFE(seat_sel->sel_lost_list, l, l_next, sel_lost)
- {
- if ((sel_lost->request == sel->owner) &&
- (sel_lost->type == type))
- {
- eina_promise_resolve(sel_lost->promise, eina_value_uint_init(sel_lost->type));
- }
- }
- }
-}
-
-static Sel_Manager_Seat_Selection *
-_sel_manager_seat_selection_init(Efl_Ui_Selection_Manager_Data *pd, unsigned int seat)
-{
- Sel_Manager_Seat_Selection *seat_sel = NULL;
- Eina_List *l = NULL;
-
- EINA_LIST_FOREACH(pd->seat_list, l, seat_sel)
- {
- if(seat_sel->seat == seat)
- break;
- }
- if (!seat_sel)
- {
- seat_sel = calloc(1, sizeof(Sel_Manager_Seat_Selection));
- if (!seat_sel)
- {
- ERR("Failed to allocate seat");
- return NULL;
- }
- seat_sel->saved_types = calloc(1, sizeof(Saved_Type));
- seat_sel->seat = seat;
- seat_sel->pd = pd;
- pd->seat_list = eina_list_append(pd->seat_list, seat_sel);
- }
-#ifdef HAVE_ELEMENTARY_X
- if (!seat_sel->sel_list)
- {
- seat_sel->sel_list = calloc(1, (EFL_UI_SELECTION_TYPE_CLIPBOARD + 1) * sizeof(Sel_Manager_Selection));
- if (!seat_sel->sel_list)
- {
- ERR("failed to allocate selection list");
- return NULL;
- }
- _set_selection_list(seat_sel->sel_list, seat_sel);
- }
-#endif
-#ifdef HAVE_ELEMENTARY_WL2
- if (!seat_sel->sel)
- {
- Sel_Manager_Selection *sel = calloc(1, sizeof(Sel_Manager_Selection));
- if (!sel)
- {
- ERR("failed to allocate selection");
- return NULL;
- }
- sel->seat_sel = seat_sel;
- seat_sel->sel = sel;
- }
-#endif
-#ifdef HAVE_ELEMENTARY_COCOA
- if (!seat_sel->sel)
- {
- Sel_Manager_Selection *sel = calloc(1, sizeof(Sel_Manager_Selection));
- if (!sel)
- {
- ERR("failed to allocate selection");
- return NULL;
- }
- sel->seat_sel = seat_sel;
- seat_sel->sel = sel;
- }
-#endif
-#ifdef HAVE_ELEMENTARY_WIN32
- if (!seat_sel->sel_list)
- {
- seat_sel->sel_list = calloc(1, (EFL_UI_SELECTION_TYPE_CLIPBOARD + 1) * sizeof(Sel_Manager_Selection));
- if (!seat_sel->sel_list)
- {
- ERR("failed to allocate selection list");
- return NULL;
- }
- _set_selection_list(seat_sel->sel_list, seat_sel);
- }
-#endif
-
- return seat_sel;
-}
-
-static void
-_sel_manager_promise_cancel(Eo *obj EINA_UNUSED, void *data, const Eina_Future *dead_future EINA_UNUSED)
-{
- Sel_Manager_Selection_Lost *sel_lost = data;
- sel_lost->seat_sel->sel_lost_list = eina_list_remove(sel_lost->seat_sel->sel_lost_list, sel_lost);
- free(sel_lost);
-}
-
-static inline Eina_Future *
-_update_sel_lost_list(Efl_Object *obj, Efl_Ui_Selection_Type type,
- Sel_Manager_Seat_Selection *seat_sel)
-{
- Eina_Promise *p;
- Sel_Manager_Selection_Lost *sel_lost;
-
- sel_lost = calloc(1, sizeof(Sel_Manager_Selection_Lost));
- if (!sel_lost)
- return NULL;
- sel_lost->request = obj;
- sel_lost->type = type;
- sel_lost->seat_sel = seat_sel;
- seat_sel->sel_lost_list = eina_list_append(seat_sel->sel_lost_list, sel_lost);
-
- p = efl_loop_promise_new(obj);
- if (!p) return NULL;
- sel_lost->promise = p;
-
- return efl_future_then(obj, eina_future_new(p),
- .data = sel_lost,
- .free = _sel_manager_promise_cancel);
-}
-
-/* TODO: this should not be an actual tempfile, but rather encode the object
- * as http://dataurl.net/ if it's an image or similar. Evas should support
- * decoding it as memfile. */
-static Tmp_Info *
-_tempfile_new(int size)
-{
-#ifdef HAVE_MMAP
- Tmp_Info *info;
- const char *tmppath = NULL;
- mode_t cur_umask;
- int len;
-
- info = calloc(1, sizeof(Tmp_Info));
- if (!info) return NULL;
-#if defined(HAVE_GETUID) && defined(HAVE_GETEUID)
- if (getuid() == geteuid())
-#endif
- tmppath = getenv("TMP");
- if (!tmppath) tmppath = P_tmpdir;
- len = snprintf(NULL, 0, "%s/%sXXXXXX", tmppath, "elmcnpitem-");
- if (len < 0) goto on_error;
- len++;
- info->filename = malloc(len);
- if (!info->filename) goto on_error;
- snprintf(info->filename,len,"%s/%sXXXXXX", tmppath, "elmcnpitem-");
- cur_umask = umask(S_IRWXO | S_IRWXG);
- info->fd = mkstemp(info->filename);
- umask(cur_umask);
- if (info->fd < 0) goto on_error;
-# ifdef __linux__
- {
- char *tmp;
- /* And before someone says anything see POSIX 1003.1-2008 page 400 */
- long pid;
-
- pid = (long)getpid();
- /* Use pid instead of /proc/self: That way if can be passed around */
- len = snprintf(NULL,0,"/proc/%li/fd/%i", pid, info->fd);
- len++;
- tmp = malloc(len);
- if (tmp)
- {
- snprintf(tmp,len, "/proc/%li/fd/%i", pid, info->fd);
- unlink(info->filename);
- free(info->filename);
- info->filename = tmp;
- }
- }
-# endif
- sel_debug("filename is %s\n", info->filename);
- if (size < 1) goto on_error;
- /* Map it in */
- if (ftruncate(info->fd, size))
- {
- perror("ftruncate");
- goto on_error;
- }
- eina_mmap_safety_enabled_set(EINA_TRUE);
- info->map = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED, info->fd, 0);
- if (info->map == MAP_FAILED)
- {
- perror("mmap");
- goto on_error;
- }
- return info;
-
- on_error:
- if (info->fd >= 0) close(info->fd);
- info->fd = -1;
- /* Set map to NULL and return */
- info->map = NULL;
- info->len = 0;
- free(info->filename);
- free(info);
- return NULL;
-#else
- (void) size;
- return NULL;
-#endif
-}
-
-static int
-_tmpinfo_free(Tmp_Info *info)
-{
- if (!info) return 0;
- free(info->filename);
- free(info);
- return 0;
-}
-
-static inline void
-_drop_target_cbs_del(Efl_Ui_Selection_Manager_Data *pd, Sel_Manager_Dropable *dropable, Efl_Object *obj)
-{
- if (dropable)
- {
- Drop_Format *df;
- while (dropable->format_list)
- {
- df = EINA_INLIST_CONTAINER_GET(dropable->format_list, Drop_Format);
- efl_ui_selection_manager_drop_target_del(pd->sel_man, obj,
- df->format, dropable->seat);
- // If drop_target_del() happened to delete dropabale, then
- // re-fetch it each loop to make sure it didn't
- dropable = efl_key_data_get(obj, "__elm_dropable");
- if (!dropable) break;
- }
- }
-}
-
-static void
-_all_drop_targets_cbs_del(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *info EINA_UNUSED)
-{
- Efl_Ui_Selection_Manager_Data *pd = data;
- Sel_Manager_Dropable *dropable = NULL;
-
- if (!pd) return;
- dropable = efl_key_data_get(obj, "__elm_dropable");
- _drop_target_cbs_del(pd, dropable, obj);
-}
-
-static void
-_dropable_coords_adjust(Sel_Manager_Dropable *dropable, Eina_Position2D *pos)
-{
- Ecore_Evas *ee;
- Evas *evas = evas_object_evas_get(dropable->obj);
- int ex = 0, ey = 0, ew = 0, eh = 0;
- Evas_Object *win;
-
- ee = ecore_evas_ecore_evas_get(evas);
- ecore_evas_geometry_get(ee, &ex, &ey, &ew, &eh);
- pos->x = pos->x - ex;
- pos->y = pos->y - ey;
-
- /* For Wayland, frame coords have to be subtracted. */
- Evas_Coord fx, fy;
- evas_output_framespace_get(evas, &fx, &fy, NULL, NULL);
- if (fx || fy) sel_debug("evas frame fx %d fy %d\n", fx, fy);
- pos->x = pos->x - fx;
- pos->y = pos->y - fy;
-
- if (elm_widget_is(dropable->obj))
- {
- win = elm_widget_top_get(dropable->obj);
- if (win && efl_isa(win, EFL_UI_WIN_CLASS))
- {
- Evas_Coord x2, y2;
- int rot = elm_win_rotation_get(win);
- switch (rot)
- {
- case 90:
- x2 = ew - pos->y;
- y2 = pos->x;
- break;
- case 180:
- x2 = ew - pos->x;
- y2 = eh - pos->y;
- break;
- case 270:
- x2 = pos->y;
- y2 = eh - pos->x;
- break;
- default:
- x2 = pos->x;
- y2 = pos->y;
- break;
- }
- sel_debug("rotation %d, w %d, h %d - x:%d->%d, y:%d->%d\n",
- rot, ew, eh, pos->x, x2, pos->y, y2);
- pos->x = x2;
- pos->y = y2;
- }
- }
-}
-
-static Eina_Bool
-_drag_cancel_animate(void *data, double pos)
-{ /* Animation to "move back" drag-window */
- Sel_Manager_Seat_Selection *seat_sel = data;
- sel_debug("in, pos: %f", pos);
- if (pos >= 0.99)
- {
-#ifdef HAVE_ELEMENTARY_X
- Ecore_X_Window xdragwin = _x11_xwin_get(seat_sel->drag_win);
- ecore_x_window_ignore_set(xdragwin, 0);
-#endif
- sel_debug("Delete drag_win");
- evas_object_del(seat_sel->drag_win);
- seat_sel->drag_win = NULL;
- return ECORE_CALLBACK_CANCEL;
- }
- else
- {
- int x, y;
- x = seat_sel->drag_win_end.x - (pos * (seat_sel->drag_win_end.x - seat_sel->drag_win_start.x));
- y = seat_sel->drag_win_end.y - (pos * (seat_sel->drag_win_end.y - seat_sel->drag_win_start.y));
- evas_object_move(seat_sel->drag_win, x, y);
- }
-
- return ECORE_CALLBACK_RENEW;
-}
-
-static Efl_Ui_Selection_Format
-_dnd_types_to_format(Efl_Ui_Selection_Manager_Data *pd, const char **types, int ntypes)
-{
- Efl_Ui_Selection_Format ret_type = 0;
- int i;
- for (i = 0; i < ntypes; i++)
- {
- Sel_Manager_Atom *atom = eina_hash_find(pd->type_hash, types[i]);
- if (atom) ret_type |= atom->format;
- }
- return ret_type;
-}
-
-static Eina_List *
-_dropable_list_geom_find(Efl_Ui_Selection_Manager_Data *pd, Evas *evas, Evas_Coord px, Evas_Coord py)
-{
- Eina_List *itr, *top_objects_list = NULL, *dropable_list = NULL;
- Evas_Object *top_obj;
- Sel_Manager_Dropable *dropable = NULL;
-
- if (!pd->drop_list) return NULL;
-
- /* We retrieve the (non-smart) objects pointed by (px, py) */
- top_objects_list = evas_tree_objects_at_xy_get(evas, NULL, px, py);
- /* We walk on this list from the last because if the list contains more than one
- * element, all but the last will repeat events. The last one can repeat events
- * or not. Anyway, this last one is the first that has to be taken into account
- * for the determination of the drop target.
- */
- EINA_LIST_REVERSE_FOREACH(top_objects_list, itr, top_obj)
- {
- Evas_Object *object = top_obj;
- /* We search for the dropable data into the object. If not found, we search into its parent.
- * For example, if a button is a drop target, the first object will be an (internal) image.
- * The drop target is attached to the button, i.e to image's parent. That's why we need to
- * walk on the parents until NULL.
- * If we find this dropable data, we found our drop target.
- */
- while (object)
- {
- dropable = efl_key_data_get(object, "__elm_dropable");
- if (dropable)
- {
- Eina_Bool exist = EINA_FALSE;
- Eina_List *l;
- Sel_Manager_Dropable *d = NULL;
- EINA_LIST_FOREACH(dropable_list, l, d)
- {
- if (d == dropable)
- {
- exist = EINA_TRUE;
- break;
- }
- }
- if (!exist)
- dropable_list = eina_list_append(dropable_list, dropable);
- object = evas_object_smart_parent_get(object);
- if (dropable)
- sel_debug("Drop target %p of type %s found\n",
- dropable->obj, efl_class_name_get(efl_class_get(dropable->obj)));
- }
- else
- object = evas_object_smart_parent_get(object);
- }
- }
- eina_list_free(top_objects_list);
- return dropable_list;
-}
-
-#ifdef HAVE_ELEMENTARY_X
-static Ecore_X_Window
-_x11_xwin_get(const Efl_Object *obj)
-{
- if (!obj) return 0;
-
- Ecore_X_Window xwin = 0;
- //get top
- const Evas_Object *top = obj;
- const Evas_Object *parent = obj;
- while(parent)
- {
- top = parent;
- parent = efl_parent_get(parent);
- }
- if (efl_isa(top, EFL_UI_WIN_CLASS))
- {
- xwin = elm_win_xwindow_get(top);
- }
- if (!xwin)
- {
- Ecore_Evas *ee;
- Evas *evas = evas_object_evas_get(obj);
- if (!evas) return 0;
- ee = ecore_evas_ecore_evas_get(evas);
- if (!ee) return 0;
-
- while(!xwin)
- {
- const char *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 0;
- xwin = _elm_ee_xwin_get(ee);
- }
- else
- {
- xwin = _elm_ee_xwin_get(ee);
- if (!xwin) return 0;
- }
- }
- }
-
- return xwin;
-}
-
-static Eina_Bool
-_x11_is_uri_type_data(Sel_Manager_Selection *sel EINA_UNUSED, Ecore_X_Event_Selection_Notify *notify)
-{
- Ecore_X_Selection_Data *data;
- char *p;
-
- data = notify->data;
- sel_debug("data->format is %d %p %p", data->format, notify, data);
- if (data->content == ECORE_X_SELECTION_CONTENT_FILES) return EINA_TRUE;
- p = (char *)data->data;
- if (!p) return EINA_TRUE;
- sel_debug("Got %s", p);
- if (strncmp(p, "file:/", 6))
- {
- if (*p != '/') return EINA_FALSE;
- }
- return EINA_TRUE;
-}
-
-static Sel_Manager_Seat_Selection *
-_x11_sel_manager_seat_selection_init(Efl_Ui_Selection_Manager_Data *pd, unsigned int seat)
-{
- Sel_Manager_Seat_Selection *seat_sel = NULL;
- Eina_List *l = NULL;
-
- EINA_LIST_FOREACH(pd->seat_list, l, seat_sel)
- {
- if(seat_sel->seat == seat)
- break;
- }
- if (!seat_sel)
- {
- seat_sel = calloc(1, sizeof(Sel_Manager_Seat_Selection));
- if (!seat_sel)
- {
- ERR("Failed to allocate seat");
- return NULL;
- }
- seat_sel->saved_types = calloc(1, sizeof(Saved_Type));
- seat_sel->seat = seat;
- seat_sel->pd = pd;
- pd->seat_list = eina_list_append(pd->seat_list, seat_sel);
- }
- if (!seat_sel->sel_list)
- {
- //TODO: reduce memory (may be just need one common sel_list)
- seat_sel->sel_list = calloc(1, (EFL_UI_SELECTION_TYPE_CLIPBOARD + 1) * sizeof(Sel_Manager_Selection));
- if (!seat_sel->sel_list)
- {
- ERR("failed to allocate selection list");
- return NULL;
- }
- _set_selection_list(seat_sel->sel_list, seat_sel);
- }
-
- return seat_sel;
-}
-
-static Eina_Bool
-_x11_data_preparer_text(Sel_Manager_Seat_Selection *seat_sel EINA_UNUSED,
- Ecore_X_Event_Selection_Notify *notify,
- Efl_Ui_Selection_Data *ddata, Tmp_Info **tmp_info EINA_UNUSED)
-{
- sel_debug("text data preparer");
- Ecore_X_Selection_Data *data = notify->data;
- ddata->format = EFL_UI_SELECTION_FORMAT_TEXT;
- ddata->content.mem = eina_memdup(data->data, data->length, EINA_TRUE);
- ddata->content.len = data->length;
- return EINA_TRUE;
-}
-
-static Eina_Bool
-_x11_data_preparer_markup(Sel_Manager_Seat_Selection *seat_sel EINA_UNUSED,
- Ecore_X_Event_Selection_Notify *notify,
- Efl_Ui_Selection_Data *ddata, Tmp_Info **tmp_info EINA_UNUSED)
-{
- sel_debug("markup data preparer");
- Ecore_X_Selection_Data *data = notify->data;
- ddata->format = EFL_UI_SELECTION_FORMAT_MARKUP;
- ddata->content.mem = eina_memdup(data->data, data->length, EINA_TRUE);
- ddata->content.len = data->length;
- return EINA_TRUE;
-}
-
-/**
- * So someone is pasting an image into my entry or widget...
- */
-static Eina_Bool
-_x11_data_preparer_uri(Sel_Manager_Seat_Selection *seat_sel, Ecore_X_Event_Selection_Notify *notify,
- Efl_Ui_Selection_Data *ddata, Tmp_Info **tmp_info EINA_UNUSED)
-{
- sel_debug("uri data preparer");
- Ecore_X_Selection_Data *data;
- Ecore_X_Selection_Data_Files *files;
- char *p, *stripstr = NULL;
-
- data = notify->data;
- sel_debug("data->format is %d %p %p\n", data->format, notify, data);
- if (data->content == ECORE_X_SELECTION_CONTENT_FILES)
- {
- Efreet_Uri *uri;
- Eina_Strbuf *strbuf;
- int i;
-
- sel_debug("got a files list\n");
- files = notify->data;
- /*
- if (files->num_files > 1)
- {
- // Don't handle many items <- this makes mr bigglesworth sad :(
- sel_debug("more then one file: Bailing\n");
- return EINA_FALSE;
- }
- stripstr = p = strdup(files->files[0]);
- */
-
- strbuf = eina_strbuf_new();
- if (!strbuf)
- return EINA_FALSE;
-
- for (i = 0; i < files->num_files ; i++)
- {
- uri = efreet_uri_decode(files->files[i]);
- if (uri)
- {
- eina_strbuf_append(strbuf, uri->path);
- efreet_uri_free(uri);
- }
- else
- {
- eina_strbuf_append(strbuf, files->files[i]);
- }
- if (i < (files->num_files - 1))
- eina_strbuf_append(strbuf, "\n");
- }
- stripstr = eina_strbuf_string_steal(strbuf);
- eina_strbuf_free(strbuf);
- }
- else
- {
- Efreet_Uri *uri;
-
- p = (char *)eina_memdup((unsigned char *)data->data, data->length, EINA_TRUE);
- if (!p) return EINA_FALSE;
- uri = efreet_uri_decode(p);
- if (!uri)
- {
- /* Is there any reason why we care of URI without scheme? */
- if (p[0] == '/') stripstr = p;
- else free(p);
- }
- else
- {
- free(p);
- stripstr = strdup(uri->path);
- efreet_uri_free(uri);
- }
- }
-
- if (!stripstr)
- {
- sel_debug("Couldn't find a file\n");
- return EINA_FALSE;
- }
- free(seat_sel->saved_types->imgfile);
-#if 0 // this seems to be broken - we should be handling uri lists as text
- if (seat_sel->saved_types->textreq)
- {
- seat_sel->saved_types->textreq = 0;
- seat_sel->saved_types->imgfile = stripstr;
- }
- else
-#endif
- {
- ddata->format = EFL_UI_SELECTION_FORMAT_TEXT;
- ddata->content.mem = stripstr;
- ddata->content.len = strlen(stripstr);
- seat_sel->saved_types->imgfile = NULL;
- }
- return EINA_TRUE;
-}
-
-/**
- * Just received an vcard, either through cut and paste, or dnd.
- */
-static Eina_Bool
-_x11_data_preparer_vcard(Sel_Manager_Seat_Selection *seat_sel EINA_UNUSED,
- Ecore_X_Event_Selection_Notify *notify,
- Efl_Ui_Selection_Data *ddata, Tmp_Info **tmp_info EINA_UNUSED)
-{
- sel_debug("vcard receive\n");
- Ecore_X_Selection_Data *data = notify->data;
- ddata->format = EFL_UI_SELECTION_FORMAT_VCARD;
- ddata->content.mem = eina_memdup(data->data, data->length, EINA_TRUE);
- ddata->content.len = data->length;
- return EINA_TRUE;
-}
-
-static Eina_Bool
-_x11_data_preparer_image(Sel_Manager_Seat_Selection *seat_sel EINA_UNUSED,
- Ecore_X_Event_Selection_Notify *notify,
- Efl_Ui_Selection_Data *ddata, Tmp_Info **tmp_info)
-{
- Ecore_X_Selection_Data *data = notify->data;
- sel_debug("got a image file!\n");
- sel_debug("Size if %d\n", data->length);
-
- ddata->format = EFL_UI_SELECTION_FORMAT_IMAGE;
- data = notify->data;
-
- Tmp_Info *tmp = _tempfile_new(data->length);
- if (!tmp) return EINA_FALSE;
- memcpy(tmp->map, data->data, data->length);
- munmap(tmp->map, data->length);
- ddata->content.mem = strdup(tmp->filename);
- ddata->content.len = strlen(tmp->filename);
- *tmp_info = tmp;
- return EINA_TRUE;
-}
-
-static Eina_Bool
-_x11_win_filter(Eo *manager EINA_UNUSED, Ecore_X_Window xwin)
-{
- Eo *win;
- const Eina_List *l;
-
- EINA_LIST_FOREACH(_elm_win_list, l, win)
- {
- if (elm_win_window_id_get(win) == xwin) return EINA_FALSE;
- }
- return EINA_TRUE;
-}
-
-/*
- * Callback to handle a targets response on a selection request:
- * So pick the format we'd like; and then request it.
- */
-static Eina_Bool
-_x11_notify_handler_targets(Efl_Ui_Selection_Manager_Data *pd, Sel_Manager_Selection *sel, Ecore_X_Event_Selection_Notify *notify)
-{
- sel_debug("notify handler targets");
- Ecore_X_Selection_Data_Targets *targets;
- Ecore_X_Atom *atom_list;
- int i, j;
-
- targets = notify->data;
- atom_list = (Ecore_X_Atom *)(targets->data.data);
- for (j = (SELECTION_ATOM_LISTING_ATOMS + 1); j < SELECTION_N_ATOMS; j++)
- {
- sel_debug("\t%s %d", pd->atom_list[j].name, pd->atom_list[j].x_atom);
- if (!(pd->atom_list[j].format & sel->request_format)) continue;
- for (i = 0; i < targets->data.length; i++)
- {
- if ((pd->atom_list[j].x_atom == atom_list[i]) && (pd->atom_list[j].x_data_preparer))
- {
- if (j == SELECTION_ATOM_TEXT_URILIST)
- {
- if (!_x11_is_uri_type_data(sel, notify)) continue;
- }
- sel_debug("Atom %s matches", pd->atom_list[j].name);
- goto done;
- }
- }
- }
- sel_debug("Couldn't find anything that matches");
- return ECORE_CALLBACK_PASS_ON;
-done:
- sel_debug("Sending request for %s, xwin=%#llx",
- pd->atom_list[j].name, (unsigned long long)sel->xwin);
- sel->request(sel->xwin, pd->atom_list[j].name);
- return ECORE_CALLBACK_PASS_ON;
-}
-
-static Eina_Bool
-_x11_fixes_selection_notify(void *data, int t EINA_UNUSED, void *event)
-{
- Efl_Ui_Selection_Manager_Data *pd = data;
- Efl_Ui_Selection_Changed e;
- Elm_Cnp_Event_Selection_Changed *_e;
- Ecore_X_Event_Fixes_Selection_Notify *ev = event;
- Sel_Manager_Seat_Selection *seat_sel;
- Efl_Ui_Selection_Type type;
- Sel_Manager_Selection *sel;
-
- if (_x11_win_filter(pd->sel_man, ev->win)) return ECORE_CALLBACK_PASS_ON;
-
- switch (ev->selection)
- {
- case ECORE_X_SELECTION_CLIPBOARD:
- type = EFL_UI_SELECTION_TYPE_CLIPBOARD;
- break;
- case ECORE_X_SELECTION_PRIMARY:
- type = EFL_UI_SELECTION_TYPE_PRIMARY;
- break;
- default: return ECORE_CALLBACK_RENEW;
- }
- seat_sel = _x11_sel_manager_seat_selection_init(pd, 1);
- if (!seat_sel) return ECORE_CALLBACK_RENEW;
- sel = seat_sel->sel_list + type;
- if (sel->active && (sel->xwin != ev->owner))
- efl_ui_selection_manager_selection_clear(pd->sel_man, sel->owner, type, seat_sel->seat);
- e.type = type;
- e.seat = 1; /* under x11 this is always the default seat */
- e.exist = !!ev->owner;
-
- _e = calloc(1, sizeof(Elm_Cnp_Event_Selection_Changed));
- EINA_SAFETY_ON_NULL_RETURN_VAL(_e, ECORE_CALLBACK_RENEW);
- _e->type = type;
- _e->seat_id = 1;
- _e->exists = e.exist;
-
- ecore_event_add(ELM_CNP_EVENT_SELECTION_CHANGED, _e, NULL, NULL);
- efl_event_callback_call(sel->owner, EFL_UI_SELECTION_EVENT_WM_SELECTION_CHANGED, &e);
-
- return ECORE_CALLBACK_RENEW;
-}
-
-/*
- * Response to a selection notify:
- * - So we have asked for the selection list.
- * - If it's the targets list, parse it, and fire of what we want,
- * else it's the data we want.
- */
-//NB: x11 does not have seat, use 1 as default
-static Eina_Bool
-_efl_sel_manager_x11_selection_notify(void *udata, int type EINA_UNUSED, void *event)
-{
- Efl_Ui_Selection_Manager_Data *pd = udata;
- Ecore_X_Event_Selection_Notify *ev = event;
- Sel_Manager_Selection *sel;
- Sel_Manager_Seat_Selection *seat_sel = NULL;
- int i;
-
- if (_x11_win_filter(pd->sel_man, ev->win)) return ECORE_CALLBACK_PASS_ON;
-
- seat_sel = _sel_manager_seat_selection_get(pd, 1);
- if (!seat_sel)
- return EINA_FALSE;
-
- sel_debug("selection notify callback: %d", ev->selection);
- switch (ev->selection)
- {
- case ECORE_X_SELECTION_PRIMARY:
- sel = seat_sel->sel_list + EFL_UI_SELECTION_TYPE_PRIMARY;
- break;
- case ECORE_X_SELECTION_SECONDARY:
- sel = seat_sel->sel_list + EFL_UI_SELECTION_TYPE_SECONDARY;
- break;
- case ECORE_X_SELECTION_XDND:
- sel = seat_sel->sel_list + EFL_UI_SELECTION_TYPE_DND;
- break;
- case ECORE_X_SELECTION_CLIPBOARD:
- sel = seat_sel->sel_list + EFL_UI_SELECTION_TYPE_CLIPBOARD;
- break;
- default:
- return ECORE_CALLBACK_PASS_ON;
- }
- sel_debug("Target is %s", ev->target);
- if (!sel->asked) return ECORE_CALLBACK_PASS_ON;
- sel->asked--;
-
- if (ev->selection != ECORE_X_SELECTION_XDND &&
- (!strcmp(ev->target, "TARGETS") || !strcmp(ev->target, "ATOMS")))
- {
- _x11_notify_handler_targets(pd, sel, ev);
- return ECORE_CALLBACK_PASS_ON;
- }
- for (i = 0; i < SELECTION_N_ATOMS; i++)
- {
- if (!strcmp(ev->target, pd->atom_list[i].name))
- {
- if (pd->atom_list[i].x_data_preparer)
- {
- Efl_Ui_Selection_Data ddata = { 0 };
- Tmp_Info *tmp_info = NULL;
- Eina_Bool success;
- sel_debug("Found something: %s", pd->atom_list[i].name);
-
- success = pd->atom_list[i].x_data_preparer(seat_sel, ev, &ddata, &tmp_info);
- sel_debug("ddata: %s (%zd)", (const char *)ddata.content.mem, ddata.content.len);
- if ((pd->atom_list[i].format == EFL_UI_SELECTION_FORMAT_IMAGE) &&
- (seat_sel->saved_types->imgfile))
- break;
- if (ev->selection == ECORE_X_SELECTION_XDND)
- {
- if (success)
- {
- Sel_Manager_Dropable *dropable;
- Eina_List *l;
- sel_debug("drag & drop\n");
- EINA_LIST_FOREACH(pd->drop_list, l, dropable)
- {
- if (dropable->obj == sel->request_obj) break;
- dropable = NULL;
- }
- if (dropable)
- {
- Drop_Format *df;
- Eina_Inlist *itr;
-
- ddata.action = sel->action;
- if (!dropable->is_container)
- {
- sel_debug("normal dnd, not container");
- ddata.pos = seat_sel->saved_types->pos;
- }
- else
- {
- sel_debug("Drop on container");
- Eina_Position2D pos, posret = {0, 0};
- evas_object_geometry_get(dropable->obj, &pos.x, &pos.y, NULL, NULL);
- //get item
- pos = EINA_POSITION2D(seat_sel->saved_types->pos.x + pos.x,
- seat_sel->saved_types->pos.y + pos.y);
- Efl_Object *it = NULL;
- if (dropable->item_func)
- it = dropable->item_func(dropable->item_func_data,
- dropable->obj, pos, &posret);
- ddata.pos = posret;
- ddata.item = it;
- }
- EINA_INLIST_FOREACH_SAFE(dropable->format_list, itr, df)
- {
- if (df->format & dropable->last.format)
- {
- sel_debug("calling Drop event on: %p", dropable->obj);
- efl_event_callback_call(dropable->obj, EFL_UI_DND_EVENT_DRAG_DROP, &ddata);
- }
- }
- }
- else
- {
- sel_debug("dnd: has NO dropable");
- }
- }
- /* We have to finish DnD, no matter what */
- ecore_x_dnd_send_finished();
- }
- else if (sel->data_func && success)
- {
- ddata.pos.x = ddata.pos.y = 0;
- sel->data_func(sel->data_func_data, sel->request_obj, &ddata);
- }
- free((void *)ddata.content.mem);
- if (tmp_info) _tmpinfo_free(tmp_info);
- }
- else sel_debug("Ignored: No handler!");
- break;
- }
- }
- return ECORE_CALLBACK_PASS_ON;
-}
-
-static Eina_Bool
-_x11_selection_clear(void *data, int type EINA_UNUSED, void *event)
-{
- Efl_Ui_Selection_Manager_Data *pd = data;
- Ecore_X_Event_Selection_Clear *ev = event;
- Sel_Manager_Selection *sel;
- Sel_Manager_Seat_Selection *seat_sel = NULL;
- Eina_List *l, *l_next;
- Sel_Manager_Selection_Lost *sel_lost;
- unsigned int i;
-
- if (_x11_win_filter(pd->sel_man, ev->win)) return ECORE_CALLBACK_PASS_ON;
-
- seat_sel = _sel_manager_seat_selection_get(pd, 1);
- if (!seat_sel)
- return EINA_FALSE;
-
- for (i = EFL_UI_SELECTION_TYPE_PRIMARY; i <= EFL_UI_SELECTION_TYPE_CLIPBOARD; i++)
- {
- if (seat_sel->sel_list[i].ecore_sel == ev->selection) break;
- }
- sel_debug("selection %d clear", i);
- /* Not me... Don't care */
- if (i > EFL_UI_SELECTION_TYPE_CLIPBOARD) return ECORE_CALLBACK_PASS_ON;
-
- sel = seat_sel->sel_list + i;
-
- EINA_LIST_FOREACH_SAFE(seat_sel->sel_lost_list, l, l_next, sel_lost)
- {
- if ((sel_lost->request == sel->owner) &&
- (sel_lost->type == i))
- {
- sel_debug("resolve the promise: %p", sel_lost->promise);
- eina_promise_resolve(sel_lost->promise, eina_value_uint_init(sel_lost->type));
- }
- }
- sel->active = EINA_FALSE;
- sel->owner = NULL;
-
- return ECORE_CALLBACK_PASS_ON;
-}
-
-static Eina_Bool
-_x11_general_converter(char *target EINA_UNUSED, void *data, int size EINA_UNUSED, void **data_ret, int *size_ret, Ecore_X_Atom *ttype EINA_UNUSED, int *typesize EINA_UNUSED)
-{
- sel_debug("general converter");
- Sel_Manager_Selection *sel = *(Sel_Manager_Selection **)data;
- if (sel->format == EFL_UI_SELECTION_FORMAT_NONE)
- {
- if (data_ret)
- {
- *data_ret = malloc(sel->data.len * sizeof(char) + 1);
- if (!*data_ret) return EINA_FALSE;
- memcpy(*data_ret, sel->data.mem, sel->data.len);
- ((char**)(data_ret))[0][sel->data.len] = 0;
- }
- if (size_ret) *size_ret = sel->data.len;
- }
- else
- {
- if (sel->data.mem)
- {
- if (data_ret)
- *data_ret = eina_memdup(sel->data.mem, sel->data.len, 1);
- if (size_ret) *size_ret = sel->data.len;
- }
- else
- {
- if (data_ret) *data_ret = NULL;
- if (size_ret) *size_ret = 0;
- }
- }
- return EINA_TRUE;
-}
-
-static Eina_Bool
-_x11_targets_converter(char *target EINA_UNUSED, void *data, int size EINA_UNUSED, void **data_ret, int *size_ret, Ecore_X_Atom *ttype, int *typesize)
-{
- int i, count;
- Ecore_X_Atom *aret;
- Sel_Manager_Selection *sel;
- Efl_Ui_Selection_Format seltype;
-
- sel_debug("target converter");
- if (!data_ret) return EINA_FALSE;
-
- sel = *(Sel_Manager_Selection **)data;
- seltype = sel->format;
- Sel_Manager_Seat_Selection *seat_sel = sel->seat_sel;
- Efl_Ui_Selection_Manager_Data *pd = seat_sel->pd;
-
- for (i = SELECTION_ATOM_LISTING_ATOMS + 1, count = 0; i < SELECTION_N_ATOMS ; i++)
- {
- if (seltype & pd->atom_list[i].format) count++;
- }
- aret = malloc(sizeof(Ecore_X_Atom) * count);
- if (!aret) return EINA_FALSE;
- for (i = SELECTION_ATOM_LISTING_ATOMS + 1, count = 0; i < SELECTION_N_ATOMS ; i++)
- {
- if (seltype & pd->atom_list[i].format)
- aret[count ++] = pd->atom_list[i].x_atom;
- }
-
- *data_ret = aret;
- if (typesize) *typesize = 32 /* urk */;
- if (ttype) *ttype = ECORE_X_ATOM_ATOM;
- if (size_ret) *size_ret = count;
- return EINA_TRUE;
-}
-
-static Eina_Bool
-_x11_image_converter(char *target EINA_UNUSED, void *data EINA_UNUSED, int size EINA_UNUSED, void **data_ret EINA_UNUSED, int *size_ret EINA_UNUSED, Ecore_X_Atom *ttype EINA_UNUSED, int *typesize EINA_UNUSED)
-{
- sel_debug("Image converter called");
- return EINA_TRUE;
-}
-
-static Eina_Bool
-_x11_vcard_send(char *target EINA_UNUSED, void *data EINA_UNUSED, int size EINA_UNUSED, void **data_ret, int *size_ret, Ecore_X_Atom *ttype EINA_UNUSED, int *typesize EINA_UNUSED)
-{
- Sel_Manager_Selection *sel;
-
- sel_debug("Vcard send called");
- sel = *(Sel_Manager_Selection **)data;
- if (data_ret)
- {
- char *s;
-
- s = malloc(sel->data.len + 1);
- if (!s) return EINA_FALSE;
- memcpy(s, sel->data.mem, sel->data.len);
- s[sel->data.len] = 0;
- *data_ret = s;
- }
-
- if (size_ret) *size_ret = sel->data.len;
- return EINA_TRUE;
-}
-
-static Eina_Bool
-_x11_text_converter(char *target, void *data, int size EINA_UNUSED, void **data_ret, int *size_ret, Ecore_X_Atom *ttype, int *typesize)
-{
- Sel_Manager_Selection *sel;
-
- sel = *(Sel_Manager_Selection **)data;
- if (!sel) return EINA_FALSE;
-
- sel_debug("text converter");
- if (sel->format == EFL_UI_SELECTION_FORMAT_NONE)
- {
- sel_debug("none");
- if (data_ret)
- {
- *data_ret = malloc(sel->data.len * sizeof(char) + 1);
- if (!*data_ret) return EINA_FALSE;
- memcpy(*data_ret, data, sel->data.len);
- ((char**)(data_ret))[0][sel->data.len] = 0;
- }
- if (size_ret) *size_ret = sel->data.len;
- return EINA_TRUE;
- }
-
- if (!sel->active) return EINA_TRUE;
-
- if ((sel->format & EFL_UI_SELECTION_FORMAT_MARKUP) ||
- (sel->format & EFL_UI_SELECTION_FORMAT_HTML))
- {
- char *tmp = malloc(sel->data.len + 1);
- if (tmp)
- {
- strncpy(tmp, sel->data.mem, sel->data.len);
- tmp[sel->data.len] = 0;
- *data_ret = _elm_util_mkup_to_text(tmp);
- if (size_ret && *data_ret) *size_ret = strlen(*data_ret);
- free(tmp);
- sel_debug("markup or html: %s", (const char *)*data_ret);
- }
- else return EINA_FALSE;
- }
- else if (sel->format & EFL_UI_SELECTION_FORMAT_TEXT)
- {
- ecore_x_selection_converter_text(target, sel->data.mem,
- sel->data.len,
- data_ret, size_ret,
- ttype, typesize);
- sel_debug("text");
- }
- else if (sel->format & EFL_UI_SELECTION_FORMAT_IMAGE)
- {
- efl_file_simple_get(sel->request_obj, (const char **)data_ret, NULL);
- if (!*data_ret) *data_ret = strdup("No file");
- else *data_ret = strdup(*data_ret);
-
- if (!*data_ret)
- {
- ERR("Failed to allocate memory!");
- *size_ret = 0;
- return EINA_FALSE;
- }
-
- *size_ret = strlen(*data_ret);
- }
- return EINA_TRUE;
-}
-
-static Eina_Future *
-_x11_efl_sel_manager_selection_set(Efl_Ui_Selection_Manager_Data *pd, Efl_Object *owner,
- Efl_Ui_Selection_Type type, Efl_Ui_Selection_Format format, Eina_Slice data,
- Ecore_X_Window xwin, unsigned int seat)
-{
- Sel_Manager_Seat_Selection *seat_sel;
- Sel_Manager_Selection *sel;
- Eina_Bool same_win = EINA_FALSE;
-
- seat_sel = _x11_sel_manager_seat_selection_init(pd, seat);
- seat_sel->active_type = type;
- sel = seat_sel->sel_list + type;
- //support 1 app with multiple window, 1 selection manager
- if (seat_sel->xwin == xwin)
- same_win = EINA_TRUE;
- _owner_change_check(pd->sel_man, owner, seat_sel, sel, type, same_win);
- seat_sel->xwin = xwin;
-
- sel->owner = owner;
- free(sel->data.mem);
- sel->xwin = xwin;
- sel->data = eina_slice_dup(data);
- sel->active = EINA_TRUE;
- sel->format = format;
-
- sel->set(xwin, &sel, sizeof(Sel_Manager_Selection *));
- sel_debug("data: %p (%zu)", &sel, sizeof(Sel_Manager_Selection *));
-
- return _update_sel_lost_list(owner, type, seat_sel);
-}
-
-static void
-_x11_efl_sel_manager_selection_get(const Efl_Object *request, Efl_Ui_Selection_Manager_Data *pd,
- 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,
- Ecore_X_Window xwin, unsigned int seat)
-{
- Sel_Manager_Seat_Selection *seat_sel;
- Sel_Manager_Selection *sel;;
-
- sel_debug("request: %p, seat: %u, type: %d, format: %d", request, seat, type, format);
- seat_sel = _sel_manager_seat_selection_init(pd, seat);
- sel = seat_sel->sel_list + type;
- sel->request_obj = (Efl_Object *)request;
- sel->data_func_data = data_func_data;
- sel->data_func = data_func;
- sel->data_func_free_cb = data_func_free_cb;
- sel->request_format = format;
- sel->xwin = xwin;
-
- if (sel->active)
- {
- if (sel->data.mem &&
- ((format == sel->format) || (xwin == 0)))
- {
- sel_debug("use local data");
- Efl_Ui_Selection_Data seldata;
-
- seldata.content.mem = sel->data.mem;
- seldata.content.len = sel->data.len;
- seldata.pos.x = seldata.pos.y = 0;
- seldata.format = sel->format;
- sel->data_func(sel->data_func_data, sel->request_obj, &seldata);
- return;
- }
- }
-
- sel->asked = 2;
- sel->request(xwin, ECORE_X_SELECTION_TARGET_TARGETS);
-}
-
-static void
-_x11_win_rotation_changed_cb(void *data, const Efl_Event *event)
-{
- Evas_Object *win = data;
- int rot = elm_win_rotation_get(event->object);
- elm_win_rotation_set(win, rot);
-}
-
-static Eina_Bool
-_x11_drag_mouse_up(void *data, int etype EINA_UNUSED, void *event)
-{
- Sel_Manager_Seat_Selection *seat_sel = data;
- Efl_Ui_Selection_Manager_Data *pd = seat_sel->pd;
- Ecore_X_Window xwin = seat_sel->xwin;
- Ecore_Event_Mouse_Button *ev = event;
-
- if ((ev->buttons == 1) &&
- (ev->event_window == xwin))
- {
- Eina_Bool have_drop_list = EINA_FALSE;
- Eina_List *l;
- Sel_Manager_Dropable *dropable;
-
- ecore_x_pointer_ungrab();
- ELM_SAFE_FREE(seat_sel->mouse_up_handler, ecore_event_handler_del);
- ELM_SAFE_FREE(seat_sel->dnd_status_handler, ecore_event_handler_del);
- ecore_x_dnd_self_drop();
-
- sel_debug("mouse up, xwin=%#llx\n", (unsigned long long)xwin);
-
- EINA_LIST_FOREACH(pd->drop_list, l, dropable)
- {
- if (xwin == _x11_xwin_get(dropable->obj))
- {
- have_drop_list = EINA_TRUE;
- break;
- }
- }
- if (!have_drop_list) ecore_x_dnd_aware_set(xwin, EINA_FALSE);
- efl_event_callback_call(seat_sel->drag_obj, EFL_UI_DND_EVENT_DRAG_DONE, NULL);
- if (seat_sel->drag_win)
- {
- if (seat_sel->drag_obj)
- {
- if (elm_widget_is(seat_sel->drag_obj))
- {
- Evas_Object *win = elm_widget_top_get(seat_sel->drag_obj);
- if (win && efl_isa(win, EFL_UI_WIN_CLASS))
- efl_event_callback_del(win, EFL_UI_WIN_EVENT_WIN_ROTATION_CHANGED,
- _x11_win_rotation_changed_cb, seat_sel->drag_win);
- }
- }
-
- if (!seat_sel->accept)
- { /* Commit animation when drag cancelled */
- /* Record final position of dragwin, then do animation */
- ecore_evas_animator_timeline_add(seat_sel->drag_win, 0.3,
- _drag_cancel_animate, seat_sel);
- }
- else
- { /* No animation drop was committed */
- Ecore_X_Window xdragwin = _x11_xwin_get(seat_sel->drag_win);
- ecore_x_window_ignore_set(xdragwin, 0);
- evas_object_del(seat_sel->drag_win);
- seat_sel->drag_win = NULL;
- sel_debug("deleted drag_win");
- }
- }
-
- seat_sel->drag_obj = NULL;
- seat_sel->accept = EINA_FALSE;
- }
- return EINA_TRUE;
-}
-
-static void
-_x11_drag_move(void *data, Ecore_X_Xdnd_Position *pos)
-{
- Sel_Manager_Seat_Selection *seat_sel = data;
- Efl_Dnd_Drag_Pos dp;
-
- evas_object_move(seat_sel->drag_win,
- pos->position.x - seat_sel->drag_pos.x,
- pos->position.y - seat_sel->drag_pos.y);
- seat_sel->drag_win_end.x = pos->position.x - seat_sel->drag_pos.x;
- seat_sel->drag_win_end.y = pos->position.y - seat_sel->drag_pos.y;
- sel_debug("dragevas: %p -> %p\n",
- seat_sel->drag_obj,
- evas_object_evas_get(seat_sel->drag_obj));
- dp.pos.x = pos->position.x;
- dp.pos.y = pos->position.y;
- dp.action = seat_sel->drag_action;
- //for drag side
- efl_event_callback_call(seat_sel->drag_obj, EFL_UI_DND_EVENT_DRAG_POS, &dp);
-}
-
-static void
-_x11_drag_target_del(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *info EINA_UNUSED)
-{
- Sel_Manager_Seat_Selection *seat_sel = data;
- Sel_Manager_Selection *sel = &seat_sel->sel_list[seat_sel->active_type];
-
- if (seat_sel->drag_obj == obj)
- {
- sel->request_obj = NULL;
- seat_sel->drag_obj = NULL;
- }
-}
-
-static Eina_Bool
-_x11_dnd_status(void *data, int etype EINA_UNUSED, void *ev)
-{
- Sel_Manager_Seat_Selection *seat_sel = data;
- Ecore_X_Event_Xdnd_Status *status = ev;
-
- seat_sel->accept = EINA_FALSE;
-
- /* Only thing we care about: will accept */
- if ((status) && (status->will_accept))
- {
- sel_debug("Will accept\n");
- seat_sel->accept = EINA_TRUE;
- }
- /* Won't accept */
- else
- {
- sel_debug("Won't accept accept\n");
- }
- efl_event_callback_call(seat_sel->drag_obj, EFL_UI_DND_EVENT_DRAG_ACCEPT, &seat_sel->accept);
-
- return EINA_TRUE;
-}
-
-static void
-_x11_efl_sel_manager_drag_start(Eo *obj EINA_UNUSED, Efl_Ui_Selection_Manager_Data *pd,
- Efl_Object *drag_obj, 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 EINA_UNUSED,
- Ecore_X_Window xwin, unsigned int seat)
-{
- Ecore_X_Window xdragwin;
- Sel_Manager_Seat_Selection *seat_sel;
- Sel_Manager_Selection *sel;
- Ecore_Evas *ee;
- int x, y, x2 = 0, y2 = 0, x3, y3;
- Evas_Object *icon = NULL;
- int w = 0, h = 0;
- int ex, ey, ew, eh;
- Ecore_X_Atom actx;
- int i;
- int xr, yr, rot;
-
- seat_sel = _x11_sel_manager_seat_selection_init(pd, seat);
- if (!seat_sel) return;
- seat_sel->active_type = EFL_UI_SELECTION_TYPE_DND;
-
- sel = &seat_sel->sel_list[seat_sel->active_type];
- ecore_x_dnd_types_set(xwin, NULL, 0);
- for (i = SELECTION_ATOM_LISTING_ATOMS + 1; i < SELECTION_N_ATOMS; i++)
- {
- if (format == EFL_UI_SELECTION_FORMAT_TARGETS || (pd->atom_list[i].format & format))
- {
- ecore_x_dnd_type_set(xwin, pd->atom_list[i].name, EINA_TRUE);
- sel_debug("set dnd type: %s\n", pd->atom_list[i].name);
- }
- }
-
- sel->active = EINA_TRUE;
- sel->request_obj = drag_obj;
- sel->format = format;
- if (sel->data.mem) free(sel->data.mem);
- sel->data = eina_slice_dup(data);
- sel->action = action;
- seat_sel->drag_obj = drag_obj;
- seat_sel->drag_action = action;
- seat_sel->xwin = xwin;
-
- evas_object_event_callback_add(drag_obj, EVAS_CALLBACK_DEL,
- _x11_drag_target_del, seat_sel);
- /* TODO BUG: should increase dnd-awareness, in case it's drop target as well. See _x11_drag_mouse_up() */
- ecore_x_dnd_aware_set(xwin, EINA_TRUE);
- ecore_x_dnd_callback_pos_update_set(_x11_drag_move, seat_sel);
- ecore_x_dnd_self_begin(xwin, (unsigned char *)sel, sizeof(Sel_Manager_Selection));
- actx = _x11_dnd_action_rev_map(seat_sel->drag_action);
- ecore_x_dnd_source_action_set(actx);
- ecore_x_pointer_grab(xwin);
- seat_sel->mouse_up_handler = ecore_event_handler_add(ECORE_EVENT_MOUSE_BUTTON_UP,
- _x11_drag_mouse_up, seat_sel);
- seat_sel->dnd_status_handler = ecore_event_handler_add(ECORE_X_EVENT_XDND_STATUS,
- _x11_dnd_status, seat_sel);
- seat_sel->drag_win = elm_win_add(NULL, "Elm-Drag", ELM_WIN_DND);
- elm_win_alpha_set(seat_sel->drag_win, EINA_TRUE);
- elm_win_override_set(seat_sel->drag_win, EINA_TRUE);
- xdragwin = _x11_xwin_get(seat_sel->drag_win);
- ecore_x_window_ignore_set(xdragwin, 1);
-
- /* dragwin has to be rotated as the main window is */
- if (elm_widget_is(drag_obj))
- {
- Evas_Object *win = elm_widget_top_get(drag_obj);
- if (win && efl_isa(win, EFL_UI_WIN_CLASS))
- {
- elm_win_rotation_set(seat_sel->drag_win, elm_win_rotation_get(win));
- efl_event_callback_add(win, EFL_UI_WIN_EVENT_WIN_ROTATION_CHANGED,
- _x11_win_rotation_changed_cb, seat_sel->drag_win);
- }
- }
-
- if (icon_func)
- {
- Eina_Position2D off;
-
- icon = icon_func(icon_func_data, seat_sel->drag_win, drag_obj, &off);
- if (icon)
- {
- x2 = off.x;
- y2 = off.y;
- evas_object_geometry_get(icon, NULL, NULL, &w, &h);
- }
- }
- else
- {
- icon = elm_icon_add(seat_sel->drag_win);
- evas_object_size_hint_weight_set(icon, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
- // need to resize
- }
- elm_win_resize_object_add(seat_sel->drag_win, icon);
-
- /* Position subwindow appropriately */
- ee = ecore_evas_ecore_evas_get(evas_object_evas_get(drag_obj));
- ecore_evas_geometry_get(ee, &ex, &ey, &ew, &eh);
- evas_object_resize(seat_sel->drag_win, w, h);
-
- evas_object_show(icon);
- evas_object_show(seat_sel->drag_win);
- evas_pointer_canvas_xy_get(evas_object_evas_get(drag_obj), &x3, &y3);
-
- rot = ecore_evas_rotation_get(ee);
- switch (rot)
- {
- case 90:
- xr = y3;
- yr = ew - x3;
- seat_sel->drag_pos.x = y3 - y2;
- seat_sel->drag_pos.y = x3 - x2;
- break;
- case 180:
- xr = ew - x3;
- yr = eh - y3;
- seat_sel->drag_pos.x = x3 - x2;
- seat_sel->drag_pos.y = y3 - y2;
- break;
- case 270:
- xr = eh - y3;
- yr = x3;
- seat_sel->drag_pos.x = y3 - y2;
- seat_sel->drag_pos.y = x3 - x2;
- break;
- default:
- xr = x3;
- yr = y3;
- seat_sel->drag_pos.x = x3 - x2;
- seat_sel->drag_pos.y = y3 - y2;
- break;
- }
- x = ex + xr - seat_sel->drag_pos.x;
- y = ey + yr - seat_sel->drag_pos.y;
- evas_object_move(seat_sel->drag_win, x, y);
- seat_sel->drag_win_start = EINA_POSITION2D(x, y);
- seat_sel->drag_win_end = EINA_POSITION2D(x, y);
-}
-
-static void
-_x11_dnd_dropable_handle(Efl_Ui_Selection_Manager_Data *pd, Sel_Manager_Dropable *dropable, Eina_Position2D pos, Efl_Ui_Selection_Action action)
-{
- Sel_Manager_Dropable *d, *last_dropable = NULL;
- Eina_List *l;
- Eina_Inlist *itr;
-
- EINA_LIST_FOREACH(pd->drop_list, l, d)
- {
- if (d->last.in)
- {
- last_dropable = d;
- break;
- }
- }
- if (last_dropable)
- {
- if (last_dropable == dropable) // same
- {
- Evas_Coord ox, oy;
- Drop_Format *df;
-
- sel_debug("same obj dropable %p\n", dropable->obj);
- evas_object_geometry_get(dropable->obj, &ox, &oy, NULL, NULL);
- Efl_Dnd_Drag_Pos pos_data;
- if (!dropable->is_container)
- {
- pos_data.pos = EINA_POSITION2D(pos.x - ox, pos.y - oy);
- pos_data.item = NULL;
- }
- else
- {
- Eina_Position2D posret = {0, 0};
- Efl_Object *it = NULL;
-
- if (dropable->item_func)
- it = dropable->item_func(dropable->item_func_data, dropable->obj,
- pos, &posret);
- pos_data.pos = posret;
- pos_data.item = it;
- }
- pos_data.format = dropable->last.format;
- pos_data.action = action;
- EINA_INLIST_FOREACH_SAFE(dropable->format_list, itr, df)
- {
- if (df->format & dropable->last.format)
- efl_event_callback_call(dropable->obj, EFL_UI_DND_EVENT_DRAG_POS, &pos_data);
- }
- }
- else
- {
- if (dropable) // leave last obj and enter new one
- {
- sel_debug("leave %p\n", last_dropable->obj);
- sel_debug("enter %p\n", dropable->obj);
- last_dropable->last.in = EINA_FALSE;
- last_dropable->last.type = NULL;
- dropable->last.in = EINA_TRUE;
-
- Drop_Format *df;
- EINA_INLIST_FOREACH_SAFE(dropable->format_list, itr, df)
- {
- if (df->format &dropable->last.format)
- efl_event_callback_call(dropable->obj, EFL_UI_DND_EVENT_DRAG_ENTER, NULL);
- }
- EINA_INLIST_FOREACH_SAFE(last_dropable->format_list, itr, df)
- {
- if (df->format & last_dropable->last.format)
- efl_event_callback_call(last_dropable->obj, EFL_UI_DND_EVENT_DRAG_LEAVE, NULL);
- }
- }
- else // leave last obj
- {
- sel_debug("leave %p\n", last_dropable->obj);
- last_dropable->last.in = EINA_FALSE;
- last_dropable->last.type = NULL;
-
- Drop_Format *df;
- EINA_INLIST_FOREACH_SAFE(last_dropable->format_list, itr, df)
- {
- if (df->format & last_dropable->last.format)
- efl_event_callback_call(last_dropable->obj, EFL_UI_DND_EVENT_DRAG_LEAVE, NULL);
- }
- }
- }
- }
- else
- {
- if (dropable) // enter new obj
- {
- Evas_Coord ox, oy;
-
- sel_debug("enter %p\n", dropable->obj);
- evas_object_geometry_get(dropable->obj, &ox, &oy, NULL, NULL);
- dropable->last.in = EINA_TRUE;
-
- Drop_Format *df;
- Efl_Dnd_Drag_Pos pos_data;
- if (!dropable->is_container)
- {
- pos_data.pos = EINA_POSITION2D(pos.x - ox, pos.y - oy);
- pos_data.item = NULL;
- }
- else
- {
- Eina_Position2D posret = {0, 0};
- Efl_Object *it = NULL;
- if (dropable->item_func)
- it = dropable->item_func(dropable->item_func_data, dropable->obj,
- pos, &posret);
- pos_data.pos = posret;
- pos_data.item = it;
- }
- pos_data.format = dropable->last.format;
- pos_data.action = action;
- EINA_INLIST_FOREACH_SAFE(dropable->format_list, itr, df)
- {
- if (df->format & dropable->last.format)
- {
- efl_event_callback_call(dropable->obj, EFL_UI_DND_EVENT_DRAG_ENTER, NULL);
- efl_event_callback_call(dropable->obj, EFL_UI_DND_EVENT_DRAG_POS, &pos_data);
- }
- }
- }
- else
- {
- sel_debug("both dropable & last_dropable are null\n");
- }
- }
-}
-
-static Sel_Manager_Dropable *
-_x11_dropable_find(Efl_Ui_Selection_Manager_Data *pd, Ecore_X_Window win)
-{
- Eina_List *l;
- Sel_Manager_Dropable *dropable;
-
- if (!pd->drop_list) return NULL;
- EINA_LIST_FOREACH(pd->drop_list, l, dropable)
- {
- if (_x11_xwin_get(dropable->obj) == win) return dropable;
- }
- return NULL;
-}
-
-static Evas *
-_x11_evas_get_from_xwin(Efl_Ui_Selection_Manager_Data *pd, Ecore_X_Window win)
-{
- /* Find the Evas connected to the window */
- Sel_Manager_Dropable *dropable = _x11_dropable_find(pd, win);
- return dropable ? evas_object_evas_get(dropable->obj) : NULL;
-}
-
-static Efl_Ui_Selection_Action
-_x11_dnd_action_map(Ecore_X_Atom action)
-{
- Efl_Ui_Selection_Action act = EFL_UI_SELECTION_ACTION_UNKNOWN;
-
- if (action == ECORE_X_ATOM_XDND_ACTION_COPY)
- act = EFL_UI_SELECTION_ACTION_COPY;
- else if (action == ECORE_X_ATOM_XDND_ACTION_MOVE)
- act = EFL_UI_SELECTION_ACTION_MOVE;
- else if (action == ECORE_X_ATOM_XDND_ACTION_PRIVATE)
- act = EFL_UI_SELECTION_ACTION_PRIVATE;
- else if (action == ECORE_X_ATOM_XDND_ACTION_ASK)
- act = EFL_UI_SELECTION_ACTION_ASK;
- else if (action == ECORE_X_ATOM_XDND_ACTION_LIST)
- act = EFL_UI_SELECTION_ACTION_LIST;
- else if (action == ECORE_X_ATOM_XDND_ACTION_LINK)
- act = EFL_UI_SELECTION_ACTION_LINK;
- else if (action == ECORE_X_ATOM_XDND_ACTION_DESCRIPTION)
- act = EFL_UI_SELECTION_ACTION_DESCRIPTION;
- return act;
-}
-
-static Ecore_X_Atom
-_x11_dnd_action_rev_map(Efl_Ui_Selection_Action action)
-{
- Ecore_X_Atom act = ECORE_X_ATOM_XDND_ACTION_MOVE;
-
- if (action == EFL_UI_SELECTION_ACTION_COPY)
- act = ECORE_X_ATOM_XDND_ACTION_COPY;
- else if (action == EFL_UI_SELECTION_ACTION_MOVE)
- act = ECORE_X_ATOM_XDND_ACTION_MOVE;
- else if (action == EFL_UI_SELECTION_ACTION_PRIVATE)
- act = ECORE_X_ATOM_XDND_ACTION_PRIVATE;
- else if (action == EFL_UI_SELECTION_ACTION_ASK)
- act = ECORE_X_ATOM_XDND_ACTION_ASK;
- else if (action == EFL_UI_SELECTION_ACTION_LIST)
- act = ECORE_X_ATOM_XDND_ACTION_LIST;
- else if (action == EFL_UI_SELECTION_ACTION_LINK)
- act = ECORE_X_ATOM_XDND_ACTION_LINK;
- else if (action == EFL_UI_SELECTION_ACTION_DESCRIPTION)
- act = ECORE_X_ATOM_XDND_ACTION_DESCRIPTION;
- return act;
-}
-
-static Eina_Bool
-_x11_dnd_enter(void *data, int etype EINA_UNUSED, void *ev)
-{
- Sel_Manager_Seat_Selection *seat_sel = data;
- Efl_Ui_Selection_Manager_Data *pd = seat_sel->pd;
- Ecore_X_Event_Xdnd_Enter *enter = ev;
- Sel_Manager_Dropable *dropable;
- int i;
-
- sel_debug("In");
- if (!enter) return EINA_TRUE;
- dropable = _x11_dropable_find(pd, enter->win);
- if (dropable)
- {
- sel_debug("Enter %x\n", enter->win);
- }
- /* Skip it */
- sel_debug("enter types=%p (%d)\n", enter->types, enter->num_types);
- if ((!enter->num_types) || (!enter->types)) return EINA_TRUE;
-
- sel_debug("Types\n");
- seat_sel->saved_types->ntypes = enter->num_types;
- free(seat_sel->saved_types->types);
- seat_sel->saved_types->types = malloc(sizeof(char *) * enter->num_types);
- if (!seat_sel->saved_types->types) return EINA_FALSE;
-
- for (i = 0; i < enter->num_types; i++)
- {
- seat_sel->saved_types->types[i] = eina_stringshare_add(enter->types[i]);
- sel_debug("Type is %s %p %p\n", enter->types[i],
- seat_sel->saved_types->types[i], pd->text_uri);
- if (seat_sel->saved_types->types[i] == pd->text_uri)
- {
- /* Request it, so we know what it is */
- sel_debug("Sending uri request\n");
- seat_sel->saved_types->textreq = 1;
- ELM_SAFE_FREE(seat_sel->saved_types->imgfile, free);
- ecore_x_selection_xdnd_request(enter->win, pd->text_uri);
- }
- }
-
- /* FIXME: Find an object and make it current */
- return EINA_TRUE;
-}
-
-static Eina_Bool
-_x11_dnd_position(void *data, int etype EINA_UNUSED, void *ev)
-{
- Sel_Manager_Seat_Selection *seat_sel = data;
- Efl_Ui_Selection_Manager_Data *pd = seat_sel->pd;
- Ecore_X_Event_Xdnd_Position *xpos = ev;
- Ecore_X_Rectangle rect = { 0, 0, 0, 0 };
- Sel_Manager_Dropable *dropable;
- Efl_Ui_Selection_Action act;
-
- sel_debug("In");
- /* Need to send a status back */
- /* FIXME: Should check I can drop here */
- /* FIXME: Should highlight widget */
- dropable = _x11_dropable_find(pd, xpos->win);
- if (dropable)
- {
- Evas_Coord ox = 0, oy = 0;
- Eina_Position2D pos;
-
- act = _x11_dnd_action_map(xpos->action);
- pos.x = xpos->position.x;
- pos.y = xpos->position.y;
- _dropable_coords_adjust(dropable, &pos);
- Evas *evas = _x11_evas_get_from_xwin(pd, xpos->win);
- Eina_List *dropable_list = evas ? _dropable_list_geom_find(pd, evas, pos.x, pos.y) : NULL;
- /* check if there is dropable (obj) can accept this drop */
- if (dropable_list)
- {
- Efl_Ui_Selection_Format saved_format = _dnd_types_to_format(pd, seat_sel->saved_types->types, seat_sel->saved_types->ntypes);
- Eina_List *l;
- Eina_Bool found = EINA_FALSE;
-
- EINA_LIST_FOREACH(dropable_list, l, dropable)
- {
- Drop_Format *df;
- Eina_Inlist *itr;
- EINA_INLIST_FOREACH_SAFE(dropable->format_list, itr, df)
- {
- Efl_Ui_Selection_Format common_fmt = saved_format & df->format;
- if (common_fmt)
- {
- //We found a target that can accept this type of data
- int i, min_index = SELECTION_N_ATOMS;
- //We have to find the first atom that corresponds to one
- //of the supported data types.
- for (i = 0; i < seat_sel->saved_types->ntypes; i++)
- {
- Sel_Manager_Atom *atom = eina_hash_find(pd->type_hash, seat_sel->saved_types->types[i]);
- if (atom && (atom->format & common_fmt))
- {
- int atom_idx = (atom - pd->atom_list);
- if (min_index > atom_idx) min_index = atom_idx;
- }
- }
- if (min_index != SELECTION_N_ATOMS)
- {
- sel_debug("Found atom %s\n", pd->atom_list[min_index].name);
- found = EINA_TRUE;
- dropable->last.type = pd->atom_list[min_index].name;
- dropable->last.format = common_fmt;
- break;
- }
- }
- }
- if (found) break;
- }
- if (found)
- {
- Sel_Manager_Dropable *d = NULL;
- Eina_Rectangle inter_rect = {0, 0, 0, 0};
- int idx = 0;
- EINA_LIST_FOREACH(dropable_list, l, d)
- {
- if (idx == 0)
- {
- evas_object_geometry_get(d->obj, &inter_rect.x, &inter_rect.y,
- &inter_rect.w, &inter_rect.h);
- }
- else
- {
- Eina_Rectangle cur_rect;
- evas_object_geometry_get(d->obj, &cur_rect.x, &cur_rect.y,
- &cur_rect.w, &cur_rect.h);
- if (!eina_rectangle_intersection(&inter_rect, &cur_rect)) continue;
- }
- idx++;
- }
- rect.x = inter_rect.x;
- rect.y = inter_rect.y;
- rect.width = inter_rect.w;
- rect.height = inter_rect.h;
- ecore_x_dnd_send_status(EINA_TRUE, EINA_FALSE, rect, xpos->action);
- sel_debug("dnd position %i %i %p\n", pos.x - ox, pos.y - oy, dropable);
- pos.x = pos.x - ox;
- pos.y = pos.y - oy;
- _x11_dnd_dropable_handle(pd, dropable, pos, act);
- // CCCCCCC: call dnd exit on last obj if obj != last
- // CCCCCCC: call drop position on obj
- }
- else
- {
- //if not: send false status
- ecore_x_dnd_send_status(EINA_FALSE, EINA_FALSE, rect, xpos->action);
- sel_debug("dnd position (%d, %d) not in obj\n", pos.x, pos.y);
- _x11_dnd_dropable_handle(pd, NULL, EINA_POSITION2D(0, 0), act);
- // CCCCCCC: call dnd exit on last obj
- }
- eina_list_free(dropable_list);
- }
- else
- {
- ecore_x_dnd_send_status(EINA_FALSE, EINA_FALSE, rect, xpos->action);
- sel_debug("dnd position (%d, %d) has no drop\n", pos.x, pos.y);
- _x11_dnd_dropable_handle(pd, NULL, EINA_POSITION2D(0, 0), act);
- }
- }
- else
- {
- ecore_x_dnd_send_status(EINA_FALSE, EINA_FALSE, rect, xpos->action);
- }
- return EINA_TRUE;
-}
-
-static Eina_Bool
-_x11_dnd_leave(void *data, int etype EINA_UNUSED, void *ev)
-{
- Sel_Manager_Seat_Selection *seat_sel = data;
- Eina_Position2D pos = {0, 0};
-#ifdef DEBUGON
- sel_debug("Leave %x\n", ((Ecore_X_Event_Xdnd_Leave *)ev)->win);
-#else
- (void)ev;
-#endif
- _x11_dnd_dropable_handle(seat_sel->pd, NULL, pos, EFL_UI_SELECTION_ACTION_UNKNOWN);
- // CCCCCCC: call dnd exit on last obj if there was one
- // leave->win leave->source
- return EINA_TRUE;
-}
-
-static Eina_Bool
-_x11_dnd_drop(void *data, int etype EINA_UNUSED, void *ev)
-{
- sel_debug("In");
- Sel_Manager_Seat_Selection *seat_sel = data;
- Efl_Ui_Selection_Manager_Data *pd = seat_sel->pd;
- Ecore_X_Event_Xdnd_Drop *drop;
- Sel_Manager_Dropable *dropable = NULL;
- Evas_Coord x = 0, y = 0;
- Efl_Ui_Selection_Action act = EFL_UI_SELECTION_ACTION_UNKNOWN;
- Eina_List *l;
- Sel_Manager_Selection *sel;
-
- drop = ev;
- sel_debug("drop_list %p (%d)\n", pd->drop_list, eina_list_count(pd->drop_list));
- if (!(dropable = _x11_dropable_find(pd, drop->win))) return EINA_TRUE;
-
- /* Calculate real (widget relative) position */
- // - window position
- // - widget position
- seat_sel->saved_types->pos = EINA_POSITION2D(drop->position.x, drop->position.y);
- _dropable_coords_adjust(dropable, &seat_sel->saved_types->pos);
-
- sel_debug("Drop position is %d,%d\n", seat_sel->saved_types->pos.x, seat_sel->saved_types->pos.y);
-
- EINA_LIST_FOREACH(pd->drop_list, l, dropable)
- {
- if (dropable->last.in)
- {
- evas_object_geometry_get(dropable->obj, &x, &y, NULL, NULL);
- seat_sel->saved_types->pos.x -= x;
- seat_sel->saved_types->pos.y -= y;
- goto found;
- }
- }
-
- sel_debug("Didn't find a target\n");
- return EINA_TRUE;
-
-found:
- sel_debug("0x%x\n", drop->win);
-
- act = _x11_dnd_action_map(drop->action);
-
- dropable->last.in = EINA_FALSE;
- sel_debug("Last type: %s - Last format: %X\n", dropable->last.type, dropable->last.format);
-#if 0 // this seems to be broken and causes dnd to stop working e.g. to/from
- // rage even though iut used to work fine.
- Efl_Ui_Selection_Data ddata;
- Eina_Inlist *itr;
- if ((!strcmp(dropable->last.type, pd->text_uri)))
- {
- sel_debug("We found a URI... (%scached) %s\n",
- seat_sel->saved_types->imgfile ? "" : "not ",
- seat_sel->saved_types->imgfile);
- if (seat_sel->saved_types->imgfile)
- {
- Drop_Format *df;
-
- if (!dropable->is_container)
- {
- ddata.pos = seat_sel->saved_types->pos;
- ddata.item = NULL;
- }
- else
- {
- //for container
- Efl_Object *it = NULL;
- Evas_Coord x0 = 0, y0 = 0;
- Eina_Position2D pos, posret = {0, 0};
-
- evas_object_geometry_get(dropable->obj, &x0, &y0, NULL, NULL);
- pos = EINA_POSITION2D(seat_sel->saved_types->pos.x + x0,
- seat_sel->saved_types->pos.y + y0);
- if (dropable->item_func)
- it = dropable->item_func(dropable->item_func_data, dropable->obj,
- pos, &posret);
- ddata.pos = posret;
- ddata.item = it;
- }
- ddata.action = act;
-
- EINA_INLIST_FOREACH_SAFE(dropable->format_list, itr, df)
- {
- if (df->format & EFL_UI_SELECTION_FORMAT_IMAGE)
- {
- sel_debug("Doing image insert (%s)\n", seat_sel->saved_types->imgfile);
- ddata.format = EFL_UI_SELECTION_FORMAT_IMAGE;
- ddata.content.mem = (char *)seat_sel->saved_types->imgfile;
- ddata.content.len = strlen(ddata.content.mem);
- if (df->format & dropable->last.format)
- efl_event_callback_call(dropable->obj, EFL_UI_DND_EVENT_DRAG_DROP, &ddata);
- }
- else
- {
- sel_debug("Item doesn't support images... passing\n");
- }
- }
- ecore_x_dnd_send_finished();
- ELM_SAFE_FREE(seat_sel->saved_types->imgfile, free);
- return EINA_TRUE;
- }
- else if (seat_sel->saved_types->textreq)
- {
- /* Already asked: Pretend we asked now, and paste immediately when
- * it comes in */
- seat_sel->saved_types->textreq = 0;
- ecore_x_dnd_send_finished();
- return EINA_TRUE;
- }
- }
-#endif
- sel = seat_sel->sel_list + EFL_UI_SELECTION_TYPE_DND;
- sel_debug("doing a request then: %s\n", dropable->last.type);
- sel->xwin = drop->win;
- sel->request_obj = dropable->obj;
- sel->request_format = dropable->last.format;
- sel->active = EINA_TRUE;
- sel->action = act;
- sel->asked++;
- ecore_x_selection_xdnd_request(drop->win, dropable->last.type);
-
- return EINA_TRUE;
-}
-
-static Eina_Bool
-_x11_sel_manager_drop_target_add(Efl_Ui_Selection_Manager_Data *pd, Efl_Object *target_obj,
- Efl_Ui_Selection_Format format, Ecore_X_Window xwin,
- unsigned int seat)
-{
- Sel_Manager_Dropable *dropable = NULL;
- Eina_List *l;
- Eina_Bool have_drop_list = EINA_FALSE;
- Sel_Manager_Seat_Selection *seat_sel = NULL;
-
- /* Is this the first? */
- EINA_LIST_FOREACH(pd->drop_list, l, dropable)
- {
- if (xwin == _x11_xwin_get(dropable->obj))
- {
- have_drop_list = EINA_TRUE;
- break;
- }
- }
- dropable = NULL; // In case of error, we don't want to free it
-
-
- Drop_Format *df = calloc(1, sizeof(Drop_Format));
- if (!df) return EINA_FALSE;
- df->format = format;
-
- dropable = efl_key_data_get(target_obj, "__elm_dropable");
- if (!dropable)
- {
- /* Create new drop */
- dropable = calloc(1, sizeof(Sel_Manager_Dropable));
- if (!dropable) goto error;
- dropable->last.in = EINA_FALSE;
- pd->drop_list = eina_list_append(pd->drop_list, dropable);
- if (!pd->drop_list) goto error;
- dropable->obj = target_obj;
- efl_key_data_set(target_obj, "__elm_dropable", dropable);
- }
- dropable->format_list = eina_inlist_append(dropable->format_list, EINA_INLIST_GET(df));
- dropable->seat = seat;
-
- evas_object_event_callback_add(target_obj, EVAS_CALLBACK_DEL,
- _all_drop_targets_cbs_del, pd);
- if (!have_drop_list) ecore_x_dnd_aware_set(xwin, EINA_TRUE);
-
- seat_sel = _x11_sel_manager_seat_selection_init(pd, seat);
-
- if (seat_sel->enter_handler) return EINA_TRUE;
- sel_debug("Adding drop target calls xwin=%#llx", (unsigned long long)xwin);
- seat_sel->enter_handler = ecore_event_handler_add(ECORE_X_EVENT_XDND_ENTER,
- _x11_dnd_enter, seat_sel);
- seat_sel->leave_handler = ecore_event_handler_add(ECORE_X_EVENT_XDND_LEAVE,
- _x11_dnd_leave, seat_sel);
- seat_sel->pos_handler = ecore_event_handler_add(ECORE_X_EVENT_XDND_POSITION,
- _x11_dnd_position, seat_sel);
- seat_sel->drop_handler = ecore_event_handler_add(ECORE_X_EVENT_XDND_DROP,
- _x11_dnd_drop, seat_sel);
- return EINA_TRUE;
-error:
- free(df);
- free(dropable);
- return EINA_FALSE;
-}
-
-#endif
-
-//Wayland
-#ifdef HAVE_ELEMENTARY_WL2
-static Sel_Manager_Seat_Selection *
-_wl_sel_manager_seat_selection_init(Efl_Ui_Selection_Manager_Data *pd, unsigned int seat)
-{
- Sel_Manager_Seat_Selection *seat_sel = NULL;
- Eina_List *l = NULL;
-
- EINA_LIST_FOREACH(pd->seat_list, l, seat_sel)
- {
- if(seat_sel->seat == seat)
- break;
- }
- if (!seat_sel)
- {
- seat_sel = calloc(1, sizeof(Sel_Manager_Seat_Selection));
- if (!seat_sel)
- {
- ERR("Failed to allocate seat");
- return NULL;
- }
- seat_sel->saved_types = calloc(1, sizeof(Saved_Type));
- seat_sel->seat = seat;
- seat_sel->pd = pd;
- pd->seat_list = eina_list_append(pd->seat_list, seat_sel);
- }
- if (!seat_sel->sel)
- {
- Sel_Manager_Selection *sel = calloc(1, sizeof(Sel_Manager_Selection));
- if (!sel)
- {
- ERR("failed to allocate selection");
- return NULL;
- }
- sel->seat_sel = seat_sel;
- seat_sel->sel = sel;
- }
-
- return seat_sel;
-}
-
-static void
-_wl_drag_source_del(void *data, Evas *evas EINA_UNUSED, Evas_Object *obj, void *event EINA_UNUSED)
-{
- Sel_Manager_Seat_Selection *seat_sel = data;
- if (seat_sel->drag_obj == obj)
- seat_sel->drag_obj = NULL;
-}
-
-static void
-_wl_efl_sel_manager_drag_start(Eo *obj EINA_UNUSED, Efl_Ui_Selection_Manager_Data *pd, Efl_Object *drag_obj,
- 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 EINA_UNUSED,
- Ecore_Wl2_Window *win, unsigned int seat)
-{
- Ecore_Evas *ee;
- Evas_Object *icon = NULL;
- int x, y, x2 = 0, y2 = 0, x3, y3, w = 0, h = 0;
- const char *types[SELECTION_N_ATOMS + 1];
- int i, nb_types = 0;
- Ecore_Wl2_Window *parent = NULL;
- Sel_Manager_Seat_Selection *seat_sel;
- Sel_Manager_Selection *sel;
-
- sel_debug("In");
- seat_sel = _wl_sel_manager_seat_selection_init(pd, seat);
- if (!seat_sel) return;
- seat_sel->active_type = EFL_UI_SELECTION_TYPE_DND;
- sel = seat_sel->sel;
-
- sel_debug("checking drag_win: %p", seat_sel->drag_win);
- /* if we already have a drag, get out */
- if (seat_sel->drag_win) return;
-
- for (i = SELECTION_ATOM_LISTING_ATOMS + 1; i < SELECTION_N_ATOMS; i++)
- {
- if (format == EFL_UI_SELECTION_FORMAT_TARGETS || (pd->atom_list[i].format & format))
- {
- types[nb_types++] = pd->atom_list[i].name;
- sel_debug("set dnd type: %s\n", pd->atom_list[i].name);
- }
- }
- types[nb_types] = NULL;
-
- ecore_wl2_dnd_drag_types_set(_wl_seat_get(win, drag_obj, seat), types);
-
- /* set the drag data used when a drop occurs */
- free(sel->data.mem);
- sel->data.len = 0;
- sel->data = eina_slice_dup(data);
-
- /* setup callback to notify if this object gets deleted */
- evas_object_event_callback_add(drag_obj, EVAS_CALLBACK_DEL,
- _wl_drag_source_del, sel);
-
- seat_sel->drag_obj = drag_obj;
- seat_sel->drag_action = action;
-
- seat_sel->drag_win = elm_win_add(NULL, "Elm-Drag", ELM_WIN_DND);
- elm_win_alpha_set(seat_sel->drag_win, EINA_TRUE);
- elm_win_borderless_set(seat_sel->drag_win, EINA_TRUE);
- elm_win_override_set(seat_sel->drag_win, EINA_TRUE);
-
- win = elm_win_wl_window_get(seat_sel->drag_win);
-
- if (icon_func)
- {
- Eina_Position2D off;
-
- icon = icon_func(icon_func_data, seat_sel->drag_win, drag_obj, &off);
- if (icon)
- {
- x2 = off.x;
- y2 = off.y;
- evas_object_geometry_get(icon, NULL, NULL, &w, &h);
- }
- }
- else
- {
- icon = elm_icon_add(seat_sel->drag_win);
- evas_object_size_hint_weight_set(icon, EVAS_HINT_EXPAND,
- EVAS_HINT_EXPAND);
- }
-
- elm_win_resize_object_add(seat_sel->drag_win, icon);
- evas_object_show(icon);
-
- /* Position subwindow appropriately */
- ee = ecore_evas_ecore_evas_get(evas_object_evas_get(drag_obj));
- ecore_evas_geometry_get(ee, &x, &y, NULL, NULL);
- x += x2;
- y += y2;
- seat_sel->drag_win_start.x = seat_sel->drag_win_end.x = x;
- seat_sel->drag_win_start.y = seat_sel->drag_win_end.y = y;
-
- evas_object_geometry_set(seat_sel->drag_win, x, y, w, h);
- evas_object_show(seat_sel->drag_win);
-
- evas_pointer_canvas_xy_get(evas_object_evas_get(drag_obj), &x3, &y3);
- seat_sel->drag_pos.x = x3 - x2;
- seat_sel->drag_pos.y = y3 - y2;
-
- if (elm_widget_is(drag_obj))
- {
- Evas_Object *top;
-
- top = elm_widget_top_get(drag_obj);
- if (!top) top = elm_widget_top_get(elm_widget_parent_widget_get(drag_obj));
- if (top && (efl_isa(top, EFL_UI_WIN_CLASS)))
- parent = elm_win_wl_window_get(top);
- }
- if (!parent)
- {
- Evas *evas;
-
- if (!(evas = evas_object_evas_get(drag_obj)))
- return;
- if (!(ee = ecore_evas_ecore_evas_get(evas)))
- return;
-
- parent = ecore_evas_wayland2_window_get(ee);
- }
-
- sel->drag_serial = ecore_wl2_dnd_drag_start(_wl_seat_get(win, drag_obj, seat), parent, win);
-}
-
-static Eina_Bool
-_wl_is_uri_type_data(const char *data, int len)
-{
- char *p;
- if (len < 6) return EINA_FALSE;
-
- p = (char *)data;
- if (!p) return EINA_FALSE;
- if (strncmp(p, "file:/", 6))
- {
- if (*p != '/') return EINA_FALSE;
- }
- return EINA_TRUE;
-}
-
-static Efl_Ui_Selection_Action
-_wl_to_elm(Ecore_Wl2_Drag_Action action)
-{
- #define CONV(wl, elm) if (action == wl) return elm;
- CONV(ECORE_WL2_DRAG_ACTION_COPY, EFL_UI_SELECTION_ACTION_COPY);
- CONV(ECORE_WL2_DRAG_ACTION_MOVE, EFL_UI_SELECTION_ACTION_MOVE);
- CONV(ECORE_WL2_DRAG_ACTION_ASK, EFL_UI_SELECTION_ACTION_ASK);
- #undef CONV
- return EFL_UI_SELECTION_ACTION_UNKNOWN;
-}
-
-static Eina_Bool
-_wl_targets_converter(char *target, Sel_Manager_Selection *sel, void *data EINA_UNUSED, int size EINA_UNUSED, void **data_ret, int *size_ret)
-{
- sel_debug("in\n");
- if (!data_ret) return EINA_FALSE;
-
- const char *sep = "\n";
- char *aret;
- int len = 0;
- int i = 0;
- Sel_Manager_Seat_Selection *seat_sel = sel->seat_sel;
- Efl_Ui_Selection_Manager_Data *pd = seat_sel->pd;
- Efl_Ui_Selection_Format format = EFL_UI_SELECTION_FORMAT_NONE;
- Eina_Bool is_uri = EINA_FALSE;
-
- if (sel->format)
- {
- format = sel->format;
- is_uri = _wl_is_uri_type_data(sel->data.mem, sel->data.len);
- }
- else
- {
- Sel_Manager_Atom *atom = eina_hash_find(pd->type_hash, target);
- if (atom)
- format = atom->format;
- }
- for (i = 0; i < SELECTION_N_ATOMS; i++)
- {
- if (format & pd->atom_list[i].format)
- {
- if ((is_uri) ||
- ((!is_uri) && strcmp(pd->atom_list[i].name, "text/uri-list")))
- len += strlen(pd->atom_list[i].name) + strlen(sep);
- }
- }
- len++; //terminating null byte
- aret = calloc(1, len * sizeof(char));
- if (!aret) return EINA_FALSE;
- for (i = 0; i < SELECTION_N_ATOMS; i++)
- {
- if (format & pd->atom_list[i].format)
- {
- if ((is_uri) ||
- ((!is_uri) && strcmp(pd->atom_list[i].name, "text/uri-list")))
- {
- aret = strcat(aret, pd->atom_list[i].name);
- aret = strcat(aret, sep);
- }
- }
- }
- *data_ret = aret;
- if (size_ret) *size_ret = len;
-
- return EINA_TRUE;
-}
-
-static Eina_Bool
-_wl_general_converter(char *target, Sel_Manager_Selection *sel, void *data, int size, void **data_ret, int *size_ret)
-{
- Efl_Ui_Selection_Format format = EFL_UI_SELECTION_FORMAT_NONE;
- Sel_Manager_Atom *atom = NULL;
- Sel_Manager_Seat_Selection *seat_sel = sel->seat_sel;
- Efl_Ui_Selection_Manager_Data *pd = seat_sel->pd;
-
- sel_debug("in\n");
-
- atom = eina_hash_find(pd->type_hash, target);
- if (atom)
- format = atom->format;
- if (format == EFL_UI_SELECTION_FORMAT_NONE)
- {
- if (data_ret)
- {
- *data_ret = malloc(size * sizeof(char) + 1);
- if (!*data_ret) return EINA_FALSE;
- memcpy(*data_ret, data, size);
- ((char**)(data_ret))[0][size] = 0;
- }
- if (size_ret) *size_ret = size;
- }
- else
- {
- if ((data) && (size > 0))
- {
- char *tmp = malloc(size);
- if (tmp)
- {
- memcpy(tmp, data, size);
- if (data_ret) *data_ret = tmp;
- if (size_ret) *size_ret = size;
- if (!data_ret) free(tmp);
- }
- }
- else
- {
- if (data_ret) *data_ret = NULL;
- if (size_ret) *size_ret = 0;
- }
- }
-
- return EINA_TRUE;
-}
-
-static Eina_Bool
-_wl_text_converter(char *target, Sel_Manager_Selection *sel, void *data, int size, void **data_ret, int *size_ret)
-{
- Efl_Ui_Selection_Format format = EFL_UI_SELECTION_FORMAT_NONE;
- Sel_Manager_Atom *atom = NULL;
- Sel_Manager_Seat_Selection *seat_sel = sel->seat_sel;
- Efl_Ui_Selection_Manager_Data *pd = seat_sel->pd;
-
- sel_debug("in\n");
-
- atom = eina_hash_find(pd->type_hash, target);
- if (atom)
- format = atom->format;
- if (format == EFL_UI_SELECTION_FORMAT_NONE)
- {
- if (data_ret)
- {
- *data_ret = malloc(size * sizeof(char) + 1);
- if (!*data_ret) return EINA_FALSE;
- memcpy(*data_ret, data, size);
- ((char**)(data_ret))[0][size] = 0;
- if (size_ret) *size_ret = size;
- return EINA_TRUE;
- }
- }
- else if ((format & EFL_UI_SELECTION_FORMAT_MARKUP) ||
- (format & EFL_UI_SELECTION_FORMAT_HTML))
- {
- char *tmp = malloc(size + 1);
- if (tmp)
- {
- strncpy(tmp, data, size);
- tmp[size] = 0;
- *data_ret = _elm_util_mkup_to_text(tmp);
- if (size_ret && *data_ret) *size_ret = strlen(*data_ret);
- free(tmp);
- }
- else return EINA_FALSE;
- }
- else if (format & EFL_UI_SELECTION_FORMAT_TEXT)
- {
- char *tmp = malloc(size + 1);
- if (tmp)
- {
- strncpy(tmp, data, size);
- tmp[size] = 0;
- *data_ret = tmp;
- if (size_ret && *data_ret) *size_ret = strlen(*data_ret);
- }
- else return EINA_FALSE;
- }
- else if (format & EFL_UI_SELECTION_FORMAT_IMAGE)
- {
- sel_debug("Image %s\n", evas_object_type_get(sel->request_obj));
- efl_file_simple_get(sel->request_obj, (const char **)data_ret, NULL);
- if (!*data_ret) *data_ret = strdup("No file");
- else *data_ret = strdup(*data_ret);
-
- if (!*data_ret)
- {
- ERR("Failed to allocate memory!");
- *size_ret = 0;
- return EINA_FALSE;
- }
-
- if (size_ret) *size_ret = strlen(*data_ret);
- }
- return EINA_TRUE;
-}
-
-static void
-_wl_sel_obj_del(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
-{
- Sel_Manager_Selection *sel = data;
- if (sel->owner == obj)
- {
- sel->owner = NULL;
- }
- //if (dragwidget == obj) dragwidget = NULL;
-}
-
-static Eina_Future *
-_wl_efl_sel_manager_selection_set(Efl_Ui_Selection_Manager_Data *pd,
- Efl_Object *owner, Efl_Ui_Selection_Type type,
- Efl_Ui_Selection_Format format,
- Eina_Slice data,
- Ecore_Wl2_Window *win,
- unsigned int seat)
-{
- Sel_Manager_Seat_Selection *seat_sel;
- Sel_Manager_Selection *sel;
- int i = 0, count = 0;
- Eina_Bool is_uri = EINA_FALSE;
- const char **types;
-
- if ((!data.mem) && (format != EFL_UI_SELECTION_FORMAT_IMAGE))
- {
- efl_ui_selection_manager_selection_clear(pd->sel_man, owner, type, seat);
- return NULL;
- }
-
- if (data.len <= 0)
- return NULL;
-
- seat_sel = _wl_sel_manager_seat_selection_init(pd, seat);
- seat_sel->active_type = type;
- sel = seat_sel->sel;
-
- if (sel->owner != owner)
- {
- Eina_List *l, *l_next;
- Sel_Manager_Selection_Lost *sel_lost;
-
- EINA_LIST_FOREACH_SAFE(seat_sel->sel_lost_list, l, l_next, sel_lost)
- {
- if ((sel_lost->request == sel->owner) &&
- (sel_lost->type == type))
- {
- eina_promise_resolve(sel_lost->promise, eina_value_uint_init(sel_lost->type));
- }
- }
- }
-
- if (sel->owner)
- evas_object_event_callback_del_full(sel->owner, EVAS_CALLBACK_DEL,
- _wl_sel_obj_del, sel);
- sel->active = EINA_TRUE;
- sel->owner = owner;
- sel->win = win;
- /* sel->set(win, &selection, sizeof(Elm_Sel_Type)); */
- sel->format = format;
-
- evas_object_event_callback_add
- (sel->owner, EVAS_CALLBACK_DEL, _wl_sel_obj_del, &sel);
-
- sel->data = eina_slice_dup(data);
- if (!sel->data.mem)
- {
- efl_ui_selection_manager_selection_clear(pd->sel_man, owner, type, seat_sel->seat);
- return NULL;
- }
-
- is_uri = _wl_is_uri_type_data(sel->data.mem, sel->data.len);
- types = malloc(sizeof(char *));
- if (!types) return NULL;
- for (i = 0, count = 1; i < SELECTION_N_ATOMS; i++)
- {
- if (format & pd->atom_list[i].format)
- {
- if ((is_uri) ||
- ((!is_uri) && strcmp(pd->atom_list[i].name, "text/uri-list")))
- {
- const char **t = NULL;
-
- types[count - 1] = pd->atom_list[i].name;
- count++;
- t = realloc(types, sizeof(char *) * count);
- if (!t)
- {
- free(types);
- return NULL;
- }
- types = t;
- }
- }
- }
- types[count - 1] = 0;
-
- sel->selection_serial = ecore_wl2_dnd_selection_set(_wl_seat_get(win, owner, seat_sel->seat), types);
- DBG("serial: %d", sel->selection_serial);
-
- free(types);
- //return _local_elm_cnp_selection_set(obj, selection, format, buf, buflen);
-
- return _update_sel_lost_list(owner, type, seat_sel);
-}
-
-static void
-_wl_selection_changed_free(void *data, void *ev)
-{
- ecore_wl2_display_disconnect(data);
-
- free(ev);
-}
-
-static Eina_Bool
-_wl_selection_changed(void *data, int type EINA_UNUSED, void *event)
-{
- Efl_Ui_Selection_Manager_Data *pd = data;
- Elm_Cnp_Event_Selection_Changed *_e;
- Sel_Manager_Seat_Selection *seat_sel;
- Sel_Manager_Selection *sel;
- Efl_Ui_Selection_Changed e;
- Ecore_Wl2_Event_Seat_Selection *ev = event;
- Ecore_Wl2_Input *seat;
-
- seat_sel = _wl_sel_manager_seat_selection_init(pd, ev->seat);
- sel_debug("seat: %d", ev->seat);
- if (!seat_sel) return ECORE_CALLBACK_RENEW;
- sel = seat_sel->sel;
-
- seat = ecore_wl2_display_input_find(ev->display, ev->seat);
- EINA_SAFETY_ON_NULL_RETURN_VAL(seat, ECORE_CALLBACK_RENEW);
- e.type = EFL_UI_SELECTION_TYPE_CLIPBOARD;
- e.seat = ev->seat;
- /* connect again to add ref */
- e.display = ecore_wl2_display_connect(ecore_wl2_display_name_get(ev->display));
- e.exist = !!ecore_wl2_dnd_selection_get(seat);
-
- _e = calloc(1, sizeof(Elm_Cnp_Event_Selection_Changed));
- EINA_SAFETY_ON_NULL_RETURN_VAL(_e, ECORE_CALLBACK_RENEW);
- _e->type = e.type;
- _e->seat_id = e.seat;
- _e->display = e.display;
- _e->exists = e.exist;
-
- ecore_event_add(ELM_CNP_EVENT_SELECTION_CHANGED, _e, _wl_selection_changed_free, ev->display);
- efl_event_callback_call(sel->request_obj, EFL_UI_SELECTION_EVENT_WM_SELECTION_CHANGED, &e);
-
- return ECORE_CALLBACK_RENEW;
-}
-
-static Eina_Bool
-_wl_selection_send(void *data, int type EINA_UNUSED, void *event)
-{
- Efl_Ui_Selection_Manager_Data *pd = data;
- char *buf;
- int ret, len_remained;
- int len_written = 0;
- Ecore_Wl2_Event_Data_Source_Send *ev;
- int seat;
- Sel_Manager_Seat_Selection *seat_sel;
- Sel_Manager_Selection *sel;
- void *data_ret = NULL;
- int len_ret = 0;
- int i = 0;
-
- ev = event;
- seat = ev->seat;
- sel_debug("seat: %d, type: %d", seat, type);
- seat_sel = _wl_sel_manager_seat_selection_init(pd, seat);
- if (!seat_sel) return ECORE_CALLBACK_RENEW;
- sel = seat_sel->sel;
-
- if ((ev->serial != sel->selection_serial) &&
- (ev->serial != sel->drag_serial))
- return ECORE_CALLBACK_RENEW;
-
- for (i = 0; i < SELECTION_N_ATOMS; i++)
- {
- if (!strcmp(pd->atom_list[i].name, ev->type))
- {
- sel_debug("Found a type: %s\n", pd->atom_list[i].name);
- Sel_Manager_Dropable *drop;
- drop = efl_key_data_get(sel->request_obj, "__elm_dropable");
- if (drop)
- drop->last.type = pd->atom_list[i].name;
- if (pd->atom_list[i].wl_converter)
- {
- pd->atom_list[i].wl_converter(ev->type, sel, sel->data.mem,
- sel->data.len, &data_ret, &len_ret);
- }
- else
- {
- data_ret = eina_memdup(sel->data.mem, sel->data.len, 0);
- len_ret = sel->data.len;
- }
- break;
- }
- }
-
- len_remained = len_ret;
- buf = data_ret;
-
- while (len_written < len_ret)
- {
- ret = write(ev->fd, buf, len_remained);
- if (ret == -1) break;
- buf += ret;
- len_written += ret;
- len_remained -= ret;
- }
- free(data_ret);
-
- close(ev->fd);
- ecore_wl2_display_flush(ev->display);
- return ECORE_CALLBACK_PASS_ON;
-}
-
-static Eina_Bool
-_wl_dnd_end(void *data, int type EINA_UNUSED, void *event)
-{
- sel_debug("In");
- Efl_Ui_Selection_Manager_Data *pd = data;
- Ecore_Wl2_Event_Data_Source_End *ev;
- Sel_Manager_Seat_Selection *seat_sel;
- Sel_Manager_Selection *sel;
-
- ev = event;
- seat_sel = _wl_sel_manager_seat_selection_init(pd, ev->seat);
- sel = seat_sel->sel;
- if (ev->serial != sel->drag_serial)
- return ECORE_CALLBACK_RENEW;
-
- if (seat_sel->active_type != EFL_UI_SELECTION_TYPE_DND)
- return ECORE_CALLBACK_RENEW;
-
- efl_event_callback_call(seat_sel->drag_obj, EFL_UI_DND_EVENT_DRAG_DONE, NULL);
- if (seat_sel->drag_win)
- {
- if (!seat_sel->accept)
- {
- /* Commit animation when drag cancelled */
- /* Record final position of dragwin, then do animation */
- ecore_evas_animator_timeline_add(seat_sel->drag_win, 0.3, _drag_cancel_animate, seat_sel);
- }
- else
- {
- /* No animation drop was committed */
- evas_object_del(seat_sel->drag_win);
- seat_sel->drag_win = NULL;
- }
- }
-
- seat_sel->accept = EINA_FALSE;
-
- ecore_wl2_display_flush(ev->display);
- return ECORE_CALLBACK_PASS_ON;
-}
-
-static Ecore_Wl2_Input *
-_wl_seat_get(Ecore_Wl2_Window *win, Evas_Object *obj, unsigned int seat_id)
-{
- Eo *seat, *parent2, *ewin;
- Ecore_Wl2_Input *input = NULL;
-
- input = ecore_wl2_display_input_find(ecore_wl2_window_display_get(win), seat_id);
- if (input) return input;
-
- if (obj)
- {
- // FIXME (there might be a better solution):
- // In case of inwin, we want to use the main wl2 window for cnp, but obj
- // obj belongs to the buffer canvas, so the default seat for obj does not
- // match the window win.
- 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)
- {
- 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);
- return input;
- }
-
- seat = evas_default_device_get(evas_object_evas_get(obj), EFL_INPUT_DEVICE_TYPE_SEAT);
- EINA_SAFETY_ON_NULL_RETURN_VAL(seat, NULL);
- return ecore_wl2_display_input_find(ecore_wl2_window_display_get(win),
- evas_device_seat_id_get(seat));
-}
-
-Ecore_Wl2_Window *
-_wl_window_get(const Evas_Object *obj)
-{
- Evas_Object *top;
- Ecore_Wl2_Window *win = NULL;
-
- if (elm_widget_is(obj))
- {
- top = elm_widget_top_get(obj);
- if (!top) top = elm_widget_top_get(elm_widget_parent_widget_get(obj));
- if (top && (efl_isa(top, EFL_UI_WIN_CLASS)))
- win = elm_win_wl_window_get(top);
- }
- if (!win)
- {
- Ecore_Evas *ee;
- Evas *evas;
- const char *engine_name;
-
- if (!(evas = evas_object_evas_get(obj)))
- return NULL;
- if (!(ee = ecore_evas_ecore_evas_get(evas)))
- return NULL;
-
- 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))
- {
- /* In case the engine is not a buffer, we want to check once. */
- win = ecore_evas_wayland2_window_get(ee);
- if (!win) return NULL;
- }
- }
-
- return win;
-}
-
-static void
-_wl_selection_receive_timeout(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
-{
- Sel_Manager_Selection *sel = data;
-
- if (sel->request_obj != obj) return;
-
- ecore_event_handler_del(sel->offer_handler);
-}
-
-static Eina_Bool
-_wl_selection_receive(void *data, int type EINA_UNUSED, void *event)
-{
- Ecore_Wl2_Event_Offer_Data_Ready *ev = event;
- Sel_Manager_Selection *sel = data;
-
- if (sel->sel_offer != ev->offer) return ECORE_CALLBACK_PASS_ON;
-
- if (sel->data_func)
- {
- Efl_Ui_Selection_Data sel_data;
-
- sel_data.pos.x = sel_data.pos.y = 0;
- if (((sel->format & EFL_UI_SELECTION_FORMAT_MARKUP) ||
- (sel->format & EFL_UI_SELECTION_FORMAT_HTML)) &&
- (sel->want_format == EFL_UI_SELECTION_FORMAT_TEXT))
- {
- char *tmp = malloc(ev->len + 1);
- sel_data.format = sel->format;
- sel_data.content.mem = NULL;
- sel_data.content.len = 0;
- if (tmp)
- {
- sel_data.format = sel->want_format;
- strncpy(tmp, ev->data, ev->len);
- tmp[ev->len] = 0;
- sel_data.content.mem = _elm_util_mkup_to_text(tmp);
- if (sel_data.content.mem)
- sel_data.content.len = strlen(sel_data.content.mem);
- free(tmp);
- }
- }
- else
- {
- sel_data.format = sel->format;
- sel_data.content.mem = ev->data;
- sel_data.content.len = ev->len;
- }
- sel_data.action = _wl_to_elm(ecore_wl2_offer_action_get(sel->sel_offer));
- sel->data_func(sel->data_func_data,
- sel->request_obj,
- &sel_data);
- }
- else
- {
- char *stripstr, *mkupstr;
-
- stripstr = malloc(ev->len + 1);
- if (!stripstr) return ECORE_CALLBACK_CANCEL;
- strncpy(stripstr, (char *)ev->data, ev->len);
- stripstr[ev->len] = '\0';
- mkupstr = _elm_util_text_to_mkup((const char *)stripstr);
- /* TODO BUG: should never NEVER assume it's an elm_entry! */
- _elm_entry_entry_paste(sel->request_obj, mkupstr);
- free(stripstr);
- free(mkupstr);
- }
-
- evas_object_event_callback_del_full(sel->request_obj,
- EVAS_CALLBACK_DEL,
- _wl_selection_receive_timeout, sel);
-
- ecore_event_handler_del(sel->offer_handler);
- return ECORE_CALLBACK_CANCEL;
-}
-
-static Eina_Bool
-_wl_efl_sel_manager_selection_get(const Efl_Object *request, Efl_Ui_Selection_Manager_Data *pd,
- 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,
- Ecore_Wl2_Window *win, unsigned int seat)
-{
- sel_debug("In, format: %d", format);
- Sel_Manager_Seat_Selection *seat_sel;
- Sel_Manager_Selection *sel;
- Ecore_Wl2_Input *input;
- Ecore_Wl2_Offer *offer;
- int i = 0;
-
- if (type == EFL_UI_SELECTION_TYPE_DND) return EINA_FALSE;
-
- //if (sel->active)
- //return _local_elm_cnp_selection_get(obj, selection, format, datacb, udata);
- seat_sel = _sel_manager_seat_selection_init(pd, seat);
- sel = seat_sel->sel;
- sel->request_obj = (Efl_Object *)request;
- sel->data_func_data = data_func_data;
- sel->data_func = data_func;
- sel->data_func_free_cb = data_func_free_cb;
-
- input = _wl_seat_get(win, (Efl_Object *)request, seat_sel->seat);
- offer = ecore_wl2_dnd_selection_get(input);
-
- //there can be no selection available
- if (!offer) return EINA_FALSE;
-
- for (i = 0; sm_wl_convertion[i].translates; i++)
- {
- int j = 0;
-// if (!(format & sm_wl_convertion[i].format)) continue;
-
- for (j = 0; sm_wl_convertion[i].translates[j]; j++)
- {
- if (!ecore_wl2_offer_supports_mime(offer, sm_wl_convertion[i].translates[j])) continue;
-
- //we have found matching mimetypes
- sel->sel_offer = offer;
- sel->format = sm_wl_convertion[i].format;
- sel->want_format = format;
-
- sel_debug("request type: %s", (char *)sm_wl_convertion[i].translates[j]);
- evas_object_event_callback_add(sel->request_obj, EVAS_CALLBACK_DEL,
- _wl_selection_receive_timeout, sel);
- sel->offer_handler = ecore_event_handler_add(ECORE_WL2_EVENT_OFFER_DATA_READY,
- _wl_selection_receive, sel);
-
- ecore_wl2_offer_receive(offer, (char*)sm_wl_convertion[i].translates[j]);
- ecore_wl2_display_flush(ecore_wl2_input_display_get(input));
- return EINA_TRUE;
- }
- }
-
- sel_debug("no type match");
- return EINA_FALSE;
-}
-
-static void
-_wl_sel_obj_del2(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
-{
- Sel_Manager_Selection *sel = data;
- if (sel->request_obj == obj) sel->request_obj = NULL;
-}
-
-static Sel_Manager_Dropable *
-_wl_dropable_find(Efl_Ui_Selection_Manager_Data *pd, Ecore_Wl2_Window *win)
-{
- Eina_List *l;
- Sel_Manager_Dropable *dropable;
-
- if (!pd->drop_list) return NULL;
-
- if (!win) return NULL;
-
- EINA_LIST_FOREACH(pd->drop_list, l, dropable)
- if (_wl_window_get(dropable->obj) == win)
- return dropable;
-
- return NULL;
-}
-
-static Evas *
-_wl_evas_get_from_win(Efl_Ui_Selection_Manager_Data *pd, Ecore_Wl2_Window *win)
-{
- Sel_Manager_Dropable *dropable = _wl_dropable_find(pd, win);
- return dropable ? evas_object_evas_get(dropable->obj) : NULL;
-}
-
-static Eina_Bool
-_wl_drops_accept(Sel_Manager_Seat_Selection *seat_sel, const char *type)
-{
- Efl_Ui_Selection_Manager_Data *pd;
- Sel_Manager_Selection *sel;
- Eina_List *l;
- Sel_Manager_Dropable *drop;
- Eina_Bool will_accept = EINA_FALSE;
-
- if (!type) return EINA_FALSE;
-
- pd = seat_sel->pd;
- sel = seat_sel->sel;
- EINA_LIST_FOREACH(pd->drop_list, l, drop)
- {
- Drop_Format *df;
- EINA_INLIST_FOREACH(drop->format_list, df)
- {
- for (int i = 0; sm_wl_convertion[i].translates ; ++i)
- {
- if (!(sm_wl_convertion[i].format & df->format)) continue;
-
- for (int j = 0; sm_wl_convertion[i].translates[j]; ++j)
- {
- if (!strncmp(type, sm_wl_convertion[i].translates[j], strlen(sm_wl_convertion[i].translates[j])))
- {
- sel->request_obj = drop->obj;
- return EINA_TRUE;
- }
- }
- }
- }
- }
-
- return will_accept;
-}
-
-static void
-_wl_selection_parser(void *_data, int size, char ***ret_data, int *ret_count)
-{
- char **files = NULL;
- int num_files = 0;
- char *data = NULL;
-
- data = malloc(size);
- if (data && (size > 0))
- {
- int i, is;
- char *tmp;
- char **t2;
-
- memcpy(data, _data, size);
- if (data[size - 1])
- {
- char *t;
-
- /* Isn't nul terminated */
- size++;
- t = realloc(data, size);
- if (!t) goto done;
- data = t;
- data[size - 1] = 0;
- }
-
- tmp = malloc(size);
- if (!tmp) goto done;
- i = 0;
- is = 0;
- while ((is < size) && (data[is]))
- {
- if ((i == 0) && (data[is] == '#'))
- for (; ((data[is]) && (data[is] != '\n')); is++) ;
- else
- {
- if ((data[is] != '\r') && (data[is] != '\n'))
- tmp[i++] = data[is++];
- else
- {
- while ((data[is] == '\r') || (data[is] == '\n'))
- is++;
- tmp[i] = 0;
- num_files++;
- t2 = realloc(files, num_files * sizeof(char *));
- if (t2)
- {
- files = t2;
- files[num_files - 1] = strdup(tmp);
- }
- else
- {
- num_files--;
- goto freetmp;
- }
- tmp[0] = 0;
- i = 0;
- }
- }
- }
- if (i > 0)
- {
- tmp[i] = 0;
- num_files++;
- t2 = realloc(files, num_files * sizeof(char *));
- if (t2)
- {
- files = t2;
- files[num_files - 1] = strdup(tmp);
- }
- else
- {
- num_files--;
- goto freetmp;
- }
- }
-freetmp:
- free(tmp);
- }
-done:
- free(data);
- if (ret_data) *ret_data = files;
- else
- {
- int i;
-
- for (i = 0; i < num_files; i++) free(files[i]);
- free(files);
- }
- if (ret_count) *ret_count = num_files;
-}
-
-static Eina_Bool
-_wl_data_preparer_markup(Sel_Manager_Selection *sel, Efl_Ui_Selection_Data *ddata, Ecore_Wl2_Event_Offer_Data_Ready *ev, Tmp_Info **tmp_info EINA_UNUSED)
-{
- sel_debug("In\n");
-
- ddata->format = EFL_UI_SELECTION_FORMAT_MARKUP;
- ddata->content.mem = eina_memdup((unsigned char *)ev->data, ev->len, EINA_TRUE);
- ddata->content.len = ev->len;
- ddata->action = sel->action;
-
- return EINA_TRUE;
-}
-
-static Eina_Bool
-_wl_data_preparer_uri(Sel_Manager_Selection *sel, Efl_Ui_Selection_Data *ddata, Ecore_Wl2_Event_Offer_Data_Ready *ev, Tmp_Info **tmp_info EINA_UNUSED)
-{
- Sel_Manager_Seat_Selection *seat_sel;
- char *p, *stripstr = NULL;
- char *data = ev->data;
- Sel_Manager_Dropable *drop;
- const char *type = NULL;
-
- sel_debug("In\n");
-
- seat_sel = sel->seat_sel;
- drop = efl_key_data_get(sel->request_obj, "__elm_dropable");
- if (drop) type = drop->last.type;
-
- if ((type) && (!strcmp(type, "text/uri-list")))
- {
- int num_files = 0;
- char **files = NULL;
- Efreet_Uri *uri;
- Eina_Strbuf *strbuf;
- int i;
-
- strbuf = eina_strbuf_new();
- if (!strbuf) return EINA_FALSE;
-
- _wl_selection_parser(ev->data, ev->len, &files, &num_files);
- sel_debug("got a files list\n");
-
- for (i = 0; i < num_files; i++)
- {
- uri = efreet_uri_decode(files[i]);
- if (uri)
- {
- eina_strbuf_append(strbuf, uri->path);
- efreet_uri_free(uri);
- }
- else
- {
- eina_strbuf_append(strbuf, files[i]);
- }
- if (i < (num_files - 1))
- eina_strbuf_append(strbuf, "\n");
- free(files[i]);
- }
- free(files);
- stripstr = eina_strbuf_string_steal(strbuf);
- eina_strbuf_free(strbuf);
- }
- else
- {
- Efreet_Uri *uri;
-
- p = (char *)eina_memdup((unsigned char *)data, ev->len, EINA_TRUE);
- if (!p) return EINA_FALSE;
- uri = efreet_uri_decode(p);
- if (!uri)
- {
- /* Is there any reason why we care of URI without scheme? */
- if (p[0] == '/') stripstr = p;
- else free(p);
- }
- else
- {
- free(p);
- stripstr = strdup(uri->path);
- efreet_uri_free(uri);
- }
- }
-
- if (!stripstr)
- {
- sel_debug("Couldn't find a file\n");
- return EINA_FALSE;
- }
- free(seat_sel->saved_types->imgfile);
-
- ddata->content.mem = stripstr;
- ddata->content.len = strlen(stripstr);
- ddata->action = sel->action;
- ddata->format = sel->request_format;
-
- return EINA_TRUE;
-}
-
-static Eina_Bool
-_wl_data_preparer_vcard(Sel_Manager_Selection *sel, Efl_Ui_Selection_Data *ddata, Ecore_Wl2_Event_Offer_Data_Ready *ev, Tmp_Info **tmp_info EINA_UNUSED)
-{
- sel_debug("In\n");
-
- ddata->format = EFL_UI_SELECTION_FORMAT_VCARD;
- ddata->content.mem = eina_memdup((unsigned char *)ev->data, ev->len, EINA_TRUE);
- ddata->content.len = ev->len;
- ddata->action = sel->action;
-
- return EINA_TRUE;
-}
-
-static Eina_Bool
-_wl_data_preparer_image(Sel_Manager_Selection *sel, Efl_Ui_Selection_Data *ddata, Ecore_Wl2_Event_Offer_Data_Ready *ev, Tmp_Info **tmp_info)
-{
- sel_debug("In\n");
- Tmp_Info *tmp;
- int len = 0;
-
- tmp = _tempfile_new(ev->len);
- if (!tmp)
- return EINA_FALSE;
- memcpy(tmp->map, ev->data, ev->len);
- munmap(tmp->map, ev->len);
-
- len = strlen(tmp->filename);
- ddata->format = EFL_UI_SELECTION_FORMAT_IMAGE;
- ddata->content.mem = eina_memdup((unsigned char*)tmp->filename, len, EINA_TRUE);
- ddata->content.len = len;
- ddata->action = sel->action;
- *tmp_info = tmp;
-
- return EINA_TRUE;
-}
-
-static Eina_Bool
-_wl_data_preparer_text(Sel_Manager_Selection *sel, Efl_Ui_Selection_Data *ddata, Ecore_Wl2_Event_Offer_Data_Ready *ev, Tmp_Info **tmp_info EINA_UNUSED)
-{
- sel_debug("In\n");
-
- ddata->format = EFL_UI_SELECTION_FORMAT_TEXT;
- ddata->content.mem = eina_memdup((unsigned char *)ev->data, ev->len, EINA_TRUE);
- ddata->content.len = ev->len;
- ddata->action = sel->action;
-
- return EINA_TRUE;
-}
-
-
-static void
-_wl_dropable_handle(Sel_Manager_Seat_Selection *seat_sel, Sel_Manager_Dropable *dropable, Evas_Coord x, Evas_Coord y)
-{
- Sel_Manager_Dropable *d, *last_dropable = NULL;
- Efl_Ui_Selection_Manager_Data *pd = seat_sel->pd;
- Sel_Manager_Selection *sel;
- Eina_Inlist *itr;
- Eina_List *l;
- Eina_Position2D pos;
-
- EINA_LIST_FOREACH(pd->drop_list, l, d)
- {
- if (d->last.in)
- {
- last_dropable = d;
- break;
- }
- }
-
- sel = seat_sel->sel;
- pos = EINA_POSITION2D(x, y);
- /* If we are on the same object, just update the position */
- if ((dropable) && (last_dropable == dropable))
- {
- Evas_Coord ox, oy;
- Efl_Dnd_Drag_Pos pos_data;
- Drop_Format *df;
-
- evas_object_geometry_get(dropable->obj, &ox, &oy, NULL, NULL);
- if (!dropable->is_container)
- {
- pos_data.pos = EINA_POSITION2D(x - ox, y - oy);
- pos_data.item = NULL;
- }
- else
- {
- Efl_Object *it = NULL;
-
- if (dropable->item_func)
- it = dropable->item_func(dropable->item_func_data, dropable->obj,
- pos, &pos_data.pos);
- pos_data.item = it;
- }
- pos_data.format = dropable->last.format;
- pos_data.action = sel->action;
- EINA_INLIST_FOREACH_SAFE(dropable->format_list, itr, df)
- {
- if (df->format & dropable->last.format)
- efl_event_callback_call(dropable->obj, EFL_UI_DND_EVENT_DRAG_POS, &pos_data);
- }
-
- return;
- }
- /* We leave the last dropable */
- if (last_dropable)
- {
- Drop_Format *df;
- sel_debug("leave %p\n", last_dropable->obj);
- last_dropable->last.in = EINA_FALSE;
-
- EINA_INLIST_FOREACH_SAFE(last_dropable->format_list, itr, df)
- {
- if (df->format & last_dropable->last.format)
- efl_event_callback_call(last_dropable->obj, EFL_UI_DND_EVENT_DRAG_LEAVE, NULL);
- }
- }
- /* We enter the new dropable */
- if (dropable)
- {
- sel_debug("enter %p\n", dropable->obj);
- Evas_Coord ox, oy;
- Efl_Dnd_Drag_Pos pos_data;
- Drop_Format *df;
-
- dropable->last.in = EINA_TRUE;
- evas_object_geometry_get(dropable->obj, &ox, &oy, NULL, NULL);
- if (!dropable->is_container)
- {
- pos_data.pos = EINA_POSITION2D(x - ox, y - oy);
- pos_data.item = NULL;
- }
- else
- {
- Efl_Object *it = NULL;
-
- if (dropable->item_func)
- it = dropable->item_func(dropable->item_func_data, dropable->obj,
- pos, &pos_data.pos);
- pos_data.item = it;
- }
- pos_data.format = dropable->last.format;
- pos_data.action = sel->action;
-
- EINA_INLIST_FOREACH_SAFE(dropable->format_list, itr, df)
- {
- if (df->format & dropable->last.format)
- {
- efl_event_callback_call(dropable->obj, EFL_UI_DND_EVENT_DRAG_ENTER, NULL);
- efl_event_callback_call(dropable->obj, EFL_UI_DND_EVENT_DRAG_POS, &pos_data);
- }
- }
- }
-}
-
-static void
-_wl_dropable_all_clean(Sel_Manager_Seat_Selection *seat_sel, Ecore_Wl2_Window *win)
-{
- Eina_List *l;
- Sel_Manager_Dropable *dropable;
-
- if (!win) return;
-
- EINA_LIST_FOREACH(seat_sel->pd->drop_list, l, dropable)
- {
- if (_wl_window_get(dropable->obj) == win)
- {
- dropable->last.pos.x = 0;
- dropable->last.pos.y = 0;
- dropable->last.in = EINA_FALSE;
- }
- }
-}
-
-static void
-_wl_dropable_data_handle(Sel_Manager_Selection *sel, Ecore_Wl2_Event_Offer_Data_Ready *ev)
-{
- Sel_Manager_Seat_Selection *seat_sel;
- Efl_Ui_Selection_Manager_Data *pd;
- Sel_Manager_Dropable *drop;
- Ecore_Wl2_Window *win;
-
- sel_debug("In\n");
- seat_sel = sel->seat_sel;
- pd = seat_sel->pd;
- drop = efl_key_data_get(sel->request_obj, "__elm_dropable");
- if (drop)
- {
- Sel_Manager_Atom *atom = NULL;
-
- atom = eina_hash_find(pd->type_hash, drop->last.type);
- if (atom && atom->wl_data_preparer)
- {
- Efl_Ui_Selection_Data ddata;
- Tmp_Info *tmp_info = NULL;
- Eina_Bool success;
-
- sel_debug("Call notify for: %s\n", atom->name);
- success = atom->wl_data_preparer(sel, &ddata, ev, &tmp_info);
- if (success)
- {
- Sel_Manager_Dropable *dropable;
- Eina_List *l;
-
- EINA_LIST_FOREACH(pd->drop_list, l, dropable)
- {
- if (dropable->obj == sel->request_obj) break;
- dropable = NULL;
- }
- if (dropable)
- {
- Drop_Format *df;
- Eina_Inlist *itr;
-
- if (!dropable->is_container)
- {
- ddata.pos.x = seat_sel->saved_types->pos.x;
- ddata.pos.y = seat_sel->saved_types->pos.y;
- }
- else
- {
- //for container
- Efl_Object *it = NULL;
- Evas_Coord x0 = 0, y0 = 0;
- Eina_Position2D pos, posret = {};
-
- evas_object_geometry_get(dropable->obj, &x0, &y0, NULL, NULL);
- pos = EINA_POSITION2D(seat_sel->saved_types->pos.x + x0,
- seat_sel->saved_types->pos.y + y0);
- if (dropable->item_func)
- it = dropable->item_func(dropable->item_func_data, dropable->obj,
- pos, &posret);
- ddata.pos = posret;
- ddata.item = it;
- }
- ddata.action = seat_sel->drag_action;
-
- EINA_INLIST_FOREACH_SAFE(dropable->format_list, itr, df)
- {
- if (df->format & dropable->last.format)
- efl_event_callback_call(dropable->obj, EFL_UI_DND_EVENT_DRAG_DROP, &ddata);
- }
- }
- }
- win = _wl_window_get(sel->request_obj);
- ecore_wl2_dnd_drag_end(_wl_seat_get(win, NULL, seat_sel->seat));
- if (tmp_info) _tmpinfo_free(tmp_info);
- return;
- }
- }
-
- win = _wl_window_get(sel->request_obj);
- ecore_wl2_dnd_drag_end(_wl_seat_get(win, NULL, seat_sel->seat));
- seat_sel->saved_types->textreq = 0;
-}
-
-static Eina_Bool
-_wl_dnd_enter(void *data, int type EINA_UNUSED, void *event)
-{
- Ecore_Wl2_Event_Dnd_Enter *ev;
- Eina_Array *known, *available;
- Sel_Manager_Seat_Selection *seat_sel = data;
- unsigned int i = 0;
-
- ev = event;
-
- available = ecore_wl2_offer_mimes_get(ev->offer);
-
- free(seat_sel->saved_types->types);
-
- seat_sel->saved_types->ntypes = eina_array_count(available);
- seat_sel->saved_types->types = malloc(sizeof(char *) * seat_sel->saved_types->ntypes);
- if (!seat_sel->saved_types->types) return EINA_FALSE;
-
- known = eina_array_new(5);
-
- for (i = 0; i < eina_array_count(available); i++)
- {
- seat_sel->saved_types->types[i] =
- eina_stringshare_add(eina_array_data_get(available, i));
- if (seat_sel->saved_types->types[i] == seat_sel->pd->text_uri)
- {
- seat_sel->saved_types->textreq = 1;
- ELM_SAFE_FREE(seat_sel->saved_types->imgfile, free);
- }
- }
-
- seat_sel->accept = EINA_FALSE;
- for (i = 0; i < eina_array_count(available); i++)
- {
- if (_wl_drops_accept(seat_sel, eina_array_data_get(available, i)))
- {
- eina_array_push(known, strdup(eina_array_data_get(available, i)));
- }
- }
-
- ecore_wl2_offer_mimes_set(ev->offer, known);
-
- return ECORE_CALLBACK_PASS_ON;
-}
-
-static Eina_Bool
-_wl_dnd_leave(void *data, int type EINA_UNUSED, void *event)
-{
- Ecore_Wl2_Event_Dnd_Leave *ev;
- Sel_Manager_Seat_Selection *seat_sel = data;
- Sel_Manager_Dropable *drop;
- sel_debug("In\n");
-
- ev = event;
- if ((drop = _wl_dropable_find(seat_sel->pd, ev->win)))
- {
- _wl_dropable_handle(seat_sel, NULL, 0, 0);
- _wl_dropable_all_clean(seat_sel, ev->win);
- }
-
- return ECORE_CALLBACK_PASS_ON;
-}
-
-static Eina_Bool
-_wl_dnd_position(void *data, int type EINA_UNUSED, void *event)
-{
- Ecore_Wl2_Event_Dnd_Motion *ev;
- Sel_Manager_Seat_Selection *seat_sel = data;
- Efl_Ui_Selection_Manager_Data *pd = seat_sel->pd;
- Sel_Manager_Dropable *drop;
- Eina_Bool will_accept = EINA_FALSE;
-
- ev = event;
-
- sel_debug("mouse pos %i %i\n", ev->x, ev->y);
- seat_sel->drag_win_end.x = ev->x - seat_sel->drag_pos.x;
- seat_sel->drag_win_end.y = ev->y - seat_sel->drag_pos.y;
-
- drop = _wl_dropable_find(pd, ev->win);
-
- if (drop)
- {
- Eina_Position2D pos = EINA_POSITION2D(ev->x, ev->y);
- Evas *evas = NULL;
- Eina_List *dropable_list = NULL;
-
- _dropable_coords_adjust(drop, &pos);
- evas = _wl_evas_get_from_win(pd, ev->win);
- if (evas)
- dropable_list = _dropable_list_geom_find(pd, evas, pos.x, pos.y);
-
- /* check if there is dropable (obj) can accept this drop */
- if (dropable_list)
- {
- Efl_Ui_Selection_Format saved_format;
- Eina_List *l;
- Eina_Bool found = EINA_FALSE;
- Sel_Manager_Dropable *dropable = NULL;
-
- saved_format =
- _dnd_types_to_format(pd, seat_sel->saved_types->types, seat_sel->saved_types->ntypes);
-
- EINA_LIST_FOREACH(dropable_list, l, dropable)
- {
- Drop_Format *df;
- Eina_Inlist *itr;
-
- EINA_INLIST_FOREACH_SAFE(dropable->format_list, itr, df)
- {
- Efl_Ui_Selection_Format common_fmt = saved_format & df->format;
-
- if (common_fmt)
- {
- /* We found a target that can accept this type of data */
- int i, min_index = SELECTION_N_ATOMS;
-
- /* We have to find the first atom that corresponds to one
- * of the supported data types. */
- for (i = 0; i < seat_sel->saved_types->ntypes; i++)
- {
- Sel_Manager_Atom *atom;
-
- atom = eina_hash_find(pd->type_hash,
- seat_sel->saved_types->types[i]);
-
- if (atom && (atom->format & common_fmt))
- {
- int atom_idx = (atom - pd->atom_list);
-
- if (min_index > atom_idx)
- min_index = atom_idx;
- }
- }
- if (min_index != SELECTION_N_ATOMS)
- {
- sel_debug("Found atom %s\n", pd->atom_list[min_index].name);
- found = EINA_TRUE;
- dropable->last.type = pd->atom_list[min_index].name;
- dropable->last.format = common_fmt;
- break;
- }
- }
- }
- if (found) break;
- }
- if (found)
- {
- Sel_Manager_Selection *sel = seat_sel->sel;
- Evas_Coord ox = 0, oy = 0;
-
- evas_object_geometry_get(dropable->obj, &ox, &oy, NULL, NULL);
-
- sel_debug("Candidate %p (%s)\n",
- dropable->obj, efl_class_name_get(efl_class_get(dropable->obj)));
- _wl_dropable_handle(seat_sel, dropable, pos.x - ox, pos.y - oy);
- sel->request_obj = dropable->obj;
- will_accept = EINA_TRUE;
- }
- else
- {
- //if not: send false status
- sel_debug("dnd position (%d, %d) not in obj\n", pos.x, pos.y);
- _wl_dropable_handle(seat_sel, NULL, 0, 0);
- // CCCCCCC: call dnd exit on last obj
- }
- eina_list_free(dropable_list);
- }
- }
-
- seat_sel->accept = will_accept;
- efl_event_callback_call(seat_sel->drag_obj, EFL_UI_DND_EVENT_DRAG_ACCEPT, &seat_sel->accept);
-
- return ECORE_CALLBACK_PASS_ON;
-}
-
-static Eina_Bool
-_wl_dnd_receive(void *data, int type EINA_UNUSED, void *event)
-{
- Ecore_Wl2_Event_Offer_Data_Ready *ev;
- Sel_Manager_Seat_Selection *seat_sel = data;
- Sel_Manager_Selection *sel;
- Ecore_Wl2_Offer *offer;
- sel_debug("In\n");
-
- ev = event;
- sel = seat_sel->sel;
- offer = sel->dnd_offer;
-
- if (offer != ev->offer) return ECORE_CALLBACK_PASS_ON;
-
- if (sel->request_obj)
- {
- Ecore_Wl2_Drag_Action action;
-
- action = ecore_wl2_offer_action_get(ev->offer);
- if (action == ECORE_WL2_DRAG_ACTION_ASK)
- ecore_wl2_offer_actions_set(ev->offer, ECORE_WL2_DRAG_ACTION_COPY, ECORE_WL2_DRAG_ACTION_COPY);
- action = ecore_wl2_offer_action_get(ev->offer);
- sel->action = _wl_to_elm(action);
-
- _wl_dropable_data_handle(sel, ev);
- evas_object_event_callback_del_full(sel->request_obj,
- EVAS_CALLBACK_DEL,
- _wl_sel_obj_del2, sel);
- sel->request_obj = NULL;
- }
-
- ecore_wl2_offer_finish(ev->offer);
-
- return ECORE_CALLBACK_CANCEL;
-}
-
-static Eina_Bool
-_wl_dnd_drop(void *data, int type EINA_UNUSED, void *event)
-{
- Ecore_Wl2_Event_Dnd_Drop *ev;
- Sel_Manager_Seat_Selection *seat_sel = data;
- Efl_Ui_Selection_Manager_Data *pd;
- Sel_Manager_Selection *sel;
- Sel_Manager_Dropable *drop;
- Eina_List *l;
-
- sel_debug("In\n");
- ev = event;
- seat_sel->saved_types->pos = EINA_POSITION2D(ev->x, ev->y);
- pd = seat_sel->pd;
- sel = seat_sel->sel;
- sel->dnd_offer = ev->offer;
-
- EINA_LIST_FOREACH(pd->drop_list, l, drop)
- {
- if (drop->last.in)
- {
- sel_debug("Request data of type %s; drop: %p\n", drop->last.type, drop);
- sel->request_obj = drop->obj;
- sel->request_format = drop->last.format;
- evas_object_event_callback_add(sel->request_obj,
- EVAS_CALLBACK_DEL, _wl_sel_obj_del2,
- sel);
- ecore_wl2_offer_receive(ev->offer, (char*)drop->last.type);
- ecore_event_handler_add(ECORE_WL2_EVENT_OFFER_DATA_READY, _wl_dnd_receive, seat_sel);
-
- return ECORE_CALLBACK_PASS_ON;
- }
- }
-
- ecore_wl2_dnd_drag_end(_wl_seat_get(ev->win, NULL, seat_sel->seat));
- return ECORE_CALLBACK_PASS_ON;
-}
-
-static Eina_Bool
-_wl_sel_manager_drop_target_add(Efl_Ui_Selection_Manager_Data *pd, Efl_Object *target_obj,
- Efl_Ui_Selection_Format format, unsigned int seat)
-{
- Sel_Manager_Dropable *dropable = NULL;
- Sel_Manager_Seat_Selection *seat_sel = NULL;
- Drop_Format *df;
-
- df = calloc(1, sizeof(Drop_Format));
- if (!df) return EINA_FALSE;
- df->format = format;
- dropable = efl_key_data_get(target_obj, "__elm_dropable");
- if (!dropable)
- {
- //Create new drop
- dropable = calloc(1, sizeof(Sel_Manager_Dropable));
- if (!dropable)
- {
- free(df);
- return EINA_FALSE;
- }
- pd->drop_list = eina_list_append(pd->drop_list, dropable);
- if (!pd->drop_list)
- {
- free(dropable);
- free(df);
- return EINA_FALSE;
- }
- dropable->obj = target_obj;
- efl_key_data_set(target_obj, "__elm_dropable", dropable);
- }
-
- dropable->format_list = eina_inlist_append(dropable->format_list, EINA_INLIST_GET(df));
- dropable->seat = seat;
- seat_sel = _wl_sel_manager_seat_selection_init(pd, seat);
-
- evas_object_event_callback_add(target_obj, EVAS_CALLBACK_DEL,
- _all_drop_targets_cbs_del, pd);
-
- if (!seat_sel->enter_handler)
- {
- seat_sel->enter_handler =
- ecore_event_handler_add(ECORE_WL2_EVENT_DND_ENTER,
- _wl_dnd_enter, seat_sel);
- seat_sel->leave_handler =
- ecore_event_handler_add(ECORE_WL2_EVENT_DND_LEAVE,
- _wl_dnd_leave, seat_sel);
- seat_sel->pos_handler =
- ecore_event_handler_add(ECORE_WL2_EVENT_DND_MOTION,
- _wl_dnd_position, seat_sel);
- seat_sel->drop_handler =
- ecore_event_handler_add(ECORE_WL2_EVENT_DND_DROP,
- _wl_dnd_drop, seat_sel);
- }
-
- return EINA_TRUE;
-}
-#endif
-
-#ifdef HAVE_ELEMENTARY_COCOA
-static Sel_Manager_Seat_Selection *
-_cocoa_sel_manager_seat_selection_init(Efl_Ui_Selection_Manager_Data *pd, unsigned int seat)
-{
- Sel_Manager_Seat_Selection *seat_sel = NULL;
- Eina_List *l = NULL;
-
- EINA_LIST_FOREACH(pd->seat_list, l, seat_sel)
- {
- if(seat_sel->seat == seat)
- break;
- }
- if (!seat_sel)
- {
- seat_sel = calloc(1, sizeof(Sel_Manager_Seat_Selection));
- if (!seat_sel)
- {
- ERR("Failed to allocate seat");
- return NULL;
- }
- seat_sel->saved_types = calloc(1, sizeof(Saved_Type));
- seat_sel->seat = seat;
- seat_sel->pd = pd;
- pd->seat_list = eina_list_append(pd->seat_list, seat_sel);
- }
- if (!seat_sel->sel)
- {
- Sel_Manager_Selection *sel = calloc(1, sizeof(Sel_Manager_Selection));
- if (!sel)
- {
- ERR("failed to allocate selection");
- return NULL;
- }
- sel->seat_sel = seat_sel;
- seat_sel->sel = sel;
- }
-
- return seat_sel;
-}
-
-static Ecore_Cocoa_Window *
-_cocoa_window_get(const Evas_Object *obj)
-{
- Ecore_Cocoa_Window *win = NULL;
- Evas_Object *_win;
-
- _win = elm_win_get(obj);
- if (_win)
- {
- win = elm_win_cocoa_window_get(_win);
- }
-
- if (!win)
- {
- CRI("WIN has not been retrieved!!!");
- }
-
- return win;
-}
-
-static Ecore_Cocoa_Cnp_Type
-_sel_format_to_ecore_cocoa_cnp_type(Efl_Ui_Selection_Format fmt)
-{
- Ecore_Cocoa_Cnp_Type type = 0;
-
- if ((fmt & EFL_UI_SELECTION_FORMAT_TEXT) ||
- (fmt & EFL_UI_SELECTION_FORMAT_VCARD))
- type |= ECORE_COCOA_CNP_TYPE_STRING;
- if (fmt & EFL_UI_SELECTION_FORMAT_HTML)
- type |= ECORE_COCOA_CNP_TYPE_HTML;
- if (fmt & EFL_UI_SELECTION_FORMAT_IMAGE)
- type |= ECORE_COCOA_CNP_TYPE_IMAGE;
-
- return type;
-}
-
-static void
-_cocoa_sel_obj_del_req_cb(void *data,
- Evas *e EINA_UNUSED,
- Evas_Object *obj,
- void *ev_info EINA_UNUSED)
-{
- Sel_Manager_Selection *sel = data;
- if (sel->request_obj == obj) sel->request_obj = NULL;
-}
-
-static void
-_cocoa_sel_obj_del_cb(void *data,
- Evas *e EINA_UNUSED,
- Evas_Object *obj,
- void *ev_info EINA_UNUSED)
-{
- Sel_Manager_Selection *sel = data;
- if (sel->owner == obj)
- {
- sel->owner = NULL;
- }
- //if (dragwidget == obj) dragwidget = NULL;
-}
-
-static void
-_job_pb_cb(void *data)
-{
- Sel_Manager_Selection *sel = data;
- Efl_Ui_Selection_Data ddata;
- Ecore_Cocoa_Cnp_Type type, get_type;
- void *pbdata;
- int pbdata_len;
-
- if (sel->data_func)
- {
- ddata.pos.x = 0;
- ddata.pos.y = 0;
-
- /* Pass to cocoa clipboard */
- type = _sel_format_to_ecore_cocoa_cnp_type(sel->request_format);
- pbdata = ecore_cocoa_clipboard_get(&pbdata_len, type, &get_type);
-
- ddata.format = EFL_UI_SELECTION_FORMAT_NONE;
- if (get_type & ECORE_COCOA_CNP_TYPE_STRING)
- ddata.format |= EFL_UI_SELECTION_FORMAT_TEXT;
- if (get_type & ECORE_COCOA_CNP_TYPE_IMAGE)
- ddata.format |= EFL_UI_SELECTION_FORMAT_IMAGE;
- if (get_type & ECORE_COCOA_CNP_TYPE_HTML)
- ddata.format |= EFL_UI_SELECTION_FORMAT_HTML;
-
- ddata.content.mem = pbdata;
- ddata.content.len = pbdata_len;
- ddata.action = EFL_UI_SELECTION_ACTION_UNKNOWN;
- sel->data_func(sel->data_func_data, sel->request_obj, &ddata);
- free(pbdata);
- }
-}
-
-static Eina_Future *
-_cocoa_efl_sel_manager_selection_set(Efl_Ui_Selection_Manager_Data *pd,
- Evas_Object *owner,
- Efl_Ui_Selection_Type type,
- Efl_Ui_Selection_Format format,
- Eina_Slice data,
- Ecore_Cocoa_Window *win,
- unsigned int seat)
-{
- Sel_Manager_Seat_Selection *seat_sel;
- Sel_Manager_Selection *sel;
- Ecore_Cocoa_Cnp_Type ecore_type;
- Eina_List *l, *l_next;
- Sel_Manager_Selection_Lost *sel_lost;
-
- seat_sel = _cocoa_sel_manager_seat_selection_init(pd, seat);
- seat_sel->active_type = type;
- sel = seat_sel->sel;
-
- if ((!data.mem) && (format != EFL_UI_SELECTION_FORMAT_IMAGE))
- {
- efl_ui_selection_manager_selection_clear(pd->sel_man, owner, type, seat);
- return NULL;
- }
- if (data.len <= 0) return NULL;
-
- EINA_LIST_FOREACH_SAFE(seat_sel->sel_lost_list, l, l_next, sel_lost)
- {
- if ((sel_lost->request == sel->owner) &&
- (sel_lost->type == type))
- {
- eina_promise_resolve(sel_lost->promise, eina_value_uint_init(sel_lost->type));
- }
- }
- if (sel->owner)
- evas_object_event_callback_del_full(sel->owner, EVAS_CALLBACK_DEL,
- _cocoa_sel_obj_del_cb, sel);
-
- sel->owner = owner;
- sel->win = win;
- sel->format = format;
-
- evas_object_event_callback_add(sel->owner, EVAS_CALLBACK_DEL,
- _cocoa_sel_obj_del_cb, sel);
- ELM_SAFE_FREE(sel->data.mem, free);
-
- if (format == EFL_UI_SELECTION_FORMAT_MARKUP)
- {
- //FIXME this code assumes that sel->data.mem has a \0 at the end
- sel->data.mem = evas_textblock_text_markup_to_utf8(NULL, data.mem);
- sel->data.len = strlen(sel->data.mem);
- //set the new text
- format = EFL_UI_SELECTION_FORMAT_TEXT;
- }
- else
- {
- sel->data = eina_slice_dup(data);
- }
-
- if (sel->data.mem)
- {
- ecore_type = _sel_format_to_ecore_cocoa_cnp_type(format);
- ecore_cocoa_clipboard_set(sel->data.mem, sel->data.len, ecore_type);
- }
- else
- {
- CRI("Failed to allocate memory!");
- efl_ui_selection_manager_selection_clear(pd->sel_man, owner, type, seat_sel->seat);
- return NULL;
- }
-
- return _update_sel_lost_list(owner, type, seat_sel);
-}
-
-static void
-_cocoa_efl_sel_manager_selection_get(const Efl_Object *request,
- Efl_Ui_Selection_Manager_Data *pd,
- Efl_Ui_Selection_Type type EINA_UNUSED,
- Efl_Ui_Selection_Format format,
- void *data_func_data, Efl_Ui_Selection_Data_Ready data_func, Eina_Free_Cb data_func_free_cb,
- Ecore_Cocoa_Window *win, unsigned int seat)
-{
- Sel_Manager_Seat_Selection *seat_sel;
- Sel_Manager_Selection *sel;
-
- seat_sel = _sel_manager_seat_selection_init(pd, seat);
- sel = seat_sel->sel;
- sel->request_format = format;
- sel->request_obj = (Efl_Object *)request;
- sel->data_func_data = data_func_data;
- sel->data_func = data_func;
- sel->data_func_free_cb = data_func_free_cb;
- if (sel->request_obj)
- evas_object_event_callback_del_full(sel->request_obj, EVAS_CALLBACK_DEL,
- _cocoa_sel_obj_del_req_cb, sel);
-
- sel->win = win;
- ecore_job_add(_job_pb_cb, sel);
-
- evas_object_event_callback_add(sel->request_obj, EVAS_CALLBACK_DEL,
- _cocoa_sel_obj_del_req_cb, sel);
-}
-
-#endif
-
-// win32 specific stuff
-////////////////////////////////////////////////////////////////////////////
-#ifdef HAVE_ELEMENTARY_WIN32
-static Sel_Manager_Seat_Selection *
-_win32_sel_manager_seat_selection_init(Efl_Ui_Selection_Manager_Data *pd, unsigned int seat)
-{
- Sel_Manager_Seat_Selection *seat_sel = NULL;
- Eina_List *l = NULL;
-
- EINA_LIST_FOREACH(pd->seat_list, l, seat_sel)
- {
- if(seat_sel->seat == seat)
- break;
- }
- if (!seat_sel)
- {
- seat_sel = calloc(1, sizeof(Sel_Manager_Seat_Selection));
- if (!seat_sel)
- {
- ERR("Failed to allocate seat");
- return NULL;
- }
- seat_sel->saved_types = calloc(1, sizeof(Saved_Type));
- seat_sel->seat = seat;
- seat_sel->pd = pd;
- pd->seat_list = eina_list_append(pd->seat_list, seat_sel);
- }
- if (!seat_sel->sel_list)
- {
- seat_sel->sel_list = calloc(1, (EFL_UI_SELECTION_TYPE_CLIPBOARD + 1) * sizeof(Sel_Manager_Selection));
- if (!seat_sel->sel_list)
- {
- ERR("failed to allocate selection list");
- return NULL;
- }
- _set_selection_list(seat_sel->sel_list, seat_sel);
- }
-
- return seat_sel;
-}
-
-static char *
-_win32_text_n_to_rn(char *intext)
-{
- size_t size = 0, newlines = 0;
- char *outtext = NULL, *p, *o;
-
- if (!intext) return NULL;
- for (p = intext; *p; p++)
- {
- if (*p == '\n') newlines++;
- size++;
- }
- outtext = malloc(size + newlines + 1);
- if (!outtext) return intext;
- for (p = intext, o = outtext; *p; p++, o++)
- {
- if (*p == '\n')
- {
- o++;
- *p = '\r';
- }
- *o = *p;
- }
- *o = '\0';
- free(intext);
- return outtext;
-}
-
-static void
-_win32_sel_obj_del(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
-{
- Sel_Manager_Selection *sel = data;
- if (sel->owner == obj) sel->owner = NULL;
-}
-
-static void
-_win32_sel_obj_del2(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
-{
- Sel_Manager_Selection *sel = data;
- if (sel->request_obj == obj) sel->request_obj = NULL;
-}
-
-static Ecore_Win32_Window *
-_win32_window_get(const Evas_Object *obj)
-{
- Evas_Object *top;
- Ecore_Win32_Window *win = NULL;
-
- if (elm_widget_is(obj))
- {
- top = elm_widget_top_get(obj);
- if (!top)
- {
- Evas_Object *par;
- par = elm_widget_parent_widget_get(obj);
- if (par) top = elm_widget_top_get(par);
- }
- if (top && (efl_isa(top, EFL_UI_WIN_CLASS)))
- win = elm_win_win32_window_get(top);
- }
-
- if (!win)
- {
- Ecore_Evas *ee;
- Evas *evas;
- const char *engine_name;
-
- evas = evas_object_evas_get(obj);
- if (!evas) return NULL;
-
- ee = ecore_evas_ecore_evas_get(evas);
- if (!ee) return NULL;
-
- 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;
- win = ecore_evas_win32_window_get(ee);
- }
- else
- {
- if ((strcmp(engine_name, ELM_SOFTWARE_WIN32) == 0) ||
- (strcmp(engine_name, ELM_SOFTWARE_DDRAW) == 0))
- return ecore_evas_win32_window_get(ee);
- }
- }
-
- return win;
-}
-
-static Eina_Future *
-_win32_efl_sel_manager_selection_set(Efl_Ui_Selection_Manager_Data *pd,
- Evas_Object *owner,
- Efl_Ui_Selection_Type type,
- Efl_Ui_Selection_Format format,
- Eina_Slice data,
- Ecore_Win32_Window *win,
- unsigned int seat)
-{
- Sel_Manager_Seat_Selection *seat_sel;
- Sel_Manager_Selection *sel;
-
- if (type != EFL_UI_SELECTION_TYPE_CLIPBOARD)
- return NULL;
-
- if ((!data.mem) && (format != EFL_UI_SELECTION_FORMAT_IMAGE))
- {
- efl_ui_selection_manager_selection_clear(pd->sel_man, owner, type, seat);
- return NULL;
- }
-
- seat_sel = _win32_sel_manager_seat_selection_init(pd, seat);
- seat_sel->active_type = type;
- sel = seat_sel->sel_list + type;
- if (sel->owner != owner)
- {
- Eina_List *l, *l_next;
- Sel_Manager_Selection_Lost *sel_lost;
-
- EINA_LIST_FOREACH_SAFE(seat_sel->sel_lost_list, l, l_next, sel_lost)
- {
- if ((sel_lost->request == sel->owner) &&
- (sel_lost->type == type))
- {
- eina_promise_resolve(sel_lost->promise, eina_value_uint_init(sel_lost->type));
- }
- }
-
- }
- if (sel->owner)
- evas_object_event_callback_del_full(sel->owner, EVAS_CALLBACK_DEL,
- _win32_sel_obj_del, sel);
- sel->active = EINA_TRUE;
- sel->owner = owner;
- sel->win = win;
- if (sel->set) sel->set(win, sel->data.mem, sel->data.len);
- sel->format = format;
-
- evas_object_event_callback_add
- (sel->owner, EVAS_CALLBACK_DEL, _win32_sel_obj_del, sel);
-
- ELM_SAFE_FREE(sel->data.mem, free);
- sel->data = eina_slice_dup(data);
- if (!sel->data.mem)
- {
- efl_ui_selection_manager_selection_clear(pd->sel_man, owner, type, seat_sel->seat);
- return NULL;
- }
-
- return _update_sel_lost_list(owner, type, seat_sel);
-}
-
-static void
-_win32_efl_sel_manager_selection_clear(Efl_Ui_Selection_Manager_Data *pd,
- Evas_Object *owner,
- Efl_Ui_Selection_Type type,
- Sel_Manager_Seat_Selection *seat_sel)
-{
- Sel_Manager_Selection *sel;
- Ecore_Win32_Window *win;
-
- if (type != EFL_UI_SELECTION_TYPE_CLIPBOARD)
- return;
-
- sel = seat_sel->sel_list + type;
-
- /* No longer this selection: Consider it gone! */
- if ((!sel->active) || (sel->owner != owner))
- return;
-
- if (sel->owner)
- evas_object_event_callback_del_full(sel->owner, EVAS_CALLBACK_DEL,
- _win32_sel_obj_del, sel);
- if (sel->request_obj)
- evas_object_event_callback_del_full(sel->request_obj, EVAS_CALLBACK_DEL,
- _win32_sel_obj_del2, sel);
- sel->owner = NULL;
- sel->request_obj = NULL;
- sel->active = EINA_FALSE;
- ELM_SAFE_FREE(sel->data.mem, free);
- /* sel->clear(win); */
-}
-
-static Eina_Bool
-_win32_efl_sel_manager_selection_get(const Efl_Object *request,
- Efl_Ui_Selection_Manager_Data *pd,
- 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,
- Ecore_Win32_Window *win, unsigned int seat)
-{
- Sel_Manager_Seat_Selection *seat_sel;
- Sel_Manager_Selection *sel;
- void *data;
- int size;
-
- if (type != EFL_UI_SELECTION_TYPE_CLIPBOARD)
- return EINA_FALSE;
-
- seat_sel = _sel_manager_seat_selection_init(pd, seat);
- sel = seat_sel->sel_list + type;
-
- if (sel->request_obj)
- evas_object_event_callback_del_full(sel->request_obj, EVAS_CALLBACK_DEL,
- _win32_sel_obj_del2, sel);
- sel->request_format = format;
- sel->request_obj = (Evas_Object *)request;
- sel->win = win;
- sel->data_func_data = data_func_data;
- sel->data_func = data_func;
- sel->data_func_free_cb = data_func_free_cb;
- sel->get(win, &data, &size);
-
- if (!data || (size <= 0))
- goto cb_add;
-
- if ((sel->format & EFL_UI_SELECTION_FORMAT_MARKUP) ||
- (sel->format & EFL_UI_SELECTION_FORMAT_HTML))
- {
- char *str;
-
- str = (char *)malloc(size + 1);
- if (str)
- {
- memcpy(str, data, size);
- str[size] = '\0';
- data = _win32_text_n_to_rn(_elm_util_mkup_to_text(str));
- free(str);
- if (data)
- size = strlen(data);
- else
- size = 0;
- }
- else
- {
- free(data);
- data = NULL;
- }
- }
-
- if (sel->data_func && data && (size > 0))
- {
- Efl_Ui_Selection_Data sdata;
-
- sdata.pos.x = sdata.pos.y = 0;
- sdata.format = EFL_UI_SELECTION_FORMAT_TEXT;
- sdata.content.mem = data;
- sdata.content.len = size;
- sdata.action = sel->action;
- sel->data_func(sel->data_func_data, sel->request_obj, &sdata);
- }
-
- if (data)
- free(data);
-
- cb_add:
- evas_object_event_callback_add
- (sel->request_obj, EVAS_CALLBACK_DEL, _win32_sel_obj_del2, sel);
-
- return EINA_TRUE;
-}
-
-#endif /* HAVE_ELEMENTARY_WIN32 */
-
-
-static int
-_drop_item_container_cmp(const void *d1, const void *d2)
-{
- const Item_Container_Drop_Info *di = d1;
- return (((uintptr_t)di->obj) - ((uintptr_t)d2));
-}
-
-static Eina_Bool
-_drop_item_container_del(Efl_Ui_Selection_Manager_Data *pd, Efl_Object *cont, Eina_Bool full)
-{
- Item_Container_Drop_Info *di;
-
- di = eina_list_search_unsorted(pd->drop_cont_list,
- _drop_item_container_cmp, cont);
- if (di)
- {
- _all_drop_targets_cbs_del(pd, NULL, cont, NULL);
- di->item_func_data = NULL;
- di->item_func = NULL;
-
- if (full)
- {
- pd->drop_cont_list = eina_list_remove(pd->drop_cont_list, di);
- free(di);
- }
- return EINA_TRUE;
- }
-
- return EINA_FALSE;
-}
-
-static inline Eina_List *
-_anim_icons_make(Sel_Manager_Drag_Container *dc)
-{
- Eina_List *list = NULL, *icon_list = NULL;
- Evas_Object *obj;
-
- if (dc->icon_list_func)
- {
- DBG("calling icon_list_func");
- icon_list = dc->icon_list_func(dc->icon_list_func_data, dc->cont);
- }
- EINA_LIST_FREE(icon_list, obj)
- {
- DBG("one obj in icon_list");
- Anim_Icon *ai = calloc(1, sizeof(Anim_Icon));
- if (!ai)
- {
- ERR("Failed to allocate for icon!");
- continue;
- }
-
- evas_object_geometry_get(obj, &ai->start.x, &ai->start.y, &ai->start.w, &ai->start.h);
- evas_object_show(obj);
- ai->obj = obj;
- list = eina_list_append(list, ai);
- }
- DBG("made icon list");
-
- return list;
-}
-
-static void
-_cont_obj_drag_done_cb(void *data, const Efl_Event *ev EINA_UNUSED)
-{
- Sel_Manager_Drag_Container *dc = data;
- elm_widget_scroll_freeze_pop(dc->cont);
-}
-
-static Eina_Bool
-_cont_obj_drag_start(void *data)
-{
- DBG("going to start draging");
- Sel_Manager_Drag_Container *dc = data;
-
- dc->timer = NULL;
- efl_event_callback_add(dc->cont, EFL_UI_DND_EVENT_DRAG_DONE, _cont_obj_drag_done_cb, dc);
- elm_widget_scroll_freeze_push(dc->cont);
- efl_ui_selection_manager_drag_start(dc->pd->sel_man, dc->cont, dc->format,
- eina_rw_slice_slice_get(dc->data), dc->action,
- dc->icon_func_data, dc->icon_func, dc->icon_func_free_cb,
- dc->seat);
-
- return ECORE_CALLBACK_CANCEL;
-}
-
-static Eina_Bool
-_drag_anim_play(void *data, double pos)
-{
- Sel_Manager_Drag_Container *dc = data;
-
- if (dc->animator)
- {
- Eina_List *l;
- Anim_Icon *ai;
- Evas_Coord xm, ym;
-
- if (pos > 0.99)
- {
- dc->animator = NULL;
- EINA_LIST_FOREACH(dc->icons, l, ai)
- evas_object_hide(ai->obj);
-
- _cont_obj_drag_start(dc);
- return ECORE_CALLBACK_CANCEL;
- }
-
- evas_pointer_canvas_xy_get(dc->e, &xm, &ym);
- EINA_LIST_FOREACH(dc->icons, l, ai)
- {
- int x, y, w, h;
- w = ai->start.w - ((dc->final_icon.w - ai->start.w) * pos);
- h = ai->start.h - ((dc->final_icon.h - ai->start.h) * pos);
- x = ai->start.x - (pos * (ai->start.x + (w / 2) - xm));
- y = ai->start.y - (pos * (ai->start.y + (h / 2) - ym));
- evas_object_geometry_set(ai->obj, x, y, w, h);
- }
-
- return ECORE_CALLBACK_RENEW;
- }
-
- return ECORE_CALLBACK_CANCEL;
-}
-
-static inline void
-_drag_anim_start(Sel_Manager_Drag_Container *dc)
-{
-
- dc->timer = NULL;
- if (dc->icon_func)
- {
- Eina_Position2D pos_ret;
- Evas_Object *temp_win = elm_win_add(NULL, "Temp", ELM_WIN_DND);
- Evas_Object *final_icon = dc->icon_func(dc->icon_func_data, temp_win, dc->cont, &pos_ret);
- evas_object_geometry_get(final_icon, NULL, NULL, &dc->final_icon.w, &dc->final_icon.h);
- evas_object_del(final_icon);
- evas_object_del(temp_win);
- }
- dc->animator = ecore_evas_animator_timeline_add(dc->e, dc->anim_duration, _drag_anim_play, dc);
-}
-
-static Eina_Bool
-_cont_obj_anim_start(void *data)
-{
- sel_debug("In");
- Sel_Manager_Drag_Container *dc = data;
- Efl_Object *it = NULL;
- Eina_Position2D posret; //does not use
-
- if (dc->item_get_func)
- it = dc->item_get_func(dc->item_get_func_data, dc->cont, dc->down, &posret);
- dc->timer = NULL;
- dc->format = EFL_UI_SELECTION_FORMAT_TARGETS; //default
- dc->data.len = 0;
- dc->action = EFL_UI_SELECTION_ACTION_COPY; //default
- dc->icons = NULL;
-
- //failed to get mouse-down item, abort drag
- if (!it)
- return ECORE_CALLBACK_CANCEL;
-
- if (dc->drag_data_func)
- {
- dc->drag_data_func(dc->drag_data_func_data, dc->cont,
- &dc->format, &dc->data, &dc->action);
- if (EINA_DBL_EQ(dc->anim_duration, 0.0))
- {
- _cont_obj_drag_start(dc);
- }
- else
- {
- dc->icons = _anim_icons_make(dc);
- if (dc->icons)
- {
- _drag_anim_start(dc);
- }
- else
- {
- // even if we don't manage the icons animation, we have
- // to wait until it is finished before beginning drag.
- dc->timer = ecore_timer_add(dc->anim_duration,
- _cont_obj_drag_start, dc);
- }
- }
- }
-
- return ECORE_CALLBACK_CANCEL;
-}
-
-static void
-_abort_drag(Evas_Object *obj EINA_UNUSED, Sel_Manager_Drag_Container *dc)
-{
- evas_object_event_callback_del_full(dc->cont, EVAS_CALLBACK_MOUSE_MOVE,
- _cont_obj_mouse_move_cb, dc);
- evas_object_event_callback_del_full(dc->cont, EVAS_CALLBACK_MOUSE_UP,
- _cont_obj_mouse_up_cb, dc);
- _item_container_del_internal(dc, EINA_FALSE);
-
- ELM_SAFE_FREE(dc->timer, ecore_timer_del);
- _anim_data_free(dc);
-}
-
-static void
-_cont_obj_mouse_move_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info)
-{
- Sel_Manager_Drag_Container *dc = data;
- Evas_Event_Mouse_Move *ev = event_info;
-
- if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD)
- {
- _abort_drag(obj, dc);
- }
- if (dc &&
- (evas_device_class_get(ev->dev) == EVAS_DEVICE_CLASS_TOUCH))
- {
- int dx, dy;
- int fs = elm_config_finger_size_get();
-
- dx = ev->cur.canvas.x - dc->down.x;
- dy = ev->cur.canvas.y - dc->down.y;
- if ((dx * dx + dy * dy) > (fs * fs))
- {
- sel_debug("mouse moved too much - have to cancel DnD");
- _abort_drag(obj, dc);
- }
- }
-}
-
-static void
-_anim_data_free(Sel_Manager_Drag_Container *dc)
-{
- if (dc)
- {
- ELM_SAFE_FREE(dc->animator, ecore_animator_del);
- Anim_Icon *ai;
-
- EINA_LIST_FREE(dc->icons, ai)
- {
- evas_object_del(ai->obj);
- free(ai);
- }
- dc->icons = NULL;
- }
-}
-
-static void
-_cont_obj_mouse_up_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info)
-{
- Sel_Manager_Drag_Container *dc = data;
-
- if (((Evas_Event_Mouse_Up *)event_info)->button != 1)
- return;
-
- evas_object_event_callback_del_full(dc->cont, EVAS_CALLBACK_MOUSE_MOVE,
- _cont_obj_mouse_move_cb, dc);
- evas_object_event_callback_del_full(dc->cont, EVAS_CALLBACK_MOUSE_UP,
- _cont_obj_mouse_up_cb, dc);
- ELM_SAFE_FREE(dc->timer, ecore_timer_del);
-
- _anim_data_free(dc);
-}
-
-static void
-_cont_obj_mouse_down_cb(void *data, Evas *e, Evas_Object *obj EINA_UNUSED, void *event_info)
-{
- Sel_Manager_Drag_Container *dc = data;
- Evas_Event_Mouse_Down *ev = event_info;
- if (ev->button != 1)
- return;
-
- dc->e = e;
- dc->down.x = ev->canvas.x;
- dc->down.y = ev->canvas.y;
-
- evas_object_event_callback_add(dc->cont, EVAS_CALLBACK_MOUSE_UP,
- _cont_obj_mouse_up_cb, dc);
- ecore_timer_del(dc->timer);
- if (dc->time_to_drag)
- {
- dc->timer = ecore_timer_add(dc->time_to_drag, _cont_obj_anim_start, dc);
- evas_object_event_callback_add(dc->cont, EVAS_CALLBACK_MOUSE_MOVE,
- _cont_obj_mouse_move_cb, dc);
- }
- else
- {
- _cont_obj_anim_start(dc);
- }
-}
-
-static void
-_item_container_del_internal(Sel_Manager_Drag_Container *dc, Eina_Bool full)
-{
- if (dc)
- {
- ELM_SAFE_FREE(dc->timer, ecore_timer_del);
- if (dc->animator)
- _anim_data_free(dc);
- evas_object_event_callback_del_full(dc->cont, EVAS_CALLBACK_MOUSE_DOWN,
- _cont_obj_mouse_down_cb, dc);
- if (full)
- {
- dc->item_get_func = NULL;
- dc->item_get_func_data = NULL;
- free(dc);
- }
- }
-}
-
-static int
-_drag_item_container_cmp(const void *d1, const void *d2)
-{
- const Sel_Manager_Drag_Container *dc = d1;
- return (((uintptr_t)dc->cont) - ((uintptr_t)d2));
-}
-//exposed APIs
-EOLIAN static Eina_Future *
-_efl_ui_selection_manager_selection_set(Eo *obj EINA_UNUSED, Efl_Ui_Selection_Manager_Data *pd,
- Efl_Object *owner, Efl_Ui_Selection_Type type,
- Efl_Ui_Selection_Format format,
- Eina_Slice data, unsigned int seat)
-{
- Eina_Future *p = NULL;
-
- sel_debug("owner: %p, seat: %d, type: %d, format: %d", owner, seat, type, format);
- if (type > EFL_UI_SELECTION_TYPE_CLIPBOARD)
- {
- ERR("Not supported format: %d", type);
- return NULL;
- }
-
-#ifdef HAVE_ELEMENTARY_X
- Ecore_X_Window xwin = _x11_xwin_get(owner);
- if (xwin)
- p = _x11_efl_sel_manager_selection_set(pd, owner, type, format, data, xwin, seat);
-#endif
-#ifdef HAVE_ELEMENTARY_WL2
- Ecore_Wl2_Window *win = _wl_window_get(owner);
- if (win)
- p = _wl_efl_sel_manager_selection_set(pd, owner, type, format, data, win, seat);
-#endif
-#ifdef HAVE_ELEMENTARY_COCOA
- Ecore_Cocoa_Window *win = _cocoa_window_get(owner);
- if (win)
- p = _cocoa_efl_sel_manager_selection_set(pd, owner, type, format, data, win, seat);
-#endif
-#ifdef HAVE_ELEMENTARY_WIN32
- Ecore_Win32_Window *win = _win32_window_get(owner);
- if (win)
- p = _win32_efl_sel_manager_selection_set(pd, owner, type, format, data, win, seat);
-#endif
-
- return p;
-}
-
-//TODO: add support for local
-EOLIAN static void
-_efl_ui_selection_manager_selection_get(Eo *obj EINA_UNUSED, Efl_Ui_Selection_Manager_Data *pd,
- const Efl_Object *request, 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)
-{
- sel_debug("request: %p, seat: %d, type: %d, format: %d", request, seat, type, format);
-#ifdef HAVE_ELEMENTARY_X
- Ecore_X_Window xwin = _x11_xwin_get(request);
- if (xwin)
- _x11_efl_sel_manager_selection_get(request, pd, type, format, data_func_data,
- data_func, data_func_free_cb, xwin, seat);
-#endif
-#ifdef HAVE_ELEMENTARY_WL2
- Ecore_Wl2_Window *win = _wl_window_get(request);
- if (win)
- _wl_efl_sel_manager_selection_get(request, pd, type, format, data_func_data,
- data_func, data_func_free_cb, win, seat);
-#endif
-#ifdef HAVE_ELEMENTARY_COCOA
- Ecore_Cocoa_Window *win = _cocoa_window_get(request);
- if (win)
- _cocoa_efl_sel_manager_selection_get(request, pd, type, format, data_func_data,
- data_func, data_func_free_cb, win, seat);
-#endif
-#ifdef HAVE_ELEMENTARY_WIN32
- Ecore_Win32_Window *win = _win32_window_get(request);
- if (win)
- _win32_efl_sel_manager_selection_get(request, pd, type, format, data_func_data,
- data_func, data_func_free_cb, win, seat);
-#endif
-}
-
-EOLIAN static void
-_efl_ui_selection_manager_selection_clear(Eo *obj, Efl_Ui_Selection_Manager_Data *pd,
- Efl_Object *owner, Efl_Ui_Selection_Type type, unsigned int seat)
-{
- Eina_Bool local = EINA_FALSE;
- Sel_Manager_Seat_Selection *seat_sel;
- Sel_Manager_Selection *sel = NULL;
-
- sel_debug("owner: %p, seat: %d, type: %d", owner, seat, type);
- seat_sel = _sel_manager_seat_selection_init(pd, seat);
-#ifdef HAVE_ELEMENTARY_X
- Ecore_X_Window xwin = _x11_xwin_get(obj);
- if (xwin)
- {
- sel = seat_sel->sel_list + type;
- }
-#endif
-#ifdef HAVE_ELEMENTARY_WL2
- Ecore_Wl2_Window *win = _wl_window_get(obj);
- if (win)
- {
- sel = seat_sel->sel;
- }
-#endif
-#ifdef HAVE_ELEMENTARY_COCOA
- Ecore_Cocoa_Window *win = _cocoa_window_get(obj);
- if (win)
- {
- sel = seat_sel->sel;
- }
-#endif
-#ifdef HAVE_ELEMENTARY_WIN32
- Ecore_Win32_Window *win = _win32_window_get(obj);
- {
- sel = seat_sel->sel_list + type;
- }
-#endif
- if (!sel) return;
- if ((!sel->active) && (sel->owner != owner))
- {
- return;
- }
- sel->active = EINA_FALSE;
-#ifdef HAVE_ELEMENTARY_X
- if (xwin)
- {
- seat_sel->sel_list[type].data.len = 0;
- if (seat_sel->sel_list[type].data.mem)
- {
- free(seat_sel->sel_list[type].data.mem);
- seat_sel->sel_list[type].data.mem = NULL;
- }
- if (sel->xwin != 0) local = EINA_TRUE;
- if (!local) seat_sel->sel_list[type].clear();
- else
- {
- Eina_List *l, *l_next;
- Sel_Manager_Selection_Lost *sel_lost;
-
- EINA_LIST_FOREACH_SAFE(seat_sel->sel_lost_list, l, l_next, sel_lost)
- {
- if ((sel_lost->request == sel->owner) &&
- (sel_lost->type == type))
- {
- eina_promise_resolve(sel_lost->promise, eina_value_uint_init(sel_lost->type));
- }
- }
- seat_sel->sel_list[type].owner = NULL;
- }
- }
-#endif
-#ifdef HAVE_ELEMENTARY_WL2
- if (win)
- {
- sel->selection_serial = ecore_wl2_dnd_selection_clear(_wl_seat_get(_wl_window_get(owner), owner, seat));
- }
-#endif
-#ifdef HAVE_ELEMENTARY_COCOA
- if (win)
- {
- if (sel->owner)
- evas_object_event_callback_del_full(sel->owner, EVAS_CALLBACK_DEL,
- _cocoa_sel_obj_del_cb, sel);
- if (sel->request_obj)
- evas_object_event_callback_del_full(sel->request_obj, EVAS_CALLBACK_DEL,
- _cocoa_sel_obj_del_req_cb, sel);
- sel->owner = NULL;
- sel->request_obj = NULL;
- ELM_SAFE_FREE(sel->data.mem, free);
- sel->data.len = 0;
-
- ecore_cocoa_clipboard_clear();
- }
-#endif
-#ifdef HAVE_ELEMENTARY_WIN32
- if (win)
- {
- _win32_efl_sel_manager_selection_clear(pd, owner, type, seat_sel);
- }
-#endif
-}
-
-EOLIAN static Eina_Bool
-_efl_ui_selection_manager_selection_has_owner(Eo *obj EINA_UNUSED, Efl_Ui_Selection_Manager_Data *pd EINA_UNUSED,
- Efl_Object *request, Efl_Ui_Selection_Type type,
- unsigned int seat)
-{
-#ifdef HAVE_ELEMENTARY_X
- (void)seat;
- if (_x11_xwin_get(request))
- {
- Ecore_X_Atom xtype;
- switch (type)
- {
- case EFL_UI_SELECTION_TYPE_PRIMARY:
- xtype = ECORE_X_ATOM_SELECTION_PRIMARY;
- break;
- case EFL_UI_SELECTION_TYPE_SECONDARY:
- xtype = ECORE_X_ATOM_SELECTION_SECONDARY;
- break;
- case EFL_UI_SELECTION_TYPE_DND:
- xtype = ECORE_X_ATOM_SELECTION_XDND;
- break;
- default:
- xtype = ECORE_X_ATOM_SELECTION_CLIPBOARD;
- }
- return !!ecore_x_selection_owner_get(xtype);
- }
-#endif
-#ifdef HAVE_ELEMENTARY_WL2
- Ecore_Wl2_Window *win;
-
- win = _wl_window_get(request);
- if (win)
- return !!ecore_wl2_dnd_selection_get(_wl_seat_get(win, request, seat));
-#endif
-#ifdef HAVE_ELEMENTARY_COCOA
- // FIXME: need to check if there is clipboard data. Paste always enabled.
- return EINA_TRUE;
-#endif
- return EINA_FALSE;
-}
-
-EOLIAN static void
-_efl_ui_selection_manager_drag_start(Eo *obj, Efl_Ui_Selection_Manager_Data *pd,
- Efl_Object *drag_obj, 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)
-{
-#ifdef HAVE_ELEMENTARY_X
- Ecore_X_Window xwin = _x11_xwin_get(drag_obj);
- if (xwin)
- _x11_efl_sel_manager_drag_start(obj, pd, drag_obj, format, data, action,
- icon_func_data, icon_func, icon_func_free_cb,
- xwin, seat);
-#endif
-#ifdef HAVE_ELEMENTARY_WL2
- Ecore_Wl2_Window *win = _wl_window_get(drag_obj);
- if (win)
- _wl_efl_sel_manager_drag_start(obj, pd, drag_obj, format, data, action,
- icon_func_data, icon_func, icon_func_free_cb,
- win, seat);
-#endif
-#ifdef HAVE_ELEMENTARY_WIN32
-#endif
-#ifdef HAVE_ELEMENTARY_COCOA
-#endif
-}
-
-EOLIAN static void
-_efl_ui_selection_manager_drag_cancel(Eo *obj EINA_UNUSED, Efl_Ui_Selection_Manager_Data *pd,
- Efl_Object *drag_obj, unsigned int seat)
-{
- Sel_Manager_Seat_Selection *seat_sel = _sel_manager_seat_selection_init(pd, seat);
-
-#ifdef HAVE_ELEMENTARY_X
- Ecore_X_Window xwin = _x11_xwin_get(drag_obj);
- if (xwin)
- {
- ecore_x_pointer_ungrab();
- ELM_SAFE_FREE(seat_sel->mouse_up_handler, ecore_event_handler_del);
- ELM_SAFE_FREE(seat_sel->dnd_status_handler, ecore_event_handler_del);
- ecore_x_dnd_abort(xwin);
- if (seat_sel->drag_obj)
- {
- if (elm_widget_is(seat_sel->drag_obj))
- {
- Evas_Object *win = elm_widget_top_get(seat_sel->drag_obj);
- if (win && efl_isa(win, EFL_UI_WIN_CLASS))
- efl_event_callback_del(win, EFL_UI_WIN_EVENT_WIN_ROTATION_CHANGED,
- _x11_win_rotation_changed_cb, seat_sel->drag_win);
- }
- }
- seat_sel->drag_obj = NULL;
- }
-#endif
-#ifdef HAVE_ELEMENTARY_WL2
- Ecore_Wl2_Window *win;
-
- win = _wl_window_get(drag_obj);
- if (win)
- ecore_wl2_dnd_drag_end(_wl_seat_get(win, drag_obj, seat));
-#endif
-
- ELM_SAFE_FREE(seat_sel->drag_win, evas_object_del);
-}
-
-EOLIAN static void
-_efl_ui_selection_manager_drag_action_set(Eo *obj EINA_UNUSED, Efl_Ui_Selection_Manager_Data *pd,
- Efl_Object *drag_obj, Efl_Ui_Selection_Action action,
- unsigned int seat)
-{
- Sel_Manager_Seat_Selection *seat_sel = _sel_manager_seat_selection_init(pd, seat);
- if (seat_sel->drag_action == action) return;
- seat_sel->drag_action = action;
-#ifdef HAVE_ELEMENTARY_X
- Ecore_X_Atom actx;
- Ecore_X_Window xwin = _x11_xwin_get(drag_obj);
- if (xwin)
- {
- actx = _x11_dnd_action_rev_map(action);
- ecore_x_dnd_source_action_set(actx);
- }
-#endif
-}
-
-//drop side
-EOLIAN static Eina_Bool
-_efl_ui_selection_manager_drop_target_add(Eo *obj EINA_UNUSED, Efl_Ui_Selection_Manager_Data *pd,
- Efl_Object *target_obj, Efl_Ui_Selection_Format format,
- unsigned int seat)
-{
- Eina_Bool ret = EINA_FALSE;
-#ifdef HAVE_ELEMENTARY_X
- Ecore_X_Window xwin = _x11_xwin_get(target_obj);
- if (xwin)
- ret = _x11_sel_manager_drop_target_add(pd, target_obj, format, xwin, seat);
-#endif
-#ifdef HAVE_ELEMENTARY_WL2
- Ecore_Wl2_Window *win = _wl_window_get(target_obj);
- if (win)
- ret = _wl_sel_manager_drop_target_add(pd, target_obj, format, seat);
-#endif
- return ret;
-}
-
-EOLIAN static void
-_efl_ui_selection_manager_drop_target_del(Eo *obj EINA_UNUSED, Efl_Ui_Selection_Manager_Data *pd,
- Efl_Object *target_obj, Efl_Ui_Selection_Format format,
- unsigned int seat)
-{
- Sel_Manager_Dropable *dropable = NULL;
- Sel_Manager_Seat_Selection *seat_sel;
- Eina_Bool remove_handler = EINA_FALSE;
-
- dropable = efl_key_data_get(target_obj, "__elm_dropable");
- if (dropable)
- {
- Eina_Inlist *itr;
- Drop_Format *df;
- EINA_INLIST_FOREACH_SAFE(dropable->format_list, itr, df)
- {
- if (df->format == format)
- {
- dropable->format_list = eina_inlist_remove(dropable->format_list,
- EINA_INLIST_GET(df));
- free(df);
- }
- }
- if (!dropable->format_list)
- {
- pd->drop_list = eina_list_remove(pd->drop_list, dropable);
- efl_key_data_set(target_obj, "__elm_dropable", NULL);
- free(dropable);
- evas_object_event_callback_del(target_obj, EVAS_CALLBACK_DEL,
- _all_drop_targets_cbs_del);
- }
- }
-
-#ifdef HAVE_ELEMENTARY_X
- if (pd->drop_list)
- {
- Eina_List *l;
- Ecore_X_Window xwin;
- Eina_Bool have_drop_list = EINA_FALSE;
-
- xwin = _x11_xwin_get(target_obj);
- EINA_LIST_FOREACH(pd->drop_list, l, dropable)
- {
- if (xwin == _x11_xwin_get(dropable->obj))
- {
- have_drop_list = EINA_TRUE;
- break;
- }
- }
- if (!have_drop_list)
- {
- ecore_x_dnd_aware_set(xwin, EINA_FALSE);
- remove_handler = EINA_TRUE;
- }
- }
- else remove_handler = EINA_TRUE;
-#endif
- if (remove_handler)
- {
- seat_sel = _sel_manager_seat_selection_init(pd, seat);
- ELM_SAFE_FREE(seat_sel->pos_handler, ecore_event_handler_del);
- ELM_SAFE_FREE(seat_sel->drop_handler, ecore_event_handler_del);
- ELM_SAFE_FREE(seat_sel->enter_handler, ecore_event_handler_del);
- ELM_SAFE_FREE(seat_sel->leave_handler, ecore_event_handler_del);
- }
-}
-
-EOLIAN static void
-_efl_ui_selection_manager_container_drop_item_add(Eo *obj, Efl_Ui_Selection_Manager_Data *pd,
- Efl_Object *cont, Efl_Ui_Selection_Format format,
- void *item_func_data, Efl_Dnd_Item_Get item_func,
- Eina_Free_Cb item_func_free_cb EINA_UNUSED,
- unsigned int seat)
-{
- Item_Container_Drop_Info *di;
- Sel_Manager_Dropable *dropable = NULL;
-
- if (_drop_item_container_del(pd, cont, EINA_FALSE))
- {
- di = eina_list_search_unsorted(pd->drop_cont_list, _drop_item_container_cmp, obj);
- if (!di) return;
- }
- else
- {
- di = calloc(1, sizeof(Item_Container_Drop_Info));
- if (!di) return;
-
- di->obj = obj;
- pd->drop_cont_list = eina_list_append(pd->drop_cont_list, di);
- }
- di->item_func = item_func;
- di->item_func_data = item_func_data;
-
- dropable = efl_key_data_get(cont, "__elm_dropable");
- if (!dropable)
- {
- dropable = calloc(1, sizeof(Sel_Manager_Dropable));
- if (!dropable) return;
- dropable->last.in = EINA_FALSE;
- pd->drop_list = eina_list_append(pd->drop_list, dropable);
- if (!pd->drop_list) return;
- dropable->obj = cont;
- efl_key_data_set(cont, "__elm_dropable", dropable);
- }
- dropable->is_container = EINA_TRUE;
- dropable->item_func = item_func;
- dropable->item_func_data = item_func_data;
- _efl_ui_selection_manager_drop_target_add(obj, pd, cont, format, seat);
-}
-
-EOLIAN static void
-_efl_ui_selection_manager_container_drop_item_del(Eo *obj EINA_UNUSED, Efl_Ui_Selection_Manager_Data *pd,
- Efl_Object *cont, unsigned int seat EINA_UNUSED)
-{
- _drop_item_container_del(pd, cont, EINA_TRUE);
-}
-
-EOLIAN static void
-_efl_ui_selection_manager_container_drag_item_add(Eo *obj EINA_UNUSED, Efl_Ui_Selection_Manager_Data *pd,
- Efl_Object *cont, double time_to_drag, double anim_duration,
- void *data_func_data, Efl_Dnd_Drag_Data_Get data_func, Eina_Free_Cb data_func_free_cb,
- void *item_get_func_data, Efl_Dnd_Item_Get item_get_func, Eina_Free_Cb item_get_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)
-{
- //TODO: remove previous drag one
- Sel_Manager_Drag_Container *dc = calloc(1, sizeof(Sel_Manager_Drag_Container));
- if (!dc)
- {
- ERR("Failed to allocate memory");
- return;
- }
- dc->cont = cont;
- dc->time_to_drag = time_to_drag;
- dc->anim_duration = anim_duration;
- dc->drag_data_func_data = data_func_data;
- dc->drag_data_func = data_func;
- dc->drag_data_func_free_cb = data_func_free_cb;
- dc->item_get_func_data = item_get_func_data;
- dc->item_get_func = item_get_func;
- dc->item_get_func_free_cb = item_get_func_free_cb;
- dc->icon_func_data = icon_func_data;
- dc->icon_func = icon_func;
- dc->icon_func_free_cb = icon_func_free_cb;
- dc->icon_list_func_data = icon_list_func_data;
- dc->icon_list_func = icon_list_func;
- dc->icon_list_func_free_cb = icon_list_func_free_cb;
- dc->seat = seat;
- dc->pd = pd;
-
- _sel_manager_seat_selection_init(pd, seat);
-
- pd->drag_cont_list = eina_list_append(pd->drag_cont_list, dc);
-
- evas_object_event_callback_add(cont, EVAS_CALLBACK_MOUSE_DOWN,
- _cont_obj_mouse_down_cb, dc);
-}
-
-EOLIAN static void
-_efl_ui_selection_manager_container_drag_item_del(Eo *obj EINA_UNUSED, Efl_Ui_Selection_Manager_Data *pd,
- Efl_Object *cont, unsigned int seat EINA_UNUSED)
-{
- Sel_Manager_Drag_Container *dc = eina_list_search_unsorted(pd->drag_cont_list,
- _drag_item_container_cmp, cont);
- if (dc)
- _item_container_del_internal(dc, EINA_TRUE);
-}
-
-static Eo *
-_efl_ui_selection_manager_efl_object_constructor(Eo *obj, Efl_Ui_Selection_Manager_Data *pd)
-{
-#if defined(HAVE_ELEMENTARY_X) || defined(HAVE_ELEMENTARY_WL2)
- const char *ev = getenv("ELM_DISPLAY");
-#endif
-
-#ifdef HAVE_ELEMENTARY_X
- Eina_Bool init_x = EINA_FALSE;
- Eina_Bool have_display = !!getenv("DISPLAY");
-
- if (ev) /* If ELM_DISPLAY is specified */
- {
- if (!strcmp(ev, "x11")) /* and it is X11 */
- {
- if (!have_display) /* if there is no $DISPLAY */
- {
- ERR("$ELM_DISPLAY is set to x11 but $DISPLAY is not set");
- init_x = EINA_FALSE;
- }
- else /* if there is */
- init_x = EINA_TRUE;
- }
- else /* not X11 */
- init_x = EINA_FALSE;
- }
- else /* ELM_DISPLAY not specified */
- {
- if (have_display) /* If there is a $DISPLAY */
- init_x = EINA_TRUE;
- else /* No $DISPLAY */
- init_x = EINA_FALSE;
- }
- if (init_x)
- {
- if (!ecore_x_init(NULL))
- {
- ERR("Could not initialize Ecore_X");
- return NULL;
- }
- }
-#endif
-#ifdef HAVE_ELEMENTARY_WL2
- Eina_Bool init_wl = EINA_FALSE;
- Eina_Bool have_wl_display = !!getenv("WAYLAND_DISPLAY");
-
- if (ev) /* If ELM_DISPLAY is specified */
- {
- if (!strcmp(ev, "wl")) /* and it is WL */
- {
- /* always try to connect to wl when it is enforced */
- init_wl = EINA_TRUE;
- }
- else /* not wl */
- init_wl = EINA_FALSE;
- }
- else /* ELM_DISPLAY not specified */
- {
- /* If there is a $WAYLAND_DISPLAY */
- if ((have_wl_display) && (!getenv("DISPLAY")))
- init_wl = EINA_TRUE;
- else /* No $WAYLAND_DISPLAY */
- init_wl = EINA_FALSE;
- }
- if (init_wl)
- {
- if (!ecore_wl2_init())
- {
- ERR("Could not initialize Ecore_Wl2");
- return NULL;
- }
- _elm_wl_display = ecore_wl2_display_connect(NULL);
- if (!_elm_wl_display)
- {
- ERR("Could not connect to Wayland Display");
- ecore_wl2_shutdown();
- return NULL;
- }
- }
-#endif
-
- obj = efl_constructor(efl_super(obj, MY_CLASS));
-
- pd->sel_man = obj;
- pd->atom_list = calloc(1, SELECTION_N_ATOMS * sizeof(Sel_Manager_Atom));
- if (!pd->atom_list)
- {
- ERR("failed to allocate atom_list");
- return NULL;
- }
- pd->atom_list[SELECTION_ATOM_TARGETS].name = "TARGETS";
- pd->atom_list[SELECTION_ATOM_TARGETS].format = EFL_UI_SELECTION_FORMAT_TARGETS;
-#ifdef HAVE_ELEMENTARY_X
- pd->atom_list[SELECTION_ATOM_TARGETS].x_converter = _x11_targets_converter;
-#endif
-#ifdef HAVE_ELEMENTARY_WL2
- pd->atom_list[SELECTION_ATOM_TARGETS].wl_converter = _wl_targets_converter;
-#endif
- pd->atom_list[SELECTION_ATOM_ATOM].name = "ATOM"; // for opera browser
- pd->atom_list[SELECTION_ATOM_ATOM].format = EFL_UI_SELECTION_FORMAT_TARGETS;
-#ifdef HAVE_ELEMENTARY_X
- pd->atom_list[SELECTION_ATOM_ATOM].x_converter = _x11_targets_converter;
-#endif
-#ifdef HAVE_ELEMENTARY_WL2
- pd->atom_list[SELECTION_ATOM_ATOM].wl_converter = _wl_targets_converter;
-#endif
-
- pd->atom_list[SELECTION_ATOM_ELM].name = "application/x-elementary-markup";
- pd->atom_list[SELECTION_ATOM_ELM].format = EFL_UI_SELECTION_FORMAT_MARKUP;
-#ifdef HAVE_ELEMENTARY_X
- pd->atom_list[SELECTION_ATOM_ELM].x_converter = _x11_general_converter;
- pd->atom_list[SELECTION_ATOM_ELM].x_data_preparer = _x11_data_preparer_markup;
-#endif
-#ifdef HAVE_ELEMENTARY_WL2
- pd->atom_list[SELECTION_ATOM_ELM].wl_converter = _wl_general_converter;
- pd->atom_list[SELECTION_ATOM_ELM].wl_data_preparer = _wl_data_preparer_markup;
-#endif
-
- pd->atom_list[SELECTION_ATOM_TEXT_URILIST].name = "text/uri-list";
- pd->atom_list[SELECTION_ATOM_TEXT_URILIST].format = EFL_UI_SELECTION_FORMAT_TEXT;
-#ifdef HAVE_ELEMENTARY_X
- pd->atom_list[SELECTION_ATOM_TEXT_URILIST].x_converter = _x11_general_converter;
- pd->atom_list[SELECTION_ATOM_TEXT_URILIST].x_data_preparer = _x11_data_preparer_uri;
-#endif
-#ifdef HAVE_ELEMENTARY_WL2
- pd->atom_list[SELECTION_ATOM_TEXT_URILIST].wl_converter = _wl_general_converter;
- pd->atom_list[SELECTION_ATOM_TEXT_URILIST].wl_data_preparer = _wl_data_preparer_uri;
-#endif
-
- pd->atom_list[SELECTION_ATOM_TEXT_X_VCARD].name = "text/x-vcard";
- pd->atom_list[SELECTION_ATOM_TEXT_X_VCARD].format = EFL_UI_SELECTION_FORMAT_VCARD;
-#ifdef HAVE_ELEMENTARY_X
- pd->atom_list[SELECTION_ATOM_TEXT_X_VCARD].x_converter = _x11_vcard_send;
- pd->atom_list[SELECTION_ATOM_TEXT_X_VCARD].x_data_preparer = _x11_data_preparer_vcard;
-#endif
-#ifdef HAVE_ELEMENTARY_WL2
- pd->atom_list[SELECTION_ATOM_TEXT_X_VCARD].wl_data_preparer = _wl_data_preparer_vcard;
-#endif
-
- pd->atom_list[SELECTION_ATOM_IMAGE_PNG].name = "image/png";
- pd->atom_list[SELECTION_ATOM_IMAGE_PNG].format = EFL_UI_SELECTION_FORMAT_IMAGE;
-#ifdef HAVE_ELEMENTARY_X
- pd->atom_list[SELECTION_ATOM_IMAGE_PNG].x_converter = _x11_image_converter;
- pd->atom_list[SELECTION_ATOM_IMAGE_PNG].x_data_preparer = _x11_data_preparer_image;
-#endif
-#ifdef HAVE_ELEMENTARY_WL2
- pd->atom_list[SELECTION_ATOM_IMAGE_PNG].wl_data_preparer = _wl_data_preparer_image;
-#endif
-
- pd->atom_list[SELECTION_ATOM_IMAGE_JPEG].name = "image/jpeg";
- pd->atom_list[SELECTION_ATOM_IMAGE_JPEG].format = EFL_UI_SELECTION_FORMAT_IMAGE;
-#ifdef HAVE_ELEMENTARY_X
- pd->atom_list[SELECTION_ATOM_IMAGE_JPEG].x_converter = _x11_image_converter;
- pd->atom_list[SELECTION_ATOM_IMAGE_JPEG].x_data_preparer = _x11_data_preparer_image;
-#endif
-#ifdef HAVE_ELEMENTARY_WL2
- pd->atom_list[SELECTION_ATOM_IMAGE_JPEG].wl_data_preparer = _wl_data_preparer_image;
-#endif
-
- pd->atom_list[SELECTION_ATOM_IMAGE_BMP].name = "image/x-ms-bmp";
- pd->atom_list[SELECTION_ATOM_IMAGE_BMP].format = EFL_UI_SELECTION_FORMAT_IMAGE;
-#ifdef HAVE_ELEMENTARY_X
- pd->atom_list[SELECTION_ATOM_IMAGE_BMP].x_converter = _x11_image_converter;
- pd->atom_list[SELECTION_ATOM_IMAGE_BMP].x_data_preparer = _x11_data_preparer_image;
-#endif
-#ifdef HAVE_ELEMENTARY_WL2
- pd->atom_list[SELECTION_ATOM_IMAGE_BMP].wl_data_preparer = _wl_data_preparer_image;
-#endif
-
- pd->atom_list[SELECTION_ATOM_IMAGE_GIF].name = "image/gif";
- pd->atom_list[SELECTION_ATOM_IMAGE_GIF].format = EFL_UI_SELECTION_FORMAT_IMAGE;
-#ifdef HAVE_ELEMENTARY_X
- pd->atom_list[SELECTION_ATOM_IMAGE_GIF].x_converter = _x11_image_converter;
- pd->atom_list[SELECTION_ATOM_IMAGE_GIF].x_data_preparer = _x11_data_preparer_image;
-#endif
-#ifdef HAVE_ELEMENTARY_WL2
- pd->atom_list[SELECTION_ATOM_IMAGE_GIF].wl_data_preparer = _wl_data_preparer_image;
-#endif
-
- pd->atom_list[SELECTION_ATOM_IMAGE_TIFF].name = "image/tiff";
- pd->atom_list[SELECTION_ATOM_IMAGE_TIFF].format = EFL_UI_SELECTION_FORMAT_IMAGE;
-#ifdef HAVE_ELEMENTARY_X
- pd->atom_list[SELECTION_ATOM_IMAGE_TIFF].x_converter = _x11_image_converter;
- pd->atom_list[SELECTION_ATOM_IMAGE_TIFF].x_data_preparer = _x11_data_preparer_image;
-#endif
-#ifdef HAVE_ELEMENTARY_WL2
- pd->atom_list[SELECTION_ATOM_IMAGE_TIFF].wl_data_preparer = _wl_data_preparer_image;
-#endif
-
- pd->atom_list[SELECTION_ATOM_IMAGE_SVG].name = "image/svg+xml";
- pd->atom_list[SELECTION_ATOM_IMAGE_SVG].format = EFL_UI_SELECTION_FORMAT_IMAGE;
-#ifdef HAVE_ELEMENTARY_X
- pd->atom_list[SELECTION_ATOM_IMAGE_SVG].x_converter = _x11_image_converter;
- pd->atom_list[SELECTION_ATOM_IMAGE_SVG].x_data_preparer = _x11_data_preparer_image;
-#endif
-#ifdef HAVE_ELEMENTARY_WL2
- pd->atom_list[SELECTION_ATOM_IMAGE_SVG].wl_data_preparer = _wl_data_preparer_image;
-#endif
-
- pd->atom_list[SELECTION_ATOM_IMAGE_XPM].name = "image/x-xpixmap";
- pd->atom_list[SELECTION_ATOM_IMAGE_XPM].format = EFL_UI_SELECTION_FORMAT_IMAGE;
-#ifdef HAVE_ELEMENTARY_X
- pd->atom_list[SELECTION_ATOM_IMAGE_XPM].x_converter = _x11_image_converter;
- pd->atom_list[SELECTION_ATOM_IMAGE_XPM].x_data_preparer = _x11_data_preparer_image;
-#endif
-#ifdef HAVE_ELEMENTARY_WL2
- pd->atom_list[SELECTION_ATOM_IMAGE_XPM].wl_data_preparer = _wl_data_preparer_image;
-#endif
-
- pd->atom_list[SELECTION_ATOM_IMAGE_TGA].name = "image/x-tga";
- pd->atom_list[SELECTION_ATOM_IMAGE_TGA].format = EFL_UI_SELECTION_FORMAT_IMAGE;
-#ifdef HAVE_ELEMENTARY_X
- pd->atom_list[SELECTION_ATOM_IMAGE_TGA].x_converter = _x11_image_converter;
- pd->atom_list[SELECTION_ATOM_IMAGE_TGA].x_data_preparer = _x11_data_preparer_image;
-#endif
-#ifdef HAVE_ELEMENTARY_WL2
- pd->atom_list[SELECTION_ATOM_IMAGE_TGA].wl_data_preparer = _wl_data_preparer_image;
-#endif
-
- pd->atom_list[SELECTION_ATOM_IMAGE_PPM].name = "image/x-portable-pixmap";
- pd->atom_list[SELECTION_ATOM_IMAGE_PPM].format = EFL_UI_SELECTION_FORMAT_IMAGE;
-#ifdef HAVE_ELEMENTARY_X
- pd->atom_list[SELECTION_ATOM_IMAGE_PPM].x_converter = _x11_image_converter;
- pd->atom_list[SELECTION_ATOM_IMAGE_PPM].x_data_preparer = _x11_data_preparer_image;
-#endif
-#ifdef HAVE_ELEMENTARY_WL2
- pd->atom_list[SELECTION_ATOM_IMAGE_PPM].wl_data_preparer = _wl_data_preparer_image;
-#endif
-
- pd->atom_list[SELECTION_ATOM_UTF8STRING].name = "UTF8_STRING";
- pd->atom_list[SELECTION_ATOM_UTF8STRING].format = EFL_UI_SELECTION_FORMAT_TEXT | EFL_UI_SELECTION_FORMAT_MARKUP | EFL_UI_SELECTION_FORMAT_HTML;
-#ifdef HAVE_ELEMENTARY_X
- pd->atom_list[SELECTION_ATOM_UTF8STRING].x_converter = _x11_text_converter;
- pd->atom_list[SELECTION_ATOM_UTF8STRING].x_data_preparer = _x11_data_preparer_text;
-#endif
-#ifdef HAVE_ELEMENTARY_WL2
- pd->atom_list[SELECTION_ATOM_UTF8STRING].wl_converter = _wl_text_converter;
- pd->atom_list[SELECTION_ATOM_UTF8STRING].wl_data_preparer = _wl_data_preparer_text,
-#endif
-
- pd->atom_list[SELECTION_ATOM_STRING].name = "STRING";
- pd->atom_list[SELECTION_ATOM_STRING].format = EFL_UI_SELECTION_FORMAT_TEXT | EFL_UI_SELECTION_FORMAT_MARKUP | EFL_UI_SELECTION_FORMAT_HTML;
-#ifdef HAVE_ELEMENTARY_X
- pd->atom_list[SELECTION_ATOM_STRING].x_converter = _x11_text_converter;
- pd->atom_list[SELECTION_ATOM_STRING].x_data_preparer = _x11_data_preparer_text;
-#endif
-#ifdef HAVE_ELEMENTARY_WL2
- pd->atom_list[SELECTION_ATOM_STRING].wl_converter = _wl_text_converter;
- pd->atom_list[SELECTION_ATOM_STRING].wl_data_preparer = _wl_data_preparer_text;
-#endif
-
- pd->atom_list[SELECTION_ATOM_COMPOUND_TEXT].name = "COMPOUND_TEXT";
- pd->atom_list[SELECTION_ATOM_COMPOUND_TEXT].format = EFL_UI_SELECTION_FORMAT_TEXT | EFL_UI_SELECTION_FORMAT_MARKUP | EFL_UI_SELECTION_FORMAT_HTML;
-#ifdef HAVE_ELEMENTARY_X
- pd->atom_list[SELECTION_ATOM_COMPOUND_TEXT].x_converter = _x11_text_converter;
- pd->atom_list[SELECTION_ATOM_COMPOUND_TEXT].x_data_preparer = _x11_data_preparer_text;
-#endif
-#ifdef HAVE_ELEMENTARY_WL2
- pd->atom_list[SELECTION_ATOM_COMPOUND_TEXT].wl_converter = _wl_text_converter;
- pd->atom_list[SELECTION_ATOM_COMPOUND_TEXT].wl_data_preparer = _wl_data_preparer_text;
-#endif
-
- pd->atom_list[SELECTION_ATOM_TEXT].name = "TEXT";
- pd->atom_list[SELECTION_ATOM_TEXT].format = EFL_UI_SELECTION_FORMAT_TEXT | EFL_UI_SELECTION_FORMAT_MARKUP | EFL_UI_SELECTION_FORMAT_HTML;
-#ifdef HAVE_ELEMENTARY_X
- pd->atom_list[SELECTION_ATOM_TEXT].x_converter = _x11_text_converter;
- pd->atom_list[SELECTION_ATOM_TEXT].x_data_preparer = _x11_data_preparer_text;
-#endif
-#ifdef HAVE_ELEMENTARY_WL2
- pd->atom_list[SELECTION_ATOM_TEXT].wl_converter = _wl_text_converter;
- pd->atom_list[SELECTION_ATOM_TEXT].wl_data_preparer = _wl_data_preparer_text;
-#endif
-
- pd->atom_list[SELECTION_ATOM_TEXT_PLAIN_UTF8].name = "text/plain;charset=utf-8";
- pd->atom_list[SELECTION_ATOM_TEXT_PLAIN_UTF8].format = EFL_UI_SELECTION_FORMAT_TEXT;
-#ifdef HAVE_ELEMENTARY_X
- pd->atom_list[SELECTION_ATOM_TEXT_PLAIN_UTF8].x_converter = _x11_text_converter;
- pd->atom_list[SELECTION_ATOM_TEXT_PLAIN_UTF8].x_data_preparer = _x11_data_preparer_text;
-#endif
-#ifdef HAVE_ELEMENTARY_WL2
- pd->atom_list[SELECTION_ATOM_TEXT_PLAIN_UTF8].wl_converter = _wl_text_converter;
- pd->atom_list[SELECTION_ATOM_TEXT_PLAIN_UTF8].wl_data_preparer = _wl_data_preparer_text;
-#endif
-
- pd->atom_list[SELECTION_ATOM_TEXT_PLAIN].name = "text/plain";
- pd->atom_list[SELECTION_ATOM_TEXT_PLAIN].format = EFL_UI_SELECTION_FORMAT_TEXT;
-#ifdef HAVE_ELEMENTARY_X
- pd->atom_list[SELECTION_ATOM_TEXT_PLAIN].x_converter = _x11_text_converter;
- pd->atom_list[SELECTION_ATOM_TEXT_PLAIN].x_data_preparer = _x11_data_preparer_text;
-#endif
-#ifdef HAVE_ELEMENTARY_WL2
- pd->atom_list[SELECTION_ATOM_TEXT_PLAIN].wl_converter = _wl_text_converter;
- pd->atom_list[SELECTION_ATOM_TEXT_PLAIN].wl_data_preparer = _wl_data_preparer_text;
-#endif
-
-
- int i;
-#ifdef HAVE_ELEMENTARY_X
- if (ecore_x_display_get())
- {
- for (i = 0; i < SELECTION_N_ATOMS; i++)
- {
- pd->atom_list[i].x_atom = ecore_x_atom_get(pd->atom_list[i].name);
- ecore_x_selection_converter_atom_add
- (pd->atom_list[i].x_atom, pd->atom_list[i].x_converter);
- }
- pd->notify_handler = ecore_event_handler_add(ECORE_X_EVENT_SELECTION_NOTIFY,
- _efl_sel_manager_x11_selection_notify, pd);
- pd->clear_handler = ecore_event_handler_add(ECORE_X_EVENT_SELECTION_CLEAR,
- _x11_selection_clear, pd);
- if (ECORE_X_EVENT_FIXES_SELECTION_NOTIFY) // If XFIXES is not available ECORE_X_EVENT_FIXES_SELECTION_NOTIFY would be NULL
- pd->fix_handler = ecore_event_handler_add(ECORE_X_EVENT_FIXES_SELECTION_NOTIFY,
- _x11_fixes_selection_notify, pd);
- }
-#endif
-
- pd->type_hash = eina_hash_string_small_new(NULL);
- for (i = 0; i < SELECTION_N_ATOMS; i++)
- {
- eina_hash_add(pd->type_hash, pd->atom_list[i].name, &pd->atom_list[i]);
- }
- pd->text_uri = eina_stringshare_add("text/uri-list");
-
-#ifdef HAVE_ELEMENTARY_WL2
- if (_elm_wl_display)
- {
- pd->send_handler = ecore_event_handler_add(ECORE_WL2_EVENT_DATA_SOURCE_SEND,
- _wl_selection_send, pd);
- pd->changed_handler = ecore_event_handler_add(ECORE_WL2_EVENT_SEAT_SELECTION,
- _wl_selection_changed, pd);
- pd->end_handler = ecore_event_handler_add(ECORE_WL2_EVENT_DATA_SOURCE_END,
- _wl_dnd_end, pd);
- }
-#endif
- managers = eina_list_append(managers, obj);
- return obj;
-}
-
-static void
-_efl_ui_selection_manager_efl_object_destructor(Eo *obj, Efl_Ui_Selection_Manager_Data *pd)
-{
- Sel_Manager_Seat_Selection *seat_sel;
- Eina_List *l;
- Sel_Manager_Dropable *dropable;
-
- managers = eina_list_remove(managers, obj);
- EINA_LIST_FOREACH(pd->drop_list, l, dropable)
- {
- _drop_target_cbs_del(pd, dropable, dropable->obj);
- }
-#ifdef HAVE_ELEMENTARY_X
- ecore_event_handler_del(pd->notify_handler);
- ecore_event_handler_del(pd->clear_handler);
-#endif
-#ifdef HAVE_ELEMENTARY_WL2
- ecore_event_handler_del(pd->send_handler);
- ecore_event_handler_del(pd->changed_handler);
- ecore_event_handler_del(pd->end_handler);
-#endif
- free(pd->atom_list);
- EINA_LIST_FREE(pd->seat_list, seat_sel)
- {
- ecore_event_handler_del(seat_sel->pos_handler);
- ecore_event_handler_del(seat_sel->drop_handler);
- ecore_event_handler_del(seat_sel->enter_handler);
- ecore_event_handler_del(seat_sel->leave_handler);
-#ifdef HAVE_ELEMENTARY_X
- free(seat_sel->sel_list);
-#endif
-#ifdef HAVE_ELEMENTARY_WL2
- free(seat_sel->sel);
-#endif
-#ifdef HAVE_ELEMENTARY_COCOA
- free(seat_sel->sel);
-#endif
-#ifdef HAVE_ELEMENTARY_WIN32
- free(seat_sel->sel_list);
-#endif
- free(seat_sel->saved_types->types);
- free(seat_sel->saved_types->imgfile);
- free(seat_sel->saved_types);
- }
- eina_hash_free(pd->type_hash);
- eina_stringshare_del(pd->text_uri);
-
- efl_destructor(efl_super(obj, MY_CLASS));
-#if defined(HAVE_ELEMENTARY_X) || defined(HAVE_ELEMENTARY_WL2) || defined(HAVE_ELEMENTARY_WIN32)
- const char *ev = getenv("ELM_DISPLAY");
-#endif
-
-#ifdef HAVE_ELEMENTARY_X
- Eina_Bool init_x = EINA_FALSE;
- Eina_Bool have_display = !!getenv("DISPLAY");
-
- if (ev) /* If ELM_DISPLAY is specified */
- {
- if (!strcmp(ev, "x11")) /* and it is X11 */
- {
- if (!have_display) /* if there is no $DISPLAY */
- {
- ERR("$ELM_DISPLAY is set to x11 but $DISPLAY is not set");
- init_x = EINA_FALSE;
- }
- else /* if there is */
- init_x = EINA_TRUE;
- }
- else /* not X11 */
- init_x = EINA_FALSE;
- }
- else /* ELM_DISPLAY not specified */
- {
- if (have_display) /* If there is a $DISPLAY */
- init_x = EINA_TRUE;
- else /* No $DISPLAY */
- init_x = EINA_FALSE;
- }
- if (init_x)
- {
- if (ecore_x_display_get())
- ecore_x_shutdown();
- }
-#endif
-#ifdef HAVE_ELEMENTARY_WL2
- Eina_Bool init_wl = EINA_FALSE;
- Eina_Bool have_wl_display = !!getenv("WAYLAND_DISPLAY");
-
- if (ev) /* If ELM_DISPLAY is specified */
- {
- if (!strcmp(ev, "wl")) /* and it is WL */
- {
- /* always try to connect to wl when it is enforced */
- init_wl = EINA_TRUE;
- }
- else /* not wl */
- init_wl = EINA_FALSE;
- }
- else /* ELM_DISPLAY not specified */
- {
- /* If there is a $WAYLAND_DISPLAY */
- if ((have_wl_display) && (!getenv("DISPLAY")))
- init_wl = EINA_TRUE;
- else /* No $WAYLAND_DISPLAY */
- init_wl = EINA_FALSE;
- }
- if (init_wl)
- {
- if (!managers) ecore_wl2_display_disconnect(_elm_wl_display);
- ecore_wl2_shutdown();
- }
-#endif
-}
-
-#ifdef HAVE_ELEMENTARY_X
-static void
-_set_selection_list(Sel_Manager_Selection *sel_list, Sel_Manager_Seat_Selection *seat_sel)
-{
- sel_list[EFL_UI_SELECTION_TYPE_PRIMARY].debug = "Primary";
- sel_list[EFL_UI_SELECTION_TYPE_PRIMARY].ecore_sel = ECORE_X_SELECTION_PRIMARY;
- sel_list[EFL_UI_SELECTION_TYPE_PRIMARY].set = ecore_x_selection_primary_set;
- sel_list[EFL_UI_SELECTION_TYPE_PRIMARY].clear = ecore_x_selection_primary_clear;
- sel_list[EFL_UI_SELECTION_TYPE_PRIMARY].request = ecore_x_selection_primary_request;
- sel_list[EFL_UI_SELECTION_TYPE_PRIMARY].seat_sel = seat_sel;
-
- sel_list[EFL_UI_SELECTION_TYPE_SECONDARY].debug = "Secondary";
- sel_list[EFL_UI_SELECTION_TYPE_SECONDARY].ecore_sel = ECORE_X_SELECTION_SECONDARY;
- sel_list[EFL_UI_SELECTION_TYPE_SECONDARY].set = ecore_x_selection_secondary_set;
- sel_list[EFL_UI_SELECTION_TYPE_SECONDARY].clear = ecore_x_selection_secondary_clear;
- sel_list[EFL_UI_SELECTION_TYPE_SECONDARY].request = ecore_x_selection_secondary_request;
- sel_list[EFL_UI_SELECTION_TYPE_SECONDARY].seat_sel = seat_sel;
-
- sel_list[EFL_UI_SELECTION_TYPE_DND].debug = "DnD";
- sel_list[EFL_UI_SELECTION_TYPE_DND].ecore_sel = ECORE_X_SELECTION_PRIMARY;
- sel_list[EFL_UI_SELECTION_TYPE_DND].request = ecore_x_selection_xdnd_request;
- sel_list[EFL_UI_SELECTION_TYPE_DND].seat_sel = seat_sel;
-
- sel_list[EFL_UI_SELECTION_TYPE_CLIPBOARD].debug = "Clipboard";
- sel_list[EFL_UI_SELECTION_TYPE_CLIPBOARD].ecore_sel = ECORE_X_SELECTION_CLIPBOARD;
- sel_list[EFL_UI_SELECTION_TYPE_CLIPBOARD].set = ecore_x_selection_clipboard_set;
- sel_list[EFL_UI_SELECTION_TYPE_CLIPBOARD].clear = ecore_x_selection_clipboard_clear;
- sel_list[EFL_UI_SELECTION_TYPE_CLIPBOARD].request = ecore_x_selection_clipboard_request;
- sel_list[EFL_UI_SELECTION_TYPE_CLIPBOARD].seat_sel = seat_sel;
-}
-#endif
-#ifdef HAVE_ELEMENTARY_WIN32
-static void
-_set_selection_list(Sel_Manager_Selection *sel_list, Sel_Manager_Seat_Selection *seat_sel)
-{
- sel_list[EFL_UI_SELECTION_TYPE_PRIMARY].debug = "Primary";
- sel_list[EFL_UI_SELECTION_TYPE_PRIMARY].ecore_sel = ECORE_WIN32_SELECTION_PRIMARY;
- sel_list[EFL_UI_SELECTION_TYPE_PRIMARY].set = ecore_win32_clipboard_set;
- sel_list[EFL_UI_SELECTION_TYPE_PRIMARY].clear = ecore_win32_clipboard_clear;
- sel_list[EFL_UI_SELECTION_TYPE_PRIMARY].get = ecore_win32_clipboard_get;
- sel_list[EFL_UI_SELECTION_TYPE_PRIMARY].seat_sel = seat_sel;
-
- sel_list[EFL_UI_SELECTION_TYPE_SECONDARY].debug = "Secondary";
- sel_list[EFL_UI_SELECTION_TYPE_SECONDARY].ecore_sel = ECORE_WIN32_SELECTION_OTHER;
- sel_list[EFL_UI_SELECTION_TYPE_SECONDARY].seat_sel = seat_sel;
-
- sel_list[EFL_UI_SELECTION_TYPE_DND].debug = "DnD";
- sel_list[EFL_UI_SELECTION_TYPE_DND].ecore_sel = ECORE_WIN32_SELECTION_OTHER;
- sel_list[EFL_UI_SELECTION_TYPE_DND].seat_sel = seat_sel;
-
- sel_list[EFL_UI_SELECTION_TYPE_CLIPBOARD].debug = "Clipboard";
- sel_list[EFL_UI_SELECTION_TYPE_CLIPBOARD].ecore_sel = ECORE_WIN32_SELECTION_CLIPBOARD;
- sel_list[EFL_UI_SELECTION_TYPE_CLIPBOARD].set = ecore_win32_clipboard_set;
- sel_list[EFL_UI_SELECTION_TYPE_CLIPBOARD].clear = ecore_win32_clipboard_clear;
- sel_list[EFL_UI_SELECTION_TYPE_CLIPBOARD].seat_sel = seat_sel;
-}
-#endif
-
-#include "efl_ui_selection_manager.eo.c"
diff --git a/src/lib/elementary/efl_ui_selection_manager.eo b/src/lib/elementary/efl_ui_selection_manager.eo
deleted file mode 100644
index e7df9cce77..0000000000
--- a/src/lib/elementary/efl_ui_selection_manager.eo
+++ /dev/null
@@ -1,139 +0,0 @@
-import efl_ui_dnd_types;
-
-class @beta Efl.Ui.Selection_Manager extends Efl.Object {
- methods {
- selection_set @beta {
- [[Set selection]]
- params {
- @in owner: Efl.Object; [[Seleciton owner]]
- @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 @optional;[[Specified seat for multiple seats case.]]
- }
- return: future<void>; [[Future for tracking when the selection is lost]]
- }
- selection_get @beta {
- [[Get selection]]
- params {
- @in request: const(Efl.Object); [[Seleciton owner]]
- @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 @optional;[[Specified seat for multiple seats case.]]
- }
- }
- selection_clear @beta {
- params {
- @in owner: Efl.Object; [[Seleciton owner]]
- @in type: Efl.Ui.Selection_Type; [[Selection type]]
- @in seat: uint @optional; [[Specified seat for multiple seats case.]]
- }
- }
- selection_has_owner @beta {
- [[Check if the request object has selection or not]]
- params {
- @in request: Efl.Object; [[Request object]]
- @in type: Efl.Ui.Selection_Type; [[Selection type]]
- @in seat: uint @optional; [[Specified seat for multiple seats case.]]
- }
- return: bool; [[EINA_TRUE if the request object has selection, otherwise, EINA_FALSE]]
- }
- drag_start @beta {
- [[This starts 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
- ]]
- params {
- @in drag_obj: Efl.Object; [[Drag object]]
- @in format: Efl.Ui.Selection_Format; [[Data format]]
- @in data: Eina.Slice; [[Data to transfer]]
- @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 @beta {
- [[This sets the action for the drag]]
- params {
- @in drag_obj: Efl.Object; [[Drag object]]
- @in action: Efl.Ui.Selection_Action; [[Drag action]]
- @in seat: uint; [[Specified seat for multiple seats case.]]
- }
- }
- drag_cancel @beta {
- [[This cancels the on-going drag]]
- params {
- @in drag_obj: Efl.Object; [[Drag object]]
- @in seat: uint; [[Specified seat for multiple seats case.]]
- }
- }
- container_drag_item_add @beta {
- [[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_UI_DND_EVENT_DRAG_POS
- - EFL_UI_DND_EVENT_DRAG_ACCEPT
- - EFL_UI_DND_EVENT_DRAG_DONE.]]
- params {
- @in cont: Efl.Object; [[Container object]]
- @in time_to_drag: double; [[Time since mouse down happens to drag starts]]
- @in anim_duration: double; [[animation duration]]
- @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]]
- @in seat: uint; [[Specified seat for multiple seats case]]
- }
- }
- container_drag_item_del @beta {
- [[Remove drag function of items in the container object.]]
- params {
- @in cont: Efl.Object; [[Container object]]
- @in seat: uint; [[Specified seat for multiple seats case]]
- }
- }
- drop_target_add @beta {
- [[Add a dropable target. There are four events emitted:
- - EFL_UI_DND_DROP_DRAG_ENTER
- - EFL_UI_DND_DROP_DRAG_LEAVE
- - EFL_UI_DND_DROP_DRAG_POS
- - EFL_UI_DND_DROP_DRAG_DROP.]]
- params {
- @in target_obj: Efl.Object; [[Drop target]]
- @in format: Efl.Ui.Selection_Format; [[Accepted data format]]
- @in seat: uint; [[Specified seat for multiple seats case.]]
- }
- return: bool; [[$true on success, $false otherwise]]
- }
- drop_target_del @beta {
- [[Remove a dropable target]]
- params {
- @in target_obj: Efl.Object; [[Drop target]]
- @in format: Efl.Ui.Selection_Format; [[Accepted data format]]
- @in seat: uint; [[Specified seat for multiple seats case.]]
- }
- }
- container_drop_item_add @beta {
- [[Add dropable target for a container in which items can drop to it]]
- params {
- @in cont: Efl.Object; [[Container object]]
- @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.]]
- }
- }
- container_drop_item_del @beta {
- [[Remove dropable target for the container]]
- params {
- @in cont: Efl.Object; [[Container object]]
- @in seat: uint; [[Specified seat for multiple seats case.]]
- }
- }
- }
- implements {
- Efl.Object.constructor;
- Efl.Object.destructor;
- }
-}
diff --git a/src/lib/elementary/efl_ui_selection_types.eot b/src/lib/elementary/efl_ui_selection_types.eot
deleted file mode 100644
index cbe5e0dc7b..0000000000
--- a/src/lib/elementary/efl_ui_selection_types.eot
+++ /dev/null
@@ -1,60 +0,0 @@
-enum @beta Efl.Ui.Selection_Type
-{
- [[Selection type]]
- primary, [[Primary text selection (highlighted or selected text)]]
- secondary, [[Used when primary selection is in use]]
- dnd, [[Drag and Drop]]
- clipboard [[Clipboard selection (ctrl+C)]]
-}
-
-enum @beta Efl.Ui.Selection_Format
-{
- [[Selection format]]
- targets = -1, [[For matching every possible atom]]
- none = 0x0, [[Content is from outside of EFL]]
- text = 0x01, [[Plain unformatted text: Used for things that don't want rich markup]]
- markup = 0x2, [[Edje textblock markup, including inline images]]
- image = 0x4, [[Images]]
- vcard = 0x08, [[Vcards]]
- html = 0x10 [[Raw HTML-like data (eg. webkit)]]
-}
-
-enum @beta Efl.Ui.Selection_Action
-{
- [[Defines the kind of action associated with the drop data]]
- unknown, [[Action type is unknown]]
- copy, [[Copy the data]]
- move, [[Move the data]]
- private, [[Private action type]]
- ask, [[Ask the user what to do]]
- list, [[List the data]]
- link, [[Link the data]]
- description [[Describe the data]]
-}
-
-struct @beta Efl.Ui.Selection_Data
-{
- [[Structure holding the info about selected data]]
- pos: Eina.Position2D; [[Coordinates of the drop (DND operations only)]]
- format: Efl.Ui.Selection_Format; [[Format of the selection]]
- content: Eina.Slice; [[Selection data]]
- action: Efl.Ui.Selection_Action; [[Action to perform with the data]]
- item: Efl.Object; [[Item under the drag position. It is only available for container]]
-}
-
-function @beta Efl.Ui.Selection_Data_Ready {
- [[Function pointer for getting selection]]
- params {
- @in obj: Efl.Object; [[Object which requested for the selection]]
- @in seldata: ptr(Efl.Ui.Selection_Data); [[Selection data]]
- }
-};
-
-struct @beta Efl.Ui.Selection_Changed
-{
- [[Selection-changed specific information.]] // TODO: This needs to be filled in.
- type: Efl.Ui.Selection_Type; [[Selection type]]
- seat: int; [[The seat on which the selection changed, or NULL for "default"]]
- display: void_ptr; [[The display connection object, NULL under X11]]
- exist: bool; [[EINA_TRUE if the selection has an owner]]
-}
diff --git a/src/lib/elementary/efl_ui_tags.c b/src/lib/elementary/efl_ui_tags.c
index 95c5ce59d7..5cc37badda 100644
--- a/src/lib/elementary/efl_ui_tags.c
+++ b/src/lib/elementary/efl_ui_tags.c
@@ -757,7 +757,7 @@ _view_init(Evas_Object *obj, Efl_Ui_Tags_Data *sd)
sd->entry = efl_add(EFL_UI_TEXTBOX_CLASS, sd->box,
efl_text_multiline_set(efl_added, EINA_FALSE),
efl_text_set(efl_added, ""),
- efl_ui_textbox_cnp_mode_set(efl_added, EFL_UI_SELECTION_FORMAT_MARKUP),
+ efl_ui_textbox_cnp_dnd_mode_set(efl_added, EFL_UI_TEXTBOX_CNP_CONTENT_MARKUP),
efl_input_text_input_panel_autoshow_set(efl_added, EINA_FALSE),
efl_text_interactive_editable_set(efl_added, EINA_TRUE),
efl_composite_attach(obj, efl_added));
diff --git a/src/lib/elementary/efl_ui_textbox.c b/src/lib/elementary/efl_ui_textbox.c
index a53c265d38..2831dca6d7 100644
--- a/src/lib/elementary/efl_ui_textbox.c
+++ b/src/lib/elementary/efl_ui_textbox.c
@@ -22,7 +22,6 @@
typedef struct _Efl_Ui_Textbox_Data Efl_Ui_Textbox_Data;
typedef struct _Efl_Ui_Text_Rectangle Efl_Ui_Text_Rectangle;
typedef struct _Anchor Anchor;
-typedef struct _Selection_Loss_Data Selection_Loss_Data;
/**
* Base widget smart data extended with entry instance data.
@@ -69,7 +68,7 @@ struct _Efl_Ui_Textbox_Data
const char *hover_style; /**< style of a hover object */
} anchor_hover;
- Efl_Ui_Selection_Format cnp_mode;
+ const char *cnp_mime_type;
Elm_Sel_Format drop_format;
struct {
@@ -81,11 +80,7 @@ struct _Efl_Ui_Textbox_Data
Eina_Size2D scroll;
Eina_Size2D layout;
} last;
- struct
- {
- Eina_Future *primary;
- Eina_Future *clipboard;
- } sel_future;
+ Efl_Ui_Textbox_Cnp_Content content;
Eina_Bool sel_handles_enabled : 1;
Eina_Bool start_handler_down : 1;
Eina_Bool start_handler_shown : 1;
@@ -147,12 +142,6 @@ struct _Efl_Ui_Text_Rectangle
Evas_Object *obj_bg, *obj_fg, *obj;
};
-struct _Selection_Loss_Data
-{
- Eo *obj;
- Efl_Ui_Selection_Type stype;
-};
-
#define MY_CLASS EFL_UI_TEXTBOX_CLASS
#define MY_CLASS_PFX efl_ui_textbox
#define MY_CLASS_NAME "Efl.Ui.Textbox"
@@ -208,7 +197,7 @@ static void _anchors_free(Efl_Ui_Textbox_Data *sd);
static void _selection_defer(Eo *obj, Efl_Ui_Textbox_Data *sd);
static Eina_Position2D _decoration_calc_offset(Efl_Ui_Textbox_Data *sd);
static void _update_text_theme(Eo *obj, Efl_Ui_Textbox_Data *sd);
-static void _efl_ui_textbox_selection_paste_type(Eo *obj, Efl_Ui_Selection_Type type);
+static void _efl_ui_textbox_selection_paste_type(Eo *obj, Efl_Ui_Textbox_Data *sd, Efl_Ui_Cnp_Buffer type);
static Eina_Bool _key_action_copy(Evas_Object *obj, const char *params);
static Eina_Bool _key_action_paste(Evas_Object *obj, const char *params);
@@ -407,16 +396,19 @@ _update_selection_handler(Eo *obj)
}
}
-static void
-_selection_data_cb(void *data EINA_UNUSED, Eo *obj,
- Efl_Ui_Selection_Data *sel_data)
+static Eina_Value
+_selection_data_cb(Efl_Ui_Textbox *obj, void *data EINA_UNUSED, const Eina_Value value)
{
+ Eina_Content *content;
+ Eina_Slice slice;
Efl_Text_Cursor *cur, *start, *end;
Efl_Text_Change_Info info = { NULL, 0, 0, 0, 0 };
- char *buf = eina_slice_strdup(sel_data->content);
- size_t len = sel_data->content.len;
+ if (eina_value_type_get(&value) != EINA_VALUE_TYPE_CONTENT)
+ return EINA_VALUE_EMPTY;
+ content = eina_value_to_content(&value);
+ slice = eina_content_data_get(content);
efl_text_interactive_selection_cursors_get(obj, &start, &end);
if (!efl_text_cursor_equal(start, end))
{
@@ -426,83 +418,130 @@ _selection_data_cb(void *data EINA_UNUSED, Eo *obj,
cur = efl_text_interactive_main_cursor_get(obj);
info.type = EFL_TEXT_CHANGE_TYPE_INSERT;
info.position = efl_text_cursor_position_get(cur);
- info.length = len;
- info.content = buf;
- if (sel_data->format == EFL_UI_SELECTION_FORMAT_MARKUP)
+ info.length = slice.len;
+ info.content = slice.mem;
+ if (eina_streq(eina_content_type_get(content), "application/x-elementary-markup"))
+ {
+ efl_text_cursor_markup_insert(cur, slice.mem);
+ }
+ else if (!strncmp(eina_content_type_get(content), "image/", strlen("image/")))
{
- efl_text_cursor_markup_insert(cur, buf);
+ Eina_Strbuf *result = eina_strbuf_new();
+ eina_strbuf_append_printf(result, "<item absize=240x180 href=");
+ eina_strbuf_append_slice(result, slice);
+ eina_strbuf_append_printf(result, "></item>");
+ efl_text_cursor_markup_insert(cur, eina_strbuf_string_get(result));
+ eina_strbuf_free(result);
}
else // TEXT
{
- efl_text_cursor_text_insert(cur, buf);
+ efl_text_cursor_text_insert(cur, slice.mem);
}
efl_event_callback_call(obj, EFL_TEXT_INTERACTIVE_EVENT_CHANGED_USER, &info);
- free(buf);
+
+ return EINA_VALUE_EMPTY;
}
-static void
-_dnd_enter_cb(void *data EINA_UNUSED,
- Evas_Object *obj)
+static Eina_Array*
+_figure_out_types(Eo *obj EINA_UNUSED, Efl_Ui_Textbox_Data *sd)
+{
+ Eina_Array *types = eina_array_new(10);
+
+ if (sd->content & EFL_UI_TEXTBOX_CNP_CONTENT_MARKUP)
+ eina_array_push(types, "application/x-elementary-markup");
+ if (sd->content & EFL_UI_TEXTBOX_CNP_CONTENT_IMAGE)
+ {
+ eina_array_push(types, "image/png");
+ eina_array_push(types, "image/jpeg");
+ eina_array_push(types, "image/x-ms-bmp");
+ eina_array_push(types, "image/gif");
+ eina_array_push(types, "image/tiff");
+ eina_array_push(types, "image/svg+xml");
+ eina_array_push(types, "image/x-xpixmap");
+ eina_array_push(types, "image/x-tga");
+ eina_array_push(types, "image/x-portable-pixmap");
+ }
+ if (sd->content & EFL_UI_TEXTBOX_CNP_CONTENT_TEXT)
+ eina_array_push(types, "text/plain;charset=utf-8");
+ return types;
+}
+
+static Eina_Bool
+_accepting_drops(Eo *obj, Efl_Ui_Textbox_Data *sd, Eina_Accessor *mime_types)
{
- efl_ui_focus_util_focus(obj);
+ int i = 0;
+ const char *mime_type;
+
+ if (efl_ui_widget_disabled_get(obj)) return EINA_FALSE;
+
+ EINA_ACCESSOR_FOREACH(mime_types, i, mime_type)
+ {
+ if (sd->content & EFL_UI_TEXTBOX_CNP_CONTENT_TEXT &&
+ eina_streq(mime_type, "text/plain;charset=utf-8"))
+ return EINA_TRUE;
+
+ if (sd->content & EFL_UI_TEXTBOX_CNP_CONTENT_IMAGE &&
+ strncmp(mime_type, "image/", strlen("image/")))
+ return EINA_TRUE;
+
+ if (sd->content & EFL_UI_TEXTBOX_CNP_CONTENT_MARKUP &&
+ eina_streq(mime_type, "application/x-elementary-markup"))
+ return EINA_TRUE;
+ }
+ return EINA_FALSE;
}
static void
-_dnd_leave_cb(void *data EINA_UNUSED,
- Evas_Object *obj EINA_UNUSED)
+_dnd_enter_cb(void *data EINA_UNUSED,
+ const Efl_Event *ev)
{
+ Efl_Ui_Dnd_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_Dnd_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_Dnd_Event *drop = ev->info;
+ Eina_Future *future;
+ Eina_Array *types;
- rv = edje_object_part_text_cursor_coord_set
- (sd->entry_edje, "efl.text", EDJE_CURSOR_MAIN, drop->x, drop->y);
+ EFL_UI_TEXT_DATA_GET(ev->object, sd);
+ types = _figure_out_types(ev->object, sd);
- if (!rv) WRN("Warning: Failed to position cursor: paste anyway");
+ if (!_accepting_drops(ev->object, sd, drop->available_types))
+ return;
- //rv = _selection_data_cb(NULL, obj, drop);
+ future = efl_ui_dnd_drop_data_get(ev->object, 0, eina_array_iterator_new(types));
+ eina_array_free(types);
- return rv;
-}
-
-static Elm_Sel_Format
-_get_drop_format(Evas_Object *obj)
-{
- if (efl_text_interactive_editable_get(obj) && (efl_text_multiline_get(obj)) && (!efl_text_password_get(obj)) && (!efl_ui_widget_disabled_get(obj)))
- return EFL_UI_SELECTION_FORMAT_MARKUP | EFL_UI_SELECTION_FORMAT_IMAGE;
- return EFL_UI_SELECTION_FORMAT_MARKUP;
+ efl_future_then(ev->object, future, _selection_data_cb);
}
/* we can't reuse layout's here, because it's on entry_edje only */
@@ -516,12 +555,6 @@ _efl_ui_textbox_efl_ui_widget_disabled_set(Eo *obj, Efl_Ui_Textbox_Data *sd, Ein
efl_ui_widget_disabled_set(efl_super(obj, MY_CLASS), disabled);
- elm_drop_target_del(obj, sd->drop_format,
- _dnd_enter_cb, NULL,
- _dnd_leave_cb, NULL,
- _dnd_pos_cb, NULL,
- _dnd_drop_cb, NULL);
-
emission = efl_ui_widget_disabled_get(obj) ? "efl,state,disabled" : "efl,state,enabled";
efl_layout_signal_emit(sd->entry_edje, emission, "efl");
if (sd->scroll)
@@ -529,15 +562,6 @@ _efl_ui_textbox_efl_ui_widget_disabled_set(Eo *obj, Efl_Ui_Textbox_Data *sd, Ein
efl_ui_scrollable_scroll_freeze_set(obj, efl_ui_widget_disabled_get(obj));
}
- if (!efl_ui_widget_disabled_get(obj))
- {
- sd->drop_format = _get_drop_format(obj);
- elm_drop_target_add(obj, sd->drop_format,
- _dnd_enter_cb, NULL,
- _dnd_leave_cb, NULL,
- _dnd_pos_cb, NULL,
- _dnd_drop_cb, NULL);
- }
_update_text_theme(obj, sd);
}
@@ -804,83 +828,36 @@ _popup_position(Evas_Object *obj)
efl_gfx_entity_geometry_set(sd->popup, EINA_RECT(r.x + cx, r.y + cy, m.w, m.h));
}
-static Eina_Value
-_selection_lost_cb(void *data, const Eina_Value value)
+static void
+_selection_lost_cb(void *data EINA_UNUSED, const Efl_Event *ev)
{
- Selection_Loss_Data *sdata = data;
- EFL_UI_TEXT_DATA_GET(sdata->obj, sd);
+ Efl_Ui_Cnp_Buffer *buffer = 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 (*buffer == EFL_UI_CNP_BUFFER_SELECTION)
{
- 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), "text/plain");
- ldata = calloc(1, sizeof(Selection_Loss_Data));
- if (!ldata) goto end;
+ efl_ui_selection_set(obj, buffer, content, 0);
- ldata->obj = obj;
- eina_future_then_easy(f, _selection_lost_cb, NULL, NULL, EINA_VALUE_TYPE_UINT, ldata);
-
- //if (seltype == EFL_UI_SELECTION_TYPE_CLIPBOARD)
- // eina_stringshare_replace(&sd->cut_sel, sel);
-
-end:
free(sel);
}
@@ -956,7 +933,7 @@ _menu_call(Evas_Object *obj)
{
Eina_Bool ownersel;
- ownersel = elm_selection_selection_has_owner(obj);
+ ownersel = elm_cnp_clipboard_selection_has_owner(obj);
/* prevent stupid blank hoversel */
if (efl_text_interactive_have_selection_get(obj) && efl_text_password_get(obj)) return;
if (_elm_config->desktop_entry && (!efl_text_interactive_have_selection_get(obj)) && ((!efl_text_interactive_editable_get(obj)) || (!ownersel)))
@@ -1133,7 +1110,7 @@ _mouse_down_cb(void *data, const Efl_Event *event)
if (ev->button == 2)
{
- _efl_ui_textbox_selection_paste_type(data, EFL_UI_SELECTION_TYPE_PRIMARY);
+ _efl_ui_textbox_selection_paste_type(data, sd, EFL_UI_CNP_BUFFER_SELECTION);
}
/* If right button is pressed and context menu disabled is true,
@@ -1654,10 +1631,18 @@ _efl_ui_textbox_efl_object_constructor(Eo *obj, Efl_Ui_Textbox_Data *sd)
{
Eo *text_obj;
+ sd->content = EFL_UI_TEXTBOX_CNP_CONTENT_MARKUP;
+
ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd, NULL);
if (!elm_widget_theme_klass_get(obj))
elm_widget_theme_klass_set(obj, "text");
+
+ efl_event_callback_add(obj, EFL_UI_SELECTION_EVENT_WM_SELECTION_CHANGED, _selection_lost_cb, NULL);
+ efl_event_callback_add(obj, EFL_UI_DND_EVENT_DROP_ENTER, _dnd_enter_cb, NULL);
+ efl_event_callback_add(obj, EFL_UI_DND_EVENT_DROP_POS, _dnd_pos_cb, NULL);
+ efl_event_callback_add(obj, EFL_UI_DND_EVENT_DROP_DROP, _dnd_drop_cb, NULL);
+
obj = efl_constructor(efl_super(obj, MY_CLASS));
efl_event_callback_add(obj, EFL_INPUT_EVENT_LONGPRESSED, _long_press_cb, obj);
@@ -1674,11 +1659,9 @@ _efl_ui_textbox_efl_object_constructor(Eo *obj, Efl_Ui_Textbox_Data *sd)
efl_composite_attach(obj, text_obj);
sd->entry_edje = wd->resize_obj;
- sd->cnp_mode = EFL_UI_SELECTION_FORMAT_TEXT;
sd->context_menu_enabled = EINA_TRUE;
efl_text_interactive_editable_set(obj, EINA_TRUE);
efl_text_interactive_selection_allowed_set(obj, EINA_TRUE);
- sd->drop_format = EFL_UI_SELECTION_FORMAT_MARKUP | EFL_UI_SELECTION_FORMAT_IMAGE;
sd->last.scroll = EINA_SIZE2D(0, 0);
sd->sel_handles_enabled = EINA_FALSE;
@@ -1691,12 +1674,6 @@ _efl_ui_textbox_efl_object_finalize(Eo *obj,
{
obj = efl_finalize(efl_super(obj, MY_CLASS));
- elm_drop_target_add(obj, sd->drop_format,
- _dnd_enter_cb, NULL,
- _dnd_leave_cb, NULL,
- _dnd_pos_cb, NULL,
- _dnd_drop_cb, NULL);
-
efl_access_object_role_set(obj, EFL_ACCESS_ROLE_ENTRY);
_update_guide_text(obj, sd);
@@ -1805,11 +1782,6 @@ _efl_ui_textbox_efl_text_format_password_set(Eo *obj, Efl_Ui_Textbox_Data *sd, E
efl_text_replacement_char_set(obj, ENTRY_PASSWORD_MASK_CHARACTER_UTF8);
efl_text_password_set(sd->text_obj, password);
- elm_drop_target_del(obj, sd->drop_format,
- _dnd_enter_cb, NULL,
- _dnd_leave_cb, NULL,
- _dnd_pos_cb, NULL,
- _dnd_drop_cb, NULL);
if (password)
{
efl_text_multiline_set(obj, EINA_FALSE);
@@ -1819,12 +1791,6 @@ _efl_ui_textbox_efl_text_format_password_set(Eo *obj, Efl_Ui_Textbox_Data *sd, E
else
{
efl_text_multiline_set(obj, EINA_TRUE);
- sd->drop_format = _get_drop_format(obj);
- elm_drop_target_add(obj, sd->drop_format,
- _dnd_enter_cb, NULL,
- _dnd_leave_cb, NULL,
- _dnd_pos_cb, NULL,
- _dnd_drop_cb, NULL);
efl_input_text_input_content_type_set(obj, ((efl_input_text_input_content_type_get(obj) | EFL_INPUT_TEXT_CONTENT_TYPE_AUTO_COMPLETE) & ~EFL_INPUT_TEXT_CONTENT_TYPE_SENSITIVE_DATA));
efl_access_object_role_set(obj, EFL_ACCESS_ROLE_ENTRY);
}
@@ -1891,19 +1857,8 @@ _efl_ui_textbox_efl_text_interactive_editable_set(Eo *obj, Efl_Ui_Textbox_Data *
efl_ui_widget_theme_apply(obj);
efl_ui_widget_focus_allow_set(obj, editable);
- elm_drop_target_del(obj, sd->drop_format,
- _dnd_enter_cb, NULL,
- _dnd_leave_cb, NULL,
- _dnd_pos_cb, NULL,
- _dnd_drop_cb, NULL);
if (editable)
{
- sd->drop_format = _get_drop_format(obj);
- elm_drop_target_add(obj, sd->drop_format,
- _dnd_enter_cb, NULL,
- _dnd_leave_cb, NULL,
- _dnd_pos_cb, NULL,
- _dnd_drop_cb, NULL);
if (sd->cursor)
{
efl_gfx_entity_visible_set(sd->cursor, EINA_TRUE);
@@ -1961,7 +1916,7 @@ _efl_ui_textbox_selection_cut(Eo *obj, Efl_Ui_Textbox_Data *sd)
/*In password mode, cut will remove text only*/
if (!efl_text_password_get(obj))
- _selection_store(EFL_UI_SELECTION_TYPE_CLIPBOARD, obj);
+ _selection_store(EFL_UI_CNP_BUFFER_COPY_AND_PASTE, obj);
efl_text_interactive_selection_cursors_get(obj, &start, &end);
start_pos = efl_text_cursor_position_get(start);
@@ -1993,25 +1948,27 @@ _efl_ui_textbox_selection_copy(Eo *obj, Efl_Ui_Textbox_Data *sd)
efl_layout_signal_emit(sd->entry_edje, "efl,state,select,off", "efl");
efl_ui_widget_scroll_hold_pop(obj);
}
- _selection_store(EFL_UI_SELECTION_TYPE_CLIPBOARD, obj);
+ _selection_store(EFL_UI_CNP_BUFFER_COPY_AND_PASTE, obj);
efl_event_callback_call(obj, EFL_UI_TEXTBOX_EVENT_SELECTION_COPY, NULL);
}
-
static void
-_efl_ui_textbox_selection_paste_type(Eo *obj, Efl_Ui_Selection_Type type)
+_efl_ui_textbox_selection_paste_type(Eo *obj, Efl_Ui_Textbox_Data *sd, Efl_Ui_Cnp_Buffer type)
{
- Efl_Ui_Selection_Format formats = EFL_UI_SELECTION_FORMAT_TEXT | EFL_UI_SELECTION_FORMAT_MARKUP;
+ Eina_Future *future;
+ Eina_Array *types = _figure_out_types(obj, sd);
- efl_ui_selection_get(obj, type, formats,
- NULL, _selection_data_cb, NULL, 1);
+ future = efl_ui_selection_get(obj, type, 0, eina_array_iterator_new(types));
+
+ efl_future_then(obj, future, _selection_data_cb);
efl_event_callback_call(obj, EFL_UI_TEXTBOX_EVENT_SELECTION_PASTE, NULL);
+ eina_array_free(types);
}
EOLIAN static void
-_efl_ui_textbox_selection_paste(Eo *obj, Efl_Ui_Textbox_Data *sd EINA_UNUSED)
+_efl_ui_textbox_selection_paste(Eo *obj, Efl_Ui_Textbox_Data *sd)
{
- _efl_ui_textbox_selection_paste_type(obj, EFL_UI_SELECTION_TYPE_CLIPBOARD);
+ _efl_ui_textbox_selection_paste_type(obj, sd, EFL_UI_CNP_BUFFER_COPY_AND_PASTE);
}
EOLIAN static void
@@ -2028,44 +1985,15 @@ _efl_ui_textbox_context_menu_enabled_get(const Eo *obj EINA_UNUSED, Efl_Ui_Textb
}
EOLIAN static void
-_efl_ui_textbox_cnp_mode_set(Eo *obj, Efl_Ui_Textbox_Data *sd, Efl_Ui_Selection_Format cnp_mode)
+_efl_ui_textbox_cnp_dnd_mode_set(Eo *obj EINA_UNUSED, Efl_Ui_Textbox_Data *sd, Efl_Ui_Textbox_Cnp_Content content)
{
- Elm_Sel_Format dnd_format = EFL_UI_SELECTION_FORMAT_MARKUP;
-
- if (cnp_mode != EFL_UI_SELECTION_FORMAT_TARGETS)
- {
- if (cnp_mode & EFL_UI_SELECTION_FORMAT_VCARD)
- ERR("VCARD format not supported for copy & paste!");
- else if (cnp_mode & EFL_UI_SELECTION_FORMAT_HTML)
- ERR("HTML format not supported for copy & paste!");
- cnp_mode &= ~EFL_UI_SELECTION_FORMAT_VCARD;
- cnp_mode &= ~EFL_UI_SELECTION_FORMAT_HTML;
- }
-
- if (sd->cnp_mode == cnp_mode) return;
- sd->cnp_mode = cnp_mode;
- if (sd->cnp_mode == EFL_UI_SELECTION_FORMAT_TEXT)
- dnd_format = EFL_UI_SELECTION_FORMAT_TEXT;
- else if (cnp_mode == EFL_UI_SELECTION_FORMAT_IMAGE)
- dnd_format |= EFL_UI_SELECTION_FORMAT_IMAGE;
-
- elm_drop_target_del(obj, sd->drop_format,
- _dnd_enter_cb, NULL,
- _dnd_leave_cb, NULL,
- _dnd_pos_cb, NULL,
- _dnd_drop_cb, NULL);
- sd->drop_format = dnd_format;
- elm_drop_target_add(obj, sd->drop_format,
- _dnd_enter_cb, NULL,
- _dnd_leave_cb, NULL,
- _dnd_pos_cb, NULL,
- _dnd_drop_cb, NULL);
+ sd->content = content;
}
-EOLIAN static Efl_Ui_Selection_Format
-_efl_ui_textbox_cnp_mode_get(const Eo *obj EINA_UNUSED, Efl_Ui_Textbox_Data *sd)
+EOLIAN static Efl_Ui_Textbox_Cnp_Content
+_efl_ui_textbox_cnp_dnd_mode_get(const Eo *obj EINA_UNUSED, Efl_Ui_Textbox_Data *sd)
{
- return sd->cnp_mode;
+ return sd->content;
}
EOLIAN static void
@@ -3279,7 +3207,7 @@ _efl_ui_textbox_selection_changed_cb(void *data, const Efl_Event *event EINA_UNU
Eo *obj = data;
EFL_UI_TEXT_DATA_GET(obj, sd);
_edje_signal_emit(sd, "selection,changed", "efl.text");
- _selection_store(EFL_UI_SELECTION_TYPE_PRIMARY, obj);
+ _selection_store(EFL_UI_CNP_BUFFER_SELECTION, obj);
_selection_defer(obj, sd);
}
diff --git a/src/lib/elementary/efl_ui_textbox.eo b/src/lib/elementary/efl_ui_textbox.eo
index 2b7ccf9472..ff0898b6fc 100644
--- a/src/lib/elementary/efl_ui_textbox.eo
+++ b/src/lib/elementary/efl_ui_textbox.eo
@@ -1,3 +1,10 @@
+enum Efl.Ui.Textbox_Cnp_Content {
+ Nothing = 0, [[You can paste or drop nothing]]
+ Text = 1, [[You can paste normal Text]]
+ Markup = 3, [[You can paste Markup (Normal text is also just markup)]]
+ Image = 4, [[You can paste Images]]
+}
+
class @beta Efl.Ui.Textbox extends Efl.Ui.Layout_Base implements Efl.Input.Clickable,
Efl.Access.Text, Efl.Access.Editable.Text
composites
@@ -31,8 +38,7 @@ class @beta Efl.Ui.Textbox extends Efl.Ui.Layout_Base implements Efl.Input.Click
enabled: bool; [[$true to enable the contextual menu.]]
}
}
- @property cnp_mode @beta {
- /* FIXME: Efl.Ui.Selection_Format does not allow markup without images! */
+ @property cnp_dnd_mode @beta {
[[Control pasting of text and images for the widget.
Normally the entry allows both text and images to be pasted.
@@ -44,7 +50,7 @@ class @beta Efl.Ui.Textbox extends Efl.Ui.Layout_Base implements Efl.Input.Click
get {
}
values {
- format: Efl.Ui.Selection_Format; [[Format for copy & paste.]]
+ allowed_formats : Efl.Ui.Textbox_Cnp_Content; [[Format for cnp]]
}
}
@property selection_handles_enabled {
diff --git a/src/lib/elementary/efl_ui_win.c b/src/lib/elementary/efl_ui_win.c
index 2430b50638..7235cd1bea 100644
--- a/src/lib/elementary/efl_ui_win.c
+++ b/src/lib/elementary/efl_ui_win.c
@@ -213,6 +213,9 @@ struct _Efl_Ui_Win_Data
int ignore_frame_resize;
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;
@@ -382,6 +385,8 @@ static void _elm_win_frame_style_update(Efl_Ui_Win_Data *sd, Eina_Bool force_emi
static inline void _elm_win_need_frame_adjust(Efl_Ui_Win_Data *sd, const char *engine);
static void _elm_win_resize_objects_eval(Evas_Object *obj, Eina_Bool force_resize);
static void _elm_win_frame_obj_update(Efl_Ui_Win_Data *sd, Eina_Bool force);
+static void _ee_backbone_init(Efl_Ui_Win *obj, Efl_Ui_Win_Data *pd);
+static void _ee_backbone_shutdown(Efl_Ui_Win *obj, Efl_Ui_Win_Data *pd);
static inline Efl_Ui_Win_Type
_elm_win_type_to_efl_ui_win_type(Elm_Win_Type type)
@@ -5933,6 +5938,7 @@ _efl_ui_win_efl_object_finalize(Eo *obj, Efl_Ui_Win_Data *sd)
efl_file_mmap_get(efl_super(efl_part(obj, "background"), EFL_UI_WIN_PART_CLASS)))
efl_file_load(efl_part(obj, "background"));
}
+ _ee_backbone_init(obj, sd);
return obj;
}
@@ -5968,6 +5974,8 @@ _efl_ui_win_efl_object_destructor(Eo *obj, Efl_Ui_Win_Data *pd EINA_UNUSED)
if (pd->finalize_future)
eina_future_cancel(pd->finalize_future);
+ _ee_backbone_shutdown(obj, pd);
+
efl_destructor(efl_super(obj, MY_CLASS));
efl_unref(pd->provider);
@@ -5984,6 +5992,7 @@ _efl_ui_win_efl_object_constructor(Eo *obj, Efl_Ui_Win_Data *pd)
pd->provider = efl_add_ref(EFL_UI_FOCUS_PARENT_PROVIDER_STANDARD_CLASS, NULL);
pd->profile.available = eina_array_new(4);
pd->max_w = pd->max_h = -1;
+ pd->planned_changes = eina_array_new(10);
// For bindings: if no parent, allow simple unref
if (!efl_parent_get(obj))
@@ -9187,6 +9196,211 @@ elm_win_teamwork_uri_open(Efl_Ui_Win *obj EINA_UNUSED, const char *uri EINA_UNUS
ERR("Calling deprecrated function '%s'", __FUNCTION__);
}
+/* 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_Dnd_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_LEAVE, &ev);
+ }
+ else if (!target->currently_inside && inside)
+ {
+ target->currently_inside = EINA_TRUE;
+ efl_event_callback_call(target->obj, EFL_UI_DND_EVENT_DROP_ENTER, &ev);
+ }
+ else if (target->currently_inside && inside)
+ {
+ efl_event_callback_call(target->obj, EFL_UI_DND_EVENT_DROP_POS, &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_Dnd_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_ENTER, &ev);
+ }
+ else if (!move_inside && !target->currently_inside)
+ {
+ target->currently_inside = EINA_FALSE;
+ efl_event_callback_call(target->obj, EFL_UI_DND_EVENT_DROP_LEAVE, &ev);
+ }
+ }
+}
+
+static void
+_drop_cb(Ecore_Evas *ee, unsigned int seat EINA_UNUSED, Eina_Position2D p, const char *action)
+{
+ 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_Dnd_Drop_Event ev = {{p, seat, ecore_evas_drop_available_types_get(ee, seat)}, action};
+
+ if (inside)
+ {
+ EINA_SAFETY_ON_FALSE_RETURN(target->currently_inside);
+ efl_event_callback_call(target->obj, EFL_UI_DND_EVENT_DROP_DROP, &ev);
+ }
+ }
+}
+
+static void
+_ee_backbone_init(Efl_Ui_Win *obj EINA_UNUSED, Efl_Ui_Win_Data *pd)
+{
+ pd->selection_changed = eina_array_new(1);
+ pd->drop_target = eina_inarray_new(sizeof(Ui_Dnd_Target), 1);
+
+ ecore_evas_callback_selection_changed_set(pd->ee, _selection_changed_cb);
+ ecore_evas_callback_drop_drop_set(pd->ee, _drop_cb);
+ ecore_evas_callback_drop_motion_set(pd->ee, _motion_cb);
+ ecore_evas_callback_drop_state_changed_set(pd->ee, _enter_state_change_cb);
+}
+
+static void
+_ee_backbone_shutdown(Efl_Ui_Win *obj EINA_UNUSED, Efl_Ui_Win_Data *pd)
+{
+ ecore_evas_callback_selection_changed_set(pd->ee, NULL);
+ ecore_evas_callback_drop_drop_set(pd->ee, NULL);
+ ecore_evas_callback_drop_motion_set(pd->ee, NULL);
+ ecore_evas_callback_drop_state_changed_set(pd->ee, NULL);
+
+ eina_array_free(pd->selection_changed);
+ pd->selection_changed = NULL;
+ eina_inarray_free(pd->drop_target);
+ pd->drop_target = NULL;
+
+}
+
+static Eina_Bool
+_remove(void *data, void *gdata)
+{
+ if (data == gdata)
+ return EINA_FALSE;
+ return EINA_TRUE;
+}
+
+void
+_drop_event_register(Eo *obj)
+{
+ Ui_Dnd_Target target = {obj, EINA_FALSE};
+ Efl_Ui_Win_Data *pd = efl_data_scope_safe_get(efl_provider_find(obj, MY_CLASS), MY_CLASS);
+ EINA_SAFETY_ON_NULL_RETURN(pd);
+
+ eina_inarray_push(pd->drop_target, &target);
+}
+
+void
+_drop_event_unregister(Eo *obj)
+{
+ int idx = -1;
+ Efl_Ui_Win_Data *pd = efl_data_scope_safe_get(efl_provider_find(obj, MY_CLASS), MY_CLASS);
+
+ for (unsigned int i = 0; i < eina_inarray_count(pd->drop_target); ++i)
+ {
+ Ui_Dnd_Target *target = eina_inarray_nth(pd->drop_target, i);
+ if (target->obj == obj)
+ {
+ //FIXME emit drop
+ target->currently_inside = EINA_FALSE;
+ idx = i;
+ }
+ }
+ if (idx != -1)
+ eina_inarray_remove_at(pd->drop_target, idx);
+}
+
+void
+_selection_changed_event_register(Eo *obj)
+{
+ Efl_Ui_Win_Data *pd = efl_data_scope_safe_get(efl_provider_find(obj, MY_CLASS), MY_CLASS);
+
+ eina_array_push(pd->selection_changed, obj);
+}
+void
+_selection_changed_event_unregister(Eo *obj)
+{
+ Efl_Ui_Win_Data *pd = efl_data_scope_safe_get(efl_provider_find(obj, MY_CLASS), MY_CLASS);
+
+ eina_array_remove(pd->selection_changed, _remove, obj);
+}
/* Internal EO APIs and hidden overrides */
ELM_WIDGET_KEY_DOWN_DEFAULT_IMPLEMENT(efl_ui_win, Efl_Ui_Win_Data)
diff --git a/src/lib/elementary/elm_cnp.c b/src/lib/elementary/elm_cnp.c
new file mode 100644
index 0000000000..b4c1c930de
--- /dev/null
+++ b/src/lib/elementary/elm_cnp.c
@@ -0,0 +1,235 @@
+#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, eina_stringshare_add("text/plain;charset=utf-8"));
+ if (format & ELM_SEL_FORMAT_MARKUP)
+ eina_array_push(ret, eina_stringshare_add("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, eina_stringshare_add("text/vcard"));
+ if (format & ELM_SEL_FORMAT_HTML)
+ eina_array_push(ret, eina_stringshare_add("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;
+}
+
+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, 0, _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, 0, _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, 0, 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
+_seleciton_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)
+ 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, _seleciton_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, _seleciton_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, 0, _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;
+}
diff --git a/src/lib/elementary/elm_cnp.h b/src/lib/elementary/elm_cnp.h
index 5feda3acc0..06346e40a5 100644
--- a/src/lib/elementary/elm_cnp.h
+++ b/src/lib/elementary/elm_cnp.h
@@ -43,8 +43,6 @@
* @{
*/
-# include <efl_ui_selection_types.eot.h>
-
/**
* Event notifying that the selection has changed
* @see Elm_Cnp_Event_Selection_Changed
diff --git a/src/lib/elementary/elm_dnd.c b/src/lib/elementary/elm_dnd.c
new file mode 100644
index 0000000000..b128da0126
--- /dev/null
+++ b/src/lib/elementary/elm_dnd.c
@@ -0,0 +1,806 @@
+#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 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, "privat")) 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_Dnd_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_Dnd_Drop_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, 0, 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_ENTER, _enter_cb},
+ {EFL_UI_DND_EVENT_DROP_LEAVE, _leave_cb},
+ {EFL_UI_DND_EVENT_DROP_POS, _pos_cb},
+ {EFL_UI_DND_EVENT_DROP_DROP, _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, 0);
+ 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, 0);
+
+ 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;
+}
diff --git a/src/lib/elementary/elm_entry.c b/src/lib/elementary/elm_entry.c
index ab1f11544b..e3a81dea76 100644
--- a/src/lib/elementary/elm_entry.c
+++ b/src/lib/elementary/elm_entry.c
@@ -708,7 +708,7 @@ _selection_data_cb(void *data EINA_UNUSED,
char *entry_tag;
int len;
static const char *tag_string =
- "<item absize=240x180 href=file://%s></item>";
+ "<item absize=240x180 href=%s></item>";
len = strlen(tag_string) + strlen(buf);
entry_tag = alloca(len + 1);
@@ -1628,7 +1628,7 @@ _selection_store(Elm_Sel_Type seltype,
if ((!sel) || (!sel[0])) return; /* avoid deleting our own selection */
elm_cnp_selection_set
- (obj, seltype, ELM_SEL_FORMAT_MARKUP, sel, strlen(sel));
+ (obj, seltype, ELM_SEL_FORMAT_MARKUP, sel, strlen(sel) + 1);
elm_cnp_selection_loss_callback_set(obj, seltype, _selection_clear, obj);
if (seltype == ELM_SEL_TYPE_CLIPBOARD)
eina_stringshare_replace(&sd->cut_sel, sel);
@@ -1731,7 +1731,7 @@ _menu_call(Evas_Object *obj)
const char *context_menu_orientation;
Eina_Bool ownersel;
- ownersel = elm_selection_selection_has_owner(obj);
+ ownersel = elm_cnp_clipboard_selection_has_owner(obj);
if (!sd->items)
{
/* prevent stupid blank hoversel */
diff --git a/src/lib/elementary/elm_main.c b/src/lib/elementary/elm_main.c
index d6c2b2a82f..ddda1337b9 100644
--- a/src/lib/elementary/elm_main.c
+++ b/src/lib/elementary/elm_main.c
@@ -910,7 +910,6 @@ elm_quicklaunch_sub_shutdown(void)
_elm_module_shutdown();
if (_elm_prefs_initted)
_elm_prefs_shutdown();
- _efl_ui_dnd_shutdown();
elm_color_class_shutdown();
}
diff --git a/src/lib/elementary/elm_priv.h b/src/lib/elementary/elm_priv.h
index 89878716f3..7a3da94cb7 100644
--- a/src/lib/elementary/elm_priv.h
+++ b/src/lib/elementary/elm_priv.h
@@ -165,7 +165,6 @@
# 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;
@@ -668,9 +667,6 @@ void _elm_prefs_data_init(void);
void _elm_prefs_data_shutdown(void);
/* init functions for dnd and cnp */
-Eo* _efl_ui_selection_manager_get(Eo *obj);
-void _efl_ui_dnd_shutdown(void);
-
int _elm_ews_wm_init(void);
void _elm_ews_wm_shutdown(void);
void _elm_ews_wm_rescale(Elm_Theme *th,
@@ -1060,4 +1056,10 @@ typedef struct
Efl_Ui_Shared_Win_Data* efl_ui_win_shared_data_get(Efl_Ui_Win *win);
+void _selection_changed_event_register(Eo *obj);
+void _selection_changed_event_unregister(Eo *obj);
+void _drop_event_register(Eo *obj);
+void _drop_event_unregister(Eo *obj);
+void _register_selection_changed(Efl_Ui_Selection *selection);
+
#endif
diff --git a/src/lib/elementary/meson.build b/src/lib/elementary/meson.build
index 0cb3fc7db9..6dea02ed9f 100644
--- a/src/lib/elementary/meson.build
+++ b/src/lib/elementary/meson.build
@@ -142,7 +142,6 @@ pub_eo_files = [
'elm_code_widget.eo',
'efl_ui_selection.eo',
'efl_ui_dnd.eo',
- 'efl_ui_dnd_container.eo',
'efl_ui_focus_manager_window_root.eo',
'efl_ui_spotlight_container.eo',
'efl_ui_spotlight_manager.eo',
@@ -210,8 +209,6 @@ endforeach
pub_eo_types_files = [
'elm_general.eot',
'efl_ui.eot',
- 'efl_ui_selection_types.eot',
- 'efl_ui_dnd_types.eot'
]
foreach eo_file : pub_eo_types_files
@@ -235,7 +232,6 @@ priv_eo_files = [
'efl_ui_focus_parent_provider.eo',
'efl_ui_focus_parent_provider_standard.eo',
'efl_ui_state_model.eo',
- 'efl_ui_selection_manager.eo',
'efl_datetime_manager.eo',
'efl_ui_size_model.eo',
'efl_ui_homogeneous_model.eo',
@@ -785,6 +781,8 @@ elementary_src = [
'elm_icon.c',
'efl_ui_image.c',
'elm_index.c',
+ 'elm_cnp.c',
+ 'elm_dnd.c',
'efl_access_object.c',
'efl_access_action.c',
'efl_access_component.c',
@@ -907,7 +905,6 @@ elementary_src = [
'efl_ui_scroller.c',
'efl_ui_scroll_manager.c',
'efl_ui_pan.c',
- 'efl_ui_selection_manager.c',
'efl_ui_selection_manager_private.h',
'efl_ui_selection.c',
'efl_datetime_manager.c',
diff --git a/src/lib/eo/eina_types.eot b/src/lib/eo/eina_types.eot
index 04d728a8d3..5d1e9cf0f8 100644
--- a/src/lib/eo/eina_types.eot
+++ b/src/lib/eo/eina_types.eot
@@ -60,6 +60,8 @@ struct @extern Eina.Matrix3 {
zz: double; [[ZZ value.]]
}
+struct @extern Eina.Content;
+
struct @extern Eina.Matrix4 {
[[A bidimensional array of floating point values with 4 rows and 4 columns.
diff --git a/src/lib/evas/canvas/evas_main.c b/src/lib/evas/canvas/evas_main.c
index 95d0f36bd0..9aa455553d 100644
--- a/src/lib/evas/canvas/evas_main.c
+++ b/src/lib/evas/canvas/evas_main.c
@@ -120,6 +120,21 @@ _efl_gfx_image_load_error_to_evas_load_error(Eina_Error err)
return EVAS_LOAD_ERROR_GENERIC;
}
+static Eina_Content*
+_markup_to_utf8(Eina_Content *from, const char *to_type)
+{
+ Eina_Slice slice = eina_content_data_get(from);
+ char *utf8 = evas_textblock_text_markup_to_utf8(NULL, slice.mem);
+ return eina_content_new((Eina_Slice)EINA_SLICE_STR_FULL(utf8), to_type);
+}
+
+static Eina_Content*
+_utf8_to_markup(Eina_Content *from, const char *to_type)
+{
+ Eina_Slice slice = eina_content_data_get(from);
+ char *markup = evas_textblock_text_utf8_to_markup(NULL, slice.mem);
+ return eina_content_new((Eina_Slice)EINA_SLICE_STR_FULL(markup), to_type);
+}
EAPI int
evas_init(void)
@@ -179,6 +194,9 @@ evas_init(void)
_efl_gfx_image_load_error_init();
+ 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;
shutdown_filter:
diff --git a/src/modules/ecore_evas/engines/x/ecore_evas_x.c b/src/modules/ecore_evas/engines/x/ecore_evas_x.c
index 2dbd2ec60a..d82e16ac2f 100644
--- a/src/modules/ecore_evas/engines/x/ecore_evas_x.c
+++ b/src/modules/ecore_evas/engines/x/ecore_evas_x.c
@@ -4201,6 +4201,15 @@ _ecore_evas_x_selection_init(void)
"text/x-vcard",
"text/uri-list",
"application/x-elementary-markup",
+ "image/png",
+ "image/jpeg",
+ "image/x-ms-bmp",
+ "image/gif",
+ "image/tiff",
+ "image/svg+xml",
+ "image/x-xpixmap",
+ "image/x-tga",
+ "image/x-portable-pixmap",
"ATOM",
"TARGETS",
NULL
diff --git a/src/tests/elementary/efl_ui_test_text.c b/src/tests/elementary/efl_ui_test_text.c
index b7886544f1..0944afa0ef 100644
--- a/src/tests/elementary/efl_ui_test_text.c
+++ b/src/tests/elementary/efl_ui_test_text.c
@@ -44,6 +44,12 @@ EFL_START_TEST(text_cnp)
}
EFL_END_TEST
+static void
+_stop_event_soon(void *data EINA_UNUSED, const Efl_Event *ev)
+{
+ efl_event_callback_stop(ev->object);
+}
+
EFL_START_TEST(text_all_select_all_unselect)
{
Eo *txt;
@@ -57,7 +63,7 @@ EFL_START_TEST(text_all_select_all_unselect)
efl_event_callback_add(efl_added, EFL_TEXT_INTERACTIVE_EVENT_SELECTION_CHANGED,
increment_int_changed, &i_selection)
);
-
+ efl_event_callback_priority_add(txt, EFL_UI_SELECTION_EVENT_WM_SELECTION_CHANGED, EFL_CALLBACK_PRIORITY_BEFORE, _stop_event_soon, NULL);
efl_text_set(txt, "Hello");
efl_text_interactive_all_select(txt);
Efl_Text_Cursor *c1=NULL, *c2 =NULL;
@@ -122,6 +128,7 @@ EFL_START_TEST(text_selection)
Eo *win = win_add();
txt = efl_add(EFL_UI_TEXTBOX_CLASS, win);
+ efl_event_callback_priority_add(txt, EFL_UI_SELECTION_EVENT_WM_SELECTION_CHANGED, EFL_CALLBACK_PRIORITY_BEFORE, _stop_event_soon, NULL);
efl_gfx_entity_size_set(txt, EINA_SIZE2D(300, 300));
efl_text_set(txt, "Hello");
get_me_to_those_events(txt);
@@ -160,7 +167,7 @@ EFL_START_TEST(text_user_change)
txt = efl_add(EFL_UI_TEXTBOX_CLASS, win,
efl_event_callback_add(efl_added, EFL_TEXT_INTERACTIVE_EVENT_CHANGED_USER, user_changed, &info)
);
-
+ efl_event_callback_priority_add(txt, EFL_UI_SELECTION_EVENT_WM_SELECTION_CHANGED, EFL_CALLBACK_PRIORITY_BEFORE, _stop_event_soon, NULL);
efl_text_set(txt, "Hello");
efl_gfx_entity_size_set(txt, EINA_SIZE2D(300, 300));
efl_text_interactive_all_select(txt);
@@ -177,6 +184,7 @@ EFL_START_TEST(text_scroll_mode)
Eo *txt, *win, *cur;
win = win_add();
txt = efl_add(EFL_UI_TEXTBOX_CLASS, win);
+ efl_event_callback_priority_add(txt, EFL_UI_SELECTION_EVENT_WM_SELECTION_CHANGED, EFL_CALLBACK_PRIORITY_BEFORE, _stop_event_soon, NULL);
cur = efl_text_interactive_main_cursor_get(txt);
efl_text_set(txt, "Hello");
/*scroll mode is false by default*/
@@ -199,6 +207,7 @@ EFL_START_TEST(text_change_event)
Eo *win = win_add();
txt = efl_add(EFL_UI_TEXTBOX_CLASS, win);
+ efl_event_callback_priority_add(txt, EFL_UI_SELECTION_EVENT_WM_SELECTION_CHANGED, EFL_CALLBACK_PRIORITY_BEFORE, _stop_event_soon, NULL);
efl_gfx_entity_size_set(txt, EINA_SIZE2D(300, 300));
efl_text_set(txt, "Hello");
int i_changed = 0;
@@ -223,6 +232,7 @@ EFL_START_TEST(text_keys_handler)
Eo *win = win_add();
txt = efl_add(EFL_UI_TEXTBOX_CLASS, win);
+ efl_event_callback_priority_add(txt, EFL_UI_SELECTION_EVENT_WM_SELECTION_CHANGED, EFL_CALLBACK_PRIORITY_BEFORE, _stop_event_soon, NULL);
efl_gfx_entity_size_set(txt, EINA_SIZE2D(300, 300));
efl_text_set(txt, "Hello");