forked from enlightenment/enlightenment
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
This commit is contained in:
parent
3c722ac7f2
commit
5bde1a8648
|
@ -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 *
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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();
|
||||
}
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue