discomfitor pushed a commit to branch master.

http://git.enlightenment.org/core/enlightenment.git/commit/?id=5bde1a864838d9c86cf5cf59564e3efaf1389393

commit 5bde1a864838d9c86cf5cf59564e3efaf1389393
Author: Mike Blumenkrantz <zm...@osg.samsung.com>
Date:   Thu Aug 6 19:26:08 2015 -0400

    implement x11->wayland dnd operations
    
    still a little rough, but the basics are functional. works by showing
    the x11 compositor selection window, which has rects to exclude geometries
    of xwl clients, for getting x11 xdnd events, and then manually sending
    all the related client messages in order to inform the x11 client that
    enlightenment is, in fact, an extremely credible xdnd drop site and not
    a rogue compositor which will mangle/destroy the dnd data.
    
    still render crashes after the operation completes, so possibly not the
    most useful thing to be using now
---
 src/bin/e_comp_wl_data.c          |  35 ++++++-
 src/bin/e_dnd.c                   |  15 +++
 src/modules/Makefile_xwayland.mk  |   3 +-
 src/modules/xwayland/dnd.c        | 202 ++++++++++++++++++++++++++++++++++++++
 src/modules/xwayland/e_mod_main.c |   3 +
 5 files changed, 256 insertions(+), 2 deletions(-)

diff --git a/src/bin/e_comp_wl_data.c b/src/bin/e_comp_wl_data.c
index 11d5c78..d42fb0c 100644
--- a/src/bin/e_comp_wl_data.c
+++ b/src/bin/e_comp_wl_data.c
@@ -685,6 +685,30 @@ e_comp_wl_data_device_send_enter(E_Client *ec)
    e_comp->wl_comp_data->selection.target = ec;
    evas_object_event_callback_add(ec->frame, EVAS_CALLBACK_DEL, 
_e_comp_wl_data_device_target_del, ec);
 
+#ifndef HAVE_WAYLAND_ONLY
+   if (e_client_has_xwindow(e_comp->wl_comp_data->drag_client))
+     {
+        int d1 = 0x5UL, d2, d3, d4;
+
+        d2 = d3 = d4 = 0;
+
+        if (e_comp->wl_comp_data->drag->num_types > 3)
+          d1 |= 0x1UL;
+        else
+          {
+             if (e_comp->wl_comp_data->drag->num_types > 0)
+               d2 = ecore_x_atom_get(e_comp->wl_comp_data->drag->types[0]);
+             if (e_comp->wl_comp_data->drag->num_types > 1)
+               d3 = ecore_x_atom_get(e_comp->wl_comp_data->drag->types[1]);
+             if (e_comp->wl_comp_data->drag->num_types > 2)
+               d4 = ecore_x_atom_get(e_comp->wl_comp_data->drag->types[2]);
+          }
+
+        
ecore_x_client_message32_send(e_client_util_win_get(e_comp->wl_comp_data->drag_client),
+          ECORE_X_ATOM_XDND_ENTER, ECORE_X_EVENT_MASK_NONE,
+          e_comp->cm_selection, d1, d2, d3, d4);
+     }
+#endif
    x = wl_fixed_to_int(e_comp->wl_comp_data->ptr.x) - 
e_comp->wl_comp_data->selection.target->client.x;
    y = wl_fixed_to_int(e_comp->wl_comp_data->ptr.y) - 
e_comp->wl_comp_data->selection.target->client.y;
    serial = wl_display_next_serial(e_comp->wl_comp_data->wl.disp);
@@ -701,8 +725,17 @@ e_comp_wl_data_device_send_leave(E_Client *ec)
    evas_object_event_callback_del_full(ec->frame, EVAS_CALLBACK_DEL, 
_e_comp_wl_data_device_target_del, ec);
    if (e_comp->wl_comp_data->selection.target == ec)
      e_comp->wl_comp_data->selection.target = NULL;
+#ifndef HAVE_WAYLAND_ONLY
+   if (e_client_has_xwindow(e_comp->wl_comp_data->drag_client))
+     {
+        
ecore_x_client_message32_send(e_client_util_win_get(e_comp->wl_comp_data->drag_client),
+               ECORE_X_ATOM_XDND_LEAVE, ECORE_X_EVENT_MASK_NONE,
+               e_comp->cm_selection, 0, 0, 0, 0);
+     }
+#endif
    res = 
e_comp_wl_data_find_for_client(wl_resource_get_client(ec->comp_data->surface));
-   wl_data_device_send_leave(res);
+   if (res)
+     wl_data_device_send_leave(res);
 }
 
 EINTERN void *
