Bug 1289432 - Migrate remaining InputQueue code to use the new mQueuedInput structure instead of the block-based queue. r=botond
authorKartikaya Gupta <kgupta@mozilla.com>
Wed, 14 Sep 2016 07:54:37 -0400
changeset 355218 da3219c8f5b73d0c0dec0be788947fee4202608b
parent 355217 8ff1c50ceb8b129e6a75cbee08fe849a2e355062
child 355219 3644e59ed455b4433145999d795d5e10af52c524
push id6570
push userraliiev@mozilla.com
push dateMon, 14 Nov 2016 12:26:13 +0000
treeherdermozilla-beta@f455459b2ae5 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbotond
bugs1289432
milestone51.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1289432 - Migrate remaining InputQueue code to use the new mQueuedInput structure instead of the block-based queue. r=botond MozReview-Commit-ID: 41M1QGp8kcX
gfx/layers/apz/src/InputBlockState.cpp
gfx/layers/apz/src/InputBlockState.h
gfx/layers/apz/src/InputQueue.cpp
gfx/layers/apz/src/InputQueue.h
gfx/layers/apz/test/gtest/TestGestureDetector.cpp
--- a/gfx/layers/apz/src/InputBlockState.cpp
+++ b/gfx/layers/apz/src/InputBlockState.cpp
@@ -283,56 +283,16 @@ DragBlockState::DispatchEvent(const Inpu
   MouseInput mouseInput = aEvent.AsMouseInput();
   if (!mouseInput.TransformToLocal(mTransformToApzc)) {
     return;
   }
 
   GetTargetApzc()->HandleDragEvent(mouseInput, mDragMetrics);
 }
 
-void
-DragBlockState::AddEvent(const MouseInput& aEvent)
-{
-  mEvents.AppendElement(aEvent);
-}
-
-bool
-DragBlockState::HasEvents() const
-{
-  return !mEvents.IsEmpty();
-}
-
-void
-DragBlockState::DropEvents(nsTArray<UniquePtr<QueuedInput>>* aQueued)
-{
-  TBS_LOG("%p dropping %" PRIuSIZE " events\n", this, mEvents.Length());
-  MOZ_ASSERT(aQueued->Length() >= mEvents.Length());
-  for (size_t i = 0; i < mEvents.Length(); i++) {
-    MOZ_ASSERT(aQueued->ElementAt(i)->Block() == this);
-    MOZ_ASSERT(aQueued->ElementAt(i)->Input()->mInputType == mEvents[i].mInputType);
-  }
-  aQueued->RemoveElementsAt(0, mEvents.Length());
-  mEvents.Clear();
-}
-
-void
-DragBlockState::HandleEvents(nsTArray<UniquePtr<QueuedInput>>* aQueued)
-{
-  while (HasEvents()) {
-    TBS_LOG("%p returning first of %" PRIuSIZE " events\n", this, mEvents.Length());
-    MouseInput event = mEvents[0];
-    MOZ_ASSERT(aQueued->Length() > 0);
-    MOZ_ASSERT(aQueued->ElementAt(0)->Block() == this);
-    MOZ_ASSERT(aQueued->ElementAt(0)->Input()->mInputType == event.mInputType);
-    aQueued->RemoveElementAt(0);
-    mEvents.RemoveElementAt(0);
-    DispatchEvent(event);
-  }
-}
-
 bool
 DragBlockState::MustStayActive()
 {
   return !mReceivedMouseUp;
 }
 
 const char*
 DragBlockState::Type()
@@ -432,56 +392,16 @@ WheelBlockState::Update(ScrollWheelInput
 
   // Update the time of the last known good event, and reset the mouse move
   // time to null. This will reset the delays on both the general transaction
   // timeout and the mouse-move-in-frame timeout.
   mLastEventTime = aEvent.mTimeStamp;
   mLastMouseMove = TimeStamp();
 }
 
