From 0edc730308c5fc78a811c56a45cd6e30997c0dc7 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Wed, 22 Jun 2016 00:26:46 -0700 Subject: [PATCH] GUACAMOLE-55: Only the guacClipboard directive should fire guacClipboard events. --- .../client/controllers/clientController.js | 47 +--------- .../app/client/directives/guacClipboard.js | 86 ++++++++++++++++++- .../app/client/services/clipboardService.js | 39 +-------- .../webapp/app/client/types/ManagedClient.js | 4 + 4 files changed, 90 insertions(+), 86 deletions(-) diff --git a/guacamole/src/main/webapp/app/client/controllers/clientController.js b/guacamole/src/main/webapp/app/client/controllers/clientController.js index daa782229..6b1c943ae 100644 --- a/guacamole/src/main/webapp/app/client/controllers/clientController.js +++ b/guacamole/src/main/webapp/app/client/controllers/clientController.js @@ -32,7 +32,6 @@ 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'); @@ -245,15 +244,6 @@ 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. */ @@ -384,24 +374,11 @@ 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', 'text/plain', $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) { @@ -437,18 +414,9 @@ angular.module('client').controller('clientController', ['$scope', '$routeParams }); - // Update pressed keys as they are released, synchronizing the clipboard - // with any data that appears to have come from those key presses + // Update pressed keys as they are released $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]; @@ -561,19 +529,6 @@ 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', 'text/plain', 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/client/directives/guacClipboard.js b/guacamole/src/main/webapp/app/client/directives/guacClipboard.js index c656b9ade..eb17639db 100644 --- a/guacamole/src/main/webapp/app/client/directives/guacClipboard.js +++ b/guacamole/src/main/webapp/app/client/directives/guacClipboard.js @@ -23,7 +23,9 @@ * 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. + * 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. */ angular.module('client').directive('guacClipboard', [function guacClipboard() { @@ -59,7 +61,87 @@ angular.module('client').directive('guacClipboard', [function guacClipboard() { config.controller = ['$scope', '$injector', '$element', function guacClipboardController($scope, $injector, $element) { - // STUB + // Required services + var $rootScope = $injector.get('$rootScope'); + 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 = {}; + + // Watch clipboard for new data, associating it with any pressed keys + $scope.$watch('data', function clipboardChanged(data) { + + // Associate new clipboard data with any currently-pressed key + for (var keysym in keysCurrentlyPressed) + clipboardDataFromKey[keysym] = data; + + // Notify of updated clipboard data + $rootScope.$broadcast('guacClipboard', 'text/plain', 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, firing a new + * "guacClipboard" event if it has. + */ + var checkClipboard = function checkClipboard() { + clipboardService.getLocalClipboard().then(function clipboardRead(data) { + $scope.data = data; + }); + }; + + // Attempt to read the clipboard if it may have changed + window.addEventListener('load', checkClipboard, true); + window.addEventListener('copy', checkClipboard, true); + window.addEventListener('cut', checkClipboard, true); + window.addEventListener('focus', function focusGained(e) { + + // Only recheck clipboard if it's the window itself that gained focus + if (e.target === window) + checkClipboard(); + + }, true); }]; diff --git a/guacamole/src/main/webapp/app/client/services/clipboardService.js b/guacamole/src/main/webapp/app/client/services/clipboardService.js index 7a5950476..19cd865e0 100644 --- a/guacamole/src/main/webapp/app/client/services/clipboardService.js +++ b/guacamole/src/main/webapp/app/client/services/clipboardService.js @@ -24,8 +24,7 @@ angular.module('client').factory('clipboardService', ['$injector', function clipboardService($injector) { // Get required services - var $q = $injector.get('$q'); - var $rootScope = $injector.get('$rootScope'); + var $q = $injector.get('$q'); var service = {}; @@ -44,14 +43,6 @@ angular.module('client').factory('clipboardService', ['$injector', */ var clipboardContent = document.createElement('textarea'); - /** - * The contents of the last clipboard event broadcast by this service when - * the clipboard contents changed. - * - * @type String - */ - var lastClipboardEvent = ''; - // Ensure textarea is selectable but not visible clipElement.appendChild(clipboardContent); clipElement.style.position = 'absolute'; @@ -129,34 +120,6 @@ angular.module('client').factory('clipboardService', ['$injector', return deferred.promise; }; - /** - * Checks whether the clipboard data has changed, firing a new - * "guacClipboard" event if it has. - */ - var checkClipboard = function checkClipboard() { - service.getLocalClipboard().then(function clipboardRead(data) { - - // Fire clipboard event if the data has changed - if (data !== lastClipboardEvent) { - $rootScope.$broadcast('guacClipboard', 'text/plain', data); - lastClipboardEvent = data; - } - - }); - }; - - // Attempt to read the clipboard if it may have changed - window.addEventListener('load', checkClipboard, true); - window.addEventListener('copy', checkClipboard, true); - window.addEventListener('cut', checkClipboard, true); - window.addEventListener('focus', function focusGained(e) { - - // Only recheck clipboard if it's the window itself that gained focus - if (e.target === window) - checkClipboard(); - - }, true); - return service; }]); diff --git a/guacamole/src/main/webapp/app/client/types/ManagedClient.js b/guacamole/src/main/webapp/app/client/types/ManagedClient.js index 9a2870687..40a4dbf13 100644 --- a/guacamole/src/main/webapp/app/client/types/ManagedClient.js +++ b/guacamole/src/main/webapp/app/client/types/ManagedClient.js @@ -383,6 +383,10 @@ angular.module('client').factory('ManagedClient', ['$rootScope', '$injector', ManagedClientState.setConnectionState(managedClient.clientState, ManagedClientState.ConnectionState.CONNECTED); + // Send any clipboard data already provided + if (managedClient.clipboardData) + client.setClipboard(managedClient.clipboardData); + // Begin streaming audio input if possible requestAudioStream(client);