void InputQueue::MaybeRequestContentResponse(const RefPtr<AsyncPanZoomController>& aTarget, CancelableBlockState* aBlock) { bool waitForMainThread = false; if (aBlock->IsTargetConfirmed()) { // Content won't prevent-default this, so we can just set the flag directly. INPQ_LOG("not waiting for content response on block %p\n", aBlock); aBlock->SetContentResponse(false); } else { waitForMainThread = true; } if (aBlock->AsTouchBlock() && gfxPrefs::TouchActionEnabled()) { // waitForMainThread is set to true unconditionally here, but if the APZCTM // has the touch-action behaviours for this block, it will set it // immediately after we unwind out of this ReceiveInputEvent call. So even // though we are scheduling the main-thread timeout, we might end up not // waiting. INPQ_LOG("waiting for main thread touch-action info on block %p\n", aBlock); waitForMainThread = true; } if (waitForMainThread) { // We either don't know for sure if aTarget is the right APZC, or we may // need to wait to give content the opportunity to prevent-default the // touch events. Either way we schedule a timeout so the main thread stuff // can run. ScheduleMainThreadTimeout(aTarget, aBlock); } }
nsEventStatus InputQueue::ReceiveMouseInput(const RefPtr<AsyncPanZoomController>& aTarget, bool aTargetConfirmed, const MouseInput& aEvent, uint64_t* aOutInputBlockId) { // On a new mouse down we can have a new target so we must force a new block // with a new target. bool newBlock = DragTracker::StartsDrag(aEvent); DragBlockState* block = newBlock ? nullptr : mActiveDragBlock.get(); if (block && block->HasReceivedMouseUp()) { block = nullptr; } if (!block && mDragTracker.InDrag()) { // If there's no current drag block, but we're getting a move with a button // down, we need to start a new drag block because we're obviously already // in the middle of a drag (it probably got interrupted by something else). INPQ_LOG("got a drag event outside a drag block, need to create a block to hold it\n"); newBlock = true; } mDragTracker.Update(aEvent); if (!newBlock && !block) { // This input event is not in a drag block, so we're not doing anything // with it, return eIgnore. return nsEventStatus_eIgnore; } if (!block) { MOZ_ASSERT(newBlock); block = new DragBlockState(aTarget, aTargetConfirmed, aEvent); INPQ_LOG("started new drag block %p id %" PRIu64 " for %sconfirmed target %p\n", block, block->GetBlockId(), aTargetConfirmed ? "" : "un", aTarget.get()); mActiveDragBlock = block; CancelAnimationsForNewBlock(block); MaybeRequestContentResponse(aTarget, block); } if (aOutInputBlockId) { *aOutInputBlockId = block->GetBlockId(); } mQueuedInputs.AppendElement(MakeUnique<QueuedInput>(aEvent, *block)); ProcessQueue(); if (DragTracker::EndsDrag(aEvent)) { block->MarkMouseUpReceived(); } // The event is part of a drag block and could potentially cause // scrolling, so return DoDefault. return nsEventStatus_eConsumeDoDefault; }
nsEventStatus InputQueue::ReceiveScrollWheelInput(const RefPtr<AsyncPanZoomController>& aTarget, bool aTargetConfirmed, const ScrollWheelInput& aEvent, uint64_t* aOutInputBlockId) { WheelBlockState* block = nullptr; if (!mInputBlockQueue.IsEmpty()) { block = mInputBlockQueue.LastElement()->AsWheelBlock(); // If the block is not accepting new events we'll create a new input block // (and therefore a new wheel transaction). if (block && (!block->ShouldAcceptNewEvent() || block->MaybeTimeout(aEvent))) { block = nullptr; } } MOZ_ASSERT(!block || block->InTransaction()); if (!block) { block = new WheelBlockState(aTarget, aTargetConfirmed, aEvent); INPQ_LOG("started new scroll wheel block %p for target %p\n", block, aTarget.get()); SweepDepletedBlocks(); mInputBlockQueue.AppendElement(block); CancelAnimationsForNewBlock(block); MaybeRequestContentResponse(aTarget, block); } else { INPQ_LOG("received new event in block %p\n", block); } if (aOutInputBlockId) { *aOutInputBlockId = block->GetBlockId(); } block->Update(aEvent); // Note that the |aTarget| the APZCTM sent us may contradict the confirmed // target set on the block. In this case the confirmed target (which may be // null) should take priority. This is equivalent to just always using the // target (confirmed or not) from the block, which is what // MaybeHandleCurrentBlock() does. if (!MaybeHandleCurrentBlock(block, aEvent)) { block->AddEvent(aEvent.AsScrollWheelInput()); } return nsEventStatus_eConsumeDoDefault; }
nsEventStatus InputQueue::ReceiveScrollWheelInput(const RefPtr<AsyncPanZoomController>& aTarget, bool aTargetConfirmed, const ScrollWheelInput& aEvent, uint64_t* aOutInputBlockId) { WheelBlockState* block = mActiveWheelBlock.get(); // If the block is not accepting new events we'll create a new input block // (and therefore a new wheel transaction). if (block && (!block->ShouldAcceptNewEvent() || block->MaybeTimeout(aEvent))) { block = nullptr; } MOZ_ASSERT(!block || block->InTransaction()); if (!block) { block = new WheelBlockState(aTarget, aTargetConfirmed, aEvent); INPQ_LOG("started new scroll wheel block %p id %" PRIu64 " for target %p\n", block, block->GetBlockId(), aTarget.get()); mActiveWheelBlock = block; CancelAnimationsForNewBlock(block); MaybeRequestContentResponse(aTarget, block); } else { INPQ_LOG("received new event in block %p\n", block); } if (aOutInputBlockId) { *aOutInputBlockId = block->GetBlockId(); } // Note that the |aTarget| the APZCTM sent us may contradict the confirmed // target set on the block. In this case the confirmed target (which may be // null) should take priority. This is equivalent to just always using the // target (confirmed or not) from the block, which is what // ProcessQueue() does. mQueuedInputs.AppendElement(MakeUnique<QueuedInput>(aEvent, *block)); // The WheelBlockState needs to affix a counter to the event before we process // it. Note that the counter is affixed to the copy in the queue rather than // |aEvent|. block->Update(mQueuedInputs.LastElement()->Input()->AsScrollWheelInput()); ProcessQueue(); return nsEventStatus_eConsumeDoDefault; }
void InputQueue::ScheduleMainThreadTimeout(const RefPtr<AsyncPanZoomController>& aTarget, uint64_t aInputBlockId) { INPQ_LOG("scheduling main thread timeout for target %p\n", aTarget.get()); aTarget->PostDelayedTask( NewRunnableMethod(this, &InputQueue::MainThreadTimeout, aInputBlockId), gfxPrefs::APZContentResponseTimeout()); }
void InputQueue::MaybeRequestContentResponse(const RefPtr<AsyncPanZoomController>& aTarget, CancelableBlockState* aBlock) { bool waitForMainThread = false; if (aBlock->IsTargetConfirmed()) { // Content won't prevent-default this, so we can just set the flag directly. INPQ_LOG("not waiting for content response on block %p\n", aBlock); aBlock->SetContentResponse(false); } else { waitForMainThread = true; } if (aBlock->AsTouchBlock() && gfxPrefs::TouchActionEnabled()) { // TODO: once bug 1101628 is fixed, waitForMainThread should only be set // to true if the APZCTM didn't know the touch-action behaviours for this // block. waitForMainThread = true; } if (waitForMainThread) { // We either don't know for sure if aTarget is the right APZC, or we may // need to wait to give content the opportunity to prevent-default the // touch events. Either way we schedule a timeout so the main thread stuff // can run. ScheduleMainThreadTimeout(aTarget, aBlock->GetBlockId()); } }
void InputQueue::ScheduleMainThreadTimeout(const RefPtr<AsyncPanZoomController>& aTarget, CancelableBlockState* aBlock) { INPQ_LOG("scheduling main thread timeout for target %p\n", aTarget.get()); aBlock->StartContentResponseTimer(); aTarget->PostDelayedTask(NewRunnableMethod<uint64_t>(this, &InputQueue::MainThreadTimeout, aBlock->GetBlockId()), gfxPrefs::APZContentResponseTimeout()); }
uint64_t InputQueue::InjectNewTouchBlock(AsyncPanZoomController* aTarget) { TouchBlockState* block = StartNewTouchBlock(aTarget, /* aTargetConfirmed = */ true, /* aCopyPropertiesFromCurrent = */ true); INPQ_LOG("injecting new touch block %p with id %" PRIu64 " and target %p\n", block, block->GetBlockId(), aTarget); ScheduleMainThreadTimeout(aTarget, block->GetBlockId()); return block->GetBlockId(); }
void InputQueue::ProcessInputBlocks() { APZThreadUtils::AssertOnControllerThread(); do { CancelableBlockState* curBlock = CurrentBlock(); if (!curBlock->IsReadyForHandling()) { break; } INPQ_LOG("processing input block %p; preventDefault %d target %p\n", curBlock, curBlock->IsDefaultPrevented(), curBlock->GetTargetApzc().get()); RefPtr<AsyncPanZoomController> target = curBlock->GetTargetApzc(); // target may be null here if the initial target was unconfirmed and then // we later got a confirmed null target. in that case drop the events. if (!target) { curBlock->DropEvents(); } else if (curBlock->IsDefaultPrevented()) { curBlock->DropEvents(); target->ResetInputState(); } else { UpdateActiveApzc(curBlock->GetTargetApzc()); curBlock->HandleEvents(); } MOZ_ASSERT(!curBlock->HasEvents()); if (mInputBlockQueue.Length() == 1 && curBlock->MustStayActive()) { // Some types of blocks (e.g. touch blocks) accumulate events until the // next input block is started. Therefore we cannot remove the block from // the queue until we have started another block. This block will be // removed by SweepDeletedBlocks() whenever a new block is added. break; } // If we get here, we know there are more touch blocks in the queue after // |curBlock|, so we can remove |curBlock| and try to process the next one. INPQ_LOG("discarding processed %s block %p\n", curBlock->Type(), curBlock); mInputBlockQueue.RemoveElementAt(0); } while (!mInputBlockQueue.IsEmpty()); }
void InputQueue::SweepDepletedBlocks() { // We're going to start a new block, so clear out any depleted blocks at the head of the queue. // See corresponding comment in ProcessInputBlocks. while (!mInputBlockQueue.IsEmpty()) { CancelableBlockState* block = mInputBlockQueue[0].get(); if (!block->IsReadyForHandling() || block->HasEvents()) { break; } INPQ_LOG("discarding depleted %s block %p\n", block->Type(), block); mInputBlockQueue.RemoveElementAt(0); } }
void InputQueue::ContentReceivedInputBlock(uint64_t aInputBlockId, bool aPreventDefault) { APZThreadUtils::AssertOnControllerThread(); INPQ_LOG("got a content response; block=%" PRIu64 "\n", aInputBlockId); bool success = false; CancelableBlockState* block = FindBlockForId(aInputBlockId, nullptr); if (block) { success = block->SetContentResponse(aPreventDefault); block->RecordContentResponseTime(); } if (success) { ProcessQueue(); } }
bool InputQueue::MaybeHandleCurrentBlock(CancelableBlockState *block, const InputData& aEvent) { if (block == CurrentBlock() && block->IsReadyForHandling()) { const RefPtr<AsyncPanZoomController>& target = block->GetTargetApzc(); INPQ_LOG("current block is ready with target %p preventdefault %d\n", target.get(), block->IsDefaultPrevented()); if (!target || block->IsDefaultPrevented()) { return true; } UpdateActiveApzc(block->GetTargetApzc()); block->DispatchImmediate(aEvent); return true; } return false; }
void InputQueue::SetConfirmedTargetApzc(uint64_t aInputBlockId, const RefPtr<AsyncPanZoomController>& aTargetApzc) { APZThreadUtils::AssertOnControllerThread(); INPQ_LOG("got a target apzc; block=%" PRIu64 " guid=%s\n", aInputBlockId, aTargetApzc ? Stringify(aTargetApzc->GetGuid()).c_str() : ""); bool success = false; for (size_t i = 0; i < mInputBlockQueue.Length(); i++) { if (mInputBlockQueue[i]->GetBlockId() == aInputBlockId) { success = mInputBlockQueue[i]->SetConfirmedTargetApzc(aTargetApzc); break; } } if (success) { ProcessInputBlocks(); } }
void InputQueue::ContentReceivedInputBlock(uint64_t aInputBlockId, bool aPreventDefault) { APZThreadUtils::AssertOnControllerThread(); INPQ_LOG("got a content response; block=%" PRIu64 "\n", aInputBlockId); bool success = false; for (size_t i = 0; i < mInputBlockQueue.Length(); i++) { if (mInputBlockQueue[i]->GetBlockId() == aInputBlockId) { CancelableBlockState* block = mInputBlockQueue[i].get(); success = block->SetContentResponse(aPreventDefault); break; } } if (success) { ProcessInputBlocks(); } }
void InputQueue::SetAllowedTouchBehavior(uint64_t aInputBlockId, const nsTArray<TouchBehaviorFlags>& aBehaviors) { APZThreadUtils::AssertOnControllerThread(); INPQ_LOG("got allowed touch behaviours; block=%" PRIu64 "\n", aInputBlockId); bool success = false; CancelableBlockState* block = FindBlockForId(aInputBlockId, nullptr); if (block && block->AsTouchBlock()) { success = block->AsTouchBlock()->SetAllowedTouchBehaviors(aBehaviors); block->RecordContentResponseTime(); } else if (block) { NS_WARNING("input block is not a touch block"); } if (success) { ProcessQueue(); } }
void InputQueue::SetConfirmedTargetApzc(uint64_t aInputBlockId, const RefPtr<AsyncPanZoomController>& aTargetApzc) { APZThreadUtils::AssertOnControllerThread(); INPQ_LOG("got a target apzc; block=%" PRIu64 " guid=%s\n", aInputBlockId, aTargetApzc ? Stringify(aTargetApzc->GetGuid()).c_str() : ""); bool success = false; InputData* firstInput = nullptr; CancelableBlockState* block = FindBlockForId(aInputBlockId, &firstInput); if (block) { success = block->SetConfirmedTargetApzc(aTargetApzc, InputBlockState::TargetConfirmationState::eConfirmed, firstInput); block->RecordContentResponseTime(); } if (success) { ProcessQueue(); } }
void InputQueue::ProcessQueue() { APZThreadUtils::AssertOnControllerThread(); while (!mQueuedInputs.IsEmpty()) { CancelableBlockState* curBlock = mQueuedInputs[0]->Block(); if (!curBlock->IsReadyForHandling()) { break; } INPQ_LOG("processing input from block %p; preventDefault %d target %p\n", curBlock, curBlock->IsDefaultPrevented(), curBlock->GetTargetApzc().get()); RefPtr<AsyncPanZoomController> target = curBlock->GetTargetApzc(); // target may be null here if the initial target was unconfirmed and then // we later got a confirmed null target. in that case drop the events. if (target) { if (curBlock->IsDefaultPrevented()) { if (curBlock->AsTouchBlock()) { target->ResetTouchInputState(); } } else { UpdateActiveApzc(target); curBlock->DispatchEvent(*(mQueuedInputs[0]->Input())); } } mQueuedInputs.RemoveElementAt(0); } if (CanDiscardBlock(mActiveTouchBlock)) { mActiveTouchBlock = nullptr; } if (CanDiscardBlock(mActiveWheelBlock)) { mActiveWheelBlock = nullptr; } if (CanDiscardBlock(mActiveDragBlock)) { mActiveDragBlock = nullptr; } if (CanDiscardBlock(mActivePanGestureBlock)) { mActivePanGestureBlock = nullptr; } }
void InputQueue::MainThreadTimeout(const uint64_t& aInputBlockId) { APZThreadUtils::AssertOnControllerThread(); INPQ_LOG("got a main thread timeout; block=%" PRIu64 "\n", aInputBlockId); bool success = false; for (size_t i = 0; i < mInputBlockQueue.Length(); i++) { if (mInputBlockQueue[i]->GetBlockId() == aInputBlockId) { // time out the touch-listener response and also confirm the existing // target apzc in the case where the main thread doesn't get back to us // fast enough. success = mInputBlockQueue[i]->TimeoutContentResponse(); success |= mInputBlockQueue[i]->SetConfirmedTargetApzc(mInputBlockQueue[i]->GetTargetApzc()); break; } } if (success) { ProcessInputBlocks(); } }
void InputQueue::SetAllowedTouchBehavior(uint64_t aInputBlockId, const nsTArray<TouchBehaviorFlags>& aBehaviors) { APZThreadUtils::AssertOnControllerThread(); INPQ_LOG("got allowed touch behaviours; block=%" PRIu64 "\n", aInputBlockId); bool success = false; for (size_t i = 0; i < mInputBlockQueue.Length(); i++) { if (mInputBlockQueue[i]->GetBlockId() == aInputBlockId) { TouchBlockState *block = mInputBlockQueue[i]->AsTouchBlock(); if (block) { success = block->SetAllowedTouchBehaviors(aBehaviors); } else { NS_WARNING("input block is not a touch block"); } break; } } if (success) { ProcessInputBlocks(); } }
void InputQueue::MainThreadTimeout(uint64_t aInputBlockId) { APZThreadUtils::AssertOnControllerThread(); INPQ_LOG("got a main thread timeout; block=%" PRIu64 "\n", aInputBlockId); bool success = false; InputData* firstInput = nullptr; CancelableBlockState* block = FindBlockForId(aInputBlockId, &firstInput); if (block) { // time out the touch-listener response and also confirm the existing // target apzc in the case where the main thread doesn't get back to us // fast enough. success = block->TimeoutContentResponse(); success |= block->SetConfirmedTargetApzc( block->GetTargetApzc(), InputBlockState::TargetConfirmationState::eTimedOut, firstInput); } if (success) { ProcessQueue(); } }
nsEventStatus InputQueue::ReceivePanGestureInput(const RefPtr<AsyncPanZoomController>& aTarget, bool aTargetConfirmed, const PanGestureInput& aEvent, uint64_t* aOutInputBlockId) { if (aEvent.mType == PanGestureInput::PANGESTURE_MAYSTART || aEvent.mType == PanGestureInput::PANGESTURE_CANCELLED) { // Ignore these events for now. return nsEventStatus_eConsumeDoDefault; } PanGestureBlockState* block = nullptr; if (aEvent.mType != PanGestureInput::PANGESTURE_START) { block = mActivePanGestureBlock.get(); } PanGestureInput event = aEvent; nsEventStatus result = nsEventStatus_eConsumeDoDefault; if (!block || block->WasInterrupted()) { if (event.mType != PanGestureInput::PANGESTURE_START) { // Only PANGESTURE_START events are allowed to start a new pan gesture // block, but we really want to start a new block here, so we magically // turn this input into a PANGESTURE_START. INPQ_LOG("transmogrifying pan input %d to PANGESTURE_START for new block\n", event.mType); event.mType = PanGestureInput::PANGESTURE_START; } block = new PanGestureBlockState(aTarget, aTargetConfirmed, event); INPQ_LOG("started new pan gesture block %p id %" PRIu64 " for target %p\n", block, block->GetBlockId(), aTarget.get()); if (aTargetConfirmed && event.mRequiresContentResponseIfCannotScrollHorizontallyInStartDirection && !CanScrollTargetHorizontally(event, block)) { // This event may trigger a swipe gesture, depending on what our caller // wants to do it. We need to suspend handling of this block until we get // a content response which will tell us whether to proceed or abort the // block. block->SetNeedsToWaitForContentResponse(true); // Inform our caller that we haven't scrolled in response to the event // and that a swipe can be started from this event if desired. result = nsEventStatus_eIgnore; } mActivePanGestureBlock = block; CancelAnimationsForNewBlock(block); MaybeRequestContentResponse(aTarget, block); } else { INPQ_LOG("received new event in block %p\n", block); } if (aOutInputBlockId) { *aOutInputBlockId = block->GetBlockId(); } // Note that the |aTarget| the APZCTM sent us may contradict the confirmed // target set on the block. In this case the confirmed target (which may be // null) should take priority. This is equivalent to just always using the // target (confirmed or not) from the block, which is what // ProcessQueue() does. mQueuedInputs.AppendElement(MakeUnique<QueuedInput>(event, *block)); ProcessQueue(); return result; }
nsEventStatus InputQueue::ReceiveTouchInput(const RefPtr<AsyncPanZoomController>& aTarget, bool aTargetConfirmed, const MultiTouchInput& aEvent, uint64_t* aOutInputBlockId) { TouchBlockState* block = nullptr; if (aEvent.mType == MultiTouchInput::MULTITOUCH_START) { nsTArray<TouchBehaviorFlags> currentBehaviors; bool haveBehaviors = false; if (!gfxPrefs::TouchActionEnabled()) { haveBehaviors = true; } else if (!mInputBlockQueue.IsEmpty() && CurrentBlock()->AsTouchBlock()) { haveBehaviors = CurrentTouchBlock()->GetAllowedTouchBehaviors(currentBehaviors); // If the behaviours aren't set, but the main-thread response timer on // the block is expired we still treat it as though it has behaviors, // because in that case we still want to interrupt the fast-fling and // use the default behaviours. haveBehaviors |= CurrentTouchBlock()->IsContentResponseTimerExpired(); } block = StartNewTouchBlock(aTarget, aTargetConfirmed, false); INPQ_LOG("started new touch block %p for target %p\n", block, aTarget.get()); // XXX using the chain from |block| here may be wrong in cases where the // target isn't confirmed and the real target turns out to be something // else. For now assume this is rare enough that it's not an issue. if (block == CurrentBlock() && aEvent.mTouches.Length() == 1 && block->GetOverscrollHandoffChain()->HasFastFlungApzc() && haveBehaviors) { // If we're already in a fast fling, and a single finger goes down, then // we want special handling for the touch event, because it shouldn't get // delivered to content. Note that we don't set this flag when going // from a fast fling to a pinch state (i.e. second finger goes down while // the first finger is moving). block->SetDuringFastFling(); block->SetConfirmedTargetApzc(aTarget); if (gfxPrefs::TouchActionEnabled()) { block->SetAllowedTouchBehaviors(currentBehaviors); } INPQ_LOG("block %p tagged as fast-motion\n", block); } CancelAnimationsForNewBlock(block); MaybeRequestContentResponse(aTarget, block); } else { if (!mInputBlockQueue.IsEmpty()) { block = mInputBlockQueue.LastElement().get()->AsTouchBlock(); } if (!block) { NS_WARNING("Received a non-start touch event while no touch blocks active!"); return nsEventStatus_eIgnore; } INPQ_LOG("received new event in block %p\n", block); } if (aOutInputBlockId) { *aOutInputBlockId = block->GetBlockId(); } // Note that the |aTarget| the APZCTM sent us may contradict the confirmed // target set on the block. In this case the confirmed target (which may be // null) should take priority. This is equivalent to just always using the // target (confirmed or not) from the block. RefPtr<AsyncPanZoomController> target = block->GetTargetApzc(); nsEventStatus result = nsEventStatus_eIgnore; // XXX calling ArePointerEventsConsumable on |target| may be wrong here if // the target isn't confirmed and the real target turns out to be something // else. For now assume this is rare enough that it's not an issue. if (block->IsDuringFastFling()) { INPQ_LOG("dropping event due to block %p being in fast motion\n", block); result = nsEventStatus_eConsumeNoDefault; } else if (target && target->ArePointerEventsConsumable(block, aEvent.AsMultiTouchInput().mTouches.Length())) { result = nsEventStatus_eConsumeDoDefault; } if (!MaybeHandleCurrentBlock(block, aEvent)) { block->AddEvent(aEvent.AsMultiTouchInput()); } return result; }
nsEventStatus InputQueue::ReceivePanGestureInput(const RefPtr<AsyncPanZoomController>& aTarget, bool aTargetConfirmed, const PanGestureInput& aEvent, uint64_t* aOutInputBlockId) { if (aEvent.mType == PanGestureInput::PANGESTURE_MAYSTART || aEvent.mType == PanGestureInput::PANGESTURE_CANCELLED) { // Ignore these events for now. return nsEventStatus_eConsumeDoDefault; } PanGestureBlockState* block = nullptr; if (!mInputBlockQueue.IsEmpty() && aEvent.mType != PanGestureInput::PANGESTURE_START) { block = mInputBlockQueue.LastElement()->AsPanGestureBlock(); } nsEventStatus result = nsEventStatus_eConsumeDoDefault; if (!block || block->WasInterrupted()) { if (aEvent.mType != PanGestureInput::PANGESTURE_START) { // Only PANGESTURE_START events are allowed to start a new pan gesture block. return nsEventStatus_eConsumeDoDefault; } block = new PanGestureBlockState(aTarget, aTargetConfirmed, aEvent); INPQ_LOG("started new pan gesture block %p for target %p\n", block, aTarget.get()); if (aTargetConfirmed && aEvent.mRequiresContentResponseIfCannotScrollHorizontallyInStartDirection && !CanScrollTargetHorizontally(aEvent, block)) { // This event may trigger a swipe gesture, depending on what our caller // wants to do it. We need to suspend handling of this block until we get // a content response which will tell us whether to proceed or abort the // block. block->SetNeedsToWaitForContentResponse(true); // Inform our caller that we haven't scrolled in response to the event // and that a swipe can be started from this event if desired. result = nsEventStatus_eIgnore; } SweepDepletedBlocks(); mInputBlockQueue.AppendElement(block); CancelAnimationsForNewBlock(block); MaybeRequestContentResponse(aTarget, block); } else { INPQ_LOG("received new event in block %p\n", block); } if (aOutInputBlockId) { *aOutInputBlockId = block->GetBlockId(); } // Note that the |aTarget| the APZCTM sent us may contradict the confirmed // target set on the block. In this case the confirmed target (which may be // null) should take priority. This is equivalent to just always using the // target (confirmed or not) from the block, which is what // MaybeHandleCurrentBlock() does. if (!MaybeHandleCurrentBlock(block, aEvent)) { block->AddEvent(aEvent.AsPanGestureInput()); } return result; }