Copy / Paste - has anyone built a good solution for this?

Copy / Paste doesn’t work into or out of a Unity (and NGUI) WebGL game. As far as I can tell this is a JS issue by (security) design.

One of the top results for this issue on google points to a closed bug : Unity Issue Tracker - UI text input does not support copy/paste on WebGL build which incorrectly claims it’s ‘fixed’

It sounds like from various other snippets and hints from Unity staff in the forums like it should be possible to make this work by some combination of special keyboard access mode and having a hidden text field on the page. Has anyone actually done this successfully? Or have some other working method for copying/pasting text into/out of Unity? I’m looking for a working example implementation. Thanks!

Hello Aurigan.

When original issue was submitted, copy-paste also did not work correctly between Unity input fields, which has been fixed.

You are talking about copy to and paste from the system clipboard. Yes, it is in fact should be possible in the latest versions of major browsers (except, probably, Safari). The fix however requires nontrivial changes in the Unity input processing scheme. The main issue here is that due to the browser security policy, such actions can only be performed inside a JavaScript event handler initiated by the user, while all the Unity input events are queued and processed in the main loop when the initial JavaScript handler has already exited. One possible workaround for that would be to process clipboard events outside of the input queue and out of order, which however may cause undesired side effects. When all those issues are resolved, this functionality will be added.

1 Like

Hey Alex, thanks for the reply. Great to hear that this might actually get fixed so hacks aren’t needed.

In the short term are you aware of any solution out there that can make this work? I found this post : WebGL and HTML Overlay - Unity Engine - Unity Discussions which looks like it creates an overlay whos contents are then forwarded to Unity - any improvement over that concept?

I don’t have ready to use code to share at the moment, but I might prepare it and post here later. For now you might check out the document.execCommand functionality (https://developer.mozilla.org/en-US/docs/Web/API/Document/execCommand). In addition you might consider the document.onpaste event. This will let you create a much nicer solution. However the mentioned html edit field overlay is also a valid fallback.

1 Like

Example clean code would be much appreciated!

The specific use-case I’m trying to solve for is that I generate some text in my game and want the player to be able to copy that. I also then want the player to be able to paste it back into the game.

Ok so I worked out how to get an overlay solution working. The way this works is to add a div on top of the unity game canvas that contains a textarea and two buttons (cancel overlay and import text). It’s (really) ugly but it works :slight_smile:

JS plugin (save as ImportExportPlugin.jslib in Plugins/WebGL)

var ImportExportPlugin = {
    ShowOverlay: function(stringPointer)
    {

      if (!document.getElementById('inputOverlay')) {
        var myoverlay = document.createElement('div');
        myoverlay.setAttribute('id', 'inputOverlay');
        document.body.appendChild(myoverlay);          
        document.getElementById('inputOverlay').innerHTML = "<textarea id='saveGameInput'></textarea>
<button onClick='SendMessage(\"Import Export Panel(Clone)\",\"ImportFromWebOverlay\",document.getElementById(\"saveGameInput\").value)'>Import</button><button onClick='SendMessage(\"Import Export Panel(Clone)\",\"CloseOverlay\",\"\")'>Cancel</button>";
      }
      
      var exported = Pointer_stringify(stringPointer);
      document.getElementById('saveGameInput').value = exported;
      document.getElementById('inputOverlay').setAttribute('style','display:block;');
      document.getElementById('inputOverlay').focus();
    },
    HideOverlay: function()
    {
        document.getElementById('inputOverlay').setAttribute('style','display:none;');
    }
};
mergeInto(LibraryManager.library, ImportExportPlugin);

C# code to add plugin functions and call them with content

    [DllImport("__Internal")]
    private static extern void ShowOverlay(string exportedGameSave);

    [DllImport("__Internal")]
    private static extern void HideOverlay();

    void ShowImportExportOverlay (string gameSave) {
        ShowOverlay(gameSave);
        ToggleCaptureAllInput(false);
    }

    public void ImportFromWebOverlay(string importStr){
        HideOverlay();
        LoadGameFromImportedString(importStr);
        ToggleCaptureAllInput(true);
    }

    public void CloseOverlay(string param){
        HideOverlay();
        ToggleCaptureAllInput(true);
    }

    void ToggleCaptureAllInput(bool captureAll){
        #if !UNITY_EDITOR && UNITY_WEBGL
        WebGLInput.captureAllKeyboardInput = captureAll;
        #endif
    }

CSS for overlay elements (add to your custom WebGL template)

button {
    background-color: white;
    border: none;
    color: black;
    padding: 10px;
    margin: 10px;
    text-align: center;
    text-decoration: none;
    display: inline-block;
    font-size: 16px;
}

div#inputOverlay{
  text-align:center;
  margin:0;
  padding:10px;
  width:100%;
  height:100%;
  background-color: purple;
  z-index: 1;
  position: fixed;
}

