2005-03-22 13:59:35 -08:00
|
|
|
/*
|
|
|
|
* vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
|
|
|
|
*/
|
2004-11-23 07:17:56 -08:00
|
|
|
#include "Ecore.h"
|
2004-02-04 23:14:56 -08:00
|
|
|
#include "ecore_x_private.h"
|
2004-11-23 07:17:56 -08:00
|
|
|
#include "Ecore_X.h"
|
2004-12-04 02:10:29 -08:00
|
|
|
#include "Ecore_X_Atoms.h"
|
2004-02-04 23:14:56 -08:00
|
|
|
|
2004-12-27 10:28:14 -08:00
|
|
|
static Ecore_X_DND_Protocol *_xdnd = NULL;
|
2004-12-27 10:30:28 -08:00
|
|
|
static int _ecore_x_dnd_init_count = 0;
|
2004-02-04 23:14:56 -08:00
|
|
|
|
|
|
|
void
|
2005-03-22 13:59:35 -08:00
|
|
|
_ecore_x_dnd_init(void)
|
2004-02-04 23:14:56 -08:00
|
|
|
{
|
2004-12-27 10:30:28 -08:00
|
|
|
if (!_ecore_x_dnd_init_count)
|
2005-03-22 13:59:35 -08:00
|
|
|
{
|
|
|
|
_xdnd = calloc(1, sizeof(Ecore_X_DND_Protocol));
|
2004-12-27 10:30:28 -08:00
|
|
|
|
2005-03-22 13:59:35 -08:00
|
|
|
_xdnd->version = ECORE_X_DND_VERSION;
|
|
|
|
_xdnd->source = None;
|
|
|
|
_xdnd->dest = None;
|
|
|
|
_xdnd->state = ECORE_X_DND_IDLE;
|
|
|
|
}
|
2004-12-27 10:28:14 -08:00
|
|
|
|
2005-03-22 13:59:35 -08:00
|
|
|
_ecore_x_dnd_init_count++;
|
2004-12-27 10:28:14 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
_ecore_x_dnd_shutdown(void)
|
|
|
|
{
|
2005-03-22 13:59:35 -08:00
|
|
|
_ecore_x_dnd_init_count--;
|
|
|
|
if (_ecore_x_dnd_init_count > 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (_xdnd)
|
|
|
|
free(_xdnd);
|
2004-12-27 10:28:14 -08:00
|
|
|
_xdnd = NULL;
|
2004-12-27 10:30:28 -08:00
|
|
|
_ecore_x_dnd_init_count = 0;
|
2004-02-04 23:14:56 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2005-03-22 13:59:35 -08:00
|
|
|
ecore_x_dnd_aware_set(Ecore_X_Window win, int on)
|
2004-02-04 23:14:56 -08:00
|
|
|
{
|
2004-02-05 21:32:51 -08:00
|
|
|
Atom prop_data = ECORE_X_DND_VERSION;
|
2005-03-22 13:59:35 -08:00
|
|
|
|
2004-02-04 23:14:56 -08:00
|
|
|
if (on)
|
2005-03-22 13:59:35 -08:00
|
|
|
ecore_x_window_prop_property_set(win, ECORE_X_ATOM_XDND_AWARE,
|
|
|
|
XA_ATOM, 32, &prop_data, 1);
|
2004-02-04 23:14:56 -08:00
|
|
|
else
|
2005-03-22 13:59:35 -08:00
|
|
|
ecore_x_window_prop_property_del(win, ECORE_X_ATOM_XDND_AWARE);
|
2004-02-04 23:14:56 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2005-03-22 13:59:35 -08:00
|
|
|
ecore_x_dnd_version_get(Ecore_X_Window win)
|
2004-02-04 23:14:56 -08:00
|
|
|
{
|
|
|
|
unsigned char *prop_data;
|
|
|
|
int num;
|
2005-03-22 13:59:35 -08:00
|
|
|
|
2004-12-04 02:10:29 -08:00
|
|
|
if (ecore_x_window_prop_property_get(win, ECORE_X_ATOM_XDND_AWARE,
|
2004-02-05 21:32:51 -08:00
|
|
|
XA_ATOM, 32, &prop_data, &num))
|
2005-03-22 13:59:35 -08:00
|
|
|
{
|
|
|
|
int version = (int) *prop_data;
|
|
|
|
free(prop_data);
|
|
|
|
return version;
|
|
|
|
}
|
2004-02-04 23:14:56 -08:00
|
|
|
else
|
2005-03-22 13:59:35 -08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
ecore_x_dnd_type_isset(Ecore_X_Window win, const char *type)
|
|
|
|
{
|
|
|
|
int num, i, ret = 0;
|
|
|
|
unsigned char *data;
|
|
|
|
Ecore_X_Atom *atoms, atom;
|
|
|
|
|
|
|
|
if (!ecore_x_window_prop_property_get(win, ECORE_X_ATOM_XDND_TYPE_LIST,
|
|
|
|
XA_ATOM, 32, &data, &num))
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
atom = ecore_x_atom_get(type);
|
|
|
|
atoms = (Ecore_X_Atom *)data;
|
|
|
|
|
|
|
|
for (i = 0; i < num; ++i)
|
|
|
|
{
|
|
|
|
if (atom == atoms[i])
|
|
|
|
{
|
|
|
|
ret = 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
XFree(data);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
ecore_x_dnd_type_set(Ecore_X_Window win, const char *type, int on)
|
|
|
|
{
|
|
|
|
Ecore_X_Atom atom;
|
|
|
|
Ecore_X_Atom *oldset = NULL, *newset = NULL;
|
|
|
|
int i, j = 0, num = 0;
|
|
|
|
unsigned char *data = NULL;
|
|
|
|
unsigned char *old_data = NULL;
|
|
|
|
|
|
|
|
atom = ecore_x_atom_get(type);
|
|
|
|
ecore_x_window_prop_property_get(win, ECORE_X_ATOM_XDND_TYPE_LIST,
|
|
|
|
XA_ATOM, 32, &old_data, &num);
|
|
|
|
oldset = (Ecore_X_Atom *)old_data;
|
|
|
|
|
|
|
|
if (on)
|
|
|
|
{
|
|
|
|
if (ecore_x_dnd_type_isset(win, type))
|
|
|
|
{
|
|
|
|
XFree(old_data);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
newset = calloc(num + 1, sizeof(Ecore_X_Atom));
|
|
|
|
if (!newset) return;
|
|
|
|
data = (unsigned char *)newset;
|
|
|
|
|
|
|
|
for (i = 0; i < num; i++)
|
|
|
|
newset[i + 1] = oldset[i];
|
|
|
|
/* prepend the new type */
|
|
|
|
newset[0] = atom;
|
|
|
|
|
|
|
|
ecore_x_window_prop_property_set(win, ECORE_X_ATOM_XDND_TYPE_LIST,
|
|
|
|
XA_ATOM, 32, data, num + 1);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (!ecore_x_dnd_type_isset(win, type))
|
|
|
|
{
|
|
|
|
XFree(old_data);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
newset = calloc(num - 1, sizeof(Atom));
|
|
|
|
if (!newset)
|
|
|
|
{
|
|
|
|
XFree(old_data);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
data = (unsigned char *)newset;
|
|
|
|
for (i = 0; i < num; i++)
|
|
|
|
if (oldset[i] != atom)
|
|
|
|
newset[j++] = oldset[i];
|
|
|
|
|
|
|
|
ecore_x_window_prop_property_set(win, ECORE_X_ATOM_XDND_TYPE_LIST,
|
|
|
|
XA_ATOM, 32, data, num - 1);
|
|
|
|
}
|
|
|
|
XFree(oldset);
|
|
|
|
free(newset);
|
|
|
|
}
|
2004-02-04 23:14:56 -08:00
|
|
|
|
|
|
|
Ecore_X_DND_Protocol *
|
2005-03-22 13:59:35 -08:00
|
|
|
_ecore_x_dnd_protocol_get(void)
|
2004-02-04 23:14:56 -08:00
|
|
|
{
|
|
|
|
return _xdnd;
|
|
|
|
}
|
|
|
|
|
2005-03-22 13:59:35 -08:00
|
|
|
int
|
|
|
|
ecore_x_dnd_begin(Ecore_X_Window source, unsigned char *data, int size)
|
2004-02-04 23:14:56 -08:00
|
|
|
{
|
2004-02-05 21:32:51 -08:00
|
|
|
|
|
|
|
if (!ecore_x_dnd_version_get(source))
|
2005-03-22 13:59:35 -08:00
|
|
|
return 0;
|
|
|
|
|
2004-02-04 23:14:56 -08:00
|
|
|
/* Take ownership of XdndSelection */
|
2005-03-23 02:53:34 -08:00
|
|
|
if (!ecore_x_selection_xdnd_set(source, data, size))
|
2005-03-22 13:59:35 -08:00
|
|
|
return 0;
|
|
|
|
|
2004-02-04 23:14:56 -08:00
|
|
|
_xdnd->source = source;
|
2004-02-05 21:32:51 -08:00
|
|
|
_xdnd->state = ECORE_X_DND_DRAGGING;
|
2004-02-21 00:58:20 -08:00
|
|
|
_xdnd->time = _ecore_x_event_last_time;
|
2004-02-04 23:14:56 -08:00
|
|
|
|
2004-04-23 15:17:01 -07:00
|
|
|
/* Default Accepted Action: ask */
|
2004-12-04 02:10:29 -08:00
|
|
|
_xdnd->action = ECORE_X_ATOM_XDND_ACTION_ASK;
|
2004-04-23 15:17:01 -07:00
|
|
|
_xdnd->accepted_action = None;
|
2004-02-04 23:14:56 -08:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2005-03-23 10:33:50 -08:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-03-22 13:59:35 -08:00
|
|
|
void
|
2004-02-07 11:37:47 -08:00
|
|
|
ecore_x_dnd_send_status(int will_accept, int suppress, Ecore_X_Rectangle rectangle, Ecore_X_Atom action)
|
|
|
|
{
|
|
|
|
XEvent xev;
|
|
|
|
|
2005-03-22 13:59:35 -08:00
|
|
|
if (_xdnd->state == ECORE_X_DND_IDLE ||
|
2004-02-07 11:37:47 -08:00
|
|
|
_xdnd->state == ECORE_X_DND_FINISHED)
|
2005-03-22 13:59:35 -08:00
|
|
|
return;
|
2004-02-07 11:37:47 -08:00
|
|
|
|
|
|
|
memset(&xev, 0, sizeof(XEvent));
|
|
|
|
|
|
|
|
_xdnd->rectangle.x = rectangle.x;
|
|
|
|
_xdnd->rectangle.y = rectangle.y;
|
|
|
|
_xdnd->rectangle.width = rectangle.width;
|
|
|
|
_xdnd->rectangle.height = rectangle.height;
|
|
|
|
_xdnd->will_accept = will_accept;
|
|
|
|
_xdnd->suppress = suppress;
|
|
|
|
|
|
|
|
xev.xclient.type = ClientMessage;
|
|
|
|
xev.xclient.display = _ecore_x_disp;
|
2004-12-04 02:10:29 -08:00
|
|
|
xev.xclient.message_type = ECORE_X_ATOM_XDND_STATUS;
|
2004-02-07 11:37:47 -08:00
|
|
|
xev.xclient.format = 32;
|
|
|
|
xev.xclient.window = _xdnd->source;
|
|
|
|
|
|
|
|
xev.xclient.data.l[0] = _xdnd->dest;
|
2005-03-23 10:33:50 -08:00
|
|
|
xev.xclient.data.l[1] = 0;
|
2004-02-07 11:37:47 -08:00
|
|
|
if (will_accept)
|
2005-03-22 13:59:35 -08:00
|
|
|
xev.xclient.data.l[1] |= 0x1UL;
|
2004-02-07 11:37:47 -08:00
|
|
|
if (!suppress)
|
2005-03-22 13:59:35 -08:00
|
|
|
xev.xclient.data.l[1] |= 0x2UL;
|
|
|
|
|
2004-02-07 11:37:47 -08:00
|
|
|
/* Set rectangle information */
|
|
|
|
xev.xclient.data.l[2] = rectangle.x;
|
|
|
|
xev.xclient.data.l[2] <<= 16;
|
|
|
|
xev.xclient.data.l[2] |= rectangle.y;
|
|
|
|
xev.xclient.data.l[3] = rectangle.width;
|
|
|
|
xev.xclient.data.l[3] <<= 16;
|
|
|
|
xev.xclient.data.l[3] |= rectangle.height;
|
|
|
|
|
|
|
|
if (will_accept)
|
2005-03-22 13:59:35 -08:00
|
|
|
{
|
|
|
|
xev.xclient.data.l[4] = action;
|
|
|
|
_xdnd->accepted_action = action;
|
|
|
|
}
|
2004-02-07 11:37:47 -08:00
|
|
|
else
|
2005-03-22 13:59:35 -08:00
|
|
|
{
|
|
|
|
xev.xclient.data.l[4] = None;
|
|
|
|
_xdnd->accepted_action = action;
|
|
|
|
}
|
2004-02-07 11:37:47 -08:00
|
|
|
|
|
|
|
XSendEvent(_ecore_x_disp, _xdnd->source, False, 0, &xev);
|
|
|
|
}
|
2004-02-29 00:15:47 -08:00
|
|
|
|
2005-03-23 02:53:34 -08:00
|
|
|
void
|
|
|
|
ecore_x_dnd_send_finished(void)
|
|
|
|
{
|
|
|
|
XEvent xev;
|
|
|
|
|
|
|
|
xev.xany.type = ClientMessage;
|
|
|
|
xev.xany.display = _ecore_x_disp;
|
|
|
|
xev.xclient.message_type = ECORE_X_ATOM_XDND_FINISHED;
|
|
|
|
xev.xclient.format = 32;
|
2005-03-23 07:40:53 -08:00
|
|
|
xev.xclient.window = _xdnd->source;
|
2005-03-23 02:53:34 -08:00
|
|
|
|
|
|
|
xev.xclient.data.l[0] = _xdnd->dest;
|
2005-03-23 10:33:50 -08:00
|
|
|
xev.xclient.data.l[1] = 0;
|
|
|
|
xev.xclient.data.l[2] = 0;
|
2005-03-23 02:53:34 -08:00
|
|
|
if (_xdnd->will_accept)
|
|
|
|
{
|
|
|
|
xev.xclient.data.l[1] |= 0x1UL;
|
|
|
|
xev.xclient.data.l[2] = _xdnd->accepted_action;
|
|
|
|
}
|
|
|
|
XSendEvent(_ecore_x_disp, _xdnd->source, False, 0, &xev);
|
|
|
|
}
|
|
|
|
|
2004-02-29 00:15:47 -08:00
|
|
|
void
|
|
|
|
_ecore_x_dnd_drag(int x, int y)
|
|
|
|
{
|
|
|
|
XEvent xev;
|
|
|
|
Ecore_X_Window win;
|
2005-03-22 13:59:35 -08:00
|
|
|
|
2004-02-29 00:15:47 -08:00
|
|
|
/* Preinitialize XEvent struct */
|
|
|
|
memset(&xev, 0, sizeof(XEvent));
|
|
|
|
xev.xany.type = ClientMessage;
|
|
|
|
xev.xany.display = _ecore_x_disp;
|
|
|
|
xev.xclient.format = 32;
|
|
|
|
|
|
|
|
/* Attempt to find a DND-capable window under the cursor */
|
|
|
|
win = ecore_x_window_at_xy_get(x, y);
|
|
|
|
while ((win) && !(ecore_x_dnd_version_get(win)))
|
2005-03-22 13:59:35 -08:00
|
|
|
win = ecore_x_window_parent_get(win);
|
2004-02-29 00:15:47 -08:00
|
|
|
|
|
|
|
/* Send XdndLeave to current destination window if we have left it */
|
2005-03-23 10:33:50 -08:00
|
|
|
if ((_xdnd->dest) && (win != _xdnd->dest))
|
2005-03-22 13:59:35 -08:00
|
|
|
{
|
|
|
|
xev.xclient.window = _xdnd->dest;
|
|
|
|
xev.xclient.message_type = ECORE_X_ATOM_XDND_LEAVE;
|
|
|
|
xev.xclient.data.l[0] = _xdnd->source;
|
2005-03-23 10:33:50 -08:00
|
|
|
xev.xclient.data.l[1] = 0;
|
2004-02-29 00:15:47 -08:00
|
|
|
|
2005-03-22 13:59:35 -08:00
|
|
|
XSendEvent(_ecore_x_disp, _xdnd->dest, False, 0, &xev);
|
|
|
|
}
|
2004-02-29 00:15:47 -08:00
|
|
|
|
|
|
|
if (win)
|
2005-03-22 13:59:35 -08:00
|
|
|
{
|
|
|
|
_xdnd->version = MIN(ECORE_X_DND_VERSION,
|
|
|
|
ecore_x_dnd_version_get(win));
|
|
|
|
if (win != _xdnd->dest)
|
|
|
|
{
|
2005-03-23 02:53:34 -08:00
|
|
|
int i, num;
|
|
|
|
unsigned char *data;
|
|
|
|
Ecore_X_Atom *types;
|
|
|
|
|
|
|
|
ecore_x_window_prop_property_get(_xdnd->source, ECORE_X_ATOM_XDND_TYPE_LIST,
|
|
|
|
XA_ATOM, 32, &data, &num);
|
|
|
|
types = (Ecore_X_Atom *)data;
|
2005-03-22 13:59:35 -08:00
|
|
|
|
|
|
|
/* Entered new window, send XdndEnter */
|
|
|
|
xev.xclient.window = win;
|
|
|
|
xev.xclient.message_type = ECORE_X_ATOM_XDND_ENTER;
|
|
|
|
xev.xclient.data.l[0] = _xdnd->source;
|
2005-03-23 10:33:50 -08:00
|
|
|
xev.xclient.data.l[1] = 0;
|
2005-03-23 02:53:34 -08:00
|
|
|
if (num > 3)
|
2005-03-22 13:59:35 -08:00
|
|
|
xev.xclient.data.l[1] |= 0x1UL;
|
|
|
|
else
|
|
|
|
xev.xclient.data.l[1] &= 0xfffffffeUL;
|
|
|
|
xev.xclient.data.l[1] |= ((unsigned long) _xdnd->version) << 24;
|
|
|
|
|
2005-03-23 10:33:50 -08:00
|
|
|
for (i = 2; i < 5; i++)
|
|
|
|
xev.xclient.data.l[i] = 0;
|
2005-03-23 02:53:34 -08:00
|
|
|
for (i = 0; i < MIN(num, 3); ++i)
|
|
|
|
xev.xclient.data.l[i + 2] = types[i];
|
|
|
|
XFree(data);
|
2005-03-22 13:59:35 -08:00
|
|
|
XSendEvent(_ecore_x_disp, win, False, 0, &xev);
|
|
|
|
_xdnd->await_status = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* FIXME: Handle box information */
|
|
|
|
/*if (!_xdnd->await_status)
|
|
|
|
{*/
|
|
|
|
xev.xclient.window = win;
|
|
|
|
xev.xclient.message_type = ECORE_X_ATOM_XDND_POSITION;
|
|
|
|
xev.xclient.data.l[0] = _xdnd->source;
|
|
|
|
xev.xclient.data.l[1] = 0; /* Reserved */
|
|
|
|
xev.xclient.data.l[2] = ((x << 16) & 0xffff0000) | (y & 0xffff);
|
2005-03-23 10:33:50 -08:00
|
|
|
xev.xclient.data.l[3] = _xdnd->time; /* Version 1 */
|
2005-03-22 13:59:35 -08:00
|
|
|
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;
|
|
|
|
/*}*/
|
|
|
|
}
|
2004-02-29 00:15:47 -08:00
|
|
|
|
|
|
|
if (_xdnd->state == ECORE_X_DND_DROPPED)
|
2005-03-22 13:59:35 -08:00
|
|
|
{
|
|
|
|
if (win)
|
|
|
|
{
|
|
|
|
if (_xdnd->will_accept)
|
|
|
|
{
|
|
|
|
xev.xclient.window = win;
|
|
|
|
xev.xclient.message_type = ECORE_X_ATOM_XDND_DROP;
|
|
|
|
xev.xclient.data.l[0] = _xdnd->source;
|
|
|
|
xev.xclient.data.l[1] = 0;
|
2005-03-23 10:33:50 -08:00
|
|
|
xev.xclient.data.l[2] = _xdnd->time;
|
2005-03-22 13:59:35 -08:00
|
|
|
XSendEvent(_ecore_x_disp, win, False, 0, &xev);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
xev.xclient.window = win;
|
|
|
|
xev.xclient.message_type = ECORE_X_ATOM_XDND_LEAVE;
|
|
|
|
xev.xclient.data.l[0] = _xdnd->source;
|
2005-03-23 10:33:50 -08:00
|
|
|
xev.xclient.data.l[1] = 0;
|
2005-03-22 13:59:35 -08:00
|
|
|
XSendEvent(_ecore_x_disp, win, False, 0, &xev);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
_xdnd->will_accept = 0;
|
|
|
|
}
|
2004-02-29 00:15:47 -08:00
|
|
|
_xdnd->dest = win;
|
|
|
|
}
|
|
|
|
|