devilhorns pushed a commit to branch master.

http://git.enlightenment.org/core/elementary.git/commit/?id=f0eea6c266d8621b9316f8f98a468617d5d6ce5b

commit f0eea6c266d8621b9316f8f98a468617d5d6ce5b
Author: Chris Michael <cp.mich...@samsung.com>
Date:   Thu Nov 7 11:57:14 2013 +0000

    Fix elementary copy/paste for wayland. Rework copy/paste code in elm.
    
    This is part of a larger copy/paste fix for efl/elm wayland.
    Previously, copy/paste would not work via keyboard shortcuts. This
    series of changes fixes that issue (wrt elm_entry anyway).
    
    This also adds addtional copy/paste support (wrt efl wayland),
    including support for various mime types (text/plain, elm-markup, and
    html).
    
    Signed-off-by: Chris Michael <cp.mich...@samsung.com>
---
 src/lib/elm_cnp.c | 285 ++++++++++++++++++++++++++++++++++++++++++++++++------
 1 file changed, 253 insertions(+), 32 deletions(-)

diff --git a/src/lib/elm_cnp.c b/src/lib/elm_cnp.c
index b321de1..a40f87b 100644
--- a/src/lib/elm_cnp.c
+++ b/src/lib/elm_cnp.c
@@ -2147,11 +2147,31 @@ struct _Wl_Cnp_Selection
 
    Evas_Object *widget;
    Evas_Object *requestwidget;
+
+   void *udata;
+   Elm_Sel_Type seltype;
+   Elm_Sel_Format requestformat;
+   Elm_Drop_Cb datacb;
+
+   Elm_Selection_Loss_Cb loss_cb;
+   void *loss_data;
+
+   Elm_Sel_Format format;
+   Ecore_Wl_Window *win;
+   Elm_Xdnd_Action action;
+
+   Eina_Bool active : 1;
 };
 
 static Eina_Bool _wl_elm_cnp_init(void);
 
-static Wl_Cnp_Selection wl_cnp_selection = {0, 0, NULL, NULL};
+static Wl_Cnp_Selection wl_cnp_selection = 
+{
+   0, 0, NULL, NULL, 
+   NULL, 0, 0, NULL, NULL, NULL, 
+   0, NULL, 0, EINA_FALSE
+};
+
 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__);
@@ -2188,6 +2208,14 @@ 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_del(void *data, Evas *e __UNUSED__, Evas_Object *obj, void 
*event_info __UNUSED__)
+{
+   Wl_Cnp_Selection *sel = data;
+   if (sel->widget == obj) sel->widget = NULL;
+   if (dragwidget == obj) dragwidget = NULL;
+}
+
+static void
 _wl_sel_obj_del2(void *data, Evas *e __UNUSED__, Evas_Object *obj, void 
*event_info __UNUSED__)
 {
    Wl_Cnp_Selection *sel = data;
@@ -2195,59 +2223,187 @@ _wl_sel_obj_del2(void *data, Evas *e __UNUSED__, 
Evas_Object *obj, void *event_i
 }
 
 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)
