How to copy the canvas contents to the clipboard? Topic is solved

Add-ons for Pale Moon and other applications
General discussion, compatibility, contributed extensions, themes, plugins, and more.

Moderators: FranklinDM, Lootyhoof

htuyar
Moonbather
Moonbather
Posts: 69
Joined: 2015-09-11, 10:19
Location: Istanbul

How to copy the canvas contents to the clipboard?

Unread post by htuyar » 2021-07-20, 20:30

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?

User avatar
RealityRipple
Astronaut
Astronaut
Posts: 644
Joined: 2018-05-17, 02:34
Location: Los Berros Canyon, California
Contact:

Re: How to copy the canvas contents to the clipboard?

Unread post by RealityRipple » 2021-07-20, 20:38

How about using blobs? Canvas has a toBlob function and ClipboardItem can be constructed using a blob type. Should do the trick.

vannilla
Moon Magic practitioner
Moon Magic practitioner
Posts: 2181
Joined: 2018-05-05, 13:29

Re: How to copy the canvas contents to the clipboard?

Unread post by vannilla » 2021-07-20, 21:46

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.

htuyar
Moonbather
Moonbather
Posts: 69
Joined: 2015-09-11, 10:19
Location: Istanbul

Re: How to copy the canvas contents to the clipboard?

Unread post by htuyar » 2021-07-20, 22:33

@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
Moon Magic practitioner
Moon Magic practitioner
Posts: 2181
Joined: 2018-05-05, 13:29

Re: How to copy the canvas contents to the clipboard?

Unread post by vannilla » 2021-07-20, 23:38

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.

htuyar
Moonbather
Moonbather
Posts: 69
Joined: 2015-09-11, 10:19
Location: Istanbul

Re: How to copy the canvas contents to the clipboard?

Unread post by htuyar » 2021-07-21, 18:22

vannilla wrote:
2021-07-20, 23:38
That function is probably defined by the extension itself.
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.
vannilla wrote:
2021-07-20, 23:38
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.
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?

User avatar
RealityRipple
Astronaut
Astronaut
Posts: 644
Joined: 2018-05-17, 02:34
Location: Los Berros Canyon, California
Contact:

Re: How to copy the canvas contents to the clipboard?

Unread post by RealityRipple » 2021-07-21, 19:19

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.

htuyar
Moonbather
Moonbather
Posts: 69
Joined: 2015-09-11, 10:19
Location: Istanbul

Re: How to copy the canvas contents to the clipboard?

Unread post by htuyar » 2021-07-21, 19:56

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.

vannilla
Moon Magic practitioner
Moon Magic practitioner
Posts: 2181
Joined: 2018-05-05, 13:29

Re: How to copy the canvas contents to the clipboard?

Unread post by vannilla » 2021-07-21, 20:03

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:

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.
 *
 */
 
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.

htuyar
Moonbather
Moonbather
Posts: 69
Joined: 2015-09-11, 10:19
Location: Istanbul

Re: How to copy the canvas contents to the clipboard?

Unread post by htuyar » 2021-07-23, 09:16

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.

Locked