From 0679c10187e60ca16bd70c1cd37640e834972a0d Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Wed, 29 Jun 2016 18:40:35 -0700 Subject: [PATCH] GUACAMOLE-55: Move local clipboad sync logic back into clientController. Keep the guacClipboard directive lean and with a single purpose. --- .../client/controllers/clientController.js | 47 ++++++- .../app/clipboard/directives/guacClipboard.js | 115 ++---------------- 2 files changed, 54 insertions(+), 108 deletions(-) diff --git a/guacamole/src/main/webapp/app/client/controllers/clientController.js b/guacamole/src/main/webapp/app/client/controllers/clientController.js index 6b1c943ae..aec8252ee 100644 --- a/guacamole/src/main/webapp/app/client/controllers/clientController.js +++ b/guacamole/src/main/webapp/app/client/controllers/clientController.js @@ -32,6 +32,7 @@ angular.module('client').controller('clientController', ['$scope', '$routeParams // Required services var $location = $injector.get('$location'); var authenticationService = $injector.get('authenticationService'); + var clipboardService = $injector.get('clipboardService'); var guacClientManager = $injector.get('guacClientManager'); var guacNotification = $injector.get('guacNotification'); var preferenceService = $injector.get('preferenceService'); @@ -244,6 +245,15 @@ angular.module('client').controller('clientController', ['$scope', '$routeParams */ var keysCurrentlyPressed = {}; + /** + * Map of all currently pressed keys (by keysym) to the clipboard contents + * received from the remote desktop while those keys were pressed. All keys + * not currently pressed will not have entries within this map. + * + * @type Object. + */ + var clipboardDataFromKey = {}; + /* * Check to see if all currently pressed keys are in the set of menu keys. */ @@ -374,11 +384,24 @@ angular.module('client').controller('clientController', ['$scope', '$routeParams $scope.$watch('menu.shown', function menuVisibilityChanged(menuShown, menuShownPreviousState) { + // Send clipboard data if menu is hidden + if (!menuShown && menuShownPreviousState) + $scope.$broadcast('guacClipboard', $scope.client.clipboardData); + // Disable client keyboard if the menu is shown $scope.client.clientProperties.keyboardEnabled = !menuShown; }); + // Watch clipboard for new data, associating it with any pressed keys + $scope.$watch('client.clipboardData', function clipboardChanged(data) { + + // Associate new clipboard data with any currently-pressed key + for (var keysym in keysCurrentlyPressed) + clipboardDataFromKey[keysym] = data; + + }); + // Track pressed keys, opening the Guacamole menu after Ctrl+Alt+Shift $scope.$on('guacKeydown', function keydownListener(event, keysym, keyboard) { @@ -414,9 +437,18 @@ angular.module('client').controller('clientController', ['$scope', '$routeParams }); - // Update pressed keys as they are released + // Update pressed keys as they are released, synchronizing the clipboard + // with any data that appears to have come from those key presses $scope.$on('guacKeyup', function keyupListener(event, keysym, keyboard) { + // Sync local clipboard with any clipboard data received while this + // key was pressed (if any) + var clipboardData = clipboardDataFromKey[keysym]; + if (clipboardData) { + clipboardService.setLocalClipboard(clipboardData); + delete clipboardDataFromKey[keysym]; + } + // Mark key as released delete keysCurrentlyPressed[keysym]; @@ -529,6 +561,19 @@ angular.module('client').controller('clientController', ['$scope', '$routeParams }); } + // Hide status and sync local clipboard once connected + else if (connectionState === ManagedClientState.ConnectionState.CONNECTED) { + + // Sync with local clipboard + clipboardService.getLocalClipboard().then(function clipboardRead(data) { + $scope.$broadcast('guacClipboard', data); + }); + + // Hide status notification + guacNotification.showStatus(false); + + } + // Hide status for all other states else guacNotification.showStatus(false); diff --git a/guacamole/src/main/webapp/app/clipboard/directives/guacClipboard.js b/guacamole/src/main/webapp/app/clipboard/directives/guacClipboard.js index a04c06f32..97fc6e026 100644 --- a/guacamole/src/main/webapp/app/clipboard/directives/guacClipboard.js +++ b/guacamole/src/main/webapp/app/clipboard/directives/guacClipboard.js @@ -18,14 +18,10 @@ */ /** - * A directive which exposes the current clipboard contents, if possible, - * allowing the user to edit those contents. If the current clipboard contents - * cannot be directly accessed, the user can at least directly copy/paste data - * within the field provided by this directive. The contents of this clipboard - * directive, whether retrieved from the local or manipulated manually by the - * user, are exposed via the "data" attribute. In addition to updating the - * "data" attribute, changes to clipboard data will be broadcast on the scope - * via "guacClipboard" events. + * A directive provides an editor whose contents are exposed via a + * ClipboardData object via the "data" attribute. If this data should also be + * synced to the local clipboard, or sent via a connected Guacamole client + * using a "guacClipboard" event, it is up to external code to do so. */ angular.module('clipboard').directive('guacClipboard', ['$injector', function guacClipboard($injector) { @@ -48,12 +44,9 @@ angular.module('clipboard').directive('guacClipboard', ['$injector', config.scope = { /** - * The data to display within the field provided by this directive. If - * the local clipboard can be accessed by JavaScript, this will be set - * automatically as the local clipboard changes. Failing that, this - * will be set when the user manually modifies the contents of the - * field. Changes to this value will be rendered within the field and, - * if possible, will be pushed to the local clipboard. + * The data to display within the field provided by this directive. This + * data will modified or replaced when the user manually alters the + * contents of the field. * * @type ClipboardData */ @@ -66,29 +59,9 @@ angular.module('clipboard').directive('guacClipboard', ['$injector', function guacClipboardController($scope, $injector, $element) { // Required services - var $rootScope = $injector.get('$rootScope'); var $window = $injector.get('$window'); var clipboardService = $injector.get('clipboardService'); - /** - * Map of all currently pressed keys by keysym. If a particular key is - * currently pressed, the value stored under that key's keysym within - * this map will be true. All keys not currently pressed will not have entries - * within this map. - * - * @type Object. - */ - var keysCurrentlyPressed = {}; - - /** - * Map of all currently pressed keys (by keysym) to the clipboard - * contents received while those keys were pressed. All keys not - * currently pressed will not have entries within this map. - * - * @type Object. - */ - var clipboardDataFromKey = {}; - /** * The FileReader to use to read File or Blob data received from the * clipboard. @@ -236,10 +209,6 @@ angular.module('clipboard').directive('guacClipboard', ['$injector', // Watch clipboard for new data, associating it with any pressed keys $scope.$watch('data', function clipboardDataChanged(data) { - // Associate new clipboard data with any currently-pressed key - for (var keysym in keysCurrentlyPressed) - clipboardDataFromKey[keysym] = data; - // Stop any current read process if (reader.readyState === 1) reader.abort(); @@ -263,75 +232,7 @@ angular.module('clipboard').directive('guacClipboard', ['$injector', } - // Notify of change - $rootScope.$broadcast('guacClipboard', data); - - // Attempt to set local clipboard with received data - clipboardService.setLocalClipboard(data); - - }); - - // Track pressed keys - $scope.$on('guacKeydown', function keydownListener(event, keysym, keyboard) { - - // Record key as pressed - keysCurrentlyPressed[keysym] = true; - - }); - - // Update pressed keys as they are released, synchronizing the clipboard - // with any data that appears to have come from those key presses - $scope.$on('guacKeyup', function keyupListener(event, keysym, keyboard) { - - // Sync local clipboard with any clipboard data received while this - // key was pressed (if any) - var clipboardData = clipboardDataFromKey[keysym]; - if (clipboardData) { - clipboardService.setLocalClipboard(clipboardData); - delete clipboardDataFromKey[keysym]; - } - - // Mark key as released - delete keysCurrentlyPressed[keysym]; - - }); - - /** - * Checks whether the clipboard data has changed, updating the stored - * clipboard data if it has. If this function is being called due to a - * DOM event, that event should be passed to this function such that the - * context of the call can be taken into account. Focus events, in - * particular, need to be considered only in the context of the window. - * - * @param {Event} [e] - * The event currently being handled, if any. - */ - var checkClipboard = function checkClipboard(e) { - - // Ignore focus events for anything except the window - if (e && e.type === 'focus' && e.target !== $window) - return; - - clipboardService.getLocalClipboard().then(function clipboardRead(data) { - $scope.data = data; - }); - - }; - - // Attempt to read the clipboard if it may have changed - $window.addEventListener('copy', checkClipboard); - $window.addEventListener('cut', checkClipboard); - $window.addEventListener('focus', checkClipboard); - - // Clean up on destruction - $scope.$on('$destroy', function destroyClipboard() { - $window.removeEventListener('copy', checkClipboard); - $window.removeEventListener('cut', checkClipboard); - $window.removeEventListener('focus', checkClipboard); - }); - - // Perform initial clipboard check - checkClipboard(); + }); // end $scope.data watch }];