-void
-WheelBlockState::AddEvent(const ScrollWheelInput& aEvent)
-{
-  mEvents.AppendElement(aEvent);
-}
-
-bool
-WheelBlockState::HasEvents() const
-{
-  return !mEvents.IsEmpty();
-}
-
-void
-WheelBlockState::DropEvents(nsTArray<UniquePtr<QueuedInput>>* aQueued)
-{
-  TBS_LOG("%p dropping %" PRIuSIZE " events\n", this, mEvents.Length());
-  MOZ_ASSERT(aQueued->Length() >= mEvents.Length());
-  for (size_t i = 0; i < mEvents.Length(); i++) {
-    MOZ_ASSERT(aQueued->ElementAt(i)->Block() == this);
-    MOZ_ASSERT(aQueued->ElementAt(i)->Input()->mInputType == mEvents[i].mInputType);
-  }
-  aQueued->RemoveElementsAt(0, mEvents.Length());
-  mEvents.Clear();
-}
-
-void
-WheelBlockState::HandleEvents(nsTArray<UniquePtr<QueuedInput>>* aQueued)
-{
-  while (HasEvents()) {
-    TBS_LOG("%p returning first of %" PRIuSIZE " events\n", this, mEvents.Length());
-    ScrollWheelInput event = mEvents[0];
-    MOZ_ASSERT(aQueued->Length() > 0);
-    MOZ_ASSERT(aQueued->ElementAt(0)->Block() == this);
-    MOZ_ASSERT(aQueued->ElementAt(0)->Input()->mInputType == event.mInputType);
-    aQueued->RemoveElementAt(0);
-    mEvents.RemoveElementAt(0);
-    DispatchEvent(event);
-  }
-}
-
 bool
 WheelBlockState::MustStayActive()
 {
   return !mTransactionEnded;
 }
 
 const char*
 WheelBlockState::Type()
@@ -652,56 +572,16 @@ PanGestureBlockState::SetConfirmedTarget
       apzc = scrollableApzc;
     }
   }
 
   InputBlockState::SetConfirmedTargetApzc(apzc, aState, aFirstInput);
   return true;
 }
 
-void
-PanGestureBlockState::AddEvent(const PanGestureInput& aEvent)
-{
-  mEvents.AppendElement(aEvent);
-}
-
-bool
-PanGestureBlockState::HasEvents() const
-{
-  return !mEvents.IsEmpty();
-}
-
-void
-PanGestureBlockState::DropEvents(nsTArray<UniquePtr<QueuedInput>>* aQueued)
-{
-  TBS_LOG("%p dropping %" PRIuSIZE " events\n", this, mEvents.Length());
-  MOZ_ASSERT(aQueued->Length() >= mEvents.Length());
-  for (size_t i = 0; i < mEvents.Length(); i++) {
-    MOZ_ASSERT(aQueued->ElementAt(i)->Block() == this);
-    MOZ_ASSERT(aQueued->ElementAt(i)->Input()->mInputType == mEvents[i].mInputType);
-  }
-  aQueued->RemoveElementsAt(0, mEvents.Length());
-  mEvents.Clear();
-}
-
-void
-PanGestureBlockState::HandleEvents(nsTArray<UniquePtr<QueuedInput>>* aQueued)
-{
-  while (HasEvents()) {
-    TBS_LOG("%p returning first of %" PRIuSIZE " events\n", this, mEvents.Length());
-    PanGestureInput event = mEvents[0];
-    MOZ_ASSERT(aQueued->Length() > 0);
-    MOZ_ASSERT(aQueued->ElementAt(0)->Block() == this);
-    MOZ_ASSERT(aQueued->ElementAt(0)->Input()->mInputType == event.mInputType);
-    aQueued->RemoveElementAt(0);
-    mEvents.RemoveElementAt(0);
-    DispatchEvent(event);
-  }
-}
-
 bool
 PanGestureBlockState::MustStayActive()
 {
   return !mInterrupted;
 }
 
 const char*
 PanGestureBlockState::Type()
@@ -851,69 +731,28 @@ TouchBlockState::SetSingleTapOccurred()
 
 bool
 TouchBlockState::SingleTapOccurred() const
 {
   return mSingleTapOccurred;
 }
 
 bool
-TouchBlockState::HasEvents() const
-{
-  return !mEvents.IsEmpty();
-}
-
-void
-TouchBlockState::AddEvent(const MultiTouchInput& aEvent)
-{
-  TBS_LOG("%p adding event of type %d\n", this, aEvent.mType);
-  mEvents.AppendElement(aEvent);
-}
-
-bool
 TouchBlockState::MustStayActive()
 {
   return true;
 }
 
 const char*
 TouchBlockState::Type()
 {
   return "touch";
 }
 
 void