+_wl_elm_cnp_selection_set(Evas_Object *obj, Elm_Sel_Type selection, 
Elm_Sel_Format format, const void *selbuf, size_t buflen)
 {
-   const char *types[10] = {0, };
+   Ecore_Wl_Window *win;
+   Wl_Cnp_Selection *sel = &wl_cnp_selection;
+
+   if ((!selbuf) && (format != ELM_SEL_FORMAT_IMAGE))
+     return elm_object_cnp_selection_clear(obj, selection);
 
    _wl_elm_cnp_init();
 
-   /* TODO: other EML_SEL_TYPE and ELM_SEL_FORMAT */
-   if (ELM_SEL_TYPE_CLIPBOARD == selection)
+   win = elm_win_wl_window_get(obj);
+
+   if (sel->loss_cb) sel->loss_cb(sel->loss_data, selection);
+
+   if (sel->widget)
+     evas_object_event_callback_del_full(sel->widget, 
+                                         EVAS_CALLBACK_DEL,
+                                         _wl_sel_obj_del, &wl_cnp_selection);
+   sel->widget = NULL;
+
+   sel->active = EINA_TRUE;
+   sel->seltype = selection;
+   sel->widget = obj;
+   sel->win = win;
+   /* sel->set(win, &selection, sizeof(Elm_Sel_Type)); */
+   sel->format = format;
+   sel->loss_cb = NULL;
+   sel->loss_data = NULL;
+
+   evas_object_event_callback_add
+     (sel->widget, EVAS_CALLBACK_DEL, _wl_sel_obj_del, 
+         &wl_cnp_selection);
+
+   if (selbuf)
      {
-        types[0] = "text/plain;charset=utf-8";
-        ecore_wl_dnd_selection_set(ecore_wl_input_get(), types);
+        if (format & ELM_SEL_FORMAT_IMAGE)
+          {
+             /* FIXME */
+             // selbuf is actual image data, not text/string
+             sel->selbuf = malloc(buflen + 1);
+             if (!sel->selbuf)
+               {
+                  elm_object_cnp_selection_clear(obj, selection);
+                  return EINA_FALSE;
+               }
+             memcpy(sel->selbuf, selbuf, buflen);
+             sel->selbuf[buflen] = 0;
+          }
+        else
+          {
+             const char *types[10] = {0, };
+             int i = -1;
 
-        if (wl_cnp_selection.selbuf) free(wl_cnp_selection.selbuf);
-        wl_cnp_selection.selbuf = strdup((char*)selbuf);
-        wl_cnp_selection.buflen = buflen;
-        return EINA_TRUE;
+             if (format & ELM_SEL_FORMAT_TEXT)
+               {
+                  types[++i] = "text/plain";
+                  types[++i] = "text/plain;charset=utf-8";
+               }
+
+             if (format & ELM_SEL_FORMAT_MARKUP)
+               types[++i] = "application/x-elementary-markup";
+
+             if (format & ELM_SEL_FORMAT_HTML)
+               {
+                  types[++i] = "text/html";
+                  types[++i] = "text/html;charset=utf-8";
+               }
+
+             if (i < 0) return EINA_FALSE;
+
+             ecore_wl_dnd_selection_set(ecore_wl_input_get(), types);
+
+             if (sel->selbuf) free(sel->selbuf);
+             sel->buflen = buflen;
+             sel->selbuf = strdup((char*)selbuf);
+
+             return EINA_TRUE;
+          }
      }
+   else
+     sel->selbuf = NULL;
 
    return EINA_FALSE;
 }
 
 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__)
+_wl_elm_cnp_selection_get(Evas_Object *obj, Elm_Sel_Type selection, 
Elm_Sel_Format format, Elm_Drop_Cb datacb, void *udata)
 {
+   Ecore_Wl_Window *win;
+   Wl_Cnp_Selection *sel = &wl_cnp_selection;
+
    _wl_elm_cnp_init();
 
-   /* For now, just avoid overlapped request */
-   if (wl_cnp_selection.requestwidget) return EINA_FALSE;
+   win = elm_win_wl_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->requestwidget = NULL;
+
+   sel->requestformat = format;
+   sel->requestwidget = obj;
+   sel->win = win;
+   /* sel->request(win, ECORE_X_SELECTION_TARGET_TARGETS); */
+   sel->datacb = datacb;
+   sel->udata = udata;
 
-   /* TODO: other EML_SEL_TYPE and ELM_SEL_FORMAT */
-   if (ELM_SEL_TYPE_CLIPBOARD == selection)
+   evas_object_event_callback_add(sel->requestwidget, 
+                                  EVAS_CALLBACK_DEL, _wl_sel_obj_del2, 
+                                  &wl_cnp_selection);
+
+   if (selection == ELM_SEL_TYPE_CLIPBOARD)
      {
-        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_selection_get(ecore_wl_input_get(),
-                                   "text/plain;charset=utf-8");
+        const char *types[10] = {0, };
+        int i = -1;
+
+        if (format & ELM_SEL_FORMAT_TEXT)
+          {
+             types[++i] = "text/plain";
+             types[++i] = "text/plain;charset=utf-8";
+          }
+
+        if (format & ELM_SEL_FORMAT_MARKUP)
+          types[++i] = "application/x-elementary-markup";
+
+        if (format & ELM_SEL_FORMAT_HTML)
+          {
+             types[++i] = "text/html";
+             types[++i] = "text/html;charset=utf-8";
+          }
+
+        if (i < 0) return EINA_FALSE;
+
+        ecore_wl_dnd_selection_get(ecore_wl_input_get(), *types);
      }
+
    return EINA_TRUE;
 }
 
