misc update relates to xdnd.
[wmaker-crm.git] / src / xdnd.c
blobfa3587842f5464391f6cce72cae6e2bd3e476979
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 = scr->xdestring;
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){
111 printf("get -%s-\n",delme);
113 scr->xdestring=delme;
116 /*send finished*/
117 memset (&xevent, 0, sizeof(xevent));
118 xevent.xany.type = ClientMessage;
119 xevent.xany.display = dpy;
120 xevent.xclient.window = selowner;
121 xevent.xclient.message_type = _XA_XdndFinished;
122 xevent.xclient.format = 32;
123 XDND_FINISHED_TARGET_WIN(&xevent) = event->xselection.requestor;
124 XSendEvent(dpy, selowner, 0, 0, &xevent);
126 /*process dropping*/
127 for (;retain[0];retain++) {
128 if (retain[0] < 32) retain[0] = 32;
129 if (!strncmp(retain, "file:", 5)) {
130 int i;
131 for (i=0;i<5;retain[i++]=' ');
134 retain = scr->xdestring;
135 if (scr->xdestring){
136 if (!strncmp(scr->xdestring, "file:", 5))
137 scr->xdestring+=5;
139 wDockReceiveDNDDrop(scr,event);
140 if (retain){
141 XFree(retain);
142 scr->xdestring = NULL;
146 Bool
147 isAwareXDND(Window window)
149 Atom actual;
150 int format;
151 unsigned long count, remaining;
152 unsigned char *data=0;
153 Atom *types, *t;
155 if (!window) return False;
156 XGetWindowProperty (dpy, window, _XA_XdndAware,
157 0, 0x8000000L, False, XA_ATOM,
158 &actual, &format,
159 &count, &remaining, &data);
160 if (actual != XA_ATOM || format != 32 || count == 0 || !data) {
161 if (data)
162 XFree (data);
163 return False;
165 if (data)
166 XFree (data);
167 return True;
170 Bool
171 acceptXDND(Window window)
173 WScreen *scr = wScreenForWindow(window);
174 WWindow *wwin = wWindowFor(window);
175 WDock *dock;
176 int icon_pos,i;
178 icon_pos = -1;
179 if ((dock = scr->dock)!=NULL) {
180 for (i=0; i<dock->max_icons; i++) {
181 if (dock->icon_array[i]
182 && dock->icon_array[i]->icon->core->window==window) {
183 icon_pos = i;
184 break;
188 if (icon_pos<0 && (dock = scr->workspaces[scr->current_workspace]->clip)!=NULL) {
189 for (i=0; i<dock->max_icons; i++) {
190 if (dock->icon_array[i]
191 && dock->icon_array[i]->icon->core->window==window) {
192 icon_pos = i;
193 break;
197 if (icon_pos<0) return False;
198 if (!dock) return False;
199 if (isAwareXDND(dock->icon_array[icon_pos]->icon->icon_win)) return False;
201 if (dock->icon_array[icon_pos]->dnd_command!=NULL) return True;
203 return False;
206 Bool
207 wXDNDProcessClientMessage(XClientMessageEvent *event)
209 /* test */
211 char * name = XGetAtomName(dpy, event->message_type);
213 printf("Get %s\n",name);
215 XFree(name);
219 if (event->message_type == _XA_MOTIF_DRAG_AND_DROP_MESSAGE) {
220 printf("motif dnd msg %d\n",event->data.b[0]);
221 if (event->data.b[0] == XmDROP_START){
222 unsigned x_root, y_root, flags;
223 unsigned char reason;
224 unsigned long timestamp;
225 Atom atom;
226 Window source_window;
227 MotifDragInitiatorInfo *initiator_info;
228 Atom ret_type;
229 int ret_format;
230 unsigned long ret_item;
231 unsigned long remain_byte;
233 reason = event->data.b[0];
234 flags = event->data.s[1];
235 timestamp = event->data.l[1];
236 x_root = event->data.s[4];
237 y_root = event->data.s[5];
238 atom = event->data.l[3];
239 source_window = event->data.l[4];
241 XGetWindowProperty(dpy, source_window, atom,
242 0, sizeof(*initiator_info), True, atom_support,
243 &ret_type, &ret_format,
244 &ret_item, &remain_byte, (unsigned char **)&initiator_info);
247 else */
248 if (event->message_type == _XA_XdndEnter) {
249 if ((event->data.l[1] & 1) == 0){
250 atom_support = event->data.l[2];
253 else puts("enter more than 3 types");
255 return True;
256 } else if (event->message_type == _XA_XdndLeave) {
257 return True;
258 } else if (event->message_type == _XA_XdndDrop) {
259 if (event->data.l[0] == XGetSelectionOwner(dpy, _XA_XdndSelection)){
260 XConvertSelection(dpy, _XA_XdndSelection, atom_support,
261 _XA_WINDOWMAKER_XDNDEXCHANGE, event->window, CurrentTime);
264 else puts("wierd selection owner");
266 return True;
267 } else if (event->message_type == _XA_XdndPosition) {
268 XEvent xevent;
269 Window srcwin = event->data.l[0];
270 if (atom_support != XInternAtom(dpy, "text/uri-list", False)) {
271 return True;
274 memset (&xevent, 0, sizeof(xevent));
275 xevent.xany.type = ClientMessage;
276 xevent.xany.display = dpy;
277 xevent.xclient.window = srcwin;
278 xevent.xclient.message_type = _XA_XdndStatus;
279 xevent.xclient.format = 32;
281 XDND_STATUS_TARGET_WIN (&xevent) = event->window;
282 XDND_STATUS_WILL_ACCEPT_SET (&xevent, acceptXDND(event->window));
283 XDND_STATUS_WANT_POSITION_SET(&xevent, True);
284 XDND_STATUS_RECT_SET(&xevent, 0, 0, 1024,768);
285 XDND_STATUS_ACTION(&xevent) = _XA_XdndActionCopy;
287 XSendEvent(dpy, srcwin, 0, 0, &xevent);
289 return True;
291 return False;
294 #endif