How to copy the canvas contents to the clipboard? Topic is solved
Moderators: FranklinDM, Lootyhoof
How to copy the canvas contents to the clipboard?
I'm trying to improve my screenshot extension (Simple Screenshot, a fork of Easy Screenshot). At first release, I had only done the necessary rebranding. Now I did some substantial cleanup and added a few small features like a context menu entry and setting output file names from the URL. One other thing I wanted to add is to copy the screenshot to the clipboard instead of writing to file. I read the source for other similar extensions, searched on udn.realityripple.com, MDN, stackoverflow, etc but I couldn't come up with anything working and got very confused along the way. There's "goDoCommand", and "commandDispatcher", and "clipboard.set" and probably some other stuff. Can anyone give me some pointers about how to proceed on this?
- RealityRipple
- Astronaut
- Posts: 659
- Joined: 2018-05-17, 02:34
- Location: Los Berros Canyon, California
- Contact:
Re: How to copy the canvas contents to the clipboard?
How about using blobs? Canvas has a toBlob function and ClipboardItem can be constructed using a blob type. Should do the trick.
Re: How to copy the canvas contents to the clipboard?
There is also the XPCOM clipboard component (nsIClipboard in tandem with nsTransferable) which in theory should be able to store arbitrary data, but I never used it for something that is not a string so I don't know how hard it is to make it work with pictures.
Still, it's there and you might want to take a look anyway.
Still, it's there and you might want to take a look anyway.
Re: How to copy the canvas contents to the clipboard?
@RealityRipple Thanks but I still couldn't figure it out. I keep getting a "navigator.clipboard is undefined" error.
@vannilla I had seen that one but couldn't get that to work either. I'll have another try.
Basically what I want is a function that takes a canvas object and puts its contents into the clipboard. I feel like a plain JS function in a separate JS source file is not in the right context to do this. Maybe some imports are needed? For example another extension uses "goDoCommand('cmd_copyImageContents')" but when I try that I get an error saying that "goDoCommand" is not available. I can't understand how the JS/XUL namespace works.
@vannilla I had seen that one but couldn't get that to work either. I'll have another try.
Basically what I want is a function that takes a canvas object and puts its contents into the clipboard. I feel like a plain JS function in a separate JS source file is not in the right context to do this. Maybe some imports are needed? For example another extension uses "goDoCommand('cmd_copyImageContents')" but when I try that I get an error saying that "goDoCommand" is not available. I can't understand how the JS/XUL namespace works.
Re: How to copy the canvas contents to the clipboard?
That function is probably defined by the extension itself.
If you want to see how nsIClipboard is used, you can check my Link Harvester extension.
You can then try to use the same approach but with the canvas buffer instead.
If you want to see how nsIClipboard is used, you can check my Link Harvester extension.
You can then try to use the same approach but with the canvas buffer instead.
Re: How to copy the canvas contents to the clipboard?
You mean "goDoCommand", right? No, it doesn't show up in a recursive grep in the directory. It's also covered in some of the documentation on MDN/UDN. The examples are all given for XUL files where it says that you have to include the globalOverlay.js file. I understand that this is an old method of interacting with the clipboard.
OK, that helps. I think I'm getting closer. The Link Harvester code accesses the clipboard through "Services.clipboard" rather than "navigator.clipboard" and it doesn't tell me that it's not defined. So I might continue with RealityRipple's suggestion to use canvas.toBlob and ClipboardItem once I can figure out how to construct a ClipboardItem instance, because the examples just use "new ClipboardItem()" and that doesn't work directly. Do I need to use a Components.classes[..].createInstance() type of code?
- RealityRipple
- Astronaut
- Posts: 659
- Joined: 2018-05-17, 02:34
- Location: Los Berros Canyon, California
- Contact:
Re: How to copy the canvas contents to the clipboard?
ClipboardItem only works for the web api clipboard. For nsIClipboard, pretty sure you need to use nsITransferable. I was messing around with it yesterday for a bit and I don't think you'll be able to feed either a blob or an arraybuffer (or uint8array) into nsITransferable. At least, all my tests using addDataFlavor('image/png') and setTransferData('image/png', blob, blob.byteLength) failed. You might need to generate a temp file and then pass nsITransferable an nsIFile to get it to work. And then, I'm not sure if it'll count as an image or a file that's copied to the clipboard.
Oh, and goDoCommand is for XUL <command> elements. It's basically a way of making clean names to run code that's going to be called by multiple elements or wants to be extensible for additional overlays and scripts. If the <command> element with an ID to match the goDoCommand's parameter doesn't exist in the current window, calling it won't work.
Oh, and goDoCommand is for XUL <command> elements. It's basically a way of making clean names to run code that's going to be called by multiple elements or wants to be extensible for additional overlays and scripts. If the <command> element with an ID to match the goDoCommand's parameter doesn't exist in the current window, calling it won't work.
Re: How to copy the canvas contents to the clipboard?
Thank you so much. It looks like I'll have to leave this to a future release.
In case anyone stumbles on this thread and is interested, the Screenshoter extension has this feature (copying the canvas image to the clipboard), examining its source code could help.
In case anyone stumbles on this thread and is interested, the Screenshoter extension has this feature (copying the canvas image to the clipboard), examining its source code could help.
Re: How to copy the canvas contents to the clipboard?
With the premise that I haven't tried anything of what I'm going to list hereafter...
According to the documentation, you can use an nsIFlavorDataProvider object to transfer arbitrary data. Looking at the documentation, the nsIFlavorDataProvider is described as:
What you could try to do is to create an object implementing nsIFlavorDataProvider's getFlavorData method, where you make so that data is read from a suitable in-memory representation of the image you want to store in the clipboard.
Probably you can wrap the data-blob generated through the method suggested by RealityRipple and be done just like that.
However, re-read the disclaimer at the top of this post before you attempt anything.
According to the documentation, you can use an nsIFlavorDataProvider object to transfer arbitrary data. Looking at the documentation, the nsIFlavorDataProvider is described as:
Code: Select all
/**
* nsIFlavorDataProvider allows a flavor to 'promise' data later,
* supplying the data lazily.
*
* To use it, call setTransferData, passing the flavor string,
* a nsIFlavorDataProvider QI'd to nsISupports, and a data size of 0.
*
* When someone calls getTransferData later, if the data size is
* stored as 0, the nsISupports will be QI'd to nsIFlavorDataProvider,
* and its getFlavorData called.
*
*/
Probably you can wrap the data-blob generated through the method suggested by RealityRipple and be done just like that.
However, re-read the disclaimer at the top of this post before you attempt anything.
Re: How to copy the canvas contents to the clipboard?
I did manage to get text data to the clipboard but not binary data. My current options are to look into the nsIFlavorDataProvider as suggested by vannilla (looked quite complicated to me) or to see if there's a way copying the image as text (as data-uri) and have the O/S and other applications understand it (not very likely).
In any case, thanks again RealityRipple and vannilla for all your help.
In any case, thanks again RealityRipple and vannilla for all your help.