+static void
+_wl_elm_cnp_selection_loss_callback_set(Evas_Object *obj __UNUSED__, 
Elm_Sel_Type selection __UNUSED__, Elm_Selection_Loss_Cb func, const void *data)
+{
+   Wl_Cnp_Selection *sel = &wl_cnp_selection;
+
+   _wl_elm_cnp_init();
+
+   sel->loss_cb = func;
+   sel->loss_data = (void *)data;
+}
+
 static Eina_Bool
-_wl_elm_cnp_selection_clear(Evas_Object *obj EINA_UNUSED, Elm_Sel_Type 
selection)
+_wl_elm_cnp_selection_clear(Evas_Object *obj, Elm_Sel_Type selection 
__UNUSED__)
 {
+   Wl_Cnp_Selection *sel = &wl_cnp_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());
-     }
+   if ((!sel->active) || (sel->widget != obj))
+     return EINA_TRUE;
+
+   if (sel->widget)
+     evas_object_event_callback_del_full(sel->widget, 
+                                         EVAS_CALLBACK_DEL,
+                                         _wl_sel_obj_del, &wl_cnp_selection);
+   if (sel->requestwidget)
+     evas_object_event_callback_del_full(sel->requestwidget, 
+                                         EVAS_CALLBACK_DEL,
+                                         _wl_sel_obj_del2, &wl_cnp_selection);
+
+   sel->widget = NULL;
+   sel->requestwidget = NULL;
+   sel->loss_cb = NULL;
+   sel->loss_data = NULL;
+
+   sel->active = EINA_FALSE;
+   ELM_SAFE_FREE(sel->selbuf, free);
+   sel->buflen = 0;
+   /* sel->clear(); */
+   ecore_wl_dnd_selection_clear(ecore_wl_input_get());
+
    return EINA_TRUE;
 }
 
@@ -2290,17 +2446,78 @@ _wl_selection_receive(void *udata, int type __UNUSED__, 
void *event)
      {
         if (!ev->done)
           {
-             /* TODO BUG: should never NEVER assume it's an elm_entry! */
-             _elm_entry_entry_paste(sel->requestwidget, ev->data);
+             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->widget, &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);
+               }
           }
         else
           {
-             evas_object_event_callback_del_full(sel->requestwidget, 
EVAS_CALLBACK_DEL,
+             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;
 }
 
@@ -3427,6 +3644,10 @@ elm_cnp_selection_loss_callback_set(Evas_Object *obj, 
Elm_Sel_Type selection,
    if (_x11_elm_widget_xwin_get(obj))
      _x11_elm_cnp_selection_loss_callback_set(obj, selection, func, data);
 #endif
+#ifdef HAVE_ELEMENTARY_WAYLAND
+   if (elm_win_wl_window_get(obj))
+     _wl_elm_cnp_selection_loss_callback_set(obj, selection, func, data);
+#endif
    _local_elm_cnp_selection_loss_callback_set(obj, selection, func, data);
 }
 

-- 


Reply via email to