/*
* Motif
*
* Copyright (c) 1987-2012, The Open Group. All rights reserved.
*
* These libraries and programs are free software; you can
* redistribute them and/or modify them under the terms of the GNU
* Lesser General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* These libraries and programs are distributed in the hope that
* they will be useful, but WITHOUT ANY WARRANTY; without even the
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with these librararies and programs; if not, write
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
* Floor, Boston, MA 02110-1301 USA
*/
/*
* HISTORY
*/
#ifdef REV_INFO
#ifndef lint
static char rcsid[] = "$XConsortium: DragUnder.c /main/12 1995/07/14 10:26:51 drk $"
#endif
#endif
/* (c) Copyright 1990, 1991, 1992 HEWLETT-PACKARD COMPANY */
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <Xm/DrawP.h>
#include "XmI.h"
#include "DragCI.h"
#include "DragICCI.h"
#include "DragOverSI.h"
#include "DragUnderI.h"
#include "DropSMgrI.h"
#include "GadgetUtiI.h"
#include "MessagesI.h"
#include "RegionI.h"
#include "ScreenI.h"
#define MESSAGE1 _XmMMsgDragUnder_0000
#define MESSAGE2 _XmMMsgDragUnder_0001
/******** Static Function Declarations ********/
static XmAnimationSaveData CreateAnimationSaveData(
XmDragContext dc,
XmAnimationData aData,
XmDragProcCallbackStruct *dpcb) ;
static void FreeAnimationData(
XmAnimationSaveData aSaveData) ;
static Boolean SaveAll(
XmAnimationSaveData aSaveData,
Position x,
Position y,
Dimension width,
Dimension height) ;
static Boolean SaveSegments(
XmAnimationSaveData aSaveData,
Position x,
Position y,
Dimension width,
Dimension height,
Dimension *thickness) ;
static void DrawHighlight(
XmAnimationSaveData aSaveData) ;
static void DrawShadow(
XmAnimationSaveData aSaveData) ;
static void DrawPixmap(
XmAnimationSaveData aSaveData) ;
static void AnimateExpose(Widget w, XmAnimationSaveData aSaveData,
XEvent *event,
Boolean *cont);
static void AnimateEnter(
XmDropSiteManagerObject dsm,
XmAnimationData aData,
XmDragProcCallbackStruct *dpcb) ;
static void AnimateLeave(
XmDropSiteManagerObject dsm,
XmAnimationData aData,
XmDragProcCallbackStruct *dpcb) ;
/******** End Static Function Declarations ********/
/*****************************************************************************
*
* CreateAnimationSaveData ()
*
* Create and fill an XmAnimationSaveData structure containing the data
* needed to animate the dropsite.
***************************************************************************/
/*ARGSUSED*/
static XmAnimationSaveData
CreateAnimationSaveData(
XmDragContext dc,
XmAnimationData aData,
XmDragProcCallbackStruct *dpcb ) /* unused */
{
XmAnimationSaveData aSaveData;
XGCValues v;
unsigned long vmask;
XmDropSiteVisuals dsv;
int ac;
Arg al[5];
Window junkWin;
int junkInt;
unsigned int junkUInt;
unsigned char activeMode;
aSaveData = (XmAnimationSaveData)
XtMalloc (sizeof (XmAnimationSaveDataRec));
aSaveData->dragOver = aData->dragOver;
aSaveData->display = XtDisplay (dc);
aSaveData->xmScreen = (XmScreen) XmGetXmScreen (aData->screen);
aSaveData->window = aData->window;
aSaveData->windowX = aData->windowX;
aSaveData->windowY = aData->windowY;
if (aSaveData->dragOver) {
aSaveData->xmScreen = (XmScreen) XmGetXmScreen (XtScreen (aSaveData->dragOver));
}
else {
aSaveData->xmScreen = (XmScreen) XmGetXmScreen(XtScreen (dc));
}
/*
* Get the window depth.
*/
if (!XGetGeometry (aSaveData->display, aSaveData->window,
&junkWin, &junkInt, &junkInt,
&junkUInt, &junkUInt, &junkUInt,
&(aSaveData->windowDepth))) {
XmeWarning ((Widget) dc, MESSAGE1);
aSaveData->windowDepth = 0;
}
aSaveData->clipRegion = aData->clipRegion;
aSaveData->dropSiteRegion = aData->dropSiteRegion;
dsv = XmDropSiteGetActiveVisuals ((Widget) dc);
aSaveData->background = dsv->background;
aSaveData->foreground = dsv->foreground;
aSaveData->topShadowColor = dsv->topShadowColor;
aSaveData->topShadowPixmap = dsv->topShadowPixmap;
aSaveData->bottomShadowColor = dsv->bottomShadowColor;
aSaveData->bottomShadowPixmap = dsv->bottomShadowPixmap;
aSaveData->shadowThickness = dsv->shadowThickness;
aSaveData->highlightThickness = dsv->highlightThickness;
aSaveData->highlightColor = dsv->highlightColor;
aSaveData->highlightPixmap = dsv->highlightPixmap;
aSaveData->borderWidth = dsv->borderWidth;
XtFree ((char *)dsv);
ac = 0;
XtSetArg (al[ac], XmNanimationStyle, &(aSaveData->animationStyle)); ac++;
XtSetArg (al[ac], XmNanimationMask, &(aSaveData->animationMask)); ac++;
XtSetArg (al[ac], XmNanimationPixmap, &(aSaveData->animationPixmap)); ac++;
XtSetArg (al[ac], XmNanimationPixmapDepth,
&(aSaveData->animationPixmapDepth)); ac++;
XmDropSiteRetrieve ((Widget) dc, al, ac);
if (aSaveData->animationStyle == XmDRAG_UNDER_PIXMAP &&
aSaveData->animationPixmap != None &&
aSaveData->animationPixmap != XmUNSPECIFIED_PIXMAP &&
aSaveData->animationPixmapDepth != 1 &&
aSaveData->animationPixmapDepth != aSaveData->windowDepth) {
XmeWarning ((Widget) dc, MESSAGE2);
aSaveData->animationPixmap = XmUNSPECIFIED_PIXMAP;
}
/*
* Create the draw GC.
*/
v.foreground = aSaveData->foreground;
v.background = aSaveData->background;
v.graphics_exposures = False;
v.subwindow_mode = IncludeInferiors;
vmask = GCGraphicsExposures|GCSubwindowMode|GCForeground|GCBackground;
aSaveData->drawGC =
XCreateGC (aSaveData->display, aSaveData->window, vmask, &v);
if (aSaveData -> dragOver != (Widget) NULL) {
/* Save info on active drag over mode */
XtSetArg(al[0], XmNdragOverActiveMode, &activeMode);
XtGetValues((Widget) aSaveData -> dragOver, al, 1);
aSaveData->activeMode = activeMode;
} else {
/* XmCURSOR is as good as any other value for here. We only
check this against XmDRAG_WINDOW */
aSaveData->activeMode = XmCURSOR;
}
/* initialize savedPixmaps list */
aSaveData->savedPixmaps = NULL;
aSaveData->numSavedPixmaps = 0;
return (aSaveData);
}
/*****************************************************************************
*
* FreeAnimationData ()
*
* Free an XmAnimationSaveData structure.
***************************************************************************/
static void
FreeAnimationData(
XmAnimationSaveData aSaveData )
{
Cardinal i;
switch (aSaveData->animationStyle)
{
case XmDRAG_UNDER_SHADOW_IN:
case XmDRAG_UNDER_SHADOW_OUT:
XFreeGC (aSaveData->display, aSaveData->topShadowGC);
XFreeGC (aSaveData->display, aSaveData->bottomShadowGC);
XFreeGC (aSaveData->display, aSaveData->drawGC);
break;
case XmDRAG_UNDER_HIGHLIGHT:
XFreeGC (aSaveData->display, aSaveData->highlightGC);
XFreeGC (aSaveData->display, aSaveData->drawGC);
break;
case XmDRAG_UNDER_PIXMAP:
XFreeGC (aSaveData->display, aSaveData->drawGC);
case XmDRAG_UNDER_NONE:
default:
break;
}
if (aSaveData->numSavedPixmaps) {
for (i = 0; i < aSaveData->numSavedPixmaps; i++) {
_XmFreeScratchPixmap (aSaveData->xmScreen,
aSaveData->savedPixmaps[i].pixmap);
}
XtFree ((char *)aSaveData->savedPixmaps);
}
XtFree ((char *)aSaveData);
}
/*****************************************************************************
*
* SaveAll ()
*
* Save the original contents of a dropsite window that will be overwritten
* by dropsite animation into a rectangular backing store.
***************************************************************************/
static Boolean
SaveAll(
XmAnimationSaveData aSaveData,
Position x,
Position y,
Dimension width,
Dimension height )
{
DragPixmapData *pData;
if (width <= 0 || height <= 0) {
return (False);
}
aSaveData->numSavedPixmaps = 1;
aSaveData->savedPixmaps = pData =
(DragPixmapData *) XtMalloc (sizeof(DragPixmapData));
if (!pData) {
return (False);
}
pData->x = x;
pData->y = y;
pData->width = width;
pData->height = height;
pData->pixmap =
_XmAllocScratchPixmap (aSaveData->xmScreen,
(Cardinal) aSaveData->windowDepth,
pData->width, pData->height);
XCopyArea (aSaveData->display, aSaveData->window,
pData->pixmap, aSaveData->drawGC,
pData->x, pData->y,
pData->width, pData->height, 0, 0);
return (True);
}
/*****************************************************************************
*
* SaveSegments ()
*
* Save the original contents of a dropsite window that will be overwritten
* by dropsite highlighting or shadowing of indicated thickness. This will
* save 0, 1, or 4 strips into backing store, depending on the dimensions
* of the dropsite and the animation thickness.
***************************************************************************/
static Boolean
SaveSegments(
XmAnimationSaveData aSaveData,
Position x,
Position y,
Dimension width,
Dimension height,
Dimension *thickness )
{
DragPixmapData *pData;
Boolean save_all = False;
if (width <= 0 || height <= 0 || *thickness <= 0) {
return (False);
}
if (*thickness > (width >> 1)) {
*thickness = (width >> 1);
save_all = True;
}
if (*thickness > (height >> 1)) {
*thickness = (height >> 1);
save_all = True;
}
if (save_all) {
return (SaveAll (aSaveData, x, y, width, height));
}
aSaveData->numSavedPixmaps = 4;
aSaveData->savedPixmaps = pData =
(DragPixmapData *) XtMalloc (sizeof(DragPixmapData) * 4);
if (!pData) {
return (False);
}
pData->x = x;
pData->y = y;
pData->width = width;
pData->height = *thickness;
pData->pixmap =
_XmAllocScratchPixmap (aSaveData->xmScreen,
(Cardinal) aSaveData->windowDepth,
pData->width, pData->height);
XCopyArea (aSaveData->display, aSaveData->window,
pData->pixmap, aSaveData->drawGC,
pData->x, pData->y,
pData->width, pData->height, 0, 0);
pData++;
pData->x = x;
pData->y = y + *thickness;
pData->width = *thickness;
pData->height = height - (*thickness << 1);
pData->pixmap =
_XmAllocScratchPixmap (aSaveData->xmScreen,
(Cardinal) aSaveData->windowDepth,
pData->width, pData->height);
XCopyArea (aSaveData->display, aSaveData->window,
pData->pixmap, aSaveData->drawGC,
pData->x, pData->y,
pData->width, pData->height, 0, 0);
pData++;
pData->x = x;
pData->y = y + height - *thickness;
pData->width = width;
pData->height = *thickness;
pData->pixmap =
_XmAllocScratchPixmap (aSaveData->xmScreen,
(Cardinal) aSaveData->windowDepth,
pData->width, pData->height);
XCopyArea (aSaveData->display, aSaveData->window,
pData->pixmap, aSaveData->drawGC,
pData->x, pData->y,
pData->width, pData->height, 0, 0);
pData++;
pData->x = x + width - *thickness;
pData->y = y + *thickness;
pData->width = *thickness;
pData->height = height - (*thickness << 1);
pData->pixmap =
_XmAllocScratchPixmap (aSaveData->xmScreen,
(Cardinal) aSaveData->windowDepth,
pData->width, pData->height);
XCopyArea (aSaveData->display, aSaveData->window,
pData->pixmap, aSaveData->drawGC,
pData->x, pData->y,
pData->width, pData->height, 0, 0);
return (True);
}
/*****************************************************************************
*
* DrawHighlight ()
*
* Draws a highlight around the indicated region.
***************************************************************************/
static void
DrawHighlight(
XmAnimationSaveData aSaveData )
{
XGCValues v;
unsigned long vmask;
Dimension offset;
Position x;
Position y;
Dimension width;
Dimension height;
XRectangle extents;
/*
* Create the highlightGC
*/
v.foreground = aSaveData->highlightColor;
v.background = aSaveData->background;
v.graphics_exposures = False;
v.subwindow_mode = IncludeInferiors;
vmask = GCGraphicsExposures|GCSubwindowMode|GCForeground|GCBackground;
if (aSaveData->highlightPixmap != None &&
aSaveData->highlightPixmap != XmUNSPECIFIED_PIXMAP) {
int depth ;
XmeGetPixmapData(XtScreen(aSaveData->xmScreen),
aSaveData->highlightPixmap,
NULL,
&depth,
NULL, NULL, NULL, NULL, NULL, NULL);
if (depth == 1) {
v.fill_style = FillStippled;
v.stipple = aSaveData->highlightPixmap;
vmask |= GCStipple | GCFillStyle;
} else {
v.fill_style = FillTiled;
v.tile = aSaveData->highlightPixmap;
vmask |= GCTile | GCFillStyle;
}
}
aSaveData->highlightGC =
XCreateGC(aSaveData->display, aSaveData->window, vmask, &v);
_XmRegionSetGCRegion (aSaveData->display, aSaveData->highlightGC,
0, 0, aSaveData->clipRegion);
/* draw highlight */
_XmRegionGetExtents (aSaveData->dropSiteRegion, &extents);
offset = aSaveData->borderWidth;
if (_XmRegionGetNumRectangles(aSaveData->dropSiteRegion) == 1L) {
x = extents.x + offset;
y = extents.y + offset;
width = extents.width - (offset << 1);
height = extents.height - (offset << 1);
if (SaveSegments (aSaveData, x, y, width, height,
&aSaveData->highlightThickness)) {
XmeDrawHighlight (aSaveData->display, aSaveData->window,
aSaveData->highlightGC,
x, y, width, height,
aSaveData->highlightThickness);
}
}
else {
if (SaveAll (aSaveData, extents.x, extents.y, extents.width,
extents.height)) {
_XmRegionDrawShadow (aSaveData->display, aSaveData->window,
aSaveData->highlightGC, aSaveData->highlightGC,
aSaveData->dropSiteRegion,
offset, aSaveData->highlightThickness,
XmSHADOW_OUT);
}
}
}
/*****************************************************************************
*
* DrawShadow ()
*
* Draws a 3-D shadow around the indicated region.
***************************************************************************/
static void
DrawShadow(
XmAnimationSaveData aSaveData )
{
XGCValues v;
unsigned long vmask;
Dimension offset;
Position x;
Position y;
Dimension width;
Dimension height;
XRectangle extents;
/*
* Create the topShadowGC
*/
v.foreground = aSaveData->topShadowColor;
v.background = aSaveData->foreground;
v.graphics_exposures = False;
v.subwindow_mode = IncludeInferiors;
vmask = GCGraphicsExposures|GCSubwindowMode|GCForeground|GCBackground;
if (aSaveData->topShadowPixmap != None &&
aSaveData->topShadowPixmap != XmUNSPECIFIED_PIXMAP) {
int depth ;
XmeGetPixmapData(XtScreen(aSaveData->xmScreen),
aSaveData->topShadowPixmap,
NULL,
&depth,
NULL, NULL, NULL, NULL, NULL, NULL);
if (depth == 1) {
v.fill_style = FillStippled;
v.stipple = aSaveData->topShadowPixmap;
vmask |= GCStipple | GCFillStyle;
} else {
v.fill_style = FillTiled;
v.tile = aSaveData->topShadowPixmap;
vmask |= GCTile | GCFillStyle;
}
}
aSaveData->topShadowGC =
XCreateGC(aSaveData->display, aSaveData->window, vmask, &v);
_XmRegionSetGCRegion (aSaveData->display, aSaveData->topShadowGC,
0, 0, aSaveData->clipRegion);
/*
* Create the bottomShadowGC
*/
v.foreground = aSaveData->bottomShadowColor;
v.background = aSaveData->foreground;
v.graphics_exposures = False;
v.subwindow_mode = IncludeInferiors;
vmask = GCGraphicsExposures|GCSubwindowMode|GCForeground|GCBackground;
if (aSaveData->bottomShadowPixmap != None &&
aSaveData->bottomShadowPixmap != XmUNSPECIFIED_PIXMAP) {
int depth ;
XmeGetPixmapData(XtScreen(aSaveData->xmScreen),
aSaveData->bottomShadowPixmap,
NULL,
&depth,
NULL, NULL, NULL, NULL, NULL, NULL);
if (depth == 1) {
v.fill_style = FillStippled;
v.stipple = aSaveData->bottomShadowPixmap;
vmask |= GCStipple | GCFillStyle;
} else {
v.fill_style = FillTiled;
v.tile = aSaveData->bottomShadowPixmap;
vmask |= GCTile | GCFillStyle;
}
}
aSaveData->bottomShadowGC =
XCreateGC(aSaveData->display, aSaveData->window, vmask, &v);
_XmRegionSetGCRegion (aSaveData->display, aSaveData->bottomShadowGC,
0, 0, aSaveData->clipRegion);
/*
* Draw the shadows.
*/
_XmRegionGetExtents (aSaveData->dropSiteRegion, &extents);
offset = aSaveData->borderWidth + aSaveData->highlightThickness;
if (_XmRegionGetNumRectangles(aSaveData->dropSiteRegion) == 1L) {
x = extents.x + offset;
y = extents.y + offset;
width = extents.width - (offset << 1);
height = extents.height - (offset << 1);
if (SaveSegments (aSaveData, x, y, width, height,
&aSaveData->shadowThickness)) {
XmeDrawShadows (aSaveData->display, aSaveData->window,
aSaveData->topShadowGC,
aSaveData->bottomShadowGC,
x, y, width, height,
aSaveData->shadowThickness,
(aSaveData->animationStyle ==
XmDRAG_UNDER_SHADOW_IN) ?
XmSHADOW_IN : XmSHADOW_OUT);
}
}
else {
if (SaveAll (aSaveData, extents.x, extents.y,
extents.width, extents.height)) {
_XmRegionDrawShadow (aSaveData->display, aSaveData->window,
aSaveData->topShadowGC,
aSaveData->bottomShadowGC,
aSaveData->dropSiteRegion,
offset, aSaveData->shadowThickness,
(aSaveData->animationStyle ==
XmDRAG_UNDER_SHADOW_IN) ?
XmSHADOW_IN : XmSHADOW_OUT);
}
}
}
/*****************************************************************************
*
* DrawPixmap ()
*
* Copy an animationPixmap, possibly masked, to the dropsite window.
***************************************************************************/
static void
DrawPixmap(
XmAnimationSaveData aSaveData )
{
Position x;
Position y;
Dimension width;
Dimension height;
XRectangle extents;
XGCValues v;
unsigned long vmask;
Pixmap mask = XmUNSPECIFIED_PIXMAP;
GC maskGC = NULL;
if (aSaveData->animationPixmap == None ||
aSaveData->animationPixmap == XmUNSPECIFIED_PIXMAP) {
return;
}
/*
* Determine the destination location and dimensions -- the
* dropsite's bounding box.
*/
_XmRegionGetExtents (aSaveData->dropSiteRegion, &extents);
x = extents.x;
y = extents.y;
width = extents.width;
height = extents.height;
/*
* Save the original window contents.
* Draw the DrawUnder pixmap into the window.
* Assume correct depth -- checked in CreateAnimationSaveData().
*/
if (SaveAll (aSaveData, x, y, width, height)) {
if (aSaveData->animationMask != None &&
aSaveData->animationMask != XmUNSPECIFIED_PIXMAP) {
/*
* AnimationMask specified: create a composite mask consisting
* of both the clipping region and the animationMask to use for
* copying the animationPixmap into the dropSite.
*
* Create a mask and maskGC.
* Set the composite mask to 0's.
* Or the animationMask into it through the ClipRegion.
* Set the drawGC's ClipMask to the composite mask.
*/
mask = _XmAllocScratchPixmap (aSaveData->xmScreen, 1,
width, height);
v.background = 0;
v.foreground = 1;
v.function = GXclear;
v.graphics_exposures = False;
v.subwindow_mode = IncludeInferiors;
vmask = GCGraphicsExposures|GCSubwindowMode|
GCBackground|GCForeground|GCFunction;
maskGC = XCreateGC (aSaveData->display, mask, vmask, &v);
XFillRectangle (aSaveData->display, mask, maskGC,
0, 0, width, height);
XSetFunction (aSaveData->display, maskGC, GXor);
_XmRegionSetGCRegion (aSaveData->display, maskGC,
-x, -y, aSaveData->clipRegion);
XCopyArea (aSaveData->display,
aSaveData->animationMask,
mask, maskGC,
0, 0, width, height, 0, 0);
XSetClipOrigin (aSaveData->display, aSaveData->drawGC, x, y);
XSetClipMask (aSaveData->display, aSaveData->drawGC, mask);
XFreeGC (aSaveData->display, maskGC);
}
else {
_XmRegionSetGCRegion (aSaveData->display, aSaveData->drawGC,
0, 0, aSaveData->clipRegion);
}
/*
* Copy the animationPixmap to the window.
* If the animationPixmapDepth is 1 we treat the animationPixmap
* as a bitmap and use XCopyPlane. For 1-deep dropsite windows,
* this may not be the same as treating the animationPixmap as a
* 1-deep pixmap and using XCopyArea.
*/
if (aSaveData->animationPixmapDepth == 1) {
XCopyPlane (aSaveData->display,
aSaveData->animationPixmap,
aSaveData->window, aSaveData->drawGC,
0, 0, width, height, x, y, 1L);
}
else {
XCopyArea (aSaveData->display,
aSaveData->animationPixmap,
aSaveData->window, aSaveData->drawGC,
0, 0, width, height, x, y);
}
if (mask != XmUNSPECIFIED_PIXMAP) {
_XmFreeScratchPixmap (aSaveData->xmScreen, mask);
}
}
}
/*****************************************************************************
*
* AnimateExpose ()
*
***************************************************************************/
/*ARGSUSED*/
static void
AnimateExpose(Widget w, /* unused */
XmAnimationSaveData aSaveData,
XEvent *event, /* unused */
Boolean *cont) /* unused */
{
/*
* If dragging a pixmap or window, hide it while drawing the
* animation.
*/
if (aSaveData->dragOver && aSaveData->activeMode != XmDRAG_WINDOW) {
_XmDragOverHide (aSaveData->dragOver,
aSaveData->windowX, aSaveData->windowY,
aSaveData->clipRegion);
}
/* Draw the visuals. */
switch(aSaveData->animationStyle) {
default:
case XmDRAG_UNDER_HIGHLIGHT:
DrawHighlight (aSaveData);
break;
case XmDRAG_UNDER_SHADOW_IN:
case XmDRAG_UNDER_SHADOW_OUT:
DrawShadow (aSaveData);
break;
case XmDRAG_UNDER_PIXMAP:
DrawPixmap (aSaveData);
break;
case XmDRAG_UNDER_NONE:
break;
}
/*
* If dragging a pixmap or window, show it.
*/
if (aSaveData->dragOver && aSaveData->activeMode != XmDRAG_WINDOW) {
_XmDragOverShow (aSaveData->dragOver,
aSaveData->windowX, aSaveData->windowY,
aSaveData->clipRegion);
}
}
/*****************************************************************************
*
* AnimateEnter ()
*
***************************************************************************/
/*ARGSUSED*/
static void
AnimateEnter(
XmDropSiteManagerObject dsm, /* unused */
XmAnimationData aData,
XmDragProcCallbackStruct *dpcb )
{
Widget dc = dpcb->dragContext;
XmAnimationSaveData aSaveData;
Widget dswidget = GetDSWidget((XmDSInfo) (dsm->dropManager.curInfo));
Boolean dummy;
/*
* Create and fill an XmAnimationSaveData structure containing the
* data needed to animate the dropsite. Save it for AnimateLeave().
*/
aSaveData = CreateAnimationSaveData ((XmDragContext) dc, aData, dpcb);
*((XtPointer *) aData->saveAddr) = (XtPointer) aSaveData;
/* Show the visual */
AnimateExpose(dswidget, aSaveData, NULL, &dummy);
/* Save the dragunder widget */
aSaveData->dragUnder = dswidget;
if (aSaveData->activeMode == XmDRAG_WINDOW) {
/* Install the event handler to redo visual on Exposure */
Widget hwidget = dswidget;
if (XmIsGadget(hwidget))
hwidget = XtParent(hwidget);
XtInsertEventHandler(hwidget, ExposureMask, False,
(XtEventHandler) AnimateExpose,
(XtPointer) aSaveData, XtListTail);
}
}
/*****************************************************************************
*
* AnimateLeave ()
*
***************************************************************************/
/*ARGSUSED*/
static void
AnimateLeave(
XmDropSiteManagerObject dsm, /* unused */
XmAnimationData aData,
XmDragProcCallbackStruct *dpcb ) /* unused */
{
XmAnimationSaveData aSaveData =
(XmAnimationSaveData) *((XtPointer *) aData->saveAddr);
if (aSaveData) {
Cardinal i;
DragPixmapData *pData;
/* Move to here to avoid crashes when aSaveData already zeroed */
if (aSaveData->activeMode == XmDRAG_WINDOW) {
/* Remove the event handler to redo visual on Exposure */
Widget hwidget = aSaveData -> dragUnder;
if (XmIsGadget(hwidget))
hwidget = XtParent(hwidget);
XtRemoveEventHandler(hwidget, ExposureMask, False,
(XtEventHandler) AnimateExpose,
(XtPointer) aSaveData);
}
/*
* If dragging a pixmap or window, hide it while erasing the
* animation.
*/
if (aSaveData->dragOver) {
_XmDragOverHide (aSaveData->dragOver,
aSaveData->windowX, aSaveData->windowY,
aSaveData->clipRegion);
}
/*
* Copy any saved segments back into the window.
* Be sure GCRegion is set properly here.
*/
_XmRegionSetGCRegion (aSaveData->display, aSaveData->drawGC,
0, 0, aSaveData->clipRegion);
for (pData = aSaveData->savedPixmaps, i = aSaveData->numSavedPixmaps;
i; pData++, i--) {
XCopyArea (aSaveData->display,
pData->pixmap,
aSaveData->window,
aSaveData->drawGC,
0, 0,
pData->width,
pData->height,
pData->x,
pData->y);
}
/*
* If dragging a pixmap or window, show it.
* Free the XmAnimationSaveData structure created in AnimateEnter().
*/
if (aSaveData->dragOver) {
_XmDragOverShow (aSaveData->dragOver,
aSaveData->windowX, aSaveData->windowY,
aSaveData->clipRegion);
}
FreeAnimationData (aSaveData);
*((XtPointer *) aData->saveAddr) = (XtPointer) NULL;
}
}
/*****************************************************************************
*
* _XmDragUnderAnimation ()
*
***************************************************************************/
void
_XmDragUnderAnimation(
Widget w,
XtPointer clientData,
XtPointer callData )
{
XmDropSiteManagerObject dsm = (XmDropSiteManagerObject) w;
XmDragProcCallbackStruct *dpcb = (XmDragProcCallbackStruct *) callData;
XmAnimationData aData = (XmAnimationData) clientData;
switch(dpcb->reason)
{
case XmCR_DROP_SITE_LEAVE_MESSAGE:
AnimateLeave(dsm, aData, dpcb);
break;
case XmCR_DROP_SITE_ENTER_MESSAGE:
AnimateEnter(dsm, aData, dpcb);
break;
default:
break;
}
}