-TouchBlockState::DropEvents(nsTArray<UniquePtr<QueuedInput>>* aQueued)
-{
-  TBS_LOG("%p dropping %" PRIuSIZE " events\n", this, mEvents.Length());
-  MOZ_ASSERT(aQueued->Length() >= mEvents.Length());
-  for (size_t i = 0; i < mEvents.Length(); i++) {
-    MOZ_ASSERT(aQueued->ElementAt(i)->Block() == this);
-    MOZ_ASSERT(aQueued->ElementAt(i)->Input()->mInputType == mEvents[i].mInputType);
-  }
-  aQueued->RemoveElementsAt(0, mEvents.Length());
-  mEvents.Clear();
-}
-
-void
-TouchBlockState::HandleEvents(nsTArray<UniquePtr<QueuedInput>>* aQueued)
-{
-  while (HasEvents()) {
-    TBS_LOG("%p returning first of %" PRIuSIZE " events\n", this, mEvents.Length());
-    MultiTouchInput event = mEvents[0];
-    MOZ_ASSERT(aQueued->Length() > 0);
-    MOZ_ASSERT(aQueued->ElementAt(0)->Block() == this);
-    MOZ_ASSERT(aQueued->ElementAt(0)->Input()->mInputType == event.mInputType);
-    aQueued->RemoveElementAt(0);
-    mEvents.RemoveElementAt(0);
-    DispatchEvent(event);
-  }
-}
-
-void
 TouchBlockState::DispatchEvent(const InputData& aEvent) const
 {
   MOZ_ASSERT(aEvent.mInputType == MULTITOUCH_INPUT);
   mTouchCounter.Update(aEvent.AsMultiTouchInput());
   CancelableBlockState::DispatchEvent(aEvent);
 }
 
 bool
--- a/gfx/layers/apz/src/InputBlockState.h
+++ b/gfx/layers/apz/src/InputBlockState.h
@@ -179,32 +179,16 @@ public:
 
   /**
    * @return true iff this block has received all the information needed
    *         to properly dispatch the events in the block.
    */
   virtual bool IsReadyForHandling() const;
 
   /**
-   * Returns whether or not this block has pending events.
-   */
-  virtual bool HasEvents() const = 0;
-
-  /**
-   * Throw away all the events in this input block.
-   */
-  virtual void DropEvents(nsTArray<UniquePtr<QueuedInput>>* aQueued) = 0;
-
-  /**
-   * Process all events using this input block's target apzc, leaving this
-   * block depleted. This input block's apzc must not be nullptr.
-   */
-  virtual void HandleEvents(nsTArray<UniquePtr<QueuedInput>>* aQueued) = 0;
-
-  /**
    * Return true if this input block must stay active if it would otherwise
    * be removed as the last item in the pending queue.
    */
   virtual bool MustStayActive() = 0;
 
   /**
    * Return a descriptive name for the block kind.
    */
