5 #define XDND_SOURCE_VERSION(dragInfo) dragInfo->protocolVersion
6 #define XDND_DEST_INFO(dragInfo) dragInfo->destInfo
7 #define XDND_DEST_VIEW(dragInfo) dragInfo->destInfo->destView
9 static Bool _WindowExists
;
11 Atom
W_OperationToAction(WMScreen
* scr
, WMDragOperationType operation
)
18 return scr
->xdndActionCopy
;
21 return scr
->xdndActionMove
;
24 return scr
->xdndActionLink
;
27 return scr
->xdndActionAsk
;
29 case WDOperationPrivate
:
30 return scr
->xdndActionPrivate
;
37 WMDragOperationType
W_ActionToOperation(WMScreen
* scr
, Atom action
)
39 if (action
== scr
->xdndActionCopy
) {
40 return WDOperationCopy
;
42 } else if (action
== scr
->xdndActionMove
) {
43 return WDOperationMove
;
45 } else if (action
== scr
->xdndActionLink
) {
46 return WDOperationLink
;
48 } else if (action
== scr
->xdndActionAsk
) {
49 return WDOperationAsk
;
51 } else if (action
== scr
->xdndActionPrivate
) {
52 return WDOperationPrivate
;
54 } else if (action
== None
) {
56 return WDOperationNone
;
58 char *tmp
= XGetAtomName(scr
->display
, action
);
60 wwarning(_("unknown XDND action %s"), tmp
);
63 return WDOperationCopy
;
67 static void freeDragOperationItem(void *item
)
72 WMArray
*WMCreateDragOperationArray(int initialSize
)
74 return WMCreateArrayWithDestructor(initialSize
, freeDragOperationItem
);
77 WMDragOperationItem
*WMCreateDragOperationItem(WMDragOperationType type
, char *text
)
79 W_DragOperationItem
*result
= wmalloc(sizeof(W_DragOperationItem
));
84 return (WMDragOperationItem
*) result
;
87 WMDragOperationType
WMGetDragOperationItemType(WMDragOperationItem
* item
)
89 return ((W_DragOperationItem
*) item
)->type
;
92 char *WMGetDragOperationItemText(WMDragOperationItem
* item
)
94 return ((W_DragOperationItem
*) item
)->text
;
97 static int handleNoWindowXError(Display
* dpy
, XErrorEvent
* errEvt
)
99 /* Parameter not used, but tell the compiler that it is ok */
102 if (errEvt
->error_code
== BadWindow
|| errEvt
->error_code
== BadDrawable
) {
103 _WindowExists
= False
;
107 return errEvt
->error_code
;
110 static Bool
windowExists(Display
* dpy
, Window win
)
112 void *previousErrorHandler
;
113 XWindowAttributes attr
;
115 XSynchronize(dpy
, True
);
116 previousErrorHandler
= XSetErrorHandler(handleNoWindowXError
);
117 _WindowExists
= True
;
119 /* can generate BadDrawable or BadWindow */
120 XGetWindowAttributes(dpy
, win
, &attr
);
122 XSetErrorHandler(previousErrorHandler
);
123 XSynchronize(dpy
, False
);
124 return _WindowExists
;
128 W_SendDnDClientMessage(Display
* dpy
, Window win
, Atom message
,
130 unsigned long data1
, unsigned long data2
, unsigned long data3
, unsigned long data4
)
135 char *msgName
= XGetAtomName(dpy
, message
);
137 printf("sending message %s ... ", msgName
);
141 if (!windowExists(dpy
, win
)) {
142 wwarning(_("target %lu for XDND message no longer exists"), win
);
143 return False
; /* message not sent */
146 ev
.type
= ClientMessage
;
147 ev
.xclient
.message_type
= message
;
148 ev
.xclient
.format
= 32;
149 ev
.xclient
.window
= win
;
150 ev
.xclient
.data
.l
[0] = data0
;
151 ev
.xclient
.data
.l
[1] = data1
;
152 ev
.xclient
.data
.l
[2] = data2
;
153 ev
.xclient
.data
.l
[3] = data3
;
154 ev
.xclient
.data
.l
[4] = data4
;
156 XSendEvent(dpy
, win
, False
, 0, &ev
);
162 return True
; /* message sent */
165 static void handleLeaveMessage(WMDraggingInfo
* info
)
167 if (XDND_DEST_INFO(info
) != NULL
) {
168 /* XDND_DEST_VIEW is never NULL (it's the xdnd aware view) */
169 wassertr(XDND_DEST_VIEW(info
) != NULL
);
170 if (XDND_DEST_VIEW(info
)->dragDestinationProcs
!= NULL
) {
171 XDND_DEST_VIEW(info
)->dragDestinationProcs
->concludeDragOperation(XDND_DEST_VIEW(info
));
173 W_DragDestinationInfoClear(info
);
177 void W_HandleDNDClientMessage(WMView
* toplevel
, XClientMessageEvent
* event
)
179 WMScreen
*scr
= W_VIEW_SCREEN(toplevel
);
180 WMDraggingInfo
*info
= &scr
->dragInfo
;
181 Atom messageType
= event
->message_type
;
185 char *msgTypeName
= XGetAtomName(scr
->display
, messageType
);
187 if (msgTypeName
!= NULL
)
188 printf("event type = %s\n", msgTypeName
);
190 printf("pb with event type !\n");
194 /* Messages from destination to source */
195 if (messageType
== scr
->xdndStatusAtom
|| messageType
== scr
->xdndFinishedAtom
) {
196 W_DragSourceStopTimer();
197 W_DragSourceStateHandler(info
, event
);
201 /* Messages from source to destination */
202 if (messageType
== scr
->xdndEnterAtom
) {
203 Bool positionSent
= (XDND_DEST_INFO(info
) != NULL
);
205 W_DragDestinationStopTimer();
206 W_DragDestinationStoreEnterMsgInfo(info
, toplevel
, event
);
208 /* Xdnd version 3 and up are not compatible with version 1 or 2 */
209 if (XDND_SOURCE_VERSION(info
) > 2) {
212 /* xdndPosition previously received on xdnd aware view */
213 W_DragDestinationStateHandler(info
, event
);
216 W_DragDestinationStartTimer(info
);
220 wwarning(_("unsupported version %i for XDND enter message"), XDND_SOURCE_VERSION(info
));
221 W_DragDestinationCancelDropOnEnter(toplevel
, info
);
226 if (messageType
== scr
->xdndPositionAtom
) {
227 W_DragDestinationStopTimer();
228 W_DragDestinationStorePositionMsgInfo(info
, toplevel
, event
);
229 W_DragDestinationStateHandler(info
, event
);
233 if (messageType
== scr
->xdndSelectionAtom
|| messageType
== scr
->xdndDropAtom
) {
234 W_DragDestinationStopTimer();
235 W_DragDestinationStateHandler(info
, event
);
239 if (messageType
== scr
->xdndLeaveAtom
) {
240 /* conclude drop operation, and clear dragging info */
241 W_DragDestinationStopTimer();
242 handleLeaveMessage(info
);
246 /* called in destroyView (wview.c) */
247 void W_FreeViewXdndPart(WMView
* view
)
249 WMUnregisterViewDraggedTypes(view
);
251 if (view
->dragSourceProcs
)
252 wfree(view
->dragSourceProcs
);
254 if (view
->dragDestinationProcs
)
255 wfree(view
->dragDestinationProcs
);
258 WMReleasePixmap(view
->dragImage
);