You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@guacamole.apache.org by mj...@apache.org on 2016/03/20 03:21:49 UTC
[09/50] incubator-guacamole-client git commit: GUAC-1480: Use
AllowClipboard and execCommand for local/remote clipboard integration.
GUAC-1480: Use AllowClipboard and execCommand for local/remote clipboard integration.
Project: http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/commit/7ec53c94
Tree: http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/tree/7ec53c94
Diff: http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/diff/7ec53c94
Branch: refs/heads/master
Commit: 7ec53c94ce889b6f5bdcedb689f580dff0eb5fbe
Parents: 14889c7
Author: James Muehlner <ja...@guac-dev.org>
Authored: Mon Feb 1 22:03:44 2016 -0800
Committer: James Muehlner <ja...@guac-dev.org>
Committed: Mon Feb 1 22:03:44 2016 -0800
----------------------------------------------------------------------
.../app/client/controllers/clientController.js | 19 ++-
.../app/client/services/clipboardService.js | 171 +++++++++++++++++++
.../webapp/app/client/types/ManagedClient.js | 3 +
3 files changed, 188 insertions(+), 5 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/blob/7ec53c94/guacamole/src/main/webapp/app/client/controllers/clientController.js
----------------------------------------------------------------------
diff --git a/guacamole/src/main/webapp/app/client/controllers/clientController.js b/guacamole/src/main/webapp/app/client/controllers/clientController.js
index fd445d1..99bf723 100644
--- a/guacamole/src/main/webapp/app/client/controllers/clientController.js
+++ b/guacamole/src/main/webapp/app/client/controllers/clientController.js
@@ -35,6 +35,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');
@@ -230,11 +231,6 @@ angular.module('client').controller('clientController', ['$scope', '$routeParams
$scope.menu.shown = false;
};
- // Update the model when clipboard data received from client
- $scope.$on('guacClientClipboard', function clientClipboardListener(event, client, mimetype, clipboardData) {
- $scope.clipboardData = clipboardData;
- });
-
/**
* The client which should be attached to the client UI.
*
@@ -526,6 +522,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', 'text/plain', data);
+ });
+
+ // Hide status notification
+ guacNotification.showStatus(false);
+
+ }
+
// Hide status for all other states
else
guacNotification.showStatus(false);
http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/blob/7ec53c94/guacamole/src/main/webapp/app/client/services/clipboardService.js
----------------------------------------------------------------------
diff --git a/guacamole/src/main/webapp/app/client/services/clipboardService.js b/guacamole/src/main/webapp/app/client/services/clipboardService.js
new file mode 100644
index 0000000..7880159
--- /dev/null
+++ b/guacamole/src/main/webapp/app/client/services/clipboardService.js
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 2016 Glyptodon LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+/**
+ * A service for accessing local clipboard data.
+ */
+angular.module('client').factory('clipboardService', ['$injector',
+ function clipboardService($injector) {
+
+ // Get required services
+ var $q = $injector.get('$q');
+ var $rootScope = $injector.get('$rootScope');
+
+ var service = {};
+
+ /**
+ * A div which is used to hide the clipboard textarea and remove it from
+ * document flow.
+ *
+ * @type Element
+ */
+ var clipElement = document.createElement('div');
+
+ /**
+ * The textarea that will be used to hold the local clipboard contents.
+ *
+ * @type Element
+ */
+ 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 = '';
+
+ clipElement.appendChild(clipboardContent);
+ clipElement.style.position = 'absolute';
+ clipElement.style.width = '0px';
+ clipElement.style.height = '0px';
+ clipElement.style.overflow = 'hidden';
+
+ document.body.appendChild(clipElement);
+
+ /**
+ * Sets the local clipboard, if possible, to the given text.
+ *
+ * @param {String} text
+ * The text to which the local clipboard should be set.
+ *
+ * @return {Promise}
+ * A promise that will resolve if setting the clipboard was successful,
+ * and will reject if it failed.
+ */
+ service.setLocalClipboard = function setLocalClipboard(text) {
+
+ var deferred = $q.defer();
+
+ // First, see if allow clipboard extension is installed
+ if (window.AllowClipboard) {
+
+ var clipboardClient = new AllowClipboard.Client.ClipboardClient();
+
+ clipboardClient.write(text, function(success) {
+ if (success)
+ deferred.resolve();
+ else
+ deferred.reject();
+ });
+
+ }
+
+ // Otherwise, try execCommand
+ else {
+
+ // Copy the given value into the clipboard DOM element
+ clipboardContent.value = text;
+ clipboardContent.select();
+
+ // Attempt to copy data from clipboard element into local clipboard
+ if (document.execCommand('copy'))
+ deferred.resolve();
+ else
+ deferred.reject();
+
+ }
+
+ return deferred.promise;
+ };
+
+ /**
+ * Get the current value of the local clipboard.
+ *
+ * @return {Promise}
+ * A promise that will resolve with the contents of the local clipboard
+ * if getting the clipboard was successful, and will reject if it
+ * failed.
+ */
+ service.getLocalClipboard = function getLocalClipboard() {
+
+ var deferred = $q.defer();
+
+ // First, see if allow clipboard extension is installed
+ if (window.AllowClipboard) {
+
+ var clipboardClient = new AllowClipboard.Client.ClipboardClient();
+
+ clipboardClient.read(function(success, data) {
+ if (success)
+ deferred.resolve(data);
+ else
+ deferred.reject();
+ });
+
+ }
+
+ // Otherwise, try execCommand
+ else {
+
+ // Clear and select the clipboard DOM element
+ clipboardContent.value = '';
+ clipboardContent.select();
+
+ // Attempt paste local clipboard into clipboard DOM element
+ if (document.execCommand('paste'))
+ deferred.resolve(clipboardContent.value);
+ else
+ deferred.reject();
+
+ }
+
+ return deferred.promise;
+ };
+
+ // Periodically attempt to read the clipboard, firing an event if successful
+ window.setInterval(function periodicallyReadClipboard() {
+ 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;
+ }
+
+ });
+ }, 100);
+
+ return service;
+
+}]);
http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/blob/7ec53c94/guacamole/src/main/webapp/app/client/types/ManagedClient.js
----------------------------------------------------------------------
diff --git a/guacamole/src/main/webapp/app/client/types/ManagedClient.js b/guacamole/src/main/webapp/app/client/types/ManagedClient.js
index a518ca8..5187cb0 100644
--- a/guacamole/src/main/webapp/app/client/types/ManagedClient.js
+++ b/guacamole/src/main/webapp/app/client/types/ManagedClient.js
@@ -38,8 +38,10 @@ angular.module('client').factory('ManagedClient', ['$rootScope', '$injector',
// Required services
var $document = $injector.get('$document');
var $q = $injector.get('$q');
+ var $rootScope = $injector.get('$rootScope');
var $window = $injector.get('$window');
var authenticationService = $injector.get('authenticationService');
+ var clipboardService = $injector.get('clipboardService');
var connectionGroupService = $injector.get('connectionGroupService');
var connectionService = $injector.get('connectionService');
var guacAudio = $injector.get('guacAudio');
@@ -403,6 +405,7 @@ angular.module('client').factory('ManagedClient', ['$rootScope', '$injector',
reader.onend = function clipboard_text_end() {
$rootScope.$apply(function updateClipboard() {
managedClient.clipboardData = data;
+ clipboardService.setLocalClipboard(data);
});
};