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 }