VkCutPaste(3x)VkCutPaste(3x)NAMEVkCutPaste - A simple API for Cut/Copy/Drag/Drop
INHERITS FROM
VkCallbackObject : VkBase
HEADER FILE
#include <Vk/VkCutPaste.h>
PUBLIC PROTOCOL SUMMARY
Constructor/Destructor
VkCutPaste(Widget w);
void ~VkCutPaste(void);
Copy (Export) Methods
void clear(Atom selection, Time time = CurrentTime);
Boolean putCopy(Atom selection, Atom target,
XtPointer data, unsigned long numBytes);
Boolean putCopy(Atom selection, const char *targetName,
XtPointer data, unsigned long numBytes);
Boolean putReference(Atom selection, Atom target,
XtPointer data, unsigned long numBytes);
Boolean putReference(Atom selection,
const char *targetName,
XtPointer data, unsigned long numBytes);
Boolean getLocalReference(Atom selection, int index,
Atom *target, XtPointer *dataRet,
unsigned long *numBytesRet);
Boolean getLocalTypeReference(Atom selection,
Atom target, XtPointer *dataRet,
unsigned long *numBytesRet);
Boolean remove(Atom selection, Atom target);
Copy (Export) Methods - ViewKit 1.5.3 only
Boolean export(Atom selection, Time time = CurrentTime);
Copy (Export) Methods - ViewKit 2.1 only
Boolean exportData(Atom selection, Time time = CurrentTime);
Paste (Import) Methods
void import(Atom selection, Atom *interestList,
int interestListLen, ImportCallbackProc proc,
void *clientData = NULL,
Time theTime = CurrentTime);
XtPointer importImmediate(Atom selection,
Atom *interestList, int interestListLen,
Atom *targetRet, unsigned long *numBytesRet,
Page 1
VkCutPaste(3x)VkCutPaste(3x)
Time theTime = CurrentTime);
Drag Away Methods
Widget dragAwayCopy(Widget w, XEvent *xev, Atom target,
XtPointer data, unsigned long numBytes,
DragAwayCallbackProc dragAwayProc = NULL,
void *clientData = NULL);
Widget dragAwayCopy(Widget w, XEvent *xev,
const char *targetName,
XtPointer data, unsigned long numBytes,
DragAwayCallbackProc dragAwayProc = NULL,
void *clientData = NULL);
Widget dragAwayCopyExtended(Widget w, XEvent *xev,
Atom *targetList, XtPointer *dataList,
unsigned long *lenList, int numDragItems,
DragAwayCallbackProc dragAwayProc = NULL,
void *clientData = NULL,
ArgList args = NULL, int numArgs = 0);
Drop Methods
Boolean registerDropSite(Widget w,
Atom *interestList, int interestListLen,
DropSiteCallbackProc dropProc,
void *clientData = NULL);
Boolean registerDropSiteExtended(Widget w,
Atom *interestList, int interestListLen,
DropSiteCallbackProc dropProc,
DragCallbackProc dragProc = NULL,
void *clientData = NULL,
Arg *args = NULL, int numArgs = 0);
Boolean unregisterDropSite(Widget w);
Data Type and Converter Methods
void registerDataType(Atom target, Atom type, int format,
unsigned long flags = CUTPASTE_NORMAL_TYPE,
DestroyProc destroyProc = NULL,
void *clientData = NULL);
void registerDataType(const char *targetName,
const char *typeName, int format,
unsigned long flags = CUTPASTE_NORMAL_TYPE,
DestroyProc destroyProc = NULL,
void *clientData = NULL);
Boolean getDataTypeInfo(Atom target, Atom *type,
int *format, unsigned long *flags);
void registerConverter(Atom from, Atom to,
ConvertProc converter,
CanConvertProc canConvert = NULL,
void *clientData = NULL);
void registerConverter(const char *fromName,
Page 2
VkCutPaste(3x)VkCutPaste(3x)
const char *toName, ConvertProc converter,
CanConvertProc canConvert = NULL,
void *clientData = NULL);
Other Methods
unsigned long getVersion(void);
Atom primaryAtom(void);
Atom clipboardAtom(void);
Widget getWidget(void);
Time getXServerTime(void);
void setTransactionsTimeout(unsigned long numSeconds);
Boolean isOwnedByMe(Atom selection);
Boolean isOwnedByLocalHost(Atom selection);
Boolean registerLoseSelection(Atom selection,
LoseSelectionProc loseSelProc,
void *clientData);
Boolean getFilenamesFromSGI_ICON(char *sgiIconData,
unsigned long numBytes,
char ***fileNameArrayRet, int *numFilesRet);
void freeFilenamesFromSGI_ICON(char **fileNameArray,
int numFiles);
Callback Function Prototypes
typedef Boolean (*ConvertProc)(Widget w, Atom selection,
void *clientData, Atom srcTarget, XtPointer src,
unsigned long numSrcBytes, Atom dstTarget,
XtPointer *dst, unsigned long *numDstBytes);
typedef Boolean (*CanConvertProc)(Widget w,
Atom selection, void *clientData, Atom srcTarget,
XtPointer src, unsigned long numSrcBytes,
Atom dstTarget);
typedef void (*DestroyProc)(Widget w, Atom selection,
Atom target, XtPointer data, unsigned long numBytes,
void *clientData);
typedef void (*LoseSelectionProc)(Widget w,
Atom selection, void *clientData);
typedef void (*DropSiteCallbackProc)(Widget w,
Atom target, XtPointer data, unsigned long numBytes,
int x, int y, void *clientData);
typedef void (*DragCallbackProc)(Widget w, Atom target,
int reason, int x, int y, void *clientData);
typedef void (*DragAwayCallbackProc)(Widget w,
Boolean result,void *clientData);
typedef void (*ImportCallbackProc)(Widget w, Atom target,
XtPointer data, unsigned long numBytes,
void *clientData);
Page 3
VkCutPaste(3x)VkCutPaste(3x)CLASS DESCRIPTION
The VkCutPaste class provides a simple C++ API that helps developers
add inter-application Copy/Paste/Drag/Drop to their applications
with very little effort, and with little or no understanding of
Motif's and X-Window's complex protocols.
The VkCutPaste library uses the Xt Intrinsics and Motif to implement
a totally standard X-Selection ICCCM compliant communication, so
your application must link with those libraries to use this API.
The VkCutPaste does not require other parts of ViewKit, and can be
used in a standard Motif application.
FUNCTION DESCRIPTIONSVkCutPaste()
VkCutPaste(Widget w);
Instantiates a VkCutPaste object. The "w" must not be destroyed for
the life of this class, since it is used by the VkCutPaste class
during the execution of most of the methods. Do not pass the same
widget into more than one concurrent instance of the VkCutPaste
class.
~VkCutPaste()
void ~VkCutPaste(void);
This deletes any remaining memory allocated by the VkCutPaste class.
Because the VkCutPaste class will sometimes create temporary files,
it is important to always call the destructor when you are through
with the class.
clear()
void clear(Atom selection, Time time = CurrentTime);
Usually called immediately before a "putCopy()". Clears the
indicated selection, and frees any memory that was allocated as part
of an earlier "putCopy()". After a "clear()", no data is being
offered to any other ICCCM clients on this selection. The
"selection" is either CLIPBOARD or PRIMARY.
clipboardAtom()
Atom clipboardAtom(void);
Returns the CLIPBOARD atom. This is a convenience function, and
returns exactly the same thing as XmInternAtom(dpy, "CLIPBOARD",
False).
Page 4
VkCutPaste(3x)VkCutPaste(3x)dragAwayCopy()
Widget dragAwayCopy(Widget w, XEvent *xev, Atom target,
XtPointer data, unsigned long numBytes,
DragAwayCallbackProc dragAwayProc = NULL,
void *clientData = NULL);
Widget dragAwayCopy(Widget w, XEvent *xev,
const char *targetName,
XtPointer data, unsigned long numBytes,
DragAwayCallbackProc dragAwayProc = NULL,
void *clientData = NULL);
Drags away data from this application. The "data" can be free'd
immediately after calling this function, because this function makes
a copy of the data for its use. The "xev" should be the ButtonPress
event that the user did to initiate the drag. The optional
"dragAwayProc" is called after the drag completes, and one of the
parameters to that function indicates if the drag was successful or
not. The DragContext created for this drag and drop transaction is
returned (see XmDragStart).
dragAwayCopyExtended()
Widget dragAwayCopyExtended(Widget w, XEvent *xev,
Atom *targetList, XtPointer *dataList,
unsigned long *lenList, int numDragItems,
DragAwayCallbackProc dragAwayProc = NULL,
void *clientData = NULL,
ArgList args = NULL, int numArgs = 0);
This does exactly what "dragAwayCopy()" does, but provides more
options for the advanced programmer who needs more control. For
example, the programmer could specify the drag away data as more
than one "target" (it should be the same conceptual object, just in
different formats, like GIF and XPM format data of the same image).
The programmer could also use this function to specify the various
drag icons by specifying those parameters in the "args" argument.
"Args" and "numArgs" are passed of to XmDragStart(). The following
"args" are not allowed: XmNconvertProc, XmNdragOperations,
XmNexportTargets, XmNnumExportTargets, XmNclientData. See the
XmDragContext man page for information on other valid arguments.
Motif's Drop Copy protocol (XmDROP_COPY) is the only drag and drop
operation supported. The DragContext created for this drag and drop
transaction is returned (see XmDragStart).
export() - ViewKit 1.5.3 only
Boolean export(Atom selection,
Time time = CurrentTime);
Page 5
VkCutPaste(3x)VkCutPaste(3x)
Usually called immediately after a "putCopy()", this makes the data
in the indicated selection available to other ICCCM clients.
exportData() - ViewKit 2.1 only
Boolean exportData(Atom selection,
Time time = CurrentTime);
Usually called immediately after a "putCopy()", this makes the data
in the indicated selection available to other ICCCM clients.
freeFilenamesFromSGI_ICON()
void freeFilenamesFromSGI_ICON(char **fileNameArray,
int numFiles);
This frees the data that is returned from the
"getFilenamesFromSGI_ICON()" method.
getFilenamesFromSGI_ICON()
Boolean getFilenamesFromSGI_ICON(char *sgiIconData,
unsigned long numBytes,
char ***fileNameArrayRet, int *numFilesRet);
This convenience method parses the data of target _SGI_ICON which
the SGI desktop uses to drag one or more files around. An
application would call this function inside of its
"DropSiteCallbackProc" when it receives a target of _SGI_ICON.
After an application is done with the filename list, it should free
the memory allocated inside "getFilenamesFromSGI_ICON()" by calling
"freeFilenamesFromSGI_ICON()".
getDataTypeInfo()
Boolean getDataTypeInfo(Atom target, Atom *type,
int *format, unsigned long *flags);
Given the "target", this method returns the "type" and the "format"
of this kind of target as specified by the ICCCM manual, and also
any associated "flags". True is returned if the "target" was found,
and False otherwise. The VkCutPaste class knows about an extensive
list of targets already. This list can be added to by calling the
"registerDataType()" method. The "flags" returned is a bit mask of
the following flags: CUTPASTE_NORMAL_TYPE, CUTPASTE_FILENAME_TYPE,
and CUTPASTE_HIDDEN_TYPE. See "registerDataType()" for more
information.
getLocalReference()
Boolean getLocalReference(Atom selection, int index,
Atom *target, XtPointer *dataRet, unsigned long
*numBytesRet);
Page 6
VkCutPaste(3x)VkCutPaste(3x)
Allows you to retrieve the contents of the local export selection.
This is NOT X Selections based. This only gives you a pointer, so
the data must not be free'd or modified. Returns a pointer to the
data at "index" (if multiple "putCopy()" were called, the first one
is at index 0, the second is at index 1, and so on).
getLocalTypeReference()
Boolean getLocalTypeReference(Atom selection,
Atom target, XtPointer *dataRet,
unsigned long *numBytesRet);
Does exactly the same thing as "getLocalReference()", but instead of
specifying an "index", you specify the "target" you wish to retrieve
from the exported selection.
getVersion()
unsigned long getVersion(void);
Returns the version number of this implementation of the VkCutPaste
class. For example, the first version is 0x010000, version 2.1 will
be 0x020100, etc.
getWidget()
Widget getWidget(void);
Returns the widget that was originally passed to the VkCutPaste
constructor.
getXServerTime()
Time getXServerTime(void);
Invokes a round trip to the X-Server, and returns a server
timestamp. Most applications should try to avoid this call and use
the "CurrentTime" flag to the VkCutPaste methods, or even better
should use the timestamp out of a recent X-Event. However, there
are some rare situations where there are no X-Events handy and
CurrentTime will not work, so this convenience method is a failsafe
way to get a valid server timestamp.
import()
void import(Atom selection, Atom *interestList,
int interestListLen, ImportCallbackProc proc,
void *clientData = NULL,
Time theTime = CurrentTime);
Page 7
VkCutPaste(3x)VkCutPaste(3x)
This is a non-blocking method which will retrieve Copy and Paste
data from any ICCCM client. The "selection" should be either
CLIPBOARD or PRIMARY. The "interestList" is an ordered array of the
targets this application is interested in. For example,
interestList[0] might be XPM, interestList[1] might be GIF_89, and
interestList[2] might be STRING. In this example, you would set
"interestListLen" to be "3". The "proc" will be invoked with either
NULL data, or an XPM, GIF_89, or STRING. NULL simply means that
nothing was available of any of the requested types. "import()"
makes a copy of the interestList, so you can free this data
immediately after this call completes (and before the "proc" is
called).
importImmediate()
XtPointer importImmediate(Atom selection,
Atom *interestList, int interestListLen,
Atom *targetRet, unsigned long *numBytesRet,
Time theTime = CurrentTime);
This is a blocking version of the "import()" method. This function
blocks until the data is retrieved, so it eliminates the callback.
Since this function uses it's own internal event loop, clients that
are not using the standard "XtAppMainLoop()" (or in ViewKit are not
using the standard "app->run()") might want to avoid this call.
isOwnedByLocalHost()
Boolean isOwnedByLocalHost(Atom selection);
Returns True if the indicated selection is currently owned by a
client running on the same machine as this client. This call is
useful if you are planning to copy and paste filenames with other
clients, since a file that is on a different machine is not
accessible to your client. Some examples of filename targets are
XPM_FILE and GIF_89_FILE. Data stream types like XPM and GIF_89 are
always safe and will always work, and should be used unless there is
some overwhelming reason to exchange filenames.
isOwnedByMe()
Boolean isOwnedByMe(Atom selection);
Returns True if the selection is currently owned by this client.
This can be used to optimize the "Paste()" function to be faster
when this client would have exchanged data with itself anyway.
primaryAtom()
Atom primaryAtom(void);
Page 8
VkCutPaste(3x)VkCutPaste(3x)
Returns the PRIMARY atom. This is a convenience function, and
returns exactly the same thing as XmInternAtom(dpy, "PRIMARY",
False).
putCopy()
Boolean putCopy(Atom selection, Atom target,
XtPointer data, unsigned long numBytes);
Boolean putCopy(Atom selection, const char *targetName,
XtPointer data, unsigned long numBytes);
This method is usually called immediately after a "clear()" and
immediately before "export()" (or "exportData()" if using ViewKit
2.1). These three methods make the "data" specified in the putCopy()
available to any ICCCM client on the indicated "selection", which
should be either PRIMARY or CLIPBOARD. The "data" passed into
"putCopy()" can be free'd immediately after this call, since
"putCopy()" makes a copy of the data.
putReference()
Boolean putReference(Atom selection, Atom target,
XtPointer data, unsigned long numBytes);
Boolean putReference(Atom selection,
const char *targetName,
XtPointer data, unsigned long numBytes);
This method can be used instead of "putCopy()" if the data is so
large that an extra copy is not possible or is terribly inefficient.
This call DOES NOT make a copy of the data, so you must not ever
free "data" until after you "remove()" this data from the currently
exported selection. If for whatever reason the data becomes
invalid, you must call "remove()" to remove this reference.
registerConverter()
void registerConverter(Atom from, Atom to,
ConvertProc converter,
CanConvertProc canConvert = NULL,
void *clientData = NULL);
void registerConverter(const char *fromName,
const char *toName, ConvertProc converter,
CanConvertProc canConvert = NULL,
void *clientData = NULL);
Registers a converter between two data targets. The VkCutPaste
class provides integral support for converters. Converters are used
to extend the targets that your application understands. For
example, if you call "dragAway()" with XPM data (this is an image),
and a drop site in another ICCCM application only accepts images of
type GIF_89, then the drop would normally fail. However, if you
have registered a converter from XPM to GIF_89, the VkCutPaste class
Page 9
VkCutPaste(3x)VkCutPaste(3x)
will automatically call your converter and successfully drop the
GIF_89 on the destination client. This same converter will fire if
you attempt to "import()" a GIF_89 yourself, yet the other client is
only offering XPM. The converter is called to provide you with the
data type you requested. The optional "canConvertProc" is provided
so that your application can conditionally offer conversion support
for a given target. The "canConvert" function returns True if the
converter can perform the requested conversion, and False otherwise.
The "canConvert" function is called by VkCutPaste so that VkCutPaste
doesn't offer targets to requesting clients that cannot actually be
produced. If your conversions will always work under all
circumstances, do not register a "CanConvertProc".
registerDataType()
void registerDataType(Atom target, Atom type, int format,
unsigned long flags = CUTPASTE_NORMAL_TYPE,
DestroyProc destroyProc = NULL,
void *clientData = NULL);
void registerDataType(const char *targetName,
const char *typeName, int format,
unsigned long flags = CUTPASTE_NORMAL_TYPE,
DestroyProc destroyProc = NULL,
void *clientData = NULL);
Registers a data target with the VkCutPaste class, and at the same
time tells the class what the type, format, and flags are. This is
only necessary if the VkCutPaste class has never heard of this
format before (the VkCutPaste class contains an extensive internal
list of known targets, see the REGISTERED TARGETS section for more
information).
The "flags" are a bit mask of the following flags:
CUTPASTE_NORMAL_TYPE, CUTPASTE_FILENAME_TYPE, and
CUTPASTE_HIDDEN_TYPE. Any new filename target as described here
needs to be flagged as a "CUTPASTE_FILENAME_TYPE" so that the
VkCutPaste class can deal with it properly. A
"CUTPASTE_HIDDEN_TYPE" means that this target will never be
published to other clients. This is unusual, but can be useful if
you are using an internal representation you do not wish to ever
expose.
You can optionally specify a function that is called to destroy
auxiliary data associated with this data target. An example usage
of the DestroyProc would be if you need to register a new target as
filename data (CUTPASTE_FILENAME_TYPE).
cnp->registerDataType("MY_FILE", "MY_FILE", 8,
CUT_PASTE_FILENAME_TYPE, fileDestroyProc, NULL);
Before your client calls putCopy() with a filename target, it needs to
Page 10
VkCutPaste(3x)VkCutPaste(3x)
create a file that will be given to the VkCutPaste class. The VkCutPaste
class will call the DestroyProc when this file is no longer needed.
cnp->putCopy(xaCLIPBOARD, "MY_FILE", filename, strlen(filename) + 1);
Now, when the VkCutPaste class no longer needs the file referenced by
filename, the DestroyProc is called. For file targets, the DestroyProc
should remove the file. In the DestroyProc, "data" is a copy of the data
that was made when your client called putCopy(). For this example, data
is the filename that was handed over to the VkCutPaste class.
static void fileDestroyProc(Widget w, Atom selection, Atom target,
XtPointer data, unsigned long numBytes, void * clientData)
{
// DO NOT free the filename itself, just remove the file.
if (target == MY_FILE && data != NULL)
{
char *fname = (char *)data;
unlink(fname);
}
}
Notice that this is only necessary if you need to register a new data
type. See the section "FILE AND DATA OWNERSHIP" for more information.
registerDropSite()
Boolean registerDropSite(Widget w,
Atom *interestList, int interestListLen,
DropSiteCallbackProc dropProc,
void *clientData = NULL);
Registers a widget as a drop site. The "interestList" is an ordered
list of what data targets the drop site will accept. When another
client drops data on this widget, the "dropProc" will be called with
exactly one target. That target is the earliest one found in the
interestList which the other client can supply, or that can be
converted to, see "registerConverter()").
registerDropSiteExtended()
Boolean registerDropSiteExtended(Widget w,
Atom *interestList, int interestListLen,
DropSiteCallbackProc dropProc,
DragCallbackProc dragProc = NULL,
void *clientData = NULL,
Arg *args = NULL, int numArgs = 0);
Page 11
VkCutPaste(3x)VkCutPaste(3x)
This does exactly what "registerDropSite()" does, but provides more
options for the advanced programmer who needs more control. For
example, the programmer could specify the various drop icons by
specifying those parameters in the "args" argument. "Args" and
"numArgs" are passed off to XmDropSiteRegister(). The following
"args" are not allowed: XmNdragProc, XmNdropProc,
XmNdropSiteOperations, XmNinportTargets, XmNnumImportTargets. See
the XmDropSite man page for information on other valid arguments.
Motif's Drop Copy protocol (XmDROP_COPY) is the only drag and drop
operation supported. Possible "reasons" that are passed to the
DragCallbackProc are: XmCR_DROP_SITE_LEAVE_MESSAGE,
XmCR_DROP_SITE_ENTER_MESSAGE, and XmCR_DROP_SITE_MOTION_MESSAGE.
registerLoseSelection()
Boolean registerLoseSelection(Atom selection,
LoseSelectionProc loseSelProc,
void *clientData);
The "loseSelProc" will be called when this application loses the
selection ownership to some other client. This is very useful in
the case of PRIMARY, since in the loseSelProc callback the
application should un-highlight what was previously highlighted as
the PRIMARY selection.
remove()
Boolean remove(Atom selection, Atom target);
Removes the indicated "target" from the currently exported
selection. For example, if you had called "putReference(XPM)" and
now the XPM data has become invalid for some reason, you must call
"remove(XPM)".
setTransactionsTimeout()
void setTransactionsTimeout(unsigned long numSeconds);
Sets the transaction timeout. The default Motif timeout is 5
seconds, which means that if the remote client does not respond to a
request for data within 5 seconds, the transaction is canceled and
no data is transferred. For some large data targets, or those that
require long conversions, 5 seconds may not be adequate.
unregisterDropSite()
Boolean unregisterDropSite(Widget w);
Unregisters a drop site. This makes it stop accepting drops of any
kind.
Page 12
VkCutPaste(3x)VkCutPaste(3x)EXAMPLES
This section provides examples to help get you started using the
VkCutPaste class. For a detailed description on data and file ownership
during cut/paste and drag/drop operations, see the section "FILE AND DATA
OWNERSHIP".
There are four separate actions supported by the VkCutPaste class:
COPY
- make some data available to another X-Client
PASTE
- import data from another X-Client
DRAG
- drag some data away to another X-Client
DROP
- accept some data that is dropped on us
Before you can use any of this support, you must instantiate the
VkCutPaste class in your program (probably at program startup). This can
be done with the following two lines of code, where "someWidget" is any
widget in your Motif or ViewKit program that will be valid during the
lifetime of the VkCutPaste class:
#include <Vk/VkCutPaste.h>
cnp = new VkCutPaste(someWidget);
COPY - In your application, let's imagine that an XPM image is currently
highlighted, and that the user has selected the Copy menu item from the
Edit menu. In the menu Callback, you might put the following code:
extern XtPointer image; // ptr to XPM Image buffer
extern unsigned long numBytes; // num bytes of Image data
Atom xaCLIPBOARD = cnp->clipboardAtom();
Atom xaXPM = XmInternAtom(dpy, "XPM", False);
cnp->clear(xaCLIPBOARD); // clear clipboard
cnp->putCopy(xaCLIPBOARD, xaXPM, image, numBytes);
cnp->export(xaCLIPBOARD); // make it available
Now any application on your desktop is able to "Paste" the data (assuming
of course that the destination application has implemented standard X-
Window Copy and Paste). To make this data available on the PRIMARY
selection, you could simply substitute xaCLIPBOARD with XA_PRIMARY (or
cnp->primaryAtom()).
Page 13
VkCutPaste(3x)VkCutPaste(3x)
PASTE - In your application, let's imagine that the user has selected the
Paste menu item from the Edit menu, and that you are willing to paste
either a GIF Image or an XPM Image. In the menu Callback, you might put
the following code:
XtPointer image;
unsigned long numBytes;
Atom targetRet;
Atom xaCLIPBOARD = cnp->clipboardAtom();
Atom xaGIF = XmInternAtom(dpy, "GIF_89", False);
Atom xaXPM = XmInternAtom(dpy, "XPM", False);
Atom interestList[2];
interestList[0] = xaGIF_89; // we first prefer GIF Image
interestList[1] = xaXPM; // we also accept XPM Image
int numItemsInList = 2;
image = cnp->importImmediate(xaCLIPBOARD, interestList,
numItemsInList, &targetRet, &numBytes);
if (image == NULL)
printf("No Images available.");
else if (targetRet == xaGIF)
printf("We received a GIF Image.");
else if (targetRet == xaXPM)
printf("We received an XPM Image.");
The image that is returned should eventually be freed with
"XtFree(image);" The list of "targets" you are willing to accept can be
arbitrarily long, and just happens to be "2" in this example.
DRAG - In your application, let's imagine that the user has just pressed
a mouse button down on an XPM Image and has begun dragging it out of your
application to be dropped on another application. At the moment you want
the drag to begin, you might put the following code:
extern XtPointer image; // ptr to XPM Image data
extern unsigned long numBytes; // num bytes of Image data
extern XEvent *xev; // X-event causing drag
extern Widget theWidget; // widget where drag begins
Atom xaXPM = XmInternAtom(dpy, "XPM", False);
cnp->dragAwayCopy(theWidget, xev, xaXPM, image, numBytes);
The "dragAwayCopy" makes a copy of your data, and so you can free the
image data immediately after the call. There are two optional parameters
Page 14
VkCutPaste(3x)VkCutPaste(3x)
that are not usually specified, but if you wish to know when the dragAway
is finished, or if the dragAway was successful or not, you can pass in a
callback procedure and any data you like. This would look like:
// dragAwayCB is invoked after completion of the dragAway
//
void dragAwayCB(Widget w, Boolean dragSuccess,
XtPointer clientData)
{
printf("Drag success=%d.", dragSuccess);
printf("ClientData=%d.", clientData);
}
cnp->dragAwayCopy(theWidget, xev, xaXPM, image, numBytes,
dragAwayCB, (XtPointer) 123);
DROP - In your application, let's imagine that you want to accept a
"drop" on a certain widget of either an XPM Image or a GIF Image. After
you create the widget that will be "dropped" on, you might write the
following code:
Atom xaXPM = XmInternAtom(dpy, "XPM", False);
Atom xaGIF = XmInternAtom(dpy, "GIF_89", False);
// dropProcCB - invoked whenever anyone drops an image
// on the widget
//
void dropProcCB(Widget w, Atom target, XtPointer data,
unsigned long numBytes, int x, int y,
XtPointer clientData)
{
if (target == xaXPM)
printf("XPM Image dropped at x=%d, y=%d.", x, y);
else if (target == xaGIF)
printf("GIF Image dropped at x=%d, y=%d.", x, y);
// eventually you should "XtFree(data)" to free the mem
}
// this code is done once, and makes the indicated widget
// a "DropSite"
//
extern Widget theWidget; // the widget that is
// to become a dropSite
Atom interestList[2];
interestList[0] = xaXPM; // we first prefer XPM
interestList[1] = xaGIF_89; // we also accept GIF
int numItemsInList = 2;
Page 15
VkCutPaste(3x)VkCutPaste(3x)
cnp->registerDropSite(theWidget, interestList,
numItemsInList, dropProcCB, (XtPointer) 123);
The list of "targets" you accept on the DropSite can be arbitrarily long,
and just happens to be "2" in this example.
ADVANCED EXAMPLES
The above examples show the most simple uses of the VkCutPaste library.
However, we support much more functionality for those programmers who
wish to customize the behavior in some way, or have additional needs.
REGISTERING CONVERTERS - The VkCutPaste library provides integral support
for converters. It has unified the interface, so that once the programmer
registers one converter, it will convert for Drag, Drop, Copy and Paste
invisibly. The example code below places only an XPM Image on the
clipboard, yet the VkCutPaste class offers up both the XPM Image and also
a GIF Image, because the appropriate converter has been registered.
Atom xaXPM = XmInternAtom(dpy, "XPM", False);
Atom xaGIF = XmInternAtom(dpy, "GIF_89", False);
Atom xaCLIPBOARD = cnp->clipboardAtom();
extern XtPointer image; // ptr to XPM Image buffer
extern unsigned long numBytes; // num bytes of Image data
Boolean convertXPMtoGIF(Widget w, Atom selection,
void *clientData, Atom srcTarget, XtPointer src,
unsigned long numSrcBytes, Atom dstTarget,
XtPointer *dst, unsigned long *numDstBytes)
{
// code to convert from XPM Image to GIF omitted, but
// this will malloc space for the dst image, and set
// *numDstBytes to indicate the number of bytes
// malloc'ed, and set *dst to point at the new image
}
cnp->registerConverter(xaXPM, xaGIF, convertXPMtoGIF);
cnp->clear(xaCLIPBOARD); // clear clipboard
cnp->putCopy(xaCLIPBOARD, xaXPM, image, numBytes);
cnp->export(xaCLIPBOARD); // make it available
At this point, if any other application asks us for a GIF Image, we will
supply it by calling the convertXPMtoGIF() converter function on the fly.
Also, if we ask specifically to import a GIF at this point with the
Page 16
VkCutPaste(3x)VkCutPaste(3x)
following code:
image = cnp->importImmediate(xaCLIPBOARD, &xaGIF, 1,
&targetRet, &numBytes);
then we will successfully get a GIF Image even if the remote client is
only offering a XPM Image. The converter will fire during the
"importImmediate()" call to supply us with the correct data. This same
converter will fire automatically now on DragAway calls and also on Drop
calls.
FILE AND DATA OWNERSHIP
The pseudocode below details the ownership of files and data during
different stages of cut/paste and drag/drop. The examples show
copy/paste and drag/drop of stream data, and of filename data.
Filename data simply means the data that is transfered is a filename.
For example, when transferring a XPM_FILE target, the data transferred is
actually the filename, not the data contained in the file. The receiving
application will need to retrieve the filename, then access the file.
The VkCutPaste class will only recognize targets as being filename
targets if they have been registered with the CUTPASTE_FILENAME_TYPE flag
(see registerDataType()). See the "REGISTERED TARGETS" section below for
a list of targets which have been pre-registered.
A note on filename targets
It should be noted that applications should rarely need to use filename
targets for cut/paste and drag/drop operations. In fact exchanging
filenames with other applications simply WILL NOT WORK when the sender
and receiver applications are running on different computers. When given
a choice between filename targets and the corresponding data stream
targets, applications should always exchange the data stream targets.
In the examples below, cnp is an instance of the VkCutPaste class, and
filename target is any target which has been registered with the
CUTPASTE_FILENAME_TYPE flag (see registerDataType()).
Copy of Filenames:
//
// Create a file on disk. Ownership of the file will be transferred
// to the VkCutPaste class at putCopy() time.
//
char *filename = create a file, return the malloc'ed filename;
//
// Clear any prior putCopy() or export().
Page 17
VkCutPaste(3x)VkCutPaste(3x)
//
cnp->clear();
//
// Copies the filename 'filename', and transfers the ownership of the
// file on disk to the VkCutPaste class. Note that the file itself
// is NOT copied, only the filename. The client can now free the
// memory used by filename, but must NOT reference the disk file
// again.
//
cnp->putCopy(filename);
//
// The VkCutPaste class has made a copy of the filename, so the
// original data should be freed by the client.
//
free(filename);
//
// Make the data available to other clients.
//
cnp->export();
...
//
// Some time later, if the VkCutPaste class gets a request for this
// filename, the VkCutPaste class will clone the file, and hand off to // the requesting client the cloned filename. Ownership of this
// cloned file is transferred to the requesting client.
//
...
//
// The next time clear() is called, any data that has been copied
// during prior putCopy() calls is freed, and any files that the
// VkCutPaste class has obtained ownership of during prior putCopy()
// calls are removed. After this clear(), this VkCutPaste instance
// no longer has any data available for export.
//
cnp->clear();
Copy of Stream Data:
//
// Create some data in memory.
//
char *data = create some data;
//
Page 18
VkCutPaste(3x)VkCutPaste(3x)
// Clear any prior putCopy() or export().
//
cnp->clear();
//
// The VkCutPaste class makes a copy of the data. This copy of
// the data will be freed during the next "clear()" operation.
//
cnp->putCopy(data);
//
// The VkCutPaste class has made a copy of the data, so the original
// data should be freed by the client.
//
free(data);
//
// Make the data available to other clients.
//
cnp->export();
...
//
// The next time clear() is called, any data that has been copied
// during prior putCopy() calls is freed, and any files that the
// VkCutPaste class has obtained ownership of during prior
// putCopy() calls are removed. After this clear(), this
// VkCutPaste instance no longer has any data available for export.
//
cnp->clear();
Paste of Filenames:
//
// Client requests a filename target. The filename returned and
// the corresponding file on disk are now owned by this client. It
// is therefore the responsibility of the requesting client to remove
// (unlink()) the file when the client is finished with it, and
// free the filename.
//
cnp->importImmediate(filename);
//
// After this client is done with the file, the file must be
// removed, and the filename freed.
//
unlink(filename);
free(filename);
Page 19
VkCutPaste(3x)VkCutPaste(3x)
Paste of Stream Data:
//
// Client requests the data. This data is now owned by this
// client. The client will use data, and should free it when
// it is done processing the data.
//
cnp->importImmediate(data);
//
// Free the imported data when you are done processing it.
//
free(data);
Drag of Filenames:
//
// Create a file on disk. Ownership of the file will be
// transferred to the VkCutPaste class at dragAwayCopy() time.
//
char *filename = create a file, return the malloc'ed filename;
//
// Copies the filename 'filename', and transfers the ownership of the
// file on disk to the VkCutPaste class. Note that the file itself
// is NOT copied, only the filename. The client can now free the
// memory used by filename, but must NOT reference the disk file
// again. The VkCutPaste class will free this copy of the data, and
// remove the file when the drag and drop operation is complete.
//
cnp->dragAwayCopy(filename);
//
// The VkCutPaste class has made a copy of the filename, so the
// original data should be freed by the client.
//
free(filename);
...
//
// Some time later, if the VkCutPaste class gets a request for this
// filename, the VkCutPaste class will clone the file, and hand off
// the cloned filename to the requesting client. Ownership of this
// cloned file is transferred to the requesting client. The
// original file is removed when the drag and drop operation is
// complete.
//
Drag of Stream Data:
Page 20
VkCutPaste(3x)VkCutPaste(3x)
//
// Create some data in memory.
//
char *data = create some data;
//
// The VkCutPaste class makes a copy of the data. The VkCutPaste
// class will free this copy of the data when the drag and drop
// operation is complete.
//
cnp->dragAwayCopy(data);
//
// The client can now free the original data.
//
free(data);
Drop of Filenames:
//
// The "drop" client registers a drop site.
//
cnp->registerDropSite(dropFilenameCallback);
...
//
// Some time later, the dropFilenameCallback() routine is called.
// Inside of the dropFilenameCallback, the filename passed in and
// the corresponding file on disk are now owned by this client. It
// is therefore the responsibility of the requesting client to remove
// (unlink()) the file when the client is finished with it, and free
// the filename.
//
dropFilenameCallback(filename)
{
// Do some processing on the file.
unlink(filename); // After this client is done with
// the file, the file must be removed,
free(filename); // and the filename freed.
}
Drop of Stream Data:
//
// The "drop" client registers a drop site.
//
cnp->registerDropSite(dropDataCallback);
Page 21
VkCutPaste(3x)VkCutPaste(3x)
...
//
// Some time later, the dropDataCallback() routine is called.
//
dropDataCallback(data)
{
// Do some processing with this data.
//
// Free the data when you are done processing it.
//
free(data);
}
REGISTERED TARGETS
Filename Targets
AIFF_C_FILE, AIFF_FILE, APPLE_QUICKTIME_FILE, AUTODESK_3DS_FILE,
AUTODESK_DXF_FILE, AVID_OMFI_FILE, AVI_FILE, FITS_FILE, GIF_89_FILE,
HTML_FILE, IGES_FILE, INVENTOR_2_0_FILE, INVENTOR_2_1_FILE, JFIF_FILE,
MPEG_1_AUDIO_FILE, MPEG_1_VIDEO_FILE, NEXT_FILE, PGM_FILE, PHOTO_CD_FILE,
PIXAR_RIB_FILE, PNM_FILE, PPM_FILE, SD2_FILE, SGI_AUDIO_FILE,
_SGI_AUDIO_FILENAME, SGI_MOVIE_FILE, _SGI_MOVIE_FILENAME,
SGI_RGBIMAGE_FILE, _SGI_RGB_IMAGE_FILENAME, SGI_SHOWCASE_FILE,
SOFTIMAGE_DSC_FILE, SOFTIMAGE_HRC_FILE, TIFF_FILE, VRML_1_0_FILE,
WAVERONT_OBJ_FILE, WAVE_FILE, XPM_FILE
Stream Targets
AIFF, AIFF_C, APPLE_QUICKTIME, AUTODESK_3DS, AUTODESK_DXF, AVI,
AVID_OMFI, BACKGROUND, BITMAP, CLASS, CLIENT_WINDOW, COLORMAP,
COMPOUND_TEXT, DECNET_ADDRESS, DRAWABLE, FILE_NAME, FITS, FOREGROUND,
GIF_89, HOSTNAME, HOST_NAME, HTML, IGES, INVENTOR, INVENTOR_2_0,
INVENTOR_2_1, IP_ADDRESS, JFIF, MPEG_1_AUDIO, MPEG_1_SYSTEMS,
MPEG_1_VIDEO, MULTIPLE, NAME, NEXT, ODIF, OWNER_OS, PGM, PHOTO_CD,
PIXAR_RIB, PIXMAP, PNM, PPM, SD2, SGI_AUDIO, _SGI_AUDIO, _SGI_ICON,
SGI_MOVIE, _SGI_MOVIE, SGI_RGBIMAGE, _SGI_RGB_IMAGE, SGI_SHOWCASE,
SOFTIMAGE_DSC, SOFTIMAGE_HRC, STRING, TARGETS, TEXT, TIFF, TIMESTAMP,
USER, VRML_1_0, WAVE, WAVERONT_OBJ, XPM
AUTHORSVkCutPaste was written by Jim Young and Brian Wilson of Silicon Graphics,
Inc.
INHERITED MEMBER FUNCTIONS
Inherited from VkComponent
installDestroyHandler(), removeDestroyHandler(), widgetDestroyed(),
setDefaultResources(), getResources(), VkComponent(), manage(),
unmanage(), baseWidget(), okToQuit(), _name, _baseWidget, _w,
Page 22
VkCutPaste(3x)VkCutPaste(3x)
deleteCallback
CLASSES USED BY THIS CLASS
None
SEE ALSO
VkComponent, VkApp
Inter-Client Communications Conventions Manual, Version 2.0
ViewKit Programmer's Guide
The X Window System, DEC Press, Bob Sheifler and Jim Gettys
The X Window System Toolkit, DEC Press, Paul Asente and Ralph Swick
The OSF/Motif Programmers Reference, Prentice Hall, OSF
Page 23