Bug 1292904 Part 3 - Use only caret image for touch area if event is a mouse type. r=mtseng
authorTing-Yu Lin <tlin@mozilla.com>
Sun, 14 Aug 2016 21:39:30 +0800
changeset 309944 0552273a68a16a14ff4f7c0b6400f6f11fd8cf6e
parent 309943 ce482fb4d62b16015f225798f6a58ac3573533b1
child 309945 e6e5569551be46e7200a5b33afdd22e48474ee34
push id30575
push userryanvm@gmail.com
push dateFri, 19 Aug 2016 13:46:06 +0000
treeherdermozilla-central@3da4d64410c0 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmtseng
bugs1292904
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 1292904 Part 3 - Use only caret image for touch area if event is a mouse type. r=mtseng That is, exclude the text overlay to fix the double clicking and triple clicking on a word in editable text area. MozReview-Commit-ID: 5bELcNSRo2A
layout/base/AccessibleCaret.cpp
layout/base/AccessibleCaret.h
layout/base/AccessibleCaretEventHub.cpp
layout/base/AccessibleCaretEventHub.h
layout/base/AccessibleCaretManager.cpp
layout/base/AccessibleCaretManager.h
layout/base/gtest/TestAccessibleCaretEventHub.cpp
--- a/layout/base/AccessibleCaret.cpp
+++ b/layout/base/AccessibleCaret.cpp
@@ -174,27 +174,32 @@ AccessibleCaret::Intersects(const Access
   }
 
   nsRect rect = nsLayoutUtils::GetRectRelativeToFrame(CaretElement(), RootFrame());
   nsRect rhsRect = nsLayoutUtils::GetRectRelativeToFrame(aCaret.CaretElement(), RootFrame());
   return rect.Intersects(rhsRect);
 }
 
 bool
