/* * CDE - Common Desktop Environment * * Copyright (c) 1993-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 */ /* $XConsortium: DndIcon.c /main/5 1996/06/21 17:28:34 ageorge $ */ /********************************************************************* * * File: DndIcon.c * * Description: Implemenation of DND drag icons * ********************************************************************* * *+SNOTICE * * RESTRICTED CONFIDENTIAL INFORMATION: * * The information in this document is subject to special * restrictions in a confidential disclosure agreement between * HP, IBM, Sun, USL, SCO and Univel. Do not distribute this * document outside HP, IBM, Sun, USL, SCO, or Univel without * Sun's specific written approval. This documment and all copies * and derivative works thereof must be returned or destroyed at * Sun's request. * * Copyright 1993 Sun Microsystems, Inc. All rights reserved. * * (c) Copyright 1993, 1994 Hewlett-Packard Company * (c) Copyright 1993, 1994 International Business Machines Corp. * (c) Copyright 1993, 1994 Sun Microsystems, Inc. * (c) Copyright 1993, 1994 Novell, Inc. * *+ENOTICE */ #include #include #include #include #include #include "Dnd.h" #include "DndP.h" #include "DndIconI.h" #include "DtSvcLock.h" /* * Component types of a drag icon (source/state/operation) */ enum { DtDND_DRAG_SOURCE, DtDND_DRAG_STATE, DtDND_DRAG_OPERATION }; /* * The XmDragIcon widgets for the state & operation components * of a Drag Icon */ typedef struct _DragIcons { Widget validIcon, invalidIcon, noneIcon; Widget moveIcon, copyIcon, linkIcon; } DragIcons; /* * Collection of drag icons for text & data drags */ typedef struct _DragCollection { DtDndDragSource sourceType; DragIcons text; DragIcons data; Widget textSource; Widget dataSource; Widget multipleSource; } DragCollection; /* * The context that the DragCollection is stored against. * Used in getDragCollection() and destroyDragCollection(). */ static XContext dragCollectionContext; /* * Creates an XmDragIcon for use as the source component of the drag icon. */ Widget DtDndCreateSourceIcon( Widget widget, Pixmap pixmap, Pixmap mask) { Widget dragIcon; Window rootWindow; int pixmapX, pixmapY; unsigned int pixmapWidth, pixmapHeight, pixmapBorder, pixmapDepth; Arg args[20]; Cardinal nn = 0; _DtSvcWidgetToAppContext(widget); _DtSvcAppLock(app); while (XmIsGadget(widget)) { widget = XtParent(widget); } XGetGeometry (XtDisplayOfObject(widget), pixmap, &rootWindow, &pixmapX, &pixmapY, &pixmapWidth, &pixmapHeight, &pixmapBorder, &pixmapDepth); XtSetArg(args[nn], XmNwidth, pixmapWidth); nn++; XtSetArg(args[nn], XmNheight, pixmapHeight); nn++; XtSetArg(args[nn], XmNmaxWidth, pixmapWidth); nn++; XtSetArg(args[nn], XmNmaxHeight, pixmapHeight); nn++; XtSetArg(args[nn], XmNpixmap, pixmap); nn++; XtSetArg(args[nn], XmNmask, mask); nn++; XtSetArg(args[nn], XmNdepth, pixmapDepth); nn++; dragIcon = XmCreateDragIcon(widget, "sourceIcon", args, nn); _DtSvcAppUnlock(app); return(dragIcon); } /* * Calculates the x,y offsets for the state cursor relative to the source */ static void calcStateIconOffset( Widget sourceIcon, int *stateOffsetX, int *stateOffsetY) { Display *dpy = XtDisplayOfObject(sourceIcon); Pixmap pixmap; Window root; int pixmapX, pixmapY; unsigned int pixmapW, pixmapH, junk; XtVaGetValues(sourceIcon, XmNpixmap, &pixmap, NULL); if (pixmap == None) return; XGetGeometry(dpy, pixmap, &root, &pixmapX, &pixmapY, &pixmapW, &pixmapH, &junk, &junk); if (pixmapH == 16) { *stateOffsetX = *stateOffsetY = 8; } else { *stateOffsetX = *stateOffsetY = 16; } } /* * Selects or activates the request type of source by setting * the default drag icon resources on the XmScreen widget. */ static void selectDragSource( DragCollection *dc, Widget xmScreen, DtDndDragSource sourceType, Widget sourceIcon) { Display *dpy = XtDisplayOfObject(xmScreen); Widget validIcon, invalidIcon, noneIcon, moveIcon, copyIcon, linkIcon, defSourceIcon; int hotX, hotY, stateOffsetX, stateOffsetY, offsetDeltaX, offsetDeltaY; Arg args[30]; Cardinal nn = 0; /* * Choose the state/operation/default-source drag icons based * on the requested drag-source-type */ switch (sourceType) { case DtDND_DRAG_SOURCE_TEXT: validIcon = dc->text.validIcon; invalidIcon = dc->text.invalidIcon; noneIcon = dc->text.noneIcon; moveIcon = dc->text.moveIcon; copyIcon = dc->text.copyIcon; linkIcon = dc->text.linkIcon; defSourceIcon = dc->textSource; hotX = text_x_hot; hotY = text_y_hot; stateOffsetX = text_x_offset_state; stateOffsetY = text_y_offset_state; offsetDeltaX = text_x_offset_delta; offsetDeltaY = text_y_offset_delta; break; case DtDND_DRAG_SOURCE_DATA: validIcon = dc->data.validIcon; invalidIcon = dc->data.invalidIcon; noneIcon = dc->data.noneIcon; moveIcon = dc->data.moveIcon; copyIcon = dc->data.copyIcon; linkIcon = dc->data.linkIcon; defSourceIcon = dc->dataSource; hotX = data_x_hot; hotY = data_y_hot; stateOffsetX = data_x_offset_state; stateOffsetY = data_y_offset_state; offsetDeltaX = data_x_offset_delta; offsetDeltaY = data_y_offset_delta; break; case DtDND_DRAG_SOURCE_MULTIPLE: validIcon = dc->data.validIcon; invalidIcon = dc->data.invalidIcon; noneIcon = dc->data.noneIcon; moveIcon = dc->data.moveIcon; copyIcon = dc->data.copyIcon; linkIcon = dc->data.linkIcon; defSourceIcon = dc->multipleSource; hotX = data_x_hot; hotY = data_y_hot; stateOffsetX = data_x_offset_state; stateOffsetY = data_y_offset_state; offsetDeltaX = data_x_offset_delta; offsetDeltaY = data_y_offset_delta; break; default: case DtDND_DRAG_SOURCE_DEFAULT: validIcon = NULL; invalidIcon = NULL; noneIcon = NULL; moveIcon = NULL; copyIcon = NULL; linkIcon = NULL; defSourceIcon = NULL; hotX = motif_x_hot; hotY = motif_y_hot; stateOffsetX = motif_x_offset_state; stateOffsetY = motif_y_offset_state; offsetDeltaX = motif_x_offset_delta; offsetDeltaY = motif_y_offset_delta; break; } /* * Calculate the offsets of the state icon from the * DtDND_DRAG_SOURCE_DATA source icon if specified */ if (sourceIcon && sourceType == DtDND_DRAG_SOURCE_DATA) { calcStateIconOffset(sourceIcon, &stateOffsetX, &stateOffsetY); } nn = 0; XtSetArg(args[nn], XmNhotX, hotX); nn++; XtSetArg(args[nn], XmNhotY, hotY); nn++; XtSetArg(args[nn], XmNoffsetX, stateOffsetX); nn++; XtSetArg(args[nn], XmNoffsetY, stateOffsetY); nn++; if (validIcon) XtSetValues(validIcon, args, nn); if (invalidIcon) XtSetValues(invalidIcon, args, nn); if (noneIcon) XtSetValues(noneIcon, args, nn); nn = 0; XtSetArg(args[nn], XmNoffsetX, stateOffsetX + offsetDeltaX); nn++; XtSetArg(args[nn], XmNoffsetY, stateOffsetY + offsetDeltaY); nn++; if (moveIcon) XtSetValues(moveIcon, args, nn); if (copyIcon) XtSetValues(copyIcon, args, nn); if (linkIcon) XtSetValues(linkIcon, args, nn); /* * Set the default drag cursor icons for the XmScreen widget */ XtVaSetValues(xmScreen, XmNdefaultValidCursorIcon, validIcon, XmNdefaultInvalidCursorIcon, invalidIcon, XmNdefaultNoneCursorIcon, noneIcon, XmNdefaultMoveCursorIcon, moveIcon, XmNdefaultCopyCursorIcon, copyIcon, XmNdefaultLinkCursorIcon, linkIcon, XmNdefaultSourceCursorIcon, defSourceIcon, NULL); dc->sourceType = sourceType; } /* * Create a drag icon widget from the passed bits */ static Widget makeDragIconFromData( Widget widget, unsigned char *bits, unsigned char *maskbits, int width, int height, int component) { Widget icon; Pixmap pixmap, mask; Display *dpy = XtDisplayOfObject(widget); Screen *screen = XtScreenOfObject(widget); Window root = RootWindowOfScreen(screen); String name; Arg args[30]; Cardinal nn = 0; pixmap = XCreatePixmapFromBitmapData(dpy, root, (char *)bits, width, height, 1, 0, 1); mask = XCreatePixmapFromBitmapData(dpy, root, (char *)maskbits, width, height, 1, 0, 1); switch (component) { case DtDND_DRAG_SOURCE: name = "sourceIcon"; break; case DtDND_DRAG_STATE: name = "stateIcon"; XtSetArg(args[nn], XmNattachment, XmATTACH_NORTH_WEST); nn++; XtSetArg(args[nn], XmNoffsetX, -6); nn++; XtSetArg(args[nn], XmNoffsetY, -6); nn++; XtSetArg(args[nn], XmNhotX, 3); nn++; XtSetArg(args[nn], XmNhotY, 3); nn++; break; case DtDND_DRAG_OPERATION: name = "operationIcon"; XtSetArg(args[nn], XmNattachment, XmATTACH_NORTH_WEST); nn++; XtSetArg(args[nn], XmNoffsetX, 1); nn++; XtSetArg(args[nn], XmNoffsetY, 1); nn++; break; } XtSetArg(args[nn], XmNwidth, width); nn++; XtSetArg(args[nn], XmNheight, height); nn++; XtSetArg(args[nn], XmNmaxWidth, width); nn++; XtSetArg(args[nn], XmNmaxHeight, height); nn++; XtSetArg(args[nn], XmNpixmap, pixmap); nn++; XtSetArg(args[nn], XmNmask, mask); nn++; XtSetArg(args[nn], XmNdepth, 1); nn++; icon = XmCreateDragIcon(widget, name, args, nn); return icon; } /* * Create the collection of text & data drag icons; state/operation * cursors and source icons. */ static DragCollection * makeDragCollection( Widget widget) { DragCollection *dc = XtNew(DragCollection); Display *dpy = XtDisplayOfObject(widget); Screen *screen = XtScreenOfObject(widget); Window root = RootWindowOfScreen(screen); Widget xmScreen = XmGetXmScreen(screen); /* * Text & Data State Cursors */ dc->text.invalidIcon = makeDragIconFromData(widget, text_invalid_bits, text_invalid_m_bits, text_invalid_width, text_invalid_height, DtDND_DRAG_STATE); dc->text.validIcon = makeDragIconFromData(widget, text_valid_bits, text_valid_m_bits, text_valid_width, text_valid_height, DtDND_DRAG_STATE); dc->text.noneIcon = makeDragIconFromData(widget, text_none_bits, text_none_m_bits, text_none_width, text_none_height, DtDND_DRAG_STATE); dc->data.invalidIcon = makeDragIconFromData(widget, data_invalid_bits, data_invalid_m_bits, data_invalid_width, data_invalid_height, DtDND_DRAG_STATE); dc->data.validIcon = makeDragIconFromData(widget, data_valid_bits, data_valid_m_bits, data_valid_width, data_valid_height, DtDND_DRAG_STATE); dc->data.noneIcon = makeDragIconFromData(widget, data_none_bits, data_none_m_bits, data_none_width, data_none_height, DtDND_DRAG_STATE); /* * Text & Data Operation Cursors */ dc->data.moveIcon = makeDragIconFromData(widget, data_move_bits, data_move_m_bits, data_move_width, data_move_height, DtDND_DRAG_OPERATION); dc->data.copyIcon = makeDragIconFromData(widget, data_copy_bits, data_copy_m_bits, data_copy_width, data_copy_height, DtDND_DRAG_OPERATION); dc->data.linkIcon = makeDragIconFromData(widget, data_link_bits, data_link_m_bits, data_link_width, data_link_height, DtDND_DRAG_OPERATION); dc->text.moveIcon = dc->data.moveIcon; dc->text.copyIcon = dc->data.copyIcon; dc->text.linkIcon = dc->data.linkIcon; /* * Text & Data Source Cursors */ dc->textSource = makeDragIconFromData(widget, text_source_bits, text_source_m_bits, text_source_width, text_source_height, DtDND_DRAG_SOURCE); dc->dataSource = makeDragIconFromData(widget, data_single_bits, data_single_m_bits, data_single_width, data_single_height, DtDND_DRAG_SOURCE); dc->multipleSource = makeDragIconFromData(widget, data_multiple_bits, data_multiple_m_bits, data_multiple_width, data_multiple_height, DtDND_DRAG_SOURCE); dc->sourceType = DtDND_DRAG_SOURCE_DEFAULT; return dc; } /* * Destroys the cached DragCollection and context for it */ static void destroyDragCollection( Widget widget, XtPointer clientData, XtPointer callData) { DragCollection *dc = (DragCollection *)clientData; XtFree((char *)dc); XDeleteContext(XtDisplayOfObject(widget), RootWindowOfScreen(XtScreenOfObject(widget)), dragCollectionContext); } /* * Returns the cached DragCollection; will create one if needed */ static DragCollection * getDragCollection( Widget xmScreen) { DragCollection *dc = NULL; Display *dpy = XtDisplayOfObject(xmScreen); Screen *screen = XtScreenOfObject(xmScreen); Window root = RootWindowOfScreen(screen); int status; _DtSvcProcessLock(); if (dragCollectionContext == (XContext)NULL) { dragCollectionContext = XUniqueContext(); } _DtSvcProcessUnlock(); status = XFindContext(dpy, root, dragCollectionContext, (XtPointer)&dc); if (status != 0) { dc = makeDragCollection(xmScreen); XSaveContext(dpy, root, dragCollectionContext, (XtPointer)dc); XtAddCallback(xmScreen, XmNdestroyCallback, destroyDragCollection, (XtPointer)dc); } return dc; } /* * Module-public function to select/activate a source type drag icon */ void _DtDndSelectDragSource( Widget widget, DtDndDragSource sourceType, Widget sourceIcon) { Widget xmScreen = XmGetXmScreen(XtScreenOfObject(widget)); DragCollection *dc = getDragCollection(xmScreen); selectDragSource(dc, xmScreen, sourceType, sourceIcon); } void _DtDndGetIconOffset( Widget dragContext, DtDndDragSource sourceType, int * offsetX, int * offsetY) { Widget sourceIcon; int stateOffsetX, stateOffsetY; switch (sourceType) { default: case DtDND_DRAG_SOURCE_DEFAULT: *offsetX = -(motif_x_hot + motif_x_offset_state); *offsetY = -(motif_y_hot + motif_y_offset_state); break; case DtDND_DRAG_SOURCE_TEXT: *offsetX = -(text_x_hot + text_x_offset_state); *offsetY = -(text_y_hot + text_y_offset_state); break; case DtDND_DRAG_SOURCE_DATA: case DtDND_DRAG_SOURCE_MULTIPLE: *offsetX = -(data_x_hot + data_x_offset_state); *offsetY = -(data_y_hot + data_y_offset_state); XtVaGetValues(dragContext, XmNsourcePixmapIcon, &sourceIcon, NULL); if (sourceIcon != NULL) { calcStateIconOffset(sourceIcon, &stateOffsetX, &stateOffsetY); *offsetX = -(data_x_hot + stateOffsetX); *offsetY = -(data_y_hot + stateOffsetY); } break; } }