GUAC-963: Manage display (cursor and size).

This commit is contained in:
Michael Jumper
2014-12-28 23:16:55 -08:00
parent 3b81525eff
commit 9862934872
3 changed files with 219 additions and 16 deletions

View File

@@ -258,7 +258,7 @@ angular.module('client').directive('guacClient', [function guacClient() {
});
// Attach any given managed client
$scope.$watch('client', function(managedClient) {
$scope.$watch('client', function attachManagedClient(managedClient) {
// Remove any existing display
displayContainer.innerHTML = "";
@@ -274,26 +274,21 @@ angular.module('client').directive('guacClient', [function guacClient() {
display = client.getDisplay();
display.scale($scope.client.clientProperties.scale);
// Update the scale of the display when the client display size changes.
display.onresize = function() {
$scope.$apply(updateDisplayScale);
};
// Use local cursor if possible, update localCursor flag
display.oncursor = function(canvas, x, y) {
localCursor = mouse.setCursor(canvas, x, y);
};
// Add display element
displayElement = display.getElement();
displayContainer.appendChild(displayElement);
// Do nothing when the display element is clicked on.
displayElement.onclick = function(e) {
e.preventDefault();
return false;
};
});
// Update scale when display is resized
$scope.$watch('client.managedDisplay.size', function setDisplaySize() {
$scope.$evalAsync(updateDisplayScale);
});
// Keep local cursor up-to-date
$scope.$watch('client.managedDisplay.cursor', function setCursor(cursor) {
if (cursor)
localCursor = mouse.setCursor(cursor.canvas, cursor.x, cursor.y);
});
/*

View File

@@ -29,6 +29,7 @@ angular.module('client').factory('ManagedClient', ['$rootScope', '$injector',
// Required types
var ClientProperties = $injector.get('ClientProperties');
var ManagedClientState = $injector.get('ManagedClientState');
var ManagedDisplay = $injector.get('ManagedDisplay');
// Required services
var $window = $injector.get('$window');
@@ -74,6 +75,13 @@ angular.module('client').factory('ManagedClient', ['$rootScope', '$injector',
*/
this.tunnel = template.tunnel;
/**
* The display associated with the underlying Guacamole client.
*
* @type ManagedDisplay
*/
this.managedDisplay = template.managedDisplay;
/**
* The name returned via the Guacamole protocol for this connection, if
* any.
@@ -89,6 +97,20 @@ angular.module('client').factory('ManagedClient', ['$rootScope', '$injector',
*/
this.clipboardData = template.clipboardData;
/**
* The current width of the Guacamole display, in pixels.
*
* @type Number
*/
this.displayWidth = template.displayWidth || 0;
/**
* The current width of the Guacamole display, in pixels.
*
* @type Number
*/
this.displayHeight = template.displayHeight || 0;
/**
* The current state of the Guacamole client (idle, connecting,
* connected, terminated with error, etc.).
@@ -353,6 +375,9 @@ angular.module('client').factory('ManagedClient', ['$rootScope', '$injector',
};
// Manage the client display
managedClient.managedDisplay = ManagedDisplay.getInstance(client.getDisplay());
/* TODO: Restore file transfer again */
/*

View File

@@ -0,0 +1,183 @@
/*
* Copyright (C) 2014 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.
*/
/**
* Provides the ManagedDisplay class used by the guacClientManager service.
*/
angular.module('client').factory('ManagedDisplay', ['$rootScope',
function defineManagedDisplay($rootScope) {
/**
* Object which serves as a surrogate interface, encapsulating a Guacamole
* display while it is active, allowing it to be detached and reattached
* from different client views.
*
* @constructor
* @param {ManagedDisplay|Object} [template={}]
* The object whose properties should be copied within the new
* ManagedDisplay.
*/
var ManagedDisplay = function ManagedDisplay(template) {
// Use empty object by default
template = template || {};
/**
* The underlying Guacamole display.
*
* @type Guacamole.Display
*/
this.display = template.display;
/**
* The current size of the Guacamole display.
*
* @type ManagedDisplay.Dimensions
*/
this.size = new ManagedDisplay.Dimensions(template.size);
/**
* The current mouse cursor, if any.
*
* @type ManagedDisplay.Cursor
*/
this.cursor = template.cursor;
};
/**
* Object which represents the size of the Guacamole display.
*
* @constructor
* @param {ManagedDisplay.Dimensions|Object} template
* The object whose properties should be copied within the new
* ManagedDisplay.Dimensions.
*/
ManagedDisplay.Dimensions = function Dimensions(template) {
// Use empty object by default
template = template || {};
/**
* The current width of the Guacamole display, in pixels.
*
* @type Number
*/
this.width = template.width || 0;
/**
* The current width of the Guacamole display, in pixels.
*
* @type Number
*/
this.height = template.height || 0;
};
/**
* Object which represents a mouse cursor used by the Guacamole display.
*
* @constructor
* @param {ManagedDisplay.Cursor|Object} template
* The object whose properties should be copied within the new
* ManagedDisplay.Cursor.
*/
ManagedDisplay.Cursor = function Cursor(template) {
// Use empty object by default
template = template || {};
/**
* The actual mouse cursor image.
*
* @type HTMLCanvasElement
*/
this.canvas = template.canvas;
/**
* The X coordinate of the cursor hotspot.
*
* @type Number
*/
this.x = template.x;
/**
* The Y coordinate of the cursor hotspot.
*
* @type Number
*/
this.y = template.y;
};
/**
* Creates a new ManagedDisplay which represents the current state of the
* given Guacamole display.
*
* @param {Guacamole.Display} display
* The Guacamole display to represent. Changes to this display will
* affect this ManagedDisplay.
*
* @returns {ManagedDisplay}
* A new ManagedDisplay which represents the current state of the
* given Guacamole display.
*/
ManagedDisplay.getInstance = function getInstance(display) {
var managedDisplay = new ManagedDisplay({
display : display
});
// Store changes to display size
display.onresize = function() {
$rootScope.$apply(function updateClientSize() {
managedDisplay.size = new ManagedDisplay.Dimensions({
width : display.getWidth(),
height : display.getHeight()
});
});
};
// Store changes to display cursor
display.oncursor = function(canvas, x, y) {
$rootScope.$apply(function updateClientCursor() {
managedDisplay.cursor = new ManagedDisplay.Cursor({
canvas : canvas,
x : x,
y : y
});
});
};
// Do nothing when the display element is clicked on
display.getElement().onclick = function(e) {
e.preventDefault();
return false;
};
return managedDisplay;
};
return ManagedDisplay;
}]);