Added option to 'configure' to control debug information for compilation
[wmaker-crm.git] / src / xdnd.c
blob5230da5f25791658c18378cc2692b78157b95e89
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>
21 #define XDND_VERSION 3L
23 Atom _XA_XdndAware;
24 Atom _XA_XdndEnter;
25 Atom _XA_XdndLeave;
26 Atom _XA_XdndDrop;
27 Atom _XA_XdndPosition;
28 Atom _XA_XdndStatus;
29 Atom _XA_XdndActionCopy;
30 Atom _XA_XdndSelection;
31 Atom _XA_XdndFinished;
32 Atom _XA_WINDOWMAKER_XDNDEXCHANGE;
35 Atom _XA_MOTIF_DRAG_RECEIVER_INFO;
36 Atom _XA_MOTIF_DRAG_AND_DROP_MESSAGE;
39 Atom atom_support;
41 void wXDNDInitializeAtoms()
44 _XA_XdndAware = XInternAtom(dpy, "XdndAware", False);
45 _XA_XdndEnter = XInternAtom(dpy, "XdndEnter", False);
46 _XA_XdndLeave = XInternAtom(dpy, "XdndLeave", False);
47 _XA_XdndDrop = XInternAtom(dpy, "XdndDrop", False);
48 _XA_XdndPosition = XInternAtom(dpy, "XdndPosition", False);
49 _XA_XdndStatus = XInternAtom(dpy, "XdndStatus", False);
50 _XA_XdndActionCopy = XInternAtom(dpy, "XdndActionCopy", False);
51 _XA_XdndSelection = XInternAtom(dpy, "XdndSelection", False);
52 _XA_XdndFinished = XInternAtom(dpy, "XdndFinished", False);
54 _XA_WINDOWMAKER_XDNDEXCHANGE = XInternAtom(dpy, "_WINDOWMAKER_XDNDEXCHANGE", False);
57 _XA_MOTIF_DRAG_RECEIVER_INFO = XInternAtom(dpy, "_MOTIF_DRAG_RECEIVER_INFO",False);
58 _XA_MOTIF_DRAG_AND_DROP_MESSAGE = XInternAtom(dpy, "_MOTIF_DRAG_AND_DROP_MESSAGE", False);
62 void wXDNDMakeAwareness(Window window)
64 long int xdnd_version = 3;
66 MotifDragReceiverInfo info;
68 XChangeProperty(dpy, window, _XA_XdndAware, XA_ATOM, 32, PropModeAppend, (char *)&xdnd_version, 1);
70 /*** MOTIF ***
71 info.byte_order = '\0';
72 info.protocol_version = 0;
73 info.protocol_style = XmDRAG_DYNAMIC;
74 info.proxy_window = 0;
75 info.num_drop_sites = 0;
76 info.total_size = sizeof(info);
78 XChangeProperty (dpy, window,
79 _XA_MOTIF_DRAG_RECEIVER_INFO,
80 _XA_MOTIF_DRAG_RECEIVER_INFO,
81 8, PropModeReplace,
82 (unsigned char *)&info,
83 sizeof (info));
87 Bool wXDNDProcessSelection(XEvent * event)
89 WScreen *scr = wScreenForWindow(event->xselection.requestor);
90 char *retain;
91 Atom ret_type;
92 int ret_format;
93 unsigned long ret_item;
94 unsigned long remain_byte;
95 char *delme;
96 XEvent xevent;
97 Window selowner = XGetSelectionOwner(dpy, _XA_XdndSelection);
98 WMArray *items;
100 XGetWindowProperty(dpy, event->xselection.requestor,
101 _XA_WINDOWMAKER_XDNDEXCHANGE,
102 0, 65536, True, atom_support, &ret_type, &ret_format,
103 &ret_item, &remain_byte, (unsigned char **)&delme);
104 if (delme) {
105 scr->xdestring = delme;
108 /*send finished */
109 memset(&xevent, 0, sizeof(xevent));
110 xevent.xany.type = ClientMessage;
111 xevent.xany.display = dpy;
112 xevent.xclient.window = selowner;
113 xevent.xclient.message_type = _XA_XdndFinished;
114 xevent.xclient.format = 32;
115 XDND_FINISHED_TARGET_WIN(&xevent) = event->xselection.requestor;
116 XSendEvent(dpy, selowner, 0, 0, &xevent);
118 /*process dropping */
119 if (scr->xdestring) {
120 WMArrayIterator iter;
121 int length, str_size;
122 int total_size = 0;
123 char *tmp;
125 items = WMCreateArray(4);
126 retain = wstrdup(scr->xdestring);
127 XFree(scr->xdestring); /* since xdestring was created by Xlib */
129 length = strlen(retain);
131 /* search in string */
132 while (length--) {
133 if (retain[length] == '\r') { /* useless char, nuke it */
134 retain[length] = 0;
136 if (retain[length] == '\n') {
137 str_size = strlen(&retain[length + 1]);
138 if (str_size) {
139 WMAddToArray(items, wstrdup(&retain[length + 1]));
140 total_size += str_size + 3; /* reserve for " \"\"" */
141 /* this is nonsense -- if (length)
142 WMAppendArray(items, WMCreateArray(1)); */
144 retain[length] = 0;
147 /* final one */
148 WMAddToArray(items, wstrdup(retain));
149 total_size += strlen(retain) + 3;
150 wfree(retain);
152 /* now pack new string */
153 scr->xdestring = wmalloc(total_size);
154 scr->xdestring[0] = 0; /* empty string */
155 WM_ETARETI_ARRAY(items, tmp, iter) {
156 if (!strncmp(tmp, "file:", 5)) {
157 /* add more 2 chars while removing 5 is harmless */
158 strcat(scr->xdestring, " \"");
159 strcat(scr->xdestring, &tmp[5]);
160 strcat(scr->xdestring, "\"");
161 } else {
162 /* unsupport object, still need more " ? tell ]d */
163 strcat(scr->xdestring, &tmp[5]);
165 wfree(tmp);
167 WMFreeArray(items);
168 wDockReceiveDNDDrop(scr, event);
170 printf("free ");
171 puts(scr->xdestring);
173 wfree(scr->xdestring); /* this xdestring is not from Xlib (no XFree) */
176 return True;
179 Bool isAwareXDND(Window window)
181 Atom actual;
182 int format;
183 unsigned long count, remaining;
184 unsigned char *data = 0;
186 if (!window)
187 return False;
188 XGetWindowProperty(dpy, window, _XA_XdndAware,
189 0, 0x8000000L, False, XA_ATOM, &actual, &format, &count, &remaining, &data);
190 if (actual != XA_ATOM || format != 32 || count == 0 || !data) {
191 if (data)
192 XFree(data);
193 return False;
195 if (data)
196 XFree(data);
197 return True;
200 Bool acceptXDND(Window window)
202 WScreen *scr = wScreenForWindow(window);
203 WDock *dock;
204 int icon_pos, i;
206 icon_pos = -1;
207 if ((dock = scr->dock) != NULL) {
208 for (i = 0; i < dock->max_icons; i++) {
209 if (dock->icon_array[i]
210 && dock->icon_array[i]->icon->core->window == window) {
211 icon_pos = i;
212 break;
216 if (icon_pos < 0 && (dock = scr->workspaces[scr->current_workspace]->clip) != NULL) {
217 for (i = 0; i < dock->max_icons; i++) {
218 if (dock->icon_array[i]
219 && dock->icon_array[i]->icon->core->window == window) {
220 icon_pos = i;
221 break;
225 if (icon_pos < 0)
226 return False;
227 if (!dock)
228 return False;
229 if (isAwareXDND(dock->icon_array[icon_pos]->icon->icon_win))
230 return False;
232 if (dock->icon_array[icon_pos]->dnd_command != NULL)
233 return True;
235 return False;
238 Bool wXDNDProcessClientMessage(XClientMessageEvent * event)
240 /* test */
242 char *name = XGetAtomName(dpy, event->message_type);
244 printf("Get %s\n",name);
246 XFree(name);
250 if (event->message_type == _XA_MOTIF_DRAG_AND_DROP_MESSAGE) {
251 printf("motif dnd msg %d\n",event->data.b[0]);
252 if (event->data.b[0] == XmDROP_START){
253 unsigned x_root, y_root, flags;
254 unsigned char reason;
255 unsigned long timestamp;
256 Atom atom;
257 Window source_window;
258 MotifDragInitiatorInfo *initiator_info;
259 Atom ret_type;
260 int ret_format;
261 unsigned long ret_item;
262 unsigned long remain_byte;
264 reason = event->data.b[0];
265 flags = event->data.s[1];
266 timestamp = event->data.l[1];
267 x_root = event->data.s[4];
268 y_root = event->data.s[5];
269 atom = event->data.l[3];
270 source_window = event->data.l[4];
272 XGetWindowProperty(dpy, source_window, atom,
273 0, sizeof(*initiator_info), True, atom_support,
274 &ret_type, &ret_format,
275 &ret_item, &remain_byte, (unsigned char **)&initiator_info);
278 else */
279 if (event->message_type == _XA_XdndEnter) {
280 if ((event->data.l[1] & 1) == 0) {
281 atom_support = event->data.l[2];
284 else puts("enter more than 3 types");
286 return True;
287 } else if (event->message_type == _XA_XdndLeave) {
288 return True;
289 } else if (event->message_type == _XA_XdndDrop) {
290 if (event->data.l[0] == XGetSelectionOwner(dpy, _XA_XdndSelection)) {
291 XConvertSelection(dpy, _XA_XdndSelection, atom_support,
292 _XA_WINDOWMAKER_XDNDEXCHANGE, event->window, CurrentTime);
293 } else {
294 puts("wierd selection owner? QT?");
295 XConvertSelection(dpy, _XA_XdndSelection, atom_support,
296 _XA_WINDOWMAKER_XDNDEXCHANGE, event->window, CurrentTime);
298 return True;
299 } else if (event->message_type == _XA_XdndPosition) {
300 XEvent xevent;
301 Window srcwin = event->data.l[0];
302 if (atom_support != XInternAtom(dpy, "text/uri-list", False)) {
303 return True;
306 memset(&xevent, 0, sizeof(xevent));
307 xevent.xany.type = ClientMessage;
308 xevent.xany.display = dpy;
309 xevent.xclient.window = srcwin;
310 xevent.xclient.message_type = _XA_XdndStatus;
311 xevent.xclient.format = 32;
313 XDND_STATUS_TARGET_WIN(&xevent) = event->window;
314 XDND_STATUS_WILL_ACCEPT_SET(&xevent, acceptXDND(event->window));
315 XDND_STATUS_WANT_POSITION_SET(&xevent, True);
316 XDND_STATUS_RECT_SET(&xevent, 0, 0, 1024, 768);
317 XDND_STATUS_ACTION(&xevent) = _XA_XdndActionCopy;
319 XSendEvent(dpy, srcwin, 0, 0, &xevent);
321 return True;
323 return False;
326 #endif