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;
int will_accept;
int suppress;
Ecore_X_Rectangle rectangle;
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 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 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_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);
else
ecore_x_window_prop_property_del(win, ECORE_X_ATOM_XDND_AWARE);
ecore_x_dnd_type_set(win, "text/plain", 1);
}
int
@ -180,6 +179,33 @@ ecore_x_dnd_begin(Ecore_X_Window source, unsigned char *data, int size)
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
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.data.l[0] = _xdnd->dest;
xev.xclient.data.l[1] = 0;
if (will_accept)
xev.xclient.data.l[1] |= 0x1UL;
if (!suppress)
@ -244,7 +271,8 @@ ecore_x_dnd_send_finished(void)
xev.xclient.window = _xdnd->source;
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)
{
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);
/* 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.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);
}
@ -298,12 +327,15 @@ _ecore_x_dnd_drag(int x, int y)
xev.xclient.window = win;
xev.xclient.message_type = ECORE_X_ATOM_XDND_ENTER;
xev.xclient.data.l[0] = _xdnd->source;
xev.xclient.data.l[1] = 0;
if (num > 3)
xev.xclient.data.l[1] |= 0x1UL;
else
xev.xclient.data.l[1] &= 0xfffffffeUL;
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)
xev.xclient.data.l[i + 2] = types[i];
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[1] = 0; /* Reserved */
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 */
XSendEvent(_ecore_x_disp, win, False, 0, &xev);
_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.data.l[0] = _xdnd->source;
xev.xclient.data.l[1] = 0;
xev.xclient.data.l[2] = CurrentTime;
xev.xclient.data.l[3] = 0;
xev.xclient.data.l[4] = 0;
xev.xclient.data.l[2] = _xdnd->time;
XSendEvent(_ecore_x_disp, win, False, 0, &xev);
}
else
@ -346,7 +376,7 @@ _ecore_x_dnd_drag(int x, int y)
xev.xclient.window = win;
xev.xclient.message_type = ECORE_X_ATOM_XDND_LEAVE;
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);
}
}

View File

