Working on dnd drag. Doesn't quite work yet....

SVN revision: 13877
This commit is contained in:
sebastid 2005-03-23 18:33:50 +00:00 committed by sebastid
parent f919722f06
commit 83ea927187
4 changed files with 117 additions and 82 deletions

View File

@ -473,7 +473,6 @@ struct _Ecore_X_Event_Xdnd_Status
{ {
Ecore_X_Window win, target; Ecore_X_Window win, target;
int will_accept; int will_accept;
int suppress;
Ecore_X_Rectangle rectangle; Ecore_X_Rectangle rectangle;
Ecore_X_Atom action; Ecore_X_Atom action;
}; };
@ -826,6 +825,7 @@ EAPI int ecore_x_dnd_version_get(Ecore_X_Window win);
EAPI int ecore_x_dnd_type_isset(Ecore_X_Window win, const char *type); EAPI int ecore_x_dnd_type_isset(Ecore_X_Window win, const char *type);
EAPI void ecore_x_dnd_type_set(Ecore_X_Window win, const char *type, int on); EAPI void ecore_x_dnd_type_set(Ecore_X_Window win, const char *type, int on);
EAPI int ecore_x_dnd_begin(Ecore_X_Window source, unsigned char *data, int size); EAPI int ecore_x_dnd_begin(Ecore_X_Window source, unsigned char *data, int size);
EAPI void ecore_x_dnd_drop(void);
EAPI void ecore_x_dnd_send_status(int will_accept, int suppress, Ecore_X_Rectangle rectangle, Ecore_X_Atom action); EAPI void ecore_x_dnd_send_status(int will_accept, int suppress, Ecore_X_Rectangle rectangle, Ecore_X_Atom action);
EAPI void ecore_x_dnd_send_finished(void); EAPI void ecore_x_dnd_send_finished(void);

View File

