devilhorns pushed a commit to branch master.

commit daa37ad05ec7a64de399d4d5003fe1ad02984ce1
Author: Chris Michael <[email protected]>
Date:   Tue May 28 11:49:28 2013 +0100

    Add code to make Wayland Drag-n-Drop work in elementary client apps now.
    
    NB: Handle with care ... code is still a bit experimental
    
    Signed-off-by: Chris Michael <[email protected]>
---
 src/lib/elm_cnp.c | 684 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 680 insertions(+), 4 deletions(-)

diff --git a/src/lib/elm_cnp.c b/src/lib/elm_cnp.c
index 4b9eabf..45dc4f7 100644
--- a/src/lib/elm_cnp.c
+++ b/src/lib/elm_cnp.c
@@ -2100,15 +2100,38 @@ static Wl_Cnp_Selection wl_cnp_selection = {0, 0, NULL, 
NULL};
 static void _wl_sel_obj_del2(void *data, Evas *e __UNUSED__, Evas_Object *obj, 
void *event_info __UNUSED__);
 static Eina_Bool _wl_elm_cnp_selection_set(Evas_Object *obj __UNUSED__, 
Elm_Sel_Type selection, Elm_Sel_Format format __UNUSED__, const void *selbuf, 
size_t buflen);
 static Eina_Bool _wl_elm_cnp_selection_get(Evas_Object *obj, Elm_Sel_Type 
selection, Elm_Sel_Format format __UNUSED__, Elm_Drop_Cb datacb __UNUSED__, 
void *udata __UNUSED__);
+static Eina_Bool _wl_elm_cnp_selection_clear(Evas_Object *obj, Elm_Sel_Type 
selection);
+
 static Eina_Bool _wl_selection_send(void *udata, int type __UNUSED__, void 
*event);
 static Eina_Bool _wl_selection_receive(void *udata, int type __UNUSED__, void 
*event);
 
+static Eina_Bool _wl_elm_dnd_init(void);
 static Eina_Bool _wl_elm_drop_target_add(Evas_Object *obj, Elm_Sel_Format 
format, Elm_Drag_State entercb, void *enterdata, Elm_Drag_State leavecb, void 
*leavedata, Elm_Drag_Pos poscb, void *posdata, Elm_Drop_Cb dropcb, void 
*cbdata);
 static Eina_Bool _wl_elm_drop_target_del(Evas_Object *obj);
 
 static Eina_Bool _wl_elm_drag_action_set(Evas_Object *obj, Elm_Xdnd_Action 
action);
 static Eina_Bool _wl_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);
 
