ecore_wl2: introduce offer api
authorMarcel Hollerbach <marcel-hollerbach@t-online.de>
Thu, 22 Sep 2016 07:13:48 +0000 (09:13 +0200)
committerMarcel Hollerbach <marcel-hollerbach@t-online.de>
Fri, 23 Sep 2016 09:15:14 +0000 (11:15 +0200)
This commits adds api to deal with wayland offers.
It also ports elm_cnp to use the new api.

The selection_get and dnd_drag_get calls are replaced by simply receive
data from the offer.

The Offer object is now also emitted in every Enter,Motion,Drop and
Leave event, so a potential user can prefetch data and display it.
To finish a dnd operation positiv, the user has to call the finish call
before the offer is destroyed

src/lib/ecore_wl2/Ecore_Wl2.h
src/lib/ecore_wl2/ecore_wl2.c
src/lib/ecore_wl2/ecore_wl2_dnd.c
src/lib/ecore_wl2/ecore_wl2_input.c
src/lib/ecore_wl2/ecore_wl2_private.h
src/lib/elementary/elm_cnp.c

index 29f4825..34d6fff 100644 (file)
@@ -43,7 +43,7 @@ typedef struct _Ecore_Wl2_Seat Ecore_Wl2_Seat;
 typedef struct _Ecore_Wl2_Pointer Ecore_Wl2_Pointer;
 typedef struct _Ecore_Wl2_Keyboard Ecore_Wl2_Keyboard;
 typedef struct _Ecore_Wl2_Touch Ecore_Wl2_Touch;
-
+typedef struct _Ecore_Wl2_Offer Ecore_Wl2_Offer;
 /* matches protocol values */
 typedef enum
 {
@@ -51,6 +51,7 @@ typedef enum
    ECORE_WL2_DRAG_ACTION_COPY = 1,
    ECORE_WL2_DRAG_ACTION_MOVE = 2,
    ECORE_WL2_DRAG_ACTION_ASK = 4,
+   ECORE_WL2_DRAG_ACTION_LAST = 5,
 } Ecore_Wl2_Drag_Action;
 
 struct _Ecore_Wl2_Event_Connection
@@ -87,20 +88,21 @@ typedef struct _Ecore_Wl2_Event_Focus_Out
 
 typedef struct _Ecore_Wl2_Event_Dnd_Enter
 {
-   unsigned int win, source, serial;
-   char **types;
-   int num_types, x, y;
-   struct wl_data_offer *offer;
+   unsigned int win, source;
+   Ecore_Wl2_Offer *offer;
+   int x, y;
 } Ecore_Wl2_Event_Dnd_Enter;
 
 typedef struct _Ecore_Wl2_Event_Dnd_Leave
 {
    unsigned int win, source;
+   Ecore_Wl2_Offer *offer;
 } Ecore_Wl2_Event_Dnd_Leave;
 
 typedef struct _Ecore_Wl2_Event_Dnd_Motion
 {
-   unsigned int win, source, serial;
+   unsigned int win, source;
+   Ecore_Wl2_Offer *offer;
    int x, y;
 } Ecore_Wl2_Event_Dnd_Motion;
 
@@ -108,6 +110,7 @@ typedef struct _Ecore_Wl2_Event_Dnd_Drop
 {
    unsigned int win, source;
    int x, y;
+   Ecore_Wl2_Offer *offer;
 } Ecore_Wl2_Event_Dnd_Drop;
 
 typedef struct _Ecore_Wl2_Event_Dnd_End
@@ -142,13 +145,6 @@ typedef enum
    ECORE_WL2_SELECTION_DND
 } Ecore_Wl2_Selection_Type;
 
-typedef struct _Ecore_Wl2_Event_Selection_Data_Ready
-{
-   char *data;
-   int len;
-   Ecore_Wl2_Selection_Type sel_type;
-} Ecore_Wl2_Event_Selection_Data_Ready;
-
 typedef enum
 {
    ECORE_WL2_WINDOW_STATE_NONE = 0,
@@ -168,6 +164,12 @@ typedef struct _Ecore_Wl2_Event_Sync_Done
    Ecore_Wl2_Display *display;
 } Ecore_Wl2_Event_Sync_Done;
 
