From 32ed7c67249d876296fcb5d76052a84324b30e7b Mon Sep 17 00:00:00 2001 From: Samuel Mannehed Date: Thu, 11 Jun 2020 15:52:34 +0200 Subject: [PATCH] Fake cursor position when using touch With the new gestures we will simulate the cursor being in a different location than any of the touch points. This is a bit too complex for the Cursor class, so let's just explicitly tell it where we want the cursor rendered. --- core/rfb.js | 26 +++++++++++++++---------- core/util/cursor.js | 46 +++++++++++++-------------------------------- 2 files changed, 29 insertions(+), 43 deletions(-) diff --git a/core/rfb.js b/core/rfb.js index c56bdc98..4d1b6159 100644 --- a/core/rfb.js +++ b/core/rfb.js @@ -1058,6 +1058,11 @@ export default class RFB extends EventTargetMixin { } } + _fakeMouseMove(ev, elementX, elementY) { + this._handleMouseMove(elementX, elementY); + this._cursor.move(ev.detail.clientX, ev.detail.clientY); + } + _handleTapEvent(ev, bmask) { let pos = clientToElement(ev.detail.clientX, ev.detail.clientY, this._canvas); @@ -1084,7 +1089,7 @@ export default class RFB extends EventTargetMixin { } this._gestureLastTapTime = Date.now(); - this._handleMouseMove(pos.x, pos.y); + this._fakeMouseMove(this._gestureFirstDoubleTapEv, pos.x, pos.y); this._handleMouseButton(pos.x, pos.y, true, bmask); this._handleMouseButton(pos.x, pos.y, false, bmask); } @@ -1107,23 +1112,23 @@ export default class RFB extends EventTargetMixin { this._handleTapEvent(ev, 0x2); break; case 'drag': - this._handleMouseMove(pos.x, pos.y); + this._fakeMouseMove(ev, pos.x, pos.y); this._handleMouseButton(pos.x, pos.y, true, 0x1); break; case 'longpress': - this._handleMouseMove(pos.x, pos.y); + this._fakeMouseMove(ev, pos.x, pos.y); this._handleMouseButton(pos.x, pos.y, true, 0x4); break; case 'twodrag': this._gestureLastMagnitudeX = ev.detail.magnitudeX; this._gestureLastMagnitudeY = ev.detail.magnitudeY; - this._handleMouseMove(pos.x, pos.y); + this._fakeMouseMove(ev, pos.x, pos.y); break; case 'pinch': this._gestureLastMagnitudeX = Math.hypot(ev.detail.magnitudeX, ev.detail.magnitudeY); - this._handleMouseMove(pos.x, pos.y); + this._fakeMouseMove(ev, pos.x, pos.y); break; } break; @@ -1136,13 +1141,13 @@ export default class RFB extends EventTargetMixin { break; case 'drag': case 'longpress': - this._handleMouseMove(pos.x, pos.y); + this._fakeMouseMove(ev, pos.x, pos.y); break; case 'twodrag': // Always scroll in the same position. // We don't know if the mouse was moved so we need to move it // every update. - this._handleMouseMove(pos.x, pos.y); + this._fakeMouseMove(ev, pos.x, pos.y); while ((ev.detail.magnitudeY - this._gestureLastMagnitudeY) > GESTURE_SCRLSENS) { this._handleMouseButton(pos.x, pos.y, true, 0x8); this._handleMouseButton(pos.x, pos.y, false, 0x8); @@ -1168,7 +1173,7 @@ export default class RFB extends EventTargetMixin { // Always scroll in the same position. // We don't know if the mouse was moved so we need to move it // every update. - this._handleMouseMove(pos.x, pos.y); + this._fakeMouseMove(ev, pos.x, pos.y); magnitude = Math.hypot(ev.detail.magnitudeX, ev.detail.magnitudeY); if (Math.abs(magnitude - this._gestureLastMagnitudeX) > GESTURE_ZOOMSENS) { this._handleKeyEvent(KeyTable.XK_Control_L, "ControlLeft", true); @@ -1184,6 +1189,7 @@ export default class RFB extends EventTargetMixin { } } this._handleKeyEvent(KeyTable.XK_Control_L, "ControlLeft", false); + break; } break; @@ -1196,11 +1202,11 @@ export default class RFB extends EventTargetMixin { case 'twodrag': break; case 'drag': - this._handleMouseMove(pos.x, pos.y); + this._fakeMouseMove(ev, pos.x, pos.y); this._handleMouseButton(pos.x, pos.y, false, 0x1); break; case 'longpress': - this._handleMouseMove(pos.x, pos.y); + this._fakeMouseMove(ev, pos.x, pos.y); this._handleMouseButton(pos.x, pos.y, false, 0x4); break; } diff --git a/core/util/cursor.js b/core/util/cursor.js index c7a084f0..3f0b01bd 100644 --- a/core/util/cursor.js +++ b/core/util/cursor.js @@ -30,9 +30,6 @@ export default class Cursor { 'mouseleave': this._handleMouseLeave.bind(this), 'mousemove': this._handleMouseMove.bind(this), 'mouseup': this._handleMouseUp.bind(this), - 'touchstart': this._handleTouchStart.bind(this), - 'touchmove': this._handleTouchMove.bind(this), - 'touchend': this._handleTouchEnd.bind(this), }; } @@ -54,11 +51,6 @@ export default class Cursor { this._target.addEventListener('mouseleave', this._eventHandlers.mouseleave, options); this._target.addEventListener('mousemove', this._eventHandlers.mousemove, options); this._target.addEventListener('mouseup', this._eventHandlers.mouseup, options); - - // There is no "touchleave" so we monitor touchstart globally - window.addEventListener('touchstart', this._eventHandlers.touchstart, options); - this._target.addEventListener('touchmove', this._eventHandlers.touchmove, options); - this._target.addEventListener('touchend', this._eventHandlers.touchend, options); } this.clear(); @@ -76,10 +68,6 @@ export default class Cursor { this._target.removeEventListener('mousemove', this._eventHandlers.mousemove, options); this._target.removeEventListener('mouseup', this._eventHandlers.mouseup, options); - window.removeEventListener('touchstart', this._eventHandlers.touchstart, options); - this._target.removeEventListener('touchmove', this._eventHandlers.touchmove, options); - this._target.removeEventListener('touchend', this._eventHandlers.touchend, options); - document.body.removeChild(this._canvas); } @@ -131,6 +119,19 @@ export default class Cursor { this._hotSpot.y = 0; } + // Mouse events might be emulated, this allows + // moving the cursor in such cases + move(clientX, clientY) { + if (!useFallback) { + return; + } + this._position.x = clientX; + this._position.y = clientY; + this._updatePosition(); + let target = document.elementFromPoint(clientX, clientY); + this._updateVisibility(target); + } + _handleMouseOver(event) { // This event could be because we're entering the target, or // moving around amongst its sub elements. Let the move handler @@ -179,27 +180,6 @@ export default class Cursor { } } - _handleTouchStart(event) { - // Just as for mouseover, we let the move handler deal with it - this._handleTouchMove(event); - } - - _handleTouchMove(event) { - this._updateVisibility(event.target); - - this._position.x = event.changedTouches[0].clientX - this._hotSpot.x; - this._position.y = event.changedTouches[0].clientY - this._hotSpot.y; - - this._updatePosition(); - } - - _handleTouchEnd(event) { - // Same principle as for mouseup - let target = document.elementFromPoint(event.changedTouches[0].clientX, - event.changedTouches[0].clientY); - this._updateVisibility(target); - } - _showCursor() { if (this._canvas.style.visibility === 'hidden') { this._canvas.style.visibility = '';