@ -48,7 +48,6 @@ ecore_x_dnd_aware_set(Ecore_X_Window win, int on)
XA_ATOM, 32, &prop_data, 1); XA_ATOM, 32, &prop_data, 1);
else else
ecore_x_window_prop_property_del(win, ECORE_X_ATOM_XDND_AWARE); ecore_x_window_prop_property_del(win, ECORE_X_ATOM_XDND_AWARE);
ecore_x_dnd_type_set(win, "text/plain", 1);
} }
int int
@ -180,6 +179,33 @@ ecore_x_dnd_begin(Ecore_X_Window source, unsigned char *data, int size)
return 1; return 1;
} }
void
ecore_x_dnd_drop(void)
{
XEvent xev;
xev.xany.type = ClientMessage;
xev.xany.display = _ecore_x_disp;
xev.xclient.format = 32;
xev.xclient.window = _xdnd->dest;
if (_xdnd->will_accept)
{
xev.xclient.message_type = ECORE_X_ATOM_XDND_DROP;
xev.xclient.data.l[0] = _xdnd->source;
xev.xclient.data.l[1] = 0;
xev.xclient.data.l[2] = _xdnd->time;
XSendEvent(_ecore_x_disp, _xdnd->dest, False, 0, &xev);
}
else
{
xev.xclient.message_type = ECORE_X_ATOM_XDND_LEAVE;
xev.xclient.data.l[0] = _xdnd->source;
xev.xclient.data.l[1] = 0;
XSendEvent(_ecore_x_disp, _xdnd->dest, False, 0, &xev);
}
}
void void
ecore_x_dnd_send_status(int will_accept, int suppress, Ecore_X_Rectangle rectangle, Ecore_X_Atom action) ecore_x_dnd_send_status(int will_accept, int suppress, Ecore_X_Rectangle rectangle, Ecore_X_Atom action)
{ {
@ -205,6 +231,7 @@ ecore_x_dnd_send_status(int will_accept, int suppress, Ecore_X_Rectangle rectang
xev.xclient.window = _xdnd->source; xev.xclient.window = _xdnd->source;
xev.xclient.data.l[0] = _xdnd->dest; xev.xclient.data.l[0] = _xdnd->dest;
xev.xclient.data.l[1] = 0;
if (will_accept) if (will_accept)
xev.xclient.data.l[1] |= 0x1UL; xev.xclient.data.l[1] |= 0x1UL;
if (!suppress) if (!suppress)
@ -244,7 +271,8 @@ ecore_x_dnd_send_finished(void)
xev.xclient.window = _xdnd->source; xev.xclient.window = _xdnd->source;
xev.xclient.data.l[0] = _xdnd->dest; xev.xclient.data.l[0] = _xdnd->dest;
memset(xev.xclient.data.l + 1, 0, sizeof(long) * 3); xev.xclient.data.l[1] = 0;
xev.xclient.data.l[2] = 0;
if (_xdnd->will_accept) if (_xdnd->will_accept)
{ {
xev.xclient.data.l[1] |= 0x1UL; xev.xclient.data.l[1] |= 0x1UL;
@ -271,11 +299,12 @@ _ecore_x_dnd_drag(int x, int y)
win = ecore_x_window_parent_get(win); win = ecore_x_window_parent_get(win);
/* Send XdndLeave to current destination window if we have left it */ /* Send XdndLeave to current destination window if we have left it */
if ((win != _xdnd->dest) && (_xdnd->dest)) if ((_xdnd->dest) && (win != _xdnd->dest))
{ {
xev.xclient.window = _xdnd->dest; xev.xclient.window = _xdnd->dest;
xev.xclient.message_type = ECORE_X_ATOM_XDND_LEAVE; xev.xclient.message_type = ECORE_X_ATOM_XDND_LEAVE;
xev.xclient.data.l[0] = _xdnd->source; xev.xclient.data.l[0] = _xdnd->source;
xev.xclient.data.l[1] = 0;
XSendEvent(_ecore_x_disp, _xdnd->dest, False, 0, &xev); XSendEvent(_ecore_x_disp, _xdnd->dest, False, 0, &xev);
} }
@ -298,12 +327,15 @@ _ecore_x_dnd_drag(int x, int y)
xev.xclient.window = win; xev.xclient.window = win;
xev.xclient.message_type = ECORE_X_ATOM_XDND_ENTER; xev.xclient.message_type = ECORE_X_ATOM_XDND_ENTER;
xev.xclient.data.l[0] = _xdnd->source; xev.xclient.data.l[0] = _xdnd->source;
xev.xclient.data.l[1] = 0;
if (num > 3) if (num > 3)
xev.xclient.data.l[1] |= 0x1UL; xev.xclient.data.l[1] |= 0x1UL;
else else
xev.xclient.data.l[1] &= 0xfffffffeUL; xev.xclient.data.l[1] &= 0xfffffffeUL;
xev.xclient.data.l[1] |= ((unsigned long) _xdnd->version) << 24; xev.xclient.data.l[1] |= ((unsigned long) _xdnd->version) << 24;
for (i = 2; i < 5; i++)
xev.xclient.data.l[i] = 0;
for (i = 0; i < MIN(num, 3); ++i) for (i = 0; i < MIN(num, 3); ++i)
xev.xclient.data.l[i + 2] = types[i]; xev.xclient.data.l[i + 2] = types[i];
XFree(data); XFree(data);
@ -319,7 +351,7 @@ _ecore_x_dnd_drag(int x, int y)
xev.xclient.data.l[0] = _xdnd->source; xev.xclient.data.l[0] = _xdnd->source;
xev.xclient.data.l[1] = 0; /* Reserved */ xev.xclient.data.l[1] = 0; /* Reserved */
xev.xclient.data.l[2] = ((x << 16) & 0xffff0000) | (y & 0xffff); xev.xclient.data.l[2] = ((x << 16) & 0xffff0000) | (y & 0xffff);
xev.xclient.data.l[3] = CurrentTime; /* Version 1 */ xev.xclient.data.l[3] = _xdnd->time; /* Version 1 */
xev.xclient.data.l[4] = _xdnd->action; /* Version 2, Needs to be pre-set */ xev.xclient.data.l[4] = _xdnd->action; /* Version 2, Needs to be pre-set */
XSendEvent(_ecore_x_disp, win, False, 0, &xev); XSendEvent(_ecore_x_disp, win, False, 0, &xev);
_xdnd->await_status = 1; _xdnd->await_status = 1;
@ -336,9 +368,7 @@ _ecore_x_dnd_drag(int x, int y)
xev.xclient.message_type = ECORE_X_ATOM_XDND_DROP; xev.xclient.message_type = ECORE_X_ATOM_XDND_DROP;
xev.xclient.data.l[0] = _xdnd->source; xev.xclient.data.l[0] = _xdnd->source;
xev.xclient.data.l[1] = 0; xev.xclient.data.l[1] = 0;
xev.xclient.data.l[2] = CurrentTime; xev.xclient.data.l[2] = _xdnd->time;
xev.xclient.data.l[3] = 0;
xev.xclient.data.l[4] = 0;
XSendEvent(_ecore_x_disp, win, False, 0, &xev); XSendEvent(_ecore_x_disp, win, False, 0, &xev);
} }
else else
@ -346,7 +376,7 @@ _ecore_x_dnd_drag(int x, int y)
xev.xclient.window = win; xev.xclient.window = win;
xev.xclient.message_type = ECORE_X_ATOM_XDND_LEAVE; xev.xclient.message_type = ECORE_X_ATOM_XDND_LEAVE;
xev.xclient.data.l[0] = _xdnd->source; xev.xclient.data.l[0] = _xdnd->source;
memset(xev.xclient.data.l + 1, 0, sizeof(long) * 3); /* Evil */ xev.xclient.data.l[1] = 0;
XSendEvent(_ecore_x_disp, win, False, 0, &xev); XSendEvent(_ecore_x_disp, win, False, 0, &xev);
} }
} }

