cnp: add Copy & Paste support for Windows 62/85462/1
authorVincent Torri <vincent dot torri at gmail dot com>
Thu, 15 Oct 2015 21:13:42 +0000 (23:13 +0200)
committerThiep Ha <thiep.ha@samsung.com>
Thu, 25 Aug 2016 07:17:37 +0000 (16:17 +0900)
It needs the clipboard management in Ecore_Win32

@feature

Change-Id: I20f6f6bf31475b52d4341257d80801d6d4efb67a
Signed-off-by: Cedric BAIL <cedric@osg.samsung.com>
src/lib/elm_cnp.c
src/lib/elm_config.c
src/lib/elm_priv.h
src/lib/elm_win.c
src/lib/elm_win.eo
src/lib/elm_win_legacy.h

index 3dedf00..b933058 100644 (file)
@@ -4865,6 +4865,320 @@ _local_elm_selection_selection_has_owner(Evas_Object *obj EINA_UNUSED)
 }
 #endif
 
+// win32 specific stuff
+////////////////////////////////////////////////////////////////////////////
+#ifdef HAVE_ELEMENTARY_WIN32
+
+typedef struct _Win32_Cnp_Selection Win32_Cnp_Selection;
+
+struct _Win32_Cnp_Selection
+{
+   const char            *debug;
+   Evas_Object           *widget;
+   char                  *selbuf;
+   Evas_Object           *requestwidget;
+   void                  *udata;
+   Elm_Sel_Format         requestformat;
+   Elm_Drop_Cb            datacb;
+   Eina_Bool            (*set)(const Ecore_Win32_Window *window, const void *data, int size);
+   Eina_Bool            (*clear)(const Ecore_Win32_Window *window);
+   Eina_Bool            (*get)(const Ecore_Win32_Window *window , void **data, int *size);
+   Elm_Selection_Loss_Cb  loss_cb;
+   void                  *loss_data;
+
+   Elm_Sel_Format         format;
+   Ecore_Win32_Selection  ecore_sel;
+   Ecore_Win32_Window    *win;
+   Elm_Xdnd_Action        action;
+
+   Eina_Bool              active : 1;
+};
+
+#define ARRAYINIT(foo)  [foo] =
+
+static Win32_Cnp_Selection _win32_selections[ELM_SEL_TYPE_CLIPBOARD + 1] =
+{
+   ARRAYINIT(ELM_SEL_TYPE_PRIMARY)
+   {
+      .debug = "Primary",
+      .ecore_sel = ECORE_WIN32_SELECTION_PRIMARY,
+      .set = ecore_win32_clipboard_set,
+      .clear = ecore_win32_clipboard_clear,
+      .get = ecore_win32_clipboard_get,
+   },
+   ARRAYINIT(ELM_SEL_TYPE_SECONDARY)
+   {
+      .debug = "Secondary",
+      .ecore_sel = ECORE_WIN32_SELECTION_OTHER,
+   },
+   ARRAYINIT(ELM_SEL_TYPE_XDND)
+   {
+      .debug = "XDnD",
+      .ecore_sel = ECORE_WIN32_SELECTION_OTHER,
+   },
+   ARRAYINIT(ELM_SEL_TYPE_CLIPBOARD)
+   {
+      .debug = "Clipboard",
+      .ecore_sel = ECORE_WIN32_SELECTION_CLIPBOARD,
+      .set = ecore_win32_clipboard_set,
+      .clear = ecore_win32_clipboard_clear,
+      .get = ecore_win32_clipboard_get,
+   }
+};
+
+
+static void
+_win32_sel_obj_del(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
+{
+   Win32_Cnp_Selection *sel = data;
+   if (sel->widget == obj) sel->widget = NULL;
+   if (dragwidget == obj) dragwidget = NULL;
+}
+
+static void
+_win32_sel_obj_del2(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
+{
+   Win32_Cnp_Selection *sel = data;
+   if (sel->requestwidget == obj) sel->requestwidget = NULL;
+}
+
+static Eina_Bool
+_win32_elm_cnp_init(void)
+{
+   static int _init_count = 0;
+
+   if (_init_count > 0) return EINA_TRUE;
+   _init_count++;
+   return EINA_TRUE;
+}
+
+static Ecore_Win32_Window *
+_win32_elm_widget_window_get(const Evas_Object *obj)
+{
+   Evas_Object *top;
+   Ecore_Win32_Window *win = NULL;
+
+   if (elm_widget_is(obj))
+     {
+        top = elm_widget_top_get(obj);
+        if (!top)
+          {
+             Evas_Object *par;
+             par = elm_widget_parent_widget_get(obj);
+             if (par) top = elm_widget_top_get(par);
+          }
+        if (top && (eo_isa(top, ELM_WIN_CLASS)))
+          win = elm_win_win32_window_get(top);
+     }
+
+   if (!win)
+     {
+        Ecore_Evas *ee;
+        Evas *evas;
+        const char *engine_name;
+
+        evas = evas_object_evas_get(obj);
+        if (!evas) return NULL;
+
+        ee = ecore_evas_ecore_evas_get(evas);
+        if (!ee) return NULL;
+
+        engine_name = ecore_evas_engine_name_get(ee);
+        if (!strcmp(engine_name, ELM_BUFFER))
+          {
+             ee = ecore_evas_buffer_ecore_evas_parent_get(ee);
+             if (!ee) return NULL;
+             win = ecore_evas_win32_window_get(ee);
+          }
+        else
+          {
+             if ((strcmp(engine_name, ELM_SOFTWARE_WIN32) == 0) ||
+                 (strcmp(engine_name, ELM_SOFTWARE_DDRAW) == 0))
+               return ecore_evas_win32_window_get(ee);
+          }
+     }
+
+   return win;
+}
+
+static Eina_Bool
+_win32_elm_cnp_selection_set(Ecore_Win32_Window *win, Evas_Object *obj, Elm_Sel_Type selection, Elm_Sel_Format format, const void *selbuf, size_t buflen)
+{
+   Win32_Cnp_Selection *sel;
+
+   if (selection != ELM_SEL_TYPE_CLIPBOARD)
+     return EINA_FALSE;
+
+   _win32_elm_cnp_init();
+   if ((!selbuf) && (format != ELM_SEL_FORMAT_IMAGE))
+     return elm_object_cnp_selection_clear(obj, selection);
+
+   sel = _win32_selections + selection;
+   if (sel->widget != obj && sel->loss_cb) sel->loss_cb(sel->loss_data, selection);
+   if (sel->widget)
+     evas_object_event_callback_del_full(sel->widget, EVAS_CALLBACK_DEL,
+                                         _win32_sel_obj_del, sel);
+   sel->active = EINA_TRUE;
+   sel->widget = obj;
+   sel->win = win;
+   if (sel->set) sel->set(win, selbuf, buflen);
+   sel->format = format;
+   sel->loss_cb = NULL;
+   sel->loss_data = NULL;
+
+   evas_object_event_callback_add
+     (sel->widget, EVAS_CALLBACK_DEL, _win32_sel_obj_del, sel);
+
+   ELM_SAFE_FREE(sel->selbuf, free);
+   if (selbuf)
+     {
+        if (format == ELM_SEL_FORMAT_IMAGE)
+          {
+             // 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
+          sel->selbuf = strdup((char*)selbuf);
+     }
+
+   return EINA_TRUE;
+}
+
+static void
+_win32_elm_cnp_selection_loss_callback_set(Evas_Object *obj EINA_UNUSED, Elm_Sel_Type selection, Elm_Selection_Loss_Cb func, const void *data)
+{
+   Win32_Cnp_Selection *sel;
+
+   if (selection != ELM_SEL_TYPE_CLIPBOARD)
+     return;
+
+   _win32_elm_cnp_init();
+   sel = _win32_selections + selection;
+   sel->loss_cb = func;
+   sel->loss_data = (void *)data;
+}
+
+static Eina_Bool
+_win32_elm_object_cnp_selection_clear(Ecore_Win32_Window *win, Evas_Object *obj, Elm_Sel_Type selection)
+{
+   Win32_Cnp_Selection *sel;
+
+   if (selection != ELM_SEL_TYPE_CLIPBOARD)
+     return EINA_FALSE;
+
+   _win32_elm_cnp_init();
+
+   sel = _win32_selections + selection;
+
+   /* No longer this selection: Consider it gone! */
+   if ((!sel->active) || (sel->widget != obj))
+     return EINA_TRUE;
+
+   if (sel->widget)
+     evas_object_event_callback_del_full(sel->widget, EVAS_CALLBACK_DEL,
+                                         _win32_sel_obj_del, sel);
+   if (sel->requestwidget)
+     evas_object_event_callback_del_full(sel->requestwidget, EVAS_CALLBACK_DEL,
+                                         _win32_sel_obj_del2, sel);
+   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->clear(win); */
+
+   return EINA_TRUE;
+}
+
+static Eina_Bool
+_win32_elm_cnp_selection_get(Ecore_Win32_Window *win,
+                             const Evas_Object *obj,
+                             Elm_Sel_Type selection,
+                             Elm_Sel_Format format,
+                             Elm_Drop_Cb datacb,
+                             void *udata)
+{
+   Win32_Cnp_Selection *sel;
+   void *data;
+   int size;
+
+   if (selection != ELM_SEL_TYPE_CLIPBOARD)
+     return EINA_FALSE;
+
+   _win32_elm_cnp_init();
+
+   sel = _win32_selections + selection;
+
+   if (sel->requestwidget)
+     evas_object_event_callback_del_full(sel->requestwidget, EVAS_CALLBACK_DEL,
+                                         _win32_sel_obj_del2, sel);
+   sel->requestformat = format;
+   sel->requestwidget = (Evas_Object *)obj;
+   sel->win = win;
+   sel->get(win, &data, &size);
+   sel->datacb = datacb;
+   sel->udata = udata;
+
+   if (!data || (size <= 0))
+     goto cb_add;
+
+   if ((sel->format & ELM_SEL_FORMAT_MARKUP) ||
+       (sel->format & ELM_SEL_FORMAT_HTML))
+     {
+        char *str;
+
+        str = (char *)malloc(size + 1);
+        if (str)
+          {
+             memcpy(str, data, size);
+             str[size] = '\0';
+             data = _elm_util_mkup_to_text(str);
+             free(str);
+             if (data)
+               size = strlen(data);
+             else
+               size = 0;
+          }
+        else
+          {
+             free(data);
+             data = NULL;
+          }
+     }
+
+   if (sel->datacb && data && (size > 0))
+     {
+        Elm_Selection_Data sdata;
+
+        sdata.x = sdata.y = 0;
+        sdata.format = ELM_SEL_FORMAT_TEXT;
+        sdata.data = data;
+        sdata.len = size;
+        sdata.action = sel->action;
+        sel->datacb(sel->udata, sel->requestwidget, &sdata);
+     }
+
+   if (data)
+     free(data);
+
+ cb_add:
+   evas_object_event_callback_add
+     (sel->requestwidget, EVAS_CALLBACK_DEL, _win32_sel_obj_del2, sel);
+
+   return EINA_TRUE;
+}
+
+#endif /* HAVE_ELEMENTARY_WIN32 */
+
 // common internal funcs
 ////////////////////////////////////////////////////////////////////////////
 static Eina_Bool
@@ -5009,6 +5323,13 @@ elm_cnp_selection_set(Evas_Object *obj, Elm_Sel_Type selection,
    if (win)
      return _cocoa_elm_cnp_selection_set(win, obj, selection, format, selbuf, buflen);
 #endif
+#ifdef HAVE_ELEMENTARY_WIN32
+   Ecore_Win32_Window *win;
+
+   win = _win32_elm_widget_window_get(obj);
+   if (win)
+     return _win32_elm_cnp_selection_set(win, obj, selection, format, selbuf, buflen);
+#endif
    return _local_elm_cnp_selection_set(obj, selection, format, selbuf, buflen);
 }
 
@@ -5031,6 +5352,10 @@ elm_cnp_selection_loss_callback_set(Evas_Object *obj, Elm_Sel_Type selection,
    if (_cocoa_elm_widget_cocoa_window_get(obj))
      _cocoa_elm_cnp_selection_loss_callback_set(obj, selection, func, data);
 #endif
+#ifdef HAVE_ELEMENTARY_WIN32
+   if (_win32_elm_widget_window_get(obj))
+     _win32_elm_cnp_selection_loss_callback_set(obj, selection, func, data);
+#endif
    _local_elm_cnp_selection_loss_callback_set(obj, selection, func, data);
 }
 
@@ -5051,6 +5376,13 @@ elm_object_cnp_selection_clear(Evas_Object *obj, Elm_Sel_Type selection)
    if (_cocoa_elm_widget_cocoa_window_get(obj))
      return _cocoa_elm_cnp_selection_clear(obj, selection);
 #endif
+#ifdef HAVE_ELEMENTARY_WIN32
+   Ecore_Win32_Window *win;
+
+   win = _win32_elm_widget_window_get(obj);
+   if (win)
+     return _win32_elm_object_cnp_selection_clear(win, obj, selection);
+#endif
    return _local_elm_object_cnp_selection_clear(obj, selection);
 }
 
@@ -5074,6 +5406,13 @@ elm_cnp_selection_get(const Evas_Object *obj, Elm_Sel_Type selection,
    if (win)
      return _cocoa_elm_cnp_selection_get(obj, win, selection, format, datacb, udata);
 #endif
+#ifdef HAVE_ELEMENTARY_WIN32
+   Ecore_Win32_Window *win;
+
+   win = _win32_elm_widget_window_get(obj);
+   if (win)
+     return _win32_elm_cnp_selection_get(win, obj, selection, format, datacb, udata);
+#endif
    return _local_elm_cnp_selection_get(obj, selection, format, datacb, udata);
 }
 
index 75b004a..192f550 100644 (file)
@@ -3764,7 +3764,7 @@ _elm_config_file_monitor_cb(void *data EINA_UNUSED,
 void
 _elm_config_sub_init(void)
 {
-#if defined(HAVE_ELEMENTARY_X) || defined(HAVE_ELEMENTARY_WAYLAND)
+#if defined(HAVE_ELEMENTARY_X) || defined(HAVE_ELEMENTARY_WAYLAND) || defined(HAVE_ELEMENTARY_WIN32)
    const char *ev = getenv("ELM_DISPLAY");
 #endif
 
@@ -3830,6 +3830,9 @@ _elm_config_sub_init(void)
         ecore_wl_init(NULL);
      }
 #endif
+#ifdef HAVE_ELEMENTARY_WIN32
+   ecore_win32_init();
+#endif
    char buf[PATH_MAX];
    int ok = 0;
 
index 5c71c35..f04d8ba 100644 (file)
@@ -20,6 +20,9 @@
 #endif
 # include <Ecore_Cocoa.h>
 #endif
+#ifdef HAVE_ELEMENTARY_WIN32
+#include <Ecore_Win32.h>
+#endif
 
 #include <Eio.h>
 
index 6706554..087a4c3 100644 (file)
@@ -127,6 +127,12 @@ struct _Elm_Win_Data
       Ecore_Cocoa_Window *win;
    } cocoa;
 #endif
+#ifdef HAVE_ELEMENTARY_WIN32
+   struct
+   {
+      Ecore_Win32_Window *win;
+   } win32;
+#endif
 
    Ecore_Job                     *deferred_resize_job;
    Ecore_Job                     *deferred_child_eval_job;
@@ -2551,6 +2557,28 @@ _elm_ee_cocoa_win_get(const Ecore_Evas *ee)
    engine_name = ecore_evas_engine_name_get(ee);
    if (EINA_UNLIKELY(!engine_name)) return NULL;
 
+   if ((!strcmp(engine_name, ELM_SOFTWARE_WIN32)) ||
+       (!strcmp(engine_name, ELM_SOFTWARE_DDRAW)))
+     {
+        return ecore_evas_win32_window_get(ee);
+     }
+#else
+   (void)ee;
+#endif
+   return NULL;
+}
+
+Ecore_Win32_Window *
+_elm_ee_win32win_get(const Ecore_Evas *ee)
+{
+#ifdef HAVE_ELEMENTARY_WIN32
+   const char *engine_name;
+
+   if (!ee) return NULL;
+
+   engine_name = ecore_evas_engine_name_get(ee);
+   if (EINA_UNLIKELY(!engine_name)) return NULL;
+
    if (!strcmp(engine_name, "opengl_cocoa") ||
        !strcmp(engine_name, "gl_cocoa"))
      return ecore_evas_cocoa_window_get(ee);
@@ -2568,6 +2596,14 @@ _elm_win_cocoawindow_get(Elm_Win_Data *sd)
 }
 #endif
 
+#ifdef HAVE_ELEMENTARY_WIN32
+static void
+_internal_elm_win_win32window_get(Elm_Win_Data *sd)
+{
+   sd->win32.win = _elm_ee_win32win_get(sd->ee);
+}
+#endif
+
 #ifdef HAVE_ELEMENTARY_X
 static void
 _elm_win_xwin_update(Elm_Win_Data *sd)
@@ -4346,6 +4382,9 @@ _elm_win_finalize_internal(Eo *obj, Elm_Win_Data *sd, const char *name, Elm_Win_
 #ifdef HAVE_ELEMENTARY_COCOA
    _elm_win_cocoawindow_get(sd);
 #endif
+#ifdef HAVE_ELEMENTARY_WIN32
+   _internal_elm_win_win32window_get(sd);
+#endif
 
    if ((_elm_config->bgpixmap)
 #ifdef HAVE_ELEMENTARY_X
@@ -6230,6 +6269,41 @@ _elm_win_wl_window_get(Eo *obj EINA_UNUSED, Elm_Win_Data *sd)
    return NULL;
 }
 
+EAPI Ecore_Win32_Window *
+elm_win_win32_window_get(const Evas_Object *obj)
+{
+   ELM_WIN_CHECK(obj) NULL;
+   ELM_WIN_DATA_GET_OR_RETURN_VAL(obj, sd, NULL);
+   const char *engine_name = ecore_evas_engine_name_get(sd->ee);
+
+   if (!(engine_name &&
+         ((!strcmp(engine_name, ELM_SOFTWARE_WIN32)) ||
+          (!strcmp(engine_name, ELM_SOFTWARE_DDRAW)))))
+     return NULL;
+
+   if (!evas_object_smart_type_check_ptr(obj, MY_CLASS_NAME_LEGACY))
+     {
+        Ecore_Evas *ee = ecore_evas_ecore_evas_get(evas_object_evas_get(obj));
+        return _elm_ee_win32win_get(ee);
+     }
+
+   Ecore_Win32_Window *ret = NULL;
+   eo_do((Eo *) obj, ret = elm_obj_win_win32_window_get());
+   return ret;
+}
+
+EOLIAN static Ecore_Win32_Window *
+_elm_win_win32_window_get(Eo *obj EINA_UNUSED, Elm_Win_Data *sd)
+{
+#if HAVE_ELEMENTARY_WIN32
+   if (sd->win32.win) return sd->win32.win;
+   if (sd->parent) return elm_win_win32_window_get(sd->parent);
+#else
+   (void)sd;
+#endif
+   return NULL;
+}
+
 EAPI Eina_Bool
 elm_win_trap_set(const Elm_Win_Trap *t)
 {
@@ -6353,6 +6427,16 @@ _elm_win_window_id_get(Eo *obj EINA_UNUSED, Elm_Win_Data *sd)
           }
 #endif
      }
+   else if ((engine_name &&
+             ((!strcmp(engine_name, ELM_SOFTWARE_WIN32)) ||
+              (!strcmp(engine_name, ELM_SOFTWARE_DDRAW)))))
+     {
+#ifdef HAVE_ELEMENTARY_WIN32
+        _internal_elm_win_win32window_get(sd);
+        if (sd->win32.win) return (Ecore_Window)sd->win32.win;
+        if (sd->parent) return (Ecore_Window)elm_win_win32_window_get(sd->parent);
+#endif
+     }
 
    return 0;
 }
