This commit is contained in:
Samuel Mannehed (ThinLinc team) 2025-05-08 10:59:55 +02:00 committed by GitHub
commit 34d81737df
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 89 additions and 24 deletions

View File

@ -186,14 +186,14 @@ export default class GestureHandler {
} }
if (!this._hasDetectedGesture()) { if (!this._hasDetectedGesture()) {
// Ignore moves smaller than the minimum threshold
if (Math.hypot(deltaX, deltaY) < GH_MOVE_THRESHOLD) {
return;
}
// Can't be a tap or long press as we've seen movement let deltaMove = Math.hypot(deltaX, deltaY);
this._state &= ~(GH_ONETAP | GH_TWOTAP | GH_THREETAP | GH_LONGPRESS);
this._stopLongpressTimeout(); // Can't be a tap or long press if we've seen movement
if (deltaMove >= GH_MOVE_THRESHOLD) {
this._state &= ~(GH_ONETAP | GH_TWOTAP | GH_THREETAP | GH_LONGPRESS);
this._stopLongpressTimeout();
}
if (this._tracked.length !== 1) { if (this._tracked.length !== 1) {
this._state &= ~(GH_DRAG); this._state &= ~(GH_DRAG);
@ -213,10 +213,10 @@ export default class GestureHandler {
let prevDeltaMove = Math.hypot(prevTouch.firstX - prevTouch.lastX, let prevDeltaMove = Math.hypot(prevTouch.firstX - prevTouch.lastX,
prevTouch.firstY - prevTouch.lastY); prevTouch.firstY - prevTouch.lastY);
// We know that the current touch moved far enough, // Unless both touches moved further than their threshold we
// but unless both touches moved further than their // don't want to disqualify any gestures right now
// threshold we don't want to disqualify any gestures if (deltaMove > GH_MOVE_THRESHOLD &&
if (prevDeltaMove > GH_MOVE_THRESHOLD) { prevDeltaMove > GH_MOVE_THRESHOLD) {
// The angle difference between the direction of the touch points // The angle difference between the direction of the touch points
let deltaAngle = Math.abs(touch.angle - prevTouch.angle); let deltaAngle = Math.abs(touch.angle - prevTouch.angle);
@ -234,7 +234,8 @@ export default class GestureHandler {
} }
} else if (!this._isTwoTouchTimeoutRunning()) { } else if (!this._isTwoTouchTimeoutRunning()) {
// We can't determine the gesture right now, let's // We can't determine the gesture right now, let's
// wait and see if more events are on their way // wait and see if more events are on their way.
// If not, we'll have to decide which gesture it is.
this._startTwoTouchTimeout(); this._startTwoTouchTimeout();
} }
} }
@ -260,6 +261,7 @@ export default class GestureHandler {
(this._tracked.length === 0)) { (this._tracked.length === 0)) {
this._state = GH_INITSTATE; this._state = GH_INITSTATE;
this._waitingRelease = false; this._waitingRelease = false;
this._stopTwoTouchTimeout();
} }
return; return;
} }
@ -346,6 +348,7 @@ export default class GestureHandler {
if ((this._ignored.length === 0)) { if ((this._ignored.length === 0)) {
this._state = GH_INITSTATE; this._state = GH_INITSTATE;
this._waitingRelease = false; this._waitingRelease = false;
this._stopTwoTouchTimeout();
} }
} }

View File

