2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
6 * These libraries and programs are free software; you can
7 * redistribute them and/or modify them under the terms of the GNU
8 * Lesser General Public License as published by the Free Software
9 * Foundation; either version 2 of the License, or (at your option)
12 * These libraries and programs are distributed in the hope that
13 * they will be useful, but WITHOUT ANY WARRANTY; without even the
14 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU Lesser General Public License for more
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these libraries and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
23 /* $XConsortium: DndDrag.c /main/5 1996/09/27 19:00:40 drk $ */
24 /*********************************************************************
28 * Description: Implemenation of DND Drag Initator
30 *********************************************************************
34 * RESTRICTED CONFIDENTIAL INFORMATION:
36 * The information in this document is subject to special
37 * restrictions in a confidential disclosure agreement between
38 * HP, IBM, Sun, USL, SCO and Univel. Do not distribute this
39 * document outside HP, IBM, Sun, USL, SCO, or Univel without
40 * Sun's specific written approval. This documment and all copies
41 * and derivative works thereof must be returned or destroyed at
44 * Copyright 1993 Sun Microsystems, Inc. All rights reserved.
46 * (c) Copyright 1993, 1994 Hewlett-Packard Company
47 * (c) Copyright 1993, 1994 International Business Machines Corp.
48 * (c) Copyright 1993, 1994 Sun Microsystems, Inc.
49 * (c) Copyright 1993, 1994 Novell, Inc.
57 #include <X11/Intrinsic.h>
58 #include <Xm/AtomMgr.h>
59 #include <Xm/DragDrop.h>
61 #include <Xm/DragCP.h>
62 #include <Xm/DragOverSP.h>
66 #include "DtSvcLock.h"
69 * Drag Initiator Callbacks
71 static Boolean dndConvertProc(Widget, Atom*, Atom*, Atom*, XtPointer *,
72 unsigned long*, int*);
73 static void dndAppConvert(Widget, int, XEvent*, DtDragInfo*);
74 static void dndDropStartCallback(Widget, XtPointer, XtPointer);
75 static void dndDropFinishCallback(Widget, XtPointer, XtPointer);
76 static void dndDragDropFinishCallback(Widget, XtPointer, XtPointer);
77 static void dndTopLevelEnterCallback(Widget, XtPointer, XtPointer);
78 static void dndTopLevelLeaveCallback(Widget, XtPointer, XtPointer);
80 extern int _DtDndCountVarArgs(va_list vaList);
81 extern void _DtDndArgListFromVarArgs(va_list vaList,
83 ArgList *argListReturn,
84 Cardinal *argCountReturn);
85 extern void _XmDragOverChange(Widget w,
86 unsigned char dropSiteStatus);
89 * Drag Initiator Resources
92 XtCallbackList dropOnRootCallback;
97 #define Offset(field) XtOffsetOf(DragSettings, field)
99 static XtResource dragResources[] = {
100 { DtNdropOnRootCallback, DtCDropOnRootCallback,
101 XtRCallback, sizeof(XtCallbackList), Offset(dropOnRootCallback),
102 XtRImmediate, (XtPointer)NULL},
103 { DtNsourceIcon, DtCSourceIcon,
104 XtRWidget, sizeof(Widget), Offset(sourceIcon),
105 XtRImmediate, (XtPointer)NULL },
106 { DtNbufferIsText, DtCBufferIsText,
107 XtRBoolean, sizeof(Boolean), Offset(bufferIsText),
108 XtRImmediate, (XtPointer)False },
116 * Drag Start - varargs version
121 Widget dragInitiator,
123 DtDndProtocol protocol,
125 unsigned char operations,
126 XtCallbackList dragConvertCallback,
127 XtCallbackList dragFinishCallback,
134 _DtSvcWidgetToAppContext(dragInitiator);
138 va_start(vaList, dragFinishCallback);
139 argCount = _DtDndCountVarArgs(vaList);
142 va_start(vaList, dragFinishCallback);
143 _DtDndArgListFromVarArgs(vaList, argCount, &argList, &argCount);
146 dragContext = DtDndDragStart(dragInitiator, event, protocol,
147 numItems, operations,
148 dragConvertCallback, dragFinishCallback,
151 XtFree((char *)argList);
153 _DtSvcAppUnlock(app);
160 * Drag Start - arglist version
165 Widget dragInitiator,
167 DtDndProtocol protocol,
169 unsigned char operations,
170 XtCallbackList dragConvertCallback,
171 XtCallbackList dragFinishCallback,
175 XtCallbackRec dragDropFinishCbRec[] = { {dndDragDropFinishCallback,
176 NULL}, {NULL, NULL} };
177 XtCallbackRec topLevelEnterCbRec[] = { {dndTopLevelEnterCallback,
178 NULL}, {NULL, NULL} };
179 XtCallbackRec topLevelLeaveCbRec[] = { {dndTopLevelLeaveCallback,
180 NULL}, {NULL, NULL} };
181 XtCallbackRec dropStartCbRec[] = { {dndDropStartCallback,
182 NULL}, {NULL, NULL} };
183 XtCallbackRec dropFinishCbRec[] = { {dndDropFinishCallback,
184 NULL}, {NULL, NULL} };
185 Display * display = XtDisplayOfObject(dragInitiator);
186 Screen * screen = XtScreenOfObject(dragInitiator);
187 Window rootWindow = RootWindowOfScreen(screen);
188 DtDragInfo * dtDragInfo;
189 DragSettings settings;
190 DtDndDragSource sourceType;
191 DtDndTransfer * transfer;
193 int ii, nn, savedEventType;
194 Atom * exportTargets;
195 Cardinal numExportTargets;
196 _DtSvcWidgetToAppContext(dragInitiator);
200 * Reject the drag if noop or multiple protocols specified
204 case DtDND_BUFFER_TRANSFER:
205 case DtDND_FILENAME_TRANSFER:
206 case DtDND_TEXT_TRANSFER:
208 case DtDND_NOOP_TRANSFER:
210 _DtSvcAppUnlock(app);
215 * Parse resources into dragResources
218 XtGetSubresources(dragInitiator, &settings,
219 (String)NULL, (String)NULL,
220 dragResources, XtNumber(dragResources),
224 * Initialize DragInfo
227 dtDragInfo = (DtDragInfo *) XtMalloc(sizeof(DtDragInfo));
229 dtDragInfo->dragInitiator = dragInitiator;
230 dtDragInfo->dragContext = NULL;
231 dtDragInfo->protocol = protocol;
232 dtDragInfo->numItems = numItems;
233 dtDragInfo->operations = operations;
234 dtDragInfo->sourceIcon = settings.sourceIcon;
235 dtDragInfo->bufferIsText = settings.bufferIsText;
236 dtDragInfo->dragData = NULL;
237 dtDragInfo->inRoot = False;
238 dtDragInfo->status = DtDND_SUCCESS;
239 dtDragInfo->clientData = NULL;
240 dtDragInfo->backdropWindow
241 = DtWsmGetCurrentBackdropWindow(display, rootWindow);
243 dtDragInfo->dragConvertCallback
244 = _DtDndCopyCallbackList(dragConvertCallback);
245 dtDragInfo->dragFinishCallback
246 = _DtDndCopyCallbackList(dragFinishCallback);
247 dtDragInfo->dropOnRootCallback
248 = _DtDndCopyCallbackList(settings.dropOnRootCallback);
250 dtDragInfo->dragData = (DtDndContext *)XtCalloc(1,sizeof(DtDndContext));
251 dtDragInfo->dragData->protocol = dtDragInfo->protocol;
252 dtDragInfo->dragData->numItems = 0;
255 * Get data transfer method
256 * Use the transfer targets as export targets
259 dtDragInfo->transfer = _DtDndCreateExportTransfer(dtDragInfo);
261 exportTargets = dtDragInfo->transfer->targets;
262 numExportTargets = dtDragInfo->transfer->numTargets;
265 printf("DtDndDragStart: drag from widget 0x%p\n", dragInitiator);
266 _DtDndPrintTransfers(display,dtDragInfo->transfer,1);
274 sourceType = DtDND_DRAG_SOURCE_MULTIPLE;
276 sourceType = dtDragInfo->transfer->methods->sourceType;
279 _DtDndSelectDragSource(dragInitiator, sourceType,
280 dtDragInfo->sourceIcon);
283 * Construct argument list
286 #define NUM_DRAG_ARGS 30
287 args = (Arg *) XtMalloc(sizeof(Arg) * (NUM_DRAG_ARGS + argCount));
291 * Copy in passed arguments
295 for (ii = 0; ii < argCount; ii++) {
296 XtSetArg(args[nn], argList[ii].name, argList[ii].value); nn++;
300 * Set basic drag start arguments
303 XtSetArg(args[nn], XmNexportTargets, exportTargets);
305 XtSetArg(args[nn], XmNnumExportTargets, numExportTargets);
307 XtSetArg(args[nn], XmNdragOperations, operations);
309 XtSetArg(args[nn], XmNblendModel, XmBLEND_ALL);
311 XtSetArg(args[nn], XmNcursorBackground, WhitePixelOfScreen(screen));
313 XtSetArg(args[nn], XmNcursorForeground, BlackPixelOfScreen(screen));
315 XtSetArg(args[nn], XmNclientData, dtDragInfo);
318 if (dtDragInfo->sourceIcon != NULL) {
319 XtSetArg(args[nn],XmNsourcePixmapIcon, dtDragInfo->sourceIcon);
321 XtSetArg(args[nn],XmNsourceCursorIcon, dtDragInfo->sourceIcon);
326 * Set up DnD callbacks for Motif
329 XtSetArg(args[nn], XmNconvertProc, dndConvertProc);
332 dragDropFinishCbRec[0].closure = (XtPointer) dtDragInfo;
333 dropFinishCbRec[0].closure = (XtPointer) dtDragInfo;
334 dtDragInfo->dragDropFinishCallback
335 = _DtDndCopyCallbackList(dragDropFinishCbRec);
336 dtDragInfo->dropFinishCallback
337 = _DtDndCopyCallbackList(dropFinishCbRec);
339 XtSetArg(args[nn], XmNdragDropFinishCallback, dtDragInfo->dragDropFinishCallback);
341 XtSetArg(args[nn], XmNdropFinishCallback, dtDragInfo->dropFinishCallback);
345 * Only use top-level-enter/leave callbacks if also doing drop-on-root
348 if (dtDragInfo->dropOnRootCallback != NULL) {
350 topLevelEnterCbRec[0].closure = (XtPointer) dtDragInfo;
351 topLevelLeaveCbRec[0].closure = (XtPointer) dtDragInfo;
352 dropStartCbRec[0].closure = (XtPointer) dtDragInfo;
353 dtDragInfo->topLevelEnterCallback
354 = _DtDndCopyCallbackList(topLevelEnterCbRec);
355 dtDragInfo->topLevelLeaveCallback
356 = _DtDndCopyCallbackList(topLevelLeaveCbRec);
357 dtDragInfo->dropStartCallback
358 = _DtDndCopyCallbackList(dropStartCbRec);
360 XtSetArg(args[nn], XmNtopLevelEnterCallback, dtDragInfo->topLevelEnterCallback);
362 XtSetArg(args[nn], XmNtopLevelLeaveCallback, dtDragInfo->topLevelLeaveCallback);
364 XtSetArg(args[nn], XmNdropStartCallback, dtDragInfo->dropStartCallback);
369 * Fake a button press. This is necessary because Motif requires
370 * a drag to start on a button press. We need to be able to start
371 * a drag on a mouse motion event when Bselect is held down. Since
372 * the motion event has the fields necessary for Motif this works.
375 savedEventType = event->type;
377 if (event->type == MotionNotify) {
378 event->type = ButtonPress;
385 dtDragInfo->dragContext = XmDragStart(dragInitiator, event, args, nn);
387 XtFree((char *)args);
389 event->type = savedEventType;
391 _DtSvcAppUnlock(app);
392 return (dtDragInfo->dragContext);
395 /*********************************************************************
397 * Drag Initiator Callbacks
399 *********************************************************************/
402 * dndDropStartCallback
407 dndDropStartCallback(
409 XtPointer clientData,
412 DtDragInfo *dtDragInfo = (DtDragInfo *) clientData;
413 DtDndContext *dragData;
414 XmDragContext xmDragContext = (XmDragContext)dtDragInfo->dragContext;
415 XmDropStartCallbackStruct *xmDropInfo = (XmDropStartCallback) callData;
416 DtDndTransferCallbackStruct dropCallData;
417 int posOffsetX, posOffsetY;
420 * If the user has cancelled the drop, or the drop isn't on the
421 * root, or there are no dropOnRoot or convert callbacks
422 * then reject the drop.
425 if (xmDragContext->drag.dragCompletionStatus == XmDROP_CANCEL ||
426 dtDragInfo->inRoot == False ||
427 dtDragInfo->dropOnRootCallback == NULL ||
428 dtDragInfo->dragConvertCallback == NULL ) {
430 xmDropInfo->dropSiteStatus = XmINVALID_DROP_SITE;
431 xmDropInfo->dropAction = XmDROP_CANCEL;
437 * The following is to handle the dropOnRoot situation.
438 * We handle both the convert and transfer sides of the
439 * transaction here. First we get the application drag data
440 * and then we call the application dropOnRoot callback.
444 * Initialize protocol specific dragData
447 dtDragInfo->dragData->numItems = dtDragInfo->numItems;
449 (*dtDragInfo->transfer->methods->convertInit)(dtDragInfo);
452 * Invoke the application convert callback
455 dndAppConvert(dragContext, DtCR_DND_CONVERT_DATA,
456 xmDropInfo->event, dtDragInfo);
458 if (dtDragInfo->status == DtDND_FAILURE) {
463 * Setup dropOnRootcall data and invoke the dropOnroot callback
466 _DtDndGetIconOffset(dtDragInfo->dragContext,
467 dtDragInfo->transfer->methods->sourceType,
468 &posOffsetX, &posOffsetY);
470 dropCallData.reason = DtCR_DND_ROOT_TRANSFER;
471 dropCallData.event = xmDropInfo->event;
472 dropCallData.x = xmDropInfo->x + posOffsetX;
473 dropCallData.y = xmDropInfo->y + posOffsetY;
474 dropCallData.operation = xmDropInfo->operation;
475 dropCallData.dropData = dtDragInfo->dragData;
476 dropCallData.completeMove = False;
477 dropCallData.status = DtDND_SUCCESS;
479 _DtDndCallCallbackList(dragContext, dtDragInfo->dropOnRootCallback,
480 (XtPointer)&dropCallData);
483 * Tell Motif that the root is a valid drop site
486 xmDropInfo->dropSiteStatus = XmVALID_DROP_SITE;
487 xmDropInfo->dropAction = XmDROP;
501 XtPointer *returnValue,
502 unsigned long *returnLength,
505 Atom realSelectionAtom; /* Motif hides the selection atom */
506 DtDragInfo *dtDragInfo = NULL;
507 XSelectionRequestEvent *selectionRequestEvent;
512 Display *display = XtDisplayOfObject(dragContext);
513 char *atomname = XGetAtomName(display,*target);
514 printf("dndConvertProc: target = %s\n",(atomname ? atomname : "Null"));
515 if (atomname) XFree(atomname);
522 XtVaGetValues(dragContext, XmNclientData, &dtDragInfo, NULL);
524 if (dtDragInfo == NULL || dtDragInfo->status == DtDND_FAILURE) {
529 * Get selection request event
532 XtVaGetValues(dragContext, XmNiccHandle, &realSelectionAtom, NULL);
533 selectionRequestEvent = XtGetSelectionRequest(dragContext,
534 realSelectionAtom, NULL); /* REMIND: NULL for atomic transfer */
537 * Get the application drag data if necessary
540 if (dtDragInfo->dragData->numItems == 0) {
542 dtDragInfo->dragData->numItems = dtDragInfo->numItems;
544 (*dtDragInfo->transfer->methods->convertInit)(dtDragInfo);
546 dndAppConvert(dragContext, DtCR_DND_CONVERT_DATA,
547 (XEvent *)selectionRequestEvent, dtDragInfo);
549 if (dtDragInfo->status == DtDND_FAILURE) {
555 * Handle transfer protocol independent target conversions
558 if (*target == XA_TARGETS) {
560 * TARGETS Construct a list of targets consisting of those
561 * the dnd library supports plus those supported by
562 * the drag initiator.
564 int ii, LIBRARY_TARGETS = 6;
567 Cardinal numAvailTargets;
568 Cardinal numAllTargets;
570 (*dtDragInfo->transfer->methods->getAvailTargets)(dtDragInfo,
571 &availTargets, &numAvailTargets);
573 numAllTargets = numAvailTargets + LIBRARY_TARGETS;
574 allTargets = (Atom *)XtMalloc(sizeof(Atom) * numAllTargets);
576 for (ii = 0; ii < numAvailTargets; ii++) {
577 allTargets[ii] = availTargets[ii];
580 XtFree((char *)availTargets);
582 ii = numAvailTargets;
584 allTargets[ii++] = XA_TARGETS;
585 allTargets[ii++] = XA_TIMESTAMP;
586 allTargets[ii++] = XA_MULTIPLE;
587 allTargets[ii++] = XA_HOST_NAME;
588 allTargets[ii++] = XA_SUN_FILE_HOST_NAME;
589 allTargets[ii++] = XA_DELETE;
591 *returnType = XA_ATOM;
593 *returnValue = (XtPointer)allTargets;
594 *returnLength = numAllTargets * sizeof(Atom)/4;
598 } else if (*target == XA_TIMESTAMP || *target == XA_MULTIPLE) {
600 * TIMESTAMP and MULTIPLE are handled by the Intrinsics
604 } else if (*target == XA_HOST_NAME ||
605 *target == XA_SUN_FILE_HOST_NAME) {
607 * HOST_NAME, _SUN_FILE_HOST_NAME The name of this host
609 *returnType = XA_STRING;
610 *returnValue = (XtPointer)XtNewString(_DtDndGetHostName());
611 *returnLength = strlen((char *)*returnValue) + 1;
616 } else if (*target == XA_DELETE) {
618 * DELETE Set up convert callback data to specify
619 * deletion and invoke the application-defined
620 * convertCallback() to perform the delete.
623 *returnType = XA_NULL;
625 *returnValue = (XtPointer) NULL;
628 dndAppConvert(dragContext, DtCR_DND_CONVERT_DELETE,
629 (XEvent *)selectionRequestEvent, dtDragInfo);
633 } else if (*target == XA_SUN_ENUM_COUNT) {
635 * _SUN_ENUMERATION_COUNT The number of items available
637 int *count = XtNew(int);
639 if (dtDragInfo->dragData->numItems == 1) {
643 dtDragInfo->status = DtDND_FAILURE;
646 *returnType = XA_INTEGER;
647 *returnValue = (XtPointer)count;
654 * Invoke protocol specific convert method
656 status = (*dtDragInfo->transfer->methods->convert)(
657 dragContext, dtDragInfo,
659 returnType, returnValue,
660 returnLength, returnFormat,
661 selectionRequestEvent);
670 * Call the application convert callback
677 DtDragInfo * dtDragInfo)
679 DtDndConvertCallbackStruct convertCallData;
681 convertCallData.reason = reason;
682 convertCallData.event = event;
683 convertCallData.dragData = dtDragInfo->dragData;
684 convertCallData.status = DtDND_SUCCESS;
686 _DtDndCallCallbackList(dragContext, dtDragInfo->dragConvertCallback,
687 (XtPointer)&convertCallData);
689 dtDragInfo->status = convertCallData.status;
691 if (reason == DtCR_DND_CONVERT_DATA &&
692 dtDragInfo->dragData->numItems <= 0) {
693 dtDragInfo->status = DtDND_FAILURE;
699 * dndDropFinishCallback
701 * Handle drop-on-root case
704 dndDropFinishCallback(
706 XtPointer clientData,
709 DtDragInfo *dtDragInfo = (DtDragInfo *) clientData;
710 XmDropFinishCallbackStruct *xmDropFinishCallData =
711 (XmDropFinishCallbackStruct *) callData;
713 if (dtDragInfo->dropOnRootCallback != NULL &&
714 dtDragInfo->inRoot &&
715 xmDropFinishCallData->dropSiteStatus == XmVALID_DROP_SITE) {
717 xmDropFinishCallData->completionStatus = XmDROP_SUCCESS;
719 XtVaSetValues(dtDragInfo->dragContext,
720 XmNblendModel, XmBLEND_NONE, NULL);
725 * dndDragDropFinishCallback
727 * Call the application dragFinishCallback
730 dndDragDropFinishCallback(
732 XtPointer clientData,
735 XmDragDropFinishCallbackStruct *xmDndFinishInfo =
736 (XmDragDropFinishCallbackStruct *)callData;
737 DtDragInfo *dtDragInfo = (DtDragInfo *)clientData;
738 DtDndDragFinishCallbackStruct dragFinishCallData;
741 * Invoke application dragFinishCallback
744 dragFinishCallData.reason = DtCR_DND_DRAG_FINISH;
745 dragFinishCallData.event = xmDndFinishInfo->event;
746 dragFinishCallData.sourceIcon = dtDragInfo->sourceIcon;
747 dragFinishCallData.dragData = dtDragInfo->dragData;
749 _DtDndCallCallbackList(dragContext, dtDragInfo->dragFinishCallback,
750 (XtPointer)&dragFinishCallData);
753 * Restore motif default drag cursors
756 _DtDndSelectDragSource(dragContext, DtDND_DRAG_SOURCE_DEFAULT, NULL);
759 * Invoke protocol specific convertFinish
762 (*dtDragInfo->transfer->methods->convertFinish)(dtDragInfo);
765 * Free data structures allocated during the drag
768 XtFree((char *)dtDragInfo->transfer->targets);
769 XtFree((char *)dtDragInfo->transfer);
770 XtFree((char *)dtDragInfo->dragConvertCallback);
771 XtFree((char *)dtDragInfo->dragFinishCallback);
772 XtFree((char *)dtDragInfo->dragDropFinishCallback);
773 XtFree((char *)dtDragInfo->dropFinishCallback);
774 if (dtDragInfo->dropOnRootCallback != NULL) {
775 XtFree((char *)dtDragInfo->topLevelEnterCallback);
776 XtFree((char *)dtDragInfo->topLevelLeaveCallback);
777 XtFree((char *)dtDragInfo->dropStartCallback);
779 XtFree((char *)dtDragInfo->dropOnRootCallback);
780 XtFree((char *)dtDragInfo->dragData);
781 XtFree((char *)dtDragInfo);
785 * dndTopLevelEnterCallback -- Support for drop-on-root callback.
786 * When a drop-on-root callback has been set, determines if
787 * the drag has entered the root window (or equivalents)
788 * and sneakily changes Motif's idea that the root is an
789 * invalid drop site to think that it's really a valid one.
790 * Also updates dtDragInfo.inRoot as needed.
793 dndTopLevelEnterCallback(
795 XtPointer clientData,
798 XmTopLevelEnterCallbackStruct *xmEnterInfo =
799 (XmTopLevelEnterCallbackStruct *) callData;
800 DtDragInfo *dtDragInfo = (DtDragInfo *) clientData;
801 XmDragContext xmDragContext = (XmDragContext) dragContext;
802 XmDragOverShellWidget dragOverShell = xmDragContext->drag.curDragOver;
805 if (xmEnterInfo->window == RootWindowOfScreen(xmEnterInfo->screen) ||
806 dtDragInfo->backdropWindow == xmEnterInfo->window ) {
808 dragOverShell->drag.cursorState = XmVALID_DROP_SITE;
809 _XmDragOverChange((Widget)dragOverShell,
810 dragOverShell->drag.cursorState);
812 dtDragInfo->inRoot = True;
815 dtDragInfo->inRoot = False;
820 * dndTopLevelLeaveCallback -- Support for drop-on-root callback.
821 * When a drop-on-root callback has been set, determines if
822 * the drag is exiting the root window and restores Motif's
823 * internal state back to thinking that the root window is
824 * an invalid drop site. We don't update dtDragInfo->inRoot
825 * here since the top-level-leave callback is called before
826 * the drop callback which needs to know if we're in the root
830 dndTopLevelLeaveCallback(
832 XtPointer clientData,
835 XmTopLevelLeaveCallbackStruct *xmLeaveInfo =
836 (XmTopLevelLeaveCallbackStruct *) callData;
837 DtDragInfo *dtDragInfo = (DtDragInfo *) clientData;
838 XmDragContext xmDragContext = (XmDragContext) dragContext;
839 XmDragOverShellWidget dragOverShell = xmDragContext->drag.curDragOver;
842 if (xmLeaveInfo->window == RootWindowOfScreen(xmLeaveInfo->screen) ||
843 dtDragInfo->backdropWindow == xmLeaveInfo->window ) {
845 dragOverShell->drag.cursorState = XmINVALID_DROP_SITE;
847 _XmDragOverChange((Widget)dragOverShell,
848 dragOverShell->drag.cursorState);