diff --git a/src/bin/e_dnd.c b/src/bin/e_dnd.c
index a8f5d69..167515e 100644
--- a/src/bin/e_dnd.c
+++ b/src/bin/e_dnd.c
@@ -227,6 +227,8 @@ e_dnd_init(void)
 
    if (e_comp->comp_type == E_PIXMAP_TYPE_X)
      e_drop_xdnd_register_set(e_comp->ee_win, 1);
+   else
+     e_drop_xdnd_register_set(e_comp->cm_selection, 1);
 
    _action = ECORE_X_ATOM_XDND_ACTION_PRIVATE;
 #endif
@@ -1211,6 +1213,18 @@ _e_dnd_cb_mouse_move(void *data EINA_UNUSED, int type 
EINA_UNUSED, void *event)
    if (!_xdnd)
      _e_drag_update(_drag_win_root, ev->x, ev->y,
                     _action ?: ECORE_X_ATOM_XDND_ACTION_PRIVATE);
+# ifdef HAVE_WAYLAND
+   if ((e_comp->comp_type == E_PIXMAP_TYPE_WL) && e_comp_util_has_x())
+     {
+        if (e_comp->wl_comp_data->drag != _drag_current) return 
ECORE_CALLBACK_RENEW;
+        if (!e_comp->wl_comp_data->ptr.ec) return ECORE_CALLBACK_RENEW;
+        if (e_client_has_xwindow(e_comp->wl_comp_data->ptr.ec)) return 
ECORE_CALLBACK_RENEW;
+        
ecore_x_client_message32_send(e_client_util_win_get(e_comp->wl_comp_data->drag_client),
+          ECORE_X_ATOM_XDND_POSITION, ECORE_X_EVENT_MASK_NONE,
+          e_comp->cm_selection, 0, ((ev->x << 16) & 0xffff0000) | (ev->y & 
0xffff),
+          ev->timestamp, ECORE_X_ATOM_XDND_ACTION_COPY);
+     }
+# endif
 #endif
 
    return ECORE_CALLBACK_PASS_ON;
