1
/* Many part of code are ripped of an example from JX's site */
8
#include "WindowMaker.h"
14
#include "workspace.h"
19
#include <X11/Xatom.h>
22
#define XDND_VERSION 3L
28
Atom _XA_XdndPosition;
30
Atom _XA_XdndActionCopy;
31
Atom _XA_XdndSelection;
32
Atom _XA_XdndFinished;
33
Atom _XA_WINDOWMAKER_XDNDEXCHANGE;
36
Atom _XA_MOTIF_DRAG_RECEIVER_INFO;
37
Atom _XA_MOTIF_DRAG_AND_DROP_MESSAGE;
43
wXDNDInitializeAtoms()
46
_XA_XdndAware = XInternAtom(dpy, "XdndAware", False);
47
_XA_XdndEnter = XInternAtom(dpy, "XdndEnter", False);
48
_XA_XdndLeave = XInternAtom(dpy, "XdndLeave", False);
49
_XA_XdndDrop = XInternAtom(dpy, "XdndDrop", False);
50
_XA_XdndPosition = XInternAtom(dpy, "XdndPosition", False);
51
_XA_XdndStatus = XInternAtom(dpy, "XdndStatus", False);
52
_XA_XdndActionCopy = XInternAtom(dpy, "XdndActionCopy", False);
53
_XA_XdndSelection = XInternAtom(dpy, "XdndSelection", False);
54
_XA_XdndFinished = XInternAtom(dpy, "XdndFinished", False);
56
_XA_WINDOWMAKER_XDNDEXCHANGE = XInternAtom(dpy, "_WINDOWMAKER_XDNDEXCHANGE", False);
59
_XA_MOTIF_DRAG_RECEIVER_INFO = XInternAtom(dpy, "_MOTIF_DRAG_RECEIVER_INFO",False);
60
_XA_MOTIF_DRAG_AND_DROP_MESSAGE = XInternAtom(dpy, "_MOTIF_DRAG_AND_DROP_MESSAGE", False);
65
wXDNDMakeAwareness(Window window)
67
long int xdnd_version = 3;
69
MotifDragReceiverInfo info;
71
XChangeProperty (dpy, window, _XA_XdndAware, XA_ATOM,
72
32, PropModeAppend, (char *)&xdnd_version, 1);
75
info.byte_order = '\0';
76
info.protocol_version = 0;
77
info.protocol_style = XmDRAG_DYNAMIC;
78
info.proxy_window = 0;
79
info.num_drop_sites = 0;
80
info.total_size = sizeof(info);
82
XChangeProperty (dpy, window,
83
_XA_MOTIF_DRAG_RECEIVER_INFO,
84
_XA_MOTIF_DRAG_RECEIVER_INFO,
86
(unsigned char *)&info,
92
wXDNDClearAwareness(Window window)
94
XDeleteProperty (dpy, window, _XA_XdndAware);
98
wXDNDProcessSelection(XEvent *event)
100
WScreen *scr = wScreenForWindow(event->xselection.requestor);
104
unsigned long ret_item;
105
unsigned long remain_byte;
108
Window selowner = XGetSelectionOwner(dpy,_XA_XdndSelection);
112
XGetWindowProperty(dpy, event->xselection.requestor,
113
_XA_WINDOWMAKER_XDNDEXCHANGE,
114
0, 65536, True, atom_support, &ret_type, &ret_format,
115
&ret_item, &remain_byte, (unsigned char **)&delme);
117
scr->xdestring=delme;
121
memset (&xevent, 0, sizeof(xevent));
122
xevent.xany.type = ClientMessage;
123
xevent.xany.display = dpy;
124
xevent.xclient.window = selowner;
125
xevent.xclient.message_type = _XA_XdndFinished;
126
xevent.xclient.format = 32;
127
XDND_FINISHED_TARGET_WIN(&xevent) = event->xselection.requestor;
128
XSendEvent(dpy, selowner, 0, 0, &xevent);
131
if (scr->xdestring) {
132
WMArrayIterator iter;
133
int length, str_size;
137
items = WMCreateArray(4);
138
retain = wstrdup(scr->xdestring);
139
XFree(scr->xdestring); /* since xdestring was created by Xlib */
141
length = strlen(retain);
143
/* search in string */
145
if (retain[length] == '\r') { /* useless char, nuke it */
148
if (retain[length] == '\n') {
149
str_size = strlen(&retain[length + 1]);
151
WMAddToArray(items, wstrdup(&retain[length + 1]));
152
total_size += str_size + 3; /* reserve for " \"\"" */
153
/* this is nonsense -- if (length)
154
WMAppendArray(items, WMCreateArray(1));*/
160
WMAddToArray(items, wstrdup(retain));
161
total_size += strlen(retain) + 3;
164
/* now pack new string */
165
scr->xdestring = wmalloc(total_size);
166
scr->xdestring[0]=0; /* empty string */
167
WM_ETARETI_ARRAY(items, tmp, iter) {
168
if (!strncmp(tmp,"file:",5)) {
169
/* add more 2 chars while removing 5 is harmless */
170
strcat(scr->xdestring, " \"");
171
strcat(scr->xdestring, &tmp[5]);
172
strcat(scr->xdestring, "\"");
174
/* unsupport object, still need more " ? tell ]d */
175
strcat(scr->xdestring, &tmp[5]);
180
wDockReceiveDNDDrop(scr,event);
183
puts(scr->xdestring);
185
wfree(scr->xdestring); /* this xdestring is not from Xlib (no XFree) */
188
/* why doesn't this function return anything ? -Dan */
192
isAwareXDND(Window window)
196
unsigned long count, remaining;
197
unsigned char *data=0;
199
if (!window) return False;
200
XGetWindowProperty (dpy, window, _XA_XdndAware,
201
0, 0x8000000L, False, XA_ATOM,
203
&count, &remaining, &data);
204
if (actual != XA_ATOM || format != 32 || count == 0 || !data) {
215
acceptXDND(Window window)
217
WScreen *scr = wScreenForWindow(window);
222
if ((dock = scr->dock)!=NULL) {
223
for (i=0; i<dock->max_icons; i++) {
224
if (dock->icon_array[i]
225
&& dock->icon_array[i]->icon->core->window==window) {
231
if (icon_pos<0 && (dock = scr->workspaces[scr->current_workspace]->clip)!=NULL) {
232
for (i=0; i<dock->max_icons; i++) {
233
if (dock->icon_array[i]
234
&& dock->icon_array[i]->icon->core->window==window) {
240
if (icon_pos<0) return False;
241
if (!dock) return False;
242
if (isAwareXDND(dock->icon_array[icon_pos]->icon->icon_win)) return False;
244
if (dock->icon_array[icon_pos]->dnd_command!=NULL) return True;
250
wXDNDProcessClientMessage(XClientMessageEvent *event)
254
char * name = XGetAtomName(dpy, event->message_type);
256
printf("Get %s\n",name);
262
if (event->message_type == _XA_MOTIF_DRAG_AND_DROP_MESSAGE) {
263
printf("motif dnd msg %d\n",event->data.b[0]);
264
if (event->data.b[0] == XmDROP_START){
265
unsigned x_root, y_root, flags;
266
unsigned char reason;
267
unsigned long timestamp;
269
Window source_window;
270
MotifDragInitiatorInfo *initiator_info;
273
unsigned long ret_item;
274
unsigned long remain_byte;
276
reason = event->data.b[0];
277
flags = event->data.s[1];
278
timestamp = event->data.l[1];
279
x_root = event->data.s[4];
280
y_root = event->data.s[5];
281
atom = event->data.l[3];
282
source_window = event->data.l[4];
284
XGetWindowProperty(dpy, source_window, atom,
285
0, sizeof(*initiator_info), True, atom_support,
286
&ret_type, &ret_format,
287
&ret_item, &remain_byte, (unsigned char **)&initiator_info);
291
if (event->message_type == _XA_XdndEnter) {
292
if ((event->data.l[1] & 1) == 0){
293
atom_support = event->data.l[2];
296
else puts("enter more than 3 types");
299
} else if (event->message_type == _XA_XdndLeave) {
301
} else if (event->message_type == _XA_XdndDrop) {
302
if (event->data.l[0] == XGetSelectionOwner(dpy, _XA_XdndSelection)){
303
XConvertSelection(dpy, _XA_XdndSelection, atom_support,
304
_XA_WINDOWMAKER_XDNDEXCHANGE, event->window, CurrentTime);
307
puts("wierd selection owner? QT?");
308
XConvertSelection(dpy, _XA_XdndSelection, atom_support,
309
_XA_WINDOWMAKER_XDNDEXCHANGE, event->window, CurrentTime);
312
} else if (event->message_type == _XA_XdndPosition) {
314
Window srcwin = event->data.l[0];
315
if (atom_support != XInternAtom(dpy, "text/uri-list", False)) {
319
memset (&xevent, 0, sizeof(xevent));
320
xevent.xany.type = ClientMessage;
321
xevent.xany.display = dpy;
322
xevent.xclient.window = srcwin;
323
xevent.xclient.message_type = _XA_XdndStatus;
324
xevent.xclient.format = 32;
326
XDND_STATUS_TARGET_WIN (&xevent) = event->window;
327
XDND_STATUS_WILL_ACCEPT_SET (&xevent, acceptXDND(event->window));
328
XDND_STATUS_WANT_POSITION_SET(&xevent, True);
329
XDND_STATUS_RECT_SET(&xevent, 0, 0, 1024,768);
330
XDND_STATUS_ACTION(&xevent) = _XA_XdndActionCopy;
332
XSendEvent(dpy, srcwin, 0, 0, &xevent);