offer->source->target(offer->source, serial, mime_type);
}
+static Eina_Bool
+_e_comp_wl_dnd_offer_mediate(void *data, Ecore_Fd_Handler *handler)
+{
+ E_Comp_Wl_Data_Offer *offer;
+ char *p;
+ int read_len = 0, write_len = 0;
+ int source_fd = -1;
+
+ if (!(offer = (E_Comp_Wl_Data_Offer*)data))
+ return ECORE_CALLBACK_CANCEL;
+
+ source_fd = ecore_main_fd_handler_fd_get(handler);
+ if (source_fd < 0) goto cleanup;
+ if (offer->fd < 0) goto cleanup;
+
+ p = (char *)calloc(sizeof(char), CLIPBOARD_CHUNK);
+
+ while ((read_len = read(source_fd, p, CLIPBOARD_CHUNK)) > 0)
+ {
+ write_len = write(offer->fd, p, read_len);
+ if (read_len != write_len)
+ {
+ ERR("IO error in _e_comp_wl_dnd_offer_mediate");
+ break;
+ }
+ }
+
+cleanup:
+ if (offer->fd > 0)
+ {
+ close(offer->fd);
+ offer->fd = 0;
+ }
+ if (source_fd > 0) close(source_fd);
+ if (handler != NULL) ecore_main_fd_handler_del(handler);
+ if (p) free(p);
+
+ return ECORE_CALLBACK_DONE;
+}
+
+static int
+_e_comp_wl_dnd_offer_mediator_init(E_Comp_Wl_Data_Offer* offer, int fd)
+{
+ EINA_SAFETY_ON_NULL_RETURN_VAL(offer, -1);
+
+ if (pipe2(offer->source->fd, O_CLOEXEC|O_DIRECT|O_NONBLOCK) == -1)
+ {
+ ERR("Could not create unidirectional pipe for dnd: %m");
+ return -1;
+ }
+
+ offer->fd = fd;
+ offer->source->fd_handler =
+ ecore_main_fd_handler_add(offer->source->fd[0], ECORE_FD_READ,
+ _e_comp_wl_dnd_offer_mediate, offer,
+ NULL, NULL);
+
+ DBG("_e_comp_wl_dnd_offer_mediate:: init mediator, offer_fd: %d / source_fd: %d, %d", fd, offer->source->fd[0], offer->source->fd[1]);
+ return offer->source->fd[1];
+}
+
static void
_e_comp_wl_data_offer_cb_receive(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, const char *mime_type, int32_t fd)
{
E_Comp_Wl_Data_Offer *offer;
+ int new_fd;
DBG("Data Offer Receive FD:%d", fd);
if (!(offer = wl_resource_get_user_data(resource)))
- return;
+ {
+ close(fd);
+ return;
+ }
- if (offer->source)
- offer->source->send(offer->source, mime_type, fd);
+ new_fd = _e_comp_wl_dnd_offer_mediator_init(offer, fd);
+ if (new_fd < 0)
+ {
+ DBG("_e_comp_wl_dnd_offer_mediator_init failed, close fd:%d", fd);
+ close(fd);
+ return;
+ }
- close(fd);
+ if (offer->source)
+ offer->source->send(offer->source, mime_type, new_fd);
+ close(new_fd);
}
/* called by wl_data_offer_destroy */
if (offer->source)
{
wl_list_remove(&offer->source_destroy_listener.link);
+ ecore_main_fd_handler_del(offer->source->fd_handler);
if (offer->dropped && offer->source != e_comp_wl->drag_source)
_e_comp_wl_data_source_cancelled_send(offer->source);
}