Merge pull request #930 from dlukez/master

Handle simultaneous touch events
This commit is contained in:
Ian Gilman 2016-05-17 10:44:46 -07:00
commit 436ff0d086
5 changed files with 219 additions and 7 deletions

View File

@ -1357,11 +1357,11 @@
* @private
* @inner
*/
function capturePointer( tracker, pointerType ) {
function capturePointer( tracker, pointerType, pointerCount ) {
var pointsList = tracker.getActivePointersListByType( pointerType ),
eventParams;
pointsList.captureCount++;
pointsList.captureCount += (pointerCount || 1);
if ( pointsList.captureCount === 1 ) {
if ( $.Browser.vendor === $.BROWSERS.IE && $.Browser.version < 9 ) {
@ -1400,11 +1400,11 @@
* @private
* @inner
*/
function releasePointer( tracker, pointerType ) {
function releasePointer( tracker, pointerType, pointerCount ) {
var pointsList = tracker.getActivePointersListByType( pointerType ),
eventParams;
pointsList.captureCount--;
pointsList.captureCount -= (pointerCount || 1);
if ( pointsList.captureCount === 0 ) {
if ( $.Browser.vendor === $.BROWSERS.IE && $.Browser.version < 9 ) {
@ -2074,7 +2074,7 @@
if ( updatePointersDown( tracker, event, gPoints, 0 ) ) { // 0 means primary button press/release or touch contact
$.stopEvent( event );
capturePointer( tracker, 'touch' );
capturePointer( tracker, 'touch', touchCount );
}
$.cancelEvent( event );
@ -2128,7 +2128,7 @@
}
if ( updatePointersUp( tracker, event, gPoints, 0 ) ) {
releasePointer( tracker, 'touch' );
releasePointer( tracker, 'touch', touchCount );
}
// simulate touchleave on our tracked element

View File

@ -53,6 +53,7 @@
<!-- Helpers -->
<script src="/test/helpers/legacy.mouse.shim.js"></script>
<script src="/test/helpers/test.js"></script>
<script src="/test/helpers/touch.js"></script>
<!-- Modules -->
<!-- Polyfill must be inserted first because it is testing functions

134
test/helpers/touch.js Normal file
View File

@ -0,0 +1,134 @@
/* global TouchUtil, $ */
(function () {
var touches,
identifier,
target;
// ----------
window.TouchUtil = {
reset: function () {
touches = [];
identifier = 0;
},
initTracker: function ( tracker ) {
// for testing in other touch-enabled browsers
if ( !('ontouchstart' in window) ) {
tracker.setTracking( false );
OpenSeadragon.MouseTracker.subscribeEvents.push( 'touchstart', 'touchend' );
tracker.setTracking( true );
}
target = tracker.element;
},
resetTracker: function ( tracker ) {
// for testing in other touch-enabled browsers
if ( !('ontouchstart' in window) ) {
tracker.setTracking( false );
['touchstart', 'touchend'].forEach(function ( type ) {
var index = OpenSeadragon.MouseTracker.subscribeEvents.indexOf( type );
if ( index > -1 ) {
OpenSeadragon.MouseTracker.subscribeEvents.splice( index, 1 );
}
});
tracker.setTracking( true );
}
target = null;
},
start: function () {
var touch,
event,
newTouches = [];
for ( var i = 0; i < arguments.length; i++ ) {
touch = createTouch(
target.offsetLeft + arguments[ i ][ 0 ],
target.offsetTop + arguments[ i ][ 1 ]
);
touches.push( touch );
newTouches.push( touch );
}
event = createTouchEvent( 'touchstart', newTouches );
target.dispatchEvent( event );
return newTouches.length === 1 ? newTouches[ 0 ] : newTouches;
},
end: function ( changedTouches ) {
if ( !$.isArray( changedTouches ) ) {
changedTouches = [ changedTouches ];
}
var event;
touches = touches.filter(function ( touch ) {
return changedTouches.indexOf( touch ) === -1;
});
event = createTouchEvent( 'touchend', changedTouches );
target.dispatchEvent( event );
}
};
// ----------
function createTouch( x, y ) {
try {
// new spec
return new Touch({
identifier: identifier++,
target: target,
pageX: target.offsetLeft + x,
pageY: target.offsetTop + y
} );
} catch (e) {
// legacy
return document.createTouch( window, target, identifier++, x, y, x, y );
}
}
function createTouchList( touches ) {
// legacy
return document.createTouchList.apply( document, touches );
}
function createTouchEvent( type, changedTouches ) {
try {
// new spec
return new TouchEvent( type, {
view: window,
bubbles: true,
cancelable: true,
touches: touches,
targetTouches: touches,
changedTouches: changedTouches
} );
} catch (e) {
// legacy
var touchEvent = document.createEvent( 'TouchEvent' );
var touch1 = changedTouches[ 0 ];
touchEvent.initTouchEvent(
createTouchList( touches ), // touches
createTouchList( touches ), // targetTouches
createTouchList( changedTouches ), // changedTouches
type, // type
window, // view
touch1.screenX, // screenX
touch1.screenY, // screenY
touch1.clientX, // clientX
touch1.clientY, // clientY
false, // ctrlKey
false, // altKey
false, // shiftKey
false // metaKey
);
return touchEvent;
}
}
})();

View File

@ -1,4 +1,4 @@
/* global module, asyncTest, $, ok, equal, notEqual, start, test, Util, testLog */
/* global module, asyncTest, $, ok, equal, notEqual, start, test, TouchUtil, Util, testLog */
(function () {
var viewer;
@ -677,6 +677,82 @@
viewer.open( '/test/data/testpattern.dzi' );
} );
// ----------
if ('TouchEvent' in window) {
asyncTest( 'MouseTracker: touch events', function () {
var $canvas = $( viewer.element ).find( '.openseadragon-canvas' ).not( '.navigator .openseadragon-canvas' ),
tracker = viewer.innerTracker,
touches;
var reset = function () {
touches = [];
TouchUtil.reset();
};
var assessTouchExpectations = function ( expected ) {
var pointersList = tracker.getActivePointersListByType( 'touch' );
if ('captureCount' in expected) {
equal( pointersList.captureCount, expected.captureCount, expected.description + 'Pointer capture count matches expected (' + expected.captureCount + ')' );
}
if ('contacts' in expected) {
equal( pointersList.contacts, expected.contacts, expected.description + 'Pointer contact count matches expected (' + expected.contacts + ')' );
}
if ('trackedPointers' in expected) {
equal( pointersList.getLength(), expected.trackedPointers, expected.description + 'Tracked pointer count matches expected (' + expected.trackedPointers + ')' );
}
};
var onOpen = function ( event ) {
viewer.removeHandler( 'open', onOpen );
TouchUtil.initTracker( tracker );
// start-end-end (multi-touch start event)
reset();
touches = TouchUtil.start( [0,0], [20,20] );
assessTouchExpectations({
description: 'start-end-end (multi-touch start event) [capture]: ',
captureCount: 2,
contacts: 2,
trackedPointers: 2
});
TouchUtil.end( touches[1] );
TouchUtil.end( touches[0] );
assessTouchExpectations({
description: 'start-end-end (multi-touch start event) [release]: ',
captureCount: 0,
contacts: 0,
trackedPointers: 0
});
// start-start-end (multi-touch end event)
reset();
touches.push( TouchUtil.start([0, 0]) );
touches.push( TouchUtil.start([20, 20]) );
assessTouchExpectations({
description: 'start-start-end (multi-touch end event) [capture]: ',
captureCount: 2,
contacts: 2,
trackedPointers: 2
});
TouchUtil.end( touches );
assessTouchExpectations({
description: 'start-start-end (multi-touch end event) [release]: ',
captureCount: 0,
contacts: 0,
trackedPointers: 0
});
TouchUtil.resetTracker( tracker );
viewer.close();
start();
};
viewer.addHandler( 'open', onOpen );
viewer.open( '/test/data/testpattern.dzi' );
} );
}
// ----------
asyncTest('Viewer: preventDefaultAction', function() {
var $canvas = $(viewer.element).find('.openseadragon-canvas')

View File

@ -17,6 +17,7 @@
<script src="/build/openseadragon/openseadragon.js"></script>
<script src="/test/helpers/legacy.mouse.shim.js"></script>
<script src="/test/helpers/test.js"></script>
<script src="/test/helpers/touch.js"></script>
<!-- Polyfill must be inserted first because it is testing functions
reassignments which could be done by other test. -->