intercept a fact that some app copied something to clipboard? (RiscOS Cloverleaf)
Sergey Lentsov (8268) 63 posts |
Hello, I would like to try to implement shared Clipboard in the RPCEmu so RiscOS clipboard contents can be copied to host system and back. Right now I have a problem how to intercept a fact that some app copied something to clipboard. As I understand the RiscOS does not have a separate clipboard and every app must keep clipboard contents in itself and provide to others by Message_DataRequest, is it right? |
Andreas Skyman (8677) 170 posts |
This would be fantastic! Even just one way, e.g. host to emulated, would be a wonderful improvement! |
Jeffrey Lee (213) 6048 posts |
I ran into this same problem when adding clipboard support to the VNC server (the server needs to notify the client of all clipboard changes). The solution I went with was to check for new clipboard contents 25cs after the last key/mouse button press. That way it should detect any changes which were triggered by keyboard shortcuts or menu items, without also causing constant checking while people are typing normally (assuming they have a reasonable typing speed!) Most of the code for this is in task.c in the server sources (http://www.phlamethrower.co.uk/riscos/vnc_serv.php)
There’s also some code in there for translating to/from ISO 8859-1 (which is what’s used by the basic VNC clipboard protocol), you can probably replace that with UTF-8 or similar. |
Sergey Lentsov (8268) 63 posts |
@Jeffrey Lee |
Steve Fryatt (216) 2105 posts |
Just an observation on this, which has come to light in the past week or so… While it sounds as if it’s not an issue for Jeffrey’s algorithm, another trick used by several applications is to send a Message_DataRequest immediately on receipt of a Message_ClaimEntity, in order to find out what has happened. Even if the application then doesn’t follow up on the resulting MessageRamFetch or Message_DataSave from the clipboard owner, it seems that this can go badly wrong as soon as two applications are trying to play the same game. If both send a Message_DataRequest in the same poll as the Message_ClaimEntity arrives, which is the natural thing to do, that can result in the clipboard owner sending out two concurrent Message_DataSaves. If it isn’t designed to handle multiple message exchanges in parallel (and a lot of apps are not designed in that way), then this will go badly wrong as soon as the “wrong” application sends back a Message_DataSaveAck and the references don’t match. The solution seems to be for applications which try to follow the clipboard around to simply set a flag on receipt of Message_ClaimEntity and then send the Message_DataRequest on the next null event. I’ve just had to do this for Clipper (which will be out as an update “soon”), because much stuff was breaking when Clipper ran on a system alongside UniServe (which is doing exactly the same trick as Clipper). The sequence of events is roughly:
Note that Clipper never sends the Message_DataSaveAck, as it doesn’t want the data — it just wants to know where it is. That doesn’t matter, though, as it only needs one of the applications to attempt to take the data for this to all fall over in a heap. ETA: Arguably Clipper and UniServe are both in the right here, but it’s not clear in the PRMs whether multiple Data Transfer exchanges can happen in parallel and many applications don’t seem to allow for such a scenario. Remember that the clipboard additions to the Data Transfer Protocol post-date the PRMs by several years. The app which led to the discovery above had the decency to check the references and stop with an error; I’m aware of another well-known title which just seems to carry on talking to UniServe as if it was Clipper… |
David J. Ruck (33) 1635 posts |
This a is a very good point. It’s also a reminder when thinking about SMD that it’s not just the strict ordering of message sending, wimp polls and responses that needs to be maintained, but also that the vast majority of applications can only have one data save protocol sequence in flight at any one time. |