@@ -1421,6 +1435,7 @@ _e_dnd_cb_event_dnd_selection(void *data EINA_UNUSED, int 
type EINA_UNUSED, void
 
    if (!eina_hash_find(_drop_win_hash, &ev->win)) return 
ECORE_CALLBACK_PASS_ON;
    if (ev->selection != ECORE_X_SELECTION_XDND) return ECORE_CALLBACK_PASS_ON;
+   if (e_comp->comp_type != E_PIXMAP_TYPE_X) return ECORE_CALLBACK_RENEW;
 
    if (!_xdnd)
      {
diff --git a/src/modules/Makefile_xwayland.mk b/src/modules/Makefile_xwayland.mk
index 5afc15b..56fd137 100644
--- a/src/modules/Makefile_xwayland.mk
+++ b/src/modules/Makefile_xwayland.mk
@@ -13,7 +13,8 @@ src_modules_xwayland_module_la_LIBADD   = $(MOD_LIBS) 
@XWAYLAND_LIBS@ @WAYLAND_L
 src_modules_xwayland_module_la_LDFLAGS = $(MOD_LDFLAGS)
 
 src_modules_xwayland_module_la_SOURCES = \
-src/modules/xwayland/e_mod_main.c
+src/modules/xwayland/e_mod_main.c \
+src/modules/xwayland/dnd.c
 
 PHONIES += xwayland install-xwayland
 xwayland: $(xwaylandpkg_LTLIBRARIES)
diff --git a/src/modules/xwayland/dnd.c b/src/modules/xwayland/dnd.c
new file mode 100644
index 0000000..69ae9b5
--- /dev/null
+++ b/src/modules/xwayland/dnd.c
@@ -0,0 +1,202 @@
+#define E_COMP_WL
+#include "e.h"
+#include <dlfcn.h>
+
+#define WL_TEXT_STR "text/plain;charset=utf-8"
+
+static void (*xconvertselection)(Ecore_X_Display *, Ecore_X_Atom, 
Ecore_X_Atom, Ecore_X_Atom, Ecore_X_Window, Ecore_X_Time);
+static Ecore_X_Atom string_atom;
+static Ecore_X_Atom xwl_dnd_atom;
+
+static int32_t cur_fd = -1;
+
+static void
+_xdnd_finish(Eina_Bool success)
+{
+   
ecore_x_client_message32_send(e_client_util_win_get(e_comp->wl_comp_data->drag_client),
 ECORE_X_ATOM_XDND_FINISHED, ECORE_X_EVENT_MASK_NONE,
+     e_comp->cm_selection, !!success, (!!success) * 
ECORE_X_ATOM_XDND_ACTION_COPY, 0, 0);
+}
+
+static void
+_xwayland_dnd_finish(void)
+{
+   ecore_x_window_hide(e_comp->cm_selection);
+   ecore_x_window_prop_property_del(e_comp->cm_selection, 
ECORE_X_ATOM_XDND_TYPE_LIST);
+   e_comp->wl_comp_data->drag_client = NULL;
+   e_comp->wl_comp_data->drag_source = NULL;
+   cur_fd = -1;
+}
+
+static void
+_xwayland_drop(E_Drag *drag, int dropped)
+{
+   if (e_comp->comp_type != E_PIXMAP_TYPE_WL) return;
+   e_comp->wl_comp_data->drag = NULL;
+   if (e_object_is_del(E_OBJECT(drag)) || 
(!e_comp->wl_comp_data->selection.target))
+     _xdnd_finish(0);
+   else
+     {
+        struct wl_resource *res;
+
+        res = 
e_comp_wl_data_find_for_client(wl_resource_get_client(e_comp->wl_comp_data->selection.target->comp_data->surface));
+        if (res)
+          {
+             wl_data_device_send_drop(res);
+             wl_data_device_send_leave(res);
+             
ecore_x_client_message32_send(e_client_util_win_get(e_comp->wl_comp_data->drag_client),
 ECORE_X_ATOM_XDND_DROP, ECORE_X_EVENT_MASK_NONE,
+               e_comp->cm_selection, 0, ecore_x_current_time_get(), 0, 0);
+          }
+        return;
+     }
+   _xwayland_dnd_finish();
+}
+
+static void
+_xwayland_target_send(E_Comp_Wl_Data_Source *source, uint32_t serial 
EINA_UNUSED, const char* mime_type)
+{
+   DBG("XWL Data Source Target Send");
+   
ecore_x_client_message32_send(e_client_util_win_get(e_comp->wl_comp_data->drag_client),
 ECORE_X_ATOM_XDND_STATUS, ECORE_X_EVENT_MASK_NONE,
+     e_comp->cm_selection, 2 | !!mime_type, 0, 0, (!!mime_type) * 
ECORE_X_ATOM_XDND_ACTION_COPY);
+}
+
+static void
+_xwayland_send_send(E_Comp_Wl_Data_Source *source, const char* mime_type, 
int32_t fd)
+{
+   Ecore_X_Atom type;
+
+   DBG("XWL Data Source Source Send");
+
+   _xdnd_finish(0);
+
+   if (eina_streq(mime_type, WL_TEXT_STR))
+     type = string_atom;
+   else
+     type = ecore_x_atom_get(mime_type);
+
+   cur_fd = fd;
+   xconvertselection(ecore_x_display_get(), ECORE_X_ATOM_SELECTION_XDND, type, 
xwl_dnd_atom, e_comp->cm_selection, 0);
+}
+
+static void
+_xwayland_cancelled_send(E_Comp_Wl_Data_Source *source)
+{
+   DBG("XWL Data Source Cancelled Send");
+   e_object_del(E_OBJECT(e_comp->wl_comp_data->drag));
+}
+
+static Eina_Bool
+_xwl_fixes_selection_notify(void *d EINA_UNUSED, int t EINA_UNUSED, 
Ecore_X_Event_Fixes_Selection_Notify *ev)
+{
+   if (ev->atom == ECORE_X_ATOM_SELECTION_XDND)
+     {
+        if (ev->owner)
+          {
+             int x, y, num;
+             unsigned char *data;
+             const char **names = NULL;
+             Eina_List *namelist = NULL;
+             E_Comp_Wl_Data_Source *source;
+
+             if (ecore_x_window_prop_property_get(ev->owner,
+                                                  ECORE_X_ATOM_XDND_TYPE_LIST,
+                                                  ECORE_X_ATOM_ATOM,
+                                                  32,
+                                                  &data,
+                                                  &num))
+               {
+                  int i;
+                  Ecore_X_Atom *types = (void*)data;
+
+                  names = malloc(num * sizeof(void*));
+                  for (i = 0; i < num; i++)
+                    {
+                       const char *name;
+
+                       if (types[i] == string_atom)
+                         {
+                            name = names[i] = "UTF8_STRING";
+                            namelist = eina_list_append(namelist, 
eina_stringshare_add(WL_TEXT_STR));
+                         }
+                       else
+                         names[i] = name = ecore_x_atom_name_get(types[i]);
+                       namelist = eina_list_append(namelist, 
eina_stringshare_add(name));
+                    }
+                  if (num > 3)
+                    {
+                       ecore_x_window_prop_property_set(e_comp->cm_selection,
+                         ECORE_X_ATOM_XDND_TYPE_LIST, ECORE_X_ATOM_ATOM, 32, 
names, num);
+                    }
+
+                  free(data);
+               }
+             evas_pointer_canvas_xy_get(e_comp->evas, &x, &y);
+             e_comp->wl_comp_data->drag_client = 
e_pixmap_find_client(E_PIXMAP_TYPE_X, ev->owner);
+             e_comp->wl_comp_data->drag = e_drag_new(x, y, names, num, NULL, 
0, NULL, _xwayland_drop);
+             ecore_x_window_move_resize(e_comp->cm_selection, 0, 0, e_comp->w, 
e_comp->h);
+             ecore_x_window_show(e_comp->cm_selection);
+             e_drag_start(e_comp->wl_comp_data->drag, x, y);
+             if (e_comp->wl_comp_data->ptr.ec)
+               e_comp_wl_data_device_send_enter(e_comp->wl_comp_data->ptr.ec);
+             e_comp_canvas_feed_mouse_up(0);
+             source = 
e_comp_wl_data_manager_source_create(e_comp->wl_comp_data->xwl_client,
+               e_comp->wl_comp_data->mgr.resource, 1);
+             e_comp->wl_comp_data->drag_source = source;
+             source->target = _xwayland_target_send;
+             source->send = _xwayland_send_send;
+             source->cancelled = _xwayland_cancelled_send;
+             source->mime_types = namelist;
+             free(names);
+          }
+        else
+          {
+             if (e_comp->wl_comp_data->drag)
+               e_object_del(E_OBJECT(e_comp->wl_comp_data->drag));
+             ecore_x_window_hide(e_comp->cm_selection);
+             e_comp->wl_comp_data->drag = NULL;
+             e_comp->wl_comp_data->drag_client = NULL;
+          }
+        e_screensaver_inhibit_toggle(!!ev->owner);
+        return ECORE_CALLBACK_RENEW;
+     }
+   //if (ev->atom == ECORE_X_ATOM_SELECTION_CLIPBOARD)
+   return ECORE_CALLBACK_RENEW;
+}
+
+static Eina_Bool
+_xwl_selection_notify(void *d EINA_UNUSED, int t EINA_UNUSED, 
Ecore_X_Event_Selection_Notify *ev)
+{
+   Ecore_X_Selection_Data *sd;
+   int wrote = 0;
+
+   DBG("XWL SELECTION NOTIFY");
+   if ((ev->selection != ECORE_X_SELECTION_XDND) && (ev->selection == 
ECORE_X_SELECTION_CLIPBOARD))
+     {
+        e_object_del(E_OBJECT(e_comp->wl_comp_data->drag));
+        return ECORE_CALLBACK_RENEW;
+     }
+   /* FIXME: ecore-x events are fucked */
+   //if (ecore_x_atom_get(ev->target) != xwl_dnd_atom) return 
ECORE_CALLBACK_RENEW;
+   sd = ev->data;
+
+   do
+     {
+        wrote += write(cur_fd, sd->data, sd->length);
+     } while (wrote < sd->length);
+   _xdnd_finish(1);
+   close(cur_fd);
+   _xwayland_dnd_finish();
+   return ECORE_CALLBACK_RENEW;
+}
+
+EINTERN void
+dnd_init(void)
+{
+   ecore_x_fixes_selection_notification_request(ecore_x_atom_get("CLIPBOARD"));
+   ecore_x_fixes_selection_notification_request(ECORE_X_ATOM_SELECTION_XDND);
+   ecore_event_handler_add(ECORE_X_EVENT_FIXES_SELECTION_NOTIFY, 
(Ecore_Event_Handler_Cb)_xwl_fixes_selection_notify, NULL);
+   ecore_event_handler_add(ECORE_X_EVENT_SELECTION_NOTIFY, 
(Ecore_Event_Handler_Cb)_xwl_selection_notify, NULL);
+   xconvertselection = dlsym(NULL, "XConvertSelection");
+   string_atom = ecore_x_atom_get("UTF8_STRING");
+   xwl_dnd_atom = ecore_x_atom_get("E_XWL_DND_ATOM_HAHA");
+   e_comp_shape_queue();
+}
diff --git a/src/modules/xwayland/e_mod_main.c 
b/src/modules/xwayland/e_mod_main.c
index 5926ad6..8cacc27 100644
--- a/src/modules/xwayland/e_mod_main.c
+++ b/src/modules/xwayland/e_mod_main.c
@@ -3,6 +3,8 @@
 #include <sys/socket.h>
 #include <sys/un.h>
 
+EINTERN void dnd_init(void);
+
 /* local structures */
 typedef struct _E_XWayland_Server E_XWayland_Server;
 struct _E_XWayland_Server
@@ -256,6 +258,7 @@ xnotify(void *d EINA_UNUSED, Ecore_Thread *eth EINA_UNUSED, 
void *disp)
      }
    assert(ecore_x_init_from_display(disp));
    e_comp_x_init();
+   dnd_init();
 }
 
 static void

-- 


Reply via email to