diff --git a/src/renderers/shared/event/eventPlugins/ResponderEventPlugin.js b/src/renderers/shared/event/eventPlugins/ResponderEventPlugin.js index 3719fb92e8..456746ae52 100644 --- a/src/renderers/shared/event/eventPlugins/ResponderEventPlugin.js +++ b/src/renderers/shared/event/eventPlugins/ResponderEventPlugin.js @@ -46,13 +46,14 @@ var trackedTouchCount = 0; */ var previousActiveTouches = 0; -var changeResponder = function(nextResponderInst) { +var changeResponder = function(nextResponderInst, blockNativeResponder) { var oldResponderInst = responderInst; responderInst = nextResponderInst; if (ResponderEventPlugin.GlobalResponderHandler !== null) { ResponderEventPlugin.GlobalResponderHandler.onChange( oldResponderInst, - nextResponderInst + nextResponderInst, + blockNativeResponder ); } }; @@ -370,6 +371,7 @@ function setResponderAndExtractTransfer( grantEvent.touchHistory = ResponderTouchHistoryStore.touchHistory; EventPropagators.accumulateDirectDispatches(grantEvent); + var blockNativeResponder = executeDirectDispatch(grantEvent) === true; if (responderInst) { var terminationRequestEvent = ResponderSyntheticEvent.getPooled( @@ -396,7 +398,7 @@ function setResponderAndExtractTransfer( terminateEvent.touchHistory = ResponderTouchHistoryStore.touchHistory; EventPropagators.accumulateDirectDispatches(terminateEvent); extracted = accumulate(extracted, [grantEvent, terminateEvent]); - changeResponder(wantsResponderInst); + changeResponder(wantsResponderInst, blockNativeResponder); } else { var rejectEvent = ResponderSyntheticEvent.getPooled( eventTypes.responderReject, @@ -410,7 +412,7 @@ function setResponderAndExtractTransfer( } } else { extracted = accumulate(extracted, grantEvent); - changeResponder(wantsResponderInst); + changeResponder(wantsResponderInst, blockNativeResponder); } return extracted; } @@ -423,9 +425,13 @@ function setResponderAndExtractTransfer( * @param {string} topLevelType Record from `EventConstants`. * @return {boolean} True if a transfer of responder could possibly occur. */ -function canTriggerTransfer(topLevelType, targetInst) { - return !!targetInst && ( - topLevelType === EventConstants.topLevelTypes.topScroll || +function canTriggerTransfer(topLevelType, topLevelInst, nativeEvent) { + return topLevelInst && ( + // responderIgnoreScroll: We are trying to migrate away from specifically + // tracking native scroll events here and responderIgnoreScroll indicates we + // will send topTouchCancel to handle canceling touch events instead + (topLevelType === EventConstants.topLevelTypes.topScroll && + !nativeEvent.responderIgnoreScroll) || (trackedTouchCount > 0 && topLevelType === EventConstants.topLevelTypes.topSelectionChange) || isStartish(topLevelType) || @@ -492,7 +498,7 @@ var ResponderEventPlugin = { ResponderTouchHistoryStore.recordTouchTrack(topLevelType, nativeEvent, nativeEventTarget); - var extracted = canTriggerTransfer(topLevelType, targetInst) ? + var extracted = canTriggerTransfer(topLevelType, targetInst, nativeEvent) ? setResponderAndExtractTransfer( topLevelType, targetInst, diff --git a/src/renderers/shared/event/eventPlugins/__tests__/ResponderEventPlugin-test.js b/src/renderers/shared/event/eventPlugins/__tests__/ResponderEventPlugin-test.js index a14aec7847..42d6f13361 100644 --- a/src/renderers/shared/event/eventPlugins/__tests__/ResponderEventPlugin-test.js +++ b/src/renderers/shared/event/eventPlugins/__tests__/ResponderEventPlugin-test.js @@ -730,8 +730,8 @@ describe('ResponderEventPlugin', function() { // Parent is responder, and responder is transferred by a second touch start config.startShouldSetResponder.captured.grandParent = {order: 0, returnVal: true}; - config.responderTerminationRequest.parent = {order: 1, returnVal: true}; - config.responderGrant.grandParent = {order: 2}; + config.responderGrant.grandParent = {order: 1}; + config.responderTerminationRequest.parent = {order: 2, returnVal: true}; config.responderTerminate.parent = {order: 3}; config.responderStart.grandParent = {order: 4}; run(config, three, startConfig(three.child, [three.child, three.child], [1])); @@ -899,10 +899,11 @@ describe('ResponderEventPlugin', function() { config.moveShouldSetResponder.captured.grandParent = {order: 0, returnVal: false}; config.moveShouldSetResponder.captured.parent = {order: 1, returnVal: false}; config.moveShouldSetResponder.bubbled.parent = {order: 2, returnVal: true}; - config.responderTerminationRequest.child = {order: 3, returnVal: false}; - config.responderReject.parent = {order: 4}; + config.responderGrant.parent = {order: 3}; + config.responderTerminationRequest.child = {order: 4, returnVal: false}; + config.responderReject.parent = {order: 5}; // The start/move should occur on the original responder if new one is rejected - config.responderMove.child = {order: 5}; + config.responderMove.child = {order: 6}; var touchConfig = moveConfig(three.child, [three.child], [0]); @@ -913,10 +914,11 @@ describe('ResponderEventPlugin', function() { config.startShouldSetResponder.captured.grandParent = {order: 0, returnVal: false}; config.startShouldSetResponder.captured.parent = {order: 1, returnVal: false}; config.startShouldSetResponder.bubbled.parent = {order: 2, returnVal: true}; - config.responderTerminationRequest.child = {order: 3, returnVal: false}; - config.responderReject.parent = {order: 4}; + config.responderGrant.parent = {order: 3}; + config.responderTerminationRequest.child = {order: 4, returnVal: false}; + config.responderReject.parent = {order: 5}; // The start/move should occur on the original responder if new one is rejected - config.responderStart.child = {order: 5}; + config.responderStart.child = {order: 6}; touchConfig = startConfig(three.child, [three.child, three.child], [1]); @@ -946,8 +948,9 @@ describe('ResponderEventPlugin', function() { config.scrollShouldSetResponder.captured.grandParent = {order: 0, returnVal: false}; config.scrollShouldSetResponder.captured.parent = {order: 1, returnVal: false}; config.scrollShouldSetResponder.bubbled.parent = {order: 2, returnVal: true}; - config.responderTerminationRequest.child = {order: 3, returnVal: false}; - config.responderReject.parent = {order: 4}; + config.responderGrant.parent = {order: 3}; + config.responderTerminationRequest.child = {order: 4, returnVal: false}; + config.responderReject.parent = {order: 5}; run(config, three, { topLevelType: topLevelTypes.topScroll, @@ -962,8 +965,8 @@ describe('ResponderEventPlugin', function() { config.scrollShouldSetResponder.captured.grandParent = {order: 0, returnVal: false}; config.scrollShouldSetResponder.captured.parent = {order: 1, returnVal: false}; config.scrollShouldSetResponder.bubbled.parent = {order: 2, returnVal: true}; - config.responderTerminationRequest.child = {order: 3, returnVal: true}; - config.responderGrant.parent = {order: 4}; + config.responderGrant.parent = {order: 3}; + config.responderTerminationRequest.child = {order: 4, returnVal: true}; config.responderTerminate.child = {order: 5}; run(config, three, {