View File

@ -503,15 +503,16 @@ _ecore_x_event_handle_motion_notify(XEvent *xevent)
/* Xdnd handling */ /* Xdnd handling */
_xdnd = _ecore_x_dnd_protocol_get(); _xdnd = _ecore_x_dnd_protocol_get();
if (_xdnd->state == ECORE_X_DND_DRAGGING) if (_xdnd->state != ECORE_X_DND_IDLE)
{ {
/* Determine if we're still in the rectangle from the last status */ /* Determine if we're still in the rectangle from the last status */
x1 = _xdnd->rectangle.x; x1 = _xdnd->rectangle.x;
x2 = _xdnd->rectangle.x + _xdnd->rectangle.width; x2 = _xdnd->rectangle.x + _xdnd->rectangle.width;
y1 = _xdnd->rectangle.y; y1 = _xdnd->rectangle.y;
y2 = _xdnd->rectangle.y + _xdnd->rectangle.height; y2 = _xdnd->rectangle.y + _xdnd->rectangle.height;
if ((e->win != _xdnd->dest) || (e->root.x < x1) || (e->root.x > x2) if (!(_xdnd->suppress) ||
|| (e->root.y < y1) || (e->root.y > y2)) ((e->root.x < x1) || (e->root.x > x2)
|| (e->root.y < y1) || (e->root.y > y2)))
{ {
_ecore_x_dnd_drag(e->root.x, e->root.y); _ecore_x_dnd_drag(e->root.x, e->root.y);
} }
@ -995,12 +996,12 @@ _ecore_x_event_handle_selection_clear(XEvent *xevent)
Atom sel; Atom sel;
if (!(d = _ecore_x_selection_get(xevent->xselectionclear.selection))) if (!(d = _ecore_x_selection_get(xevent->xselectionclear.selection)))
return; return;
if (xevent->xselectionclear.time > d->time) if (xevent->xselectionclear.time > d->time)
{ {
_ecore_x_selection_set(None, NULL, 0, _ecore_x_selection_set(None, NULL, 0,
xevent->xselectionclear.selection); xevent->xselectionclear.selection);
} }
/* Generate event for app cleanup */ /* Generate event for app cleanup */
e = malloc(sizeof(Ecore_X_Event_Selection_Clear)); e = malloc(sizeof(Ecore_X_Event_Selection_Clear));
@ -1008,13 +1009,13 @@ _ecore_x_event_handle_selection_clear(XEvent *xevent)
e->time = xevent->xselectionclear.time; e->time = xevent->xselectionclear.time;
sel = xevent->xselectionclear.selection; sel = xevent->xselectionclear.selection;
if (sel == ECORE_X_ATOM_SELECTION_PRIMARY) if (sel == ECORE_X_ATOM_SELECTION_PRIMARY)
e->selection = ECORE_X_SELECTION_PRIMARY; e->selection = ECORE_X_SELECTION_PRIMARY;
else if (sel == ECORE_X_ATOM_SELECTION_SECONDARY) else if (sel == ECORE_X_ATOM_SELECTION_SECONDARY)
e->selection = ECORE_X_SELECTION_SECONDARY; e->selection = ECORE_X_SELECTION_SECONDARY;
else else
e->selection = ECORE_X_SELECTION_CLIPBOARD; e->selection = ECORE_X_SELECTION_CLIPBOARD;
ecore_event_add(ECORE_X_EVENT_SELECTION_CLEAR, e, NULL, NULL); ecore_event_add(ECORE_X_EVENT_SELECTION_CLEAR, e, NULL, NULL);
} }
void void
@ -1022,11 +1023,9 @@ _ecore_x_event_handle_selection_request(XEvent *xevent)
{ {
Ecore_X_Selection_Data *sd; Ecore_X_Selection_Data *sd;
XSelectionEvent xnotify; XSelectionEvent xnotify;
XEvent *xev; XEvent xev;
void *data; void *data;
xev = calloc(1, sizeof(XEvent));
xnotify.type = SelectionNotify; xnotify.type = SelectionNotify;
xnotify.display = xevent->xselectionrequest.display; xnotify.display = xevent->xselectionrequest.display;
xnotify.requestor = xevent->xselectionrequest.requestor; xnotify.requestor = xevent->xselectionrequest.requestor;
@ -1034,37 +1033,36 @@ _ecore_x_event_handle_selection_request(XEvent *xevent)
xnotify.target = xevent->xselectionrequest.target; xnotify.target = xevent->xselectionrequest.target;
xnotify.time = CurrentTime; xnotify.time = CurrentTime;
if((sd = _ecore_x_selection_get(xnotify.selection)) if ((sd = _ecore_x_selection_get(xnotify.selection))
&& (sd->win == xevent->xselectionrequest.owner)) && (sd->win == xevent->xselectionrequest.owner))
{ {
if (_ecore_x_selection_convert(xnotify.selection, xnotify.target, if (!_ecore_x_selection_convert(xnotify.selection, xnotify.target,
&data) == -1) &data) == -1)
{ {
/* Refuse selection, conversion to requested target failed */ /* Refuse selection, conversion to requested target failed */
xnotify.property = None; xnotify.property = None;
} }
else else
{ {
/* FIXME: This does not properly handle large data transfers */ /* FIXME: This does not properly handle large data transfers */
ecore_x_window_prop_property_set(xevent->xselectionrequest.requestor, ecore_x_window_prop_property_set(xevent->xselectionrequest.requestor,
xevent->xselectionrequest.property, xevent->xselectionrequest.property,
xevent->xselectionrequest.target, xevent->xselectionrequest.target,
8, data, sd->length); 8, data, sd->length);
xnotify.property = xevent->xselectionrequest.property; xnotify.property = xevent->xselectionrequest.property;
free(data); free(data);
} }
} }
else else
{ {
xnotify.property = None; xnotify.property = None;
return; return;
} }
xev->xselection = xnotify; xev.xselection = xnotify;
XSendEvent(xevent->xselectionrequest.display, XSendEvent(xevent->xselectionrequest.display,
xevent->xselectionrequest.requestor, False, 0, xev); xevent->xselectionrequest.requestor, False, 0, &xev);
XFree(xev);
} }
void void
@ -1082,25 +1080,25 @@ _ecore_x_event_handle_selection_notify(XEvent *xevent)
e->target = _ecore_x_selection_target_get(xevent->xselection.target); e->target = _ecore_x_selection_target_get(xevent->xselection.target);
selection = xevent->xselection.selection; selection = xevent->xselection.selection;
if (selection == ECORE_X_ATOM_SELECTION_PRIMARY) if (selection == ECORE_X_ATOM_SELECTION_PRIMARY)
e->selection = ECORE_X_SELECTION_PRIMARY; e->selection = ECORE_X_SELECTION_PRIMARY;
else if (selection == ECORE_X_ATOM_SELECTION_SECONDARY) else if (selection == ECORE_X_ATOM_SELECTION_SECONDARY)
e->selection = ECORE_X_SELECTION_SECONDARY; e->selection = ECORE_X_SELECTION_SECONDARY;
else if (selection == ECORE_X_ATOM_SELECTION_XDND) else if (selection == ECORE_X_ATOM_SELECTION_XDND)
e->selection = ECORE_X_SELECTION_XDND; e->selection = ECORE_X_SELECTION_XDND;
else if (selection == ECORE_X_ATOM_SELECTION_CLIPBOARD) else if (selection == ECORE_X_ATOM_SELECTION_CLIPBOARD)
e->selection = ECORE_X_SELECTION_CLIPBOARD; e->selection = ECORE_X_SELECTION_CLIPBOARD;
else else
{ {
free(e); free(e);
return; return;
} }
if (!ecore_x_window_prop_property_get(e->win, xevent->xselection.property, if (!ecore_x_window_prop_property_get(e->win, xevent->xselection.property,
AnyPropertyType, 8, &data, &num_ret)) AnyPropertyType, 8, &data, &num_ret))
{ {
free(e); free(e);
return; return;
} }
sel_data.win = e->win; sel_data.win = e->win;
sel_data.selection = selection; sel_data.selection = selection;
@ -1108,7 +1106,6 @@ _ecore_x_event_handle_selection_notify(XEvent *xevent)
sel_data.length = num_ret; sel_data.length = num_ret;
_ecore_x_selection_request_data_set(sel_data); _ecore_x_selection_request_data_set(sel_data);
ecore_event_add(ECORE_X_EVENT_SELECTION_NOTIFY, e, _ecore_x_event_free_selection_notify, NULL); ecore_event_add(ECORE_X_EVENT_SELECTION_NOTIFY, e, _ecore_x_event_free_selection_notify, NULL);
} }
void void
@ -1259,7 +1256,6 @@ _ecore_x_event_handle_client_message(XEvent *xevent)
e->win = _xdnd->source; e->win = _xdnd->source;
e->target = _xdnd->dest; e->target = _xdnd->dest;
e->will_accept = _xdnd->will_accept; e->will_accept = _xdnd->will_accept;
e->suppress = _xdnd->suppress;
e->rectangle.x = _xdnd->rectangle.x; e->rectangle.x = _xdnd->rectangle.x;
e->rectangle.y = _xdnd->rectangle.y; e->rectangle.y = _xdnd->rectangle.y;
e->rectangle.width = _xdnd->rectangle.width; e->rectangle.width = _xdnd->rectangle.width;