-AccessibleCaret::Contains(const nsPoint& aPoint) const
+AccessibleCaret::Contains(const nsPoint& aPoint, TouchArea aTouchArea) const
 {
   if (!IsVisuallyVisible()) {
     return false;
   }
 
   nsRect textOverlayRect =
     nsLayoutUtils::GetRectRelativeToFrame(TextOverlayElement(), RootFrame());
   nsRect caretImageRect =
     nsLayoutUtils::GetRectRelativeToFrame(CaretImageElement(), RootFrame());
 
+  if (aTouchArea == TouchArea::CaretImage) {
+    return caretImageRect.Contains(aPoint);
+  }
+
+  MOZ_ASSERT(aTouchArea == TouchArea::Full, "Unexpected TouchArea type!");
   return textOverlayRect.Contains(aPoint) || caretImageRect.Contains(aPoint);
 }
 
 void
 AccessibleCaret::EnsureApzAware()
 {
   // If the caret element was cloned, the listener might have been lost. So
   // if that's the case we register a dummy listener if there isn't one on
--- a/layout/base/AccessibleCaret.h
+++ b/layout/base/AccessibleCaret.h
@@ -118,17 +118,21 @@ public:
 
   virtual PositionChangedResult SetPosition(nsIFrame* aFrame, int32_t aOffset);
 
   // Does two AccessibleCarets overlap?
   bool Intersects(const AccessibleCaret& aCaret) const;
 
   // Is the point within the caret's rect? The point should be relative to root
   // frame.
-  bool Contains(const nsPoint& aPoint) const;
+  enum class TouchArea {
+    Full, // Contains both text overlay and caret image.
+    CaretImage
+  };
+  bool Contains(const nsPoint& aPoint, TouchArea aTouchArea) const;
 
   // The geometry center of the imaginary caret (nsCaret) to which this
   // AccessibleCaret is attached. It is needed when dragging the caret.
   nsPoint LogicalPosition() const
   {
     return mImaginaryCaretRect.Center();
   }
 
--- a/layout/base/AccessibleCaretEventHub.cpp
+++ b/layout/base/AccessibleCaretEventHub.cpp
@@ -39,22 +39,22 @@ NS_IMPL_ISUPPORTS(AccessibleCaretEventHu
 //
 class AccessibleCaretEventHub::NoActionState
   : public AccessibleCaretEventHub::State
 {
 public:
   virtual const char* Name() const override { return "NoActionState"; }
 
   virtual nsEventStatus OnPress(AccessibleCaretEventHub* aContext,
-                                const nsPoint& aPoint,
-                                int32_t aTouchId) override
+                                const nsPoint& aPoint, int32_t aTouchId,
+                                EventClassID aEventClass) override
   {
     nsEventStatus rv = nsEventStatus_eIgnore;
 
-    if (NS_SUCCEEDED(aContext->mManager->PressCaret(aPoint))) {
+    if (NS_SUCCEEDED(aContext->mManager->PressCaret(aPoint, aEventClass))) {
       aContext->SetState(aContext->PressCaretState());
       rv = nsEventStatus_eConsumeNoDefault;
     } else {
       aContext->SetState(aContext->PressNoCaretState());
     }
 
     aContext->mPressPoint = aPoint;
     aContext->mActiveTouchId = aTouchId;
@@ -264,23 +264,24 @@ public:
 //
 class AccessibleCaretEventHub::PostScrollState
   : public AccessibleCaretEventHub::State
 {
 public:
   virtual const char* Name() const override { return "PostScrollState"; }
 
   virtual nsEventStatus OnPress(AccessibleCaretEventHub* aContext,
-                                const nsPoint& aPoint,
-                                int32_t aTouchId) override
+                                const nsPoint& aPoint, int32_t aTouchId,
+                                EventClassID aEventClass) override
   {
     aContext->mManager->OnScrollEnd();
     aContext->SetState(aContext->NoActionState());
 
-    return aContext->GetState()->OnPress(aContext, aPoint, aTouchId);
+    return aContext->GetState()->OnPress(aContext, aPoint, aTouchId,
+                                         aEventClass);
   }
 
   virtual void OnScrollStart(AccessibleCaretEventHub* aContext) override
   {
     aContext->SetState(aContext->ScrollState());
   }
 
   virtual void OnScrollEnd(AccessibleCaretEventHub* aContext) override
@@ -510,17 +511,17 @@ AccessibleCaretEventHub::HandleMouseEven
 
   int32_t id =
     (mActiveTouchId == kInvalidTouchId ? kDefaultTouchId : mActiveTouchId);
   nsPoint point = GetMouseEventPosition(aEvent);
 
   switch (aEvent->mMessage) {
     case eMouseDown:
       AC_LOGV("Before eMouseDown, state: %s", mState->Name());
-      rv = mState->OnPress(this, point, id);
+      rv = mState->OnPress(this, point, id, eMouseEventClass);
       AC_LOGV("After eMouseDown, state: %s, consume: %d", mState->Name(), rv);
       break;
 
     case eMouseMove:
       AC_LOGV("Before eMouseMove, state: %s", mState->Name());
       rv = mState->OnMove(this, point);
       AC_LOGV("After eMouseMove, state: %s, consume: %d", mState->Name(), rv);
       break;
@@ -558,17 +559,17 @@ AccessibleCaretEventHub::HandleTouchEven
   int32_t id =
     (mActiveTouchId == kInvalidTouchId ? aEvent->mTouches[0]->Identifier()
                                        : mActiveTouchId);
   nsPoint point = GetTouchEventPosition(aEvent, id);
 
   switch (aEvent->mMessage) {
     case eTouchStart:
       AC_LOGV("Before eTouchStart, state: %s", mState->Name());
-      rv = mState->OnPress(this, point, id);
+      rv = mState->OnPress(this, point, id, eTouchEventClass);
       AC_LOGV("After eTouchStart, state: %s, consume: %d", mState->Name(), rv);
       break;
 
     case eTouchMove:
       AC_LOGV("Before eTouchMove, state: %s", mState->Name());
       rv = mState->OnMove(this, point);
       AC_LOGV("After eTouchMove, state: %s, consume: %d", mState->Name(), rv);
       break;
--- a/layout/base/AccessibleCaretEventHub.h
+++ b/layout/base/AccessibleCaretEventHub.h
@@ -171,17 +171,18 @@ protected:
 // state is also responsible for transforming itself to the next concrete state.
 //
 class AccessibleCaretEventHub::State
 {
 public:
   virtual const char* Name() const { return ""; }
 
   virtual nsEventStatus OnPress(AccessibleCaretEventHub* aContext,
-                                const nsPoint& aPoint, int32_t aTouchId)
+                                const nsPoint& aPoint, int32_t aTouchId,
+                                EventClassID aEventClass)
   {
     return nsEventStatus_eIgnore;
   }
 
   virtual nsEventStatus OnMove(AccessibleCaretEventHub* aContext,
                                const nsPoint& aPoint)
   {
     return nsEventStatus_eIgnore;
--- a/layout/base/AccessibleCaretManager.cpp
+++ b/layout/base/AccessibleCaretManager.cpp
@@ -452,24 +452,32 @@ AccessibleCaretManager::ProvideHapticFee
   if (sHapticFeedback) {
     nsCOMPtr<nsIHapticFeedback> haptic =
       do_GetService("@mozilla.org/widget/hapticfeedback;1");
     haptic->PerformSimpleAction(haptic->LongPress);
   }
 }
 
 nsresult
-AccessibleCaretManager::PressCaret(const nsPoint& aPoint)
+AccessibleCaretManager::PressCaret(const nsPoint& aPoint,
+                                   EventClassID aEventClass)
 {
   nsresult rv = NS_ERROR_FAILURE;
 
-  if (mFirstCaret->Contains(aPoint)) {
+  MOZ_ASSERT(aEventClass == eMouseEventClass || aEventClass == eTouchEventClass,
+             "Unexpected event class!");
+
+  using TouchArea = AccessibleCaret::TouchArea;
+  TouchArea touchArea =
+    aEventClass == eMouseEventClass ? TouchArea::CaretImage : TouchArea::Full;
+
+  if (mFirstCaret->Contains(aPoint, touchArea)) {
     mActiveCaret = mFirstCaret.get();
     SetSelectionDirection(eDirPrevious);
-  } else if (mSecondCaret->Contains(aPoint)) {
+  } else if (mSecondCaret->Contains(aPoint, touchArea)) {
     mActiveCaret = mSecondCaret.get();
     SetSelectionDirection(eDirNext);
   }
 
   if (mActiveCaret) {
     mOffsetYToCaretLogicalPosition =
       mActiveCaret->LogicalPosition().y - aPoint.y;
     SetSelectionDragState(true);
--- a/layout/base/AccessibleCaretManager.h
+++ b/layout/base/AccessibleCaretManager.h
@@ -53,17 +53,17 @@ public:
   // Called by AccessibleCaretEventHub to inform us that PresShell is destroyed.
   void Terminate();
 
   // The aPoint in the following public methods should be relative to root
   // frame.
 
   // Press caret on the given point. Return NS_OK if the point is actually on
   // one of the carets.
-  virtual nsresult PressCaret(const nsPoint& aPoint);
+  virtual nsresult PressCaret(const nsPoint& aPoint, EventClassID aEventClass);
 
   // Drag caret to the given point. It's required to call PressCaret()
   // beforehand.
   virtual nsresult DragCaret(const nsPoint& aPoint);
 
   // Release caret from he previous press action. It's required to call
   // PressCaret() beforehand.
   virtual nsresult ReleaseCaret();
--- a/layout/base/gtest/TestAccessibleCaretEventHub.cpp
+++ b/layout/base/gtest/TestAccessibleCaretEventHub.cpp
@@ -35,17 +35,18 @@ namespace mozilla
 class MockAccessibleCaretManager : public AccessibleCaretManager
 {
 public:
   MockAccessibleCaretManager()
     : AccessibleCaretManager(nullptr)
   {
   }
 
-  MOCK_METHOD1(PressCaret, nsresult(const nsPoint& aPoint));
+  MOCK_METHOD2(PressCaret,
+               nsresult(const nsPoint& aPoint, EventClassID aEventClass));
   MOCK_METHOD1(DragCaret, nsresult(const nsPoint& aPoint));
   MOCK_METHOD0(ReleaseCaret, nsresult());
   MOCK_METHOD1(TapCaret, nsresult(const nsPoint& aPoint));
   MOCK_METHOD1(SelectWordOrShortcut, nsresult(const nsPoint& aPoint));
   MOCK_METHOD0(OnScrollStart, void());
   MOCK_METHOD0(OnScrollEnd, void());
   MOCK_METHOD0(OnScrollPositionChanged, void());
   MOCK_METHOD0(OnBlur, void());
@@ -261,17 +262,17 @@ TEST_F(AccessibleCaretEventHubTester, Te
 }
 
 template <typename PressEventCreator, typename ReleaseEventCreator>
 void
 AccessibleCaretEventHubTester::TestPressReleaseOnNoCaret(
   PressEventCreator aPressEventCreator,
   ReleaseEventCreator aReleaseEventCreator)
 {
-  EXPECT_CALL(*mHub->GetMockAccessibleCaretManager(), PressCaret(_))
+  EXPECT_CALL(*mHub->GetMockAccessibleCaretManager(), PressCaret(_, _))
     .WillOnce(Return(NS_ERROR_FAILURE));
 
   EXPECT_CALL(*mHub->GetMockAccessibleCaretManager(), ReleaseCaret()).Times(0);
 
   EXPECT_CALL(*mHub->GetMockAccessibleCaretManager(), TapCaret(_)).Times(0);
 
   HandleEventAndCheckState(aPressEventCreator(0, 0),
                            MockAccessibleCaretEventHub::PressNoCaretState(),
@@ -296,17 +297,17 @@ template <typename PressEventCreator, ty
 void
 AccessibleCaretEventHubTester::TestPressReleaseOnCaret(
   PressEventCreator aPressEventCreator,
   ReleaseEventCreator aReleaseEventCreator)
 {
   {
     InSequence dummy;
 
-    EXPECT_CALL(*mHub->GetMockAccessibleCaretManager(), PressCaret(_))
+    EXPECT_CALL(*mHub->GetMockAccessibleCaretManager(), PressCaret(_, _))
       .WillOnce(Return(NS_OK));
 
     EXPECT_CALL(*mHub->GetMockAccessibleCaretManager(), SelectWordOrShortcut(_))
       .Times(0);
 
     EXPECT_CALL(*mHub->GetMockAccessibleCaretManager(), ReleaseCaret());
     EXPECT_CALL(*mHub->GetMockAccessibleCaretManager(), TapCaret(_));
   }
@@ -346,17 +347,17 @@ AccessibleCaretEventHubTester::TestPress
   nscoord x0 = 0, y0 = 0;
   nscoord x1 = 100, y1 = 100;
   nscoord x2 = 300, y2 = 300;
   nscoord x3 = 400, y3 = 400;
 
   {
     InSequence dummy;
 
-    EXPECT_CALL(*mHub->GetMockAccessibleCaretManager(), PressCaret(_))
+    EXPECT_CALL(*mHub->GetMockAccessibleCaretManager(), PressCaret(_, _))
       .WillOnce(Return(NS_ERROR_FAILURE));
 
     EXPECT_CALL(*mHub->GetMockAccessibleCaretManager(), DragCaret(_)).Times(0);
   }
 
   HandleEventAndCheckState(aPressEventCreator(x0, y0),
                            MockAccessibleCaretEventHub::PressNoCaretState(),
                            nsEventStatus_eIgnore);
@@ -400,17 +401,17 @@ AccessibleCaretEventHubTester::TestPress
   nscoord x0 = 0, y0 = 0;
   nscoord x1 = 100, y1 = 100;
   nscoord x2 = 300, y2 = 300;
   nscoord x3 = 400, y3 = 400;
 
   {
     InSequence dummy;
 
-    EXPECT_CALL(*mHub->GetMockAccessibleCaretManager(), PressCaret(_))
+    EXPECT_CALL(*mHub->GetMockAccessibleCaretManager(), PressCaret(_, _))
       .WillOnce(Return(NS_OK));
 
     EXPECT_CALL(*mHub->GetMockAccessibleCaretManager(), DragCaret(_))
       .Times(2) // two valid drag operations
       .WillRepeatedly(Return(NS_OK));
 
     EXPECT_CALL(*mHub->GetMockAccessibleCaretManager(), ReleaseCaret())
       .WillOnce(Return(NS_OK));
@@ -450,17 +451,17 @@ TEST_F(AccessibleCaretEventHubTester,
   nscoord x0 = 0, y0 = 0;
   nscoord x1 = 100, y1 = 100;
   nscoord x2 = 300, y2 = 300;
   nscoord x3 = 400, y3 = 400;
 
   {
     InSequence dummy;
 
-    EXPECT_CALL(*mHub->GetMockAccessibleCaretManager(), PressCaret(_))
+    EXPECT_CALL(*mHub->GetMockAccessibleCaretManager(), PressCaret(_, _))
       .WillOnce(Return(NS_OK));
 
     EXPECT_CALL(*mHub->GetMockAccessibleCaretManager(), DragCaret(_))
       .WillOnce(Return(NS_OK));
 
     EXPECT_CALL(*mHub->GetMockAccessibleCaretManager(), ReleaseCaret())
       .WillOnce(Return(NS_OK));
   }
@@ -520,25 +521,25 @@ void
 AccessibleCaretEventHubTester::TestLongTapWithSelectWordSuccessful(
   PressEventCreator aPressEventCreator,
   ReleaseEventCreator aReleaseEventCreator)
 {
   MockFunction<void(::std::string aCheckPointName)> check;
   {
     InSequence dummy;
 
-    EXPECT_CALL(*mHub->GetMockAccessibleCaretManager(), PressCaret(_))
+    EXPECT_CALL(*mHub->GetMockAccessibleCaretManager(), PressCaret(_, _))
       .WillOnce(Return(NS_ERROR_FAILURE));
 
     EXPECT_CALL(*mHub->GetMockAccessibleCaretManager(), SelectWordOrShortcut(_))
       .WillOnce(Return(NS_OK));
 
     EXPECT_CALL(check, Call("longtap with scrolling"));
 
-    EXPECT_CALL(*mHub->GetMockAccessibleCaretManager(), PressCaret(_))
+    EXPECT_CALL(*mHub->GetMockAccessibleCaretManager(), PressCaret(_, _))
       .WillOnce(Return(NS_ERROR_FAILURE));
 
     EXPECT_CALL(*mHub->GetMockAccessibleCaretManager(), SelectWordOrShortcut(_))
       .WillOnce(Return(NS_OK));
 
     EXPECT_CALL(*mHub->GetMockAccessibleCaretManager(), OnScrollStart());
     EXPECT_CALL(*mHub->GetMockAccessibleCaretManager(), OnScrollEnd());
   }
@@ -603,17 +604,17 @@ template <typename PressEventCreator, ty
 void
 AccessibleCaretEventHubTester::TestLongTapWithSelectWordFailed(
   PressEventCreator aPressEventCreator,
   ReleaseEventCreator aReleaseEventCreator)
 {
   {
     InSequence dummy;
 
-    EXPECT_CALL(*mHub->GetMockAccessibleCaretManager(), PressCaret(_))
+    EXPECT_CALL(*mHub->GetMockAccessibleCaretManager(), PressCaret(_, _))
       .WillOnce(Return(NS_ERROR_FAILURE));
 
     EXPECT_CALL(*mHub->GetMockAccessibleCaretManager(), SelectWordOrShortcut(_))
       .WillOnce(Return(NS_ERROR_FAILURE));
   }
 
   HandleEventAndCheckState(aPressEventCreator(0, 0),
                            MockAccessibleCaretEventHub::PressNoCaretState(),
@@ -646,27 +647,27 @@ void
 AccessibleCaretEventHubTester::TestEventDrivenAsyncPanZoomScroll(
   PressEventCreator aPressEventCreator, MoveEventCreator aMoveEventCreator,
   ReleaseEventCreator aReleaseEventCreator)
 {
   MockFunction<void(::std::string aCheckPointName)> check;
   {
     InSequence dummy;
 
-    EXPECT_CALL(*mHub->GetMockAccessibleCaretManager(), PressCaret(_))
+    EXPECT_CALL(*mHub->GetMockAccessibleCaretManager(), PressCaret(_, _))
       .WillOnce(Return(NS_ERROR_FAILURE));
     EXPECT_CALL(*mHub->GetMockAccessibleCaretManager(), DragCaret(_)).Times(0);
 
     EXPECT_CALL(check, Call("1"));
     EXPECT_CALL(*mHub->GetMockAccessibleCaretManager(), OnScrollStart());
 
     EXPECT_CALL(check, Call("2"));
     EXPECT_CALL(*mHub->GetMockAccessibleCaretManager(), OnScrollEnd());
 
-    EXPECT_CALL(*mHub->GetMockAccessibleCaretManager(), PressCaret(_))
+    EXPECT_CALL(*mHub->GetMockAccessibleCaretManager(), PressCaret(_, _))
       .WillOnce(Return(NS_ERROR_FAILURE));
     EXPECT_CALL(*mHub->GetMockAccessibleCaretManager(), DragCaret(_)).Times(0);
 
     EXPECT_CALL(check, Call("3"));
     EXPECT_CALL(*mHub->GetMockAccessibleCaretManager(), OnScrollStart());
 
     EXPECT_CALL(check, Call("4"));
     EXPECT_CALL(*mHub->GetMockAccessibleCaretManager(), OnScrollEnd());