+static void _wl_drag_source_del(void *data EINA_UNUSED, Evas *evas 
EINA_UNUSED, Evas_Object *obj, void *event EINA_UNUSED);
+
+static Eina_Bool _wl_dnd_enter(void *data EINA_UNUSED, int type EINA_UNUSED, 
void *event);
+static Eina_Bool _wl_dnd_leave(void *data EINA_UNUSED, int type EINA_UNUSED, 
void *event);
+static Eina_Bool _wl_dnd_position(void *data EINA_UNUSED, int type 
EINA_UNUSED, void *event);
+static Eina_Bool _wl_dnd_drop(void *data EINA_UNUSED, int type EINA_UNUSED, 
void *event);
+/* static Eina_Bool _wl_dnd_offer(void *data EINA_UNUSED, int type 
EINA_UNUSED, void *event); */
+
+static Eina_Bool _wl_dnd_send(void *data, int type EINA_UNUSED, void *event);
+static Eina_Bool _wl_dnd_receive(void *data, int type EINA_UNUSED, void 
*event);
+static Eina_Bool _wl_dnd_end(void *data EINA_UNUSED, int type EINA_UNUSED, 
void *event EINA_UNUSED);
+static void _wl_dropable_data_handle(Wl_Cnp_Selection *sel, char *data);
+
+static Dropable *_wl_dropable_find(unsigned int win);
+static Dropable *_wl_dropable_find_geom(unsigned int win, Evas_Coord x, 
Evas_Coord y);
+static void _wl_dropable_handle(Dropable *drop, Evas_Coord x, Evas_Coord y, 
Eina_Bool have_obj);
+static void _wl_dropable_all_set(unsigned int win, Evas_Coord x, Evas_Coord y, 
Eina_Bool set);
+static Eina_Bool _wl_drops_accept(const char *type);
+static unsigned int _wl_elm_widget_window_get(Evas_Object *obj);
+
 static void
 _wl_sel_obj_del2(void *data, Evas *e __UNUSED__, Evas_Object *obj, void 
*event_info __UNUSED__)
 {
@@ -2127,7 +2150,7 @@ _wl_elm_cnp_selection_set(Evas_Object *obj __UNUSED__, 
Elm_Sel_Type selection, E
    if (ELM_SEL_TYPE_CLIPBOARD == selection) 
      {
         types[0] = "text/plain;charset=utf-8";
-        ecore_wl_dnd_set_selection(ecore_wl_dnd_get(), types);
+        ecore_wl_dnd_selection_set(ecore_wl_input_get(), types);
 
         if (wl_cnp_selection.selbuf) free(wl_cnp_selection.selbuf);
         wl_cnp_selection.selbuf = strdup((char*)selbuf);
@@ -2152,7 +2175,23 @@ _wl_elm_cnp_selection_get(Evas_Object *obj, Elm_Sel_Type 
selection, Elm_Sel_Form
         wl_cnp_selection.requestwidget = obj;
         evas_object_event_callback_add(wl_cnp_selection.requestwidget, 
EVAS_CALLBACK_DEL,
                                        _wl_sel_obj_del2, &wl_cnp_selection);
-        ecore_wl_dnd_get_selection(ecore_wl_dnd_get(), 
"text/plain;charset=utf-8");
+        ecore_wl_dnd_selection_get(ecore_wl_input_get(), 
+                                   "text/plain;charset=utf-8");
+     }
+   return EINA_TRUE;
+}
+
+static Eina_Bool 
+_wl_elm_cnp_selection_clear(Evas_Object *obj EINA_UNUSED, Elm_Sel_Type 
selection)
+{
+   _wl_elm_cnp_init();
+
+   if (ELM_SEL_TYPE_CLIPBOARD == selection) 
+     {
+        wl_cnp_selection.requestwidget = NULL;
+        if (wl_cnp_selection.selbuf) free(wl_cnp_selection.selbuf);
+        wl_cnp_selection.buflen = 0;
+        ecore_wl_dnd_selection_clear(ecore_wl_input_get());
      }
    return EINA_TRUE;
 }
@@ -2227,10 +2266,34 @@ _wl_elm_cnp_init(void)
 }
 
 static Eina_Bool 
+_wl_elm_dnd_init(void)
+{
+   static int _init_count = 0;
+
+   if (_init_count > 0) return EINA_TRUE;
+   _init_count++;
+
+   text_uri = eina_stringshare_add("text/uri-list");
+
+   ecore_event_handler_add(ECORE_WL_EVENT_DATA_SOURCE_SEND, 
+                           _wl_dnd_send, &wl_cnp_selection);
+   ecore_event_handler_add(ECORE_WL_EVENT_SELECTION_DATA_READY, 
+                           _wl_dnd_receive, &wl_cnp_selection);
+
+   ecore_event_handler_add(ECORE_WL_EVENT_DND_END, 
+                           _wl_dnd_end, &wl_cnp_selection);
+
+   return EINA_TRUE;
+}
+
+static Eina_Bool 
 _wl_elm_drop_target_add(Evas_Object *obj, Elm_Sel_Format format, 
Elm_Drag_State entercb, void *enterdata, Elm_Drag_State leavecb, void 
*leavedata, Elm_Drag_Pos poscb, void *posdata, Elm_Drop_Cb dropcb, void *cbdata)
 {
    Dropable *drop;
    Eina_List *l;
+   Eina_Bool first = EINA_FALSE;
+
+   first = (!drops) ? EINA_TRUE : EINA_FALSE;
 
    EINA_LIST_FOREACH(drops, l, drop)
      {
@@ -2267,6 +2330,22 @@ _wl_elm_drop_target_add(Evas_Object *obj, Elm_Sel_Format 
format, Elm_Drag_State
                                   (Evas_Object_Event_Cb)elm_drop_target_del,
                                   obj);
 
+   if (first)
+     {
+        handler_enter = 
+          ecore_event_handler_add(ECORE_WL_EVENT_DND_ENTER, 
+                                  _wl_dnd_enter, NULL);
+        handler_leave = 
+          ecore_event_handler_add(ECORE_WL_EVENT_DND_LEAVE, 
+                                  _wl_dnd_leave, NULL);
+        handler_pos = 
+          ecore_event_handler_add(ECORE_WL_EVENT_DND_POSITION, 
+                                  _wl_dnd_position, NULL);
+        handler_drop = 
+          ecore_event_handler_add(ECORE_WL_EVENT_DND_DROP, 
+                                  _wl_dnd_drop, NULL);
+     }
+
    return EINA_TRUE;
 }
 
@@ -2288,6 +2367,30 @@ _wl_elm_drop_target_del(Evas_Object *obj)
           }
      }
 
