changed indentation to use spaces only
[wmaker-crm.git] / WINGs / dragcommon.c
blob4c152c20b5ec754e6f03148cfb2741e9f5949004
1 /* #include <X11/Xatom.h> */
2 #include "WINGsP.h"
4 #define VERSION_INFO(dragInfo) dragInfo->protocolVersion
5 #define XDND_DEST_INFO(dragInfo) dragInfo->destInfo
6 #define XDND_DEST_VIEW(dragInfo) dragInfo->destInfo->destView
7 #define XDND_DEST_VIEW_STORED(dragInfo) ((dragInfo->destInfo) != NULL)\
8 && ((dragInfo->destInfo->destView) != NULL)
11 static Bool _WindowExists;
14 Atom
15 W_OperationToAction(WMScreen *scr, WMDragOperationType operation)
17 switch (operation) {
18 case WDOperationNone:
19 return None;
21 case WDOperationCopy:
22 return scr->xdndActionCopy;
24 case WDOperationMove:
25 return scr->xdndActionMove;
27 case WDOperationLink:
28 return scr->xdndActionLink;
30 case WDOperationAsk:
31 return scr->xdndActionAsk;
33 case WDOperationPrivate:
34 return scr->xdndActionPrivate;
36 default:
37 return None;
42 WMDragOperationType
43 W_ActionToOperation(WMScreen *scr, Atom action)
45 if (action == scr->xdndActionCopy) {
46 return WDOperationCopy;
48 } else if (action == scr->xdndActionMove) {
49 return WDOperationMove;
51 } else if (action == scr->xdndActionLink) {
52 return WDOperationLink;
54 } else if (action == scr->xdndActionAsk) {
55 return WDOperationAsk;
57 } else if (action == scr->xdndActionPrivate) {
58 return WDOperationPrivate;
60 } else if (action == None) {
62 return WDOperationNone;
63 } else {
64 char *tmp = XGetAtomName(scr->display, action);
66 wwarning("unknown XDND action %s ", tmp);
67 XFree(tmp);
69 return WDOperationCopy;
74 static void
75 freeDragOperationItem(void* item)
77 wfree(item);
80 WMArray*
81 WMCreateDragOperationArray(int initialSize)
83 return WMCreateArrayWithDestructor(initialSize, freeDragOperationItem);
87 WMDragOperationItem*
88 WMCreateDragOperationItem(WMDragOperationType type, char* text)
90 W_DragOperationItem *result = wmalloc(sizeof(W_DragOperationItem));
92 result->type = type;
93 result->text = text;
95 return (WMDragOperationItem*) result;
98 WMDragOperationType
99 WMGetDragOperationItemType(WMDragOperationItem* item)
101 return ((W_DragOperationItem*)item)->type;
105 char*
106 WMGetDragOperationItemText(WMDragOperationItem* item)
108 return ((W_DragOperationItem*)item)->text;
111 static int
112 handleNoWindowXError(Display *dpy, XErrorEvent *errEvt)
114 if (errEvt->error_code == BadWindow
115 || errEvt->error_code == BadDrawable) {
116 _WindowExists = False;
117 return Success;
120 return errEvt->error_code;
124 static Bool
125 windowExists(Display *dpy, Window win)
127 void* previousErrorHandler;
128 XWindowAttributes attr;
130 XSynchronize(dpy, True);
131 previousErrorHandler = XSetErrorHandler(handleNoWindowXError);
132 _WindowExists = True;
134 /* can generate BadDrawable or BadWindow */
135 XGetWindowAttributes(dpy, win, &attr);
137 XSetErrorHandler(previousErrorHandler);
138 XSynchronize(dpy, False);
139 return _WindowExists;
143 Bool
144 W_SendDnDClientMessage(Display *dpy, Window win, Atom message,
145 unsigned long data0,
146 unsigned long data1,
147 unsigned long data2,
148 unsigned long data3,
149 unsigned long data4)
151 XEvent ev;
153 if (! windowExists(dpy, win)) {
154 wwarning("xdnd message target %d does no longer exist.", win);
155 return False; /* message not sent */
158 ev.type = ClientMessage;
159 ev.xclient.message_type = message;
160 ev.xclient.format = 32;
161 ev.xclient.window = win;
162 ev.xclient.data.l[0] = data0;
163 ev.xclient.data.l[1] = data1;
164 ev.xclient.data.l[2] = data2;
165 ev.xclient.data.l[3] = data3;
166 ev.xclient.data.l[4] = data4;
169 XSendEvent(dpy, win, False, 0, &ev);
170 XFlush(dpy);
172 return True; /* message sent */
176 static void
177 handleLeaveMessage(WMDraggingInfo *info)
179 if (XDND_DEST_INFO(info) != NULL) {
180 if (XDND_DEST_VIEW(info) != NULL) {
181 XDND_DEST_VIEW(info)->dragDestinationProcs->concludeDragOperation(
182 XDND_DEST_VIEW(info));
184 W_DragDestinationInfoClear(info);
189 void
190 W_HandleDNDClientMessage(WMView *toplevel, XClientMessageEvent *event)
192 WMScreen *scr = W_VIEW_SCREEN(toplevel);
193 WMDraggingInfo *info = &scr->dragInfo;
194 Atom messageType = event->message_type;
196 #ifdef XDND_DEBUG
198 char* msgTypeName = XGetAtomName(scr->display, messageType);
200 if (msgTypeName != NULL)
201 printf("event type = %s\n", msgTypeName);
202 else
203 printf("pb with event type !\n");
205 #endif
208 /* Messages from destination to source */
209 if (messageType == scr->xdndStatusAtom
210 || messageType == scr->xdndFinishedAtom) {
211 W_DragSourceStopTimer();
212 W_DragSourceStateHandler(info, event);
213 return;
216 /* Messages from source to destination */
217 if (messageType == scr->xdndEnterAtom) {
218 W_DragDestinationStopTimer();
219 W_DragDestinationStoreEnterMsgInfo(info, toplevel, event);
221 if (VERSION_INFO(info) <= XDND_VERSION) {
222 if (XDND_DEST_VIEW_STORED(info)) {
223 /* xdndPosition previously received on xdnd aware view */
224 W_DragDestinationStateHandler(info, event);
225 return;
226 } else {
227 W_DragDestinationStartTimer(info);
228 return;
230 } else {
231 wwarning("received dnd enter msg with unsupported version %i",
232 VERSION_INFO(info));
233 W_DragDestinationCancelDropOnEnter(toplevel, info);
234 return;
238 if (messageType == scr->xdndPositionAtom) {
239 W_DragDestinationStopTimer();
240 W_DragDestinationStorePositionMsgInfo(info, toplevel, event);
241 W_DragDestinationStateHandler(info, event);
242 return;
245 if (messageType == scr->xdndSelectionAtom
246 || messageType == scr->xdndDropAtom) {
247 W_DragDestinationStopTimer();
248 W_DragDestinationStateHandler(info, event);
249 return;
252 if (messageType == scr->xdndLeaveAtom) {
253 /* conclude drop operation, and clear dragging info */
254 W_DragDestinationStopTimer();
255 handleLeaveMessage(info);
260 /* called in destroyView (wview.c) */
261 void
262 W_FreeViewXdndPart(WMView *view)
264 WMUnregisterViewDraggedTypes(view);
266 if (view->dragSourceProcs)
267 wfree(view->dragSourceProcs);
269 if (view->dragDestinationProcs)
270 wfree(view->dragDestinationProcs);
272 if (view->dragImage)
273 WMReleasePixmap(view->dragImage);