@ -503,15 +503,16 @@ _ecore_x_event_handle_motion_notify(XEvent *xevent)
/* Xdnd handling */
_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 */
x1 = _xdnd->rectangle.x;
x2 = _xdnd->rectangle.x + _xdnd->rectangle.width;
y1 = _xdnd->rectangle.y;
y2 = _xdnd->rectangle.y + _xdnd->rectangle.height;
if ((e->win != _xdnd->dest) || (e->root.x < x1) || (e->root.x > x2)
|| (e->root.y < y1) || (e->root.y > y2))
if (!(_xdnd->suppress) ||
((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);
}
@ -995,12 +996,12 @@ _ecore_x_event_handle_selection_clear(XEvent *xevent)
Atom sel;
if (!(d = _ecore_x_selection_get(xevent->xselectionclear.selection)))
return;
return;
if (xevent->xselectionclear.time > d->time)
{
_ecore_x_selection_set(None, NULL, 0,
xevent->xselectionclear.selection);
}
{
_ecore_x_selection_set(None, NULL, 0,
xevent->xselectionclear.selection);
}
/* Generate event for app cleanup */
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;
sel = xevent->xselectionclear.selection;
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)
e->selection = ECORE_X_SELECTION_SECONDARY;
e->selection = ECORE_X_SELECTION_SECONDARY;
else
e->selection = ECORE_X_SELECTION_CLIPBOARD;
e->selection = ECORE_X_SELECTION_CLIPBOARD;
ecore_event_add(ECORE_X_EVENT_SELECTION_CLEAR, e, NULL, NULL);
}
void
@ -1022,11 +1023,9 @@ _ecore_x_event_handle_selection_request(XEvent *xevent)
{
Ecore_X_Selection_Data *sd;
XSelectionEvent xnotify;
XEvent *xev;
XEvent xev;
void *data;
xev = calloc(1, sizeof(XEvent));
xnotify.type = SelectionNotify;
xnotify.display = xevent->xselectionrequest.display;
xnotify.requestor = xevent->xselectionrequest.requestor;
@ -1034,37 +1033,36 @@ _ecore_x_event_handle_selection_request(XEvent *xevent)
xnotify.target = xevent->xselectionrequest.target;
xnotify.time = CurrentTime;
if((sd = _ecore_x_selection_get(xnotify.selection))
&& (sd->win == xevent->xselectionrequest.owner))
{
if (_ecore_x_selection_convert(xnotify.selection, xnotify.target,
&data) == -1)
{
/* Refuse selection, conversion to requested target failed */
xnotify.property = None;
}
else
{
/* FIXME: This does not properly handle large data transfers */
ecore_x_window_prop_property_set(xevent->xselectionrequest.requestor,
xevent->xselectionrequest.property,
xevent->xselectionrequest.target,
8, data, sd->length);
xnotify.property = xevent->xselectionrequest.property;
free(data);
}
}
if ((sd = _ecore_x_selection_get(xnotify.selection))
&& (sd->win == xevent->xselectionrequest.owner))
{
if (!_ecore_x_selection_convert(xnotify.selection, xnotify.target,
&data) == -1)
{
/* Refuse selection, conversion to requested target failed */
xnotify.property = None;
}
else
{
/* FIXME: This does not properly handle large data transfers */
ecore_x_window_prop_property_set(xevent->xselectionrequest.requestor,
xevent->xselectionrequest.property,
xevent->xselectionrequest.target,
8, data, sd->length);
xnotify.property = xevent->xselectionrequest.property;
free(data);
}
}
else
{
xnotify.property = None;
return;
}
xev->xselection = xnotify;
{
xnotify.property = None;
return;
}
xev.xselection = xnotify;
XSendEvent(xevent->xselectionrequest.display,
xevent->xselectionrequest.requestor, False, 0, xev);
XFree(xev);
xevent->xselectionrequest.requestor, False, 0, &xev);
}
void
@ -1082,25 +1080,25 @@ _ecore_x_event_handle_selection_notify(XEvent *xevent)
e->target = _ecore_x_selection_target_get(xevent->xselection.target);
selection = xevent->xselection.selection;
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)
e->selection = ECORE_X_SELECTION_SECONDARY;
e->selection = ECORE_X_SELECTION_SECONDARY;
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)
e->selection = ECORE_X_SELECTION_CLIPBOARD;
e->selection = ECORE_X_SELECTION_CLIPBOARD;
else
{
free(e);
return;
}
{
free(e);
return;
}
if (!ecore_x_window_prop_property_get(e->win, xevent->xselection.property,
AnyPropertyType, 8, &data, &num_ret))
{
free(e);
return;
}
AnyPropertyType, 8, &data, &num_ret))
{
free(e);
return;
}
sel_data.win = e->win;
sel_data.selection = selection;
@ -1108,7 +1106,6 @@ _ecore_x_event_handle_selection_notify(XEvent *xevent)
sel_data.length = num_ret;
_ecore_x_selection_request_data_set(sel_data);
ecore_event_add(ECORE_X_EVENT_SELECTION_NOTIFY, e, _ecore_x_event_free_selection_notify, NULL);
}
void
@ -1259,7 +1256,6 @@ _ecore_x_event_handle_client_message(XEvent *xevent)
e->win = _xdnd->source;
e->target = _xdnd->dest;
e->will_accept = _xdnd->will_accept;
e->suppress = _xdnd->suppress;
e->rectangle.x = _xdnd->rectangle.x;
e->rectangle.y = _xdnd->rectangle.y;
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)
return strdup(ECORE_X_SELECTION_TARGET_TEXT);
else
return strdup(ECORE_X_SELECTION_TARGET_TEXT);
return NULL;
}
static void
@ -481,7 +481,7 @@ ecore_x_selection_converter_atom_del(Ecore_X_Atom target)
}
else
{
if(prev_cnv)
if (prev_cnv)
prev_cnv->next = cnv->next;
else
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);
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;
r = cnv->convert(tgt_str, sel->data, sel->length, &data, &size);
if (r)
if (cnv->target == target)
{
*data_ret = data;
return r;
int 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 -1;
return 0;
}
/* TODO: We need to work out a mechanism for automatic conversion to any requested