+   if (!drops)
+     {
+        if (handler_enter)
+          {
+             ecore_event_handler_del(handler_enter);
+             handler_enter = NULL;
+          }
+        if (handler_leave)
+          {
+             ecore_event_handler_del(handler_leave);
+             handler_leave = NULL;
+          }
+        if (handler_pos)
+          {
+             ecore_event_handler_del(handler_pos);
+             handler_pos = NULL;
+          }
+        if (handler_drop)
+          {
+             ecore_event_handler_del(handler_drop);
+             handler_drop = NULL;
+          }
+     }
+
    return EINA_TRUE;
 }
 
@@ -2302,15 +2405,584 @@ _wl_elm_drag_action_set(Evas_Object *obj, 
Elm_Xdnd_Action action)
 }
 
 static Eina_Bool
-_wl_elm_drag_start(Evas_Object *obj, Elm_Sel_Format format, const char *data,
+_wl_elm_drag_start(Evas_Object *obj, Elm_Sel_Format format EINA_UNUSED, 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)
 {
+   Ecore_Evas *ee;
+   Evas_Object *icon = NULL;
+   int x, y, x2 = 0, y2 = 0, x3, y3, w, h;
+   const char *types[1] = { 0, };
+
+   _wl_elm_dnd_init();
+
+   /* if we already have a drag, get out */
+   if (dragwin) return EINA_FALSE;
+
+   types[0] = "text/uri-list";
+   ecore_wl_dnd_drag_types_set(ecore_wl_input_get(), types);
+
+   /* set the drag data used when a drop occurs */
+   if (wl_cnp_selection.selbuf) free(wl_cnp_selection.selbuf);
+   wl_cnp_selection.selbuf = strdup((char*)data);
+   wl_cnp_selection.buflen = strlen(wl_cnp_selection.selbuf);
+
+   /* setup callback to notify if this object gets deleted */
+   evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL, 
+                                  _wl_drag_source_del, obj);
+
+   dragwidget = obj;
+   dragaction = action;
+   dragposcb = dragpos;
+   dragposdata = dragdata;
+   dragacceptcb = acceptcb;
+   dragacceptdata = acceptdata;
+   dragdonecb = dragdone;
+   dragdonedata = donecbdata;
+
+   dragwin = elm_win_add(NULL, "Elm-Drag", ELM_WIN_DND);
+   elm_win_alpha_set(dragwin, EINA_TRUE);
+   elm_win_borderless_set(dragwin, EINA_TRUE);
+   elm_win_override_set(dragwin, EINA_TRUE);
+
+   ecore_wl_window_type_set(elm_win_wl_window_get(dragwin), 
+                            ECORE_WL_WINDOW_TYPE_DND);
+
+   if (createicon)
+     {
+        Evas_Coord xoff = 0, yoff = 0;
+
+        icon = createicon(createdata, dragwin, &xoff, &yoff);
+        if (icon)
+          {
+             x2 = xoff;
+             y2 = yoff;
+             evas_object_geometry_get(icon, NULL, NULL, &w, &h);
+          }
+     }
+   else
+     {
+        icon = elm_icon_add(dragwin);
+        evas_object_size_hint_weight_set(icon, EVAS_HINT_EXPAND, 
+                                         EVAS_HINT_EXPAND);
+        evas_object_size_hint_align_set(icon, EVAS_HINT_FILL, EVAS_HINT_FILL);
+     }
+
+   elm_win_resize_object_add(dragwin, icon);
+   evas_object_show(icon);
+
+   /* Position subwindow appropriately */
+   ee = ecore_evas_ecore_evas_get(evas_object_evas_get(obj));
+   ecore_evas_geometry_get(ee, &x, &y, NULL, NULL);
+   x += x2;
+   y += y2;
+   dragwin_x_start = dragwin_x_end = x;
+   dragwin_y_start = dragwin_y_end = y;
+
+   evas_object_move(dragwin, x, y);
+   evas_object_resize(dragwin, w, h);
+   evas_object_show(dragwin);
+
+   evas_pointer_canvas_xy_get(evas_object_evas_get(obj), &x3, &y3);
+   _dragx = x3 - x2;
+   _dragy = y3 - y2;
+
+   ecore_wl_dnd_drag_start(ecore_wl_input_get(),
+                           elm_win_wl_window_get(obj),
+                           elm_win_wl_window_get(dragwin), 
+                           x3, y3, w, h);
+
    return EINA_TRUE;
 }
