mirror of
				https://github.com/gyurix1968/guacamole-client.git
				synced 2025-10-31 09:03:21 +00:00 
			
		
		
		
	GUACAMOLE-1204: Merge addition of client-side support for multi-touch events.
This commit is contained in:
		| @@ -463,6 +463,11 @@ angular.module('client').controller('clientController', ['$scope', '$routeParams | ||||
|     // 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; | ||||
|   | ||||
| @@ -119,6 +119,14 @@ angular.module('client').directive('guacClient', [function guacClient() { | ||||
|              */ | ||||
|             var touchPad = new Guacamole.Mouse.Touchpad(displayContainer); | ||||
|  | ||||
|             /** | ||||
|              * Guacamole touch event handling object, wrapped around the main | ||||
|              * client dislay. | ||||
|              * | ||||
|              * @type Guacamole.Touch | ||||
|              */ | ||||
|             var touch = new Guacamole.Touch(displayContainer); | ||||
|  | ||||
|             /** | ||||
|              * Updates the scale of the attached Guacamole.Client based on current window | ||||
|              * size and "auto-fit" setting. | ||||
| @@ -185,29 +193,6 @@ angular.module('client').directive('guacClient', [function guacClient() { | ||||
|  | ||||
|             }; | ||||
|  | ||||
|             /** | ||||
|              * Sends the given mouse state to the current client. | ||||
|              * | ||||
|              * @param {Guacamole.Mouse.State} mouseState The mouse state to | ||||
|              *                                           send. | ||||
|              */ | ||||
|             var sendScaledMouseState = function sendScaledMouseState(mouseState) { | ||||
|  | ||||
|                 // Scale event by current scale | ||||
|                 var scaledState = new Guacamole.Mouse.State( | ||||
|                         mouseState.x / display.getScale(), | ||||
|                         mouseState.y / display.getScale(), | ||||
|                         mouseState.left, | ||||
|                         mouseState.middle, | ||||
|                         mouseState.right, | ||||
|                         mouseState.up, | ||||
|                         mouseState.down); | ||||
|  | ||||
|                 // Send mouse event | ||||
|                 client.sendMouseState(scaledState); | ||||
|  | ||||
|             }; | ||||
|  | ||||
|             /** | ||||
|              * Handles a mouse event originating from the user's actual mouse. | ||||
|              * This differs from handleEmulatedMouseState() in that the | ||||
| @@ -226,7 +211,7 @@ angular.module('client').directive('guacClient', [function guacClient() { | ||||
|  | ||||
|                 // Send mouse state, show cursor if necessary | ||||
|                 display.showCursor(!localCursor); | ||||
|                 sendScaledMouseState(mouseState); | ||||
|                 client.sendMouseState(mouseState, true); | ||||
|  | ||||
|             }; | ||||
|  | ||||
| @@ -251,7 +236,28 @@ angular.module('client').directive('guacClient', [function guacClient() { | ||||
|  | ||||
|                 // Send mouse state, ensure cursor is visible | ||||
|                 scrollToMouse(mouseState); | ||||
|                 sendScaledMouseState(mouseState); | ||||
|                 client.sendMouseState(mouseState, true); | ||||
|  | ||||
|             }; | ||||
|  | ||||
|             /** | ||||
|              * Handles a touch event originating from the user's device. | ||||
|              * | ||||
|              * @param {Guacamole.Touch.Event} touchEvent | ||||
|              *     The touch event. | ||||
|              */ | ||||
|             var handleTouchEvent = function handleTouchEvent(event) { | ||||
|  | ||||
|                 // Do not attempt to handle touch state changes if the client | ||||
|                 // or display are not yet available | ||||
|                 if (!client || !display) | ||||
|                     return; | ||||
|  | ||||
|                 event.preventDefault(); | ||||
|  | ||||
|                 // Send touch state, hiding local cursor | ||||
|                 display.showCursor(false); | ||||
|                 client.sendTouchState(event.state, true); | ||||
|  | ||||
|             }; | ||||
|  | ||||
| @@ -310,39 +316,42 @@ angular.module('client').directive('guacClient', [function guacClient() { | ||||
|                     localCursor = mouse.setCursor(cursor.canvas, cursor.x, cursor.y); | ||||
|             }); | ||||
|  | ||||
|             // Swap mouse emulation modes depending on absolute mode flag | ||||
|             $scope.$watch('client.clientProperties.emulateAbsoluteMouse', | ||||
|                 function mouseEmulationModeChanged(emulateAbsoluteMouse) { | ||||
|             // Update touch event handling depending on remote multi-touch | ||||
|             // support and mouse emulation mode | ||||
|             $scope.$watchGroup([ | ||||
|                     'client.multiTouchSupport', | ||||
|                     'client.clientProperties.emulateAbsoluteMouse' | ||||
|                 ], function touchBehaviorChanged(emulateAbsoluteMouse) { | ||||
|  | ||||
|                 var newMode, oldMode; | ||||
|                 // Clear existing event handling | ||||
|                 touch.offEach(['touchstart', 'touchmove', 'touchend'], handleTouchEvent); | ||||
|  | ||||
|                 // Switch to touchscreen if absolute | ||||
|                 if (emulateAbsoluteMouse) { | ||||
|                     newMode = touchScreen; | ||||
|                     oldMode = touchPad; | ||||
|                 touchScreen.onmousedown = | ||||
|                 touchScreen.onmouseup = | ||||
|                 touchScreen.onmousemove = null; | ||||
|  | ||||
|                 touchPad.onmousedown = | ||||
|                 touchPad.onmouseup = | ||||
|                 touchPad.onmousemove = null; | ||||
|  | ||||
|                 // Directly forward local touch events | ||||
|                 if ($scope.client.multiTouchSupport) | ||||
|                     touch.onEach(['touchstart', 'touchmove', 'touchend'], handleTouchEvent); | ||||
|  | ||||
|                 // Switch to touchscreen if mouse emulation is required and | ||||
|                 // absolute mouse emulation is preferred | ||||
|                 else if ($scope.client.clientProperties.emulateAbsoluteMouse) { | ||||
|                     touchScreen.onmousedown = | ||||
|                     touchScreen.onmouseup   = | ||||
|                     touchScreen.onmousemove = handleEmulatedMouseState; | ||||
|                 } | ||||
|  | ||||
|                 // Switch to touchpad if not absolute (relative) | ||||
|                 // Use touchpad for mouse emulation if absolute mouse emulation | ||||
|                 // is not preferred | ||||
|                 else { | ||||
|                     newMode = touchPad; | ||||
|                     oldMode = touchScreen; | ||||
|                 } | ||||
|  | ||||
|                 // Set applicable mouse emulation object, unset the old one | ||||
|                 if (newMode) { | ||||
|  | ||||
|                     // Clear old handlers and copy state to new emulation mode | ||||
|                     if (oldMode) { | ||||
|                         oldMode.onmousedown = oldMode.onmouseup = oldMode.onmousemove = null; | ||||
|                         newMode.currentState.x = oldMode.currentState.x; | ||||
|                         newMode.currentState.y = oldMode.currentState.y; | ||||
|                     } | ||||
|  | ||||
|                     // Handle emulated events only from the new emulation mode | ||||
|                     newMode.onmousedown = | ||||
|                     newMode.onmouseup   = | ||||
|                     newMode.onmousemove = handleEmulatedMouseState; | ||||
|  | ||||
|                     touchPad.onmousedown = | ||||
|                     touchPad.onmouseup   = | ||||
|                     touchPad.onmousemove = handleEmulatedMouseState; | ||||
|                 } | ||||
|  | ||||
|             }); | ||||
|   | ||||
| @@ -155,7 +155,7 @@ | ||||
|                 </div> | ||||
|  | ||||
|                 <!-- Mouse mode --> | ||||
|                 <div class="menu-section" id="mouse-settings"> | ||||
|                 <div class="menu-section" id="mouse-settings" ng-hide="client.multiTouchSupport"> | ||||
|                     <h3>{{'CLIENT.SECTION_HEADER_MOUSE_MODE' | translate}}</h3> | ||||
|                     <div class="content"> | ||||
|                         <p class="description">{{'CLIENT.HELP_MOUSE_MODE' | translate}}</p> | ||||
|   | ||||
| @@ -203,6 +203,15 @@ angular.module('client').factory('ManagedClient', ['$rootScope', '$injector', | ||||
|          */ | ||||
|         this.shareLinks = template.shareLinks || {}; | ||||
|  | ||||
|         /** | ||||
|          * The number of simultaneous touch contacts supported by the remote | ||||
|          * desktop. Unless explicitly declared otherwise by the remote desktop | ||||
|          * after connecting, this will be 0 (multi-touch unsupported). | ||||
|          * | ||||
|          * @type Number | ||||
|          */ | ||||
|         this.multiTouchSupport = template.multiTouchSupport || 0; | ||||
|  | ||||
|         /** | ||||
|          * The current state of the Guacamole client (idle, connecting, | ||||
|          * connected, terminated with error, etc.). | ||||
| @@ -578,6 +587,11 @@ angular.module('client').factory('ManagedClient', ['$rootScope', '$injector', | ||||
|  | ||||
|         }; | ||||
|  | ||||
|         // Update level of multi-touch support when known | ||||
|         client.onmultitouch = function multiTouchSupportDeclared(layer, touches) { | ||||
|             managedClient.multiTouchSupport = touches; | ||||
|         }; | ||||
|  | ||||
|         // Update title when a "name" instruction is received | ||||
|         client.onname = function clientNameReceived(name) { | ||||
|             $rootScope.$apply(function updateClientTitle() { | ||||
|   | ||||
| @@ -124,8 +124,6 @@ angular.module('touch').directive('guacTouchDrag', [function guacTouchDrag() { | ||||
|             element.addEventListener("touchmove", function dragTouchMove(e) { | ||||
|                 if (e.touches.length === 1) { | ||||
|  | ||||
|                     e.stopPropagation(); | ||||
|  | ||||
|                     // Get touch location | ||||
|                     var x = e.touches[0].clientX; | ||||
|                     var y = e.touches[0].clientY; | ||||
| @@ -163,8 +161,6 @@ angular.module('touch').directive('guacTouchDrag', [function guacTouchDrag() { | ||||
|  | ||||
|                 if (startX && startY && e.touches.length === 0) { | ||||
|  | ||||
|                     e.stopPropagation(); | ||||
|  | ||||
|                     // Signal end of drag gesture | ||||
|                     if (inProgress && guacTouchDrag) { | ||||
|                         $scope.$apply(function dragComplete() { | ||||
|   | ||||
| @@ -159,8 +159,6 @@ angular.module('touch').directive('guacTouchPinch', [function guacTouchPinch() { | ||||
|             element.addEventListener("touchmove", function pinchTouchMove(e) { | ||||
|                 if (e.touches.length === 2) { | ||||
|  | ||||
|                     e.stopPropagation(); | ||||
|  | ||||
|                     // Calculate current zoom level | ||||
|                     currentLength = pinchDistance(e); | ||||
|  | ||||
| @@ -188,8 +186,6 @@ angular.module('touch').directive('guacTouchPinch', [function guacTouchPinch() { | ||||
|  | ||||
|                 if (startLength && e.touches.length < 2) { | ||||
|  | ||||
|                     e.stopPropagation(); | ||||
|  | ||||
|                     // Notify of pinch end | ||||
|                     if (guacTouchPinch) { | ||||
|                         $scope.$apply(function pinchComplete() { | ||||
|   | ||||
| @@ -480,6 +480,7 @@ | ||||
|         "FIELD_HEADER_ENABLE_PRINTING"            : "Enable printing:", | ||||
|         "FIELD_HEADER_ENABLE_SFTP"     : "Enable SFTP:", | ||||
|         "FIELD_HEADER_ENABLE_THEMING"             : "Enable theming:", | ||||
|         "FIELD_HEADER_ENABLE_TOUCH"               : "Enable multi-touch:", | ||||
|         "FIELD_HEADER_ENABLE_WALLPAPER"           : "Enable wallpaper:", | ||||
|         "FIELD_HEADER_GATEWAY_DOMAIN"   : "Domain:", | ||||
|         "FIELD_HEADER_GATEWAY_HOSTNAME" : "Hostname:", | ||||
| @@ -499,6 +500,7 @@ | ||||
|         "FIELD_HEADER_READ_ONLY"      : "Read-only:", | ||||
|         "FIELD_HEADER_RECORDING_EXCLUDE_MOUSE"  : "Exclude mouse:", | ||||
|         "FIELD_HEADER_RECORDING_EXCLUDE_OUTPUT" : "Exclude graphics/streams:", | ||||
|         "FIELD_HEADER_RECORDING_EXCLUDE_TOUCH"  : "Exclude touch events:", | ||||
|         "FIELD_HEADER_RECORDING_INCLUDE_KEYS"   : "Include key events:", | ||||
|         "FIELD_HEADER_RECORDING_NAME" : "Recording name:", | ||||
|         "FIELD_HEADER_RECORDING_PATH" : "Recording path:", | ||||
|   | ||||
		Reference in New Issue
	
	Block a user