Bug 1289432 - Migrate remaining InputQueue code to use the new mQueuedInput structure instead of the block-based queue. r?botond draft
authorKartikaya Gupta <kgupta@mozilla.com>
Mon, 12 Sep 2016 22:42:33 -0400
changeset 412863 4af799e8d8ce68a45c02997f448b506a6682cb4e
parent 412862 30f3663070cb0998b904d167acfb0f3377cfb7e6
child 412864 9d074607e285fe42a00b40fada0bca522b3fe4f2
push id29274
push userkgupta@mozilla.com
push dateTue, 13 Sep 2016 02:44:31 +0000
reviewersbotond
bugs1289432
milestone51.0a1
Bug 1289432 - Migrate remaining InputQueue code to use the new mQueuedInput structure instead of the block-based queue. r?botond MozReview-Commit-ID: BG96ia5PiI5
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);