+typedef struct _Ecore_Wl2_Event_Offer_Data_Ready{
+   Ecore_Wl2_Offer *offer;
+   char *data;
+   int len;
+} Ecore_Wl2_Event_Offer_Data_Ready;
+
 typedef enum _Ecore_Wl2_Window_Type
 {
    ECORE_WL2_WINDOW_TYPE_NONE,
@@ -192,16 +194,14 @@ EAPI extern int ECORE_WL2_EVENT_DND_LEAVE; /** @since 1.17 */
 EAPI extern int ECORE_WL2_EVENT_DND_MOTION; /** @since 1.17 */
 EAPI extern int ECORE_WL2_EVENT_DND_DROP; /** @since 1.17 */
 EAPI extern int ECORE_WL2_EVENT_DND_END; /** @since 1.17 */
-EAPI extern int ECORE_WL2_EVENT_DND_DATA_READY; /** @since 1.18 */
 EAPI extern int ECORE_WL2_EVENT_DATA_SOURCE_END; /** @since 1.18 */
 EAPI extern int ECORE_WL2_EVENT_DATA_SOURCE_DROP; /** @since 1.18 */
 EAPI extern int ECORE_WL2_EVENT_DATA_SOURCE_ACTION; /** @since 1.18 */
 EAPI extern int ECORE_WL2_EVENT_DATA_SOURCE_TARGET; /** @since 1.17 */
 EAPI extern int ECORE_WL2_EVENT_DATA_SOURCE_SEND; /** @since 1.17 */
-EAPI extern int ECORE_WL2_EVENT_CNP_DATA_READY; /** @since 1.18 */
 EAPI extern int ECORE_WL2_EVENT_WINDOW_CONFIGURE; /** @since 1.17 */
 EAPI extern int ECORE_WL2_EVENT_SYNC_DONE; /** @since 1.17 */
-
+EAPI extern int ECORE_WL2_EVENT_OFFER_DATA_READY; /** @since 1.19 */
 /**
  * @file
  * @brief Ecore functions for dealing with the Wayland display protocol
@@ -869,15 +869,11 @@ EAPI void ecore_wl2_dnd_drag_start(Ecore_Wl2_Input *input, Ecore_Wl2_Window *win
 
 /* TODO: doxy */
 /** @since 1.17 */
-EAPI Eina_Bool ecore_wl2_dnd_drag_get(Ecore_Wl2_Input *input, const char *type);
-
-/* TODO: doxy */
-/** @since 1.17 */
 EAPI void ecore_wl2_dnd_drag_end(Ecore_Wl2_Input *input);
 
 /* TODO: doxy */
 /** @since 1.17 */
-EAPI Eina_Bool ecore_wl2_dnd_selection_owner_has(Ecore_Wl2_Input *input);
+EAPI Ecore_Wl2_Offer* ecore_wl2_dnd_selection_get(Ecore_Wl2_Input *input);
 
 /* TODO: doxy */
 /** @since 1.17 */
@@ -885,10 +881,6 @@ EAPI Eina_Bool ecore_wl2_dnd_selection_set(Ecore_Wl2_Input *input, const char **
 
 /* TODO: doxy */
 /** @since 1.17 */
-EAPI Eina_Bool ecore_wl2_dnd_selection_get(Ecore_Wl2_Input *input, const char *type);
-
-/* TODO: doxy */
-/** @since 1.17 */
 EAPI Eina_Bool ecore_wl2_dnd_selection_clear(Ecore_Wl2_Input *input);
 
 /**
@@ -1111,6 +1103,90 @@ EAPI Ecore_Wl2_Display *ecore_wl2_window_display_get(const Ecore_Wl2_Window *win
 /* # ifdef __cplusplus */
 /* } */
 /* # endif */
+/**
+ * Get the actions available from the data source
+ *
+ * @param offer Offer object to use
+ *
+ * @return or´ed values from Ecore_Wl2_Drag_Action which are describing the available actions
+ * @since 1.19
+ */
+EAPI Ecore_Wl2_Drag_Action ecore_wl2_offer_actions_get(Ecore_Wl2_Offer *offer);
+
+/**
+ * Set the actions which are supported by you
+ *
+ * @param offer Offer object to use
+ * @param actions A or´ed value of mutliple Ecore_Wl2_Drag_Action values
+ * @param action the preffered action out of the actions
+ *
+ * @since 1.19
+ */
+EAPI void ecore_wl2_offer_actions_set(Ecore_Wl2_Offer *offer, Ecore_Wl2_Drag_Action actions, Ecore_Wl2_Drag_Action action);
+
+/**
+ * Get action which is set by either the data source or in the last call of actions_set
+ *
+ * @param offer Offer object to use
+ *
+ * @return the prefered action
+ *
+ * @since 1.19
+ */
+EAPI Ecore_Wl2_Drag_Action ecore_wl2_offer_action_get(Ecore_Wl2_Offer *offer);
+
+/**
+ * Get the mime types which are given by the source
+ *
+ * @param offer the offer to query
+ *
+ * @return a eina array of strdup´ed strings, this array must NOT be changed or freed
+ */
+EAPI Eina_Array* ecore_wl2_offer_mimes_get(Ecore_Wl2_Offer *offer);
+
+/**
+ * Set mimetypes you are accepting under this offer
+ *
+ * @param offer the offer to use
+ *
+ * @since 1.19
+ */
+EAPI void ecore_wl2_offer_mimes_set(Ecore_Wl2_Offer *offer, Eina_Array *mimes);
+
+/**
+ * Request the data from this offer.
+ * The event ECORE_WL2_EVENT_OFFER_DATA_READY is called when the data is available.
+ * There offer will be not destroyed as long as requested data is not emitted by the event.
+ *
+ * @param offer the offer to use
+ * @param mime the mimetype to receive
+ *
+ * @since 1.19
+ */
+EAPI Eina_Bool ecore_wl2_offer_receive(Ecore_Wl2_Offer *offer, char *mime);
+
+/**
+ * Check if the given offer supports the given mimetype
+ *
+ * @param offer the offer to use
+ * @param mime the mimetype to check
+ *
+ * @return Returns true if the mimetype is supported by this offer, false if not
+ *
+ * @since 1.19
+ */
+EAPI Eina_Bool ecore_wl2_offer_supprts_mime(Ecore_Wl2_Offer *offer, const char *mime);
+
+/**
+ * Mark this offer as finished
+ * This will call the dnd_finished event on the source of the sender.
+ *
+ * @param offer the offer to use
+ *
+ * @since 1.19
+ */
+EAPI void ecore_wl2_offer_finish(Ecore_Wl2_Offer *offer);
+
 
 # endif
 
index 0f8850f..f62daca 100644 (file)
@@ -28,10 +28,9 @@ EAPI int ECORE_WL2_EVENT_DATA_SOURCE_DROP = 0;
 EAPI int ECORE_WL2_EVENT_DATA_SOURCE_ACTION = 0;
 EAPI int ECORE_WL2_EVENT_DATA_SOURCE_TARGET = 0;
 EAPI int ECORE_WL2_EVENT_DATA_SOURCE_SEND = 0;
-EAPI int ECORE_WL2_EVENT_CNP_DATA_READY = 0;
-EAPI int ECORE_WL2_EVENT_DND_DATA_READY = 0;
 EAPI int ECORE_WL2_EVENT_WINDOW_CONFIGURE = 0;
 EAPI int ECORE_WL2_EVENT_SYNC_DONE = 0;
+EAPI int ECORE_WL2_EVENT_OFFER_DATA_READY = 0;
 
 EAPI int _ecore_wl2_event_window_www = -1;
 EAPI int _ecore_wl2_event_window_www_drag = -1;
@@ -87,10 +86,9 @@ ecore_wl2_init(void)
         ECORE_WL2_EVENT_DATA_SOURCE_ACTION = ecore_event_type_new();
         ECORE_WL2_EVENT_DATA_SOURCE_TARGET = ecore_event_type_new();
         ECORE_WL2_EVENT_DATA_SOURCE_SEND = ecore_event_type_new();
-        ECORE_WL2_EVENT_CNP_DATA_READY = ecore_event_type_new();
-        ECORE_WL2_EVENT_DND_DATA_READY = ecore_event_type_new();
         ECORE_WL2_EVENT_WINDOW_CONFIGURE = ecore_event_type_new();
         ECORE_WL2_EVENT_SYNC_DONE = ecore_event_type_new();
+        ECORE_WL2_EVENT_OFFER_DATA_READY = ecore_event_type_new();
         _ecore_wl2_event_window_www = ecore_event_type_new();
         _ecore_wl2_event_window_www_drag = ecore_event_type_new();
      }
@@ -138,10 +136,9 @@ ecore_wl2_shutdown(void)
    ECORE_WL2_EVENT_DATA_SOURCE_ACTION = 0;
    ECORE_WL2_EVENT_DATA_SOURCE_TARGET = 0;
    ECORE_WL2_EVENT_DATA_SOURCE_SEND = 0;
-   ECORE_WL2_EVENT_DND_DATA_READY = 0;
-   ECORE_WL2_EVENT_CNP_DATA_READY = 0;
    ECORE_WL2_EVENT_WINDOW_CONFIGURE = 0;
    ECORE_WL2_EVENT_SYNC_DONE = 0;
+   ECORE_WL2_EVENT_OFFER_DATA_READY = 0;
 
    /* shutdown Ecore_Event */
    ecore_event_shutdown();
index 74299f3..31669a7 100644 (file)
@@ -43,37 +43,16 @@ struct _dnd_read_ctx
    struct epoll_event *ep;
 };
 
-static void
-data_offer_offer(void *data, struct wl_data_offer *wl_data_offer EINA_UNUSED, const char *type)
+struct _Ecore_Wl2_Offer
 {
-   Ecore_Wl2_Dnd_Source *source = data;
-   char **p;
-
-   p = wl_array_add(&source->types, sizeof *p);
-   *p = strdup(type);
-}
-
-static void
-data_offer_source_actions(void *data, struct wl_data_offer *wl_data_offer EINA_UNUSED, uint32_t source_actions)
-{
-   Ecore_Wl2_Dnd_Source *source = data;
-
-   source->source_actions = source_actions;
-}
-
-static void
-data_offer_action(void *data, struct wl_data_offer *wl_data_offer EINA_UNUSED, uint32_t dnd_action)
-{
-   Ecore_Wl2_Dnd_Source *source = data;
-
-   source->dnd_action = dnd_action;
-}
-
-static const struct wl_data_offer_listener _offer_listener =
-{
-   data_offer_offer,
-   data_offer_source_actions,
-   data_offer_action
+   Ecore_Wl2_Input *input;
+   struct wl_data_offer *offer;
+   Eina_Array *mimetypes;
+   Ecore_Wl2_Drag_Action actions;
+   Ecore_Wl2_Drag_Action action;
+   uint32_t serial;
+   Ecore_Fd_Handler *read;
+   int ref;
 };
 
 static void
@@ -207,118 +186,14 @@ static const struct wl_data_source_listener _source_listener =
 };
 
 static void
-_selection_data_ready_cb_free(void *data EINA_UNUSED, void *event)
-{
-   Ecore_Wl2_Event_Selection_Data_Ready *ev;
-
-   ev = event;
-   if (!ev) return;
-
-   free(ev->data);
-   free(ev);
-}
-
-static Eina_Bool
-_selection_data_read(void *data, Ecore_Fd_Handler *fdh)
-{
-   int len = 0, fd;
-   char buffer[PATH_MAX];
-   Ecore_Wl2_Dnd_Source *source = data;
-   Ecore_Wl2_Event_Selection_Data_Ready *event;
-
-   fd = ecore_main_fd_handler_fd_get(fdh);
-   if (fd >= 0)
-     len = read(fd, buffer, sizeof buffer);
-   else
-     return ECORE_CALLBACK_RENEW;
-
-   event = calloc(1, sizeof(Ecore_Wl2_Event_Selection_Data_Ready));
-   if (!event) return ECORE_CALLBACK_CANCEL;
-
-   event->sel_type = source->sel_type;
-   if (len <= 0)
-     {
-        if (source->input->drag.source)
-          {
-             if (source->input->display->wl.data_device_manager_version >=
-                 WL_DATA_OFFER_FINISH_SINCE_VERSION)
-               {
-                  wl_data_offer_finish(source->offer);
-               }
-             wl_data_offer_destroy(source->offer);
-             source->offer = NULL;
-          }
-
-        fd = ecore_main_fd_handler_fd_get(source->fdh);
-        if (fd >= 0) close(fd);
-        ecore_main_fd_handler_del(source->fdh);
-        source->fdh = NULL;
-
-        event->data = source->read_data;
-        source->read_data = NULL;
-        event->len = source->len;
-        source->len = 0;
-        if (source->input->drag.source)
-          ecore_event_add(ECORE_WL2_EVENT_DND_DATA_READY, event,
-                          _selection_data_ready_cb_free, NULL);
-        else
-          ecore_event_add(ECORE_WL2_EVENT_CNP_DATA_READY, event,
-                          _selection_data_ready_cb_free, NULL);
-
-        return ECORE_CALLBACK_CANCEL;
-     }
-   else
-     {
-        int old_len = source->len;
-
-        if (!source->read_data)
-          {
-             source->read_data = malloc(len);
-             source->len = len;
-          }
-        else
-          {
-             source->len += len;
-               source->read_data = realloc(source->read_data, source->len);
-            }
-
-        memcpy(((char*)source->read_data) + old_len, buffer, len);
-        free(event);
-        return ECORE_CALLBACK_RENEW;
-     }
-}
-
-static void
-_selection_data_receive(Ecore_Wl2_Dnd_Source *source, const char *type)
+_unset_serial(void *user_data, void *event)
 {
-   int p[2];
-
-   source->active_read = EINA_TRUE;
-
-   if (pipe2(p, O_CLOEXEC) == -1)
-     return;
-
-   wl_data_offer_receive(source->offer, type, p[1]);
-   close(p[1]);
-
-   source->fdh =
-     ecore_main_fd_handler_file_add(p[0], ECORE_FD_READ | ECORE_FD_ERROR,
-                                    _selection_data_read, source, NULL, NULL);
-}
+   Ecore_Wl2_Offer *offer = user_data;
 
-void
-_ecore_wl2_dnd_add(Ecore_Wl2_Input *input, struct wl_data_offer *offer)
-{
-   Ecore_Wl2_Dnd_Source *source;
-
-   source = calloc(1, sizeof(Ecore_Wl2_Dnd_Source));
-   if (!source) return;
-
-   wl_array_init(&source->types);
-   source->input = input;
-   source->offer = offer;
+   if (offer)
+     offer->serial = 0;
 
-   wl_data_offer_add_listener(source->offer, &_offer_listener, source);
+   free(event);
 }
 
 void
@@ -326,32 +201,36 @@ _ecore_wl2_dnd_enter(Ecore_Wl2_Input *input, struct wl_data_offer *offer, struct
 {
    Ecore_Wl2_Window *window;
    Ecore_Wl2_Event_Dnd_Enter *ev;
-   char **types;
-   int num = 0;
 
    window = _ecore_wl2_display_window_surface_find(input->display, surface);
    if (!window) return;
 
    if (offer)
      {
-        input->drag.source = wl_data_offer_get_user_data(offer);
-        input->drag.source->dnd_action =
-          WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE;
-        num = (input->drag.source->types.size / sizeof(char *));
-        types = input->drag.source->types.data;
+        input->drag = wl_data_offer_get_user_data(offer);
+
+        if (!input->drag)
+          {
+             ERR("Userdata of offer not found");
+             goto emit;
+          }
+
+        input->drag->serial = serial;
+
         if (input->display->wl.data_device_manager_version >=
             WL_DATA_OFFER_SET_ACTIONS_SINCE_VERSION)
-          wl_data_offer_set_actions(offer,
-               WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY |
-               WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE,
-               WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE);
+          {
+             ecore_wl2_offer_actions_set(input->drag,
+                ECORE_WL2_DRAG_ACTION_MOVE | ECORE_WL2_DRAG_ACTION_COPY,
+                ECORE_WL2_DRAG_ACTION_MOVE);
+          }
      }
    else
      {
-        input->drag.source = NULL;
-        types = NULL;
+        input->drag = NULL;
      }
 
+emit:
    ev = calloc(1, sizeof(Ecore_Wl2_Event_Dnd_Enter));
    if (!ev) return;
 
@@ -364,27 +243,18 @@ _ecore_wl2_dnd_enter(Ecore_Wl2_Input *input, struct wl_data_offer *offer, struct
 
    ev->x = x;
    ev->y = y;
-   ev->offer = offer;
-   ev->serial = serial;
-   ev->num_types = num;
-   ev->types = types;
+   ev->offer = input->drag;
 
-   ecore_event_add(ECORE_WL2_EVENT_DND_ENTER, ev, NULL, NULL);
+   ecore_event_add(ECORE_WL2_EVENT_DND_ENTER, ev, _unset_serial, input->drag);
 }
 
 static void
 _delay_offer_destroy(void *user_data, void *event)
 {
-   Ecore_Wl2_Dnd_Source *source;
+   Ecore_Wl2_Offer *offer = user_data;
 
-   source = user_data;
-
-   if (source && source->offer
-       && !source->active_read)
-     {
-        wl_data_offer_destroy(source->offer);
-        source->offer = NULL;
-     }
+   if (offer)
+     _ecore_wl2_offer_unref(offer);
 
    free(event);
 }
@@ -406,7 +276,11 @@ _ecore_wl2_dnd_leave(Ecore_Wl2_Input *input)
 
    if (!ev->win) ev->win = ev->source;
 
-   ecore_event_add(ECORE_WL2_EVENT_DND_LEAVE, ev, _delay_offer_destroy, input->drag.source);
+   ev->offer = input->drag;
+   ev->offer->ref++;
+
+   ecore_event_add(ECORE_WL2_EVENT_DND_LEAVE, ev, _delay_offer_destroy, ev->offer);
+   input->drag = NULL;
 }
 
 void
@@ -420,6 +294,8 @@ _ecore_wl2_dnd_motion(Ecore_Wl2_Input *input, int x, int y, uint32_t serial)
    ev = calloc(1, sizeof(Ecore_Wl2_Event_Dnd_Motion));
    if (!ev) return;
 
+   input->drag->serial = serial;
+
    if (input->focus.pointer)
      ev->win = input->focus.pointer->id;
    else if (input->focus.prev_pointer)
@@ -431,9 +307,9 @@ _ecore_wl2_dnd_motion(Ecore_Wl2_Input *input, int x, int y, uint32_t serial)
 
    ev->x = x;
    ev->y = y;
-   ev->serial = serial;
+   ev->offer = input->drag;
 
-   ecore_event_add(ECORE_WL2_EVENT_DND_MOTION, ev, NULL, NULL);
+   ecore_event_add(ECORE_WL2_EVENT_DND_MOTION, ev, _unset_serial, input->drag);
 }
 
 void