View File

@ -362,7 +362,7 @@ _ecore_x_selection_target_get(Atom target)
else if (target == ECORE_X_ATOM_TEXT) else if (target == ECORE_X_ATOM_TEXT)
return strdup(ECORE_X_SELECTION_TARGET_TEXT); return strdup(ECORE_X_SELECTION_TARGET_TEXT);
else else
return strdup(ECORE_X_SELECTION_TARGET_TEXT); return NULL;
} }
static void static void
@ -481,7 +481,7 @@ ecore_x_selection_converter_atom_del(Ecore_X_Atom target)
} }
else else
{ {
if(prev_cnv) if (prev_cnv)
prev_cnv->next = cnv->next; prev_cnv->next = cnv->next;
else else
converters = NULL; /* This was the only converter */ converters = NULL; /* This was the only converter */
@ -521,25 +521,34 @@ _ecore_x_selection_convert(Atom selection, Atom target, void **data_ret)
sel = _ecore_x_selection_get(selection); sel = _ecore_x_selection_get(selection);
tgt_str = _ecore_x_selection_target_get(target); tgt_str = _ecore_x_selection_target_get(target);
for (cnv = converters; cnv; cnv = cnv->next) if (tgt_str)
{ {
if (cnv->target == target) for (cnv = converters; cnv; cnv = cnv->next)
{ {
int r; if (cnv->target == target)
r = cnv->convert(tgt_str, sel->data, sel->length, &data, &size);
if (r)
{ {
*data_ret = data; int r;
return r; r = cnv->convert(tgt_str, sel->data, sel->length, &data, &size);
if (r)
{
*data_ret = data;
return r;
}
else
return 0;
} }
else
return -1;
} }
free(tgt_str);
}
else
{
*data_ret = malloc(sel->length);
memcpy(*data_ret, sel->data, sel->length);
return 1;
} }
free(tgt_str); return 0;
return -1;
} }
/* TODO: We need to work out a mechanism for automatic conversion to any requested /* TODO: We need to work out a mechanism for automatic conversion to any requested