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 //long int xdnd_version = 3;
95 XDeleteProperty (dpy
, window
, _XA_XdndAware
);
99 wXDNDProcessSelection(XEvent
*event
)
101 WScreen
*scr
= wScreenForWindow(event
->xselection
.requestor
);
105 unsigned long ret_item
;
106 unsigned long remain_byte
;
109 Window selowner
= XGetSelectionOwner(dpy
,_XA_XdndSelection
);
113 XGetWindowProperty(dpy
, event
->xselection
.requestor
,
114 _XA_WINDOWMAKER_XDNDEXCHANGE
,
115 0, 65536, True
, atom_support
, &ret_type
, &ret_format
,
116 &ret_item
, &remain_byte
, (unsigned char **)&delme
);
118 scr
->xdestring
=delme
;
122 memset (&xevent
, 0, sizeof(xevent
));
123 xevent
.xany
.type
= ClientMessage
;
124 xevent
.xany
.display
= dpy
;
125 xevent
.xclient
.window
= selowner
;
126 xevent
.xclient
.message_type
= _XA_XdndFinished
;
127 xevent
.xclient
.format
= 32;
128 XDND_FINISHED_TARGET_WIN(&xevent
) = event
->xselection
.requestor
;
129 XSendEvent(dpy
, selowner
, 0, 0, &xevent
);
132 if (scr
->xdestring
) {
133 WMArrayIterator iter
;
134 int length
, str_size
;
138 items
= WMCreateArray(4);
139 retain
= wstrdup(scr
->xdestring
);
140 XFree(scr
->xdestring
); /* since xdestring was created by Xlib */
142 length
= strlen(retain
);
144 /* search in string */
146 if (retain
[length
] == '\r') { /* useless char, nuke it */
149 if (retain
[length
] == '\n') {
150 str_size
= strlen(&retain
[length
+ 1]);
152 WMAddToArray(items
, wstrdup(&retain
[length
+ 1]));
153 total_size
+= str_size
+ 3; /* reserve for " \"\"" */
154 /* this is nonsense -- if (length)
155 WMAppendArray(items, WMCreateArray(1));*/
161 WMAddToArray(items
, wstrdup(retain
));
162 total_size
+= strlen(retain
) + 3;
165 /* now pack new string */
166 scr
->xdestring
= wmalloc(total_size
);
167 scr
->xdestring
[0]=0; /* empty string */
168 WM_ETARETI_ARRAY(items
, tmp
, iter
) {
169 if (!strncmp(tmp
,"file:",5)) {
170 /* add more 2 chars while removing 5 is harmless */
171 strcat(scr
->xdestring
, " \"");
172 strcat(scr
->xdestring
, &tmp
[5]);
173 strcat(scr
->xdestring
, "\"");
175 /* unsupport object, still need more " ? tell ]d */
176 strcat(scr
->xdestring
, &tmp
[5]);
181 wDockReceiveDNDDrop(scr
,event
);
184 puts(scr->xdestring);
186 wfree(scr
->xdestring
); /* this xdestring is not from Xlib (no XFree) */
189 /* why doesn't this function return anything ? -Dan */
193 isAwareXDND(Window window
)
197 unsigned long count
, remaining
;
198 unsigned char *data
=0;
200 if (!window
) return False
;
201 XGetWindowProperty (dpy
, window
, _XA_XdndAware
,
202 0, 0x8000000L
, False
, XA_ATOM
,
204 &count
, &remaining
, &data
);
205 if (actual
!= XA_ATOM
|| format
!= 32 || count
== 0 || !data
) {
216 acceptXDND(Window window
)
218 WScreen
*scr
= wScreenForWindow(window
);
223 if ((dock
= scr
->dock
)!=NULL
) {
224 for (i
=0; i
<dock
->max_icons
; i
++) {
225 if (dock
->icon_array
[i
]
226 && dock
->icon_array
[i
]->icon
->core
->window
==window
) {
232 if (icon_pos
<0 && (dock
= scr
->workspaces
[scr
->current_workspace
]->clip
)!=NULL
) {
233 for (i
=0; i
<dock
->max_icons
; i
++) {
234 if (dock
->icon_array
[i
]
235 && dock
->icon_array
[i
]->icon
->core
->window
==window
) {
241 if (icon_pos
<0) return False
;
242 if (!dock
) return False
;
243 if (isAwareXDND(dock
->icon_array
[icon_pos
]->icon
->icon_win
)) return False
;
245 if (dock
->icon_array
[icon_pos
]->dnd_command
!=NULL
) return True
;
251 wXDNDProcessClientMessage(XClientMessageEvent
*event
)
255 char * name
= XGetAtomName(dpy
, event
->message_type
);
257 printf("Get %s\n",name);
263 if (event->message_type == _XA_MOTIF_DRAG_AND_DROP_MESSAGE) {
264 printf("motif dnd msg %d\n",event->data.b[0]);
265 if (event->data.b[0] == XmDROP_START){
266 unsigned x_root, y_root, flags;
267 unsigned char reason;
268 unsigned long timestamp;
270 Window source_window;
271 MotifDragInitiatorInfo *initiator_info;
274 unsigned long ret_item;
275 unsigned long remain_byte;
277 reason = event->data.b[0];
278 flags = event->data.s[1];
279 timestamp = event->data.l[1];
280 x_root = event->data.s[4];
281 y_root = event->data.s[5];
282 atom = event->data.l[3];
283 source_window = event->data.l[4];
285 XGetWindowProperty(dpy, source_window, atom,
286 0, sizeof(*initiator_info), True, atom_support,
287 &ret_type, &ret_format,
288 &ret_item, &remain_byte, (unsigned char **)&initiator_info);
292 if (event
->message_type
== _XA_XdndEnter
) {
293 if ((event
->data
.l
[1] & 1) == 0){
294 atom_support
= event
->data
.l
[2];
297 else puts("enter more than 3 types");
300 } else if (event
->message_type
== _XA_XdndLeave
) {
302 } else if (event
->message_type
== _XA_XdndDrop
) {
303 if (event
->data
.l
[0] == XGetSelectionOwner(dpy
, _XA_XdndSelection
)){
304 XConvertSelection(dpy
, _XA_XdndSelection
, atom_support
,
305 _XA_WINDOWMAKER_XDNDEXCHANGE
, event
->window
, CurrentTime
);
308 puts("wierd selection owner? QT?");
309 XConvertSelection(dpy
, _XA_XdndSelection
, atom_support
,
310 _XA_WINDOWMAKER_XDNDEXCHANGE
, event
->window
, CurrentTime
);
313 } else if (event
->message_type
== _XA_XdndPosition
) {
315 Window srcwin
= event
->data
.l
[0];
316 if (atom_support
!= XInternAtom(dpy
, "text/uri-list", False
)) {
320 memset (&xevent
, 0, sizeof(xevent
));
321 xevent
.xany
.type
= ClientMessage
;
322 xevent
.xany
.display
= dpy
;
323 xevent
.xclient
.window
= srcwin
;
324 xevent
.xclient
.message_type
= _XA_XdndStatus
;
325 xevent
.xclient
.format
= 32;
327 XDND_STATUS_TARGET_WIN (&xevent
) = event
->window
;
328 XDND_STATUS_WILL_ACCEPT_SET (&xevent
, acceptXDND(event
->window
));
329 XDND_STATUS_WANT_POSITION_SET(&xevent
, True
);
330 XDND_STATUS_RECT_SET(&xevent
, 0, 0, 1024,768);
331 XDND_STATUS_ACTION(&xevent
) = _XA_XdndActionCopy
;
333 XSendEvent(dpy
, srcwin
, 0, 0, &xevent
);