Change to the linux kernel coding style
[wmaker-crm.git] / src / xdnd.c
Commit [+]AuthorDateLineData
d4025072 id1999-05-17 20:21:43 +00001/* Many part of code are ripped of an example from JX's site */
2
3#include "wconfig.h"
4
5#ifdef XDND
6
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"
13
14#include "workspace.h"
15
33cc542e dan2001-10-04 03:07:34 +000016#include <stdlib.h>
17#include <string.h>
d4025072 id1999-05-17 20:21:43 +000018
19#include <X11/Xatom.h>
20
d4025072 id1999-05-17 20:21:43 +000021#define XDND_VERSION 3L
22
23Atom _XA_XdndAware;
24Atom _XA_XdndEnter;
25Atom _XA_XdndLeave;
26Atom _XA_XdndDrop;
27Atom _XA_XdndPosition;
28Atom _XA_XdndStatus;
29Atom _XA_XdndActionCopy;
30Atom _XA_XdndSelection;
31Atom _XA_XdndFinished;
32Atom _XA_WINDOWMAKER_XDNDEXCHANGE;
33
34/*
6830b057 dan2004-10-12 21:28:27 +000035 Atom _XA_MOTIF_DRAG_RECEIVER_INFO;
36 Atom _XA_MOTIF_DRAG_AND_DROP_MESSAGE;
37 */
d4025072 id1999-05-17 20:21:43 +000038
39Atom atom_support;
40
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +020041void wXDNDInitializeAtoms()
d4025072 id1999-05-17 20:21:43 +000042{
43
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +020044 _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);
53
54 _XA_WINDOWMAKER_XDNDEXCHANGE = XInternAtom(dpy, "_WINDOWMAKER_XDNDEXCHANGE", False);
55
56 /*
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);
59 */
d4025072 id1999-05-17 20:21:43 +000060}
61
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +020062void wXDNDMakeAwareness(Window window)
6830b057 dan2004-10-12 21:28:27 +000063{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +020064 long int xdnd_version = 3;
65 /*
66 MotifDragReceiverInfo info;
67 */
68 XChangeProperty(dpy, window, _XA_XdndAware, XA_ATOM, 32, PropModeAppend, (char *)&xdnd_version, 1);
d4025072 id1999-05-17 20:21:43 +000069
70 /*** MOTIF ***
6830b057 dan2004-10-12 21:28:27 +000071 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);
77
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));
84 */
d4025072 id1999-05-17 20:21:43 +000085}
86
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +020087void wXDNDClearAwareness(Window window)
6830b057 dan2004-10-12 21:28:27 +000088{
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +020089 XDeleteProperty(dpy, window, _XA_XdndAware);
d4025072 id1999-05-17 20:21:43 +000090}
91
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +020092Bool wXDNDProcessSelection(XEvent * event)
d4025072 id1999-05-17 20:21:43 +000093{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +020094 WScreen *scr = wScreenForWindow(event->xselection.requestor);
95 char *retain;
96 Atom ret_type;
97 int ret_format;
98 unsigned long ret_item;
99 unsigned long remain_byte;
100 char *delme;
101 XEvent xevent;
102 Window selowner = XGetSelectionOwner(dpy, _XA_XdndSelection);
103 WMArray *items;
104
105 XGetWindowProperty(dpy, event->xselection.requestor,
106 _XA_WINDOWMAKER_XDNDEXCHANGE,
107 0, 65536, True, atom_support, &ret_type, &ret_format,
108 &ret_item, &remain_byte, (unsigned char **)&delme);
109 if (delme) {
110 scr->xdestring = delme;
111 }
112
113 /*send finished */
114 memset(&xevent, 0, sizeof(xevent));
115 xevent.xany.type = ClientMessage;
116 xevent.xany.display = dpy;
117 xevent.xclient.window = selowner;
118 xevent.xclient.message_type = _XA_XdndFinished;
119 xevent.xclient.format = 32;
120 XDND_FINISHED_TARGET_WIN(&xevent) = event->xselection.requestor;
121 XSendEvent(dpy, selowner, 0, 0, &xevent);
122
123 /*process dropping */
124 if (scr->xdestring) {
125 WMArrayIterator iter;
126 int length, str_size;
127 int total_size = 0;
128 char *tmp;
129
130 items = WMCreateArray(4);
131 retain = wstrdup(scr->xdestring);
132 XFree(scr->xdestring); /* since xdestring was created by Xlib */
133
134 length = strlen(retain);
135
136 /* search in string */
137 while (length--) {
138 if (retain[length] == '\r') { /* useless char, nuke it */
139 retain[length] = 0;
140 }
141 if (retain[length] == '\n') {
142 str_size = strlen(&retain[length + 1]);
143 if (str_size) {
144 WMAddToArray(items, wstrdup(&retain[length + 1]));
145 total_size += str_size + 3; /* reserve for " \"\"" */
146 /* this is nonsense -- if (length)
147 WMAppendArray(items, WMCreateArray(1)); */
148 }
149 retain[length] = 0;
150 }
151 }
152 /* final one */
153 WMAddToArray(items, wstrdup(retain));
154 total_size += strlen(retain) + 3;
155 wfree(retain);
156
157 /* now pack new string */
158 scr->xdestring = wmalloc(total_size);
159 scr->xdestring[0] = 0; /* empty string */
160 WM_ETARETI_ARRAY(items, tmp, iter) {
161 if (!strncmp(tmp, "file:", 5)) {
162 /* add more 2 chars while removing 5 is harmless */
163 strcat(scr->xdestring, " \"");
164 strcat(scr->xdestring, &tmp[5]);
165 strcat(scr->xdestring, "\"");
166 } else {
167 /* unsupport object, still need more " ? tell ]d */
168 strcat(scr->xdestring, &tmp[5]);
169 }
170 wfree(tmp);
171 }
172 WMFreeArray(items);
173 wDockReceiveDNDDrop(scr, event);
174 /*
175 printf("free ");
176 puts(scr->xdestring);
177 */
178 wfree(scr->xdestring); /* this xdestring is not from Xlib (no XFree) */
179 }
180
181 /* why doesn't this function return anything ? -Dan */
d4025072 id1999-05-17 20:21:43 +0000182}
183
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200184Bool isAwareXDND(Window window)
d4025072 id1999-05-17 20:21:43 +0000185{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200186 Atom actual;
187 int format;
188 unsigned long count, remaining;
189 unsigned char *data = 0;
190
191 if (!window)
192 return False;
193 XGetWindowProperty(dpy, window, _XA_XdndAware,
194 0, 0x8000000L, False, XA_ATOM, &actual, &format, &count, &remaining, &data);
195 if (actual != XA_ATOM || format != 32 || count == 0 || !data) {
196 if (data)
197 XFree(data);
198 return False;
199 }
200 if (data)
201 XFree(data);
202 return True;
d4025072 id1999-05-17 20:21:43 +0000203}
204
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200205Bool acceptXDND(Window window)
d4025072 id1999-05-17 20:21:43 +0000206{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200207 WScreen *scr = wScreenForWindow(window);
208 WDock *dock;
209 int icon_pos, i;
210
211 icon_pos = -1;
212 if ((dock = scr->dock) != NULL) {
213 for (i = 0; i < dock->max_icons; i++) {
214 if (dock->icon_array[i]
215 && dock->icon_array[i]->icon->core->window == window) {
216 icon_pos = i;
217 break;
218 }
219 }
220 }
221 if (icon_pos < 0 && (dock = scr->workspaces[scr->current_workspace]->clip) != NULL) {
222 for (i = 0; i < dock->max_icons; i++) {
223 if (dock->icon_array[i]
224 && dock->icon_array[i]->icon->core->window == window) {
225 icon_pos = i;
226 break;
227 }
228 }
229 }
230 if (icon_pos < 0)
231 return False;
232 if (!dock)
233 return False;
234 if (isAwareXDND(dock->icon_array[icon_pos]->icon->icon_win))
235 return False;
236
237 if (dock->icon_array[icon_pos]->dnd_command != NULL)
238 return True;
239
240 return False;
d4025072 id1999-05-17 20:21:43 +0000241}
242
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200243Bool wXDNDProcessClientMessage(XClientMessageEvent * event)
d4025072 id1999-05-17 20:21:43 +0000244{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200245 /* test */
246 {
247 char *name = XGetAtomName(dpy, event->message_type);
248 /*
249 printf("Get %s\n",name);
250 */
251 XFree(name);
252 }
253
254 /*
255 if (event->message_type == _XA_MOTIF_DRAG_AND_DROP_MESSAGE) {
256 printf("motif dnd msg %d\n",event->data.b[0]);
257 if (event->data.b[0] == XmDROP_START){
258 unsigned x_root, y_root, flags;
259 unsigned char reason;
260 unsigned long timestamp;
261 Atom atom;
262 Window source_window;
263 MotifDragInitiatorInfo *initiator_info;
264 Atom ret_type;
265 int ret_format;
266 unsigned long ret_item;
267 unsigned long remain_byte;
268
269 reason = event->data.b[0];
270 flags = event->data.s[1];
271 timestamp = event->data.l[1];
272 x_root = event->data.s[4];
273 y_root = event->data.s[5];
274 atom = event->data.l[3];
275 source_window = event->data.l[4];
276
277 XGetWindowProperty(dpy, source_window, atom,
278 0, sizeof(*initiator_info), True, atom_support,
279 &ret_type, &ret_format,
280 &ret_item, &remain_byte, (unsigned char **)&initiator_info);
281 }
282 }
283 else */
284 if (event->message_type == _XA_XdndEnter) {
285 if ((event->data.l[1] & 1) == 0) {
286 atom_support = event->data.l[2];
287 }
288 /*
289 else puts("enter more than 3 types");
290 */
291 return True;
292 } else if (event->message_type == _XA_XdndLeave) {
293 return True;
294 } else if (event->message_type == _XA_XdndDrop) {
295 if (event->data.l[0] == XGetSelectionOwner(dpy, _XA_XdndSelection)) {
296 XConvertSelection(dpy, _XA_XdndSelection, atom_support,
297 _XA_WINDOWMAKER_XDNDEXCHANGE, event->window, CurrentTime);
298 } else {
299 puts("wierd selection owner? QT?");
300 XConvertSelection(dpy, _XA_XdndSelection, atom_support,
301 _XA_WINDOWMAKER_XDNDEXCHANGE, event->window, CurrentTime);
302 }
303 return True;
304 } else if (event->message_type == _XA_XdndPosition) {
305 XEvent xevent;
306 Window srcwin = event->data.l[0];
307 if (atom_support != XInternAtom(dpy, "text/uri-list", False)) {
308 return True;
309 }
310 {
311 memset(&xevent, 0, sizeof(xevent));
312 xevent.xany.type = ClientMessage;
313 xevent.xany.display = dpy;
314 xevent.xclient.window = srcwin;
315 xevent.xclient.message_type = _XA_XdndStatus;
316 xevent.xclient.format = 32;
317
318 XDND_STATUS_TARGET_WIN(&xevent) = event->window;
319 XDND_STATUS_WILL_ACCEPT_SET(&xevent, acceptXDND(event->window));
320 XDND_STATUS_WANT_POSITION_SET(&xevent, True);
321 XDND_STATUS_RECT_SET(&xevent, 0, 0, 1024, 768);
322 XDND_STATUS_ACTION(&xevent) = _XA_XdndActionCopy;
323
324 XSendEvent(dpy, srcwin, 0, 0, &xevent);
325 }
326 return True;
327 }
328 return False;
d4025072 id1999-05-17 20:21:43 +0000329}
330
331#endif