Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Avoid transitioning from pinch until all fingers have been released. #6479

Merged
merged 5 commits into from
May 24, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions Source/Core/ScreenSpaceEventHandler.js
Original file line number Diff line number Diff line change
Expand Up @@ -401,6 +401,7 @@ define([
var numberOfTouches = positions.length;
var action;
var clickAction;
var pinching = screenSpaceEventHandler._isPinching;

if (numberOfTouches !== 1 && screenSpaceEventHandler._buttonDown === MouseButton.LEFT) {
// transitioning from single touch, trigger UP and might trigger CLICK
Expand Down Expand Up @@ -435,7 +436,7 @@ define([
// Otherwise don't trigger CLICK, because we are adding more touches.
}

if (numberOfTouches !== 2 && screenSpaceEventHandler._isPinching) {
if (numberOfTouches === 0 && pinching) {
// transitioning from pinch, trigger PINCH_END
screenSpaceEventHandler._isPinching = false;

Expand All @@ -446,7 +447,7 @@ define([
}
}

if (numberOfTouches === 1) {
if (numberOfTouches === 1 && !pinching) {
// transitioning to single touch, trigger DOWN
var position = positions.values[0];
Cartesian2.clone(position, screenSpaceEventHandler._primaryPosition);
Expand All @@ -466,7 +467,7 @@ define([
event.preventDefault();
}

if (numberOfTouches === 2) {
if (numberOfTouches === 2 && !pinching) {
// transitioning to pinch, trigger PINCH_START
screenSpaceEventHandler._isPinching = true;

Expand Down
107 changes: 107 additions & 0 deletions Specs/Core/ScreenSpaceEventHandlerSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -1037,6 +1037,113 @@ defineSuite([
expect(action).not.toHaveBeenCalled();
});

it('handles touch pinch release', function() {
var leftDownEventType = ScreenSpaceEventType.LEFT_DOWN;
var leftDownAction = createCloningSpy('LEFT_DOWN');
handler.setInputAction(leftDownAction, leftDownEventType);

var pinchStartEventType = ScreenSpaceEventType.PINCH_START;
var pinchStartAction = createCloningSpy('PINCH_START');
handler.setInputAction(pinchStartAction, pinchStartEventType);

var pinchEndEventType = ScreenSpaceEventType.PINCH_END;
var pinchEndAction = createCloningSpy('PINCH_END');
handler.setInputAction(pinchEndAction, pinchEndEventType);

var touch1Position = {
clientX : 1,
clientY : 2
};
var touch2Position = {
clientX : 4,
clientY : 3
};
if (usePointerEvents) {
DomEventSimulator.firePointerDown(element, combine(
{
pointerType : 'touch',
pointerId : 1
},
touch1Position
));
DomEventSimulator.firePointerDown(element, combine(
{
pointerType : 'touch',
pointerId : 2
},
touch2Position
));

// Releasing one of two fingers should not trigger
// PINCH_END or LEFT_DOWN:
leftDownAction.calls.reset();
DomEventSimulator.firePointerUp(element, combine(
{
pointerType : 'touch',
pointerId : 1
},
touch1Position
));
expect(pinchEndAction).not.toHaveBeenCalled();
expect(leftDownAction).not.toHaveBeenCalled();
pinchEndAction.calls.reset();

// Putting another finger down should not trigger
// PINCH_START:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test fails, and indeed PINCH_START is re-called when the user's touch count deviates from 2 (while remaining non-zero) and returns to 2, bringing pinch out of suspension. I'm not sure this is a bad thing, as the pinch is re-starting even though it never fully stopped.

Anyway the test should be fixed, not sure if by changing the test's expectation or by suppressing the pinch re-start event.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks – I will look into this next week!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since we aren't firing PINCH_END with a single touch up, it indeed doesn't make sense to fire PINCH_START when moving back to 2 fingers down.

I added a check to see if we are already pinching when touch count returns to 0.. All tests should be green and I merged in master.

pinchStartAction.calls.reset();
DomEventSimulator.firePointerDown(element, combine(
{
pointerType : 'touch',
pointerId : 1
},
touch2Position
));
expect(pinchStartAction).not.toHaveBeenCalled();

// Releasing both fingers should trigger PINCH_END:
DomEventSimulator.firePointerUp(element, combine(
{
pointerType : 'touch',
pointerId : 1
},
touch2Position
));
DomEventSimulator.firePointerUp(element, combine({
pointerType : 'touch',
pointerId : 2
}, touch2Position));
expect(pinchEndAction).toHaveBeenCalled();
} else {
DomEventSimulator.fireTouchStart(element, {
changedTouches : [
combine({ identifier : 0 }, touch1Position),
combine({ identifier : 1 }, touch2Position)
]
});
leftDownAction.calls.reset();

// Releasing one of two fingers should not trigger
// PINCH_END or LEFT_DOWN:
DomEventSimulator.fireTouchEnd(element, {
changedTouches : [
combine({ identifier : 0 }, touch1Position)
]
});

expect(pinchEndAction).not.toHaveBeenCalled();
expect(leftDownAction).not.toHaveBeenCalled();

// Releasing both fingers should trigger PINCH_END:
pinchEndAction.calls.reset();
DomEventSimulator.fireTouchEnd(element, {
changedTouches : [
combine({ identifier : 1 }, touch2Position)
]
});
expect(pinchEndAction).toHaveBeenCalled();
}
});

it('handles touch click', function() {
var eventType = ScreenSpaceEventType.LEFT_CLICK;

Expand Down