@@ -223,27 +207,22 @@ private:
 class WheelBlockState : public CancelableBlockState
 {
 public:
   WheelBlockState(const RefPtr<AsyncPanZoomController>& aTargetApzc,
                   bool aTargetConfirmed,
                   const ScrollWheelInput& aEvent);
 
   bool SetContentResponse(bool aPreventDefault) override;
-  bool HasEvents() const override;
-  void DropEvents(nsTArray<UniquePtr<QueuedInput>>* aQueued) override;
-  void HandleEvents(nsTArray<UniquePtr<QueuedInput>>* aQueued) override;
   bool MustStayActive() override;
   const char* Type() override;
   bool SetConfirmedTargetApzc(const RefPtr<AsyncPanZoomController>& aTargetApzc,
                               TargetConfirmationState aState,
                               InputData* aFirstInput) override;
 
-  void AddEvent(const ScrollWheelInput& aEvent);
-
   WheelBlockState *AsWheelBlock() override {
     return this;
   }
 
   /**
    * Determine whether this wheel block is accepting new events.
    */
   bool ShouldAcceptNewEvent() const;
@@ -292,53 +271,46 @@ public:
    * Update the wheel transaction state for a new event.
    */
   void Update(ScrollWheelInput& aEvent);
 
 protected:
   void UpdateTargetApzc(const RefPtr<AsyncPanZoomController>& aTargetApzc) override;
 
 private:
-  nsTArray<ScrollWheelInput> mEvents;
   TimeStamp mLastEventTime;
   TimeStamp mLastMouseMove;
   uint32_t mScrollSeriesCounter;
   bool mTransactionEnded;
 };
 
 /**
  * A block of mouse events that are part of a drag
  */
 class DragBlockState : public CancelableBlockState
 {
 public:
   DragBlockState(const RefPtr<AsyncPanZoomController>& aTargetApzc,
                  bool aTargetConfirmed,
                  const MouseInput& aEvent);
 
-  bool HasEvents() const override;
-  void DropEvents(nsTArray<UniquePtr<QueuedInput>>* aQueued) override;
-  void HandleEvents(nsTArray<UniquePtr<QueuedInput>>* aQueued) override;
   bool MustStayActive() override;
   const char* Type() override;
 
   bool HasReceivedMouseUp();
   void MarkMouseUpReceived();
 
-  void AddEvent(const MouseInput& aEvent);
-
   DragBlockState *AsDragBlock() override {
     return this;
   }
 
   void SetDragMetrics(const AsyncDragMetrics& aDragMetrics);
 
   void DispatchEvent(const InputData& aEvent) const override;
 private:
-  nsTArray<MouseInput> mEvents;
   AsyncDragMetrics mDragMetrics;
   bool mReceivedMouseUp;
 };
 
 /**
  * A single block of pan gesture events.
  */
 class PanGestureBlockState : public CancelableBlockState
@@ -346,42 +318,36 @@ class PanGestureBlockState : public Canc
 public:
   PanGestureBlockState(const RefPtr<AsyncPanZoomController>& aTargetApzc,
                        bool aTargetConfirmed,
                        const PanGestureInput& aEvent);
 
   bool SetContentResponse(bool aPreventDefault) override;
   bool HasReceivedAllContentNotifications() const override;
   bool IsReadyForHandling() const override;
-  bool HasEvents() const override;
-  void DropEvents(nsTArray<UniquePtr<QueuedInput>>* aQueued) override;
-  void HandleEvents(nsTArray<UniquePtr<QueuedInput>>* aQueued) override;
   bool MustStayActive() override;
   const char* Type() override;
   bool SetConfirmedTargetApzc(const RefPtr<AsyncPanZoomController>& aTargetApzc,
                               TargetConfirmationState aState,
                               InputData* aFirstInput) override;
 
-  void AddEvent(const PanGestureInput& aEvent);
-
   PanGestureBlockState *AsPanGestureBlock() override {
     return this;
   }
 
   /**
    * @return Whether or not overscrolling is prevented for this block.
    */
   bool AllowScrollHandoff() const;
 
   bool WasInterrupted() const { return mInterrupted; }
 
   void SetNeedsToWaitForContentResponse(bool aWaitForContentResponse);
 
 private:
-  nsTArray<PanGestureInput> mEvents;
   bool mInterrupted;
   bool mWaitingForContentResponse;
 };
 
 /**
  * This class represents a single touch block. A touch block is
  * a set of touch events that can be cancelled by web content via
  * touch event listeners.
@@ -458,21 +424,16 @@ public:
    */
   void SetSingleTapOccurred();
   /**
    * @return true iff the single-tap-occurred flag is set on this block.
    */
   bool SingleTapOccurred() const;
 
   /**
-   * Add a new touch event to the queue of events in this input block.
-   */
-  void AddEvent(const MultiTouchInput& aEvent);
-
-  /**
    * @return false iff touch-action is enabled and the allowed touch behaviors for
    *         this touch block do not allow pinch-zooming.
    */
   bool TouchActionAllowsPinchZoom() const;
   /**
    * @return false iff touch-action is enabled and the allowed touch behaviors for
    *         this touch block do not allow double-tap zooming.
    */
@@ -497,31 +458,27 @@ public:
   bool UpdateSlopState(const MultiTouchInput& aInput,
                        bool aApzcCanConsumeEvents);
 
   /**
    * Returns the number of touch points currently active.
    */
   uint32_t GetActiveTouchCount() const;
 
