1 /*
2 * Motif
3 *
4 * Copyright (c) 1987-2012, The Open Group. All rights reserved.
5 *
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)
10 * any later version.
11 *
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
16 * details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these librararies and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
22 */
23 #ifdef REV_INFO
24 #ifndef lint
25 static char rcsid[] = "$TOG: DragC.c /main/29 1997/10/07 12:19:52 cshi $"
26 #endif
27 #endif
28
29 #ifdef HAVE_CONFIG_H
30 #include <config.h>
31 #endif
32
33
34 #ifndef DEFAULT_WM_TIMEOUT
35 #define DEFAULT_WM_TIMEOUT 5000
36 #endif
37
38 #include <X11/Xatom.h>
39 #include <X11/cursorfont.h>
40 #include <Xm/AtomMgr.h>
41 #include <Xm/DisplayP.h>
42 #include <Xm/DragOverSP.h>
43 #include <Xm/GadgetP.h>
44 #include <Xm/ManagerP.h>
45 #include <Xm/PrimitiveP.h>
46 #include <Xm/TransltnsP.h>
47 #include <Xm/VendorSP.h>
48 #include "XmI.h"
49 #include "DisplayI.h"
50 #include "DragBSI.h"
51 #include "DragCI.h"
52 #include "DragICCI.h"
53 #include "DragOverSI.h"
54 #include "MessagesI.h"
55 #include "TraversalI.h"
56 #include "VendorSI.h"
57
58 #include <stdio.h>
59 #ifndef X_NOT_STDC_ENV
60 #include <stdlib.h>
61 #endif
62
63 /* force the multi screen support on */
64 #define MULTI_SCREEN_DONE
65
66 #ifdef DEBUG
67 #define Warning(str) XmeWarning(NULL, str)
68 #else
69 #define Warning(str) /*EMPTY*/
70 #endif
71
72 #define BIGSIZE ((Dimension)32767)
73
74 #define MESSAGE1 _XmMMsgDragC_0001
75 #define MESSAGE2 _XmMMsgDragC_0002
76 #define MESSAGE3 _XmMMsgDragC_0003
77 #define MESSAGE4 _XmMMsgDragC_0004
78 #define MESSAGE5 _XmMMsgDragC_0005
79 #define MESSAGE6 _XmMMsgDragC_0006
80
81 typedef struct _MotionEntryRec{
82 int type;
83 Time time;
84 Window window;
85 Window subwindow;
86 Position x, y;
87 unsigned int state;
88 } MotionEntryRec, *MotionEntry;
89
90 #define STACKMOTIONBUFFERSIZE 120
91
92 typedef struct _MotionBufferRec{
93 XmDragReceiverInfo currReceiverInfo;
94 Cardinal count;
95 MotionEntryRec entries[STACKMOTIONBUFFERSIZE];
96 } MotionBufferRec, *MotionBuffer;
97
98 #define MOTIONFILTER 16
99
100 /******** Static Function Declarations ********/
101
102 static void GetRefForeground(
103 Widget widget,
104 int offset,
105 XrmValue *value) ;
106 static void CopyRefForeground(
107 Widget widget,
108 int offset,
109 XrmValue *value) ;
110 static void GetRefBackground(
111 Widget widget,
112 int offset,
113 XrmValue *value) ;
114 static void DragContextInitialize(
115 Widget req,
116 Widget new_w,
117 ArgList args,
118 Cardinal *numArgs) ;
119 static Boolean DragContextSetValues(
120 Widget old,
121 Widget ref,
122 Widget new_w,
123 Arg *args,
124 Cardinal *numArgs) ;
125 static void DragContextDestroy(
126 Widget w) ;
127 static void DragContextClassInitialize( void ) ;
128 static void DragContextClassPartInitialize( WidgetClass ) ;
129 static Window GetClientWindow(
130 Display *dpy,
131 Window win,
132 Atom atom) ;
133 static void ValidateDragOver(
134 XmDragContext dc,
135 unsigned char oldStyle,
136 unsigned char newStyle) ;
137 static XmDragReceiverInfo FindReceiverInfo(
138 XmDragContext dc,
139 Window win) ;
140 static void GetDestinationInfo(
141 XmDragContext dc,
142 Window root,
143 Window win) ;
144 static void GetScreenInfo(
145 XmDragContext dc) ;
146 static void SendDragMessage(
147 XmDragContext dc,
148 Window destination,
149 unsigned char messageType) ;
150 static void GenerateClientCallback(
151 XmDragContext dc,
152 unsigned char reason) ;
153 static void DropLoseIncrSelection(
154 Widget w,
155 Atom *selection,
156 XtPointer clientData) ;
157 static void DropLoseSelection(
158 Widget w,
159 Atom *selection) ;
160 static void DragDropFinish(
161 XmDragContext dc) ;
162 static Boolean DropConvertIncrCallback(
163 Widget w,
164 Atom *selection,
165 Atom *target,
166 Atom *typeRtn,
167 XtPointer *valueRtn,
168 unsigned long *lengthRtn,
169 int *formatRtn,
170 unsigned long *maxLengthRtn,
171 XtPointer clientData,
172 XtRequestId *requestID) ;
173 static Boolean DropConvertCallback(
174 Widget w,
175 Atom *selection,
176 Atom *target,
177 Atom *typeRtn,
178 XtPointer *valueRtn,
179 unsigned long *lengthRtn,
180 int *formatRtn) ;
181 static void DragStartProto(
182 XmDragContext dc) ;
183 static void NewScreen(
184 XmDragContext dc,
185 Window newRoot) ;
186 static void LocalNotifyHandler(
187 Widget w,
188 XtPointer client,
189 XtPointer call) ;
190 static void ExternalNotifyHandler(
191 Widget w,
192 XtPointer client,
193 XtPointer call) ;
194 static void InitiatorMsgHandler(
195 Widget w,
196 XtPointer clientData,
197 XEvent *event,
198 Boolean *dontSwallow) ;
199 static void SiteEnteredWithLocalSource(
200 Widget w,
201 XtPointer client,
202 XtPointer call) ;
203 static void SiteLeftWithLocalSource(
204 Widget w,
205 XtPointer client,
206 XtPointer call) ;
207 static void OperationChanged(
208 Widget w,
209 XtPointer client,
210 XtPointer call) ;
211 static void SiteMotionWithLocalSource(
212 Widget w,
213 XtPointer client,
214 XtPointer call) ;
215 static void DropStartConfirmed(
216 Widget w,
217 XtPointer client,
218 XtPointer call) ;
219 static Widget GetShell(
220 Widget w) ;
221 static void InitDropSiteManager(
222 XmDragContext dc) ;
223 static void TopWindowsReceived(
224 Widget w,
225 XtPointer client_data,
226 Atom *selection,
227 Atom *type,
228 XtPointer value,
229 unsigned long *length,
230 int *format) ;
231 static void DragStart(
232 XmDragContext dc,
233 Widget src,
234 XEvent *event) ;
235 static void DragStartWithTracking(
236 XmDragContext dc) ;
237 static void UpdateMotionBuffer(
238 XmDragContext dc,
239 MotionBuffer mb,
240 XEvent *event) ;
241 static void DragMotionProto(
242 XmDragContext dc,
243 Window root,
244 Window subWindow) ;
245 static void ProcessMotionBuffer(
246 XmDragContext dc,
247 MotionBuffer mb) ;
248 static void DragMotion(
249 Widget w,
250 XEvent *event,
251 String *params,
252 Cardinal *numParams) ;
253 static void DragKey(
254 Widget w,
255 XEvent *event,
256 String *params,
257 Cardinal *numParams) ;
258 static void DropStartTimeout(
259 XtPointer clientData,
260 XtIntervalId *id) ;
261 static void DropFinishTimeout(
262 XtPointer clientData,
263 XtIntervalId *id) ;
264 static void FinishAction(
265 XmDragContext dc,
266 XEvent *ev) ;
267 static void CheckModifiers(
268 XmDragContext dc,
269 unsigned int state) ;
270 static void IgnoreButtons(
271 Widget w,
272 XEvent *event,
273 String *params,
274 Cardinal *numParams) ;
275 static void CancelDrag(
276 Widget w,
277 XEvent *event,
278 String *params,
279 Cardinal *numParams) ;
280 static void HelpDrag(
281 Widget w,
282 XEvent *event,
283 String *params,
284 Cardinal *numParams) ;
285 static void FinishDrag(
286 Widget w,
287 XEvent *event,
288 String *params,
289 Cardinal *numParams) ;
290 static void InitiatorMainLoop(
291 XtPointer clientData,
292 XtIntervalId *id) ;
293 static void DragCancel(
294 XmDragContext dc) ;
295 static void CalculateDragOperation(
296 XmDragContext dc) ;
297 static void cancelDrag(
298 Widget w,
299 XtPointer client,
300 XtPointer call) ;
301 static void noMoreShell (
302 Widget w,
303 XtPointer client,
304 XtPointer call) ;
305
306 /******** End Static Function Declarations ********/
307
308
309 static XtActionsRec dragContextActions[] =
310 {
311 {"FinishDrag" , FinishDrag },
312 {"CancelDrag" , CancelDrag },
313 {"HelpDrag" , HelpDrag },
314 {"DragMotion" , DragMotion },
315 {"DragKey" , DragKey },
316 {"IgnoreButtons" , IgnoreButtons },
317 };
318
319 static XmConst unsigned char protocolMatrix[7][6] = {
320
321 /*
322 *
323 * Rows are initiator styles, Columns are receiver styles.
324 *
325 * Receiver NO DO PP P PD D
326 * Initiator -------------------------------
327 * NO | NO | NO | NO | NO | NO | NO |
328 * DO | NO | DO | DO | DO | DO | DO |
329 * PP | NO | DO | P | P | P | D |
330 * P | NO | DO | P | P | P | DO |
331 * PD | NO | DO | D | P | D | D |
332 * D | NO | DO | D | DO | D | D |
333 * PR | NO | DO | P | P | D | D |
334 */
335
336
337 { /* Initiator == XmDRAG_NONE == 0 */
338 XmDRAG_NONE, XmDRAG_NONE, XmDRAG_NONE,
339 XmDRAG_NONE, XmDRAG_NONE, XmDRAG_NONE,
340 },
341 { /* Initiator == DROP_ONLY == 1 */
342 XmDRAG_NONE, XmDRAG_DROP_ONLY, XmDRAG_DROP_ONLY,
343 XmDRAG_DROP_ONLY, XmDRAG_DROP_ONLY, XmDRAG_DROP_ONLY,
344 },
345 { /* Initiator == PREFER_PREREG == 2 */
346 XmDRAG_NONE, XmDRAG_DROP_ONLY, XmDRAG_PREREGISTER,
347 XmDRAG_PREREGISTER, XmDRAG_PREREGISTER, XmDRAG_DYNAMIC,
348 },
349 { /* Initiator == PREREG == 3 */
350 XmDRAG_NONE, XmDRAG_DROP_ONLY, XmDRAG_PREREGISTER,
351 XmDRAG_PREREGISTER, XmDRAG_PREREGISTER, XmDRAG_DROP_ONLY,
352 },
353 { /* Initiator == PREFER_DYNAMIC == 4 */
354 XmDRAG_NONE, XmDRAG_DROP_ONLY, XmDRAG_DYNAMIC,
355 XmDRAG_PREREGISTER, XmDRAG_DYNAMIC, XmDRAG_DYNAMIC,
356 },
357 { /* Initiator == XmDRAG_DYNAMIC == 5 */
358 XmDRAG_NONE, XmDRAG_DROP_ONLY, XmDRAG_DYNAMIC,
359 XmDRAG_DROP_ONLY, XmDRAG_DYNAMIC, XmDRAG_DYNAMIC,
360 },
361 { /* Initiator == DRAG_RECEIVER == 6 */
362 XmDRAG_NONE, XmDRAG_DROP_ONLY, XmDRAG_PREREGISTER,
363 XmDRAG_PREREGISTER, XmDRAG_DYNAMIC, XmDRAG_DYNAMIC,
364 },
365 };
366
367 /***************************************************************************
368 *
369 * Default values for resource lists
370 *
371 ***************************************************************************/
372
373 #define Offset(x) (XtOffsetOf(XmDragContextRec, x))
374
375 static XtResource dragContextResources[] =
376 {
377 {
378 XmNsourceWidget, XmCSourceWidget, XmRWidget,
379 sizeof(Widget), Offset(drag.sourceWidget),
380 XmRImmediate, (XtPointer)NULL,
381 },
382 {
383 XmNexportTargets, XmCExportTargets, XmRAtomList,
384 sizeof(Atom *), Offset(drag.exportTargets),
385 XmRImmediate, (XtPointer)NULL,
386 },
387 {
388 XmNnumExportTargets, XmCNumExportTargets, XmRInt,
389 sizeof(Cardinal), Offset(drag.numExportTargets),
390 XmRImmediate, (XtPointer)0,
391 },
392 {
393 XmNconvertProc, XmCConvertProc, XmRFunction,
394 sizeof(XmConvertSelectionRec), Offset(drag.convertProc),
395 XmRImmediate, (XtPointer)NULL,
396 },
397 {
398 XmNclientData, XmCClientData, XmRPointer,
399 sizeof(XtPointer), Offset(drag.clientData),
400 XmRImmediate, (XtPointer)NULL,
401 },
402 {
403 XmNincremental, XmCIncremental, XmRBoolean,
404 sizeof(Boolean), Offset(drag.incremental),
405 XmRImmediate, (XtPointer)NULL,
406 },
407 {
408 XmNdragOperations, XmCDragOperations, XmRUnsignedChar,
409 sizeof(unsigned char), Offset(drag.dragOperations),
410 XmRImmediate, (XtPointer)(XmDROP_COPY | XmDROP_MOVE),
411 },
412 {
413 XmNsourceCursorIcon, XmCSourceCursorIcon,
414 XmRWidget, sizeof(Widget),
415 Offset(drag.sourceCursorIcon), XmRImmediate, (XtPointer)NULL,
416 },
417 {
418 XmNsourcePixmapIcon, XmCSourcePixmapIcon,
419 XmRWidget, sizeof(Widget),
420 Offset(drag.sourcePixmapIcon), XmRImmediate, (XtPointer)NULL,
421 },
422 {
423 XmNstateCursorIcon, XmCStateCursorIcon,
424 XmRWidget, sizeof(Widget),
425 Offset(drag.stateCursorIcon), XmRImmediate, (XtPointer)NULL,
426 },
427 {
428 XmNoperationCursorIcon, XmCOperationCursorIcon,
429 XmRWidget, sizeof(Widget),
430 Offset(drag.operationCursorIcon), XmRImmediate, (XtPointer)NULL,
431 },
432 {
433 XmNcursorBackground, XmCCursorBackground, XmRPixel,
434 sizeof(Pixel), Offset(drag.cursorBackground), XmRCallProc,
435 (XtPointer)GetRefBackground,
436 },
437 {
438 XmNcursorForeground, XmCCursorForeground, XmRPixel,
439 sizeof(Pixel), Offset(drag.cursorForeground), XmRCallProc, (XtPointer)GetRefForeground,
440 },
441 {
442 XmNvalidCursorForeground, XmCValidCursorForeground, XmRPixel,
443 sizeof(Pixel), Offset(drag.validCursorForeground), XmRCallProc, (XtPointer)CopyRefForeground,
444 },
445 {
446 XmNinvalidCursorForeground, XmCInvalidCursorForeground,
447 XmRPixel, sizeof(Pixel), Offset(drag.invalidCursorForeground),
448 XmRCallProc, (XtPointer)CopyRefForeground,
449 },
450 {
451 XmNnoneCursorForeground, XmCNoneCursorForeground, XmRPixel,
452 sizeof(Pixel), Offset(drag.noneCursorForeground),
453 XmRCallProc, (XtPointer)CopyRefForeground,
454 },
455 {
456 XmNdropSiteEnterCallback, XmCCallback, XmRCallback,
457 sizeof(XtCallbackList), Offset(drag.siteEnterCallback),
458 XmRImmediate, (XtPointer)NULL,
459 },
460 {
461 XmNdropSiteLeaveCallback, XmCCallback, XmRCallback,
462 sizeof(XtCallbackList), Offset(drag.siteLeaveCallback),
463 XmRImmediate, (XtPointer)NULL,
464 },
465 {
466 XmNtopLevelEnterCallback, XmCCallback, XmRCallback,
467 sizeof(XtCallbackList), Offset(drag.topLevelEnterCallback),
468 XmRImmediate, (XtPointer)NULL,
469 },
470 {
471 XmNdragMotionCallback, XmCCallback, XmRCallback,
472 sizeof(XtCallbackList), Offset(drag.dragMotionCallback),
473 XmRImmediate, (XtPointer)NULL,
474 },
475 {
476 XmNtopLevelLeaveCallback, XmCCallback, XmRCallback,
477 sizeof(XtCallbackList), Offset(drag.topLevelLeaveCallback),
478 XmRImmediate, (XtPointer)NULL,
479 },
480 {
481 XmNdropStartCallback, XmCCallback, XmRCallback,
482 sizeof(XtCallbackList), Offset(drag.dropStartCallback),
483 XmRImmediate, (XtPointer)NULL,
484 },
485 {
486 XmNdragDropFinishCallback, XmCCallback, XmRCallback,
487 sizeof(XtCallbackList), Offset(drag.dragDropFinishCallback),
488 XmRImmediate, (XtPointer)NULL,
489 },
490 {
491 XmNdropFinishCallback, XmCCallback, XmRCallback,
492 sizeof(XtCallbackList), Offset(drag.dropFinishCallback),
493 XmRImmediate, (XtPointer)NULL,
494 },
495 {
496 XmNoperationChangedCallback, XmCCallback, XmRCallback,
497 sizeof(XtCallbackList), Offset(drag.operationChangedCallback),
498 XmRImmediate, (XtPointer)NULL,
499 },
500 {
501 XmNblendModel, XmCBlendModel,
502 XmRBlendModel,
503 sizeof(unsigned char), Offset(drag.blendModel),
504 XmRImmediate, (XtPointer)XmBLEND_ALL,
505 },
506 {
507 XmNsourceIsExternal, XmCSourceIsExternal, XmRBoolean,
508 sizeof(Boolean), Offset(drag.sourceIsExternal),
509 XmRImmediate, (XtPointer)False,
510 },
511 {
512 XmNsourceWindow, XmCSourceWindow, XmRWindow,
513 sizeof(Window), Offset(drag.srcWindow),
514 XmRImmediate, (XtPointer)None,
515 },
516 {
517 XmNstartTime, XmCStartTime, XmRInt,
518 sizeof(Time), Offset(drag.dragStartTime),
519 XmRImmediate, (XtPointer)0,
520 },
521 {
522 XmNiccHandle, XmCICCHandle, XmRAtom,
523 sizeof(Atom), Offset(drag.iccHandle),
524 XmRImmediate, (XtPointer)None,
525 },
526 };
527
528
529
530 externaldef(xmdragcontextclassrec)
531 XmDragContextClassRec xmDragContextClassRec = {
532 {
533 (WidgetClass) &coreClassRec, /* superclass */
534 "XmDragContext", /* class_name */
535 sizeof(XmDragContextRec), /* size */
536 DragContextClassInitialize, /* Class Initializer */
537 DragContextClassPartInitialize, /* class_part_init */
538 FALSE, /* Class init'ed ? */
539 DragContextInitialize, /* initialize */
540 NULL, /* initialize_notify */
541 XtInheritRealize, /* realize */
542 dragContextActions, /* actions */
543 XtNumber(dragContextActions), /* num_actions */
544 dragContextResources, /* resources */
545 XtNumber(dragContextResources),/* resource_count */
546 NULLQUARK, /* xrm_class */
547 FALSE, /* compress_motion */
548 XtExposeNoCompress, /* compress_exposure */
549 FALSE, /* compress_enterleave */
550 FALSE, /* visible_interest */
551 DragContextDestroy, /* destroy */
552 NULL, /* resize */
553 NULL, /* expose */
554 DragContextSetValues, /* set_values */
555 NULL, /* set_values_hook */
556 NULL, /* set_values_almost */
557 NULL, /* get_values_hook */
558 NULL, /* accept_focus */
559 XtVersion, /* intrinsics version */
560 NULL, /* callback offsets */
561 _XmDragC_defaultTranslations, /* tm_table */
562 NULL, /* query_geometry */
563 NULL, /* display_accelerator */
564 NULL, /* extension */
565 },
566 { /* dragContext */
567 DragStart, /* start */
568 DragCancel, /* cancel */
569 NULL, /* extension record */
570 },
571 };
572
573 externaldef(dragContextclass) WidgetClass
574 xmDragContextClass = (WidgetClass) &xmDragContextClassRec;
575
576 /*ARGSUSED*/
577 static void
GetRefForeground(Widget widget,int offset,XrmValue * value)578 GetRefForeground(
579 Widget widget,
580 int offset,
581 XrmValue *value )
582 {
583 static Pixel pixel;
584
585 XmDragContext dc = (XmDragContext)widget;
586 Widget sw = dc->drag.sourceWidget;
587
588 pixel = BlackPixelOfScreen(XtScreen(widget));
589
590 value->addr = (XPointer)(&pixel);
591 value->size = sizeof(Pixel);
592
593 if (sw) {
594 if (XmIsGadget(sw))
595 pixel = ((XmManagerWidget)(XtParent(sw)))->manager.foreground;
596 else if (XmIsPrimitive(sw))
597 pixel = ((XmPrimitiveWidget)sw)->primitive.foreground;
598 else if (XmIsManager(sw))
599 pixel = ((XmManagerWidget)sw)->manager.foreground;
600 }
601 } /* GetRefForeground */
602
603
604 /*ARGSUSED*/
605 static void
CopyRefForeground(Widget widget,int offset,XrmValue * value)606 CopyRefForeground(
607 Widget widget,
608 int offset,
609 XrmValue *value )
610 {
611 XmDragContext dc = (XmDragContext)widget;
612
613 value->addr = (XPointer)(&dc->drag.cursorForeground);
614 value->size = sizeof(Pixel);
615 } /* CopyRefForeground */
616
617
618 /*ARGSUSED*/
619 static void
GetRefBackground(Widget widget,int offset,XrmValue * value)620 GetRefBackground(
621 Widget widget,
622 int offset,
623 XrmValue *value )
624 {
625 static Pixel pixel;
626
627 XmDragContext dc = (XmDragContext)widget;
628 Widget sw = dc->drag.sourceWidget;
629
630 pixel = WhitePixelOfScreen(XtScreen(dc));
631
632 value->addr = (XPointer)(&pixel);
633 value->size = sizeof(Pixel);
634
635 if (sw) {
636 if (XmIsGadget(sw))
637 pixel = ((XmManagerWidget)(XtParent(sw)))->core.background_pixel;
638 else
639 pixel = sw->core.background_pixel;
640 }
641 } /* GetRefBackground */
642
643
644 /*ARGSUSED*/
645 static void
DragContextInitialize(Widget req,Widget new_w,ArgList args,Cardinal * numArgs)646 DragContextInitialize(
647 Widget req,
648 Widget new_w,
649 ArgList args,
650 Cardinal *numArgs )
651 {
652 XmDragContext dc = (XmDragContext)new_w;
653
654 dc->drag.roundOffTime = 50;
655
656 dc->drag.dragFinishTime =
657 dc->drag.dropFinishTime = 0;
658
659 dc->drag.inDropSite = False;
660 dc->drag.dragTimerId = (XtIntervalId) NULL;
661 dc->drag.activeBlendModel = dc->drag.blendModel;
662 dc->drag.trackingMode = XmDRAG_TRACK_MOTION ;
663 dc->drag.curDragOver = dc->drag.origDragOver = NULL;
664 dc->drag.startX = dc->drag.startY = 0;
665
666 dc->drag.SaveEventMask = 0L;
667
668 InitDropSiteManager(dc);
669
670 if (dc->drag.exportTargets) {
671 unsigned int size;
672 size = sizeof(Atom) * dc->drag.numExportTargets;
673 dc->drag.exportTargets = (Atom *)
674 _XmAllocAndCopy(dc->drag.exportTargets, size);
675 }
676 dc->core.x =
677 dc->core.y = 0;
678 dc->core.width =
679 dc->core.height = 16;
680
681 /* pixel values in drag context refer to the source widget's colormap */
682 if (dc->drag.sourceWidget) {
683 Widget sw = dc->drag.sourceWidget;
684 dc->core.colormap = XmIsGadget(sw) ?
685 XtParent(sw)->core.colormap : sw->core.colormap;
686 }
687
688 XtRealizeWidget((Widget)dc);
689
690 dc->drag.currReceiverInfo =
691 dc->drag.receiverInfos = NULL;
692 dc->drag.numReceiverInfos =
693 dc->drag.maxReceiverInfos = 0;
694
695 dc->drag.dragDropCancelEffect = False;
696 }
697
698 /*ARGSUSED*/
699 static Boolean
DragContextSetValues(Widget old,Widget ref,Widget new_w,Arg * args,Cardinal * numArgs)700 DragContextSetValues(
701 Widget old,
702 Widget ref,
703 Widget new_w,
704 Arg *args,
705 Cardinal *numArgs )
706 {
707 XmDragContext oldDC = (XmDragContext)old;
708 XmDragContext newDC = (XmDragContext)new_w;
709 XmDragOverShellWidget dos = newDC->drag.curDragOver;
710
711 if (oldDC->drag.exportTargets != newDC->drag.exportTargets) {
712 if (oldDC->drag.exportTargets) /* should have been freed */
713 XtFree( (char *)oldDC->drag.exportTargets);
714 if (newDC->drag.exportTargets) {
715 unsigned int size;
716 size = sizeof(Atom) * newDC->drag.numExportTargets;
717 newDC->drag.exportTargets = (Atom *)
718 _XmAllocAndCopy(newDC->drag.exportTargets, size);
719 }
720 }
721 if ( oldDC->drag.operationCursorIcon != newDC->drag.operationCursorIcon ||
722 oldDC->drag.sourceCursorIcon != newDC->drag.sourceCursorIcon ||
723 oldDC->drag.sourcePixmapIcon != newDC->drag.sourcePixmapIcon ||
724 oldDC->drag.stateCursorIcon != newDC->drag.stateCursorIcon ||
725 oldDC->drag.cursorBackground != newDC->drag.cursorBackground ||
726 oldDC->drag.cursorForeground != newDC->drag.cursorForeground ||
727 oldDC->drag.noneCursorForeground != newDC->drag.noneCursorForeground ||
728 oldDC->drag.invalidCursorForeground !=
729 newDC->drag.invalidCursorForeground ||
730 oldDC->drag.validCursorForeground !=
731 newDC->drag.validCursorForeground) {
732 _XmDragOverChange((Widget)dos, dos->drag.cursorState);
733 }
734 return False;
735 }
736
737 static void
DragContextDestroy(Widget w)738 DragContextDestroy(
739 Widget w )
740 {
741 XmDragContext dc = (XmDragContext)w;
742 Cardinal i;
743
744 /* Fix CR 5556: Restore root event mask saved at DragStart time */
745 if (0 != dc->drag.SaveEventMask)
746 XSelectInput(XtDisplay(dc), dc->drag.currWmRoot, dc->drag.SaveEventMask);
747
748 if (dc->drag.exportTargets)
749 XtFree((char *)dc->drag.exportTargets);
750
751 dc->drag.exportTargets = NULL;
752
753 if (dc->drag.dragTimerId)
754 {
755 XtRemoveTimeOut(dc->drag.dragTimerId);
756 dc->drag.dragTimerId = (XtIntervalId) NULL;
757 }
758
759 if (dc->drag.receiverInfos)
760 {
761 #ifdef MULTI_SCREEN_DONE
762 if (dc->drag.trackingMode != XmDRAG_TRACK_MOTION)
763 {
764 EventMask mask;
765 XmDragReceiverInfo info;
766
767 for (i = 1; i < dc->drag.numReceiverInfos; i++)
768 {
769 info = &(dc->drag.receiverInfos[i]);
770
771 if (info->shell)
772 mask = XtBuildEventMask(info->shell);
773 else
774 mask = 0;
775
776 XSelectInput(XtDisplay(w), info->window, mask);
777 }
778 }
779 #endif /* MULTI_SCREEN_DONE */
780 XtFree((char *)dc->drag.receiverInfos);
781 }
782 }
783
784 static void
DragContextClassInitialize(void)785 DragContextClassInitialize( void )
786 {
787 /* The applications should call XtRegisterGrabAction. */
788 }
789
790 static void
DragContextClassPartInitialize(WidgetClass wc)791 DragContextClassPartInitialize( WidgetClass wc )
792 {
793 _XmFastSubclassInit (wc, XmDRAG_CONTEXT_BIT);
794 }
795
796 static Window
GetClientWindow(Display * dpy,Window win,Atom atom)797 GetClientWindow(
798 Display *dpy,
799 Window win,
800 Atom atom )
801 {
802 Window root, parent;
803 Window *children;
804 unsigned int nchildren;
805 int i;
806 Atom type = None;
807 int format;
808 unsigned long nitems, after;
809 unsigned char *data = NULL;
810 Window inf = 0;
811
812 XGetWindowProperty(dpy, win, atom, 0, 0, False, AnyPropertyType,
813 &type, &format, &nitems, &after, &data);
814 if (data)
815 XFree(data);
816
817 if (type)
818 return win;
819 else {
820 if (!XQueryTree(dpy, win, &root, &parent, &children, &nchildren) ||
821 (nchildren == 0))
822 return 0;
823 for (i = nchildren - 1; i >= 0; i--) {
824 if ((inf = GetClientWindow(dpy, children[i], atom)) != 0) {
825 XFree(children);
826 return inf;
827 }
828 }
829 XFree(children);
830 }
831 return 0;
832 }
833
834 static void
ValidateDragOver(XmDragContext dc,unsigned char oldStyle,unsigned char newStyle)835 ValidateDragOver(
836 XmDragContext dc,
837 unsigned char oldStyle,
838 unsigned char newStyle )
839 {
840 Arg args[1];
841 XmDisplay xmDisplay = (XmDisplay)XtParent(dc);
842 unsigned char initiator = XmDRAG_NONE;
843
844 initiator = xmDisplay->display.dragInitiatorProtocolStyle;
845
846 if (newStyle != oldStyle)
847 {
848 /*
849 * If we're not still waiting to hear from the window manager,
850 * and we're not running dynamic, then we can grab.
851 */
852 if ((dc->drag.trackingMode != XmDRAG_TRACK_WM_QUERY_PENDING) &&
853 (newStyle != XmDRAG_DYNAMIC) &&
854 (initiator != XmDRAG_DYNAMIC) &&
855 (initiator != XmDRAG_PREFER_DYNAMIC))
856 {
857 if (!dc->drag.serverGrabbed)
858 {
859 XGrabServer(XtDisplay(dc));
860 dc->drag.serverGrabbed = True;
861 XtSetArg(args[0], XmNdragOverMode, XmPIXMAP);
862 XtSetValues( (Widget)dc->drag.curDragOver, args, 1);
863 }
864 }
865 else
866 {
867 if (dc->drag.serverGrabbed)
868 {
869 XUngrabServer(XtDisplay(dc));
870 dc->drag.serverGrabbed = False;
871 if (xmDisplay -> display.displayHasShapeExtension)
872 XtSetArg(args[0], XmNdragOverMode, XmDRAG_WINDOW);
873 else
874 XtSetArg(args[0], XmNdragOverMode, XmCURSOR);
875 XtSetValues( (Widget)dc->drag.curDragOver, args, 1);
876 }
877 }
878 }
879 }
880
881
882 static XmDragReceiverInfo
FindReceiverInfo(XmDragContext dc,Window win)883 FindReceiverInfo(
884 XmDragContext dc,
885 Window win )
886 {
887 Cardinal i;
888 XmDragReceiverInfo info = NULL;
889
890 for (i = 0; i < dc->drag.numReceiverInfos; i++) {
891 info = &dc->drag.receiverInfos[i];
892 if ((info->frame == win) || (info->window == win))
893 break;
894 }
895 if (i < dc->drag.numReceiverInfos)
896 return info;
897 else
898 return NULL;
899 }
900
901 XmDragReceiverInfo
_XmAllocReceiverInfo(XmDragContext dc)902 _XmAllocReceiverInfo(
903 XmDragContext dc )
904 {
905 Cardinal offset = 0;
906
907 if (dc->drag.currReceiverInfo) {
908 offset = (Cardinal) (dc->drag.currReceiverInfo -
909 dc->drag.receiverInfos);
910 }
911 if (dc->drag.numReceiverInfos == dc->drag.maxReceiverInfos) {
912 dc->drag.maxReceiverInfos = dc->drag.maxReceiverInfos*2 + 2;
913 dc->drag.receiverInfos = (XmDragReceiverInfoStruct *)
914 XtRealloc((char*)dc->drag.receiverInfos,
915 dc->drag.maxReceiverInfos *
916 sizeof(XmDragReceiverInfoStruct));
917 }
918 if (offset)
919 dc->drag.currReceiverInfo = &(dc->drag.receiverInfos[offset]);
920 dc->drag.rootReceiverInfo = dc->drag.receiverInfos;
921 return &(dc->drag.receiverInfos[dc->drag.numReceiverInfos++]);
922 }
923
924 /* Find a window with WM_STATE, else return win itself, as per ICCCM */
925 /*ARGSUSED*/
926 static void
GetDestinationInfo(XmDragContext dc,Window root,Window win)927 GetDestinationInfo(
928 XmDragContext dc,
929 Window root,
930 Window win )
931 {
932 Window clientWin = win;
933 Display *dpy = XtDisplayOfObject((Widget) dc);
934 Atom WM_STATE = XInternAtom(dpy, XmSWM_STATE, True);
935 unsigned char oldStyle = dc->drag.activeProtocolStyle;
936 XmDragReceiverInfo currReceiverInfo;
937
938 dc->drag.crossingTime = dc->drag.lastChangeTime;
939
940 currReceiverInfo =
941 dc->drag.currReceiverInfo = FindReceiverInfo(dc, win);
942
943 /*
944 * check for bootstrap case
945 */
946 if ((dc->drag.trackingMode == XmDRAG_TRACK_MOTION) &&
947 (XtWindow(dc->drag.srcShell) == win) &&
948 (!currReceiverInfo ||
949 (currReceiverInfo->frame == currReceiverInfo->window))) {
950 Window currRoot = dc->drag.currWmRoot;
951 int root_x, root_y;
952 Position rel_x, rel_y;
953 /*
954 * set frame (win) to something reasonable
955 */
956 rel_x = dc->drag.startX - dc->drag.srcShell->core.x;
957 rel_y = dc->drag.startY - dc->drag.srcShell->core.y;
958
959 if (rel_x < 0) rel_x = 0;
960 if (rel_y < 0) rel_y = 0;
961
962 (void) XTranslateCoordinates(XtDisplayOfObject((Widget) dc),
963 win, currRoot,
964 rel_x, rel_y,
965 &root_x, &root_y,
966 &win);
967 if (currReceiverInfo)
968 currReceiverInfo->frame = win;
969 }
970
971 if (currReceiverInfo == NULL) {
972 if (clientWin == win) {
973 if ((clientWin = GetClientWindow(dpy, win, WM_STATE)) == 0)
974 clientWin = win;
975 }
976 currReceiverInfo =
977 dc->drag.currReceiverInfo = _XmAllocReceiverInfo(dc);
978 currReceiverInfo->frame = win;
979 currReceiverInfo->window = clientWin;
980 currReceiverInfo->shell = XtWindowToWidget(dpy, clientWin);
981 }
982
983 /*
984 * we fetch the root info in NewScreen
985 */
986 if (currReceiverInfo != dc->drag.rootReceiverInfo /* is it the root ? */) {
987 if (!currReceiverInfo->shell) {
988 if (_XmGetDragReceiverInfo(dpy,
989 currReceiverInfo->window,
990 currReceiverInfo))
991 {
992 switch (currReceiverInfo->dragProtocolStyle) {
993 case XmDRAG_PREREGISTER:
994 case XmDRAG_PREFER_PREREGISTER:
995 case XmDRAG_PREFER_DYNAMIC:
996 break;
997 case XmDRAG_DYNAMIC:
998 case XmDRAG_DROP_ONLY:
999 case XmDRAG_NONE:
1000 /* free the data returned by the icc layer */
1001 _XmFreeDragReceiverInfo(currReceiverInfo->iccInfo);
1002 break;
1003 }
1004 }
1005 } else {
1006 XmDisplay xmDisplay = (XmDisplay)XtParent(dc);
1007
1008 /*
1009 * We only have a protocol style if we have drop sites.
1010 */
1011 if (_XmDropSiteShell(dc->drag.currReceiverInfo->shell))
1012 currReceiverInfo->dragProtocolStyle =
1013 xmDisplay->display.dragReceiverProtocolStyle;
1014 else
1015 currReceiverInfo->dragProtocolStyle = XmDRAG_NONE;
1016
1017 currReceiverInfo->xOrigin = dc->drag.currReceiverInfo->shell->core.x;
1018 currReceiverInfo->yOrigin = dc->drag.currReceiverInfo->shell->core.y;
1019 currReceiverInfo->width = dc->drag.currReceiverInfo->shell->core.width;
1020 currReceiverInfo->height = dc->drag.currReceiverInfo->shell->core.height;
1021 currReceiverInfo->depth = dc->drag.currReceiverInfo->shell->core.depth;
1022 currReceiverInfo->iccInfo = NULL;
1023 }
1024 }
1025
1026 /*
1027 * If we're still waiting on the window manager, then don't mess
1028 * with the active protocol style.
1029 */
1030 if (dc->drag.trackingMode != XmDRAG_TRACK_WM_QUERY_PENDING)
1031 {
1032 dc->drag.activeProtocolStyle =
1033 _XmGetActiveProtocolStyle((Widget)dc);
1034
1035 ValidateDragOver(dc, oldStyle, dc->drag.activeProtocolStyle);
1036 }
1037 }
1038
1039
1040 static void
GetScreenInfo(XmDragContext dc)1041 GetScreenInfo(
1042 XmDragContext dc )
1043 {
1044 Display *dpy = XtDisplay(dc);
1045 Window root = RootWindowOfScreen(XtScreen(dc->drag.curDragOver));
1046 XmDragReceiverInfo rootInfo;
1047
1048 /*
1049 * the rootInfo is the first entry in the receiverInfo
1050 * array
1051 */
1052
1053 if (dc->drag.numReceiverInfos == 0) {
1054 dc->drag.rootReceiverInfo =
1055 rootInfo = _XmAllocReceiverInfo(dc);
1056 } else {
1057 dc->drag.rootReceiverInfo =
1058 rootInfo = dc->drag.receiverInfos;
1059 }
1060
1061 rootInfo->frame = None;
1062 rootInfo->window = root;
1063 rootInfo->shell = XtWindowToWidget(dpy, root);
1064 rootInfo->xOrigin = rootInfo->yOrigin = 0;
1065 rootInfo->width = XWidthOfScreen(dc->drag.currScreen);
1066 rootInfo->height = XHeightOfScreen(dc->drag.currScreen);
1067 rootInfo->depth = DefaultDepthOfScreen(dc->drag.currScreen);
1068 rootInfo->iccInfo = NULL;
1069
1070 if (_XmGetDragReceiverInfo(dpy, root, rootInfo))
1071 {
1072 switch (rootInfo->dragProtocolStyle) {
1073 case XmDRAG_PREREGISTER:
1074 case XmDRAG_PREFER_PREREGISTER:
1075 case XmDRAG_PREFER_DYNAMIC:
1076 break;
1077 case XmDRAG_DYNAMIC:
1078 case XmDRAG_DROP_ONLY:
1079 case XmDRAG_NONE:
1080 /* free the data returned by the icc layer */
1081 _XmFreeDragReceiverInfo(rootInfo->iccInfo);
1082 break;
1083 }
1084 }
1085 }
1086
1087
1088 static void
SendDragMessage(XmDragContext dc,Window destination,unsigned char messageType)1089 SendDragMessage(
1090 XmDragContext dc,
1091 Window destination,
1092 unsigned char messageType )
1093 {
1094 XmDropSiteManagerObject dsm = (XmDropSiteManagerObject)
1095 _XmGetDropSiteManagerObject((XmDisplay)(XtParent(dc)));
1096 XmICCCallbackStruct callbackRec;
1097 int reason = _XmMessageTypeToReason(messageType);
1098
1099 callbackRec.any.event = NULL;
1100
1101 if ((dc->drag.activeProtocolStyle == XmDRAG_NONE) ||
1102 ((dc->drag.activeProtocolStyle == XmDRAG_DROP_ONLY) &&
1103 (reason != XmCR_DROP_START)))
1104 return;
1105
1106 switch(callbackRec.any.reason = reason) {
1107 case XmCR_TOP_LEVEL_ENTER:
1108 {
1109 XmTopLevelEnterCallback callback =
1110 (XmTopLevelEnterCallback)&callbackRec;
1111
1112 callback->timeStamp = dc->drag.lastChangeTime;
1113 callback->window = dc->drag.srcWindow;
1114 callback->dragProtocolStyle = dc->drag.activeProtocolStyle;
1115 callback->screen = dc->drag.currScreen;
1116 callback->x = dc->drag.currReceiverInfo->xOrigin;
1117 callback->y = dc->drag.currReceiverInfo->yOrigin;
1118 callback->iccHandle = dc->drag.iccHandle;
1119 }
1120 break;
1121 case XmCR_TOP_LEVEL_LEAVE:
1122 {
1123 XmTopLevelLeaveCallback callback =
1124 (XmTopLevelLeaveCallback)&callbackRec;
1125
1126 callback->timeStamp = dc->drag.lastChangeTime;
1127 callback->window = dc->drag.srcWindow;
1128 }
1129 break;
1130 case XmCR_DRAG_MOTION:
1131 {
1132 XmDragMotionCallback callback =
1133 (XmDragMotionCallback)&callbackRec;
1134
1135 callback->timeStamp = dc->drag.lastChangeTime;
1136 callback->x = dc->core.x;
1137 callback->y = dc->core.y;
1138 callback->operation = dc->drag.operation;
1139 callback->operations = dc->drag.operations;
1140
1141 /* Outgoing motion; be conservative */
1142 callback->dropSiteStatus = XmNO_DROP_SITE;
1143 }
1144 break;
1145 case XmCR_OPERATION_CHANGED:
1146 {
1147 XmOperationChangedCallback callback =
1148 (XmOperationChangedCallback)&callbackRec;
1149
1150 callback->timeStamp = dc->drag.lastChangeTime;
1151 callback->operation = dc->drag.operation;
1152 callback->operations = dc->drag.operations;
1153 }
1154 break;
1155 case XmCR_DROP_START:
1156 {
1157 XmDropStartCallback callback =
1158 (XmDropStartCallback)&callbackRec;
1159
1160 callback->timeStamp = dc->drag.dragFinishTime;
1161 callback->operation = dc->drag.operation;
1162 callback->operations = dc->drag.operations;
1163 callback->dropAction = dc->drag.dragCompletionStatus;
1164 callback->dropSiteStatus = dsm->dropManager.curDropSiteStatus;
1165 callback->x = dc->core.x;
1166 callback->y = dc->core.y;
1167 callback->iccHandle = dc->drag.iccHandle;
1168 callback->window = XtWindow(dc->drag.srcShell);
1169 }
1170 break;
1171 default:
1172 break;
1173 }
1174
1175 /*
1176 * if we're the initiator and the destination isn't us and either
1177 * its the drop message or the dynamic protocol send it to the wire
1178 */
1179 if ((!dc->drag.currReceiverInfo->shell) &&
1180 (!dc->drag.sourceIsExternal /* sanity check */) &&
1181 ((dc->drag.activeProtocolStyle == XmDRAG_DYNAMIC) ||
1182 (reason == XmCR_DROP_START)))
1183 {
1184 _XmSendICCCallback(XtDisplayOfObject((Widget) dc), destination,
1185 &callbackRec, XmICC_INITIATOR_EVENT);
1186 }
1187 else {
1188 XtPointer data;
1189 XmDragTopLevelClientDataStruct topLevelData;
1190 XmDragMotionClientDataStruct motionData;
1191
1192 if ((reason == XmCR_TOP_LEVEL_ENTER) ||
1193 (reason == XmCR_TOP_LEVEL_LEAVE) ||
1194 (reason == XmCR_DROP_START)){
1195
1196 topLevelData.destShell = dc->drag.currReceiverInfo->shell;
1197 topLevelData.sourceIsExternal = dc->drag.sourceIsExternal;
1198 topLevelData.iccInfo = dc->drag.currReceiverInfo->iccInfo;
1199 topLevelData.xOrigin =
1200 (Position)(dc->drag.currReceiverInfo->xOrigin);
1201 topLevelData.yOrigin = (Position)
1202 (dc->drag.currReceiverInfo->yOrigin);
1203 topLevelData.width = (Dimension)
1204 (dc->drag.currReceiverInfo->width);
1205 topLevelData.height = (Dimension)
1206 (dc->drag.currReceiverInfo->height);
1207 topLevelData.window = dc->drag.currReceiverInfo->window;
1208 topLevelData.dragOver = (Widget)dc->drag.curDragOver;
1209 data = (XtPointer)&topLevelData;
1210 }
1211 else if ((reason == XmCR_DRAG_MOTION) ||
1212 (reason == XmCR_OPERATION_CHANGED)) {
1213 motionData.window = dc->drag.currReceiverInfo->window;
1214 motionData.dragOver = (Widget)dc->drag.curDragOver;
1215 data = (XtPointer)&motionData;
1216 }
1217 else {
1218 data = NULL;
1219 }
1220
1221 _XmDSMUpdate(dsm,
1222 (XtPointer)data,
1223 (XtPointer)&callbackRec);
1224 }
1225 }
1226
1227 static void
GenerateClientCallback(XmDragContext dc,unsigned char reason)1228 GenerateClientCallback(
1229 XmDragContext dc,
1230 unsigned char reason )
1231 {
1232 XmICCCallbackStruct callbackRec;
1233 XtCallbackList callbackList = NULL;
1234
1235 callbackRec.any.event = NULL;
1236
1237 switch(callbackRec.any.reason = reason) {
1238 case XmCR_TOP_LEVEL_ENTER:
1239 if ((callbackList = dc->drag.topLevelEnterCallback) != NULL) {
1240 XmTopLevelEnterCallback callback =
1241 (XmTopLevelEnterCallback)&callbackRec;
1242
1243 callback->timeStamp = dc->drag.lastChangeTime;
1244 callback->window = dc->drag.currReceiverInfo->window;
1245 callback->dragProtocolStyle =
1246 dc->drag.activeProtocolStyle;
1247 callback->screen = dc->drag.currScreen;
1248 callback->iccHandle = dc->drag.iccHandle;
1249 callback->x = dc->drag.currReceiverInfo->xOrigin;
1250 callback->y = dc->drag.currReceiverInfo->yOrigin;
1251 }
1252 break;
1253 case XmCR_TOP_LEVEL_LEAVE:
1254 if ((callbackList = dc->drag.topLevelLeaveCallback) != NULL) {
1255 XmTopLevelLeaveCallback callback =
1256 (XmTopLevelLeaveCallback)&callbackRec;
1257
1258 callback->timeStamp = dc->drag.lastChangeTime;
1259 callback->screen = dc->drag.currScreen;
1260 callback->window = dc->drag.currReceiverInfo->window;
1261 }
1262 break;
1263 case XmCR_DRAG_MOTION:
1264 if ((callbackList = dc->drag.dragMotionCallback) != NULL) {
1265 XmDragMotionCallback callback =
1266 (XmDragMotionCallback)&callbackRec;
1267
1268 callback->timeStamp = dc->drag.lastChangeTime;
1269 callback->x = dc->core.x;
1270 callback->y = dc->core.y;
1271 callback->operation = dc->drag.operation;
1272 callback->operations = dc->drag.operations;
1273
1274 /*
1275 * If we're over DropOnly client, be optimistic.
1276 */
1277 if (dc->drag.activeProtocolStyle == XmDRAG_DROP_ONLY)
1278 {
1279 callback->dropSiteStatus = XmVALID_DROP_SITE;
1280 }
1281 else
1282 {
1283 /*
1284 * Otherwise, we're over the root (see
1285 * DragMotionProto), and there's no drop site
1286 * under us.
1287 */
1288 callback->dropSiteStatus = XmNO_DROP_SITE;
1289 }
1290 }
1291 break;
1292 case XmCR_OPERATION_CHANGED:
1293 if ((callbackList = dc->drag.operationChangedCallback) != NULL) {
1294 XmOperationChangedCallback callback =
1295 (XmOperationChangedCallback)&callbackRec;
1296
1297 callback->timeStamp = dc->drag.lastChangeTime;
1298 callback->operation = dc->drag.operation;
1299 callback->operations = dc->drag.operations;
1300
1301 /*
1302 * If we're over DropOnly client, be optimistic.
1303 */
1304 if (dc->drag.activeProtocolStyle == XmDRAG_DROP_ONLY)
1305 {
1306 callback->dropSiteStatus = XmVALID_DROP_SITE;
1307 }
1308 else
1309 {
1310 /*
1311 * Otherwise, we're over the root (see
1312 * DragMotionProto), and there's no drop site
1313 * under us.
1314 */
1315 callback->dropSiteStatus = XmNO_DROP_SITE;
1316 }
1317 }
1318 break;
1319 case XmCR_DROP_SITE_ENTER:
1320 {
1321 XmeWarning((Widget)dc, MESSAGE1);
1322 }
1323 break;
1324 case XmCR_DROP_SITE_LEAVE:
1325 {
1326 XmDropSiteLeaveCallback callback =
1327 (XmDropSiteLeaveCallback)&callbackRec;
1328
1329 callback->timeStamp = dc->drag.lastChangeTime;
1330 }
1331 break;
1332 default:
1333 break;
1334 }
1335 if (callbackList)
1336 {
1337 XtCallCallbackList( (Widget)dc, callbackList, &callbackRec);
1338
1339 if (callbackList == dc->drag.dragMotionCallback)
1340 {
1341 XmDragOverShellWidget dos = dc->drag.curDragOver;
1342 XmDragMotionCallback callback =
1343 (XmDragMotionCallback)&callbackRec;
1344
1345 dc->drag.operation = callback->operation;
1346 dc->drag.operations = callback->operations;
1347 if (dos->drag.cursorState != callback->dropSiteStatus)
1348 {
1349 dos->drag.cursorState = callback->dropSiteStatus;
1350 _XmDragOverChange((Widget)dos, dos->drag.cursorState);
1351 }
1352 }
1353 }
1354 }
1355
1356 /*ARGSUSED*/
1357 static void
DropLoseIncrSelection(Widget w,Atom * selection,XtPointer clientData)1358 DropLoseIncrSelection(
1359 Widget w,
1360 Atom *selection,
1361 XtPointer clientData )
1362 {
1363 DropLoseSelection( w, selection) ;
1364 }
1365
1366
1367 static void
DropLoseSelection(Widget w,Atom * selection)1368 DropLoseSelection(
1369 Widget w,
1370 Atom *selection)
1371 {
1372 XmDragContext dc ;
1373
1374 if (!(dc = (XmDragContext) _XmGetDragContextFromHandle( w, *selection)))
1375 {
1376 XmeWarning(w, MESSAGE2) ;
1377 }
1378
1379 if (dc && dc->drag.dropFinishTime == 0)
1380 {
1381 XmeWarning(w, MESSAGE3) ;
1382 }
1383 }
1384
1385 static void
DragDropFinish(XmDragContext dc)1386 DragDropFinish(
1387 XmDragContext dc )
1388 {
1389 Widget w = NULL;
1390
1391 XmDropSiteManagerObject dsm = (XmDropSiteManagerObject)
1392 _XmGetDropSiteManagerObject((XmDisplay)(XtParent(dc)));
1393
1394 /* Handle completion */
1395 if (dc->drag.dropFinishCallback) {
1396 XmDropFinishCallbackStruct cb;
1397
1398 cb.reason = XmCR_DROP_FINISH;
1399 cb.event = NULL;
1400 cb.timeStamp = dc->drag.dropFinishTime;
1401 cb.operation = dc->drag.operation;
1402 cb.operations = dc->drag.operations;
1403 cb.dropSiteStatus = dsm->dropManager.curDropSiteStatus;
1404 cb.dropAction = dc->drag.dragCompletionStatus;
1405 cb.completionStatus = dc->drag.dragDropCompletionStatus;
1406 XtCallCallbackList((Widget) dc, dc->drag.dropFinishCallback, &cb);
1407 dc->drag.dragDropCompletionStatus = cb.completionStatus;
1408 }
1409
1410 if (dc->drag.blendModel != XmBLEND_NONE &&
1411 dc->drag.dragDropCancelEffect == False) {
1412 _XmDragOverFinish((Widget)dc->drag.curDragOver,
1413 dc->drag.dragDropCompletionStatus);
1414 }
1415
1416 if (dc->drag.dragDropFinishCallback) {
1417 XmDragDropFinishCallbackStruct cb;
1418
1419 cb.reason = XmCR_DRAG_DROP_FINISH;
1420 cb.event = NULL;
1421 cb.timeStamp = dc->drag.dropFinishTime;
1422 XtCallCallbackList((Widget) dc, dc->drag.dragDropFinishCallback, &cb);
1423 }
1424 /*
1425 * we send this now so that the non-local receiver can clean up
1426 * its dc after everything is done
1427 */
1428
1429 XtDisownSelection(dc->drag.srcShell,
1430 dc->drag.iccHandle,
1431 dc->drag.dragFinishTime);
1432
1433 _XmFreeMotifAtom((Widget)dc, dc->drag.iccHandle);
1434
1435 XtRemoveEventHandler(dc->drag.srcShell, FocusChangeMask, True,
1436 InitiatorMsgHandler,
1437 (XtPointer)dc);
1438
1439 XtVaGetValues((Widget)dc, XmNsourceWidget, &w, NULL);
1440 if (w)
1441 XtRemoveCallback(w, XmNdestroyCallback, cancelDrag, (XtPointer)dc);
1442
1443 XtDestroyWidget((Widget) dc);
1444 }
1445
1446
1447
1448 /*
1449 * This callback is called when a drag operation needs to be terminated.
1450 * This can occur when the widget whose id is contained in the drag data
1451 * structure is destroyed.
1452 */
1453 static void
cancelDrag(Widget w,XtPointer client,XtPointer call)1454 cancelDrag(
1455 Widget w,
1456 XtPointer client,
1457 XtPointer call)
1458 {
1459 Widget dragContext = (Widget)client;
1460 XmDragCancel(dragContext);
1461 }
1462
1463 /*
1464 * This routine is passed as the frontend to the convertProc.
1465 */
1466 /*VARARGS*/
1467 static Boolean
DropConvertIncrCallback(Widget w,Atom * selection,Atom * target,Atom * typeRtn,XtPointer * valueRtn,unsigned long * lengthRtn,int * formatRtn,unsigned long * maxLengthRtn,XtPointer clientData,XtRequestId * requestID)1468 DropConvertIncrCallback(
1469 Widget w,
1470 Atom *selection,
1471 Atom *target,
1472 Atom *typeRtn,
1473 XtPointer *valueRtn,
1474 unsigned long *lengthRtn,
1475 int *formatRtn,
1476 unsigned long *maxLengthRtn,
1477 XtPointer clientData,
1478 XtRequestId *requestID )
1479 {
1480 enum {
1481 XmATRANSFER_SUCCESS, XmATRANSFER_FAILURE,
1482 XmA_MOTIF_CANCEL_DROP_EFFECT, XmA_MOTIF_DROP, XmATARGETS, NUM_ATOMS };
1483 static char *atom_names[] = {
1484 XmSTRANSFER_SUCCESS, XmSTRANSFER_FAILURE,
1485 XmS_MOTIF_CANCEL_DROP_EFFECT, XmS_MOTIF_DROP, XmSTARGETS };
1486
1487 XmDragContext dc;
1488 Time dropTime;
1489 Boolean returnVal = True;
1490 Boolean success;
1491 Atom atoms[XtNumber(atom_names)];
1492
1493 dropTime = XtGetSelectionRequest(w, *selection, requestID)->time;
1494
1495 if (!(dc = (XmDragContext)
1496 _XmGetDragContextFromHandle(w, *selection))) {
1497 XmeWarning(w, MESSAGE2);
1498 return False;
1499 }
1500 assert(XtNumber(atom_names) == NUM_ATOMS);
1501 XInternAtoms(XtDisplayOfObject((Widget) dc), atom_names,
1502 XtNumber(atom_names), False, atoms);
1503 if ((success = (*target == atoms[XmATRANSFER_SUCCESS])) ||
1504 (*target == atoms[XmATRANSFER_FAILURE]))
1505 {
1506 if (success)
1507 dc->drag.dragDropCompletionStatus = XmDROP_SUCCESS;
1508 else
1509 dc->drag.dragDropCompletionStatus = XmDROP_FAILURE;
1510 *typeRtn = *target;
1511 *lengthRtn = 0;
1512 *formatRtn = 32;
1513 *valueRtn = NULL;
1514 *maxLengthRtn = 0;
1515 /*
1516 * the time is really of the start of the transfer but ...
1517 */
1518 dc->drag.dropFinishTime = dropTime;
1519 DragDropFinish(dc);
1520 }
1521 else if (*target == atoms[XmA_MOTIF_CANCEL_DROP_EFFECT])
1522 {
1523 dc->drag.dragDropCancelEffect = True;
1524 }
1525 else /* normal transfer */
1526 {
1527 Atom motifDrop = atoms[XmA_MOTIF_DROP];
1528 returnVal = (Boolean)((*(dc->drag.convertProc.sel_incr))
1529 ((Widget)dc,
1530 &motifDrop,
1531 target,
1532 typeRtn,
1533 valueRtn,
1534 lengthRtn,
1535 formatRtn,
1536 maxLengthRtn,
1537 clientData,
1538 requestID));
1539 }
1540
1541 /* add code to handle TARGET target automatically if not there yet */
1542 if ((! returnVal) && (*target == atoms[XmATARGETS])) {
1543 int len = sizeof(Atom) * dc->drag.numExportTargets;
1544
1545 if (dc->drag.incremental & 0x2) {
1546 dc->drag.incremental = 1;
1547 *valueRtn = NULL;
1548 *lengthRtn = 0;
1549 } else {
1550 *valueRtn = XtMalloc(len);
1551 memmove(*valueRtn, dc->drag.exportTargets, len);
1552 *lengthRtn = dc->drag.numExportTargets;
1553 dc->drag.incremental = 3;
1554 }
1555 *formatRtn = 32;
1556 *typeRtn = XA_ATOM;
1557 returnVal = True;
1558 }
1559
1560 return returnVal;
1561 }
1562
1563 /*
1564 * This routine is passed as the frontend to the convertProc.
1565 */
1566 /*VARARGS*/
1567 static Boolean
DropConvertCallback(Widget w,Atom * selection,Atom * target,Atom * typeRtn,XtPointer * valueRtn,unsigned long * lengthRtn,int * formatRtn)1568 DropConvertCallback(
1569 Widget w,
1570 Atom *selection,
1571 Atom *target,
1572 Atom *typeRtn,
1573 XtPointer *valueRtn,
1574 unsigned long *lengthRtn,
1575 int *formatRtn )
1576 {
1577 enum {
1578 XmATRANSFER_SUCCESS, XmATRANSFER_FAILURE,
1579 XmA_MOTIF_CANCEL_DROP_EFFECT, XmA_MOTIF_DROP, XmATARGETS, NUM_ATOMS };
1580 static char *atom_names[] = {
1581 XmSTRANSFER_SUCCESS, XmSTRANSFER_FAILURE,
1582 XmS_MOTIF_CANCEL_DROP_EFFECT, XmS_MOTIF_DROP, XmSTARGETS };
1583
1584 XmDragContext dc;
1585 Time dropTime;
1586 Boolean returnVal = True;
1587 Boolean success;
1588 Atom atoms[XtNumber(atom_names)];
1589
1590 dropTime = XtGetSelectionRequest(w, *selection, NULL)->time;
1591
1592 if (!(dc = (XmDragContext)
1593 _XmGetDragContextFromHandle(w, *selection))) {
1594 XmeWarning(w, MESSAGE2);
1595 return False;
1596 }
1597 assert(XtNumber(atom_names) == NUM_ATOMS);
1598 XInternAtoms(XtDisplayOfObject((Widget) dc), atom_names,
1599 XtNumber(atom_names), False, atoms);
1600 if ((success = (*target == atoms[XmATRANSFER_SUCCESS])) ||
1601 (*target == atoms[XmATRANSFER_FAILURE]))
1602 {
1603 if (success)
1604 dc->drag.dragDropCompletionStatus = XmDROP_SUCCESS;
1605 else
1606 dc->drag.dragDropCompletionStatus = XmDROP_FAILURE;
1607 *typeRtn = *target;
1608 *lengthRtn = 0;
1609 *formatRtn = 32;
1610 *valueRtn = NULL;
1611 /*
1612 * the time is really of the start of the transfer but ...
1613 */
1614 dc->drag.dropFinishTime = dropTime;
1615 DragDropFinish(dc);
1616 }
1617 else if (*target == atoms[XmA_MOTIF_CANCEL_DROP_EFFECT])
1618 {
1619 dc->drag.dragDropCancelEffect = True;
1620 }
1621 else /* normal transfer */
1622 {
1623 Atom motifDrop = atoms[XmA_MOTIF_DROP];
1624 returnVal = (Boolean)
1625 ((*(dc->drag.convertProc.sel))
1626 ((Widget)dc,
1627 &motifDrop,
1628 target,
1629 typeRtn,
1630 valueRtn,
1631 lengthRtn,
1632 formatRtn));
1633 }
1634
1635 /* add code to handle TARGET target automatically if not there yet */
1636 if ((! returnVal) && (*target == atoms[XmATARGETS])) {
1637 int len = sizeof(Atom) * dc->drag.numExportTargets;
1638 *valueRtn = XtMalloc(len);
1639 memmove(*valueRtn, dc->drag.exportTargets, len);
1640 *lengthRtn = dc->drag.numExportTargets;
1641 *formatRtn = 32;
1642 *typeRtn = XA_ATOM;
1643 returnVal = True;
1644 }
1645
1646 return returnVal;
1647 }
1648
1649 /*ARGSUSED*/
1650 static void
DragStartProto(XmDragContext dc)1651 DragStartProto(
1652 XmDragContext dc)
1653 {
1654 /*
1655 * bootstrap the top_level_window code
1656 */
1657 _XmWriteInitiatorInfo((Widget)dc);
1658 GetDestinationInfo(dc,
1659 RootWindowOfScreen(XtScreen(dc)),
1660 XtWindow(dc->drag.srcShell));
1661 GenerateClientCallback(dc, XmCR_TOP_LEVEL_ENTER);
1662 SendDragMessage(dc, dc->drag.currReceiverInfo->window, XmTOP_LEVEL_ENTER);
1663 SendDragMessage(dc, dc->drag.currReceiverInfo->window, XmDRAG_MOTION);
1664 }
1665
1666
1667 static void
NewScreen(XmDragContext dc,Window newRoot)1668 NewScreen(
1669 XmDragContext dc,
1670 Window newRoot)
1671 {
1672 XmDisplay dpy = (XmDisplay) XmGetXmDisplay(XtDisplay(dc));
1673 Cardinal i;
1674 Arg args[8];
1675 Widget old = (Widget) (dc->drag.curDragOver);
1676
1677 /* Find the new screen number */
1678 for (i = 0; i < XScreenCount(XtDisplayOfObject((Widget) dc)); i++)
1679 if (RootWindow(XtDisplayOfObject((Widget) dc), i) == newRoot)
1680 break;
1681
1682 dc->drag.currScreen =
1683 ScreenOfDisplay(XtDisplayOfObject((Widget) dc), i);
1684 dc->drag.currWmRoot = RootWindowOfScreen(dc->drag.currScreen);
1685
1686
1687 /* Build a new one */
1688 i = 0;
1689 /*
1690 * If this is the first call, tracking mode will be querypending
1691 * and we have to come up in cursor mode. Otherwise, we come up
1692 * in cursor for dynamic and pixmap for preregister.
1693 */
1694 if ((dc->drag.trackingMode == XmDRAG_TRACK_WM_QUERY_PENDING) ||
1695 (dc->drag.activeProtocolStyle == XmDRAG_DYNAMIC))
1696 {
1697 if (dpy -> display.displayHasShapeExtension)
1698 XtSetArg(args[i], XmNdragOverMode, XmDRAG_WINDOW);
1699 else
1700 XtSetArg(args[i], XmNdragOverMode, XmCURSOR);
1701 i++;
1702 }
1703 else
1704 {
1705 XtSetArg(args[i], XmNdragOverMode, XmPIXMAP); i++;
1706 }
1707
1708 XtSetArg(args[i], XmNhotX, dc->core.x); i++;
1709 XtSetArg(args[i], XmNhotY, dc->core.y); i++;
1710 XtSetArg(args[i], XmNbackgroundPixmap, None); i++;
1711 XtSetArg(args[i], XmNscreen, dc->drag.currScreen);i++;
1712 XtSetArg(args[i], XmNdepth, DefaultDepthOfScreen(dc->drag.currScreen));i++;
1713 XtSetArg(args[i], XmNcolormap,
1714 DefaultColormapOfScreen(dc->drag.currScreen));i++;
1715 XtSetArg(args[i], XmNvisual, DefaultVisualOfScreen(dc->drag.currScreen));i++;
1716
1717 /*
1718 * As popup child(ren) of the dc, the drag over(s) will
1719 * automatically destroyed by Xt when the dc is destroyed.
1720 * Isn't that handy?
1721 */
1722 dc->drag.curDragOver = (XmDragOverShellWidget)
1723 XtCreatePopupShell("dragOver", xmDragOverShellWidgetClass,
1724 (Widget) dc, args, i);
1725
1726 if (dc->drag.currScreen == XtScreen(dc->drag.srcShell))
1727 _XmDragOverSetInitialPosition((Widget)dc->drag.curDragOver,
1728 dc->drag.startX, dc->drag.startY);
1729
1730 if (old != NULL) {
1731 if (old != (Widget) (dc->drag.origDragOver))
1732 XtDestroyWidget(old);
1733 else
1734 _XmDragOverHide((Widget)dc->drag.origDragOver, 0, 0, NULL);
1735 }
1736
1737 GetScreenInfo(dc);
1738
1739 if (dc->drag.origDragOver == NULL)
1740 {
1741 dc->drag.origDragOver = dc->drag.curDragOver;
1742 }
1743
1744 if (dc->drag.trackingMode == XmDRAG_TRACK_MOTION)
1745 {
1746 EventMask mask = _XmDRAG_EVENT_MASK(dc);
1747
1748 if (XGrabPointer(XtDisplayOfObject((Widget) dc->drag.curDragOver),
1749 RootWindowOfScreen(XtScreen(dc->drag.curDragOver)),
1750 False,
1751 mask,
1752 GrabModeSync,
1753 GrabModeAsync,
1754 None,
1755 _XmDragOverGetActiveCursor((Widget)dc->drag.curDragOver),
1756 dc->drag.lastChangeTime) != GrabSuccess)
1757 Warning(MESSAGE4);
1758
1759 XAllowEvents(XtDisplayOfObject((Widget) dc->drag.srcShell),
1760 SyncPointer,
1761 dc->drag.lastChangeTime);
1762 }
1763 }
1764
1765
1766 /*ARGSUSED*/
1767 static void
LocalNotifyHandler(Widget w,XtPointer client,XtPointer call)1768 LocalNotifyHandler(
1769 Widget w,
1770 XtPointer client,
1771 XtPointer call )
1772 {
1773 XmDropSiteManagerObject dsm = (XmDropSiteManagerObject)w;
1774 XmDragContext dc = (XmDragContext)client;
1775
1776 switch(((XmAnyICCCallback)call)->reason) {
1777 case XmCR_DROP_SITE_ENTER:
1778 SiteEnteredWithLocalSource((Widget)dsm, (XtPointer)dc, (XtPointer)call);
1779 break;
1780
1781 case XmCR_DROP_SITE_LEAVE:
1782 /* SiteLeftWithLocalSource expect to find an
1783 * XmDropSiteEnterPendingCallbackStruct, so upgrade the
1784 * XmDropSiteLeaveCallbackStruct.
1785 */
1786 {
1787 XmDropSiteLeaveCallbackStruct *cb =
1788 (XmDropSiteLeaveCallbackStruct *) call;
1789 XmDropSiteEnterPendingCallbackStruct new_call;
1790 new_call.reason = cb->reason;
1791 new_call.event = cb->event;
1792 new_call.timeStamp = cb->timeStamp;
1793 new_call.enter_pending = False;
1794 SiteLeftWithLocalSource((Widget) dsm, (XtPointer)dc,
1795 (XtPointer) &new_call);
1796 break;
1797 }
1798
1799 case XmCR_DRAG_MOTION:
1800 SiteMotionWithLocalSource((Widget)dsm, (XtPointer)dc, (XtPointer)call);
1801 break;
1802
1803 case XmCR_OPERATION_CHANGED:
1804 OperationChanged((Widget)dsm, (XtPointer)dc, (XtPointer)call);
1805 break;
1806
1807 case XmCR_DROP_START:
1808 DropStartConfirmed((Widget)dsm, (XtPointer)dc, (XtPointer)call);
1809
1810 default:
1811 break;
1812 }
1813 }
1814
1815 /*
1816 * sends replies to drag messages
1817 */
1818 /*ARGSUSED*/
1819 static void
ExternalNotifyHandler(Widget w,XtPointer client,XtPointer call)1820 ExternalNotifyHandler(
1821 Widget w,
1822 XtPointer client,
1823 XtPointer call )
1824 {
1825 XmDragContext dc = (XmDragContext)client;
1826 XmAnyICCCallback cb = (XmAnyICCCallback)call;
1827
1828 switch(cb->reason) {
1829 case XmCR_DROP_SITE_ENTER:
1830 case XmCR_DROP_SITE_LEAVE:
1831 case XmCR_DRAG_MOTION:
1832 case XmCR_OPERATION_CHANGED:
1833 case XmCR_DROP_START:
1834 /*
1835 * send a message to the external source
1836 */
1837 _XmSendICCCallback(XtDisplayOfObject((Widget) dc),
1838 dc->drag.srcWindow,
1839 (XmICCCallback)cb,
1840 XmICC_RECEIVER_EVENT);
1841 break;
1842
1843 default:
1844 XmeWarning((Widget)dc, MESSAGE5);
1845 break;
1846 }
1847 }
1848
1849
1850 /*
1851 * catches replies on drag messages
1852 */
1853 /*ARGSUSED*/
1854 static void
InitiatorMsgHandler(Widget w,XtPointer clientData,XEvent * event,Boolean * dontSwallow)1855 InitiatorMsgHandler(
1856 Widget w,
1857 XtPointer clientData,
1858 XEvent *event,
1859 Boolean *dontSwallow )
1860 {
1861 XmDragContext dc =(XmDragContext)clientData;
1862 XmICCCallbackStruct callbackRec;
1863
1864 if ((dc && (event->type != ClientMessage)) ||
1865 (!_XmICCEventToICCCallback((XClientMessageEvent *)event,
1866 &callbackRec, XmICC_RECEIVER_EVENT)) ||
1867 (dc->drag.dragStartTime > callbackRec.any.timeStamp) ||
1868 (dc->drag.crossingTime > callbackRec.any.timeStamp))
1869 return;
1870
1871 LocalNotifyHandler(w, (XtPointer)dc, (XtPointer)&callbackRec);
1872 }
1873
1874 /*ARGSUSED*/
1875 static void
SiteEnteredWithLocalSource(Widget w,XtPointer client,XtPointer call)1876 SiteEnteredWithLocalSource(
1877 Widget w,
1878 XtPointer client,
1879 XtPointer call )
1880 {
1881 XmDragContext dc = (XmDragContext)client;
1882 XmDropSiteEnterCallbackStruct *cb = (XmDropSiteEnterCallbackStruct *)call;
1883
1884 CalculateDragOperation(dc);
1885
1886 /* check against the current location of the pointer */
1887
1888 if (dc->drag.siteEnterCallback) {
1889 XtCallCallbackList((Widget) dc, dc->drag.siteEnterCallback, cb);
1890 }
1891 dc->drag.operation = cb->operation;
1892 dc->drag.operations = cb->operations;
1893 dc->drag.inDropSite = True;
1894
1895 _XmDragOverChange((Widget)dc->drag.curDragOver, cb->dropSiteStatus);
1896 }
1897
1898 /*ARGSUSED*/
1899 static void
SiteLeftWithLocalSource(Widget w,XtPointer client,XtPointer call)1900 SiteLeftWithLocalSource(
1901 Widget w,
1902 XtPointer client,
1903 XtPointer call )
1904 {
1905 XmDragContext dc = (XmDragContext)client;
1906 XmDropSiteEnterPendingCallbackStruct *cb =
1907 (XmDropSiteEnterPendingCallbackStruct *)call;
1908
1909 dc->drag.inDropSite = False;
1910
1911 if (dc->drag.siteLeaveCallback) {
1912 XtCallCallbackList((Widget) dc, dc->drag.siteLeaveCallback,
1913 (XmDropSiteLeaveCallbackStruct *)cb);
1914 }
1915
1916 CalculateDragOperation(dc);
1917
1918 /*
1919 * Don't forward laggard echo leaves to dragUnder
1920 */
1921 if (dc->drag.dragFinishTime == 0 && !cb->enter_pending)
1922 _XmDragOverChange((Widget)dc->drag.curDragOver, XmNO_DROP_SITE);
1923 }
1924
1925 /*ARGSUSED*/
1926 static void
OperationChanged(Widget w,XtPointer client,XtPointer call)1927 OperationChanged(
1928 Widget w,
1929 XtPointer client,
1930 XtPointer call )
1931 {
1932 XmDragContext dc = (XmDragContext)client;
1933 XmOperationChangedCallbackStruct *cb = (XmOperationChangedCallbackStruct *)call;
1934
1935 if (dc->drag.operationChangedCallback) {
1936 XtCallCallbackList((Widget) dc, dc->drag.operationChangedCallback, cb);
1937 }
1938 dc->drag.operation = cb->operation;
1939 dc->drag.operations = cb->operations;
1940 _XmDragOverChange((Widget)dc->drag.curDragOver, cb->dropSiteStatus);
1941 }
1942
1943 /*ARGSUSED*/
1944 static void
SiteMotionWithLocalSource(Widget w,XtPointer client,XtPointer call)1945 SiteMotionWithLocalSource(
1946 Widget w,
1947 XtPointer client,
1948 XtPointer call )
1949 {
1950 XmDragContext dc = (XmDragContext)client;
1951 XmDragMotionCallbackStruct *cb = (XmDragMotionCallbackStruct *)call;
1952
1953 if (dc->drag.dragMotionCallback) {
1954 XtCallCallbackList((Widget) dc, dc->drag.dragMotionCallback, cb);
1955 }
1956
1957 /* Application should not be able to change callback data so
1958 * don't call _XmDragOverChange(), this will result in better
1959 * drag performance.
1960 */
1961 }
1962
1963
1964 /*ARGSUSED*/
1965 static void
DropStartConfirmed(Widget w,XtPointer client,XtPointer call)1966 DropStartConfirmed(
1967 Widget w,
1968 XtPointer client,
1969 XtPointer call )
1970 {
1971 XmDragContext dc = (XmDragContext)client;
1972 XmDropStartCallbackStruct *cb = (XmDropStartCallbackStruct *)call;
1973 XtAppContext appContext = XtWidgetToApplicationContext((Widget)dc);
1974
1975 if (dc->drag.dragTimerId) {
1976 XtRemoveTimeOut(dc->drag.dragTimerId);
1977 dc->drag.dragTimerId = (XtIntervalId) NULL;
1978 }
1979
1980 /* Add a long timeout in case the drop site dies. */
1981 dc->drag.dragTimerId =
1982 XtAppAddTimeOut(appContext,
1983 XtAppGetSelectionTimeout(appContext) * 10,
1984 DropFinishTimeout,
1985 (XtPointer)dc);
1986
1987 if (dc->drag.dropStartCallback) {
1988 XtCallCallbackList( (Widget)dc, dc->drag.dropStartCallback, cb);
1989 }
1990 dc->drag.dragCompletionStatus = cb->dropAction;
1991
1992 switch(dc->drag.dragCompletionStatus) {
1993 case XmDROP:
1994 case XmDROP_INTERRUPT:
1995 case XmDROP_HELP:
1996 break;
1997 case XmDROP_CANCEL:
1998 break;
1999 }
2000 }
2001
2002
2003 static Widget
GetShell(Widget w)2004 GetShell(
2005 Widget w )
2006 {
2007 while (w && !XtIsShell(w))
2008 w = XtParent(w);
2009 return w;
2010 }
2011
2012 static void
InitDropSiteManager(XmDragContext dc)2013 InitDropSiteManager(
2014 XmDragContext dc )
2015 {
2016 XmDropSiteManagerObject dsm;
2017 Arg args[4];
2018 Cardinal i = 0;
2019
2020 dsm = _XmGetDropSiteManagerObject((XmDisplay)(XtParent(dc)));
2021
2022 XtSetArg(args[i], XmNclientData, dc); i++;
2023 if (dc->drag.sourceIsExternal) {
2024 XtSetArg(args[i], XmNnotifyProc, ExternalNotifyHandler); i++;
2025 }
2026 else {
2027 XtSetArg(args[i], XmNnotifyProc, LocalNotifyHandler); i++;
2028 }
2029 XtSetValues((Widget)dsm, args, i);
2030 }
2031
2032 /*ARGSUSED*/
2033 static void
TopWindowsReceived(Widget w,XtPointer client_data,Atom * selection,Atom * type,XtPointer value,unsigned long * length,int * format)2034 TopWindowsReceived(
2035 Widget w,
2036 XtPointer client_data,
2037 Atom *selection,
2038 Atom *type,
2039 XtPointer value,
2040 unsigned long *length,
2041 int *format )
2042 {
2043 XmDragContext dc = (XmDragContext)client_data;
2044 XmDisplay dd = (XmDisplay) w;
2045 Cardinal i;
2046 XmDragReceiverInfo currInfo, startInfo;
2047 Window *clientWindows;
2048 unsigned char oldStyle;
2049
2050 if (dd->display.activeDC != dc) {
2051 /* Too late... */
2052 return;
2053 }
2054
2055 /* CR 6337. Must call DragOverChange if the blendModel
2056 changes. This doesn't happen often, only in certain
2057 cases involving PREREGISTER */
2058
2059 if (dc -> drag.blendModel != dc -> drag.activeBlendModel) {
2060 dc->drag.blendModel = dc->drag.activeBlendModel;
2061 _XmDragOverChange((Widget)dc->drag.curDragOver, XmNO_DROP_SITE);
2062 }
2063
2064
2065 #ifdef MULTI_SCREEN_DONE
2066 if ((*length != 0) && (*format == 32) && (*type == XA_WINDOW)) {
2067 /*
2068 * we make a receiverInfo array one larger than the number of
2069 * client windows since we keep the root info in array[0].
2070 */
2071 if (dc->drag.numReceiverInfos >= 1)
2072 startInfo = dc->drag.receiverInfos;
2073 else
2074 startInfo = NULL;
2075
2076 dc->drag.numReceiverInfos =
2077 dc->drag.maxReceiverInfos = *length + 1;
2078 dc->drag.receiverInfos = (XmDragReceiverInfo)
2079 XtCalloc(dc->drag.maxReceiverInfos, sizeof(XmDragReceiverInfoStruct));
2080 clientWindows = (Window *)value;
2081
2082 if (startInfo) {
2083 memcpy((char *)dc->drag.receiverInfos,
2084 (char *)startInfo,
2085 sizeof(XmDragReceiverInfoStruct));
2086 dc->drag.rootReceiverInfo = dc->drag.receiverInfos;
2087 XtFree((char *)startInfo);
2088 }
2089 #ifdef DEBUG
2090 else
2091 Warning("we don't have startInfo when we should\n");
2092 #endif /* DEBUG */
2093 for (i = 1; i < dc->drag.numReceiverInfos; i++) {
2094 currInfo = &dc->drag.receiverInfos[i];
2095 currInfo->window = clientWindows[i-1];
2096 currInfo->shell = XtWindowToWidget(XtDisplay(dc),
2097 currInfo->window);
2098 if (currInfo->shell == NULL) {
2099 XSelectInput(XtDisplay(dc),
2100 currInfo->window,
2101 EnterWindowMask | LeaveWindowMask);
2102 }
2103
2104 }
2105 /*
2106 * set the currReceiver to the srcShell since that's where
2107 * we're confined to
2108 */
2109 dc->drag.currReceiverInfo =
2110 FindReceiverInfo(dc, XtWindow(dc->drag.srcShell));
2111 dc->drag.trackingMode = XmDRAG_TRACK_WM_QUERY;
2112
2113 oldStyle = dc->drag.activeProtocolStyle;
2114 dc->drag.activeProtocolStyle =
2115 _XmGetActiveProtocolStyle((Widget)dc);
2116 ValidateDragOver(dc, oldStyle, dc->drag.activeProtocolStyle);
2117 }
2118 else
2119 #endif /* MULTI_SCREEN_DONE */
2120 {
2121 EventMask mask;
2122 Window confineWindow;
2123 Cursor cursor;
2124
2125 dc->drag.trackingMode = XmDRAG_TRACK_MOTION;
2126 GetDestinationInfo(dc,
2127 dc->drag.currWmRoot,
2128 dc->drag.currReceiverInfo->window);
2129 #ifndef MULTI_SCREEN_DONE
2130 confineWindow = RootWindowOfScreen(XtScreen(dc));
2131 #else
2132 confineWindow = None;
2133 #endif /* MULTI_SCREEN_DONE */
2134
2135 /*
2136 * we need to regrab so that the confine window can be changed
2137 * from the source window. If there was another value for
2138 * trackingMode like XmDRAG_TRACK_WM_QUERY_FAILED we could do
2139 * this in DragStartWithTracking
2140 */
2141
2142 mask = _XmDRAG_EVENT_MASK(dc);
2143 cursor = _XmDragOverGetActiveCursor((Widget)dc->drag.curDragOver);
2144
2145 if (XGrabPointer(XtDisplayOfObject((Widget) dc),
2146 RootWindowOfScreen(XtScreen(dc)),
2147 False,
2148 mask,
2149 GrabModeSync,
2150 GrabModeAsync,
2151 confineWindow,
2152 cursor,
2153 dc->drag.lastChangeTime) != GrabSuccess)
2154 Warning(MESSAGE4);
2155 }
2156 #ifdef MULTI_SCREEN_DONE
2157 if (value)
2158 XtFree((char *)value);
2159 #endif /* MULTI_SCREEN_DONE */
2160
2161 DragStartWithTracking(dc);
2162 }
2163
2164
2165 /* ARGSUSED */
2166 static void
DragStart(XmDragContext dc,Widget src,XEvent * event)2167 DragStart(
2168 XmDragContext dc,
2169 Widget src,
2170 XEvent *event )
2171 {
2172 XmDisplay dd;
2173 unsigned char activeProtocolStyle;
2174 unsigned int state = event->xbutton.state;
2175 EventMask mask;
2176 Window saveWindow;
2177 Window confineWindow;
2178 Cursor cursor = None;
2179
2180 dd = (XmDisplay)XtParent(dc);
2181 dd->display.activeDC = dc;
2182 dd->display.userGrabbed = True;
2183
2184 dc->drag.crossingTime =
2185 dc->drag.dragStartTime =
2186 dc->drag.lastChangeTime = event->xbutton.time;
2187
2188 dc->drag.startX = dc->core.x = event->xbutton.x_root;
2189 dc->drag.startY = dc->core.y = event->xbutton.y_root;
2190 dc->drag.curDragOver = NULL;
2191 dc->drag.origDragOver = NULL;
2192 dc->drag.srcShell = GetShell(src);
2193 dc->drag.srcWindow = XtWindow(dc->drag.srcShell);
2194 dc->drag.iccHandle = _XmAllocMotifAtom((Widget)dc, dc->drag.dragStartTime);
2195
2196 if (dc->drag.incremental)
2197 XtOwnSelectionIncremental(dc->drag.srcShell,
2198 dc->drag.iccHandle,
2199 dc->drag.dragStartTime,
2200 DropConvertIncrCallback,
2201 DropLoseIncrSelection,
2202 NULL, NULL, dc->drag.clientData);
2203 else
2204 XtOwnSelection(dc->drag.srcShell,
2205 dc->drag.iccHandle,
2206 dc->drag.dragStartTime,
2207 DropConvertCallback,
2208 DropLoseSelection,
2209 NULL);
2210
2211
2212 dc->drag.serverGrabbed = False;
2213 dc->drag.sourceIsExternal = False;
2214
2215 dc->drag.activeProtocolStyle = activeProtocolStyle =
2216 _XmGetActiveProtocolStyle((Widget)dc);
2217
2218 switch (dc->drag.activeProtocolStyle)
2219 {
2220 case XmDRAG_PREREGISTER:
2221 dc->drag.activeProtocolStyle = XmDRAG_DYNAMIC;
2222 case XmDRAG_DYNAMIC:
2223 break;
2224 case XmDRAG_DROP_ONLY:
2225 dc->drag.activeProtocolStyle = XmDRAG_NONE;
2226 case XmDRAG_NONE:
2227 break;
2228 }
2229
2230 /* must be either DYNAMIC or NONE at this point */
2231
2232 /*
2233 * start out with the default operations in effective operations
2234 */
2235
2236 dc->drag.lastEventState = state;
2237 CalculateDragOperation(dc);
2238 dc->drag.sourceIsExternal = False;
2239
2240 /*
2241 * if we're in query_pending mode then initialize the
2242 * currReceiverInfo to us
2243 */
2244 if (dc->drag.trackingMode == XmDRAG_TRACK_MOTION) {
2245 dc->drag.activeProtocolStyle = activeProtocolStyle;
2246 #ifndef MULTI_SCREEN_DONE
2247 confineWindow = RootWindowOfScreen(XtScreen(dc));
2248 #else
2249 confineWindow = None;
2250 } else { /* XmDRAG_TRACK_WM_QUERY */
2251 dc->drag.trackingMode = XmDRAG_TRACK_WM_QUERY_PENDING;
2252 confineWindow = XtWindow(dc->drag.srcShell);
2253 }
2254 #endif /* MULTI_SCREEN_DONE */
2255
2256 if (dc->drag.trackingMode == XmDRAG_TRACK_WM_QUERY_PENDING &&
2257 activeProtocolStyle == XmDRAG_PREREGISTER) {
2258 dc->drag.blendModel = XmBLEND_NONE;
2259 }
2260
2261 NewScreen(dc, RootWindowOfScreen(XtScreen(dc)));
2262
2263 XtInsertEventHandler(dc->drag.srcShell, FocusChangeMask, True,
2264 InitiatorMsgHandler,
2265 (XtPointer)dc,
2266 XtListHead);
2267
2268 mask = _XmDRAG_EVENT_MASK(dc);
2269
2270 /*
2271 * we grab on the Xt pointer so that Xt doesn't interfere with us.
2272 * Also once we have the WM_QUERY capability this will work.
2273 * Otherwise we need to grab on the root so we can track the
2274 * changes in sub_window and infer the top_level crossings
2275 */
2276 /*
2277 * some more sleaze to get around the ungrab. Since we can't rely
2278 * on the caller to have done an owner_events true (for Xt), we need to
2279 * guarantee that the release event goes to us. The grab window
2280 * must be viewable so we can't use the dc window
2281 */
2282
2283 saveWindow = dc->core.window;
2284
2285 cursor = _XmDragOverGetActiveCursor((Widget)dc->drag.curDragOver);
2286
2287 dc->core.window = RootWindowOfScreen(XtScreen(dc));
2288 if ((XtGrabPointer((Widget)dc,
2289 False,
2290 (unsigned int) mask,
2291 GrabModeSync,
2292 GrabModeAsync,
2293 confineWindow,
2294 cursor,
2295 dc->drag.dragStartTime) != GrabSuccess) ||
2296 (XGrabPointer(XtDisplayOfObject((Widget) dc),
2297 RootWindowOfScreen(XtScreen(dc)),
2298 False,
2299 mask,
2300 GrabModeSync,
2301 GrabModeAsync,
2302 confineWindow,
2303 cursor,
2304 dc->drag.dragStartTime) != GrabSuccess) ||
2305 (XGrabKeyboard(XtDisplayOfObject((Widget) dc),
2306 RootWindowOfScreen(XtScreen(dc)),
2307 False,
2308 GrabModeSync,
2309 GrabModeAsync,
2310 dc->drag.dragStartTime) != GrabSuccess))
2311 Warning(MESSAGE4);
2312 _XmAddGrab((Widget)dc, True, False);
2313 dc->core.window = saveWindow;
2314
2315 /* Begin fixing OSF CR 5556 */
2316 /*
2317 * Add ButtonMotionMask to the already set-up event mask for root window.
2318 * This gets reinstalled in DragContextDestroy()
2319 */
2320 {
2321 XWindowAttributes xwa;
2322
2323 XGetWindowAttributes(XtDisplay(dc), dc->drag.currWmRoot, &xwa);
2324 dc->drag.SaveEventMask = xwa.your_event_mask;
2325 XSelectInput(XtDisplay(dc),
2326 dc->drag.currWmRoot,
2327 xwa.your_event_mask | ButtonMotionMask);
2328 }
2329 /* End fixing OSF CR 5556 */
2330
2331 if (dc->drag.trackingMode == XmDRAG_TRACK_WM_QUERY_PENDING) {
2332 enum { XmA_MOTIF_WM_QUERY, XmA_MOTIF_WM_ALL_CLIENTS, NUM_ATOMS };
2333 static char *atom_names[] = {
2334 XmS_MOTIF_WM_QUERY, XmS_MOTIF_WM_ALL_CLIENTS };
2335 Atom atoms[XtNumber(atom_names)];
2336
2337 assert(XtNumber(atom_names) == NUM_ATOMS);
2338 XInternAtoms(XtDisplay(dc), atom_names, XtNumber(atom_names),
2339 False, atoms);
2340
2341 XtGetSelectionValue((Widget)dd,
2342 atoms[XmA_MOTIF_WM_QUERY],
2343 atoms[XmA_MOTIF_WM_ALL_CLIENTS],
2344 TopWindowsReceived,
2345 (XtPointer)dc,
2346 dc->drag.dragStartTime);
2347
2348 XAllowEvents(XtDisplayOfObject((Widget) dc->drag.srcShell),
2349 SyncPointer,
2350 dc->drag.dragStartTime);
2351 }
2352 else
2353 DragStartWithTracking(dc);
2354
2355 XSync(XtDisplay(dc), False);
2356
2357 XtAppAddTimeOut( XtWidgetToApplicationContext( (Widget)dc),
2358 0, InitiatorMainLoop,
2359 (XtPointer)(&dd->display.activeDC));
2360 }
2361
2362
2363 /* ARGSUSED */
2364 static void
DragStartWithTracking(XmDragContext dc)2365 DragStartWithTracking(
2366 XmDragContext dc)
2367 {
2368 if (dc->drag.dragFinishTime)
2369 return;
2370
2371 if (dc->drag.trackingMode == XmDRAG_TRACK_WM_QUERY) {
2372 EventMask mask = _XmDRAG_EVENT_MASK(dc);
2373 Window confineWindow;
2374 Cursor cursor;
2375
2376 #ifndef MULTI_SCREEN_DONE
2377 confineWindow = RootWindowOfScreen(XtScreen(dc));
2378 #else
2379 confineWindow = None;
2380 #endif
2381 cursor = _XmDragOverGetActiveCursor((Widget)dc->drag.curDragOver);
2382
2383 /*
2384 * set owner events to true so that the crossings and motion
2385 * are reported relative to the destination windows. Don't
2386 * tell Xt about it so we can continue to get everything
2387 * reported to the dragContext via the spring-loaded/XtGrab
2388 * interaction. Blegh
2389 */
2390 if (XGrabPointer(XtDisplayOfObject((Widget) dc),
2391 RootWindowOfScreen(XtScreen(dc)),
2392 True,
2393 mask,
2394 GrabModeSync,
2395 GrabModeAsync,
2396 confineWindow,
2397 cursor,
2398 dc->drag.lastChangeTime) != GrabSuccess)
2399 Warning(MESSAGE4);
2400 }
2401
2402 XAllowEvents(XtDisplayOfObject((Widget) dc->drag.srcShell),
2403 SyncPointer,
2404 dc->drag.lastChangeTime);
2405 }
2406
2407 static void
UpdateMotionBuffer(XmDragContext dc,MotionBuffer mb,XEvent * event)2408 UpdateMotionBuffer(
2409 XmDragContext dc,
2410 MotionBuffer mb,
2411 XEvent *event)
2412 {
2413 Time time ;
2414 unsigned int state;
2415 Window window, subwindow;
2416 Position x ;
2417 Position y ;
2418
2419 if (dc->drag.currReceiverInfo == NULL)
2420 return;
2421
2422 dc->drag.lastChangeTime = event->xmotion.time;
2423
2424 /*
2425 * we munged the window and subwindow fields before calling
2426 * XtDispatchEvent so we could get the event thru to the
2427 * DragContext. The subwindow field will hold the interesting
2428 * info. The window field is always set (by us) to the DC window.
2429 */
2430 switch(event->type) {
2431 case MotionNotify:
2432 if (mb->count && ((mb->count % (STACKMOTIONBUFFERSIZE)) == 0)) {
2433 if (mb->count == (STACKMOTIONBUFFERSIZE)){
2434 MotionBuffer oldMb = mb;
2435 Cardinal size;
2436
2437 size = sizeof(MotionBufferRec) +
2438 (STACKMOTIONBUFFERSIZE * sizeof(MotionEntryRec));
2439 mb = (MotionBuffer) XtMalloc(size);
2440 memcpy((char *)mb, (char *)oldMb, sizeof(MotionBufferRec));
2441 }
2442 else {
2443 mb = (MotionBuffer)
2444 XtRealloc((char *)mb,
2445 (sizeof(MotionBufferRec) +
2446 (mb->count + STACKMOTIONBUFFERSIZE) *sizeof(MotionEntryRec)));
2447 }
2448 }
2449 /*
2450 * for right now use the root although this wont work for
2451 * pseudo-roots
2452 */
2453 time = event->xmotion.time;
2454 state = event->xmotion.state;
2455 x = event->xmotion.x_root;
2456 y = event->xmotion.y_root;
2457 window = event->xmotion.root;
2458 if (dc->drag.trackingMode != XmDRAG_TRACK_MOTION) {
2459 subwindow = mb->currReceiverInfo->window;
2460 }
2461 else {
2462 subwindow = event->xmotion.subwindow;
2463 }
2464 mb->entries[mb->count].time = time;
2465 mb->entries[mb->count].window = window;
2466 mb->entries[mb->count].subwindow = subwindow;
2467 mb->entries[mb->count].state = state;
2468 mb->entries[mb->count].x = x;
2469 mb->entries[mb->count++].y = y;
2470 break;
2471
2472 case EnterNotify:
2473 if ((event->xcrossing.mode == NotifyNormal) &&
2474 (dc->drag.trackingMode != XmDRAG_TRACK_MOTION)) {
2475 XmDragReceiverInfo rInfo;
2476 if ((rInfo = FindReceiverInfo(dc, event->xcrossing.subwindow))
2477 != NULL)
2478 mb->currReceiverInfo = rInfo;
2479 }
2480 break;
2481
2482 case LeaveNotify:
2483 if ((event->xcrossing.mode == NotifyNormal) &&
2484 (dc->drag.trackingMode != XmDRAG_TRACK_MOTION)) {
2485 XmDragReceiverInfo rInfo;
2486 if ((rInfo = FindReceiverInfo(dc, event->xcrossing.subwindow))
2487 != NULL) {
2488 if (rInfo == mb->currReceiverInfo)
2489 mb->currReceiverInfo = dc->drag.rootReceiverInfo;
2490 }
2491 }
2492 break;
2493 default:
2494 break;
2495 }
2496 }
2497
2498
2499 static void
DragMotionProto(XmDragContext dc,Window root,Window subWindow)2500 DragMotionProto(
2501 XmDragContext dc,
2502 Window root,
2503 Window subWindow )
2504 {
2505 Boolean incrementTimestamp = False;
2506
2507 /*
2508 * We've selected for motion on the root window. This allows us to
2509 * use the subwindow field to know whenever we have left or
2510 * entered a potential top-level window.
2511 */
2512 if ((root != dc->drag.currWmRoot) ||
2513 ((((dc->drag.trackingMode == XmDRAG_TRACK_MOTION) &&
2514 (dc->drag.currReceiverInfo->frame != subWindow))) ||
2515 ((dc->drag.trackingMode == XmDRAG_TRACK_WM_QUERY) &&
2516 (dc->drag.currReceiverInfo->window != subWindow))))
2517 {
2518 if (dc->drag.currReceiverInfo->window)
2519 {
2520 if ((dc->drag.activeProtocolStyle != XmDRAG_NONE) &&
2521 (dc->drag.activeProtocolStyle != XmDRAG_DROP_ONLY))
2522 {
2523 /*
2524 * Assumes the root window doesn't contain drop-sites !!!
2525 * Send motion to old window.
2526 *
2527 * ** Old stuff for bootstrap
2528 * ** if (dc->drag.currReceiverInfo->frame)
2529 * ** only send to non-initial windows
2530 */
2531 /*
2532 * if the receiver is dynamic and we've been
2533 * informed that we're in a drop-site then
2534 * generate a dropsite leave to the initiator. If
2535 * we haven't yet been informed of a drop-site
2536 * enter (due to latency) but one is in the pipes,
2537 * it will be ignored once it gets in based on the
2538 * timestamp being stale.
2539 *
2540 * We'll make sure it's stale by incrementing the
2541 * timestamp by one millisecond. This is a no-no but
2542 * it makes it easy to identify the echo events from
2543 * the receiver. Its also relatively safe until we
2544 * get micro-second response times :-)
2545 */
2546 if ((dc->drag.activeProtocolStyle == XmDRAG_DYNAMIC) &&
2547 (!dc->drag.currReceiverInfo->shell) &&
2548 (dc->drag.inDropSite))
2549 {
2550 GenerateClientCallback(dc, XmCR_DROP_SITE_LEAVE);
2551 dc->drag.inDropSite = False;
2552 incrementTimestamp = True;
2553 }
2554 SendDragMessage(dc, dc->drag.currReceiverInfo->window,
2555 XmDRAG_MOTION);
2556 SendDragMessage(dc, dc->drag.currReceiverInfo->window,
2557 XmTOP_LEVEL_LEAVE);
2558 }
2559 GenerateClientCallback(dc, XmCR_TOP_LEVEL_LEAVE);
2560 }
2561
2562 if (root != dc->drag.currWmRoot)
2563 NewScreen(dc, root);
2564
2565 GetDestinationInfo(dc, root, subWindow);
2566
2567 /* we should special-case the root window */
2568 if (dc->drag.currReceiverInfo->window)
2569 {
2570 if ((dc->drag.activeProtocolStyle != XmDRAG_NONE) &&
2571 (dc->drag.activeProtocolStyle != XmDRAG_DROP_ONLY))
2572 {
2573 SendDragMessage(dc, dc->drag.currReceiverInfo->window,
2574 XmTOP_LEVEL_ENTER);
2575 }
2576 /* clear iccInfo for dsm's sanity */
2577 dc->drag.currReceiverInfo->iccInfo = NULL;
2578 GenerateClientCallback(dc, XmCR_TOP_LEVEL_ENTER);
2579 }
2580 }
2581 if (dc->drag.currReceiverInfo->window)
2582 {
2583 if ((dc->drag.activeProtocolStyle != XmDRAG_NONE) &&
2584 (dc->drag.activeProtocolStyle != XmDRAG_DROP_ONLY))
2585 SendDragMessage(dc, dc->drag.currReceiverInfo->window,
2586 XmDRAG_MOTION);
2587 else
2588 GenerateClientCallback(dc, XmCR_DRAG_MOTION);
2589 }
2590 else
2591 GenerateClientCallback(dc, XmCR_DRAG_MOTION);
2592 if (incrementTimestamp)
2593 dc->drag.lastChangeTime++;
2594 }
2595
2596 static void
ProcessMotionBuffer(XmDragContext dc,MotionBuffer mb)2597 ProcessMotionBuffer(
2598 XmDragContext dc,
2599 MotionBuffer mb )
2600 {
2601 Cardinal incr, i, j, max;
2602 Window protoWindow = None;
2603
2604 incr = (mb->count / MOTIONFILTER);
2605 if (incr == 0) incr = 1;
2606 max = mb->count / incr;
2607 j = (mb->count + incr - 1) % incr;
2608 for (i = 0; i < max; i++, j += incr) {
2609 dc->core.x = mb->entries[j].x;
2610 dc->core.y = mb->entries[j].y;
2611
2612 if (mb->entries[j].state != dc->drag.lastEventState)
2613 CheckModifiers(dc, mb->entries[j].state);
2614 if (dc->drag.currWmRoot != mb->entries[j].window) {
2615 /*
2616 * cause the callbacks to get called so the client can
2617 * change the dragOver visuals
2618 */
2619 DragMotionProto(dc, mb->entries[j].window, None);
2620 protoWindow = None;
2621 }
2622 else
2623 protoWindow = mb->entries[j].subwindow;
2624
2625 }
2626 _XmDragOverMove((Widget)dc->drag.curDragOver, dc->core.x, dc->core.y);
2627
2628 /* if the protoWindow gotten above is the drag window,
2629 * we can use XTranslateCoordinates to look through the
2630 * one pixel hole (which has just been moved to be under where
2631 * the pointer was), and determine what real window we are over
2632 */
2633 if (protoWindow == XtWindow(dc->drag.curDragOver))
2634 {
2635 Window currRoot = dc->drag.currWmRoot;
2636 int dummyx, dummyy;
2637
2638 (void) XTranslateCoordinates(XtDisplay(dc), currRoot, currRoot,
2639 dc->core.x, dc->core.y,
2640 &dummyx, &dummyy,
2641 &protoWindow);
2642 }
2643
2644 /*
2645 * actually inform the receiver/initiator that movement has
2646 * occurred
2647 */
2648 DragMotionProto(dc, dc->drag.currWmRoot, protoWindow);
2649
2650 if (mb->count > STACKMOTIONBUFFERSIZE)
2651 XtFree( (char *)mb);
2652 }
2653
2654 #define IsGrabEvent(ev) \
2655 ((ev->type == ButtonPress) ||\
2656 (ev->type == ButtonRelease) ||\
2657 (ev->type == KeyPress) ||\
2658 (ev->type == KeyRelease))
2659
2660 /* ARGSUSED */
2661 static void
DragMotion(Widget w,XEvent * event,String * params,Cardinal * numParams)2662 DragMotion(
2663 Widget w,
2664 XEvent *event,
2665 String *params,
2666 Cardinal *numParams )
2667 {
2668 XmDragContext dc = (XmDragContext)w;
2669 MotionBufferRec stackBuffer;
2670 MotionBuffer motionBuffer = &stackBuffer;
2671 Boolean grabEvent = False;
2672
2673 stackBuffer.count = 0;
2674 stackBuffer.currReceiverInfo = dc->drag.currReceiverInfo;
2675 UpdateMotionBuffer(dc, motionBuffer,event);
2676
2677 /*
2678 * We need to process all outstanding events of interest
2679 * inline and flush out any stale motion events. Need to
2680 * check for state change events like modifier or button press.
2681 */
2682
2683 /*
2684 * get any that came in after
2685 */
2686 while (!grabEvent &&
2687 XCheckMaskEvent(XtDisplayOfObject((Widget) w),
2688 _XmDRAG_EVENT_MASK(dc),
2689 event)) {
2690 grabEvent = IsGrabEvent(event);
2691 if (!grabEvent) {
2692 if (dc->drag.trackingMode != XmDRAG_TRACK_MOTION)
2693 event->xmotion.subwindow = event->xmotion.window;
2694 UpdateMotionBuffer(dc, motionBuffer, event);
2695 }
2696 else
2697 XPutBackEvent(XtDisplay(dc), event);
2698 }
2699 ProcessMotionBuffer(dc, motionBuffer);
2700 XFlush(XtDisplayOfObject((Widget) dc));
2701 }
2702
2703 /* ARGSUSED */
2704 static void
DragKey(Widget w,XEvent * event,String * params,Cardinal * numParams)2705 DragKey(
2706 Widget w,
2707 XEvent *event,
2708 String *params,
2709 Cardinal *numParams )
2710 {
2711 char *direction;
2712 int dx, dy;
2713 XKeyEvent *keyevent = (XKeyEvent *) event;
2714 XEvent motionEvent;
2715 XmDisplay dd;
2716 unsigned int state = 0;
2717
2718 dd = (XmDisplay) XtParent(w);
2719
2720 direction = params[0];
2721
2722 if (event == NULL) return;
2723
2724 if (strcmp(direction, "Up") == 0)
2725 { dx = 0; dy = -1; }
2726 else if (strcmp(direction, "Down") == 0)
2727 { dx = 0; dy = 1; }
2728 else if (strcmp(direction, "Left") == 0)
2729 { dx = -1; dy = 0; }
2730 else if (strcmp(direction, "Right") == 0)
2731 { dx = 1; dy = 0; }
2732 else { /* Update on modifier key changes */
2733 dx = 0; dy = 0;
2734 if (event -> type == KeyPress)
2735 state = keyevent -> state;
2736 }
2737
2738 if (keyevent -> state & ControlMask)
2739 { dx *= 16; dy *= 16; }
2740
2741 if (dd -> display.enable_warp == False) {
2742 dx = 0; dy = 0;
2743 } else {
2744 XWarpPointer(XtDisplay(w), None, None, 0, 0, 0, 0, dx, dy);
2745 }
2746
2747 /* Send a button2 motion event so that the drag
2748 feedback will happen within DragMotion */
2749 motionEvent.xmotion.type = MotionNotify;
2750 motionEvent.xmotion.window = keyevent -> window;
2751 motionEvent.xmotion.subwindow = keyevent -> subwindow;
2752 motionEvent.xmotion.time = keyevent -> time;
2753 motionEvent.xmotion.root = keyevent -> root;
2754 motionEvent.xmotion.x = XtX(w) + dx;
2755 motionEvent.xmotion.y = XtY(w) + dy;
2756 motionEvent.xmotion.x_root = keyevent -> x_root;
2757 motionEvent.xmotion.y_root = keyevent -> y_root;
2758 motionEvent.xmotion.same_screen = keyevent -> same_screen;
2759
2760 /* Or in the modifier bits if this is an update */
2761 motionEvent.xmotion.state = Button2Mask | state;
2762 motionEvent.xmotion.is_hint = 0;
2763
2764 DragMotion(w, (XEvent *) &motionEvent, NULL, 0);
2765 }
2766
2767 /*ARGSUSED*/
2768 static void
DropStartTimeout(XtPointer clientData,XtIntervalId * id)2769 DropStartTimeout(
2770 XtPointer clientData,
2771 XtIntervalId *id )
2772 {
2773 XmDragContext dc = (XmDragContext)clientData;
2774 XmDropStartCallbackStruct callbackRec, *callback = &callbackRec;
2775 XmDropSiteManagerObject dsm = (XmDropSiteManagerObject)
2776 _XmGetDropSiteManagerObject((XmDisplay)(XtParent(dc)));
2777
2778 if (dc->drag.dropStartCallback) {
2779 callback->reason = XmCR_DROP_START;
2780 callback->event = NULL;
2781 callback->timeStamp = dc->drag.dragFinishTime;
2782 callback->operation = dc->drag.operation;
2783 callback->operations = dc->drag.operations;
2784 callback->dropAction = XmDROP_CANCEL;
2785 callback->dropSiteStatus = dsm->dropManager.curDropSiteStatus;
2786 callback->x = dc->core.x;
2787 callback->y = dc->core.y;
2788 callback->iccHandle = dc->drag.iccHandle;
2789 callback->window = XtWindow(dc->drag.srcShell);
2790 XtCallCallbackList((Widget)dc, dc->drag.dropStartCallback, callback);
2791 dc->drag.dragCompletionStatus = callback->dropAction;
2792 dsm->dropManager.curDropSiteStatus = callback->dropSiteStatus;
2793 }
2794 dc->drag.dragDropCompletionStatus = XmDROP_FAILURE;
2795 dc->drag.dropFinishTime = dc->drag.dragFinishTime;
2796
2797 DragDropFinish(dc);
2798 }
2799
2800 /*ARGSUSED*/
2801 static void
DropFinishTimeout(XtPointer clientData,XtIntervalId * id)2802 DropFinishTimeout(
2803 XtPointer clientData,
2804 XtIntervalId *id )
2805 {
2806 XmDragContext dc = (XmDragContext)clientData;
2807
2808 dc->drag.dragDropCompletionStatus = XmDROP_FAILURE;
2809 dc->drag.dropFinishTime = dc->drag.dragFinishTime;
2810
2811 DragDropFinish(dc);
2812 }
2813
2814 /*ARGSUSED*/
2815 static void
FinishAction(XmDragContext dc,XEvent * ev)2816 FinishAction(
2817 XmDragContext dc,
2818 XEvent *ev )
2819 {
2820 unsigned int state = 0;
2821 Arg args[4];
2822 Cardinal i = 0;
2823 XmDisplay dd = (XmDisplay) XmGetXmDisplay(XtDisplay(dc));
2824
2825 dd->display.activeDC = NULL;
2826 dd->display.userGrabbed = False;
2827
2828 if (ev) {
2829 switch(ev->type) {
2830 case ButtonRelease:
2831 state = ev->xbutton.state;
2832 dc->drag.lastChangeTime = ev->xbutton.time;
2833 dc->core.x = ev->xbutton.x_root;
2834 dc->core.y = ev->xbutton.y_root;
2835 break;
2836 case KeyPress:
2837 state = ev->xkey.state;
2838 dc->drag.lastChangeTime = ev->xkey.time;
2839 dc->core.x = ev->xkey.x_root;
2840 dc->core.y = ev->xkey.y_root;
2841 break;
2842 }
2843
2844 /*
2845 * start out with the default operations in effective operations
2846 */
2847 dc->drag.lastEventState = state;
2848 CalculateDragOperation(dc);
2849 }
2850
2851 /*
2852 * change the dragOver to a window in so it can persist after the
2853 * ungrab
2854 */
2855 if (dc->drag.curDragOver) {
2856 unsigned char currentMode;
2857 unsigned char currentActiveMode;
2858
2859 XtSetArg(args[0], XmNdragOverMode, ¤tMode);
2860 XtSetArg(args[1], XmNdragOverActiveMode, ¤tActiveMode);
2861 XtGetValues((Widget) dc->drag.curDragOver, args, 2);
2862
2863 i = 0;
2864 XtSetArg(args[i], XmNhotX, dc->core.x); i++;
2865 XtSetArg(args[i], XmNhotY, dc->core.y); i++;
2866 if (currentActiveMode == XmCURSOR ||
2867 (currentMode != XmDRAG_WINDOW && currentMode != XmWINDOW) ) {
2868 XtSetArg(args[i], XmNdragOverMode, XmWINDOW); i++;
2869 }
2870 XtSetValues((Widget) dc->drag.curDragOver, args, i);
2871
2872 XUngrabPointer(XtDisplayOfObject((Widget) dc), dc->drag.lastChangeTime);
2873 XtUngrabPointer((Widget) dc, dc->drag.dragFinishTime);
2874 XUngrabKeyboard(XtDisplayOfObject((Widget) dc), dc->drag.lastChangeTime);
2875
2876 _XmRemoveGrab((Widget)dc);
2877 }
2878
2879 if (dc->drag.serverGrabbed)
2880 XUngrabServer(XtDisplay((Widget) dc));
2881 /*
2882 * if we're in pre-register with a non-local raeceiver then we need
2883 * to flush a top-level leave to the local dsm.
2884 */
2885 dc->drag.dragFinishTime = dc->drag.lastChangeTime;
2886
2887 if (dc->drag.inDropSite) {
2888 GenerateClientCallback(dc, XmCR_DROP_SITE_LEAVE);
2889 dc->drag.inDropSite = False;
2890 }
2891
2892 if (dc->drag.currReceiverInfo) {
2893 if (dc->drag.currReceiverInfo->window) {
2894 SendDragMessage(dc, dc->drag.currReceiverInfo->window,
2895 XmTOP_LEVEL_LEAVE);
2896 GenerateClientCallback(dc, XmCR_TOP_LEVEL_LEAVE);
2897
2898 if ((dc->drag.activeProtocolStyle != XmDRAG_NONE) &&
2899 ((dc->drag.dragCompletionStatus == XmDROP) ||
2900 (dc->drag.dragCompletionStatus == XmDROP_HELP))) {
2901
2902 XtAppContext appContext= XtWidgetToApplicationContext((Widget)dc);
2903 /*
2904 * we send the leave message in the dragDropFinish so
2905 * that a non-local receiver can cleanup its dc
2906 */
2907 dc->drag.dragTimerId =
2908 XtAppAddTimeOut(appContext,
2909 XtAppGetSelectionTimeout(appContext),
2910 DropStartTimeout,
2911 (XtPointer)dc);
2912 SendDragMessage(dc, dc->drag.currReceiverInfo->window,
2913 XmDROP_START);
2914 }
2915 else {
2916 dc->drag.dragDropCompletionStatus = XmDROP_FAILURE;
2917 dc->drag.dropFinishTime = dc->drag.dragFinishTime;
2918 DropStartTimeout((XtPointer)dc, NULL);
2919 }
2920 }
2921 dc->drag.currReceiverInfo->frame = 0;
2922 } else {
2923 /* Cleanup anyway */
2924 DropStartTimeout((XtPointer)dc, NULL);
2925 }
2926 }
2927
2928
2929
2930 /* ARGSUSED */
2931 static void
CheckModifiers(XmDragContext dc,unsigned int state)2932 CheckModifiers(
2933 XmDragContext dc,
2934 unsigned int state)
2935 {
2936 unsigned char oldOperation = dc->drag.operation;
2937 unsigned char oldOperations = dc->drag.operations;
2938
2939 dc->drag.lastEventState = state;
2940 CalculateDragOperation(dc);
2941
2942 if ((oldOperations != dc->drag.operations) ||
2943 (oldOperation != dc->drag.operation)) {
2944 if ((dc->drag.currReceiverInfo->window) &&
2945 (dc->drag.activeProtocolStyle != XmDRAG_NONE) &&
2946 (dc->drag.activeProtocolStyle != XmDRAG_DROP_ONLY)) {
2947 SendDragMessage(dc,
2948 dc->drag.currReceiverInfo->window,
2949 XmOPERATION_CHANGED);
2950 }
2951 else {
2952 GenerateClientCallback(dc, XmCR_OPERATION_CHANGED);
2953 }
2954 }
2955 }
2956
2957 /* ARGSUSED */
2958 static void
IgnoreButtons(Widget w,XEvent * event,String * params,Cardinal * numParams)2959 IgnoreButtons(
2960 Widget w,
2961 XEvent *event,
2962 String *params,
2963 Cardinal *numParams )
2964 {
2965 XmDragContext dc = (XmDragContext)w;
2966
2967 /*
2968 * the user has pressed some other buttons and caused the server
2969 * to synch up. Swallow and continue
2970 */
2971
2972 XAllowEvents(XtDisplayOfObject((Widget) dc->drag.srcShell),
2973 SyncPointer,
2974 dc->drag.lastChangeTime);
2975 }
2976
2977 /* ARGSUSED */
2978 static void
CancelDrag(Widget w,XEvent * event,String * params,Cardinal * numParams)2979 CancelDrag(
2980 Widget w,
2981 XEvent *event,
2982 String *params,
2983 Cardinal *numParams )
2984 {
2985 XmDragContext dc = (XmDragContext)w;
2986
2987 /*
2988 * only cancel if drag has not yet completed
2989 */
2990 if (dc->drag.dragFinishTime == 0) {
2991 dc->drag.dragCompletionStatus = XmDROP_CANCEL;
2992 FinishAction(dc, event);
2993 }
2994 }
2995
2996 /* ARGSUSED */
2997 static void
HelpDrag(Widget w,XEvent * event,String * params,Cardinal * numParams)2998 HelpDrag(
2999 Widget w,
3000 XEvent *event,
3001 String *params,
3002 Cardinal *numParams )
3003 {
3004 XmDragContext dc = (XmDragContext)w;
3005
3006 dc->drag.dragCompletionStatus = XmDROP_HELP;
3007 FinishAction(dc, event);
3008 }
3009
3010
3011 /* ARGSUSED */
3012 static void
FinishDrag(Widget w,XEvent * event,String * params,Cardinal * numParams)3013 FinishDrag(
3014 Widget w,
3015 XEvent *event,
3016 String *params,
3017 Cardinal *numParams )
3018 {
3019 XmDragContext dc = (XmDragContext)w;
3020
3021 dc->drag.dragCompletionStatus = XmDROP;
3022 FinishAction(dc, event);
3023 }
3024
3025 static void
noMoreShell(Widget w,XtPointer client,XtPointer call)3026 noMoreShell(
3027 Widget w,
3028 XtPointer client,
3029 XtPointer call)
3030 {
3031 Boolean *contAction = (Boolean *)client;
3032 *contAction = False;
3033 }
3034
3035
3036 /*ARGSUSED*/
3037 static void
InitiatorMainLoop(XtPointer clientData,XtIntervalId * id)3038 InitiatorMainLoop(
3039 XtPointer clientData,
3040 XtIntervalId *id )
3041 {
3042 XmDragContext *activeDC = (XmDragContext *)clientData;
3043 XtAppContext appContext;
3044 XEvent event;
3045 Widget focusWidget, shell;
3046 Boolean contAction = True;
3047
3048 if (*activeDC) {
3049 appContext = XtWidgetToApplicationContext((Widget) *activeDC);
3050 shell = (*activeDC)->drag.srcShell;
3051 focusWidget = XmGetFocusWidget((Widget)((*activeDC)->drag.srcShell));
3052 if (_XmGetFocusPolicy(shell) == XmEXPLICIT) {
3053 XtSetKeyboardFocus(shell, None);
3054 } else {
3055 XmFocusData focusData = _XmGetFocusData(shell);
3056 if(focusData)
3057 focusData->needToFlush = False;
3058 /* CR 6384, check for null focusWidget */
3059 if (focusWidget != (Widget) NULL) {
3060 if (XmIsPrimitive(focusWidget)) {
3061 if (((XmPrimitiveWidgetClass) XtClass(focusWidget))
3062 ->primitive_class.border_unhighlight)
3063 (*(((XmPrimitiveWidgetClass) XtClass(focusWidget))
3064 ->primitive_class.border_unhighlight))(focusWidget);
3065 } else if (XmIsGadget(focusWidget)) {
3066 if (((XmGadgetClass) XtClass(focusWidget))
3067 ->gadget_class.border_unhighlight)
3068 (*(((XmGadgetClass) XtClass(focusWidget))
3069 ->gadget_class.border_unhighlight))(focusWidget);
3070 }
3071 }
3072 }
3073 DragStartProto(*activeDC);
3074 }
3075 else return;
3076
3077 XtAddCallback (shell, XmNdestroyCallback, noMoreShell,
3078 (XtPointer)&contAction);
3079
3080 while ( (*activeDC) && (XtAppGetExitFlag(appContext) == False) ) {
3081 XmDragContext dc = *activeDC;
3082 #ifdef XTHREADS
3083 XtInputMask mask;
3084
3085 while(!(mask = XtAppPending(appContext)))
3086 ; /* busy wait */
3087 if (mask & XtIMXEvent)
3088 {
3089 #endif
3090 XtAppNextEvent(appContext, &event);
3091 /*
3092 * make sure evil Focus outs don't confuse Xt and cause the
3093 * unhighlighting of the source hierarchy.
3094 */
3095 switch(event.type) {
3096 case FocusIn:
3097 case FocusOut:
3098 break;
3099 case KeyPress:
3100 case KeyRelease:
3101 case ButtonPress:
3102 case ButtonRelease:
3103 case EnterNotify:
3104 case LeaveNotify:
3105 case MotionNotify:
3106 {
3107 /* dispatch it onto the dc */
3108 switch(dc->drag.trackingMode) {
3109 case XmDRAG_TRACK_MOTION:
3110 break;
3111 #ifdef MULTI_SCREEN_DONE
3112 case XmDRAG_TRACK_WM_QUERY:
3113 event.xmotion.subwindow = event.xmotion.window;
3114 break;
3115 #endif /* MULTI_SCREEN_DONE */
3116 case XmDRAG_TRACK_WM_QUERY_PENDING:
3117 event.xmotion.subwindow = event.xmotion.window;
3118 break;
3119 }
3120 }
3121 event.xmotion.window = XtWindow(dc);
3122 break;
3123 }
3124
3125 if ((event.type == MotionNotify ||
3126 event.type == LeaveNotify ||
3127 event.type == EnterNotify) &&
3128 event.xmotion.state == dc->drag.lastEventState)
3129 DragMotion((Widget)dc, &event, NULL, 0);
3130 else
3131 XtDispatchEvent(&event);
3132 #ifdef XTHREADS
3133 }
3134 else
3135 XtAppProcessEvent(appContext, mask);
3136 #endif
3137 }
3138 /* guard against the possibility that shell was destroyed in the last event
3139 * loop while the drag operation was going on (e.g. by a timer)
3140 */
3141 if (contAction) {
3142 XtRemoveCallback (shell, XmNdestroyCallback, noMoreShell,
3143 (XtPointer)&contAction);
3144 if (_XmGetFocusPolicy(shell) == XmEXPLICIT) {
3145 XtSetKeyboardFocus(shell, focusWidget);
3146 }
3147 }
3148 }
3149
3150
3151
3152 Widget
XmDragStart(Widget w,XEvent * event,ArgList args,Cardinal numArgs)3153 XmDragStart(
3154 Widget w,
3155 XEvent *event,
3156 ArgList args,
3157 Cardinal numArgs )
3158 {
3159 XmDragContext dc;
3160 XmDisplay dd = (XmDisplay) XmGetXmDisplay(XtDisplay(w));
3161 Arg lclArgs[1];
3162 Arg *mergedArgs;
3163 XmDragStartCallbackStruct cb;
3164 _XmWidgetToAppContext(w);
3165
3166 _XmAppLock(app);
3167 if (dd->display.dragInitiatorProtocolStyle == XmDRAG_NONE) {
3168 _XmAppUnlock(app);
3169 return(NULL);
3170 }
3171
3172 if (event->type != ButtonPress &&
3173 event->type != ButtonRelease &&
3174 event->type != KeyRelease &&
3175 event->type != KeyPress &&
3176 event->type != MotionNotify ) {
3177 XmeWarning(w, MESSAGE6);
3178 _XmAppUnlock(app);
3179 return NULL;
3180 }
3181
3182 cb.reason = XmCR_DRAG_START;
3183 cb.event = event;
3184 cb.widget = w;
3185 cb.doit = True;
3186 XtCallCallbackList((Widget)dd, dd->display.dragStartCallback,
3187 (XtPointer) &cb);
3188
3189 if (!cb.doit) {
3190 _XmAppUnlock(app);
3191 return NULL;
3192 }
3193
3194 /*
3195 * check if the menu system is already active
3196 */
3197 if (dd->display.userGrabbed) {
3198 #ifdef DEBUG
3199 Warning("can't drag; menu system active\n");
3200 #endif
3201 _XmAppUnlock(app);
3202 return NULL;
3203 }
3204
3205 XtSetArg(lclArgs[0], XmNsourceWidget, w);
3206
3207 if (numArgs) {
3208 mergedArgs = XtMergeArgLists(args, numArgs, lclArgs, 1);
3209 }
3210 else {
3211 mergedArgs = lclArgs;
3212 }
3213 dc = (XmDragContext)
3214 XtCreateWidget("dragContext", xmDragContextClass,
3215 (Widget) dd, mergedArgs, numArgs + 1);
3216 XtAddCallback(w, XmNdestroyCallback, cancelDrag, (XtPointer)dc);
3217 _XmDragStart(dc, w, event);
3218
3219 if (numArgs)
3220 XtFree( (char *)mergedArgs);
3221 _XmAppUnlock(app);
3222 return (Widget)dc;
3223 }
3224
3225
3226 static void
DragCancel(XmDragContext dc)3227 DragCancel(
3228 XmDragContext dc )
3229 {
3230 dc->drag.dragCompletionStatus = XmDROP_CANCEL;
3231 FinishAction(dc, NULL);
3232 }
3233
3234 void
XmDragCancel(Widget dragContext)3235 XmDragCancel(
3236 Widget dragContext )
3237 {
3238 _XmWidgetToAppContext(dragContext);
3239 _XmAppLock(app);
3240 DragCancel((XmDragContext)dragContext);
3241 _XmAppUnlock(app);
3242 }
3243
3244
3245 /*ARGSUSED*/
3246 Boolean
XmTargetsAreCompatible(Display * dpy,Atom * exportTargets,Cardinal numExportTargets,Atom * importTargets,Cardinal numImportTargets)3247 XmTargetsAreCompatible(
3248 Display *dpy,
3249 Atom *exportTargets,
3250 Cardinal numExportTargets,
3251 Atom *importTargets,
3252 Cardinal numImportTargets )
3253 {
3254 Cardinal j, k;
3255 _XmDisplayToAppContext(dpy);
3256
3257 _XmAppLock(app);
3258 for (j = 0; j < numExportTargets; j++)
3259 for (k = 0; k < numImportTargets; k++)
3260 if (exportTargets[j] == importTargets[k]) {
3261 _XmAppUnlock(app);
3262 return True;
3263 }
3264 _XmAppUnlock(app);
3265 return False;
3266 }
3267
3268
3269 unsigned char
_XmGetActiveProtocolStyle(Widget w)3270 _XmGetActiveProtocolStyle(
3271 Widget w )
3272 {
3273 unsigned char initiator = XmDRAG_NONE,
3274 receiver = XmDRAG_NONE,
3275 active = XmDRAG_NONE;
3276 XmDragContext dc = (XmDragContext)w;
3277 XmDisplay xmDisplay = (XmDisplay)XtParent(dc);
3278
3279 initiator = xmDisplay->display.dragInitiatorProtocolStyle;
3280 receiver = xmDisplay->display.dragReceiverProtocolStyle;
3281
3282 if (!dc->drag.sourceIsExternal)
3283 {
3284 /* We are the initiator. Find the receiver. */
3285 if (dc->drag.currReceiverInfo)
3286 {
3287 receiver = dc->drag.currReceiverInfo->dragProtocolStyle;
3288 }
3289 else
3290 {
3291 /*
3292 * This function is sometimes called before we have
3293 * set up the receiver info struct on the dc. In these
3294 * cases, we are still in the initiating client, and so
3295 * we will use the initiating client's receiver protocol
3296 * style. In order to do this we have to emulate the
3297 * protocol style decision made in GetDestinationInfo.
3298 * But we can't, since we don't really know the shell
3299 * widget--the particular shell widget may not have a dnd
3300 * property attached to it.
3301 *
3302 * There are a number of different guesses that we could
3303 * make. None of them is substantially better than
3304 * not guessing at all. Not guessing only messes up if the
3305 * shell really doesn't have any drop sites--we should be
3306 * returning NONE, but we might return something else.
3307 */
3308 /*EMPTY*/
3309 }
3310
3311 active = protocolMatrix[initiator][receiver];
3312 }
3313 else
3314 {
3315 /* We are the receiver, so we can't be preregister. (Since
3316 * the receiver doesn't hear about the drag during the drag,
3317 * and so get ACTIVE protocol makes no sense.)
3318 */
3319 switch(receiver)
3320 {
3321 case XmDRAG_NONE:
3322 active = XmDRAG_NONE;
3323 break;
3324 case XmDRAG_DROP_ONLY:
3325 /* this must be post drop emulation of drag */
3326 case XmDRAG_PREREGISTER:
3327 case XmDRAG_DYNAMIC:
3328 case XmDRAG_PREFER_DYNAMIC:
3329 case XmDRAG_PREFER_PREREGISTER:
3330 case XmDRAG_PREFER_RECEIVER:
3331 active = XmDRAG_DYNAMIC;
3332 break;
3333 }
3334 }
3335 return active;
3336 }
3337
3338 static void
CalculateDragOperation(XmDragContext dc)3339 CalculateDragOperation(XmDragContext dc)
3340 {
3341 /*
3342 * Re-set to the initial settings of operation and operations
3343 */
3344 dc->drag.operations = dc->drag.dragOperations;
3345 if ((dc->drag.lastEventState & ShiftMask) &&
3346 (dc->drag.lastEventState & ControlMask)) {
3347 dc->drag.operations =
3348 dc->drag.operation = (unsigned char)
3349 (XmDROP_LINK & dc->drag.dragOperations);
3350 }
3351 else if (dc->drag.lastEventState & ShiftMask) {
3352 dc->drag.operations =
3353 dc->drag.operation = (unsigned char)
3354 (XmDROP_MOVE & dc->drag.dragOperations);
3355 }
3356 else if (dc->drag.lastEventState & ControlMask) {
3357 dc->drag.operations =
3358 dc->drag.operation = (unsigned char)
3359 (XmDROP_COPY & dc->drag.dragOperations);
3360 }
3361 else if (XmDROP_MOVE &dc->drag.dragOperations)
3362 dc->drag.operation = (unsigned char)XmDROP_MOVE;
3363 else if (XmDROP_COPY &dc->drag.dragOperations)
3364 dc->drag.operation = (unsigned char)XmDROP_COPY;
3365 else if (XmDROP_LINK &dc->drag.dragOperations)
3366 dc->drag.operation = (unsigned char)XmDROP_LINK;
3367 else {
3368 dc->drag.operations = dc->drag.operation = 0;
3369 }
3370 }
3371