loleaflet/src/map/Clipboard.js | 100 ++++++++++++++++++---------- loleaflet/test/copy-test.html | 146 +++++++++++++++++++++++++++++++++++++++++ wsd/LOOLWSD.cpp | 2 3 files changed, 214 insertions(+), 34 deletions(-)
New commits: commit d34ba83dd3dcb36c9a9c31e0f43df24ec5e26413 Author: Mike Kaganski <[email protected]> AuthorDate: Wed Jul 31 09:50:04 2019 +0000 Commit: Michael Meeks <[email protected]> CommitDate: Mon Aug 5 22:24:33 2019 -0400 Use rich paste also for IE Change-Id: I220af7fb1d2e7326e61c8ef4f9ec73980f65388b diff --git a/loleaflet/src/map/Clipboard.js b/loleaflet/src/map/Clipboard.js index 7768914e0..079f41e9f 100644 --- a/loleaflet/src/map/Clipboard.js +++ b/loleaflet/src/map/Clipboard.js @@ -657,7 +657,7 @@ L.Clipboard = L.Class.extend({ var active = document.activeElement; // Can't get HTML until it is pasted ... so quick timeout setTimeout(function() { - that.dataTransferToDocument(null, /* preferInternal = */ false, that._dummyDiv.innerHTML); + that.dataTransferToDocument(null, /* preferInternal = */ true, that._dummyDiv.innerHTML); // attempt to restore focus. if (active == null) that._map.focus(); commit bd3c723e410f8123a3e3bd65bcbeac9e740e338e Author: Michael Meeks <[email protected]> AuthorDate: Mon Jul 15 12:53:06 2019 +0100 Commit: Michael Meeks <[email protected]> CommitDate: Mon Aug 5 22:22:50 2019 -0400 copy/paste test - expand to paste. Change-Id: I69db38511aa70f1c2e7ff9613f49307dfe952bae diff --git a/loleaflet/test/copy-test.html b/loleaflet/test/copy-test.html index 761b215eb..a4165b2b2 100644 --- a/loleaflet/test/copy-test.html +++ b/loleaflet/test/copy-test.html @@ -23,7 +23,13 @@ <li id="aclass" data-event="both-aclass"><a class>Both AClass (fails on iOS)</a></li> <li/> <li/> + <li id="paste" data-event="paste"><a href="#">Paste</a></li> + <li/> + <li/> </ul> + + <div id="clipcontent"> + </div> </body> <script defer> var serial = 42; @@ -104,5 +110,37 @@ doSelect(); }; + // --------- copy function --------- + var paste = document.getElementById('paste'); + paste.onclick = function(ev) { + + if (document.execCommand('paste')) + console.log('Paste succeeded'); + else + console.log('Paste failed'); + }; + + document.onpaste = function(ev) { + if (!ev.clipboardData) { // non-standard + console.log('No clipboard data'); + return; + } + + var dataTransfer = ev.clipboardData; + var types = dataTransfer.types; + + console.log('We have ' + types.length + ' types'); + for (var t = 0; t < types.length; ++t) { + var data = new Blob([dataTransfer.getData(types[t])]); + console.log('type ' + types[t] + ' length ' + data.size + + ' -> 0x' + data.size.toString(16)); + if (types[t].startsWith('text/')) + console.log('data: ' + dataTransfer.getData(types[t])); + } + + ev.preventDefault(); + return false; + }; + </script> </body></html> commit e774e569811f05ba095921cc48f5275c5a9f74f4 Author: Michael Meeks <[email protected]> AuthorDate: Mon Jul 15 11:52:49 2019 +0100 Commit: Michael Meeks <[email protected]> CommitDate: Mon Aug 5 22:22:31 2019 -0400 Add test bits for copy/paste. Change-Id: I7e1b0bf8c834a414d2f8a87bd16ebf8465dd324a diff --git a/loleaflet/test/copy-test.html b/loleaflet/test/copy-test.html new file mode 100644 index 000000000..761b215eb --- /dev/null +++ b/loleaflet/test/copy-test.html @@ -0,0 +1,108 @@ +<!DOCTYPE html> +<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> +<title>Copy Test</title> +<meta charset="utf-8"> +</head> + <body id="body" style="user-select: none;"> <!-- text doesn't seem to matter here --> + <h1>Test clipboard code: none</h1> + <div id="area_id" contenteditable="true" style="-webkit-user-select: text; border: red; background-color: grey">dummy content</div> + + <ul> + <li id="select" data-event="select"><a href="#" class="item-link list-button">Select All</a></li> + <li/> + <li/> + <li id="both" data-event="both"><a href="#" class="item-link list-button">Both TouchStart</a></li> + <li/> + <li/> + <li id="bothclick" data-event="both-click"><a href="#" class="item-link list-button">Both Click</a></li> + <li/> + <li/> + <li id="bothstopclick" data-event="both-stop-click"><a href="#" class="item-link list-button">Both StoponTouch Click</a></li> + <li/> + <li/> + <li id="aclass" data-event="both-aclass"><a class>Both AClass (fails on iOS)</a></li> + <li/> + <li/> + </ul> +</body> + <script defer> + var serial = 42; + + document.getElementById('area_id').focus(); + + // --------- select function --------- + var doSelect = function() { + console.log('select whole area'); + var selection = window.getSelection(); + selection.removeAllRanges(); + var rangeToSelect = document.createRange(); + elem = document.getElementById('area_id'); + rangeToSelect.selectNodeContents(elem); + selection.addRange(rangeToSelect); + }; + var select = document.getElementById('select'); + select.onclick = function(ev) { + doSelect(); + }; + + // --------- copy function --------- + var doCopy = function(ev) { + console.log('On touch copy invoke'); + + try + { + console.log('exec command copy - before'); + _ret = document.execCommand('copy'); + console.log('exec command copy success: ' + _ret); + } + catch (err) + { + console.log('exception in copy ' + err); + _ret = false; + } + }; + + // --------- both function --------- + var both = document.getElementById('both'); + both.ontouchstart = function(ev) { + doCopy(); + }; + + var bothClick = document.getElementById('bothclick'); + bothClick.onclick = function(ev) { + doCopy(); + }; + + // JQuery context menu does this on touch - killing a click event + var bothStopClick = document.getElementById('bothstopclick'); + bothStopClick.ontouchstart = function(ev) { + console.log('stop on touch!'); + ev.preventDefault(); + ev.stopImmediatePropagation(); + return false; + }; + bothStopClick.onclick = function(ev) { + doCopy(); + }; + + var aclass = document.getElementById('aclass'); + aclass.onclick = function(ev) { + doCopy(); + }; + + // Actually put serial data in the thing .. + document.oncopy = function(ev) { + ev.preventDefault(); + var forclip = 'serial ' + serial++ + ' ops'; + console.log('set clip to ' + forclip); + ev.clipboardData.setData('text/plain', forclip); + }; + + // Do the selection + document.onbeforecopy = function(ev) { + console.log('we have to select in a before copy event [!]'); + doSelect(); + }; + + </script> +</body></html> commit 852e8f4b0e5f503903ab3aef545c7172bdf05004 Author: Michael Meeks <[email protected]> AuthorDate: Fri Jul 12 21:45:52 2019 +0100 Commit: Michael Meeks <[email protected]> CommitDate: Mon Aug 5 22:22:21 2019 -0400 More IE11 work, paste works again, cut/copy pending. Change-Id: I744e76c7ecb655c42ed3dfb0662c0995d2c48650 diff --git a/loleaflet/src/map/Clipboard.js b/loleaflet/src/map/Clipboard.js index 34aee3649..7768914e0 100644 --- a/loleaflet/src/map/Clipboard.js +++ b/loleaflet/src/map/Clipboard.js @@ -414,13 +414,8 @@ L.Clipboard = L.Class.extend({ console.log('Error: collapsed selection - cannot copy/paste'); }, - populateClipboard: function(ev) { + _getHtmlForClipboard: function() { var text; - - this._checkSelection(); - -// this._stopHideDownload(); - this confuses the borwser ruins copy/cut on iOS - if (this._selectionType === 'complex' || this._map._docLayer.hasGraphicSelection()) { console.log('Copy/Cut with complex/graphical selection'); @@ -444,6 +439,24 @@ L.Clipboard = L.Class.extend({ console.log('Copy/Cut with simple text selection'); text = this._selectionContent; } + return text; + }, + + // returns whether we shold stop processing the event + populateClipboard: function(ev) { + this._checkSelection(); + + if (window.isInternetExplorer) + { + var that = this; + setTimeout(function() { that._resetDiv(); }, 0); + this._clipboardSerial++; // we have no way of knowing of course. + // We let the browser copy from our div. + return false; + } + + var text = this._getHtmlForClipboard(); +// this._stopHideDownload(); - this confuses the borwser ruins copy/cut on iOS var plainText = this.stripHTML(text); if (ev.clipboardData) { // Standard @@ -451,11 +464,9 @@ L.Clipboard = L.Class.extend({ ev.clipboardData.setData('text/html', text); console.log('Put "' + text + '" on the clipboard'); this._clipboardSerial++; - - } else if (window.clipboardData) { // IE 11 - poor clipboard API - if (window.clipboardData.setData('Text', plainText)) - this._clipboardSerial++; } + + return true; // prevent default }, // only used by IE. @@ -466,23 +477,49 @@ L.Clipboard = L.Class.extend({ // Now wait for the paste ... }, + // Does the selection of text before an event comes in _beforeSelect: function(ev) { console.log('Got event ' + ev.type + ' setting up selection'); - this._resetDiv(); + if (window.isInternetExplorer && ev.type != 'paste') + // We need populate our content into the div for + // the brower to copy. + this._dummyDiv.innerHTML = this._getHtmlForClipboard(); + else + // We need some spaces in there ... + this._resetDiv(); var sel = document.getSelection(); if (!sel) return; - sel.removeAllRanges(); - var rangeToSelect = document.createRange(); - rangeToSelect.selectNodeContents(this._dummyDiv); - sel.addRange(rangeToSelect); + var selected = false; + var selectRange; + if (window.isInternetExplorer && ev.type != 'paste') + { + this._dummyDiv.focus(); - var checkSelect = document.getSelection(); - if (checkSelect.isCollapsed) - console.log('Error: failed to select - cannot copy/paste'); + if (document.body.createTextRange) // Internet Explorer + { + console.log('Legacy IE11 selection'); + selectRange = document.body.createTextRange(); + selectRange.moveToElementText(this._dummyDiv); + selectRange.select(); + selected = true; + } + } + + if (!selected) + { + sel.removeAllRanges(); + selectRange = document.createRange(); + selectRange.selectNodeContents(this._dummyDiv); + sel.addRange(selectRange); + + var checkSelect = document.getSelection(); + if (checkSelect.isCollapsed) + console.log('Error: failed to select - cannot copy/paste'); + } return false; }, @@ -595,21 +632,19 @@ L.Clipboard = L.Class.extend({ return true; }, - copy: function(ev) { - console.log('Copy'); - ev.preventDefault(); - this.populateClipboard(ev); - this._map._socket.sendMessage('uno .uno:Copy'); - return false; + _doCopyCut: function(ev, unoName) { + console.log(unoName); + var preventDefault = this.populateClipboard(ev); + this._map._socket.sendMessage('uno .uno:' + unoName); + if (preventDefault) { + ev.preventDefault(); + return false; + } }, - cut: function(ev) { - console.log('Cut'); - ev.preventDefault(); - this.populateClipboard(ev); - this._map._socket.sendMessage('uno .uno:Cut'); - return false; - }, + cut: function(ev) { return this._doCopyCut(ev, 'Cut'); }, + + copy: function(ev) { return this._doCopyCut(ev, 'Copy'); }, paste: function(ev) { console.log('Paste'); @@ -622,8 +657,7 @@ L.Clipboard = L.Class.extend({ var active = document.activeElement; // Can't get HTML until it is pasted ... so quick timeout setTimeout(function() { - var tmpDiv = document.getElementById(that._dummyDivName); - that.dataTransferToDocument(null, /* preferInternal = */ false, tmpDiv.innerHTML); + that.dataTransferToDocument(null, /* preferInternal = */ false, that._dummyDiv.innerHTML); // attempt to restore focus. if (active == null) that._map.focus(); commit 1c9a3db307c546fb82f56b36183a81875dab9c82 Author: Michael Meeks <[email protected]> AuthorDate: Wed Jul 10 17:03:09 2019 +0100 Commit: Michael Meeks <[email protected]> CommitDate: Mon Aug 5 22:22:16 2019 -0400 clipboard: remove inadvertent debug. Change-Id: I59833519d5f4a8b16c7925a8094c974a1e7f5c11 diff --git a/wsd/LOOLWSD.cpp b/wsd/LOOLWSD.cpp index 3ed895cdc..9cccc78df 100644 --- a/wsd/LOOLWSD.cpp +++ b/wsd/LOOLWSD.cpp @@ -2156,7 +2156,7 @@ private: StringTokenizer reqPathTokens(request.getURI(), "/?", StringTokenizer::TOK_IGNORE_EMPTY | StringTokenizer::TOK_TRIM); if (reqPathTokens.count() > 1 && reqPathTokens[0] == "lool" && reqPathTokens[1] == "clipboard") { - Util::dumpHex(std::cerr, "clipboard:\n", "", socket->getInBuffer()); // lots of data ... +// Util::dumpHex(std::cerr, "clipboard:\n", "", socket->getInBuffer()); // lots of data ... handleClipboardRequest(request, message, disposition); } else if (!(request.find("Upgrade") != request.end() && Poco::icompare(request["Upgrade"], "websocket") == 0) && _______________________________________________ Libreoffice-commits mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits
