elm dnd/wl: add type converters 50/83550/4
authorThiep Ha <thiepha@gmail.com>
Tue, 3 May 2016 09:07:48 +0000 (09:07 +0000)
committerMinchul Lee <slotus.lee@samsung.com>
Tue, 16 Aug 2016 06:25:37 +0000 (23:25 -0700)
we support different types for DnD, but there is no converters.
This patch adds converters for types, so that we can send
different data for different types.

Change-Id: I1150a3189091dc506d7164efc78f58b5a2fc4ea4

src/lib/elm_cnp.c

index 8ef65ad..13198db 100644 (file)
@@ -8,7 +8,7 @@
 # include <sys/mman.h>
 #endif
 
-//#define DEBUGON 1
+#define DEBUGON 1
 #ifdef DEBUGON
 # define cnp_debug(fmt, args...) fprintf(stderr, __FILE__":%s/%d : " fmt , __FUNCTION__, __LINE__, ##args)
 #else
@@ -252,6 +252,15 @@ static Eina_Bool _x11_elm_selection_selection_has_owner  (Evas_Object *obj EINA_
 
 #endif
 
+#ifdef HAVE_ELEMENTARY_WAYLAND
+typedef struct _Wl_Cnp_Selection Wl_Cnp_Selection;
+
+typedef Eina_Bool (*Wl_Converter_Fn_Cb)     (char *target, Wl_Cnp_Selection *sel, void *data, int size, void **data_ret, int *size_ret);
+static Eina_Bool _wl_targets_converter(char *target, Wl_Cnp_Selection *sel, void *data, int size, void **data_ret, int *size_ret);
+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);
+#endif
+
 struct _Cnp_Atom
 {
    const char              *name;
@@ -263,6 +272,10 @@ struct _Cnp_Atom
    /* Atom */
    Ecore_X_Atom             x_atom;
 #endif
+#ifdef HAVE_ELEMENTARY_WAYLAND
+   Wl_Converter_Fn_Cb       wl_converter;
+#endif
+
    void                    *_term;
 };
 