@@ -444,38 +320,30 @@ _ecore_wl2_dnd_drop(Ecore_Wl2_Input *input)
    ev = calloc(1, sizeof(Ecore_Wl2_Event_Dnd_Drop));
    if (!ev) return;
 
-   if (input->drag.source)
-     {
-        if (input->focus.pointer)
-          ev->win = input->focus.pointer->id;
-        else if (input->focus.prev_pointer)
-          ev->win = input->focus.prev_pointer->id;
-        if (input->focus.keyboard)
-          ev->source = input->focus.keyboard->id;
-
-        if (!ev->win) ev->win = ev->source;
-     }
+   if (input->focus.pointer)
+     ev->win = input->focus.pointer->id;
+   else if (input->focus.prev_pointer)
+     ev->win = input->focus.prev_pointer->id;
+   if (input->focus.keyboard)
+     ev->source = input->focus.keyboard->id;
+
+  if (!ev->win) ev->win = ev->source;
 
    ev->x = input->pointer.sx;
    ev->y = input->pointer.sy;
+   ev->offer = input->drag;
 
-   ecore_event_add(ECORE_WL2_EVENT_DND_DROP, ev, _delay_offer_destroy, input->drag.source);
+   ecore_event_add(ECORE_WL2_EVENT_DND_DROP, ev, NULL, NULL);
 }
 
 void
 _ecore_wl2_dnd_selection(Ecore_Wl2_Input *input, struct wl_data_offer *offer)
 {
-   if (input->selection.source) _ecore_wl2_dnd_del(input->selection.source);
-   input->selection.source = NULL;
+   if (input->selection) _ecore_wl2_offer_unref(input->selection);
+   input->selection = NULL;
 
    if (offer)
-     {
-        char **t;
-
-        input->selection.source = wl_data_offer_get_user_data(offer);
-        t = wl_array_add(&input->selection.source->types, sizeof(*t));
-        *t = NULL;
-     }
+     input->selection = wl_data_offer_get_user_data(offer);
 }
 
 void
@@ -571,25 +439,6 @@ ecore_wl2_dnd_drag_start(Ecore_Wl2_Input *input, Ecore_Wl2_Window *window, Ecore
      }
 }
 
-EAPI Eina_Bool
-ecore_wl2_dnd_drag_get(Ecore_Wl2_Input *input, const char *type)
-{
-   char **t;
-
-   EINA_SAFETY_ON_NULL_RETURN_VAL(input, EINA_FALSE);
-   EINA_SAFETY_ON_NULL_RETURN_VAL(input->drag.source, EINA_FALSE);
-
-   wl_array_for_each(t, &input->drag.source->types)
-     if (!strcmp(type, *t)) break;
-
-   if (!*t) return EINA_FALSE;
-
-   input->drag.source->sel_type = ECORE_WL2_SELECTION_DND;
-   _selection_data_receive(input->drag.source, type);
-
-   return EINA_TRUE;
-}
-
 EAPI void
 ecore_wl2_dnd_drag_end(Ecore_Wl2_Input *input)
 {
@@ -622,12 +471,12 @@ ecore_wl2_dnd_drag_end(Ecore_Wl2_Input *input)
    ecore_event_add(ECORE_WL2_EVENT_DND_END, ev, NULL, NULL);
 }
 
-EAPI Eina_Bool
-ecore_wl2_dnd_selection_owner_has(Ecore_Wl2_Input *input)
+EAPI Ecore_Wl2_Offer*
+ecore_wl2_dnd_selection_get(Ecore_Wl2_Input *input)
 {
-   EINA_SAFETY_ON_NULL_RETURN_VAL(input, EINA_FALSE);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(input, NULL);
 
-   return (input->selection.source != NULL);
+   return input->selection;
 }
 
 EAPI Eina_Bool
@@ -681,32 +530,303 @@ ecore_wl2_dnd_selection_set(Ecore_Wl2_Input *input, const char **types)
 }
 
 EAPI Eina_Bool
-ecore_wl2_dnd_selection_get(Ecore_Wl2_Input *input, const char *type)
+ecore_wl2_dnd_selection_clear(Ecore_Wl2_Input *input)
 {
-   char **t;
-
    EINA_SAFETY_ON_NULL_RETURN_VAL(input, EINA_FALSE);
-   EINA_SAFETY_ON_NULL_RETURN_VAL(input->selection.source, EINA_FALSE);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(input->data.device, EINA_FALSE);
 
-   for (t = input->selection.source->types.data; *t; t++)
-     if (!strcmp(type, *t)) break;
+   wl_data_device_set_selection(input->data.device,
+                                NULL, input->display->serial);
 
-   if (!*t) return EINA_FALSE;
+   return EINA_TRUE;
+}
 
-   input->selection.source->sel_type = ECORE_WL2_SELECTION_CNP;
-   _selection_data_receive(input->selection.source, type);
+static Ecore_Wl2_Drag_Action
+_wl_to_action_convert(uint32_t action)
+{
+#define PAIR(wl, ac) if (action == wl) return ac;
+   PAIR(WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY, ECORE_WL2_DRAG_ACTION_COPY)
+   PAIR(WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK, ECORE_WL2_DRAG_ACTION_ASK)
+   PAIR(WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE, ECORE_WL2_DRAG_ACTION_MOVE)
+   PAIR(WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE, ECORE_WL2_DRAG_ACTION_NONE)
+#undef PAIR
+   return ECORE_WL2_DRAG_ACTION_NONE;
+}
 
