Bug 1203871 - Part 2. Implement eQueryTextRectArray. r?masayuki draft
authorMakoto Kato <m_kato@ga2.so-net.ne.jp>
Mon, 14 Mar 2016 16:03:22 +0900
changeset 340455 3db082cfeda965311025106e1649056a07e77f8b
parent 340454 350791d8a21df0da11498ca7f0fc0493b6b6e584
child 340456 41fd5679bf2162a58fac17816426f64d0fb60d5b
push id12969
push userm_kato@ga2.so-net.ne.jp
push dateTue, 15 Mar 2016 10:01:34 +0000
reviewersmasayuki
bugs1203871
milestone48.0a1
Bug 1203871 - Part 2. Implement eQueryTextRectArray. r?masayuki It will use on ContentCache. MozReview-Commit-ID: 9Yu8bLlcZS5
dom/events/ContentEventHandler.cpp
dom/events/ContentEventHandler.h
dom/events/EventStateManager.cpp
widget/EventMessageList.h
widget/TextEvents.h
--- a/dom/events/ContentEventHandler.cpp
+++ b/dom/events/ContentEventHandler.cpp
@@ -1076,16 +1076,18 @@ ContentEventHandler::HandleQueryContentE
     case eQuerySelectedText:
       return OnQuerySelectedText(aEvent);
     case eQueryTextContent:
       return OnQueryTextContent(aEvent);
     case eQueryCaretRect:
       return OnQueryCaretRect(aEvent);
     case eQueryTextRect:
       return OnQueryTextRect(aEvent);
+    case eQueryTextRectArray:
+      return OnQueryTextRectArray(aEvent);
     case eQueryEditorRect:
       return OnQueryEditorRect(aEvent);
     case eQueryContentState:
       return OnQueryContentState(aEvent);
     case eQuerySelectionAsTransferable:
       return OnQuerySelectionAsTransferable(aEvent);
     case eQueryCharacterAtPoint:
       return OnQueryCharacterAtPoint(aEvent);
@@ -1265,16 +1267,89 @@ static nsINode* AdjustTextRectNode(nsINo
       node = aNode->GetChildAt(childCount - 1);
       aNodeOffset = node->IsNodeOfType(nsINode::eTEXT) ?
         static_cast<int32_t>(static_cast<nsIContent*>(node)->TextLength()) : 1;
     }
   }
   return node;
 }
 
+static
+nsIFrame*
+GetFirstFrameIntoRange(nsRange* aRange)
+{
+  // used to iterate over all contents and their frames
+  nsCOMPtr<nsIContentIterator> iter = NS_NewContentIterator();
+  iter->Init(aRange);
+
+  // get the starting frame
+  int32_t nodeOffset = aRange->StartOffset();
+  nsINode* node = iter->GetCurrentNode();
+  if (!node) {
+    node = AdjustTextRectNode(aRange->GetStartParent(), nodeOffset);
+  }
+  nsIFrame* firstFrame = nullptr;
+  GetFrameForTextRect(node, nodeOffset, true, &firstFrame);
+  return firstFrame;
+}
+
+nsresult
+ContentEventHandler::OnQueryTextRectArray(WidgetQueryContentEvent* aEvent)
+{
+  nsresult rv = Init(aEvent);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+
+  LineBreakType lineBreakType = GetLineBreakType(aEvent);
+  RefPtr<nsRange> range = new nsRange(mRootContent);
+  uint32_t offset = aEvent->mInput.mOffset;
+
+  LayoutDeviceIntRect rect;
+  WritingMode writingMode;
+  for (size_t i = 0; i < aEvent->mInput.mLength; i++) {
+    rv = SetRangeFromFlatTextOffset(range, offset, 1, lineBreakType, true,
+                                    nullptr);
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      return rv;
+    }
+
+    // get the starting frame
+    nsIFrame* firstFrame = GetFirstFrameIntoRange(range);
+    if (NS_WARN_IF(!firstFrame)) {
+      return NS_ERROR_FAILURE;
+    }
+
+    // get the starting frame rect
+    nsRect frameRect(nsPoint(0, 0), firstFrame->GetRect().Size());
+    rv = ConvertToRootRelativeOffset(firstFrame, frameRect);
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      return rv;
+    }
+
+    nsRect charRect;
+    int32_t nodeOffset = range->StartOffset();
+    rv = firstFrame->GetCharacterRectFromOffset(nodeOffset, &charRect);
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      return rv;
+    }
+
+    charRect.x += frameRect.x;
+    charRect.y += frameRect.y;
+
+    rect = LayoutDeviceIntRect::FromUnknownRect(
+             charRect.ToOutsidePixels(mPresContext->AppUnitsPerDevPixel()));
+
+    aEvent->mReply.mRectArray.AppendElement(rect);
+    offset++;
+  }
+  aEvent->mSucceeded = true;
+  return NS_OK;
+}
+
 nsresult
 ContentEventHandler::OnQueryTextRect(WidgetQueryContentEvent* aEvent)
 {
   nsresult rv = Init(aEvent);
   if (NS_FAILED(rv)) {
     return rv;
   }
 
--- a/dom/events/ContentEventHandler.h
+++ b/dom/events/ContentEventHandler.h
@@ -47,16 +47,18 @@ public:
   // eQuerySelectedText event handler
   nsresult OnQuerySelectedText(WidgetQueryContentEvent* aEvent);
   // eQueryTextContent event handler
   nsresult OnQueryTextContent(WidgetQueryContentEvent* aEvent);
   // eQueryCaretRect event handler
   nsresult OnQueryCaretRect(WidgetQueryContentEvent* aEvent);
   // eQueryTextRect event handler
   nsresult OnQueryTextRect(WidgetQueryContentEvent* aEvent);
+  // eQueryTextRectArray event handler
+  nsresult OnQueryTextRectArray(WidgetQueryContentEvent* aEvent);
   // eQueryEditorRect event handler
   nsresult OnQueryEditorRect(WidgetQueryContentEvent* aEvent);
   // eQueryContentState event handler
   nsresult OnQueryContentState(WidgetQueryContentEvent* aEvent);
   // eQuerySelectionAsTransferable event handler
   nsresult OnQuerySelectionAsTransferable(WidgetQueryContentEvent* aEvent);
   // eQueryCharacterAtPoint event handler
   nsresult OnQueryCharacterAtPoint(WidgetQueryContentEvent* aEvent);
@@ -279,13 +281,16 @@ protected:
                                int32_t aBaseOffset,
                                int32_t aXPStartOffset,
                                int32_t aXPEndOffset,
                                LineBreakType aLineBreakType);
   nsresult GenerateFlatFontRanges(nsRange* aRange,
                                   FontRangeArray& aFontRanges,
                                   uint32_t& aLength,
                                   LineBreakType aLineBreakType);