-  bool HasEvents() const override;
-  void DropEvents(nsTArray<UniquePtr<QueuedInput>>* aQueued) override;
-  void HandleEvents(nsTArray<UniquePtr<QueuedInput>>* aQueued) override;
   void DispatchEvent(const InputData& aEvent) const override;
   bool MustStayActive() override;
   const char* Type() override;
 
 private:
   nsTArray<TouchBehaviorFlags> mAllowedTouchBehaviors;
   bool mAllowedTouchBehaviorSet;
   bool mDuringFastFling;
   bool mSingleTapOccurred;
   bool mInSlop;
   ScreenIntPoint mSlopOrigin;
-  nsTArray<MultiTouchInput> mEvents;
   // A reference to the InputQueue's touch counter
   TouchCounter& mTouchCounter;
 };
 
 } // namespace layers
 } // namespace mozilla
 
 #endif // mozilla_layers_InputBlockState_h
--- a/gfx/layers/apz/src/InputQueue.cpp
+++ b/gfx/layers/apz/src/InputQueue.cpp
@@ -20,17 +20,16 @@
 namespace mozilla {
 namespace layers {
 
 InputQueue::InputQueue()
 {
 }
 
 InputQueue::~InputQueue() {
-  mInputBlockQueue.Clear();
   mQueuedInputs.Clear();
 }
 
 nsEventStatus
 InputQueue::ReceiveInputEvent(const RefPtr<AsyncPanZoomController>& aTarget,
                               bool aTargetConfirmed,
                               const InputData& aEvent,
                               uint64_t* aOutInputBlockId) {
@@ -149,17 +148,16 @@ InputQueue::ReceiveTouchInput(const RefP
       result = nsEventStatus_eConsumeNoDefault;
     } else {
       result = nsEventStatus_eConsumeDoDefault;
     }
   } else if (block->UpdateSlopState(aEvent.AsMultiTouchInput(), false)) {
     INPQ_LOG("dropping event due to block %p being in mini-slop\n", block);
     result = nsEventStatus_eConsumeNoDefault;
   }
-  block->AddEvent(aEvent.AsMultiTouchInput());
   mQueuedInputs.AppendElement(MakeUnique<QueuedInput>(aEvent.AsMultiTouchInput(), *block));
   ProcessInputBlocks();
   return result;
 }
 
 nsEventStatus
 InputQueue::ReceiveMouseInput(const RefPtr<AsyncPanZoomController>& aTarget,
                               bool aTargetConfirmed,
@@ -192,29 +190,26 @@ InputQueue::ReceiveMouseInput(const RefP
 
   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());
 
-    SweepDepletedBlocks();
-    mInputBlockQueue.AppendElement(block);
     mActiveDragBlock = block;
 
     CancelAnimationsForNewBlock(block);
     MaybeRequestContentResponse(aTarget, block);
   }
 
   if (aOutInputBlockId) {
     *aOutInputBlockId = block->GetBlockId();
   }
 
-  block->AddEvent(aEvent.AsMouseInput());
   mQueuedInputs.AppendElement(MakeUnique<QueuedInput>(aEvent.AsMouseInput(), *block));
   ProcessInputBlocks();
 
   if (DragTracker::EndsDrag(aEvent)) {
     block->MarkMouseUpReceived();
   }
 
   // The event is part of a drag block and could potentially cause
@@ -239,18 +234,16 @@ InputQueue::ReceiveScrollWheelInput(cons
 
   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());
 
-    SweepDepletedBlocks();
-    mInputBlockQueue.AppendElement(block);
     mActiveWheelBlock = block;
 
     CancelAnimationsForNewBlock(block);
     MaybeRequestContentResponse(aTarget, block);
   } else {
     INPQ_LOG("received new event in block %p\n", block);
   }
 
