The Clipboard
- Feature Owner
- Mike Pinkerton
Overview
This document describes the Clipboard Service, used to transfer data with mozilla and other applications via the native OS clipboard and assumes the reader is familiar with the Transferable object discussed in the previous document. The meat of this API can be found in nsIClipboard.
Using The Clipboard
There are two key routines in the clipboard API, one for placing the data in a given transferable on the clipboard, the other for retreiving the data from the clipboard based on the flavors registered in the transferable:
/** * Given a transferable, set the data on the native clipboard * * @param aTransferable The transferable * @param anOwner The owner of the transferable * @result NS_Ok if no errors */ void setData ( in nsITransferable aTransferable, in nsIClipboardOwner anOwner) ; /** * Given a transferable, get the clipboard data. * * @param aTransferable The transferable * @result NS_Ok if no errors */ void getData ( in nsITransferable aTransferable ) ;
When calling getData()
, only
data corresponding to registered flavors will be copied from
the native clipboard into the transferable. Any other data
that may be on the native clipboard will be ignored.
Note that setData()
may not
actually place the data on the clipboard, but may place a
"promise" which will be fulfilled when the data is actually
requested. As a result, there is another API call to ensure
that the data physically makes it to the clipboard:
/** * Some platforms support deferred notification for putting data on the clipboard * This method forces the data onto the clipboard in its various formats * * @result NS_OK if successful. */ void forceDataToClipboard ( ) ;
forceDataToClipboard()
should be called before the application terminates,
otherwise the promise can never be fulfilled and the
clipboard will be empty after the application finishes
shutting down. If there is nothing on the clipboard, this is
a no-op and is harmless to call.
To round out the API, there is one more routine which can be used to determine if there is any applicable information on the clipboard, for example, to enable the "Paste" menu item only if there is data of the appropriate flavor on the clipboard.
/** * This provides a way to give correct UI feedback about, for instance, a paste * should be allowed. It does _NOT_ actually retreive the data and should be a very * inexpensive call. All it does is check if there is data on the clipboard matching * any of the flavors in the given list. * * @aFlavorList - nsISupportsString's in a nsISupportsArray (for JavaScript). * @outResult - if data is present matching one of * @result NS_OK if successful. */ boolean hasDataMatchingFlavors ( in nsISupportsArray aFlavorList ) ;
hasDataMatchingFlavors()
should be an inexpensive call and does not actually transfer
any data to or from the clipboard. As a result, it can be
called whenever needed without too much worry about
performance.
Example
Here's an example of how you get the data off the clipboard. Notice that this snippet can understand two distinct data flavors, and prefers HTML over plain text. When the data is copied
// 1. get the clipboard service var clipboard = Components.classes["component://netscape/widget/clipboard"].getService(); if ( clipboard ) clipboard = clipboard.QueryInterface(Components.interfaces.nsIClipboard); // 2. create the transferable var trans = Components.classes["component://netscape/widget/transferable"].createInstance(); if ( trans ) trans = trans.QueryInterface(Components.interfaces.nsITransferable); if ( trans && clipboard ) { // 3. register the data flavors you want, highest fidelity first! trans.addDataFlavor("text/html"); trans.addDataFlavor("text/unicode"); // 4. get transferable from clipboard clipboard.getData ( trans ); // 5. ask transferable for the best flavor. Need to create new JS // objects for the out params. var dataObj = new Object(); var bestFlavor = new Object(); var len = new Object(); trans.getAnyTransferData ( bestFlavor, dataObj, len ); if ( bestFlavor.value == "text/html" || bestFlavor.value == "text/unicode" ) { if ( dataObj ) dataObj = dataObj.value.QueryInterface(Components.interfaces.nsISupportsWString); if ( dataObj ) { // ...do something with the data. remember len is in bytes, not chars var id = dataObj.data.substring(0, len.value / 2); } } }