cdesktopenv/cde/lib/DtSvc/DtUtil1/DndIcon.c

571 lines
15 KiB
C

/*
* 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 <stdlib.h>
#include <X11/Xlib.h>
#include <X11/Intrinsic.h>
#include <Xm/Screen.h>
#include <Xm/DragIcon.h>
#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;
}
}