changed indentation to use spaces only
[wmaker-crm.git] / src / xdnd.c
blob7de2a4087f564c0f29d2691a5a3714d5782f9432
1 /* Many part of code are ripped of an example from JX's site */
3 #include "wconfig.h"
5 #ifdef XDND
7 #include <X11/Xlib.h>
8 #include "WindowMaker.h"
9 #include "window.h"
10 #include "dock.h"
11 #include "xdnd.h"
12 #include "motif.h"
14 #include "workspace.h"
16 #include <stdlib.h>
17 #include <string.h>
19 #include <X11/Xatom.h>
22 #define XDND_VERSION 3L
24 Atom _XA_XdndAware;
25 Atom _XA_XdndEnter;
26 Atom _XA_XdndLeave;
27 Atom _XA_XdndDrop;
28 Atom _XA_XdndPosition;
29 Atom _XA_XdndStatus;
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;
40 Atom atom_support;
42 void
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);
64 void
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);
74 /*** MOTIF ***
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,
85 8, PropModeReplace,
86 (unsigned char *)&info,
87 sizeof (info));
91 void
92 wXDNDClearAwareness(Window window)
94 //long int xdnd_version = 3;
95 XDeleteProperty (dpy, window, _XA_XdndAware);
98 Bool
99 wXDNDProcessSelection(XEvent *event)
101 WScreen *scr = wScreenForWindow(event->xselection.requestor);
102 char *retain;
103 Atom ret_type;
104 int ret_format;
105 unsigned long ret_item;
106 unsigned long remain_byte;
107 char * delme;
108 XEvent xevent;
109 Window selowner = XGetSelectionOwner(dpy,_XA_XdndSelection);
110 WMArray *items;
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);
117 if (delme){
118 scr->xdestring=delme;
121 /*send finished*/
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);
131 /*process dropping*/
132 if (scr->xdestring) {
133 WMArrayIterator iter;
134 int length, str_size;
135 int total_size = 0;
136 char *tmp;
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 */
145 while (length--) {
146 if (retain[length] == '\r') { /* useless char, nuke it */
147 retain[length] = 0;
149 if (retain[length] == '\n') {
150 str_size = strlen(&retain[length + 1]);
151 if(str_size) {
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));*/
157 retain[length] = 0;
160 /* final one */
161 WMAddToArray(items, wstrdup(retain));
162 total_size += strlen(retain) + 3;
163 wfree(retain);
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, "\"");
174 } else {
175 /* unsupport object, still need more " ? tell ]d */
176 strcat(scr->xdestring, &tmp[5]);
178 wfree(tmp);
180 WMFreeArray(items);
181 wDockReceiveDNDDrop(scr,event);
183 printf("free ");
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 */
192 Bool
193 isAwareXDND(Window window)
195 Atom actual;
196 int format;
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,
203 &actual, &format,
204 &count, &remaining, &data);
205 if (actual != XA_ATOM || format != 32 || count == 0 || !data) {
206 if (data)
207 XFree (data);
208 return False;
210 if (data)
211 XFree (data);
212 return True;
215 Bool
216 acceptXDND(Window window)
218 WScreen *scr = wScreenForWindow(window);
219 WDock *dock;
220 int icon_pos,i;
222 icon_pos = -1;
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) {
227 icon_pos = i;
228 break;
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) {
236 icon_pos = i;
237 break;
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;
247 return False;
250 Bool
251 wXDNDProcessClientMessage(XClientMessageEvent *event)
253 /* test */
255 char * name = XGetAtomName(dpy, event->message_type);
257 printf("Get %s\n",name);
259 XFree(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;
269 Atom atom;
270 Window source_window;
271 MotifDragInitiatorInfo *initiator_info;
272 Atom ret_type;
273 int ret_format;
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);
291 else */
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");
299 return True;
300 } else if (event->message_type == _XA_XdndLeave) {
301 return True;
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);
307 else {
308 puts("wierd selection owner? QT?");
309 XConvertSelection(dpy, _XA_XdndSelection, atom_support,
310 _XA_WINDOWMAKER_XDNDEXCHANGE, event->window, CurrentTime);
312 return True;
313 } else if (event->message_type == _XA_XdndPosition) {
314 XEvent xevent;
315 Window srcwin = event->data.l[0];
316 if (atom_support != XInternAtom(dpy, "text/uri-list", False)) {
317 return True;
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);
335 return True;
337 return False;
340 #endif