-   return EINA_TRUE;
+static uint32_t
+_action_to_wl_convert(Ecore_Wl2_Drag_Action action)
+{
+#define PAIR(wl, ac) if (action == ac) return wl;
+   PAIR(WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY, ECORE_WL2_DRAG_ACTION_COPY)
+   PAIR(WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK, ECORE_WL2_DRAG_ACTION_ASK)
+   PAIR(WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE, ECORE_WL2_DRAG_ACTION_MOVE)
+   PAIR(WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE, ECORE_WL2_DRAG_ACTION_NONE)
+#undef PAIR
+   return WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE;
+}
+static void
+data_offer_offer(void *data, struct wl_data_offer *wl_data_offer EINA_UNUSED, const char *type)
+{
+   Ecore_Wl2_Offer *offer = data;
+   char *str;
+
+   if (type)
+     eina_array_push(offer->mimetypes, strdup(type)); /*LEEEAK */
+   else
+     {
+        while((str = eina_array_pop(offer->mimetypes)))
+          {
+             free(str);
+          }
+     }
+}
+
+static void
+data_offer_source_actions(void *data, struct wl_data_offer *wl_data_offer EINA_UNUSED, uint32_t source_actions)
+{
+   Ecore_Wl2_Offer *offer;
+   unsigned int i;
+   uint32_t types[] = {WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE,
+                       WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY,
+                       WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK,
+                       WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE};
+
+   offer = data;
+
+   offer->actions = 0;
+
+   for (i = 0; i < sizeof(types); ++i)
+   {
+      if (source_actions & types[i])
+        offer->actions |= _wl_to_action_convert(types[i]);
+   }
+}
+
+static void
+data_offer_action(void *data, struct wl_data_offer *wl_data_offer EINA_UNUSED, uint32_t dnd_action)
+{
+   Ecore_Wl2_Offer *offer;
+
+   offer = data;
+   offer->action = _wl_to_action_convert(dnd_action);
+}
+
+static const struct wl_data_offer_listener _offer_listener =
+{
+   data_offer_offer,
+   data_offer_source_actions,
+   data_offer_action
+};
+
+void
+_ecore_wl2_dnd_add(Ecore_Wl2_Input *input, struct wl_data_offer *offer)
+{
+   Ecore_Wl2_Offer *result;
+
+   result = calloc(1, sizeof(Ecore_Wl2_Offer));
+   result->offer = offer;
+   result->input = input;
+   result->mimetypes = eina_array_new(10);
+   result->ref = 1;
+
+   wl_data_offer_add_listener(offer, &_offer_listener, result);
+}
+
+EAPI Ecore_Wl2_Drag_Action
+ecore_wl2_offer_actions_get(Ecore_Wl2_Offer *offer)
+{
+   return offer->actions;
+}
+
+EAPI void
+ecore_wl2_offer_actions_set(Ecore_Wl2_Offer *offer, Ecore_Wl2_Drag_Action actions, Ecore_Wl2_Drag_Action action)
+{
+   uint32_t val = 0;
+   int i = 0;
+
+   EINA_SAFETY_ON_NULL_RETURN(offer);
+
+   for (i = 0; i < ECORE_WL2_DRAG_ACTION_LAST; ++i)
+     {
+        if (actions & i)
+          val |= _action_to_wl_convert(i);
+     }
+
+   offer->action = _action_to_wl_convert(action);
+
+   wl_data_offer_set_actions(offer->offer, val, offer->action);
+}
+
+EAPI Ecore_Wl2_Drag_Action
+ecore_wl2_offer_action_get(Ecore_Wl2_Offer *offer)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(offer, ECORE_WL2_DRAG_ACTION_NONE);
+   return offer->action;
+}
+
+EAPI Eina_Array*
+ecore_wl2_offer_mimes_get(Ecore_Wl2_Offer *offer)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(offer, NULL);
+   return offer->mimetypes;
+}
+
+static unsigned char
+_emit_mime(const void *container EINA_UNUSED, void *elem, void *data)
+{
+   Ecore_Wl2_Offer *offer = data;
+
+   wl_data_offer_accept(offer->offer, offer->serial, elem);
+
+   return 1;
+}
+
+EAPI void
+ecore_wl2_offer_mimes_set(Ecore_Wl2_Offer *offer, Eina_Array *mimes)
+{
+   EINA_SAFETY_ON_NULL_RETURN(offer);
+
+   wl_data_offer_accept(offer->offer, offer->serial, NULL);
+   if (mimes)
+     eina_array_foreach(mimes, _emit_mime, offer);
+}
+
+typedef struct {
+   int len;
+   void *data;
+   Ecore_Wl2_Offer *offer;
+} Read_Buffer;
+
+static void
+_free_buf(void *user_data, void *event)
+{
+   Read_Buffer *buf = user_data;
+
+   _ecore_wl2_offer_unref(buf->offer);
+
+   free(buf->data);
+   free(user_data);
+   free(event);
+}
+
+static Eina_Bool
+_offer_receive_fd_cb(void *data, Ecore_Fd_Handler *fdh)
+{
+   Read_Buffer *buf = data;
+   int fd = -1;
+   char buffer[255];
+   int len;
+
+   fd = ecore_main_fd_handler_fd_get(fdh);
+   if (fd >= 0)
+     len = read(fd, buffer, sizeof(buffer));
+   else
+     return ECORE_CALLBACK_RENEW;
+
+   if (len > 0)
+     {
+        int old_len = buf->len;
+
+        buf->len += len;
+        buf->data = realloc(buf->data, buf->len);
+
+        memcpy(((char*)buf->data) + old_len, buffer, len);
+        return ECORE_CALLBACK_RENEW;
+     }
+   else
+     {
+        Ecore_Wl2_Event_Offer_Data_Ready *ev;
+
+        ev = calloc(1, sizeof(Ecore_Wl2_Event_Offer_Data_Ready));
+        ev->offer = buf->offer;
+
+        ev->data = buf->data;
+        ev->len = buf->len;
+
+        ecore_event_add(ECORE_WL2_EVENT_OFFER_DATA_READY, ev, _free_buf, buf);
+
+        buf->offer->read = NULL;
+        return ECORE_CALLBACK_CANCEL;
+     }
 }
 
 EAPI Eina_Bool
-ecore_wl2_dnd_selection_clear(Ecore_Wl2_Input *input)
+ecore_wl2_offer_receive(Ecore_Wl2_Offer *offer, char *mime)
 {
-   EINA_SAFETY_ON_NULL_RETURN_VAL(input, EINA_FALSE);
-   EINA_SAFETY_ON_NULL_RETURN_VAL(input->data.device, EINA_FALSE);
+   Read_Buffer *buffer;
+   int pipe[2];
 
-   wl_data_device_set_selection(input->data.device,
-                                NULL, input->display->serial);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(offer, EINA_FALSE);
+
+   //if a read is going on exit
+   if (offer->read) return EINA_FALSE;
+
+   buffer = calloc(1, sizeof(Read_Buffer));
+   buffer->offer = offer;
+
+   // no data yet, we would have to fetch it and then tell when the data is ready
+   if (pipe2(pipe, O_CLOEXEC) == -1)
+     return EINA_FALSE;
+
+   offer->ref ++; // we are keeping this ref until the read is done AND emitted
+
+   wl_data_offer_receive(offer->offer, mime, pipe[1]);
+   close(pipe[1]);
+
+   offer->read =
+     ecore_main_fd_handler_file_add(pipe[0], ECORE_FD_READ | ECORE_FD_ERROR,
+                                    _offer_receive_fd_cb, buffer, NULL, NULL);
+   return EINA_FALSE;
+}
+
+EAPI void
+ecore_wl2_offer_finish(Ecore_Wl2_Offer *offer)
+{
+   EINA_SAFETY_ON_NULL_RETURN(offer);
+
+   wl_data_offer_finish(offer->offer);
+}
+
+void
+_ecore_wl2_offer_unref(Ecore_Wl2_Offer *offer)
+{
+   char *str;
+
+   EINA_SAFETY_ON_NULL_RETURN(offer);
+
+   offer->ref--;
+
+   if (offer->ref > 0) return;
+
+   wl_data_offer_destroy(offer->offer);
+
+   if (offer->mimetypes)
+     {
+        while((str = eina_array_pop(offer->mimetypes)))
+          free(str);
+        eina_array_free(offer->mimetypes);
+        offer->mimetypes = NULL;
+     }
 
+   if (offer->input->drag == offer) offer->input->drag = NULL;
+   if (offer->input->selection == offer) offer->input->selection = NULL;
+
+   free(offer);
+}
+
+static unsigned char
+_compare(const void *container EINA_UNUSED, void *elem, void *data)
+{
+   if (!strcmp(elem, data))
+     return EINA_FALSE;
    return EINA_TRUE;
 }
+
+EAPI Eina_Bool
+ecore_wl2_offer_supprts_mime(Ecore_Wl2_Offer *offer, const char *mime)
+{
+  EINA_SAFETY_ON_NULL_RETURN_VAL(offer, EINA_FALSE);
+  EINA_SAFETY_ON_NULL_RETURN_VAL(mime, EINA_FALSE);
+
+  return !eina_array_foreach(offer->mimetypes, _compare, (void*) mime);
+}
\ No newline at end of file
index 3ea2de0..919d424 100644 (file)
@@ -1373,8 +1373,8 @@ _ecore_wl2_input_del(Ecore_Wl2_Input *input)
      }
 
    if (input->data.source) wl_data_source_destroy(input->data.source);
-   if (input->drag.source) _ecore_wl2_dnd_del(input->drag.source);
-   if (input->selection.source) _ecore_wl2_dnd_del(input->selection.source);
+   if (input->drag) _ecore_wl2_offer_unref(input->drag);
+   if (input->selection) _ecore_wl2_offer_unref(input->selection);
    if (input->data.device) wl_data_device_destroy(input->data.device);
 
    if (input->xkb.state) xkb_state_unref(input->xkb.state);
index c15c681..23d1d58 100644 (file)
@@ -413,10 +413,7 @@ struct _Ecore_Wl2_Input
         Eina_Bool repeating : 1;
      } repeat;
 
-   struct
-     {
-        Ecore_Wl2_Dnd_Source *source;
-     } drag, selection;
+   Ecore_Wl2_Offer *drag, *selection;
 
    unsigned int seat_version;
 };
@@ -463,6 +460,8 @@ void _ecore_wl2_subsurf_free(Ecore_Wl2_Subsurface *subsurf);
 void _ecore_wl2_window_shell_surface_init(Ecore_Wl2_Window *window);
 void _ecore_wl2_window_www_surface_init(Ecore_Wl2_Window *window);
 
+void _ecore_wl2_offer_unref(Ecore_Wl2_Offer *offer);
+
 EAPI extern int _ecore_wl2_event_window_www;
 EAPI extern int _ecore_wl2_event_window_www_drag;
 
index be0b642..08b5ebb 100644 (file)
@@ -260,12 +260,12 @@ static Eina_Bool _wl_targets_converter(char *target, Wl_Cnp_Selection *sel, void
 static Eina_Bool _wl_general_converter(char *target, Wl_Cnp_Selection *sel, void *data, int size, void **data_ret, int *size_ret);
 static Eina_Bool _wl_text_converter(char *target, Wl_Cnp_Selection *sel, void *data, int size, void **data_ret, int *size_ret);
 
-typedef Eina_Bool       (*Wl_Data_Preparer_Cb)   (Wl_Cnp_Selection *sel, Elm_Selection_Data *ddata, Ecore_Wl2_Event_Selection_Data_Ready *ev, Tmp_Info **tmp_info);
-static Eina_Bool _wl_data_preparer_markup(Wl_Cnp_Selection *sel, Elm_Selection_Data *ddata, Ecore_Wl2_Event_Selection_Data_Ready *ev, Tmp_Info **tmp_info);
-static Eina_Bool _wl_data_preparer_uri(Wl_Cnp_Selection *sel, Elm_Selection_Data *ddata, Ecore_Wl2_Event_Selection_Data_Ready *ev, Tmp_Info **tmp_info);
-static Eina_Bool _wl_data_preparer_vcard(Wl_Cnp_Selection *sel, Elm_Selection_Data *ddata, Ecore_Wl2_Event_Selection_Data_Ready *ev, Tmp_Info **tmp_info);
-static Eina_Bool _wl_data_preparer_image(Wl_Cnp_Selection *sel, Elm_Selection_Data *ddata, Ecore_Wl2_Event_Selection_Data_Ready *ev, Tmp_Info **tmp_info);
-static Eina_Bool _wl_data_preparer_text(Wl_Cnp_Selection *sel, Elm_Selection_Data *ddata, Ecore_Wl2_Event_Selection_Data_Ready *ev, Tmp_Info **tmp_info);
+typedef Eina_Bool       (*Wl_Data_Preparer_Cb)   (Wl_Cnp_Selection *sel, Elm_Selection_Data *ddata, Ecore_Wl2_Event_Offer_Data_Ready *ev, Tmp_Info **tmp_info);
+static Eina_Bool _wl_data_preparer_markup(Wl_Cnp_Selection *sel, Elm_Selection_Data *ddata, Ecore_Wl2_Event_Offer_Data_Ready *ev, Tmp_Info **tmp_info);
+static Eina_Bool _wl_data_preparer_uri(Wl_Cnp_Selection *sel, Elm_Selection_Data *ddata, Ecore_Wl2_Event_Offer_Data_Ready *ev, Tmp_Info **tmp_info);
+static Eina_Bool _wl_data_preparer_vcard(Wl_Cnp_Selection *sel, Elm_Selection_Data *ddata, Ecore_Wl2_Event_Offer_Data_Ready *ev, Tmp_Info **tmp_info);
+static Eina_Bool _wl_data_preparer_image(Wl_Cnp_Selection *sel, Elm_Selection_Data *ddata, Ecore_Wl2_Event_Offer_Data_Ready *ev, Tmp_Info **tmp_info);
+static Eina_Bool _wl_data_preparer_text(Wl_Cnp_Selection *sel, Elm_Selection_Data *ddata, Ecore_Wl2_Event_Offer_Data_Ready *ev, Tmp_Info **tmp_info);
 #endif
 
 struct _Cnp_Atom
@@ -2427,7 +2427,7 @@ static Eina_Bool _wl_dnd_drop(void *data EINA_UNUSED, int type EINA_UNUSED, void
 
 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, Ecore_Wl2_Event_Selection_Data_Ready *ev);
+static void _wl_dropable_data_handle(Wl_Cnp_Selection *sel, Ecore_Wl2_Event_Offer_Data_Ready *ev);
 
 static Dropable *_wl_dropable_find(unsigned int win);
 static void _wl_dropable_handle(Dropable *drop, Evas_Coord x, Evas_Coord y);
@@ -2691,7 +2691,7 @@ done:
 }
 
 static Eina_Bool
