GUACAMOLE-724: Move handling of drag/pinch gestures to individual client tiles.

This commit is contained in:
Michael Jumper
2021-06-25 00:24:31 -07:00
parent b0febd3402
commit 90f2270dab
6 changed files with 527 additions and 508 deletions

View File

@@ -400,10 +400,13 @@ angular.module('client').controller('clientController', ['$scope', '$routeParams
return true;
}
// Hide menu when the user swipes from the right
// Show menu if the user swipes from the left, hide menu when the user
// swipes from the right, scroll menu while visible
$scope.menuDrag = function menuDrag(inProgress, startX, startY, currentX, currentY, deltaX, deltaY) {
// Hide menu if swipe gesture is detected
if ($scope.menu.shown) {
// Hide menu if swipe-from-right gesture is detected
if (Math.abs(currentY - startY) < MENU_DRAG_VERTICAL_TOLERANCE
&& startX - currentX >= MENU_DRAG_DELTA)
$scope.menu.shown = false;
@@ -414,98 +417,15 @@ angular.module('client').controller('clientController', ['$scope', '$routeParams
$scope.menu.scrollState.top -= deltaY;
}
return false;
};
// Update menu or client based on dragging gestures
$scope.clientDrag = function clientDrag(inProgress, startX, startY, currentX, currentY, deltaX, deltaY) {
// Show menu if the user swipes from the left
if (startX <= MENU_DRAG_MARGIN) {
}
// Show menu if swipe-from-left gesture is detected
else if (startX <= MENU_DRAG_MARGIN) {
if (Math.abs(currentY - startY) < MENU_DRAG_VERTICAL_TOLERANCE
&& currentX - startX >= MENU_DRAG_DELTA)
$scope.menu.shown = true;
}
// Scroll display if absolute mouse is in use
else if ($scope.client.clientProperties.emulateAbsoluteMouse) {
$scope.client.clientProperties.scrollLeft -= deltaX;
$scope.client.clientProperties.scrollTop -= deltaY;
}
return false;
};
/**
* If a pinch gesture is in progress, the scale of the client display when
* the pinch gesture began.
*
* @type Number
*/
var initialScale = null;
/**
* If a pinch gesture is in progress, the X coordinate of the point on the
* client display that was centered within the pinch at the time the
* gesture began.
*
* @type Number
*/
var initialCenterX = 0;
/**
* If a pinch gesture is in progress, the Y coordinate of the point on the
* client display that was centered within the pinch at the time the
* gesture began.
*
* @type Number
*/
var initialCenterY = 0;
// Zoom and pan client via pinch gestures
$scope.clientPinch = function clientPinch(inProgress, startLength, currentLength, centerX, centerY) {
// Do not handle pinch gestures if they would conflict with remote
// handling of similar gestures
if ($scope.client.multiTouchSupport > 1)
return false;
// Do not handle pinch gestures while relative mouse is in use
if (!$scope.client.clientProperties.emulateAbsoluteMouse)
return false;
// Stop gesture if not in progress
if (!inProgress) {
initialScale = null;
return false;
}
// Set initial scale if gesture has just started
if (!initialScale) {
initialScale = $scope.client.clientProperties.scale;
initialCenterX = (centerX + $scope.client.clientProperties.scrollLeft) / initialScale;
initialCenterY = (centerY + $scope.client.clientProperties.scrollTop) / initialScale;
}
// Determine new scale absolutely
var currentScale = initialScale * currentLength / startLength;
// Fix scale within limits - scroll will be miscalculated otherwise
currentScale = Math.max(currentScale, $scope.client.clientProperties.minScale);
currentScale = Math.min(currentScale, $scope.client.clientProperties.maxScale);
// Update scale based on pinch distance
$scope.client.clientProperties.autoFit = false;
$scope.client.clientProperties.scale = currentScale;
// Scroll display to keep original pinch location centered within current pinch
$scope.client.clientProperties.scrollLeft = initialCenterX * currentScale - centerX;
$scope.client.clientProperties.scrollTop = initialCenterY * currentScale - centerY;
return false;
};

View File

@@ -22,22 +22,33 @@
*/
angular.module('client').directive('guacClient', [function guacClient() {
return {
// Element only
var directive = {
restrict: 'E',
replace: true,
scope: {
templateUrl: 'app/client/templates/guacClient.html'
};
directive.scope = {
/**
* The client to display within this guacClient directive.
*
* @type ManagedClient
*/
client : '='
client : '=',
},
templateUrl: 'app/client/templates/guacClient.html',
controller: ['$scope', '$injector', '$element', function guacClientController($scope, $injector, $element) {
/**
* Whether translation of touch to mouse events should emulate an
* absolute pointer device, or a relative pointer device.
*
* @type boolean
*/
emulateAbsoluteMouse : '='
};
directive.controller = ['$scope', '$injector', '$element',
function guacClientController($scope, $injector, $element) {
// Required types
var ManagedClient = $injector.get('ManagedClient');
@@ -88,13 +99,6 @@ angular.module('client').directive('guacClient', [function guacClient() {
*/
var main = $element[0];
/**
* The element which functions as a detector for size changes.
*
* @type Element
*/
var resizeSensor = $element.find('.resize-sensor')[0];
/**
* Guacamole mouse event object, wrapped around the main client
* display.
@@ -326,8 +330,8 @@ angular.module('client').directive('guacClient', [function guacClient() {
// support and mouse emulation mode
$scope.$watchGroup([
'client.multiTouchSupport',
'client.clientProperties.emulateAbsoluteMouse'
], function touchBehaviorChanged(emulateAbsoluteMouse) {
'emulateAbsoluteMouse'
], function touchBehaviorChanged() {
// Clear existing event handling
touch.offEach(['touchstart', 'touchmove', 'touchend'], handleTouchEvent);
@@ -340,7 +344,7 @@ angular.module('client').directive('guacClient', [function guacClient() {
// Switch to touchscreen if mouse emulation is required and
// absolute mouse emulation is preferred
else if ($scope.client.clientProperties.emulateAbsoluteMouse)
else if ($scope.emulateAbsoluteMouse)
touchScreen.onEach(['mousedown', 'mousemove', 'mouseup'], handleEmulatedMouseEvent);
// Use touchpad for mouse emulation if absolute mouse emulation
@@ -399,6 +403,91 @@ angular.module('client').directive('guacClient', [function guacClient() {
};
// Scroll client display if absolute mouse is in use (the same drag
// gesture is needed for moving the mouse pointer with relative mouse)
$scope.clientDrag = function clientDrag(inProgress, startX, startY, currentX, currentY, deltaX, deltaY) {
if ($scope.emulateAbsoluteMouse) {
$scope.client.clientProperties.scrollLeft -= deltaX;
$scope.client.clientProperties.scrollTop -= deltaY;
}
return false;
};
/**
* If a pinch gesture is in progress, the scale of the client display when
* the pinch gesture began.
*
* @type Number
*/
var initialScale = null;
/**
* If a pinch gesture is in progress, the X coordinate of the point on the
* client display that was centered within the pinch at the time the
* gesture began.
*
* @type Number
*/
var initialCenterX = 0;
/**
* If a pinch gesture is in progress, the Y coordinate of the point on the
* client display that was centered within the pinch at the time the
* gesture began.
*
* @type Number
*/
var initialCenterY = 0;
// Zoom and pan client via pinch gestures
$scope.clientPinch = function clientPinch(inProgress, startLength, currentLength, centerX, centerY) {
// Do not handle pinch gestures if they would conflict with remote
// handling of similar gestures
if ($scope.client.multiTouchSupport > 1)
return false;
// Do not handle pinch gestures while relative mouse is in use (2+
// contact point gestures are used by relative mouse emulation to
// support right click, middle click, and scrolling)
if (!$scope.emulateAbsoluteMouse)
return false;
// Stop gesture if not in progress
if (!inProgress) {
initialScale = null;
return false;
}
// Set initial scale if gesture has just started
if (!initialScale) {
initialScale = $scope.client.clientProperties.scale;
initialCenterX = (centerX + $scope.client.clientProperties.scrollLeft) / initialScale;
initialCenterY = (centerY + $scope.client.clientProperties.scrollTop) / initialScale;
}
// Determine new scale absolutely
var currentScale = initialScale * currentLength / startLength;
// Fix scale within limits - scroll will be miscalculated otherwise
currentScale = Math.max(currentScale, $scope.client.clientProperties.minScale);
currentScale = Math.min(currentScale, $scope.client.clientProperties.maxScale);
// Update scale based on pinch distance
$scope.client.clientProperties.autoFit = false;
$scope.client.clientProperties.scale = currentScale;
// Scroll display to keep original pinch location centered within current pinch
$scope.client.clientProperties.scrollLeft = initialCenterX * currentScale - centerX;
$scope.client.clientProperties.scrollTop = initialCenterY * currentScale - centerY;
return false;
};
// Ensure focus is regained via mousedown before forwarding event
mouse.on('mousedown', document.body.focus.bind(document.body));
@@ -475,10 +564,8 @@ angular.module('client').directive('guacClient', [function guacClient() {
}, false);
/*
* END CLIENT DIRECTIVE
*/
}];
return directive;
}]
};
}]);

View File

@@ -37,7 +37,15 @@ angular.module('client').directive('guacTiledClients', [function guacTiledClient
*
* @type ManagedClientGroup
*/
clientGroup : '='
clientGroup : '=',
/**
* Whether translation of touch to mouse events should emulate an
* absolute pointer device, or a relative pointer device.
*
* @type boolean
*/
emulateAbsoluteMouse : '='
};

View File

@@ -6,10 +6,13 @@
<div class="client-view-content">
<!-- Central portion of view -->
<div class="client-body" guac-touch-drag="clientDrag" guac-touch-pinch="clientPinch">
<div class="client-body" guac-touch-drag="hiddenMenuDrag">
<!-- All connections in current display -->
<guac-tiled-clients client-group="clientGroup"></guac-tiled-clients>
<guac-tiled-clients
client-group="clientGroup"
emulate-absolute-mouse="menu.emulateAbsoluteMouse">
</guac-tiled-clients>
</div>
@@ -78,7 +81,7 @@
</div>
<!-- Scrollable body -->
<div class="menu-body" guac-touch-drag="menuDrag" guac-scroll="menu.scrollState">
<div class="menu-body" guac-touch-drag="visibleMenuDrag" guac-scroll="menu.scrollState">
<!-- Connection sharing -->
<div class="menu-section" id="share-links" ng-show="isShared()">

View File

@@ -1,4 +1,5 @@
<div class="main" guac-resize="mainElementResized">
<div class="main" guac-resize="mainElementResized"
guac-touch-drag="clientDrag" guac-touch-pinch="clientPinch">
<!-- Display -->
<div class="displayOuter">

View File

@@ -7,7 +7,7 @@
ng-click="assignFocus(client)">
<h3>{{ client.title }}</h3>
<guac-client client="client"></guac-client>
<guac-client client="client" emulate-absolute-mouse="emulateAbsoluteMouse"></guac-client>
<!-- Client-specific status/error dialog -->
<guac-client-notification client="client"></guac-client-notification>