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[] = "$XConsortium: DragUnder.c /main/12 1995/07/14 10:26:51 drk $"
26 #endif
27 #endif
28 
29 #ifdef HAVE_CONFIG_H
30 #include <config.h>
31 #endif
32 
33 
34 #include <Xm/DrawP.h>
35 #include "XmI.h"
36 #include "DragCI.h"
37 #include "DragICCI.h"
38 #include "DragOverSI.h"
39 #include "DragUnderI.h"
40 #include "DropSMgrI.h"
41 #include "GadgetUtiI.h"
42 #include "MessagesI.h"
43 #include "RegionI.h"
44 #include "ScreenI.h"
45 
46 #define MESSAGE1	_XmMMsgDragUnder_0000
47 #define MESSAGE2	_XmMMsgDragUnder_0001
48 
49 /********    Static Function Declarations    ********/
50 
51 static XmAnimationSaveData CreateAnimationSaveData(
52                         XmDragContext dc,
53                         XmAnimationData aData,
54                         XmDragProcCallbackStruct *dpcb) ;
55 static void FreeAnimationData(
56                         XmAnimationSaveData aSaveData) ;
57 static Boolean SaveAll(
58                         XmAnimationSaveData aSaveData,
59                         Position x,
60                         Position y,
61                         Dimension width,
62                         Dimension height) ;
63 static Boolean SaveSegments(
64                         XmAnimationSaveData aSaveData,
65                         Position x,
66                         Position y,
67                         Dimension width,
68                         Dimension height,
69                         Dimension *thickness) ;
70 static void DrawHighlight(
71                         XmAnimationSaveData aSaveData) ;
72 static void DrawShadow(
73                         XmAnimationSaveData aSaveData) ;
74 static void DrawPixmap(
75                         XmAnimationSaveData aSaveData) ;
76 static void AnimateExpose(Widget w, XmAnimationSaveData aSaveData,
77                           XEvent *event,
78                           Boolean *cont);
79 static void AnimateEnter(
80                         XmDropSiteManagerObject dsm,
81                         XmAnimationData aData,
82                         XmDragProcCallbackStruct *dpcb) ;
83 static void AnimateLeave(
84                         XmDropSiteManagerObject dsm,
85                         XmAnimationData aData,
86                         XmDragProcCallbackStruct *dpcb) ;
87 
88 /********    End Static Function Declarations    ********/
89 
90 
91 /*****************************************************************************
92  *
93  *  CreateAnimationSaveData ()
94  *
95  *  Create and fill an XmAnimationSaveData structure containing the data
96  *  needed to animate the dropsite.
97  ***************************************************************************/
98 
99 /*ARGSUSED*/
100 static XmAnimationSaveData
CreateAnimationSaveData(XmDragContext dc,XmAnimationData aData,XmDragProcCallbackStruct * dpcb)101 CreateAnimationSaveData(
102         XmDragContext dc,
103         XmAnimationData aData,
104         XmDragProcCallbackStruct *dpcb ) /* unused */
105 {
106     XmAnimationSaveData		aSaveData;
107     XGCValues			v;
108     unsigned long		vmask;
109     XmDropSiteVisuals		dsv;
110     int				ac;
111     Arg				al[5];
112     Window			junkWin;
113     int				junkInt;
114     unsigned int		junkUInt;
115     unsigned char		activeMode;
116 
117     aSaveData = (XmAnimationSaveData)
118 	XtMalloc (sizeof (XmAnimationSaveDataRec));
119 
120     aSaveData->dragOver = aData->dragOver;
121     aSaveData->display = XtDisplay (dc);
122     aSaveData->xmScreen = (XmScreen) XmGetXmScreen (aData->screen);
123 
124     aSaveData->window = aData->window;
125     aSaveData->windowX = aData->windowX;
126     aSaveData->windowY = aData->windowY;
127 
128     if (aSaveData->dragOver) {
129         aSaveData->xmScreen = (XmScreen) XmGetXmScreen (XtScreen (aSaveData->dragOver));
130     }
131     else {
132         aSaveData->xmScreen = (XmScreen) XmGetXmScreen(XtScreen (dc));
133     }
134 
135     /*
136      *  Get the window depth.
137      */
138 
139     if (!XGetGeometry (aSaveData->display, aSaveData->window,
140 		       &junkWin, &junkInt, &junkInt,
141 		       &junkUInt, &junkUInt, &junkUInt,
142                        &(aSaveData->windowDepth))) {
143 	XmeWarning ((Widget) dc, MESSAGE1);
144         aSaveData->windowDepth = 0;
145     }
146 
147     aSaveData->clipRegion = aData->clipRegion;
148     aSaveData->dropSiteRegion = aData->dropSiteRegion;
149 
150     dsv = XmDropSiteGetActiveVisuals ((Widget) dc);
151     aSaveData->background = dsv->background;
152     aSaveData->foreground = dsv->foreground;
153     aSaveData->topShadowColor = dsv->topShadowColor;
154     aSaveData->topShadowPixmap = dsv->topShadowPixmap;
155     aSaveData->bottomShadowColor = dsv->bottomShadowColor;
156     aSaveData->bottomShadowPixmap = dsv->bottomShadowPixmap;
157     aSaveData->shadowThickness = dsv->shadowThickness;
158     aSaveData->highlightThickness = dsv->highlightThickness;
159     aSaveData->highlightColor = dsv->highlightColor;
160     aSaveData->highlightPixmap = dsv->highlightPixmap;
161     aSaveData->borderWidth = dsv->borderWidth;
162     XtFree ((char *)dsv);
163 
164     ac = 0;
165     XtSetArg (al[ac], XmNanimationStyle, &(aSaveData->animationStyle)); ac++;
166     XtSetArg (al[ac], XmNanimationMask, &(aSaveData->animationMask)); ac++;
167     XtSetArg (al[ac], XmNanimationPixmap, &(aSaveData->animationPixmap)); ac++;
168     XtSetArg (al[ac], XmNanimationPixmapDepth,
169 	      &(aSaveData->animationPixmapDepth)); ac++;
170     XmDropSiteRetrieve ((Widget) dc, al, ac);
171 
172     if (aSaveData->animationStyle == XmDRAG_UNDER_PIXMAP &&
173 	aSaveData->animationPixmap != None &&
174         aSaveData->animationPixmap != XmUNSPECIFIED_PIXMAP &&
175         aSaveData->animationPixmapDepth != 1 &&
176         aSaveData->animationPixmapDepth != aSaveData->windowDepth) {
177 
178 	XmeWarning ((Widget) dc, MESSAGE2);
179         aSaveData->animationPixmap = XmUNSPECIFIED_PIXMAP;
180     }
181 
182     /*
183      *  Create the draw GC.
184      */
185 
186     v.foreground = aSaveData->foreground;
187     v.background = aSaveData->background;
188     v.graphics_exposures = False;
189     v.subwindow_mode = IncludeInferiors;
190     vmask = GCGraphicsExposures|GCSubwindowMode|GCForeground|GCBackground;
191     aSaveData->drawGC =
192 	XCreateGC (aSaveData->display, aSaveData->window, vmask, &v);
193 
194     if (aSaveData -> dragOver != (Widget) NULL) {
195       /* Save info on active drag over mode */
196       XtSetArg(al[0], XmNdragOverActiveMode, &activeMode);
197       XtGetValues((Widget) aSaveData -> dragOver, al, 1);
198       aSaveData->activeMode = activeMode;
199     } else {
200       /* XmCURSOR is as good as any other value for here.  We only
201 	 check this against XmDRAG_WINDOW */
202       aSaveData->activeMode = XmCURSOR;
203     }
204 
205     /* initialize savedPixmaps list */
206     aSaveData->savedPixmaps = NULL;
207     aSaveData->numSavedPixmaps = 0;
208 
209     return (aSaveData);
210 }
211 
212 /*****************************************************************************
213  *
214  *  FreeAnimationData ()
215  *
216  *  Free an XmAnimationSaveData structure.
217  ***************************************************************************/
218 
219 static void
FreeAnimationData(XmAnimationSaveData aSaveData)220 FreeAnimationData(
221         XmAnimationSaveData aSaveData )
222 {
223     Cardinal	i;
224 
225     switch (aSaveData->animationStyle)
226     {
227         case XmDRAG_UNDER_SHADOW_IN:
228         case XmDRAG_UNDER_SHADOW_OUT:
229             XFreeGC (aSaveData->display, aSaveData->topShadowGC);
230             XFreeGC (aSaveData->display, aSaveData->bottomShadowGC);
231             XFreeGC (aSaveData->display, aSaveData->drawGC);
232         break;
233 
234         case XmDRAG_UNDER_HIGHLIGHT:
235             XFreeGC (aSaveData->display, aSaveData->highlightGC);
236             XFreeGC (aSaveData->display, aSaveData->drawGC);
237         break;
238 
239         case XmDRAG_UNDER_PIXMAP:
240             XFreeGC (aSaveData->display, aSaveData->drawGC);
241 
242         case XmDRAG_UNDER_NONE:
243         default:
244         break;
245     }
246 
247     if (aSaveData->numSavedPixmaps) {
248         for (i = 0; i < aSaveData->numSavedPixmaps; i++) {
249 	    _XmFreeScratchPixmap (aSaveData->xmScreen,
250 				  aSaveData->savedPixmaps[i].pixmap);
251         }
252         XtFree ((char *)aSaveData->savedPixmaps);
253     }
254 
255     XtFree ((char *)aSaveData);
256 }
257 
258 /*****************************************************************************
259  *
260  *  SaveAll ()
261  *
262  *  Save the original contents of a dropsite window that will be overwritten
263  *  by dropsite animation into a rectangular backing store.
264  ***************************************************************************/
265 
266 static Boolean
SaveAll(XmAnimationSaveData aSaveData,Position x,Position y,Dimension width,Dimension height)267 SaveAll(
268         XmAnimationSaveData aSaveData,
269         Position x,
270         Position y,
271         Dimension width,
272         Dimension height )
273 {
274     DragPixmapData	*pData;
275 
276     if (width <= 0 || height <= 0) {
277 	return (False);
278     }
279 
280     aSaveData->numSavedPixmaps = 1;
281     aSaveData->savedPixmaps = pData =
282         (DragPixmapData *) XtMalloc (sizeof(DragPixmapData));
283     if (!pData) {
284 	return (False);
285     }
286 
287     pData->x = x;
288     pData->y = y;
289     pData->width = width;
290     pData->height = height;
291     pData->pixmap =
292 	_XmAllocScratchPixmap (aSaveData->xmScreen,
293 			       (Cardinal) aSaveData->windowDepth,
294 		               pData->width, pData->height);
295     XCopyArea (aSaveData->display, aSaveData->window,
296     	       pData->pixmap, aSaveData->drawGC,
297                pData->x, pData->y,
298 	       pData->width, pData->height, 0, 0);
299 
300     return (True);
301 }
302 
303 /*****************************************************************************
304  *
305  *  SaveSegments ()
306  *
307  *  Save the original contents of a dropsite window that will be overwritten
308  *  by dropsite highlighting or shadowing of indicated thickness.  This will
309  *  save 0, 1, or 4 strips into backing store, depending on the dimensions
310  *  of the dropsite and the animation thickness.
311  ***************************************************************************/
312 
313 static Boolean
SaveSegments(XmAnimationSaveData aSaveData,Position x,Position y,Dimension width,Dimension height,Dimension * thickness)314 SaveSegments(
315         XmAnimationSaveData aSaveData,
316         Position x,
317         Position y,
318         Dimension width,
319         Dimension height,
320         Dimension *thickness )
321 {
322     DragPixmapData	*pData;
323     Boolean		save_all = False;
324 
325     if (width <= 0 || height <= 0 || *thickness <= 0) {
326         return (False);
327     }
328     if (*thickness > (width >> 1)) {
329         *thickness = (width >> 1);
330         save_all = True;
331     }
332     if (*thickness > (height >> 1)) {
333         *thickness = (height >> 1);
334         save_all = True;
335     }
336 
337     if (save_all) {
338         return (SaveAll (aSaveData, x, y, width, height));
339     }
340 
341     aSaveData->numSavedPixmaps = 4;
342     aSaveData->savedPixmaps = pData =
343 	    (DragPixmapData *) XtMalloc (sizeof(DragPixmapData) * 4);
344     if (!pData) {
345 	    return (False);
346     }
347 
348     pData->x = x;
349     pData->y = y;
350     pData->width = width;
351     pData->height = *thickness;
352     pData->pixmap =
353 	_XmAllocScratchPixmap (aSaveData->xmScreen,
354 			       (Cardinal) aSaveData->windowDepth,
355 		               pData->width, pData->height);
356     XCopyArea (aSaveData->display, aSaveData->window,
357     	       pData->pixmap, aSaveData->drawGC,
358                pData->x, pData->y,
359 	       pData->width, pData->height, 0, 0);
360 
361     pData++;
362     pData->x = x;
363     pData->y = y + *thickness;
364     pData->width = *thickness;
365     pData->height = height - (*thickness << 1);
366     pData->pixmap =
367 	_XmAllocScratchPixmap (aSaveData->xmScreen,
368 			       (Cardinal) aSaveData->windowDepth,
369 		               pData->width, pData->height);
370     XCopyArea (aSaveData->display, aSaveData->window,
371     	       pData->pixmap, aSaveData->drawGC,
372                pData->x, pData->y,
373 	       pData->width, pData->height, 0, 0);
374 
375     pData++;
376     pData->x = x;
377     pData->y = y + height - *thickness;
378     pData->width = width;
379     pData->height = *thickness;
380     pData->pixmap =
381 	_XmAllocScratchPixmap (aSaveData->xmScreen,
382 			       (Cardinal) aSaveData->windowDepth,
383 		               pData->width, pData->height);
384     XCopyArea (aSaveData->display, aSaveData->window,
385     	       pData->pixmap, aSaveData->drawGC,
386                pData->x, pData->y,
387 	       pData->width, pData->height, 0, 0);
388 
389     pData++;
390     pData->x = x + width - *thickness;
391     pData->y = y + *thickness;
392     pData->width = *thickness;
393     pData->height = height - (*thickness << 1);
394     pData->pixmap =
395 	_XmAllocScratchPixmap (aSaveData->xmScreen,
396 			       (Cardinal) aSaveData->windowDepth,
397 		               pData->width, pData->height);
398     XCopyArea (aSaveData->display, aSaveData->window,
399     	       pData->pixmap, aSaveData->drawGC,
400                pData->x, pData->y,
401 	       pData->width, pData->height, 0, 0);
402 
403     return (True);
404 }
405 
406 /*****************************************************************************
407  *
408  *  DrawHighlight ()
409  *
410  *  Draws a highlight around the indicated region.
411  ***************************************************************************/
412 
413 static void
DrawHighlight(XmAnimationSaveData aSaveData)414 DrawHighlight(
415         XmAnimationSaveData aSaveData )
416 {
417     XGCValues		v;
418     unsigned long	vmask;
419     Dimension		offset;
420     Position		x;
421     Position		y;
422     Dimension		width;
423     Dimension		height;
424     XRectangle		extents;
425 
426     /*
427      *  Create the highlightGC
428      */
429 
430     v.foreground = aSaveData->highlightColor;
431     v.background = aSaveData->background;
432     v.graphics_exposures = False;
433     v.subwindow_mode = IncludeInferiors;
434     vmask = GCGraphicsExposures|GCSubwindowMode|GCForeground|GCBackground;
435 
436     if (aSaveData->highlightPixmap != None &&
437 	aSaveData->highlightPixmap != XmUNSPECIFIED_PIXMAP) {
438 	int depth ;
439 
440 	XmeGetPixmapData(XtScreen(aSaveData->xmScreen),
441 			 aSaveData->highlightPixmap,
442 			 NULL,
443 			 &depth,
444 			 NULL, NULL, NULL, NULL, NULL, NULL);
445 
446 	if (depth == 1) {
447 	   v.fill_style = FillStippled;
448 	   v.stipple = aSaveData->highlightPixmap;
449 	   vmask |= GCStipple | GCFillStyle;
450        } else {
451 	   v.fill_style = FillTiled;
452 	   v.tile = aSaveData->highlightPixmap;
453 	   vmask |= GCTile | GCFillStyle;
454        }
455     }
456 
457     aSaveData->highlightGC =
458 	XCreateGC(aSaveData->display, aSaveData->window, vmask, &v);
459 
460     _XmRegionSetGCRegion (aSaveData->display, aSaveData->highlightGC,
461 			  0, 0, aSaveData->clipRegion);
462 
463     /* draw highlight */
464 
465     _XmRegionGetExtents (aSaveData->dropSiteRegion, &extents);
466     offset = aSaveData->borderWidth;
467 
468     if (_XmRegionGetNumRectangles(aSaveData->dropSiteRegion) == 1L) {
469 
470         x = extents.x + offset;
471         y = extents.y + offset;
472         width = extents.width - (offset << 1);
473         height = extents.height - (offset << 1);
474 
475         if (SaveSegments (aSaveData, x, y, width, height,
476                           &aSaveData->highlightThickness)) {
477             XmeDrawHighlight (aSaveData->display, aSaveData->window,
478 				    aSaveData->highlightGC,
479 				    x, y, width, height,
480 				    aSaveData->highlightThickness);
481         }
482     }
483     else {
484         if (SaveAll (aSaveData, extents.x, extents.y, extents.width,
485 		     extents.height)) {
486             _XmRegionDrawShadow (aSaveData->display, aSaveData->window,
487 		                 aSaveData->highlightGC, aSaveData->highlightGC,
488                                  aSaveData->dropSiteRegion,
489                                  offset, aSaveData->highlightThickness,
490 				 XmSHADOW_OUT);
491 	}
492     }
493 }
494 
495 /*****************************************************************************
496  *
497  *  DrawShadow ()
498  *
499  *  Draws a 3-D shadow around the indicated region.
500  ***************************************************************************/
501 
502 static void
DrawShadow(XmAnimationSaveData aSaveData)503 DrawShadow(
504         XmAnimationSaveData aSaveData )
505 {
506     XGCValues		v;
507     unsigned long	vmask;
508     Dimension		offset;
509     Position		x;
510     Position		y;
511     Dimension		width;
512     Dimension		height;
513     XRectangle		extents;
514 
515     /*
516      *  Create the topShadowGC
517      */
518 
519     v.foreground = aSaveData->topShadowColor;
520     v.background = aSaveData->foreground;
521     v.graphics_exposures = False;
522     v.subwindow_mode = IncludeInferiors;
523     vmask = GCGraphicsExposures|GCSubwindowMode|GCForeground|GCBackground;
524 
525     if (aSaveData->topShadowPixmap != None &&
526         aSaveData->topShadowPixmap != XmUNSPECIFIED_PIXMAP) {
527 	int depth ;
528 
529 	XmeGetPixmapData(XtScreen(aSaveData->xmScreen),
530 			 aSaveData->topShadowPixmap,
531 			 NULL,
532 			 &depth,
533 			 NULL, NULL, NULL, NULL, NULL, NULL);
534 
535 	if (depth == 1) {
536 	   v.fill_style = FillStippled;
537 	   v.stipple = aSaveData->topShadowPixmap;
538 	   vmask |= GCStipple | GCFillStyle;
539        } else {
540 	   v.fill_style = FillTiled;
541 	   v.tile = aSaveData->topShadowPixmap;
542 	   vmask |= GCTile | GCFillStyle;
543        }
544     }
545 
546     aSaveData->topShadowGC =
547 	XCreateGC(aSaveData->display, aSaveData->window, vmask, &v);
548 
549     _XmRegionSetGCRegion (aSaveData->display, aSaveData->topShadowGC,
550 			  0, 0, aSaveData->clipRegion);
551 
552     /*
553      *  Create the bottomShadowGC
554      */
555 
556     v.foreground = aSaveData->bottomShadowColor;
557     v.background = aSaveData->foreground;
558     v.graphics_exposures = False;
559     v.subwindow_mode = IncludeInferiors;
560     vmask = GCGraphicsExposures|GCSubwindowMode|GCForeground|GCBackground;
561 
562     if (aSaveData->bottomShadowPixmap != None &&
563         aSaveData->bottomShadowPixmap != XmUNSPECIFIED_PIXMAP) {
564 		int depth ;
565 
566 	XmeGetPixmapData(XtScreen(aSaveData->xmScreen),
567 			 aSaveData->bottomShadowPixmap,
568 			 NULL,
569 			 &depth,
570 			 NULL, NULL, NULL, NULL, NULL, NULL);
571 
572 	if (depth == 1) {
573 	   v.fill_style = FillStippled;
574 	   v.stipple = aSaveData->bottomShadowPixmap;
575 	   vmask |= GCStipple | GCFillStyle;
576        } else {
577 	   v.fill_style = FillTiled;
578 	   v.tile = aSaveData->bottomShadowPixmap;
579 	   vmask |= GCTile | GCFillStyle;
580        }
581     }
582 
583 
584     aSaveData->bottomShadowGC =
585 	XCreateGC(aSaveData->display, aSaveData->window, vmask, &v);
586 
587     _XmRegionSetGCRegion (aSaveData->display, aSaveData->bottomShadowGC,
588 			  0, 0, aSaveData->clipRegion);
589 
590     /*
591      *  Draw the shadows.
592      */
593 
594     _XmRegionGetExtents (aSaveData->dropSiteRegion, &extents);
595     offset = aSaveData->borderWidth + aSaveData->highlightThickness;
596 
597     if (_XmRegionGetNumRectangles(aSaveData->dropSiteRegion) == 1L) {
598 
599         x = extents.x + offset;
600         y = extents.y + offset;
601         width = extents.width - (offset << 1);
602         height = extents.height - (offset << 1);
603 
604         if (SaveSegments (aSaveData, x, y, width, height,
605                           &aSaveData->shadowThickness)) {
606             XmeDrawShadows (aSaveData->display, aSaveData->window,
607 		             aSaveData->topShadowGC,
608                              aSaveData->bottomShadowGC,
609                              x, y, width, height,
610 		             aSaveData->shadowThickness,
611                              (aSaveData->animationStyle ==
612 				 XmDRAG_UNDER_SHADOW_IN) ?
613 		                     XmSHADOW_IN : XmSHADOW_OUT);
614         }
615     }
616     else {
617         if (SaveAll (aSaveData, extents.x, extents.y,
618 		     extents.width, extents.height)) {
619             _XmRegionDrawShadow (aSaveData->display, aSaveData->window,
620 		                 aSaveData->topShadowGC,
621 				 aSaveData->bottomShadowGC,
622                                  aSaveData->dropSiteRegion,
623 		                 offset, aSaveData->shadowThickness,
624                                  (aSaveData->animationStyle ==
625 				     XmDRAG_UNDER_SHADOW_IN) ?
626 		                         XmSHADOW_IN : XmSHADOW_OUT);
627 	}
628     }
629 }
630 
631 /*****************************************************************************
632  *
633  *  DrawPixmap ()
634  *
635  *  Copy an animationPixmap, possibly masked, to the dropsite window.
636  ***************************************************************************/
637 
638 static void
DrawPixmap(XmAnimationSaveData aSaveData)639 DrawPixmap(
640         XmAnimationSaveData aSaveData )
641 {
642     Position		x;
643     Position		y;
644     Dimension		width;
645     Dimension		height;
646     XRectangle		extents;
647     XGCValues		v;
648     unsigned long       vmask;
649     Pixmap		mask = XmUNSPECIFIED_PIXMAP;
650     GC			maskGC = NULL;
651 
652     if (aSaveData->animationPixmap == None ||
653         aSaveData->animationPixmap == XmUNSPECIFIED_PIXMAP) {
654 	return;
655     }
656 
657     /*
658      *  Determine the destination location and dimensions -- the
659      *  dropsite's bounding box.
660      */
661 
662     _XmRegionGetExtents (aSaveData->dropSiteRegion, &extents);
663     x = extents.x;
664     y = extents.y;
665     width = extents.width;
666     height = extents.height;
667 
668     /*
669      *  Save the original window contents.
670      *  Draw the DrawUnder pixmap into the window.
671      *  Assume correct depth -- checked in CreateAnimationSaveData().
672      */
673 
674     if (SaveAll (aSaveData, x, y, width, height)) {
675 
676 	if (aSaveData->animationMask != None &&
677 	    aSaveData->animationMask != XmUNSPECIFIED_PIXMAP) {
678 
679 	    /*
680 	     *  AnimationMask specified:  create a composite mask consisting
681 	     *  of both the clipping region and the animationMask to use for
682 	     *  copying the animationPixmap into the dropSite.
683 	     *
684 	     *    Create a mask and maskGC.
685 	     *    Set the composite mask to 0's.
686 	     *    Or the animationMask into it through the ClipRegion.
687 	     *    Set the drawGC's ClipMask to the composite mask.
688 	     */
689 
690             mask = _XmAllocScratchPixmap (aSaveData->xmScreen, 1,
691 					  width, height);
692 
693 	    v.background = 0;
694 	    v.foreground = 1;
695 	    v.function = GXclear;
696 	    v.graphics_exposures = False;
697 	    v.subwindow_mode = IncludeInferiors;
698 	    vmask = GCGraphicsExposures|GCSubwindowMode|
699 	            GCBackground|GCForeground|GCFunction;
700 	    maskGC = XCreateGC (aSaveData->display, mask, vmask, &v);
701 
702 	    XFillRectangle (aSaveData->display, mask, maskGC,
703 		            0, 0, width, height);
704 
705 	    XSetFunction (aSaveData->display, maskGC, GXor);
706 	    _XmRegionSetGCRegion (aSaveData->display, maskGC,
707 				  -x, -y, aSaveData->clipRegion);
708 	    XCopyArea (aSaveData->display,
709 		       aSaveData->animationMask,
710     	               mask, maskGC,
711                        0, 0, width, height, 0, 0);
712 
713 	    XSetClipOrigin (aSaveData->display, aSaveData->drawGC, x, y);
714 	    XSetClipMask (aSaveData->display, aSaveData->drawGC, mask);
715 
716 	    XFreeGC (aSaveData->display, maskGC);
717 	}
718 	else {
719 	    _XmRegionSetGCRegion (aSaveData->display, aSaveData->drawGC,
720 				  0, 0, aSaveData->clipRegion);
721 	}
722 
723 	/*
724 	 *  Copy the animationPixmap to the window.
725 	 *  If the animationPixmapDepth is 1 we treat the animationPixmap
726 	 *  as a bitmap and use XCopyPlane.  For 1-deep dropsite windows,
727 	 *  this may not be the same as treating the animationPixmap as a
728 	 *  1-deep pixmap and using XCopyArea.
729 	 */
730 
731 	if (aSaveData->animationPixmapDepth == 1) {
732 	    XCopyPlane (aSaveData->display,
733 			aSaveData->animationPixmap,
734     	                aSaveData->window, aSaveData->drawGC,
735                         0, 0, width, height, x, y, 1L);
736 	}
737 	else {
738 	    XCopyArea (aSaveData->display,
739 		       aSaveData->animationPixmap,
740     	               aSaveData->window, aSaveData->drawGC,
741                        0, 0, width, height, x, y);
742 	}
743 	if (mask != XmUNSPECIFIED_PIXMAP) {
744 	    _XmFreeScratchPixmap (aSaveData->xmScreen, mask);
745 	}
746     }
747 }
748 
749 /*****************************************************************************
750  *
751  *  AnimateExpose ()
752  *
753  ***************************************************************************/
754 
755 /*ARGSUSED*/
756 static void
AnimateExpose(Widget w,XmAnimationSaveData aSaveData,XEvent * event,Boolean * cont)757 AnimateExpose(Widget w,		/* unused */
758 	      XmAnimationSaveData aSaveData,
759 	      XEvent *event,	/* unused */
760 	      Boolean *cont)	/* unused */
761 {
762   /*
763    *  If dragging a pixmap or window, hide it while drawing the
764    *  animation.
765    */
766 
767   if (aSaveData->dragOver && aSaveData->activeMode != XmDRAG_WINDOW) {
768     _XmDragOverHide (aSaveData->dragOver,
769 		     aSaveData->windowX, aSaveData->windowY,
770 		     aSaveData->clipRegion);
771   }
772 
773   /* Draw the visuals. */
774   switch(aSaveData->animationStyle) {
775   default:
776   case XmDRAG_UNDER_HIGHLIGHT:
777     DrawHighlight (aSaveData);
778     break;
779 
780   case XmDRAG_UNDER_SHADOW_IN:
781   case XmDRAG_UNDER_SHADOW_OUT:
782     DrawShadow (aSaveData);
783     break;
784 
785   case XmDRAG_UNDER_PIXMAP:
786     DrawPixmap (aSaveData);
787     break;
788 
789   case XmDRAG_UNDER_NONE:
790     break;
791   }
792 
793   /*
794    *  If dragging a pixmap or window, show it.
795    */
796 
797   if (aSaveData->dragOver && aSaveData->activeMode != XmDRAG_WINDOW) {
798     _XmDragOverShow (aSaveData->dragOver,
799 		     aSaveData->windowX, aSaveData->windowY,
800 		     aSaveData->clipRegion);
801   }
802 }
803 
804 /*****************************************************************************
805  *
806  *  AnimateEnter ()
807  *
808  ***************************************************************************/
809 
810 /*ARGSUSED*/
811 static void
AnimateEnter(XmDropSiteManagerObject dsm,XmAnimationData aData,XmDragProcCallbackStruct * dpcb)812 AnimateEnter(
813         XmDropSiteManagerObject dsm, /* unused */
814         XmAnimationData aData,
815         XmDragProcCallbackStruct *dpcb )
816 {
817     Widget dc = dpcb->dragContext;
818     XmAnimationSaveData	aSaveData;
819     Widget dswidget = GetDSWidget((XmDSInfo) (dsm->dropManager.curInfo));
820     Boolean dummy;
821 
822     /*
823      *  Create and fill an XmAnimationSaveData structure containing the
824      *  data needed to animate the dropsite.  Save it for AnimateLeave().
825      */
826 
827     aSaveData = CreateAnimationSaveData ((XmDragContext) dc, aData, dpcb);
828     *((XtPointer *) aData->saveAddr) = (XtPointer) aSaveData;
829 
830     /* Show the visual */
831     AnimateExpose(dswidget, aSaveData, NULL, &dummy);
832 
833     /* Save the dragunder widget */
834     aSaveData->dragUnder = dswidget;
835 
836     if (aSaveData->activeMode == XmDRAG_WINDOW) {
837       /* Install the event handler to redo visual on Exposure */
838       Widget hwidget = dswidget;
839       if (XmIsGadget(hwidget))
840 	hwidget = XtParent(hwidget);
841       XtInsertEventHandler(hwidget, ExposureMask, False,
842 			   (XtEventHandler) AnimateExpose,
843 			   (XtPointer) aSaveData, XtListTail);
844     }
845 }
846 
847 /*****************************************************************************
848  *
849  *  AnimateLeave ()
850  *
851  ***************************************************************************/
852 
853 /*ARGSUSED*/
854 static void
AnimateLeave(XmDropSiteManagerObject dsm,XmAnimationData aData,XmDragProcCallbackStruct * dpcb)855 AnimateLeave(
856         XmDropSiteManagerObject dsm, /* unused */
857         XmAnimationData aData,
858         XmDragProcCallbackStruct *dpcb ) /* unused */
859 {
860     XmAnimationSaveData aSaveData =
861 	(XmAnimationSaveData) *((XtPointer *) aData->saveAddr);
862 
863     if (aSaveData) {
864         Cardinal	i;
865         DragPixmapData	*pData;
866 
867 	/* Move to here to avoid crashes when aSaveData already zeroed */
868 	if (aSaveData->activeMode == XmDRAG_WINDOW) {
869 	  /* Remove the event handler to redo visual on Exposure */
870 	  Widget hwidget = aSaveData -> dragUnder;
871 	  if (XmIsGadget(hwidget))
872 	    hwidget = XtParent(hwidget);
873 	  XtRemoveEventHandler(hwidget, ExposureMask, False,
874 			       (XtEventHandler) AnimateExpose,
875 			       (XtPointer) aSaveData);
876 	}
877 
878 	/*
879 	 *  If dragging a pixmap or window, hide it while erasing the
880 	 *  animation.
881 	 */
882 
883         if (aSaveData->dragOver) {
884 	    _XmDragOverHide (aSaveData->dragOver,
885     			     aSaveData->windowX, aSaveData->windowY,
886 			     aSaveData->clipRegion);
887 	}
888 
889 	/*
890 	 *  Copy any saved segments back into the window.
891 	 *  Be sure GCRegion is set properly here.
892 	 */
893 
894         _XmRegionSetGCRegion (aSaveData->display, aSaveData->drawGC,
895 			      0, 0, aSaveData->clipRegion);
896         for (pData = aSaveData->savedPixmaps, i = aSaveData->numSavedPixmaps;
897 	     i; pData++, i--) {
898             XCopyArea (aSaveData->display,
899 		       pData->pixmap,
900 		       aSaveData->window,
901 		       aSaveData->drawGC,
902                        0, 0,
903 		       pData->width,
904 		       pData->height,
905 		       pData->x,
906 		       pData->y);
907         }
908 
909 	/*
910 	 *  If dragging a pixmap or window, show it.
911          *  Free the XmAnimationSaveData structure created in AnimateEnter().
912 	 */
913 
914         if (aSaveData->dragOver) {
915 	    _XmDragOverShow (aSaveData->dragOver,
916     			     aSaveData->windowX, aSaveData->windowY,
917 			     aSaveData->clipRegion);
918 	}
919 
920         FreeAnimationData (aSaveData);
921 	*((XtPointer *) aData->saveAddr) = (XtPointer) NULL;
922     }
923 }
924 
925 /*****************************************************************************
926  *
927  *  _XmDragUnderAnimation ()
928  *
929  ***************************************************************************/
930 
931 void
_XmDragUnderAnimation(Widget w,XtPointer clientData,XtPointer callData)932 _XmDragUnderAnimation(
933     Widget w,
934     XtPointer clientData,
935     XtPointer callData )
936 {
937     XmDropSiteManagerObject dsm = (XmDropSiteManagerObject) w;
938     XmDragProcCallbackStruct *dpcb = (XmDragProcCallbackStruct *) callData;
939     XmAnimationData aData = (XmAnimationData) clientData;
940 
941     switch(dpcb->reason)
942     {
943         case XmCR_DROP_SITE_LEAVE_MESSAGE:
944             AnimateLeave(dsm, aData, dpcb);
945         break;
946 
947         case XmCR_DROP_SITE_ENTER_MESSAGE:
948             AnimateEnter(dsm, aData, dpcb);
949         break;
950 
951         default:
952         break;
953     }
954 }
955 
956