The start of some dnd cleanups.

- Formatting
- ecore_x_dnd_type_set() to set the type of a dnd object
- Fix SelectionNotify to accept dnd
- ecore_x_selection_xdnd_request_data_get() to get the data from a drop


SVN revision: 13866
This commit is contained in:
sebastid 2005-03-22 21:59:35 +00:00 committed by sebastid
parent 59de2993b3
commit 40658606dd
5 changed files with 249 additions and 133 deletions

View File

@ -75,6 +75,7 @@ extern EAPI Ecore_X_Atom ECORE_X_DND_ACTION_PRIVATE;
typedef enum _Ecore_X_Selection {
ECORE_X_SELECTION_PRIMARY,
ECORE_X_SELECTION_SECONDARY,
ECORE_X_SELECTION_XDND,
ECORE_X_SELECTION_CLIPBOARD
} Ecore_X_Selection;
@ -809,6 +810,7 @@ EAPI void ecore_x_selection_secondary_request(Ecore_X_Window w, char
EAPI void ecore_x_selection_clipboard_request(Ecore_X_Window w, char *target);
EAPI void ecore_x_selection_primary_request_data_get(void **buf, int *len);
EAPI void ecore_x_selection_secondary_request_data_get(void **buf, int *len);
EAPI void ecore_x_selection_xdnd_request_data_get(void **buf, int *len);
EAPI void ecore_x_selection_clipboard_request_data_get(void **buf, int *len);
EAPI void ecore_x_selection_converter_add(char *target, int (*func)(char *target, void *data, int size, void **data_ret, int *size_ret));
EAPI void ecore_x_selection_converter_atom_add(Ecore_X_Atom target, int (*func)(char *target, void *data, int size, void **data_ret, int *size_ret));
@ -817,7 +819,9 @@ EAPI void ecore_x_selection_converter_atom_del(Ecore_X_Atom target);
EAPI void ecore_x_dnd_aware_set(Ecore_X_Window win, int on);
EAPI int ecore_x_dnd_version_get(Ecore_X_Window win);
EAPI int ecore_x_dnd_begin (Ecore_X_Window source, unsigned char *data, int size);
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_send_status(int will_accept, int suppress, Ecore_X_Rectangle rectangle, Ecore_X_Atom action);
EAPI Ecore_X_Window ecore_x_window_new(Ecore_X_Window parent, int x, int y, int w, int h);

View File

@ -1,3 +1,6 @@
/*
* vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
*/
#include "Ecore.h"
#include "ecore_x_private.h"
#include "Ecore_X.h"
@ -8,88 +11,177 @@ static Ecore_X_DND_Protocol *_xdnd = NULL;
static int _ecore_x_dnd_init_count = 0;
void
_ecore_x_dnd_init (void)
_ecore_x_dnd_init(void)
{
if (!_ecore_x_dnd_init_count)
{
_xdnd = calloc(1, sizeof(Ecore_X_DND_Protocol));
_xdnd->version = ECORE_X_DND_VERSION;
_xdnd->source = None;
_xdnd->dest = None;
_xdnd->state = ECORE_X_DND_IDLE;
}
{
_xdnd = calloc(1, sizeof(Ecore_X_DND_Protocol));
_xdnd->version = ECORE_X_DND_VERSION;
_xdnd->source = None;
_xdnd->dest = None;
_xdnd->state = ECORE_X_DND_IDLE;
}
_ecore_x_dnd_init_count++;
}
void
_ecore_x_dnd_shutdown(void)
{
if(_xdnd)
free(_xdnd);
_ecore_x_dnd_init_count--;
if (_ecore_x_dnd_init_count > 0)
return;
if (_xdnd)
free(_xdnd);
_xdnd = NULL;
_ecore_x_dnd_init_count = 0;
}
void
ecore_x_dnd_aware_set (Ecore_X_Window win, int on)
ecore_x_dnd_aware_set(Ecore_X_Window win, int on)
{
Atom prop_data = ECORE_X_DND_VERSION;
if (on)
ecore_x_window_prop_property_set(win, ECORE_X_ATOM_XDND_AWARE,
XA_ATOM, 32, &prop_data, 1);
ecore_x_window_prop_property_set(win, ECORE_X_ATOM_XDND_AWARE,
XA_ATOM, 32, &prop_data, 1);
else
ecore_x_window_prop_property_del(win, ECORE_X_ATOM_XDND_AWARE);
/* TODO: Add dnd typelist to window properties */
ecore_x_window_prop_property_del(win, ECORE_X_ATOM_XDND_AWARE);
ecore_x_dnd_type_set(win, "text/plain", 1);
}
int
ecore_x_dnd_version_get (Ecore_X_Window win)
ecore_x_dnd_version_get(Ecore_X_Window win)
{
unsigned char *prop_data;
int num;
if (ecore_x_window_prop_property_get(win, ECORE_X_ATOM_XDND_AWARE,
XA_ATOM, 32, &prop_data, &num))
{
int version = (int) *prop_data;
free(prop_data);
return version;
}
{
int version = (int) *prop_data;
free(prop_data);
return version;
}
else
return 0;
}
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);
}
Ecore_X_DND_Protocol *
_ecore_x_dnd_protocol_get (void)
_ecore_x_dnd_protocol_get(void)
{
return _xdnd;
}
int
ecore_x_dnd_begin (Ecore_X_Window source, unsigned char *data, int size)
int
ecore_x_dnd_begin(Ecore_X_Window source, unsigned char *data, int size)
{
unsigned char *buf;
Atom _type_text_plain; /* FIXME: API-ize this stuff */
unsigned char *atoms;
int num;
if (!ecore_x_dnd_version_get(source))
return 0;
return 0;
/* Take ownership of XdndSelection */
XSetSelectionOwner(_ecore_x_disp, ECORE_X_ATOM_SELECTION_XDND, source,
_ecore_x_event_last_time);
if (XGetSelectionOwner(_ecore_x_disp, ECORE_X_ATOM_SELECTION_XDND) != source)
return 0;
return 0;
/* Initialize Selection Data Struct */
_xdnd_selection.win = source;
_xdnd_selection.selection = ECORE_X_ATOM_SELECTION_XDND;
_xdnd_selection.length = size;
_xdnd_selection.time = _ecore_x_event_last_time;
buf = malloc(size);
memcpy(buf, data, size);
_xdnd_selection.data = buf;
@ -102,22 +194,21 @@ ecore_x_dnd_begin (Ecore_X_Window source, unsigned char *data, int size)
_xdnd->action = ECORE_X_ATOM_XDND_ACTION_ASK;
_xdnd->accepted_action = None;
/* TODO: Set supported data types in API */
_type_text_plain = ecore_x_atom_get("text/plain");
_xdnd->num_types = 1;
_xdnd->types = (Atom *) calloc(1, sizeof(Atom));
_xdnd->types[0] = _type_text_plain;
ecore_x_window_prop_property_get(source, ECORE_X_ATOM_XDND_TYPE_LIST,
XA_ATOM, 32, &atoms, &num);
_xdnd->num_types = num;
_xdnd->types = (Ecore_X_Atom *)atoms;
return 1;
}
void
void
ecore_x_dnd_send_status(int will_accept, int suppress, Ecore_X_Rectangle rectangle, Ecore_X_Atom action)
{
XEvent xev;
if (_xdnd->state == ECORE_X_DND_IDLE ||
if (_xdnd->state == ECORE_X_DND_IDLE ||
_xdnd->state == ECORE_X_DND_FINISHED)
return;
return;
memset(&xev, 0, sizeof(XEvent));
@ -136,10 +227,10 @@ ecore_x_dnd_send_status(int will_accept, int suppress, Ecore_X_Rectangle rectang
xev.xclient.data.l[0] = _xdnd->dest;
if (will_accept)
xev.xclient.data.l[1] |= 0x1UL;
xev.xclient.data.l[1] |= 0x1UL;
if (!suppress)
xev.xclient.data.l[1] |= 0x2UL;
xev.xclient.data.l[1] |= 0x2UL;
/* Set rectangle information */
xev.xclient.data.l[2] = rectangle.x;
xev.xclient.data.l[2] <<= 16;
@ -149,15 +240,15 @@ ecore_x_dnd_send_status(int will_accept, int suppress, Ecore_X_Rectangle rectang
xev.xclient.data.l[3] |= rectangle.height;
if (will_accept)
{
xev.xclient.data.l[4] = action;
_xdnd->accepted_action = action;
}
{
xev.xclient.data.l[4] = action;
_xdnd->accepted_action = action;
}
else
{
xev.xclient.data.l[4] = None;
_xdnd->accepted_action = action;
}
{
xev.xclient.data.l[4] = None;
_xdnd->accepted_action = action;
}
XSendEvent(_ecore_x_disp, _xdnd->source, False, 0, &xev);
}
@ -167,7 +258,7 @@ _ecore_x_dnd_drag(int x, int y)
{
XEvent xev;
Ecore_X_Window win;
/* Preinitialize XEvent struct */
memset(&xev, 0, sizeof(XEvent));
xev.xany.type = ClientMessage;
@ -177,89 +268,89 @@ _ecore_x_dnd_drag(int x, int y)
/* 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)))
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 */
if ((win != _xdnd->dest) && (_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.window = _xdnd->dest;
xev.xclient.message_type = ECORE_X_ATOM_XDND_LEAVE;
xev.xclient.data.l[0] = _xdnd->source;
XSendEvent(_ecore_x_disp, _xdnd->dest, False, 0, &xev);
}
XSendEvent(_ecore_x_disp, _xdnd->dest, False, 0, &xev);
}
if (win)
{
_xdnd->version = MIN(ECORE_X_DND_VERSION,
ecore_x_dnd_version_get(win));
if (win != _xdnd->dest)
{
int i;
/* 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;
if(_xdnd->num_types > 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 = 0; i < MIN(_xdnd->num_types, 3); ++i)
xev.xclient.data.l[i + 2] = _xdnd->types[i];
XSendEvent(_ecore_x_disp, win, False, 0, &xev);
_xdnd->await_status = 0;
}
{
_xdnd->version = MIN(ECORE_X_DND_VERSION,
ecore_x_dnd_version_get(win));
if (win != _xdnd->dest)
{
int i;
/* 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);
xev.xclient.data.l[3] = CurrentTime; /* 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;
/*}*/
}
/* 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;
if(_xdnd->num_types > 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 = 0; i < MIN(_xdnd->num_types, 3); ++i)
xev.xclient.data.l[i + 2] = _xdnd->types[i];
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);
xev.xclient.data.l[3] = CurrentTime; /* 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;
/*}*/
}
if (_xdnd->state == ECORE_X_DND_DROPPED)
{
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;
xev.xclient.data.l[2] = CurrentTime;
xev.xclient.data.l[3] = 0;
xev.xclient.data.l[4] = 0;
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;
memset(xev.xclient.data.l + 1, 0, sizeof(long) * 3); /* Evil */
XSendEvent(_ecore_x_disp, win, False, 0, &xev);
}
}
{
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;
xev.xclient.data.l[2] = CurrentTime;
xev.xclient.data.l[3] = 0;
xev.xclient.data.l[4] = 0;
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;
memset(xev.xclient.data.l + 1, 0, sizeof(long) * 3); /* Evil */
XSendEvent(_ecore_x_disp, win, False, 0, &xev);
}
}
_xdnd->will_accept = 0;
}
_xdnd->will_accept = 0;
}
_xdnd->dest = win;
}
#if 0 /* Unused? */
void
void
_ecore_x_dnd_send_finished(void)
{
XEvent xev;

View File

@ -982,7 +982,7 @@ _ecore_x_event_handle_selection_clear(XEvent *xevent)
Ecore_X_Event_Selection_Clear *e;
Atom sel;
if(!(d = _ecore_x_selection_get(xevent->xselectionclear.selection)))
if (!(d = _ecore_x_selection_get(xevent->xselectionclear.selection)))
return;
if (xevent->xselectionclear.time > d->time)
{
@ -1073,6 +1073,8 @@ _ecore_x_event_handle_selection_notify(XEvent *xevent)
e->selection = ECORE_X_SELECTION_PRIMARY;
else if (selection == ECORE_X_ATOM_SELECTION_SECONDARY)
e->selection = ECORE_X_SELECTION_SECONDARY;
else if (selection == ECORE_X_ATOM_SELECTION_XDND)
e->selection = ECORE_X_SELECTION_XDND;
else if (selection == ECORE_X_ATOM_SELECTION_CLIPBOARD)
e->selection = ECORE_X_SELECTION_CLIPBOARD;
else

View File

@ -90,9 +90,9 @@ typedef struct _Ecore_X_DND_Protocol
} pos;
Time time;
Atom *types;
Atom action, accepted_action;
Ecore_X_Atom *types;
Ecore_X_Atom action, accepted_action;
int num_types;
int will_accept;

View File

@ -7,7 +7,7 @@
#include "Ecore_X_Atoms.h"
static Ecore_X_Selection_Data selections[3];
static Ecore_X_Selection_Data request_data[3];
static Ecore_X_Selection_Data request_data[4];
static Ecore_X_Selection_Converter *converters = NULL;
static int _ecore_x_selection_converter_text(char *target, void *data, int size, void **data_ret, int *size_ret);
@ -59,8 +59,10 @@ _ecore_x_selection_request_data_get(Ecore_X_Atom selection, void **buf, int *len
i = 0;
else if (selection == ECORE_X_ATOM_SELECTION_SECONDARY)
i = 1;
else if (selection == ECORE_X_ATOM_SELECTION_CLIPBOARD)
else if (selection == ECORE_X_ATOM_SELECTION_XDND)
i = 2;
else if (selection == ECORE_X_ATOM_SELECTION_CLIPBOARD)
i = 3;
else
return;
@ -108,6 +110,21 @@ ecore_x_selection_secondary_request_data_get(void **buf, int *len)
buf, len);
}
/**
* Fetch the data returned by a XDND selection request.
* @param buf A pointer to hold the selection data
* @param len The size of the data
*
* Get the converted data from a previous XDND selection
* request. The buffer must be freed when done with.
*/
void
ecore_x_selection_xdnd_request_data_get(void **buf, int *len)
{
_ecore_x_selection_request_data_get(ECORE_X_ATOM_SELECTION_XDND,
buf, len);
}
/**
* Fetch the data returned by a CLIPBOARD selection request.
* @param buf A pointer to hold the selection data
@ -131,8 +148,10 @@ _ecore_x_selection_request_data_set(Ecore_X_Selection_Data data)
i = 0;
else if (data.selection == ECORE_X_ATOM_SELECTION_SECONDARY)
i = 1;
else if (data.selection == ECORE_X_ATOM_SELECTION_CLIPBOARD)
else if (data.selection == ECORE_X_ATOM_SELECTION_XDND)
i = 2;
else if (data.selection == ECORE_X_ATOM_SELECTION_CLIPBOARD)
i = 3;
else
return;