The Clipboard feature within CPS has existed in the earliest WinFrame going back to 1995. I remember Marc Bloomfield working on this from even before this time. It was one of the first virtual channel features that was new to WinFrame. Many of the virtual channels were direct descendants of WinView. I still remember seeing it working for the first time. Very exciting at the time!
The idea was fairly straightforward. It was thought that it should be possible to be able to cut from one side (server or client) and paste to the other side. It sounded easy but how it works is a bit more involved.
The Clipboard has been around in Windows since Windows 1.0 in 1985. I’m certain that the Mac had it before that and also sure that the idea could even predate the Xerox PARC systems. The point is that the clipboard is key to supporting any cut/copy/paste operations.
There are some basic rules about clipboards that should always be followed on Windows. First of all, all things in the clipboard are controlled by the user. In other words, the program has no rights to add or remove anything unless the user has indicated that it should be done. In a way, the clipboard is seen as a way station for data to be transferred either within the program or outside the program.
Second of all, the clipboard should only contain one item as a whole. In the whole it can have many sub-elements but in no way should it allow for multiple different chunks of content to be inserted into the clipboard at the same time. It is possible to have a blob that contains many sub-elements but not to have many pieces at once.
The basic operation of the clipboard is that when a user issues a cut or copy, the program will take the selected data and submit it to the clipboard. The format of the data is dependent on what the program supports and whether it is a known format or a new registered format (considered private). It is legal to submit the data in multiple formats to the same clipboard. In fact, it is encouraged to do this so that other programs can actually read the data in the formats they are used to.
As an example of this, if you cut a selection of text from a word processor, the text will be stored in at least two different formats. One will be considered basic text and the other rich text format. The basic text rendition will only have the text whereas the rich text format (RTF) will have the formatting and potentially the possibility of doing pictures. In Microsoft’s world of doing clipboard, there are plenty of options of how to handle these requests.
The most simple model is this:
User does cut/copy
Program clears current clipboard
Program sets new data into clipboard
User does paste
Program gets data from clipboard
The interesting fact is that when the program to set clipboard data (SetClipboardData) it is allowed to do as many sets as it wants for as many formats as it wants. When it does the set, it needs to allocate a chunk of global memory that it will never touch again. It becomes Windows responsibility to free the memory when the next program issues the clear clipboard call (EmptyClipboard). The global block of memory contains all the data needed for that format and it makes it easy to transfer to other programs. It is kind of like taking a picture of data and then making it publicly available to other programs that understand that format.
There is a model of doing delayed rendering whereby you can delay putting data into the clipboard. This is done to avoid wasteful use of memory for large clipboard items. The idea calls for specifying that a format exists in the clipboard but not actually specifying the data. When another program goes to get the clipboard data, Windows will notify the clipboard owner that it needs to give the memory contents now. This is done by calling SetClipboardData during the WM_RENDERFORMAT message processing. This is just a simple example of how it would be handled since there are two other possible window notifications with WM_RENDERFORMATALL and WM_DESTROYCLIPBOARD.
The delayed rendering turns out to be a very important technique for supporting Citrix ICA clipboard support. Without this aspect, it would be necessary to download all the clipboard data every time the clipboard data changed. The essential design calls for only downloading the information when the programs request it. So, if the user cuts something on the server, it will only be transferred to the client if the user pastes on the client after the cut. If this was not true, the cut/copy operations on each side would need to be duplicated on the opposite machine. This would be bad since not all cut/copy operations are destined to be located on the other machine. There would be much wasted bandwidth and more than likely the data would interfere with more important data like keyboard/mouse/video traffic.
The ICA protocol that handles the clipboard data is fairly simple. There is only nine packet types that are used for the clipboard. Of these, four are used for initialization.
The client and server negotiate what they can support by working together. This includes the public and private formats. Once negotiated, these are the only formats allowed to be transferred between sides. The clipboard driver uses the virtual channel as a conduit for the clipboard data. Once a format is requested, the transfer will be split into multiple pieces if the transfer is bigger than what an ICA packet can handle.
In the next installment I will focus on the registered (private) formats and how it currently works with our clipboard driver. I will also cover some of the things discovered while working on PortICA related to the clipboard.