index 1881ae7..d0219c6 100644 (file)
@@ -996,6 +996,16 @@ class Elm.Win (Elm.Widget, Elm_Interface_Atspi_Window,
          get {
             [[Get the Ecore_Cocoa_Window of an Evas.Object.]]
             return: Ecore_Cocoa_Window *; [[The Ecore_Cocoa_Window of $obj.]]
+        }
+      }
+      @property win32_window {
+         get {
+            [[Get the Ecore_Win32_Window of an Evas_Object
+
+              @since 1.16
+            ]]
+            return: Ecore_Win32_Window *; [[The Ecore_Win32_Window of $obj.]]
+            legacy: null;
          }
       }
       @property window_id {
index 091d1cc..60040fb 100644 (file)
@@ -197,6 +197,23 @@ EAPI void                  elm_win_render(Evas_Object *obj);
  */
 EAPI Ecore_Wl_Window *elm_win_wl_window_get(const Evas_Object *obj);
 
+/* Windows specific call - returns NULL on non-Windows engines */
+/**
+ * Get the Ecore_Win32_Window of an Evas_Object
+ *
+ * Do not use this function if you'd like your application/library be portable.
+ * You have been warned.
+ *
+ * @param obj the object
+ *
+ * @return The Ecore_Win32_Window of @p obj
+ *
+ * @ingroup Win
+ *
+ * @since 1.16
+ */
+EAPI Ecore_Win32_Window *elm_win_win32_window_get(const Evas_Object *obj);
+
 /**
  * Set the preferred rotation value.
  *