+  nsresult QueryTextRectByRange(nsRange* aRange,
+                                LayoutDeviceIntRect& aRect,
+                                WritingMode& aWritingMode);
 };
 
 } // namespace mozilla
 
 #endif // mozilla_ContentEventHandler_h_
--- a/dom/events/EventStateManager.cpp
+++ b/dom/events/EventStateManager.cpp
@@ -848,16 +848,17 @@ EventStateManager::HandleQueryContentEve
       // Will not be handled locally, remote the event
       GetCrossProcessTarget()->HandleQueryContentEvent(*aEvent);
       return;
     // Following events have not been supported in e10s mode yet.
     case eQueryContentState:
     case eQuerySelectionAsTransferable:
     case eQueryCharacterAtPoint:
     case eQueryDOMWidgetHittest:
+    case eQueryTextRectArray:
       break;
     default:
       return;
   }
 
   // If there is an IMEContentObserver, we need to handle QueryContentEvent
   // with it.
   if (mIMEContentObserver) {
--- a/widget/EventMessageList.h
+++ b/widget/EventMessageList.h
@@ -220,16 +220,19 @@ NS_EVENT_MESSAGE(eQuerySelectedText)
 NS_EVENT_MESSAGE(eQueryTextContent)
 // Query for the caret rect of nth insertion point. The offset of the result is
 // relative position from the top level widget.
 NS_EVENT_MESSAGE(eQueryCaretRect)
 // Query for the bounding rect of a range of characters. This works on any
 // valid character range given offset and length. Result is relative to top
 // level widget coordinates
 NS_EVENT_MESSAGE(eQueryTextRect)
+// Query for the bounding rect array of a range of characters.
+// Thiis similar event of qQueryTextRect.
+NS_EVENT_MESSAGE(eQueryTextRectArray)
 // Query for the bounding rect of the current focused frame. Result is relative
 // to top level widget coordinates
 NS_EVENT_MESSAGE(eQueryEditorRect)
 // Query for the current state of the content. The particular members of
 // mReply that are set for each query content event will be valid on success.
 NS_EVENT_MESSAGE(eQueryContentState)
 // Query for the selection in the form of a nsITransferable.
 NS_EVENT_MESSAGE(eQuerySelectionAsTransferable)
--- a/widget/TextEvents.h
+++ b/widget/TextEvents.h
@@ -545,16 +545,26 @@ public:
 
   void InitForQueryDOMWidgetHittest(const mozilla::LayoutDeviceIntPoint& aPoint)
   {
     NS_ASSERTION(mMessage == eQueryDOMWidgetHittest,
                  "wrong initializer is called");
     refPoint = aPoint;
   }
 
+  void InitForQueryTextRectArray(uint32_t aOffset, uint32_t aLength,
+                                 bool aUseNativeLineBreak = true)
+  {
+    NS_ASSERTION(mMessage == eQueryTextRectArray,
+                 "wrong initializer is called");
+    mInput.mOffset = aOffset;
+    mInput.mLength = aLength;
+    mUseNativeLineBreak = aUseNativeLineBreak;
+  }
+
   void RequestFontRanges()
   {
     NS_ASSERTION(mMessage == eQueryTextContent,
                  "not querying text content");
     mWithFontRanges = true;
   }
 
   uint32_t GetSelectionStart(void) const
@@ -613,16 +623,18 @@ public:
     // The return widget has the caret. This is set at all query events.
     nsIWidget* mFocusedWidget;
     // mozilla::WritingMode value at the end (focus) of the selection
     mozilla::WritingMode mWritingMode;
     // Used by eQuerySelectionAsTransferable
     nsCOMPtr<nsITransferable> mTransferable;
     // Used by eQueryTextContent with font ranges requested
     AutoTArray<mozilla::FontRange, 1> mFontRanges;
+    // Used by eQueryTextRectArray
+    nsTArray<mozilla::LayoutDeviceIntRect> mRectArray;
     // true if selection is reversed (end < start)
     bool mReversed;
     // true if the selection exists
     bool mHasSelection;
     // true if DOM element under mouse belongs to widget
     bool mWidgetIsHit;
 
     Reply()