bool InputQueue::AllowScrollHandoff() const { MOZ_ASSERT(CurrentBlock()); if (CurrentBlock()->AsWheelBlock()) { return CurrentBlock()->AsWheelBlock()->AllowScrollHandoff(); } if (CurrentBlock()->AsPanGestureBlock()) { return CurrentBlock()->AsPanGestureBlock()->AllowScrollHandoff(); } return true; }
int64 MediaBlockMapReader::ReadFrames(void* buffer, int64 frameCount) { MediaBlock* block = CurrentBlock(); int64 remaining = frameCount; int64 readSize = 0; int64 totalRead = 0; while (remaining != 0) { if (block == NULL || fMap->CountBlocks()-1 > fCurrentIndex) block = NextBlock(); else return -1; int64 toRead = block->CountFrames(); if (toRead < remaining) { readSize = toRead; remaining -= toRead; } else { readSize = remaining; remaining -= readSize; } totalRead += block->ReadFrames(buffer, readSize); buffer += readSize; } return totalRead; }
PanGestureBlockState* InputQueue::CurrentPanGestureBlock() const { PanGestureBlockState* block = CurrentBlock()->AsPanGestureBlock(); MOZ_ASSERT(block); return block; }
WheelBlockState* InputQueue::CurrentWheelBlock() const { WheelBlockState* block = CurrentBlock()->AsWheelBlock(); MOZ_ASSERT(block); return block; }
TouchBlockState* InputQueue::CurrentTouchBlock() const { TouchBlockState* block = CurrentBlock()->AsTouchBlock(); MOZ_ASSERT(block); return block; }
WheelBlockState* InputQueue::GetCurrentWheelTransaction() const { if (mInputBlockQueue.IsEmpty()) { return nullptr; } WheelBlockState* block = CurrentBlock()->AsWheelBlock(); if (!block || !block->InTransaction()) { return nullptr; } return block; }
void InputQueue::CancelAnimationsForNewBlock(CancelableBlockState* aBlock) { // We want to cancel animations here as soon as possible (i.e. without waiting for // content responses) because a finger has gone down and we don't want to keep moving // the content under the finger. However, to prevent "future" touchstart events from // interfering with "past" animations (i.e. from a previous touch block that is still // being processed) we only do this animation-cancellation if there are no older // touch blocks still in the queue. if (aBlock == CurrentBlock()) { aBlock->GetOverscrollHandoffChain()->CancelAnimations(ExcludeOverscroll); } }
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; }
int64 MediaBlockMapWriter::WriteFrames(void* buffer, int64 frameCount) { MediaBlock* block = CurrentBlock(); int64 remaining = frameCount; int64 totalWrite = 0; int64 offset = 0; while (remaining > 0) { if (block == NULL || block->CurrentFrame() == MEDIA_BLOCK_MAX_FRAMES) { block = NextBlock(); if (block == NULL) block = RequestBlock(); } int64 writeSize = 0; int64 freeSize = MEDIA_BLOCK_MAX_FRAMES-block->CurrentFrame(); printf("Got a block %d available space from block %" B_PRId64 " we want to write %" B_PRId64 "\n", (int)fCurrentIndex, freeSize, remaining); if (freeSize < remaining) { writeSize = freeSize; remaining -= freeSize; } else { writeSize = remaining; remaining -= writeSize; } totalWrite += block->WriteFrames(buffer+offset, writeSize); offset += writeSize; block->SetFlushed(false); printf("Data written %" B_PRId64 "available %" B_PRId64 "\n", writeSize, MEDIA_BLOCK_MAX_FRAMES - block->CurrentFrame()); } return totalWrite; }
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()); }
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; }