Change to the linux kernel coding style
[wmaker-crm.git] / WINGs / dragcommon.c
Commit [+]AuthorDateLineData
558615a8 dan2004-10-30 05:46:37 +00001
b8193865 dan2004-04-07 10:15:52 +00002#include "WINGsP.h"
3
085e9d62 dan2006-01-22 20:33:19 +00004#define XDND_SOURCE_VERSION(dragInfo) dragInfo->protocolVersion
b8193865 dan2004-04-07 10:15:52 +00005#define XDND_DEST_INFO(dragInfo) dragInfo->destInfo
6#define XDND_DEST_VIEW(dragInfo) dragInfo->destInfo->destView
b8193865 dan2004-04-07 10:15:52 +00007
b8193865 dan2004-04-07 10:15:52 +00008static Bool _WindowExists;
9
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +020010Atom W_OperationToAction(WMScreen * scr, WMDragOperationType operation)
b8193865 dan2004-04-07 10:15:52 +000011{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +020012 switch (operation) {
13 case WDOperationNone:
14 return None;
b8193865 dan2004-04-07 10:15:52 +000015
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +020016 case WDOperationCopy:
17 return scr->xdndActionCopy;
b8193865 dan2004-04-07 10:15:52 +000018
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +020019 case WDOperationMove:
20 return scr->xdndActionMove;
b8193865 dan2004-04-07 10:15:52 +000021
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +020022 case WDOperationLink:
23 return scr->xdndActionLink;
b8193865 dan2004-04-07 10:15:52 +000024
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +020025 case WDOperationAsk:
26 return scr->xdndActionAsk;
b8193865 dan2004-04-07 10:15:52 +000027
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +020028 case WDOperationPrivate:
29 return scr->xdndActionPrivate;
b8193865 dan2004-04-07 10:15:52 +000030
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +020031 default:
32 return None;
33 }
b8193865 dan2004-04-07 10:15:52 +000034}
35
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +020036WMDragOperationType W_ActionToOperation(WMScreen * scr, Atom action)
b8193865 dan2004-04-07 10:15:52 +000037{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +020038 if (action == scr->xdndActionCopy) {
39 return WDOperationCopy;
b8193865 dan2004-04-07 10:15:52 +000040
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +020041 } else if (action == scr->xdndActionMove) {
42 return WDOperationMove;
b8193865 dan2004-04-07 10:15:52 +000043
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +020044 } else if (action == scr->xdndActionLink) {
45 return WDOperationLink;
b8193865 dan2004-04-07 10:15:52 +000046
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +020047 } else if (action == scr->xdndActionAsk) {
48 return WDOperationAsk;
b8193865 dan2004-04-07 10:15:52 +000049
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +020050 } else if (action == scr->xdndActionPrivate) {
51 return WDOperationPrivate;
b8193865 dan2004-04-07 10:15:52 +000052
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +020053 } else if (action == None) {
b8193865 dan2004-04-07 10:15:52 +000054
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +020055 return WDOperationNone;
56 } else {
57 char *tmp = XGetAtomName(scr->display, action);
b8193865 dan2004-04-07 10:15:52 +000058
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +020059 wwarning("unknown XDND action %s ", tmp);
60 XFree(tmp);
b8193865 dan2004-04-07 10:15:52 +000061
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +020062 return WDOperationCopy;
63 }
b8193865 dan2004-04-07 10:15:52 +000064}
65
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +020066static void freeDragOperationItem(void *item)
b8193865 dan2004-04-07 10:15:52 +000067{
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +020068 wfree(item);
b8193865 dan2004-04-07 10:15:52 +000069}
70
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +020071WMArray *WMCreateDragOperationArray(int initialSize)
b8193865 dan2004-04-07 10:15:52 +000072{
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +020073 return WMCreateArrayWithDestructor(initialSize, freeDragOperationItem);
b8193865 dan2004-04-07 10:15:52 +000074}
75
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +020076WMDragOperationItem *WMCreateDragOperationItem(WMDragOperationType type, char *text)
b8193865 dan2004-04-07 10:15:52 +000077{
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +020078 W_DragOperationItem *result = wmalloc(sizeof(W_DragOperationItem));
b8193865 dan2004-04-07 10:15:52 +000079
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +020080 result->type = type;
81 result->text = text;
b8193865 dan2004-04-07 10:15:52 +000082
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +020083 return (WMDragOperationItem *) result;
b8193865 dan2004-04-07 10:15:52 +000084}
85
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +020086WMDragOperationType WMGetDragOperationItemType(WMDragOperationItem * item)
b8193865 dan2004-04-07 10:15:52 +000087{
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +020088 return ((W_DragOperationItem *) item)->type;
b8193865 dan2004-04-07 10:15:52 +000089}
90
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +020091char *WMGetDragOperationItemText(WMDragOperationItem * item)
b8193865 dan2004-04-07 10:15:52 +000092{
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +020093 return ((W_DragOperationItem *) item)->text;
b8193865 dan2004-04-07 10:15:52 +000094}
95
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +020096static int handleNoWindowXError(Display * dpy, XErrorEvent * errEvt)
b8193865 dan2004-04-07 10:15:52 +000097{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +020098 if (errEvt->error_code == BadWindow || errEvt->error_code == BadDrawable) {
99 _WindowExists = False;
100 return Success;
101 }
b8193865 dan2004-04-07 10:15:52 +0000102
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200103 return errEvt->error_code;
b8193865 dan2004-04-07 10:15:52 +0000104}
105
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200106static Bool windowExists(Display * dpy, Window win)
b8193865 dan2004-04-07 10:15:52 +0000107{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200108 void *previousErrorHandler;
109 XWindowAttributes attr;
b8193865 dan2004-04-07 10:15:52 +0000110
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200111 XSynchronize(dpy, True);
112 previousErrorHandler = XSetErrorHandler(handleNoWindowXError);
113 _WindowExists = True;
b8193865 dan2004-04-07 10:15:52 +0000114
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200115 /* can generate BadDrawable or BadWindow */
116 XGetWindowAttributes(dpy, win, &attr);
b8193865 dan2004-04-07 10:15:52 +0000117
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200118 XSetErrorHandler(previousErrorHandler);
119 XSynchronize(dpy, False);
120 return _WindowExists;
b8193865 dan2004-04-07 10:15:52 +0000121}
122
b8193865 dan2004-04-07 10:15:52 +0000123Bool
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200124W_SendDnDClientMessage(Display * dpy, Window win, Atom message,
125 unsigned long data0,
126 unsigned long data1, unsigned long data2, unsigned long data3, unsigned long data4)
b8193865 dan2004-04-07 10:15:52 +0000127{
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200128 XEvent ev;
b8193865 dan2004-04-07 10:15:52 +0000129
085e9d62 dan2006-01-22 20:33:19 +0000130#ifdef XDND_DEBUG
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200131 char *msgName = XGetAtomName(dpy, message);
085e9d62 dan2006-01-22 20:33:19 +0000132
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200133 printf("sending message %s ... ", msgName);
134 XFree(msgName);
085e9d62 dan2006-01-22 20:33:19 +0000135#endif
136
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200137 if (!windowExists(dpy, win)) {
138 wwarning("xdnd message target %d does no longer exist.", win);
139 return False; /* message not sent */
140 }
b8193865 dan2004-04-07 10:15:52 +0000141
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200142 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;
b8193865 dan2004-04-07 10:15:52 +0000151
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200152 XSendEvent(dpy, win, False, 0, &ev);
153 XFlush(dpy);
b8193865 dan2004-04-07 10:15:52 +0000154
085e9d62 dan2006-01-22 20:33:19 +0000155#ifdef XDND_DEBUG
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200156 printf("sent\n");
085e9d62 dan2006-01-22 20:33:19 +0000157#endif
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200158 return True; /* message sent */
b8193865 dan2004-04-07 10:15:52 +0000159}
160
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200161static void handleLeaveMessage(WMDraggingInfo * info)
b8193865 dan2004-04-07 10:15:52 +0000162{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200163 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 }
b8193865 dan2004-04-07 10:15:52 +0000171}
172
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200173void W_HandleDNDClientMessage(WMView * toplevel, XClientMessageEvent * event)
b8193865 dan2004-04-07 10:15:52 +0000174{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200175 WMScreen *scr = W_VIEW_SCREEN(toplevel);
176 WMDraggingInfo *info = &scr->dragInfo;
177 Atom messageType = event->message_type;
b8193865 dan2004-04-07 10:15:52 +0000178
b8193865 dan2004-04-07 10:15:52 +0000179#ifdef XDND_DEBUG
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200180 {
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 }
b8193865 dan2004-04-07 10:15:52 +0000188#endif
189
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200190 /* 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 }
b8193865 dan2004-04-07 10:15:52 +0000240}
241
b8193865 dan2004-04-07 10:15:52 +0000242/* called in destroyView (wview.c) */
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200243void W_FreeViewXdndPart(WMView * view)
b8193865 dan2004-04-07 10:15:52 +0000244{
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200245 WMUnregisterViewDraggedTypes(view);
b8193865 dan2004-04-07 10:15:52 +0000246
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200247 if (view->dragSourceProcs)
248 wfree(view->dragSourceProcs);
b8193865 dan2004-04-07 10:15:52 +0000249
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200250 if (view->dragDestinationProcs)
251 wfree(view->dragDestinationProcs);
b8193865 dan2004-04-07 10:15:52 +0000252
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200253 if (view->dragImage)
254 WMReleasePixmap(view->dragImage);
b8193865 dan2004-04-07 10:15:52 +0000255}