diff --git a/guacamole/src/main/webapp/app/clipboard/services/clipboardService.js b/guacamole/src/main/webapp/app/clipboard/services/clipboardService.js index ff626ea4f..311dbc0ba 100644 --- a/guacamole/src/main/webapp/app/clipboard/services/clipboardService.js +++ b/guacamole/src/main/webapp/app/clipboard/services/clipboardService.js @@ -398,53 +398,81 @@ angular.module('clipboard').factory('clipboardService', ['$injector', var originalElement = document.activeElement; pushSelection(); + /** + * Attempts to paste the clipboard contents into the + * currently-focused element. The promise related to the current + * attempt to read the clipboard will be resolved or rejected + * depending on whether the attempt to paste succeeds. + */ + var performPaste = function performPaste() { + + // Attempt paste local clipboard into clipboard DOM element + if (document.execCommand('paste')) { + + // If the pasted data is a single image, resolve with a blob + // containing that image + var currentImage = service.getImageContent(clipboardContent); + if (currentImage) { + + // Convert the image's data URL into a blob + var blob = service.parseDataURL(currentImage); + if (blob) { + deferred.resolve(new ClipboardData({ + type : blob.type, + data : blob + })); + } + + // Reject if conversion fails + else + deferred.reject(); + + } // end if clipboard is an image + + // Otherwise, assume the clipboard contains plain text + else + deferred.resolve(new ClipboardData({ + type : 'text/plain', + data : clipboardContent.value + })); + + } + + // Otherwise, reading from the clipboard has failed + else + deferred.reject(); + + }; + + // Clean up event listener and selection once the paste attempt has + // completed + deferred.promise['finally'](function cleanupReadAttempt() { + + // Do not use future changes in focus + clipboardContent.removeEventListener('focus', performPaste); + + // Unfocus the clipboard DOM event to avoid mobile keyboard opening, + // restoring whichever element was originally focused + clipboardContent.blur(); + originalElement.focus(); + popSelection(); + + }); + + // Ensure clipboard element is blurred (and that the "focus" event + // will fire) + clipboardContent.blur(); + clipboardContent.addEventListener('focus', performPaste); + // Clear and select the clipboard DOM element clipboardContent.value = ''; clipboardContent.focus(); selectAll(clipboardContent); - // Attempt paste local clipboard into clipboard DOM element - if (document.activeElement === clipboardContent && document.execCommand('paste')) { - - // If the pasted data is a single image, resolve with a blob - // containing that image - var currentImage = service.getImageContent(clipboardContent); - if (currentImage) { - - // Convert the image's data URL into a blob - var blob = service.parseDataURL(currentImage); - if (blob) { - deferred.resolve(new ClipboardData({ - type : blob.type, - data : blob - })); - } - - // Reject if conversion fails - else - deferred.reject(); - - } // end if clipboard is an image - - // Otherwise, assume the clipboard contains plain text - else - deferred.resolve(new ClipboardData({ - type : 'text/plain', - data : clipboardContent.value - })); - - } - - // Otherwise, reading from the clipboard has failed - else + // If focus failed to be set, we cannot read the clipboard + if (document.activeElement !== clipboardContent) deferred.reject(); - // Unfocus the clipboard DOM event to avoid mobile keyboard opening, - // restoring whichever element was originally focused - clipboardContent.blur(); - originalElement.focus(); - popSelection(); - }, CLIPBOARD_READ_DELAY); return deferred.promise;