@@ -440,6 +453,10 @@ static Cnp_Atom _atoms[CNP_N_ATOMS] = {
         .formats = ELM_SEL_FORMAT_TARGETS,
 #ifdef HAVE_ELEMENTARY_X
         .x_converter = _x11_targets_converter,
+
+#endif
+#ifdef HAVE_ELEMENTARY_WAYLAND
+        .wl_converter = _wl_targets_converter,
 #endif
    },
    ARRAYINIT(CNP_ATOM_ATOM) {
@@ -448,6 +465,9 @@ static Cnp_Atom _atoms[CNP_N_ATOMS] = {
 #ifdef HAVE_ELEMENTARY_X
         .x_converter = _x11_targets_converter,
 #endif
+#ifdef HAVE_ELEMENTARY_WAYLAND
+        .wl_converter = _wl_targets_converter,
+#endif
    },
    ARRAYINIT(CNP_ATOM_XELM)  {
         .name = "application/x-elementary-markup",
@@ -456,6 +476,9 @@ static Cnp_Atom _atoms[CNP_N_ATOMS] = {
         .x_converter = _x11_general_converter,
         .x_data_preparer = _x11_data_preparer_markup,
 #endif
+#ifdef HAVE_ELEMENTARY_WAYLAND
+        .wl_converter = _wl_general_converter,
+#endif
    },
    ARRAYINIT(CNP_ATOM_text_urilist) {
         .name = "text/uri-list",
@@ -464,6 +487,9 @@ static Cnp_Atom _atoms[CNP_N_ATOMS] = {
         .x_converter = _x11_general_converter,
         .x_data_preparer = _x11_data_preparer_uri,
 #endif
+#ifdef HAVE_ELEMENTARY_WAYLAND
+        .wl_converter = _wl_general_converter,
+#endif
    },
    ARRAYINIT(CNP_ATOM_text_x_vcard) {
         .name = "text/x-vcard",
@@ -553,6 +579,9 @@ static Cnp_Atom _atoms[CNP_N_ATOMS] = {
       .x_converter = _x11_general_converter,
       .x_notify = _x11_notify_handler_html,
 #endif
+#ifdef HAVE_ELEMENTARY_WAYLAND
+        .wl_converter = _wl_general_converter,
+#endif
    },
    ARRAYINIT(CNP_ATOM_text_html) {
       .name = "text/html",
@@ -561,6 +590,9 @@ static Cnp_Atom _atoms[CNP_N_ATOMS] = {
       .x_converter = _x11_general_converter,
       .x_notify = _x11_notify_handler_html,
 #endif
+#ifdef HAVE_ELEMENTARY_WAYLAND
+        .wl_converter = _wl_general_converter,
+#endif
    },
  */
    ARRAYINIT(CNP_ATOM_UTF8STRING) {
@@ -570,6 +602,9 @@ static Cnp_Atom _atoms[CNP_N_ATOMS] = {
         .x_converter = _x11_text_converter,
         .x_data_preparer = _x11_data_preparer_text,
 #endif
+#ifdef HAVE_ELEMENTARY_WAYLAND
+        .wl_converter = _wl_text_converter,
+#endif
    },
    ARRAYINIT(CNP_ATOM_STRING) {
         .name = "STRING",
@@ -578,6 +613,9 @@ static Cnp_Atom _atoms[CNP_N_ATOMS] = {
         .x_converter = _x11_text_converter,
         .x_data_preparer = _x11_data_preparer_text,
 #endif
+#ifdef HAVE_ELEMENTARY_WAYLAND
+        .wl_converter = _wl_text_converter,
+#endif
    },
    ARRAYINIT(CNP_ATOM_COMPOUND_TEXT) {
         .name = "COMPOUND_TEXT",
@@ -586,6 +624,9 @@ static Cnp_Atom _atoms[CNP_N_ATOMS] = {
         .x_converter = _x11_text_converter,
         .x_data_preparer = _x11_data_preparer_text,
 #endif
+#ifdef HAVE_ELEMENTARY_WAYLAND
+        .wl_converter = _wl_text_converter,
+#endif
    },
    ARRAYINIT(CNP_ATOM_TEXT) {
         .name = "TEXT",
@@ -594,6 +635,9 @@ static Cnp_Atom _atoms[CNP_N_ATOMS] = {
         .x_converter = _x11_text_converter,
         .x_data_preparer = _x11_data_preparer_text,
 #endif
+#ifdef HAVE_ELEMENTARY_WAYLAND
+        .wl_converter = _wl_text_converter,
+#endif
    },
    ARRAYINIT(CNP_ATOM_text_plain_utf8) {
         .name = "text/plain;charset=utf-8",
@@ -602,6 +646,9 @@ static Cnp_Atom _atoms[CNP_N_ATOMS] = {
         .x_converter = _x11_text_converter,
         .x_data_preparer = _x11_data_preparer_text,
 #endif
+#ifdef HAVE_ELEMENTARY_WAYLAND
+        .wl_converter = _wl_text_converter,
+#endif
    },
    ARRAYINIT(CNP_ATOM_text_plain) {
         .name = "text/plain",
@@ -610,6 +657,9 @@ static Cnp_Atom _atoms[CNP_N_ATOMS] = {
         .x_converter = _x11_text_converter,
         .x_data_preparer = _x11_data_preparer_text,
 #endif
+#ifdef HAVE_ELEMENTARY_WAYLAND
+        .wl_converter = _wl_text_converter,
+#endif
    },
 };
 
@@ -2399,6 +2449,136 @@ static Eina_Bool _wl_drops_accept(const char *type);
 static unsigned int _wl_elm_widget_window_get(const Evas_Object *obj);
 static Evas * _wl_evas_get_from_win(unsigned int win);
 
+static Eina_Bool
+_wl_targets_converter(char *target, Wl_Cnp_Selection *sel EINA_UNUSED, void *data EINA_UNUSED, int size EINA_UNUSED, void **data_ret, int *size_ret)
+{
+   cnp_debug("in\n");
+   if (!data_ret) return EINA_FALSE;
+
+   const char *sep = "\n";
+   char *aret;
+   int len = 0;
+   int i = 0;
+   Elm_Sel_Format formats = ELM_SEL_FORMAT_NONE;
+   Cnp_Atom *atom = NULL;
+
+   atom = eina_hash_find(_types_hash, target);
+   if (atom)
+     formats = atom->formats;
+   for (i = 0; i < CNP_N_ATOMS; i++)
+     {
+        if (formats & _atoms[i].formats)
+          {
+             len += strlen(_atoms[i].name) + strlen(sep);
+          }
+     }
+   aret = calloc(1, len * sizeof(char));
+   if (!aret) return EINA_FALSE;
+   for (i = 0; i < CNP_N_ATOMS; i++)
+     {
+        if (formats & _atoms[i].formats)
+          {
+             aret = strcat(aret, _atoms[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, Wl_Cnp_Selection *sel EINA_UNUSED, void *data, int size, void **data_ret, int *size_ret)
+{
+   cnp_debug("in\n");
+   Elm_Sel_Format formats = ELM_SEL_FORMAT_NONE;
+   Cnp_Atom *atom = NULL;
+
+   atom = eina_hash_find(_types_hash, target);
+   if (atom)
+     formats = atom->formats;
+   if (formats == ELM_SEL_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)
+          {
+             if (data_ret) *data_ret = strdup(data);
+             if (size_ret) *size_ret = strlen(data);
+          }
+        else
+          {
+             if (data_ret) *data_ret = NULL;
+             if (size_ret) *size_ret = 0;
+          }
+     }
+
+   return EINA_TRUE;
+}
+
+static Eina_Bool
+_wl_text_converter(char *target, Wl_Cnp_Selection *sel, void *data, int size, void **data_ret, int *size_ret)
+{
+   cnp_debug("in\n");
+   Elm_Sel_Format formats = ELM_SEL_FORMAT_NONE;
+   Cnp_Atom *atom = NULL;
+
+   atom = eina_hash_find(_types_hash, target);
+   if (atom)
+     formats = atom->formats;
+   if (formats == ELM_SEL_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 ((formats & ELM_SEL_FORMAT_MARKUP) ||
+            (formats & ELM_SEL_FORMAT_HTML))
+     {
+        *data_ret = _elm_util_mkup_to_text(data);
+        if (size_ret && *data_ret) *size_ret = strlen(*data_ret);
+     }
+   else if (formats & ELM_SEL_FORMAT_TEXT)
+     {
+        *data_ret = strdup(data);
+        if (size_ret && *data_ret) *size_ret = strlen(*data_ret);
+     }
+   else if (formats & ELM_SEL_FORMAT_IMAGE)
+     {
+        cnp_debug("Image %s\n", evas_object_type_get(sel->widget));
+        evas_object_image_file_get(elm_photocam_internal_image_get(sel->widget),
+                                   (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)
 {
@@ -3338,6 +3518,9 @@ _wl_dnd_send(void *data, int type EINA_UNUSED, void *event)
    int len_written = 0;
    Wl_Cnp_Selection *sel;
    Ecore_Wl_Event_Data_Source_Send *ev;
+   void *data_ret = NULL;
+   int len_ret = 0;
+   int i = 0;
 
    cnp_debug("In\n");
    ev = event;
@@ -3369,10 +3552,34 @@ _wl_dnd_send(void *data, int type EINA_UNUSED, void *event)
    //sel = data;
    //
 
-   len_remained = sel->buflen;
-   buf = sel->selbuf;
+   for (i = 0; i < CNP_N_ATOMS; i++)
+     {
+        if (!strcmp(_atoms[i].name, ev->type))
+          {
+             cnp_debug("Found a type: %s\n", _atoms[i].name);
+             Dropable *drop;
+             eo_do(sel->requestwidget, drop = eo_key_data_get("__elm_dropable"));
+             if (drop)
+               drop->last.type = _atoms[i].name;
+             if (_atoms[i].wl_converter)
+               {
+                  _atoms[i].wl_converter(ev->type, sel, sel->selbuf,
+                                         sel->buflen, &data_ret, &len_ret);
+               }
+             else
+               {
+                  data_ret = strdup(sel->selbuf);
+                  len_ret = sel->buflen;
+               }
+             break;
+          }
+     }
 
-   while (len_written < sel->buflen)
+   len_remained = len_ret;
+   buf = data_ret;
+   cnp_debug("write: %s\n", buf);
+
+   while (len_written < len_ret)
      {
         ret = write(ev->fd, buf, len_remained);
         if (ret == -1) break;
@@ -3380,6 +3587,7 @@ _wl_dnd_send(void *data, int type EINA_UNUSED, void *event)
         len_written += ret;
         len_remained -= ret;
      }
+   free(data_ret);
 
    close(ev->fd);
    return ECORE_CALLBACK_PASS_ON;