/* * @OPENGROUP_COPYRIGHT@ * COPYRIGHT NOTICE * Copyright (c) 1990, 1991, 1992, 1993 Open Software Foundation, Inc. * Copyright (c) 1996, 1997, 1998, 1999, 2000 The Open Group * ALL RIGHTS RESERVED (MOTIF). See the file named COPYRIGHT.MOTIF for * the full copyright text. * * This software is subject to an open license. It may only be * used on, with or for operating systems which are themselves open * source systems. You must contact The Open Group for a license * allowing distribution and sublicensing of this software on, with, * or for operating systems which are not Open Source programs. * * See http://www.opengroup.org/openmotif/license for full * details of the license agreement. Any use, reproduction, or * distribution of the program constitutes recipient's acceptance of * this agreement. * * EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS * PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY * WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY * OR FITNESS FOR A PARTICULAR PURPOSE * * EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT * NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE * EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. */ /* * 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 */ #include #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; } }