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 if (errEvt
->error_code
== BadWindow
|| errEvt
->error_code
== BadDrawable
) {
99 _WindowExists
= False
;
103 return errEvt
->error_code
;
106 static Bool
windowExists(Display
* dpy
, Window win
)
108 void *previousErrorHandler
;
109 XWindowAttributes attr
;
111 XSynchronize(dpy
, True
);
112 previousErrorHandler
= XSetErrorHandler(handleNoWindowXError
);
113 _WindowExists
= True
;
115 /* can generate BadDrawable or BadWindow */
116 XGetWindowAttributes(dpy
, win
, &attr
);
118 XSetErrorHandler(previousErrorHandler
);
119 XSynchronize(dpy
, False
);
120 return _WindowExists
;
124 W_SendDnDClientMessage(Display
* dpy
, Window win
, Atom message
,
126 unsigned long data1
, unsigned long data2
, unsigned long data3
, unsigned long data4
)
131 char *msgName
= XGetAtomName(dpy
, message
);
133 printf("sending message %s ... ", msgName
);
137 if (!windowExists(dpy
, win
)) {
138 wwarning("xdnd message target %lu does no longer exist.", win
);
139 return False
; /* message not sent */
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
;
152 XSendEvent(dpy
, win
, False
, 0, &ev
);
158 return True
; /* message sent */
161 static void handleLeaveMessage(WMDraggingInfo
* info
)
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
));
169 W_DragDestinationInfoClear(info
);
173 void W_HandleDNDClientMessage(WMView
* toplevel
, XClientMessageEvent
* event
)
175 WMScreen
*scr
= W_VIEW_SCREEN(toplevel
);
176 WMDraggingInfo
*info
= &scr
->dragInfo
;
177 Atom messageType
= event
->message_type
;
181 char *msgTypeName
= XGetAtomName(scr
->display
, messageType
);
183 if (msgTypeName
!= NULL
)
184 printf("event type = %s\n", msgTypeName
);
186 printf("pb with event type !\n");
190 /* Messages from destination to source */
191 if (messageType
== scr
->xdndStatusAtom
|| messageType
== scr
->xdndFinishedAtom
) {
192 W_DragSourceStopTimer();
193 W_DragSourceStateHandler(info
, event
);
197 /* Messages from source to destination */
198 if (messageType
== scr
->xdndEnterAtom
) {
199 Bool positionSent
= (XDND_DEST_INFO(info
) != NULL
);
201 W_DragDestinationStopTimer();
202 W_DragDestinationStoreEnterMsgInfo(info
, toplevel
, event
);
204 /* Xdnd version 3 and up are not compatible with version 1 or 2 */
205 if (XDND_SOURCE_VERSION(info
) > 2) {
208 /* xdndPosition previously received on xdnd aware view */
209 W_DragDestinationStateHandler(info
, event
);
212 W_DragDestinationStartTimer(info
);
216 wwarning("received dnd enter msg with unsupported version %i", XDND_SOURCE_VERSION(info
));
217 W_DragDestinationCancelDropOnEnter(toplevel
, info
);
222 if (messageType
== scr
->xdndPositionAtom
) {
223 W_DragDestinationStopTimer();
224 W_DragDestinationStorePositionMsgInfo(info
, toplevel
, event
);
225 W_DragDestinationStateHandler(info
, event
);
229 if (messageType
== scr
->xdndSelectionAtom
|| messageType
== scr
->xdndDropAtom
) {
230 W_DragDestinationStopTimer();
231 W_DragDestinationStateHandler(info
, event
);
235 if (messageType
== scr
->xdndLeaveAtom
) {
236 /* conclude drop operation, and clear dragging info */
237 W_DragDestinationStopTimer();
238 handleLeaveMessage(info
);
242 /* called in destroyView (wview.c) */
243 void W_FreeViewXdndPart(WMView
* view
)
245 WMUnregisterViewDraggedTypes(view
);
247 if (view
->dragSourceProcs
)
248 wfree(view
->dragSourceProcs
);
250 if (view
->dragDestinationProcs
)
251 wfree(view
->dragDestinationProcs
);
254 WMReleasePixmap(view
->dragImage
);