Change to the linux kernel coding style
[wmaker-crm.git] / WINGs / dragcommon.c
1
2 #include "WINGsP.h"
3
4 #define XDND_SOURCE_VERSION(dragInfo) dragInfo->protocolVersion
5 #define XDND_DEST_INFO(dragInfo) dragInfo->destInfo
6 #define XDND_DEST_VIEW(dragInfo) dragInfo->destInfo->destView
7
8 static Bool _WindowExists;
9
10 Atom W_OperationToAction(WMScreen * scr, WMDragOperationType operation)
11 {
12 switch (operation) {
13 case WDOperationNone:
14 return None;
15
16 case WDOperationCopy:
17 return scr->xdndActionCopy;
18
19 case WDOperationMove:
20 return scr->xdndActionMove;
21
22 case WDOperationLink:
23 return scr->xdndActionLink;
24
25 case WDOperationAsk:
26 return scr->xdndActionAsk;
27
28 case WDOperationPrivate:
29 return scr->xdndActionPrivate;
30
31 default:
32 return None;
33 }
34 }
35
36 WMDragOperationType W_ActionToOperation(WMScreen * scr, Atom action)
37 {
38 if (action == scr->xdndActionCopy) {
39 return WDOperationCopy;
40
41 } else if (action == scr->xdndActionMove) {
42 return WDOperationMove;
43
44 } else if (action == scr->xdndActionLink) {
45 return WDOperationLink;
46
47 } else if (action == scr->xdndActionAsk) {
48 return WDOperationAsk;
49
50 } else if (action == scr->xdndActionPrivate) {
51 return WDOperationPrivate;
52
53 } else if (action == None) {
54
55 return WDOperationNone;
56 } else {
57 char *tmp = XGetAtomName(scr->display, action);
58
59 wwarning("unknown XDND action %s ", tmp);
60 XFree(tmp);
61
62 return WDOperationCopy;
63 }
64 }
65
66 static void freeDragOperationItem(void *item)
67 {
68 wfree(item);
69 }
70
71 WMArray *WMCreateDragOperationArray(int initialSize)
72 {
73 return WMCreateArrayWithDestructor(initialSize, freeDragOperationItem);
74 }
75
76 WMDragOperationItem *WMCreateDragOperationItem(WMDragOperationType type, char *text)
77 {
78 W_DragOperationItem *result = wmalloc(sizeof(W_DragOperationItem));
79
80 result->type = type;
81 result->text = text;
82
83 return (WMDragOperationItem *) result;
84 }
85
86 WMDragOperationType WMGetDragOperationItemType(WMDragOperationItem * item)
87 {
88 return ((W_DragOperationItem *) item)->type;
89 }
90
91 char *WMGetDragOperationItemText(WMDragOperationItem * item)
92 {
93 return ((W_DragOperationItem *) item)->text;
94 }
95
96 static int handleNoWindowXError(Display * dpy, XErrorEvent * errEvt)
97 {
98 if (errEvt->error_code == BadWindow || errEvt->error_code == BadDrawable) {
99 _WindowExists = False;
100 return Success;
101 }
102
103 return errEvt->error_code;
104 }
105
106 static Bool windowExists(Display * dpy, Window win)
107 {
108 void *previousErrorHandler;
109 XWindowAttributes attr;
110
111 XSynchronize(dpy, True);
112 previousErrorHandler = XSetErrorHandler(handleNoWindowXError);
113 _WindowExists = True;
114
115 /* can generate BadDrawable or BadWindow */
116 XGetWindowAttributes(dpy, win, &attr);
117
118 XSetErrorHandler(previousErrorHandler);
119 XSynchronize(dpy, False);
120 return _WindowExists;
121 }
122
123 Bool
124 W_SendDnDClientMessage(Display * dpy, Window win, Atom message,
125 unsigned long data0,
126 unsigned long data1, unsigned long data2, unsigned long data3, unsigned long data4)
127 {
128 XEvent ev;
129
130 #ifdef XDND_DEBUG
131 char *msgName = XGetAtomName(dpy, message);
132
133 printf("sending message %s ... ", msgName);
134 XFree(msgName);
135 #endif
136
137 if (!windowExists(dpy, win)) {
138 wwarning("xdnd message target %d does no longer exist.", win);
139 return False; /* message not sent */
140 }
141
142 ev.type = ClientMessage;
143 ev.xclient.message_type = message;
144 ev.xclient.format = 32;
145 ev.xclient.window = win;
146 ev.xclient.data.l[0] = data0;
147 ev.xclient.data.l[1] = data1;
148 ev.xclient.data.l[2] = data2;
149 ev.xclient.data.l[3] = data3;
150 ev.xclient.data.l[4] = data4;
151
152 XSendEvent(dpy, win, False, 0, &ev);
153 XFlush(dpy);
154
155 #ifdef XDND_DEBUG
156 printf("sent\n");
157 #endif
158 return True; /* message sent */
159 }
160
161 static void handleLeaveMessage(WMDraggingInfo * info)
162 {
163 if (XDND_DEST_INFO(info) != NULL) {
164 /* XDND_DEST_VIEW is never NULL (it's the xdnd aware view) */
165 wassertr(XDND_DEST_VIEW(info) != NULL);
166 if (XDND_DEST_VIEW(info)->dragDestinationProcs != NULL) {
167 XDND_DEST_VIEW(info)->dragDestinationProcs->concludeDragOperation(XDND_DEST_VIEW(info));
168 }
169 W_DragDestinationInfoClear(info);
170 }
171 }
172
173 void W_HandleDNDClientMessage(WMView * toplevel, XClientMessageEvent * event)
174 {
175 WMScreen *scr = W_VIEW_SCREEN(toplevel);
176 WMDraggingInfo *info = &scr->dragInfo;
177 Atom messageType = event->message_type;
178
179 #ifdef XDND_DEBUG
180 {
181 char *msgTypeName = XGetAtomName(scr->display, messageType);
182
183 if (msgTypeName != NULL)
184 printf("event type = %s\n", msgTypeName);
185 else
186 printf("pb with event type !\n");
187 }
188 #endif
189
190 /* Messages from destination to source */
191 if (messageType == scr->xdndStatusAtom || messageType == scr->xdndFinishedAtom) {
192 W_DragSourceStopTimer();
193 W_DragSourceStateHandler(info, event);
194 return;
195 }
196
197 /* Messages from source to destination */
198 if (messageType == scr->xdndEnterAtom) {
199 Bool positionSent = (XDND_DEST_INFO(info) != NULL);
200
201 W_DragDestinationStopTimer();
202 W_DragDestinationStoreEnterMsgInfo(info, toplevel, event);
203
204 /* Xdnd version 3 and up are not compatible with version 1 or 2 */
205 if (XDND_SOURCE_VERSION(info) > 2) {
206
207 if (positionSent) {
208 /* xdndPosition previously received on xdnd aware view */
209 W_DragDestinationStateHandler(info, event);
210 return;
211 } else {
212 W_DragDestinationStartTimer(info);
213 return;
214 }
215 } else {
216 wwarning("received dnd enter msg with unsupported version %i", XDND_SOURCE_VERSION(info));
217 W_DragDestinationCancelDropOnEnter(toplevel, info);
218 return;
219 }
220 }
221
222 if (messageType == scr->xdndPositionAtom) {
223 W_DragDestinationStopTimer();
224 W_DragDestinationStorePositionMsgInfo(info, toplevel, event);
225 W_DragDestinationStateHandler(info, event);
226 return;
227 }
228
229 if (messageType == scr->xdndSelectionAtom || messageType == scr->xdndDropAtom) {
230 W_DragDestinationStopTimer();
231 W_DragDestinationStateHandler(info, event);
232 return;
233 }
234
235 if (messageType == scr->xdndLeaveAtom) {
236 /* conclude drop operation, and clear dragging info */
237 W_DragDestinationStopTimer();
238 handleLeaveMessage(info);
239 }
240 }
241
242 /* called in destroyView (wview.c) */
243 void W_FreeViewXdndPart(WMView * view)
244 {
245 WMUnregisterViewDraggedTypes(view);
246
247 if (view->dragSourceProcs)
248 wfree(view->dragSourceProcs);
249
250 if (view->dragDestinationProcs)
251 wfree(view->dragDestinationProcs);
252
253 if (view->dragImage)
254 WMReleasePixmap(view->dragImage);
255 }