Documentation: Clipboard and Primary Selection [Remove Frame]
|
FOX supports three different ways of moving or copying data between applications:
All three methods can exchange essentially arbitrary amounts of data, or arbitrary types. Exchanges may take place between different controls in the same application, or different controls in different applications. Under X-Windows, the different applications may even be running on different machines of different types.
Whether using the clipboard, drag and drop, or primary selection, applications must first agree on the types of data being exchanged. A single piece of data, for example, an image, may be exchanged using different representations. For an image, for instance, the transfer may take place as GIF or BMP formats.
To increase the odds that both the originating application and the receiving one support the same data representations, the originating application can furnish its list of supported representations for the data. The receiving application, after inspecting this list, can then ask for the one format of the supplied list it also supports.
Registering Clipboard Types
|
In order to communicate a particular data structure across applications,
both partners need to first register a Drag Type. Registering a
drag type yields a unique number which is guaranteed to be the same for
all applications on the desktop.
The Drag Type is created by calling the function:
FXDragType FXApp::registerDragType(const FXString& name) const;
The registerDragType() function registers a new Drag Type name on the application's desktop, and returns an abstract handle to the Drag Type. The returned handle is used in all subsequent clipboard, drag and drop, or primary selection operations to signify the data type being exchanged.
Chosing one of the standard MIME types. for commonly available data streams will ensure that data can be exchanged between FOX programs and programs written using other toolkits.
The function:
FXString FXApp::getDragTypeName(FXDragType type) const;
will return the Drag Type Name, given the Drag Type type. You may need to use this in case your application receives a drop of an unknown type, and you need to decide what to do with it.
Clipboard Exchange
|
The clipboard is a single facility on the desktop which can be interrogated about the
types of objects currently retained, and the contents of these objects.
The clipboard is said to be owned by a window, meaning that whenever
such a query must be asnwered, that particular window is the one which will be
asked.
The advantage of this model is that it permits an easy-going decentralized
scheme where 3rd-party widgets can implement any number of clipboard data types
without any need for central coordination.
Moreover, the originator can furnish a large number of potential formats for
the clipboard selection, yet will only be called upon to actually supply one
of these formats during the transaction.
Upon performing a Cut or Copy to clipboard operation, the originating widget will claim ownership of the clipboard by calling:
FXbool FXWindow::acquireClipboard(const FXDragType *types,FXuint numtypes);
where types is a list of Drag Types previously registered (see above), and numtypes is the number of such types.
When one widget acquires the clipboard, the previous widget which owned the clipboard will receive a message of type SEL_CLIPBOARD_LOST, which should cause that widget to release all data previously retained regarding the clipboard operation.
If the caller has successfully invoked acquireClipboard(), it can allocate storage to remember the clipboard selection in. As it may be requested to furnish the selection in any of the previously stated data types, it may have to remember multiple representations of the clipboard selection.
The widget calling acquireClipboard() will receive a message of type SEL_CLIPBOARD_GAINED.
To voluntarily release the clipboard, a widget may call:
virtual void FXWindow::releaseClipboard();
This will cause the calling widget to receive a message of type SEL_CLIPBOARD_LOST, just as if some other widget had called acquireClipboard().
The proper response to receiving a SEL_CLIPBOARD_LOST message is to release the clipboard selection data:
long MyWidget::onClipboardLost(FXObject* sender,FXSelector sel,void* ptr){ BaseClassOfMyWidget::onClipboardLost(sender,sel,ptr); ... free the data ... return 1; }
A widget which wants to obtain the clipboard selection can ask for the entire list of clipboard types by calling:
FXbool inquireDNDTypes(FXDNDOrigin origin,FXDragType*& types,FXuint& numtypes) const;
Where the parameter origin should be set to FROM_CLIPBOARD. The result will be placed in an array of Drag Types types of length numtypes.
Often, the requesting widget can deal with only one single type of data; for such cases, its more convenient to be able to ask if one particular Drag Type is supported by the originator:
FXbool offeredDNDType(FXDNDOrigin origin,FXDragType type) const;
Where again, origin must be set to FROM_CLIPBOARD, and type is the type which we want to know about.
In even simpler scenarios, the requesting widget may simply ask for the clipboard data of a certain datatype. This is appropriate if there is no special action needed in preparation to receiving the data.
A widget can obtain the data using:
FXbool getDNDData(FXDNDOrigin origin,FXDragType type,FXuchar*& data,FXuint& size) const;
Once more, origin is set to FROM_CLIPBOARD. The requested type is given in type. Upon successful return, data will refer to a byte array containing the clipboard selection data, and size will contain the length of this data array. If the originating widget is unable to furnish the requested data type, getDNDData() returns FALSE and the data and size will be set to NULL and 0, respectively.
The requesting widget is now resposible for deleting the memory, which must be done using FXFREE().
When a widget requests data using getDNDData(), a message of type SEL_CLIPBOARD_REQUEST is issued to the widget owning the clipboard. The originating widget must call:
FXbool setDNDData(FXDNDOrigin origin,FXDragType type,FXuchar* data,FXuint size) const;
With origin set to FROM_CLIPBOARD, type to the requested data type. The originating widget must allocate (using FXMALLOC) and fill a data array with the clipboard selection and pass a reference to data, and the size of the array in size.
After handing the array to setDNDData(), the originating widget no longer owns the data array and should make NO attempts to free it!
To figure out which datatype was requested by the requesting widget, the originating widget can inspect the target member of the FXEvent structure passed in the SEL_CLIPBOARD_REQUEST message pointer.
A typical widget implementation first lets its base class inspect the Drag Type, and if it was not handled yet, inspects it itself:
long MyWidget::onClipboardRequest(FXObject* sender,FXSelector sel,void* ptr){ // See if base class knows how to deal with the requested clipboard type if(BaseClassOfMyWidget::onClipboardRequest(sender,sel,ptr)) return 1; // See if we can deal with this type ourselves if(((FXEvent*)ptr)->target==mydataType){ FXuchar *data; FXuint len; ... FXMALLOC(&data,FXuchar,len); ... fill data ... // Give the array to the system! setDNDData(FROM_CLIPBOARD,event->target,data,len); // Return 1 because it was handled here return 1; } // Return 0 to signify we haven't dealt with it yet; a derived // class from MyWidget may yet give it another try ... return 0; }
Thus, MyWidget itself can also be subclassed so as to add even more data types!
Clipboard Originator
|
Clipboard Requestor
|
Primary Selection Exchange
|
Also, upon receiving a SEL_SELECTION_LOST, typically all that happens is that the text is deselected, instead of deleted.
When exchanging via primary selection, the origin parameter is normally set to FROM_SELECTION.
Copyright © 1997-2022 Jeroen van der Zijp |