textArea{
  width:600px;
  height:200px;
  padding:5px;
  margin:10px;
}

This was adapted from WebGL and HTML Overlay - Unity Engine - Unity Discussions, for my specific use-case I needed to import / export an encrypted save game string.

1 Like

Is this on Unity’s plans to fix; or is it likely to stay broken for the medium/long-term?

Hello AFrisby.

There is nothing that can be described as ‘broken’ here. Browser security policy implies the following limitations:

  1. You can only get the content of the system clipboard from paste event, and, specifically in Firefox, the paste event is only sent when an editable element on the page is focused. You can technically make the canvas editable, however in most versions this will result in the edit cursor overlaying the canvas and other issues. So it seems that currently the only way to make it work is to add an additional hidden editable element (like a hidden textarea) to the page. This will not work reliably for the browser Paste menu command, unless the hidden element is constantly focused, which might not be desirable for some WebGL applications.
    P.S. contrary to the popular belief, Flash wont help you capture the system clipboard content, as clearly stated here http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/desktop/Clipboard.html (unless you are utilizing the same paste event, which basically makes Flash approach useless)

  2. Although most modern browsers support execCommand, currently it does not seem to be supported by Safari, which means there is no universal solution for copying content into the system clipboard. However, it can be easily done in Chrome 42+, Firefox 41+, Edge and Opera 29+ using the following code:

  var textToCopy = 'Hello World!';

  var clipboardBuffer = document.createElement('textarea');
  clipboardBuffer.style.cssText = 'position:fixed; top:-10px; left:-10px; height:0; width:0; opacity:0;';
  document.body.appendChild(clipboardBuffer);

  var copyButton = document.createElement('button');
  copyButton.innerHTML = 'Copy "' + textToCopy + '" to the system clipboard';
  copyButton.onclick = function() {
    clipboardBuffer.focus();
    clipboardBuffer.value = textToCopy;
    clipboardBuffer.setSelectionRange(0, clipboardBuffer.value.length);
    var succeeded;
    try { succeeded = document.execCommand('copy'); } catch (e) {}
    alert(succeeded ? 'Copied successfully' : 'Error: current browser does not fully support execCommand functionality or this event handler was not initiated by the user');
  }
  document.body.appendChild(copyButton);
  1. According to the browser security policy, execCommand can only be successfully executed from an event handler initiated by the user (for example, it will work from onkeydown or onclick, but not from onload or setTimeout). Normally, one would register a keyup event handler after the copy shortcut has been pressed, but this solution is not universal, as in recent versions of Firefox on Mac you are not able to execute execCommand from a keyup event handler while the Command key is down. Unity is processing events through an intermediate queue, therefore performing security restricted action would require bypassing the input queue and processing the event out of order, which is quite challenging to perform reliably in the current version.

Nevertheless, we are planning to provide a workaround for the copy/paste browser security restriction, supporting keyboard shortcuts in most of the recent browsers (except copying into system clipboard in Safari) starting from Unity 5.5

For the current Unity version I can propose a simple workaround, a Paste UI button near the input field which will popup an html input field where user can paste the system clipboard and click OK (no need for overlays, just use the JavaScript prompt function for that); and a Copy UI button near the input field that will copy the field content into the system clipboard (using the code above) when user clicks the button (expect Safari). Also you might need an example of how to perform an action restricted by the browser security policy from a Unity UI button OnButtonPointerDown event http://forum.unity3d.com/threads/how-do-i-let-the-user-load-an-image-from-their-harddrive-into-a-webgl-app.380985/#post-2474594

2 Likes

This is good news :slight_smile:

Could you give us an update about the status of this?

Hello Rojoss.
No update on this yet, but it is being worked on.

1 Like

Hi alexsuvorov

It’s good to hear that people are working on this. It certainly seems like an important feature. We are currently looking for the paste functionality - and I don’t seem to be able to persuade our UI designer that a javascript text box is a good idea…

So, any news if this will make it into Unity 5.5? … I just tried the 5.5.0b3 and I could not paste text in both Windows and OS X.

Hi there! any updates?

hey any update here?

You have to write Javascript code (outside of Unity that Unity calls), that pops up a little dialog with an edit box, have the user past into that, then send that pasted string to your Unity App using messages, thats the only way I know becuase you cant do copy/paste i dont think.

Hey, Any update for the fix of the bug in Unity 5.5?

Also looking for some updates on this. document.onpaste event seems like a decent work around. Are there any example son how to use this?

This thread
Is dead.

1 Like

Any update on this or any other workaround? We are developing game using c#, so i am not sure how can we use above snippet in our code? Any guidence?

Still no progress?