forked from enlightenment/efl
607 lines
20 KiB
Plaintext
607 lines
20 KiB
Plaintext
#define WL_TEXT_STR "text/plain;charset=utf-8"
|
|
#define INCR_CHUNK_SIZE 1 << 17
|
|
|
|
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 comp_dnd_atom;
|
|
static Ecore_X_Atom timestamp_atom;
|
|
static Ecore_X_Atom incr_atom;
|
|
static Ecore_X_Atom int_atom;
|
|
|
|
static Eina_Hash *pipes;
|
|
|
|
typedef struct
|
|
{
|
|
Ecore_Fd_Handler *fdh;
|
|
Comp_Data_Device_Source *source;
|
|
Ecore_X_Window win;
|
|
Ecore_X_Atom atom;
|
|
Ecore_X_Atom selection;
|
|
Ecore_X_Atom property;
|
|
Eina_Binbuf *buf;
|
|
Eina_Bool incr : 1;
|
|
} Pipe;
|
|
|
|
static void
|
|
_pipe_free(Pipe *p)
|
|
{
|
|
int fd = ecore_main_fd_handler_fd_get(p->fdh);
|
|
if (fd >= 0)
|
|
close(fd);
|
|
ecore_main_fd_handler_del(p->fdh);
|
|
eina_binbuf_free(p->buf);
|
|
free(p);
|
|
}
|
|
|
|
static void
|
|
_incr_update(Pipe *p, Eina_Bool success)
|
|
{
|
|
ecore_x_selection_notify_send(p->win, p->selection, p->atom, (!!success) * p->property, 0);
|
|
}
|
|
|
|
static void
|
|
_incr_upload(Pipe *p)
|
|
{
|
|
size_t size;
|
|
|
|
size = eina_binbuf_length_get(p->buf);
|
|
size = MIN(size, INCR_CHUNK_SIZE);
|
|
ecore_x_window_prop_property_set(p->win, p->property, p->atom, 8, (void*)eina_binbuf_string_get(p->buf), size);
|
|
eina_binbuf_free(p->buf);
|
|
p->buf = NULL;
|
|
}
|
|
|
|
static Eina_Bool
|
|
x11_offer_write(void *data, Ecore_Fd_Handler *fdh)
|
|
{
|
|
Comp_Data_Device_Transfer *dt = data;
|
|
int len = -1;
|
|
|
|
if (ecore_main_fd_handler_active_get(fdh, ECORE_FD_WRITE))
|
|
{
|
|
int fd = ecore_main_fd_handler_fd_get(fdh);
|
|
if (fd >= 0)
|
|
len = write(fd,
|
|
eina_binbuf_string_get(dt->source->reader_data) + dt->offset,
|
|
eina_binbuf_length_get(dt->source->reader_data) - dt->offset);
|
|
if (len > 0) dt->offset += len;
|
|
}
|
|
|
|
if ((len <= 0) || (dt->offset == eina_binbuf_length_get(dt->source->reader_data)))
|
|
{
|
|
fdh_del(fdh);
|
|
eina_stringshare_del(dt->mime_type);
|
|
dt->source->transfers = eina_inlist_remove(dt->source->transfers, EINA_INLIST_GET(dt));
|
|
|
|
if (dt->source->x11_owner)
|
|
{
|
|
Ecore_Window win = ecore_evas_window_get(ecore_evas_ecore_evas_get(dt->source->seat->c->evas));
|
|
if (dt->type == COMP_DATA_DEVICE_OFFER_TYPE_DND)
|
|
ecore_x_client_message32_send(dt->source->x11_owner,
|
|
ECORE_X_ATOM_XDND_FINISHED, ECORE_X_EVENT_MASK_NONE,
|
|
win, (len >= 0), action_convert(dt->source->current_dnd_action), 0, 0);
|
|
ecore_x_window_prop_property_del(win, ECORE_X_ATOM_XDND_TYPE_LIST);
|
|
if (dt->source == dt->source->seat->drag.source)
|
|
dt->source->seat->drag.source = NULL;
|
|
}
|
|
|
|
if ((!dt->source->transfers) && (dt->source->seat->selection_source != dt->source))
|
|
comp_data_device_source_reader_clear(dt->source);
|
|
free(dt);
|
|
}
|
|
|
|
return ECORE_CALLBACK_RENEW;
|
|
}
|
|
|
|
static void
|
|
x11_send_send(Comp_Data_Device_Source *source, const char* mime_type, int32_t fd, Comp_Data_Device_Offer_Type type)
|
|
{
|
|
Ecore_X_Atom t, sel = ECORE_X_ATOM_SELECTION_CLIPBOARD;
|
|
Comp_Data_Device_Transfer *dt;
|
|
Ecore_Window win;
|
|
char *name;
|
|
win = ecore_evas_window_get(ecore_evas_ecore_evas_get(source->seat->c->evas));
|
|
if (type == COMP_DATA_DEVICE_OFFER_TYPE_DND)
|
|
sel = ECORE_X_ATOM_SELECTION_XDND;
|
|
|
|
if (eina_streq(mime_type, WL_TEXT_STR))
|
|
t = string_atom;
|
|
else
|
|
t = ecore_x_atom_get(mime_type);
|
|
|
|
dt = calloc(1, sizeof(Comp_Data_Device_Transfer));
|
|
dt->type = type;
|
|
dt->fdh = ecore_main_fd_handler_add(fd, 0, x11_offer_write, dt, NULL, NULL);
|
|
dt->source = source;
|
|
name = ecore_x_atom_name_get(t);
|
|
dt->mime_type = eina_stringshare_add(name);
|
|
free(name);
|
|
dt->source->transfers = eina_inlist_append(dt->source->transfers, EINA_INLIST_GET(dt));
|
|
xconvertselection(ecore_x_display_get(), sel, t, comp_dnd_atom, win, ecore_x_current_time_get());
|
|
}
|
|
|
|
static Eina_Bool
|
|
x11_fixes_selection_notify(void *d EINA_UNUSED, int t EINA_UNUSED, Ecore_X_Event_Fixes_Selection_Notify *ev)
|
|
{
|
|
Ecore_X_Window win;
|
|
Eina_List *l;
|
|
Comp *c;
|
|
Comp_Seat *s;
|
|
|
|
EINA_LIST_FOREACH(comps, l, c)
|
|
{
|
|
win = ecore_evas_window_get(ecore_evas_ecore_evas_get(c->evas));
|
|
if (ev->owner == win)
|
|
return ECORE_CALLBACK_RENEW;
|
|
c->x11_selection = 0;
|
|
}
|
|
if (ev->atom == ECORE_X_ATOM_SELECTION_CLIPBOARD)
|
|
{
|
|
EINA_LIST_FOREACH(comps, l, c)
|
|
EINA_INLIST_FOREACH(c->seats, s)
|
|
{
|
|
s->x11_selection_owner = ev->owner;
|
|
if (ev->owner) s->selection_source = NULL;
|
|
}
|
|
if (ev->owner)
|
|
{
|
|
EINA_LIST_FOREACH(comps, l, c)
|
|
{
|
|
win = ecore_evas_window_get(ecore_evas_ecore_evas_get(c->evas));
|
|
if (l != comps)
|
|
{
|
|
Eina_List *ll;
|
|
Comp *c2;
|
|
Ecore_X_Window win2 = 0;
|
|
EINA_LIST_FOREACH(comps, ll, c2)
|
|
{
|
|
win2 = ecore_evas_window_get(ecore_evas_ecore_evas_get(c->evas));
|
|
if (win == win2) break;
|
|
if (l == ll) break;
|
|
}
|
|
if ((win == win2) && (l != ll)) continue;
|
|
}
|
|
xconvertselection(ecore_x_display_get(), ECORE_X_ATOM_SELECTION_CLIPBOARD,
|
|
ECORE_X_ATOM_SELECTION_TARGETS, comp_dnd_atom, win, 0);
|
|
}
|
|
}
|
|
}
|
|
return ECORE_CALLBACK_RENEW;
|
|
}
|
|
|
|
static Eina_Bool
|
|
x11_selection_notify(void *d EINA_UNUSED, int t EINA_UNUSED, Ecore_X_Event_Selection_Notify *ev)
|
|
{
|
|
Ecore_X_Selection_Data *sd;
|
|
Eina_List *l, *lc = NULL;
|
|
Comp *c;
|
|
Comp_Seat *s;
|
|
Comp_Data_Device_Transfer *dt;
|
|
Eina_Binbuf *buf = NULL;
|
|
|
|
if ((ev->selection != ECORE_X_SELECTION_XDND) && (ev->selection != ECORE_X_SELECTION_CLIPBOARD))
|
|
{
|
|
EINA_LIST_FOREACH(comps, l, c)
|
|
EINA_INLIST_FOREACH(c->seats, s)
|
|
{
|
|
ecore_evas_free(s->drag.proxy_win);
|
|
s->drag.proxy_win = NULL;
|
|
}
|
|
return ECORE_CALLBACK_RENEW;
|
|
}
|
|
EINA_LIST_FOREACH(comps, l, c)
|
|
{
|
|
Ecore_X_Window win = ecore_evas_window_get(ecore_evas_ecore_evas_get(c->evas));
|
|
if (win == ev->win) lc = eina_list_append(lc, c);
|
|
}
|
|
if (ev->selection == ECORE_X_SELECTION_CLIPBOARD)
|
|
{
|
|
if (eina_streq(ev->target, "TARGETS"))
|
|
{
|
|
Ecore_X_Selection_Data_Targets *tgs = ev->data;
|
|
int i, j;
|
|
const char **types;
|
|
|
|
types = alloca((tgs->num_targets + 1) * sizeof(void*));
|
|
for (i = j = 0; i < tgs->num_targets; i++)
|
|
if (tgs->targets[i])
|
|
types[j++] = tgs->targets[i];
|
|
types[j] = NULL;
|
|
EINA_LIST_FREE(lc, c)
|
|
EINA_INLIST_FOREACH(c->seats, s)
|
|
s->client_selection_serial = ecore_wl2_dnd_selection_set(s->client_seat, (const char**)types);
|
|
return ECORE_CALLBACK_RENEW;
|
|
}
|
|
}
|
|
if (ev->property != comp_dnd_atom) return ECORE_CALLBACK_RENEW;
|
|
EINA_LIST_FREE(lc, c)
|
|
{
|
|
EINA_INLIST_FOREACH(c->seats, s)
|
|
{
|
|
|
|
if (s->drag.source && s->drag.source->transfers &&
|
|
(ev->selection == ECORE_X_SELECTION_XDND))
|
|
{
|
|
EINA_INLIST_FOREACH(s->drag.source->transfers, dt)
|
|
if (eina_streq(ev->target, dt->mime_type))
|
|
{
|
|
if (!s->drag.source->reader_data)
|
|
s->drag.source->reader_data = eina_binbuf_new();
|
|
buf = s->drag.source->reader_data;
|
|
break;
|
|
}
|
|
}
|
|
else if (s->selection_source && s->selection_source->transfers &&
|
|
(ev->selection == ECORE_X_SELECTION_CLIPBOARD))
|
|
{
|
|
EINA_INLIST_FOREACH(s->selection_source->transfers, dt)
|
|
if (eina_streq(ev->target, dt->mime_type))
|
|
{
|
|
if (!s->selection_source->reader_data)
|
|
s->selection_source->reader_data = eina_binbuf_new();
|
|
buf = s->selection_source->reader_data;
|
|
break;
|
|
}
|
|
}
|
|
if (buf) break;
|
|
}
|
|
if (buf) break;
|
|
}
|
|
eina_list_free(lc);
|
|
|
|
if (!buf) return ECORE_CALLBACK_RENEW;
|
|
sd = ev->data;
|
|
eina_binbuf_append_length(buf, sd->data, sd->length);
|
|
ecore_main_fd_handler_active_set(dt->fdh, ECORE_FD_WRITE | ECORE_FD_ERROR);
|
|
|
|
return ECORE_CALLBACK_RENEW;
|
|
}
|
|
|
|
static Eina_Bool
|
|
x11_pipe_read(void *data, Ecore_Fd_Handler *fdh)
|
|
{
|
|
Pipe *p = data;
|
|
ssize_t len = -1;
|
|
unsigned char *buf;
|
|
int fd;
|
|
|
|
buf = malloc(INCR_CHUNK_SIZE);
|
|
fd = ecore_main_fd_handler_fd_get(fdh);
|
|
if (fd >= 0)
|
|
len = read(fd, (void*)buf, INCR_CHUNK_SIZE);
|
|
if (len < 0)
|
|
{
|
|
free(buf);
|
|
_incr_update(p, 0);
|
|
eina_hash_del_by_key(pipes, &p->win);
|
|
return ECORE_CALLBACK_RENEW;
|
|
}
|
|
if (len == INCR_CHUNK_SIZE)
|
|
{
|
|
p->buf = eina_binbuf_manage_new(buf, len, 0);
|
|
if (p->incr)
|
|
_incr_upload(p);
|
|
else
|
|
{
|
|
unsigned long size = INCR_CHUNK_SIZE;
|
|
|
|
p->incr = 1;
|
|
ecore_x_window_prop_property_set(p->win, p->atom, incr_atom, 32, &size, 1);
|
|
_incr_update(p, 1);
|
|
}
|
|
ecore_main_fd_handler_active_set(p->fdh, 0);
|
|
return ECORE_CALLBACK_RENEW;
|
|
}
|
|
if (len)
|
|
{
|
|
p->buf = eina_binbuf_manage_new(buf, len, 0);
|
|
_incr_upload(p);
|
|
}
|
|
else
|
|
free(buf);
|
|
if (p->incr)
|
|
ecore_main_fd_handler_active_set(p->fdh, 0);
|
|
else
|
|
{
|
|
_incr_update(p, 1);
|
|
eina_hash_del_by_key(pipes, &p->win);
|
|
}
|
|
return ECORE_CALLBACK_RENEW;
|
|
}
|
|
|
|
static Eina_Bool
|
|
x11_selection_request(void *d EINA_UNUSED, int t EINA_UNUSED, Ecore_X_Event_Selection_Request *ev)
|
|
{
|
|
Comp_Data_Device_Source *source;
|
|
Eina_List *l;
|
|
Comp *c;
|
|
const char *type;
|
|
Comp_Seat *s = NULL;
|
|
|
|
EINA_LIST_FOREACH(comps, l, c)
|
|
{
|
|
Ecore_Window win = ecore_evas_window_get(ecore_evas_ecore_evas_get(c->evas));
|
|
if (c->x11_selection || ((ev->owner == win) && (ev->selection == ECORE_X_ATOM_SELECTION_XDND)))
|
|
{
|
|
s = EINA_INLIST_CONTAINER_GET(c->seats, Comp_Seat);
|
|
break;
|
|
}
|
|
}
|
|
if (!s) return ECORE_CALLBACK_RENEW;
|
|
if (s->drag.source)
|
|
source = s->drag.source;
|
|
else if (s->selection_source)
|
|
source = s->selection_source;
|
|
else
|
|
return ECORE_CALLBACK_RENEW;
|
|
|
|
if (ev->target == ECORE_X_ATOM_SELECTION_TARGETS)
|
|
{
|
|
Ecore_X_Atom *atoms;
|
|
int i = 0;
|
|
|
|
atoms = alloca((2 + eina_list_count(source->mime_types)) * sizeof(void*));
|
|
EINA_LIST_FOREACH(source->mime_types, l, type)
|
|
atoms[i++] = ecore_x_atom_get(type);
|
|
atoms[i++] = timestamp_atom;
|
|
atoms[i++] = ECORE_X_ATOM_SELECTION_TARGETS;
|
|
ecore_x_window_prop_property_set(ev->requestor, ev->property, ECORE_X_ATOM_ATOM, 32, atoms, i);
|
|
ecore_x_selection_notify_send(ev->requestor, ev->selection, ev->target, ev->property, 0);
|
|
}
|
|
else if (ev->target == timestamp_atom)
|
|
{
|
|
Ecore_X_Time timestamp;
|
|
|
|
timestamp = ecore_x_current_time_get();
|
|
ecore_x_window_prop_property_set(ev->requestor, ev->property, int_atom, 32, (void*)×tamp, 1);
|
|
ecore_x_selection_notify_send(ev->requestor, ev->selection, ev->target, ev->property, 0);
|
|
}
|
|
else
|
|
{
|
|
char *name;
|
|
Pipe *p;
|
|
|
|
name = ecore_x_atom_name_get(ev->target);
|
|
EINA_LIST_FOREACH(source->mime_types, l, type)
|
|
if (eina_streq(name, type))
|
|
{
|
|
int fds[2];
|
|
|
|
if (socketpair(AF_UNIX, (SOCK_STREAM | SOCK_CLOEXEC), 0, fds) < 0)
|
|
{
|
|
EINA_LOG_ERR("socketpair failed!\n");
|
|
continue;
|
|
}
|
|
if (fcntl(fds[0], F_SETFL, O_NONBLOCK) < 0)
|
|
{
|
|
close(fds[0]);
|
|
close(fds[1]);
|
|
EINA_LOG_ERR("NONBLOCK for socketpair failed!\n");
|
|
continue;
|
|
}
|
|
p = calloc(1, sizeof(Pipe));
|
|
p->fdh = ecore_main_fd_handler_add(fds[0], ECORE_FD_READ, x11_pipe_read, p, NULL, NULL);
|
|
p->win = ev->requestor;
|
|
p->source = source;
|
|
wl_data_source_send_send(source->res, type, fds[1]);
|
|
close(fds[1]);
|
|
p->atom = ev->target;
|
|
p->selection = ev->selection;
|
|
p->property = ev->property;
|
|
ecore_x_window_sniff(ev->requestor);
|
|
eina_hash_add(pipes, &p->win, p);
|
|
break;
|
|
}
|
|
free(name);
|
|
}
|
|
return ECORE_CALLBACK_RENEW;
|
|
}
|
|
|
|
static Eina_Bool
|
|
x11_property(void *d EINA_UNUSED, int t EINA_UNUSED, Ecore_X_Event_Window_Property *ev)
|
|
{
|
|
Pipe *p;
|
|
|
|
if (!ev->state) return ECORE_CALLBACK_RENEW;
|
|
p = eina_hash_find(pipes, &ev->win);
|
|
if (!p) return ECORE_CALLBACK_RENEW;
|
|
/* FIXME: WHO FORGOT THE FUCKING STATE FLAG???? */
|
|
ecore_main_fd_handler_active_set(p->fdh, ECORE_FD_READ);
|
|
return ECORE_CALLBACK_RENEW;
|
|
}
|
|
|
|
static Eina_Bool
|
|
x11_dnd_enter(void *d EINA_UNUSED, int t EINA_UNUSED, Ecore_X_Event_Xdnd_Enter *ev)
|
|
{
|
|
Comp_Seat *s;
|
|
Comp *c;
|
|
Eina_List *l;
|
|
const char **types;
|
|
int i;
|
|
|
|
types = alloca(sizeof(void*) * (ev->num_types + 1));
|
|
for (i = 0; i < ev->num_types; i++)
|
|
types[i] = ev->types[i];
|
|
types[ev->num_types] = NULL;
|
|
|
|
EINA_LIST_FOREACH(comps, l, c)
|
|
{
|
|
Ecore_Window win = ecore_evas_window_get(ecore_evas_ecore_evas_get(c->evas));
|
|
if (win != ev->win) continue;
|
|
EINA_INLIST_FOREACH(c->seats, s)
|
|
{
|
|
if (s->drag.x11_owner == ev->source) continue;
|
|
s->drag.x11_owner = ev->source;
|
|
for (i = 0; i < ev->num_types; i++)
|
|
s->drag.x11_types = eina_list_append(s->drag.x11_types, eina_stringshare_add(ev->types[i]));
|
|
ecore_wl2_dnd_drag_types_set(s->client_seat, (const char**)types);
|
|
ecore_wl2_dnd_set_actions(s->client_seat);
|
|
}
|
|
}
|
|
|
|
return ECORE_CALLBACK_RENEW;
|
|
}
|
|
|
|
static Eina_Bool
|
|
x11_dnd_leave(void *d EINA_UNUSED, int t EINA_UNUSED, Ecore_X_Event_Xdnd_Leave *ev)
|
|
{
|
|
Comp_Seat *s;
|
|
Comp *c;
|
|
Eina_List *l;
|
|
|
|
EINA_LIST_FOREACH(comps, l, c)
|
|
{
|
|
Ecore_Window win = ecore_evas_window_get(ecore_evas_ecore_evas_get(c->evas));
|
|
if (win != ev->win) continue;
|
|
EINA_INLIST_FOREACH(c->seats, s)
|
|
{
|
|
if (s->drag.x11_owner == win) continue; //self drag
|
|
if (s->drag.source)
|
|
wl_data_source_send_cancelled(s->drag.source->res);
|
|
if (s->client_seat)
|
|
ecore_wl2_dnd_drag_end(s->client_seat);
|
|
s->drag.source = NULL;
|
|
s->drag.res = NULL;
|
|
s->drag.enter = NULL;
|
|
s->drag.x11_owner = 0;
|
|
}
|
|
}
|
|
return ECORE_CALLBACK_RENEW;
|
|
}
|
|
|
|
static Eina_Bool
|
|
x11_dnd_position(void *d EINA_UNUSED, int t EINA_UNUSED, Ecore_X_Event_Xdnd_Position *ev)
|
|
{
|
|
Comp *c;
|
|
Eina_List *l;
|
|
Comp_Seat *s;
|
|
|
|
EINA_LIST_FOREACH(comps, l, c)
|
|
{
|
|
int x, y, cx, cy, cw, ch;
|
|
Ecore_Window win = ecore_evas_window_get(ecore_evas_ecore_evas_get(c->evas));
|
|
if (win != ev->win) continue;
|
|
ecore_evas_geometry_get(ecore_evas_ecore_evas_get(c->evas), &x, &y, NULL, NULL);
|
|
evas_object_geometry_get(c->obj, &cx, &cy, &cw, &ch);
|
|
if (!COORDS_INSIDE(ev->position.x, ev->position.y, x + cx, y + cy, cw, ch)) continue;
|
|
EINA_INLIST_FOREACH(c->seats, s)
|
|
dnd_motion(s, ev->position.x - x - cx, ev->position.y - y - cy);
|
|
}
|
|
return ECORE_CALLBACK_RENEW;
|
|
}
|
|
|
|
static Eina_Bool
|
|
x11_dnd_drop(void *d EINA_UNUSED, int t EINA_UNUSED, Ecore_X_Event_Xdnd_Drop *ev)
|
|
{
|
|
Comp *c;
|
|
Eina_List *l;
|
|
Comp_Seat *s;
|
|
|
|
EINA_LIST_FOREACH(comps, l, c)
|
|
{
|
|
int x, y, cx, cy, cw, ch;
|
|
Ecore_Window win = ecore_evas_window_get(ecore_evas_ecore_evas_get(c->evas));
|
|
if (win != ev->win) continue;
|
|
ecore_evas_geometry_get(ecore_evas_ecore_evas_get(c->evas), &x, &y, NULL, NULL);
|
|
evas_object_geometry_get(c->obj, &cx, &cy, &cw, &ch);
|
|
if (!COORDS_INSIDE(ev->position.x, ev->position.y, x + cx, y + cy, cw, ch)) continue;
|
|
EINA_INLIST_FOREACH(c->seats, s)
|
|
drag_grab_button(s, 0, s->drag.id, WL_POINTER_BUTTON_STATE_RELEASED);
|
|
}
|
|
return ECORE_CALLBACK_RENEW;
|
|
}
|
|
|
|
static Eina_Bool
|
|
x11_dnd_finished(void *d EINA_UNUSED, int t EINA_UNUSED, Ecore_X_Event_Xdnd_Finished *ev)
|
|
{
|
|
Comp *c;
|
|
Eina_List *l;
|
|
Comp_Seat *s;
|
|
|
|
EINA_LIST_FOREACH(comps, l, c)
|
|
{
|
|
Ecore_Window win = ecore_evas_window_get(ecore_evas_ecore_evas_get(c->evas));
|
|
if (win != ev->win) continue;
|
|
EINA_INLIST_FOREACH(c->seats, s)
|
|
{
|
|
Comp_Data_Device_Source *source = s->drag.source;
|
|
if (s->drag.x11_owner != win) continue;
|
|
if (s->drag.source) s->drag.source->accepted = ev->completed;
|
|
drag_grab_button(s, 0, s->drag.id, WL_POINTER_BUTTON_STATE_RELEASED);
|
|
data_source_notify_finish(source);
|
|
}
|
|
}
|
|
return ECORE_CALLBACK_RENEW;
|
|
}
|
|
|
|
static Eina_Bool
|
|
x11_dnd_mouse_up(void *d EINA_UNUSED, int t EINA_UNUSED, Ecore_Event_Mouse_Button *ev)
|
|
{
|
|
Comp *c;
|
|
Eina_List *l;
|
|
Comp_Seat *s;
|
|
|
|
EINA_LIST_FOREACH(comps, l, c)
|
|
{
|
|
Ecore_Window win = ecore_evas_window_get(ecore_evas_ecore_evas_get(c->evas));
|
|
if (win != ev->event_window) continue;
|
|
EINA_INLIST_FOREACH(c->seats, s)
|
|
if (s->drag.id == ev->buttons)
|
|
{
|
|
ecore_x_dnd_self_drop();
|
|
ecore_x_pointer_ungrab();
|
|
ecore_evas_free(s->drag.proxy_win);
|
|
}
|
|
}
|
|
return ECORE_CALLBACK_RENEW;
|
|
}
|
|
|
|
static void
|
|
x11_dnd_move(void *data, Ecore_X_Xdnd_Position *pos)
|
|
{
|
|
evas_object_move(data, pos->position.x, pos->position.y);
|
|
}
|
|
|
|
static void
|
|
x11_init(void)
|
|
{
|
|
Ecore_Event_Handler *h;
|
|
|
|
ecore_x_fixes_selection_notification_request(ecore_x_atom_get("CLIPBOARD"));
|
|
ecore_x_fixes_selection_notification_request(ECORE_X_ATOM_SELECTION_XDND);
|
|
h = ecore_event_handler_add(ECORE_X_EVENT_FIXES_SELECTION_NOTIFY, (Ecore_Event_Handler_Cb)x11_fixes_selection_notify, NULL);
|
|
handlers = eina_list_append(handlers, h);
|
|
h = ecore_event_handler_add(ECORE_X_EVENT_SELECTION_NOTIFY, (Ecore_Event_Handler_Cb)x11_selection_notify, NULL);
|
|
handlers = eina_list_append(handlers, h);
|
|
h = ecore_event_handler_add(ECORE_X_EVENT_SELECTION_REQUEST, (Ecore_Event_Handler_Cb)x11_selection_request, NULL);
|
|
handlers = eina_list_append(handlers, h);
|
|
h = ecore_event_handler_add(ECORE_X_EVENT_WINDOW_PROPERTY, (Ecore_Event_Handler_Cb)x11_property, NULL);
|
|
handlers = eina_list_append(handlers, h);
|
|
h = ecore_event_handler_add(ECORE_X_EVENT_XDND_ENTER, (Ecore_Event_Handler_Cb)x11_dnd_enter, NULL);
|
|
handlers = eina_list_append(handlers, h);
|
|
h = ecore_event_handler_add(ECORE_X_EVENT_XDND_LEAVE, (Ecore_Event_Handler_Cb)x11_dnd_leave, NULL);
|
|
handlers = eina_list_append(handlers, h);
|
|
h = ecore_event_handler_add(ECORE_X_EVENT_XDND_POSITION, (Ecore_Event_Handler_Cb)x11_dnd_position, NULL);
|
|
handlers = eina_list_append(handlers, h);
|
|
h = ecore_event_handler_add(ECORE_X_EVENT_XDND_DROP, (Ecore_Event_Handler_Cb)x11_dnd_drop, NULL);
|
|
handlers = eina_list_append(handlers, h);
|
|
h = ecore_event_handler_add(ECORE_X_EVENT_XDND_FINISHED, (Ecore_Event_Handler_Cb)x11_dnd_finished, NULL);
|
|
handlers = eina_list_append(handlers, h);
|
|
h = ecore_event_handler_add(ECORE_EVENT_MOUSE_BUTTON_UP, (Ecore_Event_Handler_Cb)x11_dnd_mouse_up, NULL);
|
|
handlers = eina_list_append(handlers, h);
|
|
xconvertselection = dlsym(NULL, "XConvertSelection");
|
|
string_atom = ecore_x_atom_get("UTF8_STRING");
|
|
timestamp_atom = ecore_x_atom_get("TIMESTAMP");
|
|
int_atom = ecore_x_atom_get("INTEGER");
|
|
incr_atom = ecore_x_atom_get("TIMESTAMP");
|
|
comp_dnd_atom = ecore_x_atom_get("SIRCMPWIDG_ATOM");
|
|
pipes = eina_hash_int32_new((Eina_Free_Cb)_pipe_free);
|
|
}
|
|
|
|
static void
|
|
x11_shutdown(void)
|
|
{
|
|
eina_hash_free(pipes);
|
|
pipes = NULL;
|
|
}
|