Bug 1289432 - Start populating the mQueuedInput array with queued input objects. r?botond draft
authorKartikaya Gupta <kgupta@mozilla.com>
Mon, 12 Sep 2016 22:42:17 -0400
changeset 412856 3f2e93c1c88709d499e2db8c7bf93118f12e6581
parent 412855 5de5a38ecb530c20dc50465eb304396998c2d42e
child 412857 494cbf7104e52726d47d15e92cd04f2d57b7523d
push id29274
push userkgupta@mozilla.com
push dateTue, 13 Sep 2016 02:44:31 +0000
reviewersbotond
bugs1289432
milestone51.0a1
Bug 1289432 - Start populating the mQueuedInput array with queued input objects. r?botond Most of the changes to InputBlockState.* are temporary and will be removed in a future patch, once the transition to using mQueuedInputs is complete. However, the code is useful as an intermediate step to verify that mQueuedInputs is maintaining events in the same order and with the same lifetime as the old block- based queue. MozReview-Commit-ID: J3j3JTwC1TV
gfx/layers/apz/src/InputBlockState.cpp
gfx/layers/apz/src/InputBlockState.h
gfx/layers/apz/src/InputQueue.cpp
gfx/layers/apz/src/QueuedInput.cpp
gfx/layers/apz/src/QueuedInput.h
--- a/gfx/layers/apz/src/InputBlockState.cpp
+++ b/gfx/layers/apz/src/InputBlockState.cpp
@@ -8,16 +8,17 @@
 #include "AsyncPanZoomController.h"         // for AsyncPanZoomController
 #include "AsyncScrollBase.h"                // for kScrollSeriesTimeoutMs
 #include "gfxPrefs.h"                       // for gfxPrefs
 #include "mozilla/MouseEvents.h"
 #include "mozilla/SizePrintfMacros.h"       // for PRIuSIZE
 #include "mozilla/Telemetry.h"              // for Telemetry
 #include "mozilla/layers/APZCTreeManager.h" // for AllowedTouchBehavior
 #include "OverscrollHandoffState.h"
