14 #define IS_DROPPABLE(view) (view!=NULL && view->droppableTypes!=NULL && \
15 view->dragDestinationProcs!=NULL)
18 static Atom
operationToAction(WMScreen
*scr
, WMDragOperationType operation
);
19 static WMDragOperationType
actionToOperation(WMScreen
*scr
, Atom action
);
21 static Bool _XErrorOccured
= False
;
27 WMSetViewDragSourceProcs(WMView
*view
, WMDragSourceProcs
*procs
)
29 if (view
->dragSourceProcs
)
30 free(view
->dragSourceProcs
);
31 view
->dragSourceProcs
= wmalloc(sizeof(WMDragSourceProcs
));
33 *view
->dragSourceProcs
= *procs
;
35 /* XXX fill in non-implemented stuffs */
39 /***********************************************************************/
43 handleXError(Display
*dpy
, XErrorEvent
*ev
)
45 _XErrorOccured
= True
;
52 protectBlock(Bool begin
)
54 static void *oldHandler
= NULL
;
57 oldHandler
= XSetErrorHandler(handleXError
);
59 XSetErrorHandler(oldHandler
);
67 makeDragIcon(WMScreen
*scr
, WMPixmap
*pixmap
)
72 XSetWindowAttributes attribs
;
76 pixmap
= scr
->defaultObjectIcon
;
78 size
= WMGetPixmapSize(pixmap
);
82 flags
= CWSaveUnder
|CWBackPixmap
|CWOverrideRedirect
|CWColormap
;
83 attribs
.save_under
= True
;
84 attribs
.background_pixmap
= pix
;
85 attribs
.override_redirect
= True
;
86 attribs
.colormap
= scr
->colormap
;
87 window
= XCreateWindow(scr
->display
, scr
->rootWin
, 0, 0, size
.width
,
88 size
.height
, 0, scr
->depth
, InputOutput
,
89 scr
->visual
, flags
, &attribs
);
93 XShapeCombineMask(dpy
, scr
->balloon
->window
, ShapeBounding
, 0, 0, mask
,
103 slideWindow(Display
*dpy
, Window win
, int srcX
, int srcY
, int dstX
, int dstY
)
109 iterations
= WMIN(25, WMAX(abs(dstX
-srcX
), abs(dstY
-srcY
)));
114 dx
= (double)(dstX
-srcX
)/iterations
;
115 dy
= (double)(dstY
-srcY
)/iterations
;
117 for (i
= 0; i
<= iterations
; i
++) {
118 XMoveWindow(dpy
, win
, x
, y
);
130 findChildInWindow(Display
*dpy
, Window toplevel
, int x
, int y
)
137 if (!XQueryTree(dpy
, toplevel
, &foo
, &bar
,
138 &children
, &nchildren
) || children
== NULL
) {
142 /* first window that contains the point is the one */
143 for (i
= nchildren
-1; i
>= 0; i
--) {
144 XWindowAttributes attr
;
146 if (XGetWindowAttributes(dpy
, children
[i
], &attr
)
147 && attr
.map_state
== IsViewable
148 && x
>= attr
.x
&& y
>= attr
.y
149 && x
< attr
.x
+ attr
.width
&& y
< attr
.y
+ attr
.height
) {
152 child
= findChildInWindow(dpy
, children
[i
],
153 x
- attr
.x
, y
- attr
.y
);
170 findViewInToplevel(Display
*dpy
, Window toplevel
, int x
, int y
)
174 child
= findChildInWindow(dpy
, toplevel
, x
, y
);
177 return W_GetViewForXWindow(dpy
, child
);
185 lookForToplevel(WMScreen
*scr
, Window window
, Bool
*isAware
)
187 Window toplevel
= None
;
193 atoms
= XListProperties(scr
->display
, window
, &count
);
194 for (j
= 0; j
< count
; j
++) {
195 if (atoms
[j
] == scr
->wmStateAtom
) {
197 } else if (atoms
[j
] == scr
->xdndAwareAtom
) {
204 if (toplevel
== None
) {
209 if (!XQueryTree(scr
->display
, window
, &foo
, &bar
,
210 &children
, &nchildren
) || children
== NULL
) {
214 for (j
= 0; j
< nchildren
; j
++) {
215 toplevel
= lookForToplevel(scr
, children
[j
], isAware
);
216 if (toplevel
!= None
)
231 findToplevelUnderDragPointer(WMScreen
*scr
, int x
, int y
, Window iconWindow
)
236 Bool overSomething
= False
;
239 if (!XQueryTree(scr
->display
, scr
->rootWin
, &foo
, &bar
,
240 &children
, &nchildren
) || children
== NULL
) {
241 SPIT("couldnt query tree!");
245 /* try to find the window below the iconWindow by traversing
246 * the whole window list */
248 /* first find the position of the iconWindow */
249 for (i
= nchildren
-1; i
>= 0; i
--) {
250 if (children
[i
] == iconWindow
) {
260 /* first window that contains the point is the one */
261 for (; i
>= 0; i
--) {
262 XWindowAttributes attr
;
264 if (XGetWindowAttributes(scr
->display
, children
[i
], &attr
)
265 && attr
.map_state
== IsViewable
266 && x
>= attr
.x
&& y
>= attr
.y
267 && x
< attr
.x
+ attr
.width
&& y
< attr
.y
+ attr
.height
) {
271 overSomething
= True
;
273 toplevel
= lookForToplevel(scr
, children
[i
], &isaware
);
297 sendClientMessage(Display
*dpy
, Window win
, Atom message
,
298 unsigned data1
, unsigned data2
, unsigned data3
,
299 unsigned data4
, unsigned data5
)
303 ev
.type
= ClientMessage
;
304 ev
.xclient
.message_type
= message
;
305 ev
.xclient
.format
= 32;
306 ev
.xclient
.window
= win
;
307 ev
.xclient
.data
.l
[0] = data1
;
308 ev
.xclient
.data
.l
[1] = data2
;
309 ev
.xclient
.data
.l
[2] = data3
;
310 ev
.xclient
.data
.l
[3] = data4
;
311 ev
.xclient
.data
.l
[4] = data5
;
313 XSendEvent(dpy
, win
, False
, 0, &ev
);
321 notifyPosition(WMScreen
*scr
, WMDraggingInfo
*info
)
323 Atom action
= operationToAction(scr
, info
->sourceOperation
);
325 sendClientMessage(scr
->display
, info
->destinationWindow
,
326 scr
->xdndPositionAtom
,
329 info
->location
.x
<<16|info
->location
.y
,
331 action
/* operation */);
339 notifyDrop(WMScreen
*scr
, WMDraggingInfo
*info
)
341 sendClientMessage(scr
->display
, info
->destinationWindow
,
352 notifyDragLeave(WMScreen
*scr
, WMDraggingInfo
*info
)
354 sendClientMessage(scr
->display
, info
->destinationWindow
,
356 info
->sourceWindow
, 0, 0, 0, 0);
362 notifyDragEnter(WMScreen
*scr
, WMDraggingInfo
*info
)
366 d
= XDND_VERSION
<< 24;
368 sendClientMessage(scr
->display
, info
->destinationWindow
,
370 info
->sourceWindow
, d
, 0, 0, 0);
377 translateCoordinates(WMScreen
*scr
, Window target
, int fromX
, int fromY
,
382 XTranslateCoordinates(scr
->display
, scr
->rootWin
, target
,
383 fromX
, fromY
, x
, y
, &child
);
388 updateDraggingInfo(WMScreen
*scr
, WMDraggingInfo
*info
,
389 XEvent
*event
, Window iconWindow
)
394 size
= WMGetPixmapSize(info
->image
);
396 if (event
->type
== MotionNotify
) {
397 info
->imageLocation
.x
= event
->xmotion
.x_root
-(int)size
.width
/2;
398 info
->imageLocation
.y
= event
->xmotion
.y_root
-(int)size
.height
/2;
400 info
->location
.x
= event
->xmotion
.x_root
;
401 info
->location
.y
= event
->xmotion
.y_root
;
402 info
->timestamp
= event
->xmotion
.time
;
404 } else if (event
->type
== ButtonRelease
) {
405 info
->imageLocation
.x
= event
->xbutton
.x_root
-(int)size
.width
/2;
406 info
->imageLocation
.y
= event
->xbutton
.y_root
-(int)size
.height
/2;
408 info
->location
.x
= event
->xbutton
.x_root
;
409 info
->location
.y
= event
->xbutton
.y_root
;
410 info
->timestamp
= event
->xbutton
.time
;
413 toplevel
= findToplevelUnderDragPointer(scr
,
417 info
->destinationWindow
= toplevel
;
424 processMotion(WMScreen
*scr
, WMDraggingInfo
*info
, WMDraggingInfo
*oldInfo
,
425 WMRect
*rect
, unsigned currentAction
)
429 if (info
->destinationWindow
== None
) { /* entered an unsupporeted window */
431 if (oldInfo
->destinationWindow
!= None
432 && oldInfo
->destinationWindow
!= scr
->rootWin
) {
435 notifyDragLeave(scr
, oldInfo
);
438 } else if (info
->destinationWindow
== scr
->rootWin
) {
440 if (oldInfo
->destinationWindow
!= None
441 && oldInfo
->destinationWindow
!= scr
->rootWin
) {
442 SPIT("left window to root");
444 notifyDragLeave(scr
, oldInfo
);
449 } else if (oldInfo
->destinationWindow
!= info
->destinationWindow
) {
451 if (oldInfo
->destinationWindow
!= None
452 && oldInfo
->destinationWindow
!= scr
->rootWin
) {
453 notifyDragLeave(scr
, oldInfo
);
456 SPIT("entered window");
459 action
= notifyDragEnter(scr
, info
);
463 #define LEFT_RECT(r, X, Y) (X < r->pos.x || Y < r->pos.y \
464 || X >= r->pos.x + r->size.width \
465 || Y >= r->pos.y + r->size.height)
467 if (rect
->size
.width
== 0 ||
468 (LEFT_RECT(rect
, info
->location
.x
, info
->location
.y
))) {
470 action
= notifyPosition(scr
, info
);
472 rect
->size
.width
= 0;
480 convertSelection(WMView
*view
, Atom selection
, Atom target
,
481 void *cdata
, Atom
*type
)
483 WMScreen
*scr
= W_VIEW_SCREEN(view
);
485 char *typeName
= XGetAtomName(scr
->display
, target
);
489 data
= view
->dragSourceProcs
->fetchDragData(view
, typeName
);
491 if (typeName
!= NULL
)
499 selectionLost(WMView
*view
, Atom selection
, void *cdata
)
501 if (W_VIEW_SCREEN(view
)->dragSourceView
== view
) {
502 wwarning("DND selection lost during drag operation...");
508 selectionDone(WMView
*view
, Atom selection
, Atom target
, void *cdata
)
521 timeoutCallback(void *data
)
523 wwarning("drag & drop timed out while waiting for response from 0x%x\n",
529 * State Machine For Drag Source:
530 * ------------------------------
532 * State Call Mtn Ent Lea Crs BUp StA StR Fin TO
533 * 0) idle 1bu - - - - - - - - -
534 * 1) drag over target - 1au - 2cu 1cbu 5fu 3 4 1w -
535 * 2) drag over nothing - 2 1bu - - 0 - - 2w -
536 * 3) drag targ+accept - 3u - 2cu 1cbu 6f 3 4w 0z -
537 * 4) drag targ+reject - 4u - 2cu 1cbu 0 3w 4 0z -
538 * 5) waiting status - 5X 5X 5X 5X - 6f 0 0z 0w
539 * 6) dropped - - - - - - - - 0 0w
542 * Call - called WMDragImageFromView()
544 * Ent - Enter droppable window
545 * Lea - Leave droppable window (or rectangle)
546 * Crs - Leave droppable window (or rectangle) and enter another
547 * BUp - Button Released
548 * StA - XdndStatus client msg with Accept drop
549 * StR - XdndStatus client msg with Reject drop
550 * Fin - XdndFinish client msg
554 * a - send update message
555 * b - send enter message
556 * c - send leave message
557 * d - release drag section info
558 * e - send drop message
560 * u - update dragInfo
563 * w - warn about unexpected reply
564 * z - abort operation.. unexpected reply
568 WMDragImageFromView(WMView
*view
, WMPixmap
*image
, char *dataTypes
[],
569 WMPoint atLocation
, WMSize mouseOffset
, XEvent
*event
,
572 WMScreen
*scr
= view
->screen
;
573 Display
*dpy
= scr
->display
;
577 WMRect rect
= {{0,0},{0,0}};
581 XColor black
= {0, 0,0,0, DoRed
|DoGreen
|DoBlue
};
582 XColor green
= {0x0045b045, 0x4500,0xb000,0x4500, DoRed
|DoGreen
|DoBlue
};
583 XColor back
= {0, 0xffff,0xffff,0xffff, DoRed
|DoGreen
|DoBlue
};
584 WMDraggingInfo dragInfo
;
585 WMDraggingInfo oldDragInfo
;
586 WMHandlerID timer
= NULL
;
587 static WMSelectionProcs handler
= {
594 wassertr(scr
->dragSourceView
== NULL
);
596 wassertr(view
->dragSourceProcs
!= NULL
);
599 /* prepare icon to be dragged */
601 image
= scr
->defaultObjectIcon
;
603 size
= WMGetPixmapSize(image
);
605 icon
= makeDragIcon(scr
, image
);
607 XMoveWindow(dpy
, icon
, event
->xmotion
.x_root
-(int)size
.width
/2,
608 event
->xmotion
.y_root
-(int)size
.height
/2);
609 XMapRaised(dpy
, icon
);
612 /* init dragging info */
614 scr
->dragSourceView
= view
;
616 memset(&dragInfo
, 0, sizeof(WMDraggingInfo
));
617 memset(&oldDragInfo
, 0, sizeof(WMDraggingInfo
));
618 dragInfo
.image
= image
;
619 dragInfo
.sourceView
= view
;
620 dragInfo
.sourceWindow
= W_VIEW_DRAWABLE(W_TopLevelOfView(view
));
622 dragInfo
.destinationWindow
= dragInfo
.sourceWindow
;
624 dragInfo
.location
.x
= event
->xmotion
.x_root
;
625 dragInfo
.location
.y
= event
->xmotion
.y_root
;
626 dragInfo
.imageLocation
= atLocation
;
629 /* start pointer grab */
630 XGrabPointer(dpy
, scr
->rootWin
, False
,
631 ButtonPressMask
|ButtonReleaseMask
|ButtonMotionMask
,
632 GrabModeSync
, GrabModeAsync
, None
, scr
->defaultCursor
,
637 _XErrorOccured
= False
;
639 /* take ownership of XdndSelection */
640 if (!WMCreateSelectionHandler(view
, scr
->xdndSelectionAtom
,
643 wwarning("could not get ownership or DND selection");
647 if (view
->dragSourceProcs
->beganDragImage
!= NULL
) {
648 view
->dragSourceProcs
->beganDragImage(view
, image
, atLocation
);
651 processMotion(scr
, &dragInfo
, &oldDragInfo
, &rect
, action
);
655 while (state
!= 6 && state
!= 0 && !_XErrorOccured
) {
656 XAllowEvents(dpy
, SyncPointer
, CurrentTime
);
657 WMNextEvent(dpy
, &ev
);
661 if (state
>= 1 && state
<= 4) {
662 while (XCheckTypedEvent(dpy
, MotionNotify
, &ev
)) ;
666 oldDragInfo
= dragInfo
;
668 updateDraggingInfo(scr
, &dragInfo
, &ev
, icon
);
670 XMoveWindow(dpy
, icon
, dragInfo
.imageLocation
.x
,
671 dragInfo
.imageLocation
.y
);
673 processMotion(scr
, &dragInfo
, &oldDragInfo
, &rect
, action
);
677 /* XXXif entered a different destination, check the operation */
681 if (oldDragInfo
.destinationWindow
!= None
682 && oldDragInfo
.destinationWindow
!= scr
->rootWin
683 && (dragInfo
.destinationWindow
== None
684 || dragInfo
.destinationWindow
== scr
->rootWin
)) {
685 /* left the droppable window */
692 if (dragInfo
.destinationWindow
!= None
693 && dragInfo
.destinationWindow
!= scr
->rootWin
) {
702 if (oldDragInfo
.destinationWindow
!= None
703 && oldDragInfo
.destinationWindow
!= scr
->rootWin
704 && (dragInfo
.destinationWindow
== None
705 || dragInfo
.destinationWindow
== scr
->rootWin
)) {
706 /* left the droppable window */
717 /* if (state >= 1 && state <= 4) */ {
721 oldDragInfo
= dragInfo
;
723 updateDraggingInfo(scr
, &dragInfo
, &ev
, icon
);
725 XMoveWindow(dpy
, icon
, dragInfo
.imageLocation
.x
,
726 dragInfo
.imageLocation
.y
);
728 processMotion(scr
, &dragInfo
, &oldDragInfo
, &rect
, action
);
730 dragInfo
.timestamp
= ev
.xbutton
.time
;
737 timer
= WMAddTimerHandler(3000, timeoutCallback
,
738 (void*)dragInfo
.destinationWindow
);
754 if ((state
== 1 || state
== 3 || state
== 4 || state
== 5)
755 && ev
.xclient
.message_type
== scr
->xdndStatusAtom
756 && ev
.xclient
.data
.l
[0] == dragInfo
.destinationWindow
) {
758 if (ev
.xclient
.data
.l
[1] & 1) {
759 SPIT("got accept msg");
760 /* will accept drop */
769 WMDeleteTimerHandler(timer
);
775 action
= actionToOperation(scr
, ev
.xclient
.data
.l
[4]);
777 SPIT("got reject msg");
787 WMDeleteTimerHandler(timer
);
795 if (ev
.xclient
.data
.l
[1] & (1<<1)) {
796 rect
.pos
.x
= ev
.xclient
.data
.l
[2] >> 16;
797 rect
.pos
.y
= ev
.xclient
.data
.l
[2] & 0xffff;
798 rect
.size
.width
= ev
.xclient
.data
.l
[3] >> 16;
799 rect
.size
.height
= ev
.xclient
.data
.l
[3] & 0xffff;
804 } else if ((state
>= 1 && state
<= 5)
805 && ev
.xclient
.message_type
== scr
->xdndFinishedAtom
806 && ev
.xclient
.window
== dragInfo
.destinationWindow
) {
808 wwarning("drag source received unexpected XdndFinished message from %x",
809 (unsigned)dragInfo
.destinationWindow
);
811 if (state
== 3 || state
== 4 || state
== 5) {
814 WMDeleteTimerHandler(timer
);
825 if (ostate
!= state
) {
827 XRecolorCursor(dpy
, scr
->defaultCursor
, &green
, &back
);
828 } else if (ostate
== 3) {
829 XRecolorCursor(dpy
, scr
->defaultCursor
, &black
, &back
);
836 WMDeleteTimerHandler(timer
);
838 } else if (_XErrorOccured
) {
839 /* got a timeout, send leave */
840 notifyDragLeave(scr
, &dragInfo
);
843 XUngrabPointer(dpy
, CurrentTime
);
845 SPIT("exited main loop");
847 if (_XErrorOccured
|| state
!= 6) {
851 assert(dragInfo
.destinationWindow
!= None
);
854 notifyDrop(scr
, &dragInfo
);
864 XDestroyWindow(dpy
, icon
);
869 scr
->dragSourceView
= NULL
;
871 WMDeleteSelectionHandler(view
, scr
->xdndSelectionAtom
,
872 event
->xmotion
.time
);
875 slideWindow(dpy
, icon
,
876 dragInfo
.imageLocation
.x
, dragInfo
.imageLocation
.y
,
877 atLocation
.x
, atLocation
.y
);
879 XDestroyWindow(dpy
, icon
);
880 if (view
->dragSourceProcs
->endedDragImage
!= NULL
) {
881 view
->dragSourceProcs
->endedDragImage(view
, image
,
882 dragInfo
.imageLocation
,
899 operationToAction(WMScreen
*scr
, WMDragOperationType operation
)
902 case WDOperationNone
:
905 case WDOperationCopy
:
906 return scr
->xdndActionCopy
;
908 case WDOperationMove
:
909 return scr
->xdndActionMove
;
911 case WDOperationLink
:
912 return scr
->xdndActionLink
;
915 return scr
->xdndActionAsk
;
917 case WDOperationPrivate
:
918 return scr
->xdndActionPrivate
;
926 static WMDragOperationType
927 actionToOperation(WMScreen
*scr
, Atom action
)
929 if (action
== scr
->xdndActionCopy
) {
930 return WDOperationCopy
;
932 } else if (action
== scr
->xdndActionMove
) {
933 return WDOperationMove
;
935 } else if (action
== scr
->xdndActionLink
) {
936 return WDOperationLink
;
938 } else if (action
== scr
->xdndActionAsk
) {
939 return WDOperationAsk
;
941 } else if (action
== scr
->xdndActionPrivate
) {
942 return WDOperationPrivate
;
944 } else if (action
== None
) {
946 return WDOperationCopy
;
948 char *tmp
= XGetAtomName(scr
->display
, action
);
950 wwarning("unknown XDND action %s from 0x%x", tmp
,
951 (unsigned)scr
->dragInfo
.sourceWindow
);
954 return WDOperationCopy
;
964 getTypeList(Window window
, XClientMessageEvent
*event
)
969 if (event
->data
.l
[1] & 1) { /* > 3 types */
972 types
= wmalloc(4 * sizeof(Atom
));
973 if (event
->data
.l
[2] != None
)
974 types
[i
++] = event
->data
.l
[2];
975 if (event
->data
.l
[3] != None
)
976 types
[i
++] = event
->data
.l
[3];
977 if (event
->data
.l
[4] != None
)
978 types
[i
++] = event
->data
.l
[4];
983 wwarning("received invalid drag & drop type list");
992 #define DISPATCH(view, func, info) (view)->dragDestinationProcs->func(view, info)
997 receivedData(WMView
*view
, Atom selection
, Atom target
,
998 Time timestamp
, void *cdata
, WMData
*data
)
1000 WMScreen
*scr
= W_VIEW_SCREEN(view
);
1001 WMDraggingInfo
*info
= (WMDraggingInfo
*)cdata
;
1004 res
= view
->dragDestinationProcs
->performDragOperation(view
, info
, data
);
1007 DISPATCH(view
, concludeDragOperation
, info
);
1010 /* send finished message */
1011 sendClientMessage(scr
->display
, info
->sourceWindow
,
1012 scr
->xdndFinishedAtom
,
1013 info
->destinationWindow
,
1016 memset(&scr
->dragInfo
, 0, sizeof(WMDraggingInfo
));
1022 W_HandleDNDClientMessage(WMView
*toplevel
, XClientMessageEvent
*event
)
1024 WMScreen
*scr
= W_VIEW_SCREEN(toplevel
);
1025 WMView
*oldView
= NULL
;
1026 WMView
*newView
= NULL
;
1027 unsigned operation
= 0;
1033 WCross
, /* leave one and enter another */
1038 int what
= WNothing
;
1039 Bool sendStatus
= False
;
1042 source
= scr
->dragInfo
.sourceWindow
;
1043 oldView
= scr
->dragInfo
.destView
;
1046 if (event
->message_type
== scr
->xdndFinishedAtom
) {
1047 WMView
*view
= scr
->dragSourceView
;
1049 if (view
->dragSourceProcs
->endedDragImage
!= NULL
) {
1050 view
->dragSourceProcs
->endedDragImage(view
,
1051 scr
->dragInfo
.image
,
1052 scr
->dragInfo
.imageLocation
,
1056 scr
->dragSourceView
= NULL
;
1058 WMDeleteSelectionHandler(view
, scr
->xdndSelectionAtom
,
1059 scr
->dragInfo
.timestamp
);
1067 if (event
->message_type
== scr
->xdndEnterAtom
) {
1072 if (scr
->dragInfo
.sourceWindow
!= None
) {
1073 puts("received Enter event in bad order");
1076 memset(&scr
->dragInfo
, 0, sizeof(WMDraggingInfo
));
1079 if ((event
->data
.l
[1] >> 24) > XDND_VERSION
) {
1080 wwarning("received drag & drop request with unsupported version %i",
1081 (event
->data
.l
[1] >> 24));
1085 scr
->dragInfo
.protocolVersion
= event
->data
.l
[1] >> 24;
1086 scr
->dragInfo
.sourceWindow
= source
= event
->data
.l
[0];
1087 scr
->dragInfo
.destinationWindow
= event
->window
;
1090 scr
->dragInfo
.image
= NULL
;
1092 XQueryPointer(scr
->display
, scr
->rootWin
, &foo
, &bar
,
1093 &scr
->dragInfo
.location
.x
, &scr
->dragInfo
.location
.y
,
1096 translateCoordinates(scr
, scr
->dragInfo
.destinationWindow
,
1097 scr
->dragInfo
.location
.x
,
1098 scr
->dragInfo
.location
.y
, &x
, &y
);
1101 newView
= findViewInToplevel(scr
->display
,
1102 scr
->dragInfo
.destinationWindow
,
1105 } else if (event
->message_type
== scr
->xdndPositionAtom
1106 && scr
->dragInfo
.sourceWindow
== event
->data
.l
[0]) {
1108 scr
->dragInfo
.location
.x
= event
->data
.l
[2] >> 16;
1109 scr
->dragInfo
.location
.y
= event
->data
.l
[2] & 0xffff;
1111 if (scr
->dragInfo
.protocolVersion
>= 1) {
1112 scr
->dragInfo
.timestamp
= event
->data
.l
[3];
1113 scr
->dragInfo
.sourceOperation
= actionToOperation(scr
,
1117 scr
->dragInfo
.timestamp
= CurrentTime
;
1118 scr
->dragInfo
.sourceOperation
= WDOperationCopy
;
1121 translateCoordinates(scr
, scr
->dragInfo
.destinationWindow
,
1122 scr
->dragInfo
.location
.x
,
1123 scr
->dragInfo
.location
.y
, &x
, &y
);
1125 newView
= findViewInToplevel(scr
->display
,
1126 scr
->dragInfo
.destinationWindow
,
1129 } else if (event
->message_type
== scr
->xdndLeaveAtom
1130 && scr
->dragInfo
.sourceWindow
== event
->data
.l
[0]) {
1132 memset(&scr
->dragInfo
, 0, sizeof(WMDraggingInfo
));
1134 } else if (event
->message_type
== scr
->xdndDropAtom
1135 && scr
->dragInfo
.sourceWindow
== event
->data
.l
[0]) {
1146 * Now map the XDND events to WINGs events.
1149 if (what
== WNothing
) {
1150 if (IS_DROPPABLE(newView
)) {
1151 if (oldView
== NULL
) { /* entered */
1153 } else if (oldView
== newView
) { /* updated */
1159 if (oldView
!= NULL
) {
1162 /* just send rejection msg */
1173 scr
->dragInfo
.destView
= newView
;
1174 operation
= DISPATCH(newView
, draggingEntered
, &scr
->dragInfo
);
1179 scr
->dragInfo
.destView
= NULL
;
1180 DISPATCH(oldView
, draggingExited
, &scr
->dragInfo
);
1182 operation
= WDOperationNone
;
1186 DISPATCH(oldView
, draggingExited
, &scr
->dragInfo
);
1187 scr
->dragInfo
.destView
= newView
;
1188 operation
= DISPATCH(newView
, draggingEntered
, &scr
->dragInfo
);
1193 operation
= DISPATCH(oldView
, draggingUpdated
, &scr
->dragInfo
);
1201 type
= DISPATCH(oldView
, prepareForDragOperation
, &scr
->dragInfo
);
1204 if (!WMRequestSelection(scr
->dragInfo
.destView
,
1205 scr
->xdndSelectionAtom
,
1206 XInternAtom(scr
->display
, type
, False
),
1207 scr
->dragInfo
.timestamp
,
1208 receivedData
, &scr
->dragInfo
)) {
1209 wwarning("could not request data for dropped data");
1211 /* send finished message */
1212 sendClientMessage(scr
->display
, source
,
1213 scr
->xdndFinishedAtom
,
1214 scr
->dragInfo
.destinationWindow
,
1218 /* send finished message */
1219 sendClientMessage(scr
->display
, source
,
1220 scr
->xdndFinishedAtom
,
1221 scr
->dragInfo
.destinationWindow
,
1236 action
= operationToAction(scr
, operation
);
1238 sendClientMessage(scr
->display
, source
,
1239 scr
->xdndStatusAtom
,
1240 scr
->dragInfo
.destinationWindow
,
1241 action
!= None
? 1 : 0, 0, 0, action
);