e_comp_wl_data: add manual selection API to send internal data to cbhm 00/118700/7
authorMinJeong Kim <minjjj.kim@samsung.com>
Mon, 13 Mar 2017 15:54:50 +0000 (00:54 +0900)
committerMinJeong Kim <minjjj.kim@samsung.com>
Tue, 14 Mar 2017 01:44:11 +0000 (10:44 +0900)
Change-Id: Iaf49a8c1123c5efeb20deba1d2d3d9b19374775e
Signed-off-by: MinJeong Kim <minjjj.kim@samsung.com>
src/bin/e_comp_wl_data.c
src/bin/e_comp_wl_data.h

index 3ce1c4d1b8e40efac386d8ff8212107aacbe4ed3..1b947104a4e9cc19b29bb37291078ee60cec5fff 100644 (file)
@@ -274,10 +274,10 @@ _e_comp_wl_data_device_selection_set(void *data EINA_UNUSED, E_Comp_Wl_Data_Sour
 
    if (sel_source)
      {
-        if (sel_source->cancelled)
-          sel_source->cancelled(sel_source);
         if (!e_comp_wl->clipboard.xwl_owner)
           wl_list_remove(&e_comp_wl->selection.data_source_listener.link);
+        if (sel_source->cancelled)
+          sel_source->cancelled(sel_source);
         e_comp_wl->selection.data_source = NULL;
      }
 
@@ -807,7 +807,7 @@ e_comp_wl_data_device_keyboard_focus_set(void)
       eina_list_remove(e_comp_wl->selection.data_only_list,
                        data_device_res);
 
-   if (source)
+   if (source && !source->is_manual)
      {
         offer_res =
            _e_comp_wl_data_device_data_offer_create(source, data_device_res);
@@ -994,7 +994,7 @@ e_comp_wl_data_device_only_set(struct wl_resource *data_device_res, Eina_Bool se
            eina_list_append(e_comp_wl->selection.data_only_list, data_device_res);
 
         source = (E_Comp_Wl_Data_Source *)e_comp_wl->selection.data_source;
-        if (source)
+        if (source && !source->is_manual)
           {
              offer_res =
                 _e_comp_wl_data_device_data_offer_create(source, data_device_res);
@@ -1015,3 +1015,193 @@ e_comp_wl_data_device_only_set(struct wl_resource *data_device_res, Eina_Bool se
      }
 }
 
+static void
+_e_comp_wl_data_device_destroy_manual_source(struct wl_listener *listener EINA_UNUSED, void *data EINA_UNUSED)
+{
+  struct wl_resource *data_device_res = NULL;
+  struct wl_client *cbhm_client = NULL;
+
+  e_comp_wl->selection.data_source = NULL;
+
+  if (e_comp_wl->selection.cbhm)
+     cbhm_client =  wl_resource_get_client(e_comp_wl->selection.cbhm);
+
+   if (cbhm_client)
+     {
+        data_device_res =
+           e_comp_wl_data_find_for_client(cbhm_client);
+
+        if (data_device_res)
+          wl_data_device_send_selection(data_device_res, NULL);
+     }
+}
+
+static int
+_e_comp_wl_manual_source_ref(E_Comp_Wl_Manual_Data_Source *source)
+{
+   source->ref ++;
+   return source->ref;
+}
+
+static int
+_e_comp_wl_manual_source_unref(E_Comp_Wl_Manual_Data_Source *source)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(source, 0);
+   source->ref --;
+   if (source->ref > 0)
+     return source->ref;
+
+   _mime_types_free(&source->data_source);
+
+   wl_signal_emit(&source->data_source.destroy_signal, &source->data_source);
+   wl_array_release(&source->contents);
+   free(source);
+
+   return 0;
+}
+
+static void
+_e_comp_wl_manual_offer_load(E_Comp_Wl_Manual_Data_Source *source, int fd)
+{
+   char *p;
+   size_t size;
+   int len;
+   int offset = 0;
+
+   size = source->contents.size;
+   p = (char *)source->contents.data;
+   len = write(fd, p, size);
+   if (len > 0) offset += len;
+   else if (len == -1)
+     ERR("could not write for fd(%d) :%m", fd);
+
+   if ((offset == size) || (len <= 0))
+     {
+        _e_comp_wl_manual_source_unref(source);
+     }
+}
+
+static void
+_e_comp_wl_manual_source_target_send(E_Comp_Wl_Data_Source *source EINA_UNUSED, uint32_t serial EINA_UNUSED, const char *mime_type EINA_UNUSED)
+{
+}
+
+static void
+_e_comp_wl_manual_source_send_send(E_Comp_Wl_Data_Source *source, const char *mime_type, int fd)
+{
+   E_Comp_Wl_Manual_Data_Source *man_source;
+
+   man_source = container_of(source, E_Comp_Wl_Manual_Data_Source, data_source);
+   if (!man_source) return;
+
+   _e_comp_wl_manual_offer_load(man_source, fd);
+   close(fd);
+}
+
+static void
+_e_comp_wl_manual_source_cancelled_send(E_Comp_Wl_Data_Source *source EINA_UNUSED)
+{
+   E_Comp_Wl_Manual_Data_Source *man_source;
+
+   man_source = container_of(source, E_Comp_Wl_Manual_Data_Source, data_source);
+   if (!man_source) return;
+
+   _e_comp_wl_manual_source_unref(man_source);
+}
+
+static void
+_e_comp_wl_data_device_manual_selection_set(E_Comp_Wl_Data_Source *source, uint32_t serial)
+{
+   E_Comp_Wl_Data_Source *sel_source;
+   struct wl_resource *offer_res, *data_device_res;
+   struct wl_client *cbhm_client = NULL;
+
+   sel_source = (E_Comp_Wl_Data_Source*)e_comp_wl->selection.data_source;
+
+   if (e_comp_wl->selection.cbhm)
+     cbhm_client = wl_resource_get_client(e_comp_wl->selection.cbhm);
+
+   if (sel_source)
+     {
+        if (!e_comp_wl->clipboard.xwl_owner)
+          wl_list_remove(&e_comp_wl->selection.data_source_listener.link);
+        if (sel_source->cancelled)
+          sel_source->cancelled(sel_source);
+        e_comp_wl->selection.data_source = NULL;
+     }
+
+   e_comp_wl->selection.data_source = sel_source = source;
+   e_comp_wl->clipboard.xwl_owner = NULL;
+   e_comp_wl->selection.serial = serial;
+
+   if (cbhm_client)
+     {
+        data_device_res =
+           e_comp_wl_data_find_for_client(cbhm_client);
+        if ((data_device_res) && (source))
+          {
+             offer_res =
+                _e_comp_wl_data_device_data_offer_create(source,
+                                                         data_device_res);
+             wl_data_device_send_selection(data_device_res, offer_res);
+          }
+     }
+
+   //do not notify to internal clipboard
+   //wl_signal_emit(&e_comp_wl->selection.signal, e_comp->wl_comp_data);
+
+   if (source)
+     {
+        e_comp_wl->selection.data_source_listener.notify =
+           _e_comp_wl_data_device_destroy_manual_source;
+        wl_signal_add(&source->destroy_signal,
+                      &e_comp_wl->selection.data_source_listener);
+     }
+}
+
+E_API Eina_Bool
+e_comp_wl_data_device_manual_selection_set(void *data, size_t size, Eina_List *mime_list)
+{
+   E_Comp_Wl_Manual_Data_Source *man_source;
+   Eina_List *l;
+   const char *t;
+
+   if ((size <= 0) || (!data) || (!mime_list)) return EINA_FALSE;
+
+   man_source = E_NEW(E_Comp_Wl_Manual_Data_Source, 1);
+   if (!man_source) return EINA_FALSE;
+
+   man_source->data_source.resource = NULL;
+   man_source->data_source.target = _e_comp_wl_manual_source_target_send;
+   man_source->data_source.send = _e_comp_wl_manual_source_send_send;
+   man_source->data_source.cancelled = _e_comp_wl_manual_source_cancelled_send;
+   man_source->data_source.is_manual = EINA_TRUE;
+
+   wl_array_init(&man_source->contents);
+   wl_signal_init(&man_source->data_source.destroy_signal);
+
+   man_source->serial = e_comp_wl->selection.serial;
+
+   if (!man_source->data_source.mime_types)
+     man_source->data_source.mime_types = eina_array_new(64);
+
+   if (man_source->data_source.mime_types == NULL)
+     {
+        wl_array_release(&man_source->contents);
+        E_FREE(man_source);
+        return EINA_FALSE;
+     }
+
+   EINA_LIST_FOREACH(mime_list, l, t)
+      eina_array_push(man_source->data_source.mime_types, eina_stringshare_add(t));
+
+   if (man_source->contents.alloc < size)
+     wl_array_add(&man_source->contents, size);
+   man_source->contents.size += size;
+   memcpy(man_source->contents.data, data, size);
+
+   _e_comp_wl_manual_source_ref(man_source);
+   _e_comp_wl_data_device_manual_selection_set(&man_source->data_source, man_source->serial);
+   return EINA_TRUE;
+}
+
index 354870252a0d1ab29cf9762345b04c039eed36d2..174cb1e4b33718aac28d60f5e4e9567ee8c18698 100644 (file)
@@ -15,6 +15,8 @@ typedef struct _E_Comp_Wl_Data_Source E_Comp_Wl_Data_Source;
 typedef struct _E_Comp_Wl_Data_Offer E_Comp_Wl_Data_Offer;
 typedef struct _E_Comp_Wl_Clipboard_Source E_Comp_Wl_Clipboard_Source;
 typedef struct _E_Comp_Wl_Clipboard_Offer E_Comp_Wl_Clipboard_Offer;
+typedef struct _E_Comp_Wl_Manual_Data_Source E_Comp_Wl_Manual_Data_Source;
+typedef struct _E_Comp_Wl_Manual_Data_Offer E_Comp_Wl_Manual_Data_Offer;
 
 struct _E_Comp_Wl_Data_Source
 {
@@ -26,6 +28,8 @@ struct _E_Comp_Wl_Data_Source
    void (*target) (E_Comp_Wl_Data_Source *source, uint32_t serial, const char* mime_type);
    void (*send) (E_Comp_Wl_Data_Source *source, const char* mime_type, int32_t fd);
    void (*cancelled) (E_Comp_Wl_Data_Source *source);
+
+   Eina_Bool is_manual;
 };
 
 struct _E_Comp_Wl_Data_Offer
@@ -54,6 +58,22 @@ struct _E_Comp_Wl_Clipboard_Offer
    size_t offset;
 };
 
+struct _E_Comp_Wl_Manual_Data_Source
+{
+    E_Comp_Wl_Data_Source data_source;
+    uint32_t serial;
+
+    struct wl_array contents;
+    int ref;
+};
+
+struct _E_Comp_Wl_Manual_Data_Offer
+{
+    E_Comp_Wl_Manual_Data_Source *source;
+    Ecore_Fd_Handler *fd_handler;
+    size_t offset;
+};
+
 E_API void e_comp_wl_data_device_send_enter(E_Client *ec);
 E_API void e_comp_wl_data_device_send_leave(E_Client *ec);
 EINTERN void *e_comp_wl_data_device_send_offer(E_Client *ec);
@@ -66,5 +86,6 @@ E_API int e_comp_wl_clipboard_source_ref(E_Comp_Wl_Clipboard_Source *source);
 E_API int e_comp_wl_clipboard_source_unref(E_Comp_Wl_Clipboard_Source *source);
 E_API E_Comp_Wl_Clipboard_Source *e_comp_wl_clipboard_source_create(const char *mime_type, uint32_t serial, int *fd);
 E_API void e_comp_wl_data_device_only_set(struct wl_resource *data_device_res, Eina_Bool set);
+E_API Eina_Bool e_comp_wl_data_device_manual_selection_set(void *data, size_t size, Eina_List *mime_list);
 # endif
 #endif