@@ -262,17 +255,16 @@ InputQueue::ReceiveScrollWheelInput(cons
   ScrollWheelInput event(aEvent);
   block->Update(event);
 
   // 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
   // ProcessInputBlocks() does.
-  block->AddEvent(event);
   mQueuedInputs.AppendElement(MakeUnique<QueuedInput>(event, *block));
   ProcessInputBlocks();
 
   return nsEventStatus_eConsumeDoDefault;
 }
 
 static bool
 CanScrollTargetHorizontally(const PanGestureInput& aInitialEvent,
@@ -326,18 +318,16 @@ InputQueue::ReceivePanGestureInput(const
       // 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);
     mActivePanGestureBlock = block;
 
     CancelAnimationsForNewBlock(block);
     MaybeRequestContentResponse(aTarget, block);
   } else {
     INPQ_LOG("received new event in block %p\n", block);
   }
 
@@ -345,17 +335,16 @@ InputQueue::ReceivePanGestureInput(const
     *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
   // ProcessInputBlocks() does.
-  block->AddEvent(event.AsPanGestureInput());
   mQueuedInputs.AppendElement(MakeUnique<QueuedInput>(event.AsPanGestureInput(), *block));
   ProcessInputBlocks();
 
   return result;
 }
 
 void
 InputQueue::CancelAnimationsForNewBlock(CancelableBlockState* aBlock)
@@ -408,66 +397,41 @@ InputQueue::InjectNewTouchBlock(AsyncPan
     /* 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);
   return block->GetBlockId();
 }
 
-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);
-    ClearActiveBlock(block);
-    mInputBlockQueue.RemoveElementAt(0);
-  }
-}
-
 TouchBlockState*
 InputQueue::StartNewTouchBlock(const RefPtr<AsyncPanZoomController>& aTarget,
                                bool aTargetConfirmed,
                                bool aCopyPropertiesFromCurrent)
 {
   TouchBlockState* newBlock = new TouchBlockState(aTarget, aTargetConfirmed,
       mTouchCounter);
   if (aCopyPropertiesFromCurrent) {
     // We should never enter here without a current touch block, because this
     // codepath is invoked from the OnLongPress handler in
     // AsyncPanZoomController, which should bail out if there is no current
     // touch block.
     MOZ_ASSERT(GetCurrentTouchBlock());
     newBlock->CopyPropertiesFrom(*GetCurrentTouchBlock());
   }
 
-  SweepDepletedBlocks();
-
-  // Add the new block to the queue.
-  mInputBlockQueue.AppendElement(newBlock);
   mActiveTouchBlock = newBlock;
   return newBlock;
 }
 
 CancelableBlockState*
 InputQueue::GetCurrentBlock() const
 {
   APZThreadUtils::AssertOnControllerThread();
-
-  if (mInputBlockQueue.IsEmpty()) {
-    return nullptr;
-  }
-  return mInputBlockQueue[0].get();
+  return mQueuedInputs.IsEmpty() ? nullptr : mQueuedInputs[0]->Block();
 }
 
 TouchBlockState*
 InputQueue::GetCurrentTouchBlock() const
 {
   CancelableBlockState* block = GetCurrentBlock();
   return block ? block->AsTouchBlock() : mActiveTouchBlock.get();
 }
@@ -501,19 +465,19 @@ InputQueue::GetCurrentWheelTransaction()
     return nullptr;
   }
   return block;
 }
 
 bool
 InputQueue::HasReadyTouchBlock() const
 {
-  return !mInputBlockQueue.IsEmpty() &&
-         mInputBlockQueue[0]->AsTouchBlock() &&
-         mInputBlockQueue[0]->IsReadyForHandling();
+  return !mQueuedInputs.IsEmpty() &&
+      mQueuedInputs[0]->Block()->AsTouchBlock() &&
+      mQueuedInputs[0]->Block()->IsReadyForHandling();
 }
 
 bool
 InputQueue::AllowScrollHandoff() const
 {
   if (GetCurrentWheelBlock()) {
     return GetCurrentWheelBlock()->AllowScrollHandoff();
   }
@@ -567,17 +531,16 @@ InputQueue::FindBlockForId(const uint64_
     block = mActiveWheelBlock.get();
   } else if (mActiveDragBlock && mActiveDragBlock->GetBlockId() == aInputBlockId) {
     block = mActiveDragBlock.get();
   } else if (mActivePanGestureBlock && mActivePanGestureBlock->GetBlockId() == aInputBlockId) {
     block = mActivePanGestureBlock.get();
   }
   // Since we didn't encounter this block while iterating through mQueuedInputs,
   // it must have no events associated with it at the moment.
-  MOZ_ASSERT(!block || !block->HasEvents());
   if (aOutFirstInput) {
     *aOutFirstInput = nullptr;
   }
   return block;
 }
 
 void
 InputQueue::MainThreadTimeout(const uint64_t& aInputBlockId) {
@@ -678,87 +641,87 @@ InputQueue::SetAllowedTouchBehavior(uint
     ProcessInputBlocks();
   }
 }
 
 void
 InputQueue::ProcessInputBlocks() {
   APZThreadUtils::AssertOnControllerThread();
 
-  do {
-    CancelableBlockState* curBlock = GetCurrentBlock();
-    if (!curBlock || !curBlock->IsReadyForHandling()) {
+  while (!mQueuedInputs.IsEmpty()) {
+    CancelableBlockState* curBlock = mQueuedInputs[0]->Block();
+    if (!curBlock->IsReadyForHandling()) {
       break;
     }
 
-    INPQ_LOG("processing input block %p; preventDefault %d target %p\n",
+    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) {
-      curBlock->DropEvents(&mQueuedInputs);
-    } else if (curBlock->IsDefaultPrevented()) {
-      curBlock->DropEvents(&mQueuedInputs);
-      if (curBlock->AsTouchBlock()) {
-        target->ResetTouchInputState();
+    if (target) {
+      if (curBlock->IsDefaultPrevented()) {
+        if (curBlock->AsTouchBlock()) {
+          target->ResetTouchInputState();
+        }
+      } else {
+        UpdateActiveApzc(target);
+        curBlock->DispatchEvent(*(mQueuedInputs[0]->Input()));
       }
-    } else {
-      UpdateActiveApzc(curBlock->GetTargetApzc());
-      curBlock->HandleEvents(&mQueuedInputs);
     }
-    MOZ_ASSERT(!curBlock->HasEvents());
+    mQueuedInputs.RemoveElementAt(0);
+  }
 
-    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);
-    ClearActiveBlock(curBlock);
-    mInputBlockQueue.RemoveElementAt(0);
-  } while (!mInputBlockQueue.IsEmpty());
+  if (CanDiscardBlock(mActiveTouchBlock)) {
+    mActiveTouchBlock = nullptr;
+  }
+  if (CanDiscardBlock(mActiveWheelBlock)) {
+    mActiveWheelBlock = nullptr;
+  }
+  if (CanDiscardBlock(mActiveDragBlock)) {
+    mActiveDragBlock = nullptr;
+  }
+  if (CanDiscardBlock(mActivePanGestureBlock)) {
+    mActivePanGestureBlock = nullptr;
+  }
 }
 
-void
-InputQueue::ClearActiveBlock(CancelableBlockState* aBlock)
+bool
+InputQueue::CanDiscardBlock(CancelableBlockState* aBlock)
 {
-  // XXX: This function will be removed in a later patch
-  if (mActiveTouchBlock.get() == aBlock) {
-    mActiveTouchBlock = nullptr;
-  } else if (mActiveWheelBlock.get() == aBlock) {
-    mActiveWheelBlock = nullptr;
-  } else if (mActiveDragBlock.get() == aBlock) {
-    mActiveDragBlock = nullptr;
-  } else if (mActivePanGestureBlock.get() == aBlock) {
-    mActivePanGestureBlock = nullptr;
+  if (!aBlock ||
+      !aBlock->IsReadyForHandling() ||
+      aBlock->MustStayActive()) {
+    return false;
   }
+  InputData* firstInput = nullptr;
+  FindBlockForId(aBlock->GetBlockId(), &firstInput);
+  if (firstInput) {
+    // The block has at least one input event still in the queue, so it's
+    // not depleted
+    return false;
+  }
+  return true;
 }
 
 void
 InputQueue::UpdateActiveApzc(const RefPtr<AsyncPanZoomController>& aNewActive) {
   if (mLastActiveApzc && mLastActiveApzc != aNewActive
       && mTouchCounter.GetActiveTouchCount() > 0) {
     mLastActiveApzc->ResetTouchInputState();
   }
   mLastActiveApzc = aNewActive;
 }
 
 void
 InputQueue::Clear()
 {
   APZThreadUtils::AssertOnControllerThread();
 
-  mInputBlockQueue.Clear();
   mQueuedInputs.Clear();
   mActiveTouchBlock = nullptr;
   mActiveWheelBlock = nullptr;
   mActiveDragBlock = nullptr;
   mActivePanGestureBlock = nullptr;
   mLastActiveApzc = nullptr;
 }
 
--- a/gfx/layers/apz/src/InputQueue.h
+++ b/gfx/layers/apz/src/InputQueue.h
@@ -163,42 +163,34 @@ private:
                                         const ScrollWheelInput& aEvent,
                                         uint64_t* aOutInputBlockId);
   nsEventStatus ReceivePanGestureInput(const RefPtr<AsyncPanZoomController>& aTarget,
                                         bool aTargetConfirmed,
                                         const PanGestureInput& aEvent,
                                         uint64_t* aOutInputBlockId);
 
   /**
-   * Remove any blocks that are inactive - not ready, and having no events.
-   */
-  void SweepDepletedBlocks();
-
-  /**
    * Helper function that searches mQueuedInputs for the first block matching
    * the given id, and returns it. If |aOutFirstInput| is non-null, it is
    * populated with a pointer to the first input in mQueuedInputs that
    * corresponds to the block, or null if no such input was found. Note that
    * even if there are no inputs in mQueuedInputs, this function can return
    * non-null if the block id provided matches one of the depleted-but-still-
    * active blocks (mActiveTouchBlock, mActiveWheelBlock, etc.).
    */
   CancelableBlockState* FindBlockForId(const uint64_t& aInputBlockId,
                                        InputData** aOutFirstInput);
   void ScheduleMainThreadTimeout(const RefPtr<AsyncPanZoomController>& aTarget,
                                  CancelableBlockState* aBlock);
   void MainThreadTimeout(const uint64_t& aInputBlockId);
   void ProcessInputBlocks();
-  void ClearActiveBlock(CancelableBlockState* aBlock);
+  bool CanDiscardBlock(CancelableBlockState* aBlock);
   void UpdateActiveApzc(const RefPtr<AsyncPanZoomController>& aNewActive);
 
 private:
-  // The queue of input blocks that have not yet been fully processed.
-  // This member must only be accessed on the controller/UI thread.
-  nsTArray<RefPtr<CancelableBlockState>> mInputBlockQueue;
   // The queue of input events that have not yet been fully processed.
   // This member must only be accessed on the controller/UI thread.
   nsTArray<UniquePtr<QueuedInput>> mQueuedInputs;
 
   // These are the most recently created blocks of each input type. They are
   // "active" in the sense that new inputs of that type are associated with
   // them. Note that these pointers may be null if no inputs of the type have
   // arrived, or if the inputs for the type formed a complete block that was
--- a/gfx/layers/apz/test/gtest/TestGestureDetector.cpp
+++ b/gfx/layers/apz/test/gtest/TestGestureDetector.cpp
@@ -592,20 +592,21 @@ TEST_F(APZCGestureDetectorTester, TapFol
   mti.mTouches.AppendElement(SingleTouchData(inputId, ParentLayerPoint(20, 20), ScreenSize(0, 0), 0, 0));
   mti.mTouches.AppendElement(SingleTouchData(inputId + 1, ParentLayerPoint(10, 10), ScreenSize(0, 0), 0, 0));
   apzc->ReceiveInputEvent(mti, nullptr);
 
   apzc->AssertStateIsReset();
 }
 
 TEST_F(APZCGestureDetectorTester, LongPressInterruptedByWheel) {
-  // Since the wheel block interrupted the long-press, we don't expect
-  // any long-press notifications. However, this also shouldn't crash, which
-  // is what it used to do.
-  EXPECT_CALL(*mcc, HandleTap(TapType::eLongTap, _, _, _, _)).Times(0);
+  // Since we try to allow concurrent input blocks of different types to
+  // co-exist, the wheel block shouldn't interrupt the long-press detection.
+  // But more importantly, this shouldn't crash, which is what it did at one
+  // point in time.
+  EXPECT_CALL(*mcc, HandleTap(TapType::eLongTap, _, _, _, _)).Times(1);
 
   uint64_t touchBlockId = 0;
   uint64_t wheelBlockId = 0;
   nsEventStatus status = TouchDown(apzc, ScreenIntPoint(10, 10), mcc->Time(), &touchBlockId);
   if (gfxPrefs::TouchActionEnabled() && status != nsEventStatus_eConsumeNoDefault) {
     SetDefaultAllowedTouchBehavior(apzc, touchBlockId);
   }
   mcc->AdvanceByMillis(10);