+#include "QueuedInput.h"
 
 #define TBS_LOG(...)
 // #define TBS_LOG(...) printf_stderr("TBS: " __VA_ARGS__)
 
 namespace mozilla {
 namespace layers {
 
 static uint64_t sBlockCounter = InputBlockState::NO_BLOCK_ID + 1;
@@ -302,28 +303,38 @@ DragBlockState::AddEvent(const MouseInpu
 
 bool
 DragBlockState::HasEvents() const
 {
   return !mEvents.IsEmpty();
 }
 
 void
-DragBlockState::DropEvents()
+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()
+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()
 {
@@ -441,28 +452,38 @@ WheelBlockState::AddEvent(const ScrollWh
 
 bool
 WheelBlockState::HasEvents() const
 {
   return !mEvents.IsEmpty();
 }
 
 void
-WheelBlockState::DropEvents()
+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()
+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()
 {
@@ -651,28 +672,38 @@ PanGestureBlockState::AddEvent(const Pan
 
 bool
 PanGestureBlockState::HasEvents() const
 {
   return !mEvents.IsEmpty();
 }
 
 void
-PanGestureBlockState::DropEvents()
+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()
+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()
 {
@@ -852,28 +883,38 @@ TouchBlockState::MustStayActive()
 
 const char*
 TouchBlockState::Type()
 {
   return "touch";
 }
 
 void
-TouchBlockState::DropEvents()
+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()
+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
 {
--- a/gfx/layers/apz/src/InputBlockState.h
+++ b/gfx/layers/apz/src/InputBlockState.h
@@ -192,23 +192,23 @@ public:
   /**
    * 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() = 0;
+  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() = 0;
+  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;
 
   /**
@@ -230,18 +230,18 @@ class WheelBlockState : public Cancelabl
 {
 public:
   WheelBlockState(const RefPtr<AsyncPanZoomController>& aTargetApzc,
                   bool aTargetConfirmed,
                   const ScrollWheelInput& aEvent);
 
   bool SetContentResponse(bool aPreventDefault) override;
   bool HasEvents() const override;
-  void DropEvents() override;
-  void HandleEvents() 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) override;
 
   void AddEvent(const ScrollWheelInput& aEvent);
 
   WheelBlockState *AsWheelBlock() override {
@@ -315,18 +315,18 @@ private:
 class DragBlockState : public CancelableBlockState
 {
 public:
   DragBlockState(const RefPtr<AsyncPanZoomController>& aTargetApzc,
                  bool aTargetConfirmed,
                  const MouseInput& aEvent);
 
   bool HasEvents() const override;
-  void DropEvents() override;
-  void HandleEvents() 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);
 
@@ -352,18 +352,18 @@ 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() override;
-  void HandleEvents() 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) override;
 
   void AddEvent(const PanGestureInput& aEvent);
 
   PanGestureBlockState *AsPanGestureBlock() override {
@@ -502,18 +502,18 @@ public:
                        bool aApzcCanConsumeEvents);
 
   /**
    * Returns the number of touch points currently active.
    */
   uint32_t GetActiveTouchCount() const;
 
   bool HasEvents() const override;
-  void DropEvents() override;
-  void HandleEvents() 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;
--- a/gfx/layers/apz/src/InputQueue.cpp
+++ b/gfx/layers/apz/src/InputQueue.cpp
@@ -21,16 +21,17 @@ 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) {
   APZThreadUtils::AssertOnControllerThread();
@@ -169,16 +170,17 @@ InputQueue::ReceiveTouchInput(const RefP
       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;
   }
   if (!MaybeHandleCurrentBlock(block, aEvent)) {
     block->AddEvent(aEvent.AsMultiTouchInput());
+    mQueuedInputs.AppendElement(MakeUnique<QueuedInput>(aEvent.AsMultiTouchInput(), *block));
   }
   return result;
 }
 
 nsEventStatus
 InputQueue::ReceiveMouseInput(const RefPtr<AsyncPanZoomController>& aTarget,
                               bool aTargetConfirmed,
                               const MouseInput& aEvent,
@@ -228,16 +230,17 @@ InputQueue::ReceiveMouseInput(const RefP
   }
 
   if (aOutInputBlockId) {
     *aOutInputBlockId = block->GetBlockId();
   }
 
   if (!MaybeHandleCurrentBlock(block, aEvent)) {
     block->AddEvent(aEvent.AsMouseInput());
+    mQueuedInputs.AppendElement(MakeUnique<QueuedInput>(aEvent.AsMouseInput(), *block));
   }
 
   if (DragTracker::EndsDrag(aEvent)) {
     block->MarkMouseUpReceived();
   }
 
   // The event is part of a drag block and could potentially cause
   // scrolling, so return DoDefault.
@@ -290,16 +293,17 @@ InputQueue::ReceiveScrollWheelInput(cons
 
   // 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, event)) {
     block->AddEvent(event);
+    mQueuedInputs.AppendElement(MakeUnique<QueuedInput>(event, *block));
   }
 
   return nsEventStatus_eConsumeDoDefault;
 }
 
 static bool
 CanScrollTargetHorizontally(const PanGestureInput& aInitialEvent,
                             PanGestureBlockState* aBlock)
@@ -374,16 +378,17 @@ InputQueue::ReceivePanGestureInput(const
 
   // 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, event)) {
     block->AddEvent(event.AsPanGestureInput());
+    mQueuedInputs.AppendElement(MakeUnique<QueuedInput>(event.AsPanGestureInput(), *block));
   }
 
   return result;
 }
 
 void
 InputQueue::CancelAnimationsForNewBlock(CancelableBlockState* aBlock)
 {
@@ -697,25 +702,25 @@ InputQueue::ProcessInputBlocks() {
 
     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();
+      curBlock->DropEvents(&mQueuedInputs);
     } else if (curBlock->IsDefaultPrevented()) {
-      curBlock->DropEvents();
+      curBlock->DropEvents(&mQueuedInputs);
       if (curBlock->AsTouchBlock()) {
         target->ResetTouchInputState();
       }
     } else {
       UpdateActiveApzc(curBlock->GetTargetApzc());
-      curBlock->HandleEvents();
+      curBlock->HandleEvents(&mQueuedInputs);
     }
     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.
@@ -755,16 +760,17 @@ InputQueue::UpdateActiveApzc(const RefPt
 }
 
 void
 InputQueue::Clear()
 {
   APZThreadUtils::AssertOnControllerThread();
 
   mInputBlockQueue.Clear();
+  mQueuedInputs.Clear();
   mActiveTouchBlock = nullptr;
   mActiveWheelBlock = nullptr;
   mActiveDragBlock = nullptr;
   mActivePanGestureBlock = nullptr;
   mLastActiveApzc = nullptr;
 }
 
 } // namespace layers
--- a/gfx/layers/apz/src/QueuedInput.cpp
+++ b/gfx/layers/apz/src/QueuedInput.cpp
@@ -33,10 +33,22 @@ QueuedInput::QueuedInput(const MouseInpu
 }
 
 QueuedInput::QueuedInput(const PanGestureInput& aInput, PanGestureBlockState& aBlock)
   : mInput(MakeUnique<PanGestureInput>(aInput))
   , mBlock(&aBlock)
 {
 }
 
+InputData*
+QueuedInput::Input()
+{
+  return mInput.get();
+}
+
+CancelableBlockState*
+QueuedInput::Block()
+{
+  return mBlock.get();
+}
+
 } // namespace layers
 } // namespace mozilla
--- a/gfx/layers/apz/src/QueuedInput.h
+++ b/gfx/layers/apz/src/QueuedInput.h
@@ -34,16 +34,19 @@ class PanGestureBlockState;
 class QueuedInput
 {
 public:
   QueuedInput(const MultiTouchInput& aInput, TouchBlockState& aBlock);
   QueuedInput(const ScrollWheelInput& aInput, WheelBlockState& aBlock);
   QueuedInput(const MouseInput& aInput, DragBlockState& aBlock);
   QueuedInput(const PanGestureInput& aInput, PanGestureBlockState& aBlock);
 
+  InputData* Input();
+  CancelableBlockState* Block();
+
 private:
   // A copy of the input event that is provided to the constructor. This must
   // be non-null, and is owned by this QueuedInput instance (hence the
   // UniquePtr).
   UniquePtr<InputData> mInput;
   // A pointer to the block that the input event is associated with. This must
   // be non-null.
   RefPtr<CancelableBlockState> mBlock;