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
8 static Bool _WindowExists
;
10 Atom
W_OperationToAction(WMScreen
* scr
, WMDragOperationType operation
)
17 return scr
->xdndActionCopy
;
20 return scr
->xdndActionMove
;
23 return scr
->xdndActionLink
;
26 return scr
->xdndActionAsk
;
28 case WDOperationPrivate
:
29 return scr
->xdndActionPrivate
;
36 WMDragOperationType
W_ActionToOperation(WMScreen
* scr
, Atom action
)
38 if (action
== scr
->xdndActionCopy
) {
39 return WDOperationCopy
;
41 } else if (action
== scr
->xdndActionMove
) {
42 return WDOperationMove
;
44 } else if (action
== scr
->xdndActionLink
) {
45 return WDOperationLink
;
47 } else if (action
== scr
->xdndActionAsk
) {
48 return WDOperationAsk
;
50 } else if (action
== scr
->xdndActionPrivate
) {
51 return WDOperationPrivate
;
53 } else if (action
== None
) {
55 return WDOperationNone
;
57 char *tmp
= XGetAtomName(scr
->display
, action
);
59 wwarning("unknown XDND action %s ", tmp
);
62 return WDOperationCopy
;
66 static void freeDragOperationItem(void *item
)
71 WMArray
*WMCreateDragOperationArray(int initialSize
)
73 return WMCreateArrayWithDestructor(initialSize
, freeDragOperationItem
);
76 WMDragOperationItem
*WMCreateDragOperationItem(WMDragOperationType type
, char *text
)
78 W_DragOperationItem
*result
= wmalloc(sizeof(W_DragOperationItem
));
83 return (WMDragOperationItem
*) result
;
86 WMDragOperationType
WMGetDragOperationItemType(WMDragOperationItem
* item
)
88 return ((W_DragOperationItem
*) item
)->type
;
91 char *WMGetDragOperationItemText(WMDragOperationItem
* item
)
93 return ((W_DragOperationItem
*) item
)->text
;
96 static int handleNoWindowXError(Display
* dpy
, XErrorEvent
* errEvt
)
98 /* Parameter not used, but tell the compiler that it is ok */
101 if (errEvt
->error_code
== BadWindow
|| errEvt
->error_code
== BadDrawable
) {
102 _WindowExists
= False
;
106 return errEvt
->error_code
;
109 static Bool
windowExists(Display
* dpy
, Window win
)
111 void *previousErrorHandler
;
112 XWindowAttributes attr
;
114 XSynchronize(dpy
, True
);
115 previousErrorHandler
= XSetErrorHandler(handleNoWindowXError
);
116 _WindowExists
= True
;
118 /* can generate BadDrawable or BadWindow */
119 XGetWindowAttributes(dpy
, win
, &attr
);
121 XSetErrorHandler(previousErrorHandler
);
122 XSynchronize(dpy
, False
);
123 return _WindowExists
;
127 W_SendDnDClientMessage(Display
* dpy
, Window win
, Atom message
,
129 unsigned long data1
, unsigned long data2
, unsigned long data3
, unsigned long data4
)
134 char *msgName
= XGetAtomName(dpy
, message
);
136 printf("sending message %s ... ", msgName
);
140 if (!windowExists(dpy
, win
)) {
141 wwarning("xdnd message target %lu does no longer exist.", win
);
142 return False
; /* message not sent */
145 ev
.type
= ClientMessage
;
146 ev
.xclient
.message_type
= message
;
147 ev
.xclient
.format
= 32;
148 ev
.xclient
.window
= win
;
149 ev
.xclient
.data
.l
[0] = data0
;
150 ev
.xclient
.data
.l
[1] = data1
;
151 ev
.xclient
.data
.l
[2] = data2
;
152 ev
.xclient
.data
.l
[3] = data3
;
153 ev
.xclient
.data
.l
[4] = data4
;
155 XSendEvent(dpy
, win
, False
, 0, &ev
);
161 return True
; /* message sent */
164 static void handleLeaveMessage(WMDraggingInfo
* info
)
166 if (XDND_DEST_INFO(info
) != NULL
) {
167 /* XDND_DEST_VIEW is never NULL (it's the xdnd aware view) */
168 wassertr(XDND_DEST_VIEW(info
) != NULL
);
169 if (XDND_DEST_VIEW(info
)->dragDestinationProcs
!= NULL
) {
170 XDND_DEST_VIEW(info
)->dragDestinationProcs
->concludeDragOperation(XDND_DEST_VIEW(info
));
172 W_DragDestinationInfoClear(info
);
176 void W_HandleDNDClientMessage(WMView
* toplevel
, XClientMessageEvent
* event
)
178 WMScreen
*scr
= W_VIEW_SCREEN(toplevel
);
179 WMDraggingInfo
*info
= &scr
->dragInfo
;
180 Atom messageType
= event
->message_type
;
184 char *msgTypeName
= XGetAtomName(scr
->display
, messageType
);
186 if (msgTypeName
!= NULL
)
187 printf("event type = %s\n", msgTypeName
);
189 printf("pb with event type !\n");
193 /* Messages from destination to source */
194 if (messageType
== scr
->xdndStatusAtom
|| messageType
== scr
->xdndFinishedAtom
) {
195 W_DragSourceStopTimer();
196 W_DragSourceStateHandler(info
, event
);
200 /* Messages from source to destination */
201 if (messageType
== scr
->xdndEnterAtom
) {
202 Bool positionSent
= (XDND_DEST_INFO(info
) != NULL
);
204 W_DragDestinationStopTimer();
205 W_DragDestinationStoreEnterMsgInfo(info
, toplevel
, event
);
207 /* Xdnd version 3 and up are not compatible with version 1 or 2 */
208 if (XDND_SOURCE_VERSION(info
) > 2) {
211 /* xdndPosition previously received on xdnd aware view */
212 W_DragDestinationStateHandler(info
, event
);
215 W_DragDestinationStartTimer(info
);
219 wwarning("received dnd enter msg with unsupported version %i", XDND_SOURCE_VERSION(info
));
220 W_DragDestinationCancelDropOnEnter(toplevel
, info
);
225 if (messageType
== scr
->xdndPositionAtom
) {
226 W_DragDestinationStopTimer();
227 W_DragDestinationStorePositionMsgInfo(info
, toplevel
, event
);
228 W_DragDestinationStateHandler(info
, event
);
232 if (messageType
== scr
->xdndSelectionAtom
|| messageType
== scr
->xdndDropAtom
) {
233 W_DragDestinationStopTimer();
234 W_DragDestinationStateHandler(info
, event
);
238 if (messageType
== scr
->xdndLeaveAtom
) {
239 /* conclude drop operation, and clear dragging info */
240 W_DragDestinationStopTimer();
241 handleLeaveMessage(info
);
245 /* called in destroyView (wview.c) */
246 void W_FreeViewXdndPart(WMView
* view
)
248 WMUnregisterViewDraggedTypes(view
);
250 if (view
->dragSourceProcs
)
251 wfree(view
->dragSourceProcs
);
253 if (view
->dragDestinationProcs
)
254 wfree(view
->dragDestinationProcs
);
257 WMReleasePixmap(view
->dragImage
);