@ -580,7 +580,7 @@ describe('Gesture handler', function () {
touchStart(1, 50.0, 40.0); touchStart(1, 50.0, 40.0);
touchStart(2, 60.0, 40.0); touchStart(2, 60.0, 40.0);
touchMove(1, 80.0, 40.0); touchMove(1, 80.0, 40.0);
touchMove(2, 110.0, 40.0); touchMove(2, 90.0, 40.0);
expect(gestures).to.not.have.been.called; expect(gestures).to.not.have.been.called;
@ -601,7 +601,7 @@ describe('Gesture handler', function () {
detail: { type: 'twodrag', detail: { type: 'twodrag',
clientX: 55.0, clientX: 55.0,
clientY: 40.0, clientY: 40.0,
magnitudeX: 40.0, magnitudeX: 30.0,
magnitudeY: 0.0 } })); magnitudeY: 0.0 } }));
}); });
@ -609,7 +609,7 @@ describe('Gesture handler', function () {
touchStart(1, 40.0, 40.0); touchStart(1, 40.0, 40.0);
touchStart(2, 40.0, 60.0); touchStart(2, 40.0, 60.0);
touchMove(2, 40.0, 80.0); touchMove(2, 40.0, 80.0);
touchMove(1, 40.0, 100.0); touchMove(1, 40.0, 80.0);
expect(gestures).to.not.have.been.called; expect(gestures).to.not.have.been.called;
@ -631,14 +631,14 @@ describe('Gesture handler', function () {
clientX: 40.0, clientX: 40.0,
clientY: 50.0, clientY: 50.0,
magnitudeX: 0.0, magnitudeX: 0.0,
magnitudeY: 40.0 } })); magnitudeY: 30.0 } }));
}); });
it('should handle slow diagonal two finger drag', function () { it('should handle slow diagonal two finger drag', function () {
touchStart(1, 50.0, 40.0); touchStart(1, 50.0, 40.0);
touchStart(2, 40.0, 60.0); touchStart(2, 40.0, 60.0);
touchMove(1, 70.0, 60.0); touchMove(1, 70.0, 60.0);
touchMove(2, 90.0, 110.0); touchMove(2, 60.0, 80.0);
expect(gestures).to.not.have.been.called; expect(gestures).to.not.have.been.called;
@ -659,8 +659,8 @@ describe('Gesture handler', function () {
detail: { type: 'twodrag', detail: { type: 'twodrag',
clientX: 45.0, clientX: 45.0,
clientY: 50.0, clientY: 50.0,
magnitudeX: 35.0, magnitudeX: 20.0,
magnitudeY: 35.0 } })); magnitudeY: 20.0 } }));
}); });
it('should ignore too slow two finger drag', function () { it('should ignore too slow two finger drag', function () {
@ -783,7 +783,7 @@ describe('Gesture handler', function () {
it('should handle pinching inwards slowly', function () { it('should handle pinching inwards slowly', function () {
touchStart(1, 0.0, 0.0); touchStart(1, 0.0, 0.0);
touchStart(2, 130.0, 130.0); touchStart(2, 130.0, 130.0);
touchMove(1, 50.0, 40.0); touchMove(1, 30.0, 20.0);
touchMove(2, 100.0, 130.0); touchMove(2, 100.0, 130.0);
expect(gestures).to.not.have.been.called; expect(gestures).to.not.have.been.called;
@ -805,14 +805,76 @@ describe('Gesture handler', function () {
detail: { type: 'pinch', detail: { type: 'pinch',
clientX: 65.0, clientX: 65.0,
clientY: 65.0, clientY: 65.0,
magnitudeX: 50.0, magnitudeX: 70.0,
magnitudeY: 90.0 } })); magnitudeY: 110.0 } }));
});
it('should handle second pinch afterwards', function () {
touchStart(1, 0.0, 0.0);
touchStart(2, 130.0, 130.0);
touchMove(1, 30.0, 20.0);
touchMove(2, 100.0, 130.0);
expect(gestures).to.not.have.been.called;
clock.tick(60);
expect(gestures).to.have.been.calledTwice;
expect(gestures.firstCall).to.have.been.calledWith(
sinon.match({ type: 'gesturestart',
detail: { type: 'pinch',
clientX: 65.0,
clientY: 65.0,
magnitudeX: 130.0,
magnitudeY: 130.0 } }));
expect(gestures.secondCall).to.have.been.calledWith(
sinon.match({ type: 'gesturemove',
detail: { type: 'pinch',
clientX: 65.0,
clientY: 65.0,
magnitudeX: 70.0,
magnitudeY: 110.0 } }));
touchEnd(1);
touchEnd(2);
gestures.resetHistory();
touchStart(3, 0.0, 0.0);
touchStart(4, 130.0, 130.0);
touchMove(3, 30.0, 20.0);
touchMove(4, 100.0, 130.0);
expect(gestures).to.not.have.been.called;
clock.tick(60);
expect(gestures).to.have.been.calledTwice;
expect(gestures.firstCall).to.have.been.calledWith(
sinon.match({ type: 'gesturestart',
detail: { type: 'pinch',
clientX: 65.0,
clientY: 65.0,
magnitudeX: 130.0,
magnitudeY: 130.0 } }));
expect(gestures.secondCall).to.have.been.calledWith(
sinon.match({ type: 'gesturemove',
detail: { type: 'pinch',
clientX: 65.0,
clientY: 65.0,
magnitudeX: 70.0,
magnitudeY: 110.0 } }));
}); });
it('should handle pinching outwards slowly', function () { it('should handle pinching outwards slowly', function () {
touchStart(1, 100.0, 130.0); touchStart(1, 100.0, 130.0);
touchStart(2, 110.0, 130.0); touchStart(2, 110.0, 130.0);
touchMove(2, 200.0, 130.0); touchMove(2, 130.0, 130.0);
expect(gestures).to.not.have.been.called; expect(gestures).to.not.have.been.called;
@ -833,7 +895,7 @@ describe('Gesture handler', function () {
detail: { type: 'pinch', detail: { type: 'pinch',
clientX: 105.0, clientX: 105.0,
clientY: 130.0, clientY: 130.0,
magnitudeX: 100.0, magnitudeX: 30.0,
magnitudeY: 0.0 } })); magnitudeY: 0.0 } }));
}); });