Fixed return of WMGetUDStringForKey to be only a reference, not an allocated
[wmaker-crm.git] / src / xdnd.c
blob2e6d9379cd31078793502b3a59ce2c0340c6763c
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"
18 #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) {
63 long int xdnd_version = 3;
65 MotifDragReceiverInfo info;
67 XChangeProperty (dpy, window, _XA_XdndAware, XA_ATOM,
68 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 void wXDNDClearAwareness(Window window) {
88 long int xdnd_version = 3;
89 XDeleteProperty (dpy, window, _XA_XdndAware);
92 Bool
93 wXDNDProcessSelection(XEvent *event)
95 WScreen *scr = wScreenForWindow(event->xselection.requestor);
96 char *dropdata;
97 char *retain;
98 Atom ret_type;
99 int ret_format;
100 unsigned long ret_item;
101 unsigned long remain_byte;
102 char * delme;
103 XEvent xevent;
104 Window selowner = XGetSelectionOwner(dpy,_XA_XdndSelection);
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;
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);
123 /*process dropping*/
124 for (retain=scr->xdestring;retain[0];retain++) {
125 if (retain[0] < 32) retain[0] = 32;
126 if (!strncmp(retain, "file:", 5)) {
127 int i;
128 for (i=0;i<5;retain[i++]=' ');
131 retain = scr->xdestring;
132 if (scr->xdestring){
133 if (!strncmp(scr->xdestring, "file:", 5))
134 scr->xdestring+=5;
136 wDockReceiveDNDDrop(scr,event);
137 if (retain){
138 XFree(retain);
139 scr->xdestring = NULL;
143 Bool
144 isAwareXDND(Window window)
146 Atom actual;
147 int format;
148 unsigned long count, remaining;
149 unsigned char *data=0;
150 Atom *types, *t;
152 if (!window) return False;
153 XGetWindowProperty (dpy, window, _XA_XdndAware,
154 0, 0x8000000L, False, XA_ATOM,
155 &actual, &format,
156 &count, &remaining, &data);
157 if (actual != XA_ATOM || format != 32 || count == 0 || !data) {
158 if (data)
159 XFree (data);
160 return False;
162 if (data)
163 XFree (data);
164 return True;
167 Bool
168 acceptXDND(Window window)
170 WScreen *scr = wScreenForWindow(window);
171 WWindow *wwin = wWindowFor(window);
172 WDock *dock;
173 int icon_pos,i;
175 icon_pos = -1;
176 if ((dock = scr->dock)!=NULL) {
177 for (i=0; i<dock->max_icons; i++) {
178 if (dock->icon_array[i]
179 && dock->icon_array[i]->icon->core->window==window) {
180 icon_pos = i;
181 break;
185 if (icon_pos<0 && (dock = scr->workspaces[scr->current_workspace]->clip)!=NULL) {
186 for (i=0; i<dock->max_icons; i++) {
187 if (dock->icon_array[i]
188 && dock->icon_array[i]->icon->core->window==window) {
189 icon_pos = i;
190 break;
194 if (icon_pos<0) return False;
195 if (!dock) return False;
196 if (isAwareXDND(dock->icon_array[icon_pos]->icon->icon_win)) return False;
198 if (dock->icon_array[icon_pos]->dnd_command!=NULL) return True;
200 return False;
203 Bool
204 wXDNDProcessClientMessage(XClientMessageEvent *event)
206 /* test */
208 char * name = XGetAtomName(dpy, event->message_type);
210 printf("Get %s\n",name);
212 XFree(name);
216 if (event->message_type == _XA_MOTIF_DRAG_AND_DROP_MESSAGE) {
217 printf("motif dnd msg %d\n",event->data.b[0]);
218 if (event->data.b[0] == XmDROP_START){
219 unsigned x_root, y_root, flags;
220 unsigned char reason;
221 unsigned long timestamp;
222 Atom atom;
223 Window source_window;
224 MotifDragInitiatorInfo *initiator_info;
225 Atom ret_type;
226 int ret_format;
227 unsigned long ret_item;
228 unsigned long remain_byte;
230 reason = event->data.b[0];
231 flags = event->data.s[1];
232 timestamp = event->data.l[1];
233 x_root = event->data.s[4];
234 y_root = event->data.s[5];
235 atom = event->data.l[3];
236 source_window = event->data.l[4];
238 XGetWindowProperty(dpy, source_window, atom,
239 0, sizeof(*initiator_info), True, atom_support,
240 &ret_type, &ret_format,
241 &ret_item, &remain_byte, (unsigned char **)&initiator_info);
244 else */
245 if (event->message_type == _XA_XdndEnter) {
246 if ((event->data.l[1] & 1) == 0){
247 atom_support = event->data.l[2];
250 else puts("enter more than 3 types");
252 return True;
253 } else if (event->message_type == _XA_XdndLeave) {
254 return True;
255 } else if (event->message_type == _XA_XdndDrop) {
256 if (event->data.l[0] == XGetSelectionOwner(dpy, _XA_XdndSelection)){
257 XConvertSelection(dpy, _XA_XdndSelection, atom_support,
258 _XA_WINDOWMAKER_XDNDEXCHANGE, event->window, CurrentTime);
261 else puts("wierd selection owner");
263 return True;
264 } else if (event->message_type == _XA_XdndPosition) {
265 XEvent xevent;
266 Window srcwin = event->data.l[0];
267 if (atom_support != XInternAtom(dpy, "text/uri-list", False)) {
268 return True;
271 memset (&xevent, 0, sizeof(xevent));
272 xevent.xany.type = ClientMessage;
273 xevent.xany.display = dpy;
274 xevent.xclient.window = srcwin;
275 xevent.xclient.message_type = _XA_XdndStatus;
276 xevent.xclient.format = 32;
278 XDND_STATUS_TARGET_WIN (&xevent) = event->window;
279 XDND_STATUS_WILL_ACCEPT_SET (&xevent, acceptXDND(event->window));
280 XDND_STATUS_WANT_POSITION_SET(&xevent, True);
281 XDND_STATUS_RECT_SET(&xevent, 0, 0, 1024,768);
282 XDND_STATUS_ACTION(&xevent) = _XA_XdndActionCopy;
284 XSendEvent(dpy, srcwin, 0, 0, &xevent);
286 return True;
288 return False;
291 #endif