Search Unity

  1. Unity 2019.2 is now released.
    Dismiss Notice

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

Discussion in 'WebGL' started by Aurigan, May 3, 2016.

  1. Aurigan

    Aurigan

    Joined:
    Jun 30, 2013
    Posts:
    212
    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 : https://issuetracker.unity3d.com/is...s-not-support-copy-slash-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!
     
    Last edited: May 3, 2016
  2. alexsuvorov

    alexsuvorov

    Unity Technologies

    Joined:
    Nov 15, 2015
    Posts:
    317
    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.
     
  3. Aurigan

    Aurigan

    Joined:
    Jun 30, 2013
    Posts:
    212
    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 : http://forum.unity3d.com/threads/webgl-and-html-overlay.398283/#post-2599929 which looks like it creates an overlay whos contents are then forwarded to Unity - any improvement over that concept?
     
  4. alexsuvorov

    alexsuvorov

    Unity Technologies

    Joined:
    Nov 15, 2015
    Posts:
    317
    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.
     
    Aurigan likes this.
  5. Aurigan

    Aurigan

    Joined:
    Jun 30, 2013
    Posts:
    212
    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.
     
  6. Aurigan

    Aurigan

    Joined:
    Jun 30, 2013
    Posts:
    212
    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 :)

    Code (JavaScript):
    1. var ImportExportPlugin = {
    2.     ShowOverlay: function(stringPointer)
    3.     {
    4.  
    5.       if (!document.getElementById('inputOverlay')) {
    6.         var myoverlay = document.createElement('div');
    7.         myoverlay.setAttribute('id', 'inputOverlay');
    8.         document.body.appendChild(myoverlay);          
    9.         document.getElementById('inputOverlay').innerHTML = "<textarea id='saveGameInput'></textarea><br><button onClick='SendMessage(\"Import Export Panel(Clone)\",\"ImportFromWebOverlay\",document.getElementById(\"saveGameInput\").value)'>Import</button><button onClick='SendMessage(\"Import Export Panel(Clone)\",\"CloseOverlay\",\"\")'>Cancel</button>";
    10.       }
    11.      
    12.       var exported = Pointer_stringify(stringPointer);
    13.       document.getElementById('saveGameInput').value = exported;
    14.       document.getElementById('inputOverlay').setAttribute('style','display:block;');
    15.       document.getElementById('inputOverlay').focus();
    16.     },
    17.     HideOverlay: function()
    18.     {
    19.         document.getElementById('inputOverlay').setAttribute('style','display:none;');
    20.     }
    21. };
    22. mergeInto(LibraryManager.library, ImportExportPlugin);

    Code (CSharp):
    1.     [DllImport("__Internal")]
    2.     private static extern void ShowOverlay(string exportedGameSave);
    3.  
    4.     [DllImport("__Internal")]
    5.     private static extern void HideOverlay();
    6.  
    7.     void ShowImportExportOverlay (string gameSave) {
    8.         ShowOverlay(gameSave);
    9.         ToggleCaptureAllInput(false);
    10.     }
    11.  
    12.     public void ImportFromWebOverlay(string importStr){
    13.         HideOverlay();
    14.         LoadGameFromImportedString(importStr);
    15.         ToggleCaptureAllInput(true);
    16.     }
    17.  
    18.     public void CloseOverlay(string param){
    19.         HideOverlay();
    20.         ToggleCaptureAllInput(true);
    21.     }
    22.  
    23.     void ToggleCaptureAllInput(bool captureAll){
    24.         #if !UNITY_EDITOR && UNITY_WEBGL
    25.         WebGLInput.captureAllKeyboardInput = captureAll;
    26.         #endif
    27.     }

    Code (JavaScript):
    1. button {
    2.     background-color: white;
    3.     border: none;
    4.     color: black;
    5.     padding: 10px;
    6.     margin: 10px;
    7.     text-align: center;
    8.     text-decoration: none;
    9.     display: inline-block;
    10.     font-size: 16px;
    11. }
    12.  
    13. div#inputOverlay{
    14.   text-align:center;
    15.   margin:0;
    16.   padding:10px;
    17.   width:100%;
    18.   height:100%;
    19.   background-color: purple;
    20.   z-index: 1;
    21.   position: fixed;
    22. }
    23.  
    24. textArea{
    25.   width:600px;
    26.   height:200px;
    27.   padding:5px;
    28.   margin:10px;
    29. }

    This was adapted from http://forum.unity3d.com/threads/webgl-and-html-overlay.398283/#post-2599929, for my specific use-case I needed to import / export an encrypted save game string.
     
    Last edited: May 3, 2016
    skullthug likes this.
  7. AFrisby

    AFrisby

    Joined:
    Apr 14, 2010
    Posts:
    213
    Is this on Unity's plans to fix; or is it likely to stay broken for the medium/long-term?
     
  8. alexsuvorov

    alexsuvorov

    Unity Technologies

    Joined:
    Nov 15, 2015
    Posts:
    317
    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:
    Code (JavaScript):
    1.   var textToCopy = 'Hello World!';
    2.  
    3.   var clipboardBuffer = document.createElement('textarea');
    4.   clipboardBuffer.style.cssText = 'position:fixed; top:-10px; left:-10px; height:0; width:0; opacity:0;';
    5.   document.body.appendChild(clipboardBuffer);
    6.  
    7.   var copyButton = document.createElement('button');
    8.   copyButton.innerHTML = 'Copy "' + textToCopy + '" to the system clipboard';
    9.   copyButton.onclick = function() {
    10.     clipboardBuffer.focus();
    11.     clipboardBuffer.value = textToCopy;
    12.     clipboardBuffer.setSelectionRange(0, clipboardBuffer.value.length);
    13.     var succeeded;
    14.     try { succeeded = document.execCommand('copy'); } catch (e) {}
    15.     alert(succeeded ? 'Copied successfully' : 'Error: current browser does not fully support execCommand functionality or this event handler was not initiated by the user');
    16.   }
    17.   document.body.appendChild(copyButton);
    3) 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/ho...rddrive-into-a-webgl-app.380985/#post-2474594
     
    Last edited: Jun 10, 2016
    gresolio likes this.
  9. Aurigan

    Aurigan

    Joined:
    Jun 30, 2013
    Posts:
    212
    This is good news :)
     
  10. Rojoss

    Rojoss

    Joined:
    Aug 21, 2016
    Posts:
    2
    Could you give us an update about the status of this?
     
  11. alexsuvorov

    alexsuvorov

    Unity Technologies

    Joined:
    Nov 15, 2015
    Posts:
    317
    Hello Rojoss.
    No update on this yet, but it is being worked on.
     
  12. KristianE

    KristianE

    Joined:
    Nov 16, 2012
    Posts:
    4
    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.
     
  13. jfcampos

    jfcampos

    Joined:
    May 6, 2013
    Posts:
    5
    Hi there! any updates?
     
  14. nfmelendez

    nfmelendez

    Joined:
    Feb 26, 2015
    Posts:
    20
    hey any update here?
     
  15. nsmith1024

    nsmith1024

    Joined:
    Mar 18, 2014
    Posts:
    669
    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.
     
  16. tarek-hentati

    tarek-hentati

    Joined:
    Sep 30, 2014
    Posts:
    4
    Hey, Any update for the fix of the bug in Unity 5.5?
     
  17. fwalkerCirca

    fwalkerCirca

    Joined:
    Apr 10, 2017
    Posts:
    57
    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?
     
  18. Avelblood

    Avelblood

    Joined:
    May 5, 2016
    Posts:
    3
    This thread
    Is dead.
     
  19. powellreid

    powellreid

    Joined:
    Dec 18, 2017
    Posts:
    5
    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?
     
  20. Stream

    Stream

    Joined:
    Oct 28, 2013
    Posts:
    35
    Still no progress?
     
  21. JJJohan

    JJJohan

    Joined:
    Mar 18, 2016
    Posts:
    206
    I'd say hold out just a little longer. Looks like there's some development for a clipboard API happening in Emscripten.

    https://github.com/kripken/emscripten/issues/6377

    I've had luck using newer versions of Emscripten with Unity with very few changes (No luck with their experimental threading support yet though :)!)
     
  22. Deacon2099

    Deacon2099

    Joined:
    Nov 23, 2015
    Posts:
    3
  23. bondk

    bondk

    Joined:
    Feb 14, 2017
    Posts:
    4
  24. Chintan-Kansagara

    Chintan-Kansagara

    Joined:
    Jul 16, 2016
    Posts:
    19
    hello everyone.
    [finally solved copy / paste issues in WebGL]

    Step 1 : unity side

    public void CopyToClipboard()
    {
    string str = "Hello Word";
    Application.ExternalCall("CopyToClipboard", str);
    }

    Step 2 : index.html file edit side
    <head>
    <style>
    .textToCopy {
    opacity: 0
    }
    </style>

    </head>

    <body>
    <div class="webgl-content">
    <input type='text' class='textToCopy' id="textToCopy">
    </div>
    </body>

    function CopyToClipboard(arg){
    var copyText = arg;
    $('.textToCopy').val(copyText);
    var textToCopy = $('.textToCopy').val();
    console.log('copyText',textToCopy);
    $('.textToCopy').select();
    document.execCommand('copy');
    }
     
  25. FlolF

    FlolF

    Joined:
    Nov 20, 2012
    Posts:
    11
    Hi Chintan, I edited your code like the followig:

    <script>function CopyToClipboard(arg){
    var copyText = arg;
    $('.textToCopy').val(copyText);
    var textToCopy = $('.textToCopy').val();
    console.log('copyText',textToCopy);
    $('.textToCopy').select();
    document.execCommand('copy');
    }</script>

    But still no luck. It doesn't work for me. Could you elaborate further?