-_wl_data_preparer_markup(Wl_Cnp_Selection *sel, Elm_Selection_Data *ddata, Ecore_Wl2_Event_Selection_Data_Ready *ev, Tmp_Info **tmp_info EINA_UNUSED)
+_wl_data_preparer_markup(Wl_Cnp_Selection *sel, Elm_Selection_Data *ddata, Ecore_Wl2_Event_Offer_Data_Ready *ev, Tmp_Info **tmp_info EINA_UNUSED)
 {
    cnp_debug("In\n");
 
@@ -2704,7 +2704,7 @@ _wl_data_preparer_markup(Wl_Cnp_Selection *sel, Elm_Selection_Data *ddata, Ecore
 }
 
 static Eina_Bool
-_wl_data_preparer_uri(Wl_Cnp_Selection *sel, Elm_Selection_Data *ddata, Ecore_Wl2_Event_Selection_Data_Ready *ev, Tmp_Info **tmp_info EINA_UNUSED)
+_wl_data_preparer_uri(Wl_Cnp_Selection *sel, Elm_Selection_Data *ddata, Ecore_Wl2_Event_Offer_Data_Ready *ev, Tmp_Info **tmp_info EINA_UNUSED)
 {
    char *p, *stripstr = NULL;
    char *data = ev->data;
@@ -2787,7 +2787,7 @@ _wl_data_preparer_uri(Wl_Cnp_Selection *sel, Elm_Selection_Data *ddata, Ecore_Wl
 }
 
 static Eina_Bool
-_wl_data_preparer_vcard(Wl_Cnp_Selection *sel, Elm_Selection_Data *ddata, Ecore_Wl2_Event_Selection_Data_Ready *ev, Tmp_Info **tmp_info EINA_UNUSED)
+_wl_data_preparer_vcard(Wl_Cnp_Selection *sel, Elm_Selection_Data *ddata, Ecore_Wl2_Event_Offer_Data_Ready *ev, Tmp_Info **tmp_info EINA_UNUSED)
 {
    cnp_debug("In\n");
 
@@ -2800,7 +2800,7 @@ _wl_data_preparer_vcard(Wl_Cnp_Selection *sel, Elm_Selection_Data *ddata, Ecore_
 }
 
 static Eina_Bool
-_wl_data_preparer_image(Wl_Cnp_Selection *sel, Elm_Selection_Data *ddata, Ecore_Wl2_Event_Selection_Data_Ready *ev, Tmp_Info **tmp_info)
+_wl_data_preparer_image(Wl_Cnp_Selection *sel, Elm_Selection_Data *ddata, Ecore_Wl2_Event_Offer_Data_Ready *ev, Tmp_Info **tmp_info)
 {
    cnp_debug("In\n");
    Tmp_Info *tmp;
@@ -2823,7 +2823,7 @@ _wl_data_preparer_image(Wl_Cnp_Selection *sel, Elm_Selection_Data *ddata, Ecore_
 }
 
 static Eina_Bool
-_wl_data_preparer_text(Wl_Cnp_Selection *sel, Elm_Selection_Data *ddata, Ecore_Wl2_Event_Selection_Data_Ready *ev, Tmp_Info **tmp_info EINA_UNUSED)
+_wl_data_preparer_text(Wl_Cnp_Selection *sel, Elm_Selection_Data *ddata, Ecore_Wl2_Event_Offer_Data_Ready *ev, Tmp_Info **tmp_info EINA_UNUSED)
 {
    cnp_debug("In\n");
 
@@ -2954,38 +2954,83 @@ _wl_elm_cnp_selection_set(Evas_Object *obj, Elm_Sel_Type selection, Elm_Sel_Form
    return EINA_FALSE;
 }
 
+typedef struct {
+   Ecore_Wl2_Offer *offer;
+   Wl_Cnp_Selection sel;
+   Ecore_Event_Handler *handler;
+} Selection_Ready;
+
+static Eina_Bool
+_wl_selection_receive(void *data, int type EINA_UNUSED, void *event)
+{
+   Ecore_Wl2_Event_Offer_Data_Ready *ev = event;
+   Selection_Ready *ready = data;
+   Wl_Cnp_Selection *sel =  &ready->sel;
+
+   if (ready->offer != ev->offer) return ECORE_CALLBACK_PASS_ON;
+
+   if (sel->requestwidget)
+     {
+        if (sel->datacb)
+          {
+             Elm_Selection_Data sdata;
+
+             sdata.x = sdata.y = 0;
+             sdata.format = ELM_SEL_FORMAT_TEXT;
+             sdata.data = ev->data;
+             sdata.len = ev->len;
+             sdata.action = sel->action;
+             sel->datacb(sel->udata,
+                          sel->requestwidget,
+                          &sdata);
+          }
+        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->requestwidget, mkupstr);
+             free(stripstr);
+             free(mkupstr);
+          }
+        evas_object_event_callback_del_full(sel->requestwidget,
+                                            EVAS_CALLBACK_DEL,
+                                            _wl_sel_obj_del2, sel);
+        sel->requestwidget = NULL;
+     }
+   ecore_event_handler_del(ready->handler);
+   free(data);
+   return ECORE_CALLBACK_CANCEL;
+}
+
 static Eina_Bool
 _wl_elm_cnp_selection_get(const Evas_Object *obj, Elm_Sel_Type selection, Elm_Sel_Format format, Elm_Drop_Cb datacb, void *udata)
 {
    Ecore_Wl2_Window *win;
-   Wl_Cnp_Selection *sel = &wl_cnp_selection;
 
    _wl_elm_cnp_init();
 
    win = _wl_elm_widget_window_get(obj);
 
-   if (sel->requestwidget)
-     evas_object_event_callback_del_full(sel->requestwidget, EVAS_CALLBACK_DEL,
-                                         _wl_sel_obj_del2, &wl_cnp_selection);
-   sel->requestformat = format;
-   sel->requestwidget = (Evas_Object *) obj;
-   sel->win = win;
-   /* sel->request(win, ECORE_X_SELECTION_TARGET_TARGETS); */
-   sel->datacb = datacb;
-   sel->udata = udata;
-
-   evas_object_event_callback_add(sel->requestwidget, EVAS_CALLBACK_DEL,
-                                  _wl_sel_obj_del2, &wl_cnp_selection);
 
    if ((selection == ELM_SEL_TYPE_CLIPBOARD) ||
        (selection == ELM_SEL_TYPE_PRIMARY) ||
        (selection == ELM_SEL_TYPE_SECONDARY))
      {
         Ecore_Wl2_Input *input;
+        Ecore_Wl2_Offer *offer;
         const char *types[10] = {0, };
         int i = -1, j;
 
         input = ecore_wl2_window_input_get(win);
+        offer = ecore_wl2_dnd_selection_get(input);
+
+        if (!offer) return EINA_FALSE;
 
         if ((format & ELM_SEL_FORMAT_MARKUP) ||
             (format & ELM_SEL_FORMAT_TEXT))
@@ -3003,9 +3048,27 @@ _wl_elm_cnp_selection_get(const Evas_Object *obj, Elm_Sel_Type selection, Elm_Se
 
         if (i < 0) return EINA_FALSE;
 
+
         for (j = 0; j <= i; j++)
-          if (ecore_wl2_dnd_selection_get(input, types[j]))
-            break;
+          if (ecore_wl2_offer_supprts_mime(offer, types[j]))
+            {
+               Selection_Ready *ready;
+
+               ready = calloc(1, sizeof(Selection_Ready));
+
+               ready->sel.requestformat = format;
+               ready->sel.requestwidget = (Evas_Object *) obj;
+               ready->sel.win = win;
+               ready->sel.datacb = datacb;
+               ready->sel.udata = udata;
+               ready->offer = offer;
+
+               evas_object_event_callback_add(ready->sel.requestwidget, EVAS_CALLBACK_DEL,
+                                              _wl_sel_obj_del2, &ready->sel);
+
+               ecore_wl2_offer_receive(offer, (char*)types[j]);
+               ready->handler = ecore_event_handler_add(ECORE_WL2_EVENT_OFFER_DATA_READY, _wl_selection_receive, ready);
+            }
      }
 
    return EINA_TRUE;
@@ -3112,89 +3175,6 @@ _wl_selection_send(void *data, int type EINA_UNUSED, void *event)
 }
 
 static Eina_Bool
-_wl_selection_receive(void *udata, int type EINA_UNUSED, void *event)
-{
-   Wl_Cnp_Selection *sel = udata;
-   Ecore_Wl2_Event_Selection_Data_Ready *ev = event;
-
-   _wl_elm_cnp_init();
-
-   if (sel->requestwidget)
-     {
-        if (sel->seltype == ELM_SEL_TYPE_XDND)
-          {
-             Elm_Selection_Data sdata;
-             Eina_List *l;
-             Dropable *dropable;
-
-             EINA_LIST_FOREACH(drops, l, dropable)
-               {
-                  if (dropable->obj == sel->requestwidget) break;
-                  dropable = NULL;
-               }
-
-             if (dropable)
-               {
-                  Dropable_Cbs *cbs;
-
-                  sdata.x = savedtypes.x;
-                  sdata.y = savedtypes.y;
-                  sdata.format = ELM_SEL_FORMAT_TEXT;
-                  sdata.data = ev->data;
-                  sdata.len = ev->len;
-                  sdata.action = sel->action;
-
-                  EINA_INLIST_FOREACH(dropable->cbs_list, cbs)
-                    if (cbs->dropcb)
-                      cbs->dropcb(cbs->dropdata, dropable->obj, &sdata);
-
-                  goto end;
-               }
-          }
-
-        if (sel->datacb)
-          {
-             Elm_Selection_Data sdata;
-
-             sdata.x = sdata.y = 0;
-             sdata.format = ELM_SEL_FORMAT_TEXT;
-             sdata.data = ev->data;
-             sdata.len = ev->len;
-             sdata.action = sel->action;
-             sel->datacb(sel->udata,
-                          sel->requestwidget,
-                          &sdata);
-          }
-        else
-          {
-             char *stripstr, *mkupstr;
-
-             stripstr = malloc(ev->len + 1);
-             if (!stripstr) goto end;
-             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->requestwidget, mkupstr);
-             free(stripstr);
-             free(mkupstr);
-          }
-        evas_object_event_callback_del_full(sel->requestwidget,
-                                            EVAS_CALLBACK_DEL,
-                                            _wl_sel_obj_del2, sel);
-        sel->requestwidget = NULL;
-     }
-
-end:
-   if (sel->seltype == ELM_SEL_TYPE_XDND)
-     {
-        /* FIXME: Send Finished ?? */
-     }
-
-   return ECORE_CALLBACK_PASS_ON;
-}
-
-static Eina_Bool
 _wl_elm_cnp_init(void)
 {
    static int _init_count = 0;
@@ -3204,9 +3184,6 @@ _wl_elm_cnp_init(void)
 
    ecore_event_handler_add(ECORE_WL2_EVENT_DATA_SOURCE_SEND,
                            _wl_selection_send, &wl_cnp_selection);
-   ecore_event_handler_add(ECORE_WL2_EVENT_CNP_DATA_READY,
-                           _wl_selection_receive, &wl_cnp_selection);
-
    return EINA_TRUE;
 }
 
@@ -3221,9 +3198,6 @@ _wl_elm_dnd_init(void)
    text_uri = eina_stringshare_add("text/uri-list");
 
    _wl_elm_cnp_init();
-   ecore_event_handler_add(ECORE_WL2_EVENT_DND_DATA_READY,
-                           _wl_dnd_receive, &wl_cnp_selection);
-
    ecore_event_handler_add(ECORE_WL2_EVENT_DATA_SOURCE_END,
                            _wl_dnd_end, &wl_cnp_selection);
 
@@ -3468,20 +3442,23 @@ static Eina_Bool
 _wl_dnd_enter(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
 {
    Ecore_Wl2_Event_Dnd_Enter *ev;
-   int i = 0;
+   Eina_Array *known, *available;
+   unsigned int i = 0;
 
    ev = event;
 
-   if ((!ev->num_types) || (!ev->types)) return ECORE_CALLBACK_PASS_ON;
+   known = eina_array_new(5);
+   available = ecore_wl2_offer_mimes_get(ev->offer);
 
-   savedtypes.ntypes = ev->num_types;
    free(savedtypes.types);
-   savedtypes.types = malloc(sizeof(char *) * ev->num_types);
+
+   savedtypes.ntypes = eina_array_count(available);
+   savedtypes.types = malloc(sizeof(char *) * savedtypes.ntypes);
    if (!savedtypes.types) return EINA_FALSE;
 
-   for (i = 0; i < ev->num_types; i++)
+   for (i = 0; i < eina_array_count(available); i++)
      {
-        savedtypes.types[i] = eina_stringshare_add(ev->types[i]);
+        savedtypes.types[i] = eina_stringshare_add(eina_array_data_get(available, i));
         if (savedtypes.types[i] == text_uri)
           {
              savedtypes.textreq = 1;
@@ -3490,17 +3467,15 @@ _wl_dnd_enter(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
      }
 
    doaccept = EINA_FALSE;
-   for (i = 0; i < ev->num_types; i++)
+   for (i = 0; i < eina_array_count(available); i++)
      {
-        if (_wl_drops_accept(ev->types[i]))
+        if (_wl_drops_accept(eina_array_data_get(available, i)))
           {
-             doaccept = EINA_TRUE;
-             wl_data_offer_accept(ev->offer, ev->serial, ev->types[i]);
+             eina_array_push(known, strdup(eina_array_data_get(available, i)));
           }
      }
 
-   if (!doaccept)
-     wl_data_offer_accept(ev->offer, ev->serial, NULL);
+   ecore_wl2_offer_mimes_set(ev->offer, known);
 
    return ECORE_CALLBACK_PASS_ON;
 }
@@ -3635,6 +3610,38 @@ _wl_dnd_position(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
    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;
+   Ecore_Wl2_Offer *offer;
+   cnp_debug("In\n");
+
+   ev = event;
+   offer = data;
+
+   if (offer != ev->offer) return ECORE_CALLBACK_PASS_ON;
+
+   if (wl_cnp_selection.requestwidget)
+     {
+           Ecore_Wl2_Drag_Action action;
+
+           action = ecore_wl2_offer_action_get(ev->offer);
+
+           _wl_dropable_data_handle(&wl_cnp_selection, ev);
+           evas_object_event_callback_del_full(wl_cnp_selection.requestwidget,
+                                               EVAS_CALLBACK_DEL,
+                                               _wl_sel_obj_del2, &wl_cnp_selection);
+           wl_cnp_selection.requestwidget = NULL;
+
+     }
+
+   ecore_wl2_offer_finish(ev->offer);
+
+   return ECORE_CALLBACK_CANCEL;
+}
+
 static Eina_Bool
 _wl_dnd_drop(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
 {
@@ -3660,8 +3667,9 @@ _wl_dnd_drop(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
                                             &wl_cnp_selection);
 
              win = _wl_elm_widget_window_get(drop->obj);
-             ecore_wl2_dnd_drag_get(ecore_wl2_window_input_get(win),
-                                    drop->last.type);
+             ecore_wl2_offer_receive(ev->offer, (char*)drop->last.type);
+             ecore_event_handler_add(ECORE_WL2_EVENT_OFFER_DATA_READY, _wl_dnd_receive, ev->offer);
+
              return ECORE_CALLBACK_PASS_ON;
           }
      }
@@ -3672,29 +3680,6 @@ _wl_dnd_drop(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
 }
 
 static Eina_Bool
-_wl_dnd_receive(void *data, int type EINA_UNUSED, void *event)
-{
-   Wl_Cnp_Selection *sel;
-   Ecore_Wl2_Event_Selection_Data_Ready *ev;
-   cnp_debug("In\n");
-
-   ev = event;
-   sel = data;
-
-   if (sel->requestwidget)
-     {
-           _wl_dropable_data_handle(sel, ev);
-           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)
 {
    Ecore_Wl2_Event_Data_Source_End *ev;
@@ -3735,7 +3720,7 @@ _wl_dnd_end(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
 }
 
 static void
-_wl_dropable_data_handle(Wl_Cnp_Selection *sel, Ecore_Wl2_Event_Selection_Data_Ready *ev)
+_wl_dropable_data_handle(Wl_Cnp_Selection *sel, Ecore_Wl2_Event_Offer_Data_Ready *ev)
 {
    Dropable *drop;
    Ecore_Wl2_Window *win;
@@ -5185,7 +5170,7 @@ elm_selection_selection_has_owner(Evas_Object *obj)
 
    win = _wl_elm_widget_window_get(obj);
    if (win)
-     return ecore_wl2_dnd_selection_owner_has(ecore_wl2_window_input_get(win));
+     return !!ecore_wl2_dnd_selection_get(ecore_wl2_window_input_get(win));
 #endif
    return _local_elm_selection_selection_has_owner(obj);
 }