+
+static void 
+_wl_drag_source_del(void *data EINA_UNUSED, Evas *evas EINA_UNUSED, 
Evas_Object *obj, void *event EINA_UNUSED)
+{
+   if (dragwidget == obj)
+     dragwidget = NULL;
+}
+
+static Eina_Bool 
+_wl_dnd_enter(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
+{
+   Ecore_Wl_Event_Dnd_Enter *ev;
+   Dropable *drop;
+   int i = 0;
+
+   ev = event;
+
+   if ((drop = _wl_dropable_find(ev->win)))
+     _wl_dropable_all_set(ev->win, 0, 0, EINA_FALSE);
+
+   if ((!ev->num_types) || (!ev->types)) return ECORE_CALLBACK_PASS_ON;
+
+   savedtypes.ntypes = ev->num_types;
+   if (savedtypes.types) free(savedtypes.types);
+   savedtypes.types = malloc(sizeof(char *) * ev->num_types);
+   if (!savedtypes.types) return EINA_FALSE;
+
+   for (i = 0; i < ev->num_types; i++)
+     {
+        savedtypes.types[i] = eina_stringshare_add(ev->types[i]);
+        if (savedtypes.types[i] == text_uri)
+          {
+             savedtypes.textreq = 1;
+             if (savedtypes.imgfile) free(savedtypes.imgfile);
+             savedtypes.imgfile = NULL;
+          }
+     }
+
+   doaccept = EINA_FALSE;
+   for (i = 0; i < ev->num_types; i++)
+     {
+        doaccept = _wl_drops_accept(ev->types[i]);
+        if (doaccept)
+          wl_data_offer_accept(ev->offer, ev->serial, ev->types[i]);
+        else
+          wl_data_offer_accept(ev->offer, ev->serial, NULL);
+     }
+
+   return ECORE_CALLBACK_PASS_ON;
+}
+
+static Eina_Bool 
+_wl_dnd_leave(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
+{
+   Ecore_Wl_Event_Dnd_Leave *ev;
+   Dropable *drop;
+
+   ev = event;
+
+   if ((drop = _wl_dropable_find(ev->win)))
+     {
+        _wl_dropable_handle(drop, 0, 0, EINA_FALSE);
+        _wl_dropable_all_set(ev->win, 0, 0, EINA_FALSE);
+     }
+
+   return ECORE_CALLBACK_PASS_ON;
+}
+
+static Eina_Bool 
+_wl_dnd_position(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
+{
+   Ecore_Wl_Event_Dnd_Position *ev;
+   Dropable *drop, *dropable_old;
+   Eina_Bool will_accept = EINA_FALSE;
+
+   ev = event;
+
+   dragwin_x_end = ev->position.x - _dragx;
+   dragwin_y_end = ev->position.y - _dragy;
+
+   dropable_old = drop = _wl_dropable_find(ev->win);
+
+   if (drop)
+     {
+        Ecore_Evas *ee;
+        Evas_Coord ex = 0, ey = 0;
+        Evas_Coord x = 0, y = 0;
+
+        x = ev->position.x;
+        y = ev->position.y;
+        ee = ecore_evas_ecore_evas_get(evas_object_evas_get(drop->obj));
+        ecore_evas_geometry_get(ee, &ex, &ey, NULL, NULL);
+        x -= ex;
+        y -= ey;
+
+        if ((drop = _wl_dropable_find_geom(ev->win, x, y)))
+          {
+             Evas_Coord ox = 0, oy = 0;
+             int i = 0;
+
+             evas_object_geometry_get(drop->obj, &ox, &oy, NULL, NULL);
+
+             _wl_dropable_handle(drop, x - ox, y - oy, EINA_TRUE);
+
+             for (i = 0; i < savedtypes.ntypes; i++)
+               {
+                  switch (drop->types)
+                    {
+                     case ELM_SEL_FORMAT_TARGETS:
+                     case ELM_SEL_FORMAT_IMAGE:
+                       if ((!strncmp(savedtypes.types[i], "text/uri", 8)) || 
+                           (!strncmp(savedtypes.types[i], "image/", 6)))
+                         {
+                            wl_cnp_selection.requestwidget = drop->obj;
+                            will_accept = EINA_TRUE;
+                         }
+                       break;
+                     default:
+                       break;
+                    }
+
+                  if (will_accept) break;
+               }
+          }
+        else
+          _wl_dropable_handle(dropable_old, 0, 0, EINA_FALSE);
+
+        _wl_dropable_all_set(ev->win, x, y, EINA_TRUE);
+     }
+
+   doaccept = will_accept;
+
+   if (dragacceptcb)
+     dragacceptcb(dragacceptdata, wl_cnp_selection.requestwidget, will_accept);
+
+   return ECORE_CALLBACK_PASS_ON;
+}
+
+static Eina_Bool 
+_wl_dnd_drop(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
+{
+   Ecore_Wl_Event_Dnd_Drop *ev;
+   Dropable *drop;
+   Ecore_Evas *ee;
+   Evas_Coord ex = 0, ey = 0;
+   int i = 0;
+
+   ev = event;
+
+   if (!(drop = _wl_dropable_find(ev->win))) 
+     return ECORE_CALLBACK_PASS_ON;
+
+   savedtypes.x = ev->position.x;
+   savedtypes.y = ev->position.y;
+   ee = ecore_evas_ecore_evas_get(evas_object_evas_get(drop->obj));
+   ecore_evas_geometry_get(ee, &ex, &ey, NULL, NULL);
+   savedtypes.x -= ex;
+   savedtypes.y -= ey;
+
+   if (!(drop = _wl_dropable_find_geom(ev->win, savedtypes.x, savedtypes.y)))
+     return ECORE_CALLBACK_PASS_ON;
+
+   for (i = 0; i < savedtypes.ntypes; i++)
+     {
+        if ((savedtypes.types[i] == text_uri) && 
+            ((drop->types & ELM_SEL_FORMAT_MARKUP) || 
+                (drop->types & ELM_SEL_FORMAT_IMAGE)))
+          {
+             wl_cnp_selection.requestwidget = drop->obj;
+             evas_object_event_callback_add(wl_cnp_selection.requestwidget, 
+                                            EVAS_CALLBACK_DEL,
+                                            _wl_sel_obj_del2, 
+                                            &wl_cnp_selection);
+             ecore_wl_dnd_drag_get(ecore_wl_input_get(), text_uri);
+             break;
+          }
+     }
+
+   return ECORE_CALLBACK_PASS_ON;
+}
+
+static Eina_Bool 
+_wl_dnd_send(void *data, int type EINA_UNUSED, void *event)
+{
+   char *buf;
+   int ret, len_remained;
+   int len_written = 0;
+   Wl_Cnp_Selection *sel;
+   Ecore_Wl_Event_Data_Source_Send *ev;
+
+   ev = event;
+   sel = data;
+
+   len_remained = sel->buflen;
+   buf = sel->selbuf;
+
+   while (len_written < sel->buflen)
+     {
+        ret = write(ev->fd, buf, len_remained);
+        if (ret == -1) break;
+        buf += ret;
+        len_written += ret;
+        len_remained -= ret;
+     }
+
+   close(ev->fd);
+   return ECORE_CALLBACK_PASS_ON;
+}
+
+static Eina_Bool 
+_wl_dnd_receive(void *data, int type EINA_UNUSED, void *event)
+{
+   Wl_Cnp_Selection *sel;
+   Ecore_Wl_Event_Selection_Data_Ready *ev;
+
+   ev = event;
+   sel = data;
+
+   if (sel->requestwidget)
+     {
+        if (!ev->done)
+          _wl_dropable_data_handle(sel, ev->data);
+        else
+          {
+             evas_object_event_callback_del_full(sel->requestwidget, 
+                                                 EVAS_CALLBACK_DEL,
+                                                 _wl_sel_obj_del2, sel);
+             sel->requestwidget = NULL;
+          }
+     }
+
+   return ECORE_CALLBACK_PASS_ON;
+}
+
+static Eina_Bool 
+_wl_dnd_end(void *data EINA_UNUSED, int type EINA_UNUSED, void *event 
EINA_UNUSED)
+{
+   /* Ecore_Wl_Event_Dnd_End *ev; */
+
+   /* ev = event; */
+
+   if (dragdonecb) dragdonecb(dragdonedata, dragwidget);
+
+   if (dragwin)
+     {
+        if (!doaccept)
+          {
+             /* Commit animation when drag cancelled */
+             /* Record final position of dragwin, then do animation */
+             ecore_animator_timeline_add(0.3, _drag_cancel_animate, dragwin);
+          }
+        else
+          {
+             /* No animation drop was committed */
+             evas_object_del(dragwin);
+          }
+
+        dragwin = NULL;  /* if not freed here, free in end of anim */
+     }
+
+   dragdonecb = NULL;
+   dragacceptcb = NULL;
+   dragposcb = NULL;
+   dragwidget = NULL;
+   doaccept = EINA_FALSE;
+
+   ecore_wl_input_ungrab(ecore_wl_input_get());
+
+   return ECORE_CALLBACK_PASS_ON;
+}
+
+static void 
+_wl_dropable_data_handle(Wl_Cnp_Selection *sel, char *data)
+{
+   Dropable *drop;
+   unsigned int win = 0;
+   char *p, *s = NULL, *entrytag;
+   Elm_Selection_Data sdata;
+   static const char *tagstring = 
+     "<item absize=240x180 href=file://%s></item>";
+
+   win = _wl_elm_widget_window_get(sel->requestwidget);
+   drop = _wl_dropable_find_geom(win, savedtypes.x, savedtypes.y);
+
+   p = data;
+   if ((!strncmp(p, "file://", 7)) || (p[0] == '/'))
+     {
+        int len = 0;
+
+        len = sel->buflen;
+        if (!strncmp(p, "file://", 7))
+          {
+             p += 7;
+             len -= 7;
+          }
+        if (!(s = malloc(len + 1))) return;
+        memcpy(s, p, len);
+        s[len] = 0;
+     }
+
+   if (savedtypes.textreq)
+     {
+        savedtypes.textreq = 0;
+        savedtypes.imgfile = s;
+     }
+
+   sdata.x = savedtypes.x;
+   sdata.y = savedtypes.y;
+
+   if ((drop->types & ELM_SEL_FORMAT_MARKUP) && 
+       (drop->types & ELM_SEL_FORMAT_IMAGE))
+     {
+        int l = 0;
+
+        sdata.format = ELM_SEL_FORMAT_MARKUP;
+        l = strlen(tagstring) + strlen(savedtypes.imgfile);
+        entrytag = alloca(l + 1);
+        snprintf(entrytag, l + 1, tagstring, savedtypes.imgfile);
+        sdata.data = entrytag;
+        drop->dropcb(drop->cbdata, drop->obj, &sdata);
+        ecore_wl_dnd_drag_end(ecore_wl_input_get());
+        if (savedtypes.imgfile) free(savedtypes.imgfile);
+        savedtypes.imgfile = NULL;
+     }
+   else if (drop->types & ELM_SEL_FORMAT_IMAGE)
+     {
+        sdata.format = ELM_SEL_FORMAT_IMAGE;
+        sdata.data = (char *)savedtypes.imgfile;
+        drop->dropcb(drop->cbdata, drop->obj, &sdata);
+        ecore_wl_dnd_drag_end(ecore_wl_input_get());
+        if (savedtypes.imgfile) free(savedtypes.imgfile);
+        savedtypes.imgfile = NULL;
+     }
+}
+
+static Dropable *
+_wl_dropable_find(unsigned int win)
+{
+   Eina_List *l;
+   Dropable *dropable;
+   
+   if (!drops) return NULL;
+   EINA_LIST_FOREACH(drops, l, dropable)
+     if (_wl_elm_widget_window_get(dropable->obj) == win) 
+       return dropable;
+   return NULL;
+}
+
+static Dropable *
+_wl_dropable_find_geom(unsigned int win, Evas_Coord x, Evas_Coord y)
+{
+   Eina_List *l;
+   Dropable *drop;
+
+   EINA_LIST_FOREACH(drops, l, drop)
+     {
+        if (_wl_elm_widget_window_get(drop->obj) == win)
+          {
+             Evas_Coord ox, oy, ow, oh;
+
+             evas_object_geometry_get(drop->obj, &ox, &oy, &ow, &oh);
+             if ((x >= ox) && (y >= oy) && (x < (ox + ow)) && (y < (oy + oh)))
+               return drop;
+          }
+     }
+
+   return NULL;
+}
+
+static void 
+_wl_dropable_handle(Dropable *drop, Evas_Coord x, Evas_Coord y, Eina_Bool 
have_obj)
+{
+   Dropable *last = NULL;
+
+   if (drop->last.in)
+     last = _wl_dropable_find_geom(_wl_elm_widget_window_get(drop->obj), 
+                                   drop->last.x, drop->last.y);
+
+   if ((have_obj) && (last == drop))
+     {
+        if (drop->poscb) 
+          drop->poscb(drop->posdata, drop->obj, x, y, dragaction);
+     }
+   else if ((have_obj) && (!last))
+     {
+        if (drop->entercb)
+          drop->entercb(drop->enterdata, drop->obj);
+        if (drop->poscb)
+          drop->poscb(drop->posdata, drop->obj, x, y, dragaction);
+     }
+   else if ((!have_obj) && (last))
+     {
+        if (drop->leavecb)
+          drop->leavecb(drop->leavedata, drop->obj);
+     }
+   else if (have_obj)
+     {
+        if (drop->entercb)
+          drop->entercb(drop->enterdata, drop->obj);
+        if (last)
+          {
+             drop = last;
+             if (drop->leavecb)
+               drop->leavecb(drop->leavedata, drop->obj);
+          }
+     }
+}
+
+static void 
+_wl_dropable_all_set(unsigned int win, Evas_Coord x, Evas_Coord y, Eina_Bool 
set)
+{
+   Eina_List *l;
+   Dropable *dropable;
+
+   EINA_LIST_FOREACH(drops, l, dropable)
+     {
+        if (_wl_elm_widget_window_get(dropable->obj) == win)
+          {
+             dropable->last.x = x;
+             dropable->last.y = y;
+             dropable->last.in = set;
+          }
+     }
+}
+
+static Eina_Bool 
+_wl_drops_accept(const char *type)
+{
+   Eina_List *l;
+   Dropable *drop;
+   Eina_Bool will_accept = EINA_FALSE;
+
+   EINA_LIST_FOREACH(drops, l, drop)
+     {
+        switch (drop->types)
+          {
+           case ELM_SEL_FORMAT_TARGETS:
+           case ELM_SEL_FORMAT_IMAGE:
+             if ((!strncmp(type, "text/uri", 8)) || 
+                 (!strncmp(type, "image/", 6)))
+               {
+                  wl_cnp_selection.requestwidget = drop->obj;
+                  return EINA_TRUE;
+               }
+             break;
+           case ELM_SEL_FORMAT_NONE:
+             break;
+           case ELM_SEL_FORMAT_TEXT:
+             break;
+           case ELM_SEL_FORMAT_MARKUP:
+             break;
+           case ELM_SEL_FORMAT_VCARD:
+             break;
+           case ELM_SEL_FORMAT_HTML:
+             break;
+          }
+     }
+
+   return will_accept;
+}
+
+static unsigned int 
+_wl_elm_widget_window_get(Evas_Object *obj)
+{
+   Evas_Object *top;
+   Ecore_Wl_Window *win;
+
+   top = elm_widget_top_get(obj);
+   if (!top) top = elm_widget_top_get(elm_widget_parent_widget_get(obj));
+   if (top) win = elm_win_wl_window_get(top);
+   if (!win)
+     {
+        Ecore_Evas *ee;
+        Evas *evas;
+
+        if (!(evas = evas_object_evas_get(obj)))
+          return 0;
+        if (!(ee = ecore_evas_ecore_evas_get(evas)))
+          return 0;
+
+        win = ecore_evas_wayland_window_get(ee);
+     }
+
+   return win->id;
+}
+
 #endif
 
 
@@ -2687,6 +3359,10 @@ elm_object_cnp_selection_clear(Evas_Object *obj, 
Elm_Sel_Type selection)
    if (_x11_elm_widget_xwin_get(obj))
      return _x11_elm_object_cnp_selection_clear(obj, selection);
 #endif
+#ifdef HAVE_ELEMENTARY_WAYLAND
+   if (elm_win_wl_window_get(obj))
+      return _wl_elm_cnp_selection_clear(obj, selection);
+#endif
    return _local_elm_object_cnp_selection_clear(obj, selection);
 }
 
@@ -2805,7 +3481,7 @@ elm_selection_selection_has_owner(Evas_Object *obj)
 #endif
 #ifdef HAVE_ELEMENTARY_WAYLAND
    if (elm_win_wl_window_get(obj))
-     return ecore_wl_dnd_selection_has_owner(ecore_wl_dnd_get());
+     return ecore_wl_dnd_selection_owner_has(ecore_wl_input_get());
 #endif
    return _local_elm_selection_selection_has_owner(obj);
 }

-- 

------------------------------------------------------------------------------
Try New Relic Now & We'll Send You this Cool Shirt
New Relic is the only SaaS-based application performance monitoring service 
that delivers powerful full stack analytics. Optimize and monitor your
browser, app, & servers with just a few lines of code. Try New Relic
and get this awesome Nerd Life shirt! http://p.sf.net/sfu/newrelic_d2d_may

Reply via email to