Bug 1048752. Part 14: Split GetGeometry into a static and a non-static version. r=tn
authorRobert O'Callahan <robert@ocallahan.org>
Wed, 06 Aug 2014 17:19:26 +1200
changeset 199951 ca077bb6fbc3de241d982c39fbf8b942c44c0392
parent 199950 744443e8760a693dd58e9b4ba932b16bb8e23d1e
child 199952 77b56aabc8235f936eb45665081d20147baa2957
push id9784
push userryanvm@gmail.com
push dateSat, 16 Aug 2014 21:45:40 +0000
treeherderb2g-inbound@94ba78a42305 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerstn
bugs1048752
milestone34.0a1
Bug 1048752. Part 14: Split GetGeometry into a static and a non-static version. r=tn GetGeometry is used in two different ways. Sometimes it's used to get information about a particular caret. Sometimes it's used to get information about a particular selection that's not associated with a caret. Splitting GetGeometry into a non-static version for the former and a static version for the latter makes this more clear. Also it saves code since for the latter version we don't have to get an nsCaret first.
accessible/generic/HyperTextAccessible.cpp
dom/base/nsFocusManager.cpp
dom/events/ContentEventHandler.cpp
layout/base/SelectionCarets.cpp
layout/base/TouchCaret.cpp
layout/base/nsCaret.cpp
layout/base/nsCaret.h
layout/base/nsPresShell.cpp
layout/generic/nsSelection.cpp
--- a/accessible/generic/HyperTextAccessible.cpp
+++ b/accessible/generic/HyperTextAccessible.cpp
@@ -1317,26 +1317,23 @@ HyperTextAccessible::CaretLineNumber()
 nsIntRect
 HyperTextAccessible::GetCaretRect(nsIWidget** aWidget)
 {
   *aWidget = nullptr;
 
   nsRefPtr<nsCaret> caret = mDoc->PresShell()->GetCaret();
   NS_ENSURE_TRUE(caret, nsIntRect());
 
-  nsISelection* caretSelection = caret->GetCaretDOMSelection();
-  NS_ENSURE_TRUE(caretSelection, nsIntRect());
-
   bool isVisible = false;
   caret->GetCaretVisible(&isVisible);
   if (!isVisible)
     return nsIntRect();
 
   nsRect rect;
-  nsIFrame* frame = caret->GetGeometry(caretSelection, &rect);
+  nsIFrame* frame = caret->GetGeometry(&rect);
   if (!frame || rect.IsEmpty())
     return nsIntRect();
 
   nsPoint offset;
   // Offset from widget origin to the frame origin, which includes chrome
   // on the widget.
   *aWidget = frame->GetNearestWidget(offset);
   NS_ENSURE_TRUE(*aWidget, nsIntRect());
--- a/dom/base/nsFocusManager.cpp
+++ b/dom/base/nsFocusManager.cpp
@@ -2290,19 +2290,18 @@ nsFocusManager::GetSelectionLocation(nsI
             if (nullptr == newCaretFrame)
               break;
             newCaretContent = newCaretFrame->GetContent();
           } while (!newCaretContent || newCaretContent == startContent);
 
           if (newCaretFrame && newCaretContent) {
             // If the caret is exactly at the same position of the new frame,
             // then we can use the newCaretFrame and newCaretContent for our position
-            nsRefPtr<nsCaret> caret = aPresShell->GetCaret();
             nsRect caretRect;
-            nsIFrame *frame = caret->GetGeometry(domSelection, &caretRect);
+            nsIFrame *frame = nsCaret::GetGeometry(domSelection, &caretRect);
             if (frame) {
               nsPoint caretWidgetOffset;
               nsIWidget *widget = frame->GetNearestWidget(caretWidgetOffset);
               caretRect.MoveBy(caretWidgetOffset);
               nsPoint newCaretOffset;
               nsIWidget *newCaretWidget = newCaretFrame->GetNearestWidget(newCaretOffset);
               if (widget == newCaretWidget && caretRect.y == newCaretOffset.y &&
                   caretRect.x == newCaretOffset.x) {
--- a/dom/events/ContentEventHandler.cpp
+++ b/dom/events/ContentEventHandler.cpp
@@ -113,21 +113,18 @@ ContentEventHandler::Init(WidgetQueryCon
 
   aEvent->mReply.mContentsRoot = mRootContent.get();
 
   bool isCollapsed;
   rv = mSelection->GetIsCollapsed(&isCollapsed);
   NS_ENSURE_SUCCESS(rv, NS_ERROR_NOT_AVAILABLE);
   aEvent->mReply.mHasSelection = !isCollapsed;
 
-  nsRefPtr<nsCaret> caret = mPresShell->GetCaret();
-  NS_ASSERTION(caret, "GetCaret returned null");
-
   nsRect r;
-  nsIFrame* frame = caret->GetGeometry(mSelection, &r);
+  nsIFrame* frame = nsCaret::GetGeometry(mSelection, &r);
   NS_ENSURE_TRUE(frame, NS_ERROR_FAILURE);
 
   aEvent->mReply.mFocusedWidget = frame->GetNearestWidget();
 
   return NS_OK;
 }
 
 nsresult
@@ -838,40 +835,38 @@ ContentEventHandler::OnQueryCaretRect(Wi
 {
   nsresult rv = Init(aEvent);
   if (NS_FAILED(rv)) {
     return rv;
   }
 
   LineBreakType lineBreakType = GetLineBreakType(aEvent);
 
-  nsRefPtr<nsCaret> caret = mPresShell->GetCaret();
-  NS_ASSERTION(caret, "GetCaret returned null");
-
   // When the selection is collapsed and the queried offset is current caret
   // position, we should return the "real" caret rect.
   bool selectionIsCollapsed;
   rv = mSelection->GetIsCollapsed(&selectionIsCollapsed);
   NS_ENSURE_SUCCESS(rv, rv);
 
+  nsRect caretRect;
+  nsIFrame* caretFrame = nsCaret::GetGeometry(mSelection, &caretRect);
+
   if (selectionIsCollapsed) {
     uint32_t offset;
     rv = GetFlatTextOffsetOfRange(mRootContent, mFirstSelectedRange, &offset,
                                   lineBreakType);
     NS_ENSURE_SUCCESS(rv, rv);
     if (offset == aEvent->mInput.mOffset) {
-      nsRect rect;
-      nsIFrame* caretFrame = caret->GetGeometry(mSelection, &rect);
       if (!caretFrame) {
         return NS_ERROR_FAILURE;
       }
-      rv = ConvertToRootViewRelativeOffset(caretFrame, rect);
+      rv = ConvertToRootViewRelativeOffset(caretFrame, caretRect);
       NS_ENSURE_SUCCESS(rv, rv);
       aEvent->mReply.mRect =
-        rect.ToOutsidePixels(caretFrame->PresContext()->AppUnitsPerDevPixel());
+        caretRect.ToOutsidePixels(caretFrame->PresContext()->AppUnitsPerDevPixel());
       aEvent->mReply.mOffset = aEvent->mInput.mOffset;
       aEvent->mSucceeded = true;
       return NS_OK;
     }
   }
 
   // Otherwise, we should set the guessed caret rect.
   nsRefPtr<nsRange> range = new nsRange(mRootContent);
@@ -887,17 +882,17 @@ ContentEventHandler::OnQueryCaretRect(Wi
 
   nsPoint posInFrame;
   rv = frame->GetPointFromOffset(range->StartOffset(), &posInFrame);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsRect rect;
   rect.x = posInFrame.x;
   rect.y = posInFrame.y;
-  rect.width = caret->GetCaretRect().width;
+  rect.width = caretRect.width;
   rect.height = frame->GetSize().height;
 
   rv = ConvertToRootViewRelativeOffset(frame, rect);
   NS_ENSURE_SUCCESS(rv, rv);
 
   aEvent->mReply.mRect =
       rect.ToOutsidePixels(mPresContext->AppUnitsPerDevPixel());
   aEvent->mSucceeded = true;
--- a/layout/base/SelectionCarets.cpp
+++ b/layout/base/SelectionCarets.cpp
@@ -789,19 +789,18 @@ SelectionCarets::GetEndFrameRect()
 }
 
 nsIFrame*
 SelectionCarets::GetCaretFocusFrame()
 {
   nsRefPtr<nsCaret> caret = mPresShell->GetCaret();
   NS_ENSURE_TRUE(caret, nullptr);
 
-  nsISelection* caretSelection = caret->GetCaretDOMSelection();
   nsRect focusRect;
-  return caret->GetGeometry(caretSelection, &focusRect);
+  return caret->GetGeometry(&focusRect);
 }
 
 bool
 SelectionCarets::GetCaretVisible()
 {
   NS_ENSURE_TRUE(mPresShell, false);
   nsRefPtr<nsCaret> caret = mPresShell->GetCaret();
   NS_ENSURE_TRUE(caret, false);
--- a/layout/base/TouchCaret.cpp
+++ b/layout/base/TouchCaret.cpp
@@ -163,19 +163,18 @@ nsRect
 TouchCaret::GetContentBoundary()
 {
   nsCOMPtr<nsIPresShell> presShell = do_QueryReferent(mPresShell);
   if (!presShell) {
     return nsRect();
   }
 
   nsRefPtr<nsCaret> caret = presShell->GetCaret();
-  nsISelection* caretSelection = caret->GetCaretDOMSelection();
   nsRect focusRect;
-  nsIFrame* focusFrame = caret->GetGeometry(caretSelection, &focusRect);
+  nsIFrame* focusFrame = caret->GetGeometry(&focusRect);
   nsIFrame* canvasFrame = GetCanvasFrame();
 
   // Get the editing host to determine the touch caret dragable boundary.
   dom::Element* editingHost = focusFrame->GetContent()->GetEditingHost();
   if (!editingHost) {
     return nsRect();
   }
 
@@ -208,19 +207,18 @@ nscoord
 TouchCaret::GetCaretYCenterPosition()
 {
   nsCOMPtr<nsIPresShell> presShell = do_QueryReferent(mPresShell);
   if (!presShell) {
     return 0;
   }
 
   nsRefPtr<nsCaret> caret = presShell->GetCaret();
-  nsISelection* caretSelection = caret->GetCaretDOMSelection();
   nsRect focusRect;
-  nsIFrame* focusFrame = caret->GetGeometry(caretSelection, &focusRect);
+  nsIFrame* focusFrame = caret->GetGeometry(&focusRect);
   nsRect caretRect = focusFrame->GetRectRelativeToSelf();
   nsIFrame *canvasFrame = GetCanvasFrame();
   nsLayoutUtils::TransformRect(focusFrame, canvasFrame, caretRect);
 
   return (caretRect.y + caretRect.height / 2);
 }
 
 void
@@ -259,19 +257,18 @@ TouchCaret::MoveCaret(const nsPoint& mov
 {
   nsCOMPtr<nsIPresShell> presShell = do_QueryReferent(mPresShell);
   if (!presShell) {
     return;
   }
 
   // Get scrollable frame.
   nsRefPtr<nsCaret> caret = presShell->GetCaret();
-  nsISelection* caretSelection = caret->GetCaretDOMSelection();
   nsRect focusRect;
-  nsIFrame* focusFrame = caret->GetGeometry(caretSelection, &focusRect);
+  nsIFrame* focusFrame = caret->GetGeometry(&focusRect);
   nsIFrame* scrollable =
     nsLayoutUtils::GetClosestFrameOfType(focusFrame, nsGkAtoms::scrollFrame);
 
   // Convert touch/mouse position to frame coordinates.
   nsIFrame* canvasFrame = GetCanvasFrame();
   if (!canvasFrame) {
     return;
   }
@@ -450,19 +447,20 @@ TouchCaret::UpdatePosition()
 {
   MOZ_ASSERT(mVisible);
 
   nsCOMPtr<nsIPresShell> presShell = do_QueryReferent(mPresShell);
   if (!presShell) {
     return;
   }
   nsRefPtr<nsCaret> caret = presShell->GetCaret();
-  nsISelection* caretSelection = caret->GetCaretDOMSelection();
+
+  // Caret is visible and shown, update touch caret.
   nsRect focusRect;
-  nsIFrame* focusFrame = caret->GetGeometry(caretSelection, &focusRect);
+  nsIFrame* focusFrame = caret->GetGeometry(&focusRect);
   if (!focusFrame || focusRect.IsEmpty()) {
     return;
   }
 
   // Position of the touch caret relative to focusFrame.
   nsPoint pos = nsPoint(focusRect.x + (focusRect.width / 2),
                         focusRect.y + focusRect.height);
 
@@ -533,19 +531,18 @@ void
 TouchCaret::SetSelectionDragState(bool aState)
 {
   nsCOMPtr<nsIPresShell> presShell = do_QueryReferent(mPresShell);
   if (!presShell) {
     return;
   }
 
   nsRefPtr<nsCaret> caret = presShell->GetCaret();
-  nsISelection* caretSelection = caret->GetCaretDOMSelection();
   nsRect focusRect;
-  nsIFrame* caretFocusFrame = caret->GetGeometry(caretSelection, &focusRect);
+  nsIFrame* caretFocusFrame = caret->GetGeometry(&focusRect);
   nsRefPtr<nsFrameSelection> fs = caretFocusFrame->GetFrameSelection();
   fs->SetDragState(aState);
 }
 
 nsEventStatus
 TouchCaret::HandleEvent(WidgetEvent* aEvent)
 {
   MOZ_ASSERT(NS_IsMainThread());
--- a/layout/base/nsCaret.cpp
+++ b/layout/base/nsCaret.cpp
@@ -278,17 +278,17 @@ nsresult nsCaret::GetCaretVisible(bool *
 
 
 //-----------------------------------------------------------------------------
 void nsCaret::SetCaretReadOnly(bool inMakeReadonly)
 {
   mReadOnly = inMakeReadonly;
 }
 
-nsresult
+/* static */ nsresult
 nsCaret::GetGeometryForFrame(nsIFrame* aFrame,
                              int32_t   aFrameOffset,
                              nsRect*   aRect,
                              nscoord*  aBidiIndicatorSize)
 {
   nsPoint framePos(0, 0);
   nsresult rv = aFrame->GetPointFromOffset(aFrameOffset, &framePos);
   if (NS_FAILED(rv))
@@ -334,35 +334,35 @@ nsCaret::GetGeometryForFrame(nsIFrame* a
   }
 
   if (aBidiIndicatorSize)
     *aBidiIndicatorSize = caretMetrics.mBidiIndicatorSize;
 
   return NS_OK;
 }
 
-nsIFrame* nsCaret::GetGeometry(nsISelection* aSelection, nsRect* aRect)
+/* static */ nsIFrame*
+nsCaret::GetGeometry(nsISelection* aSelection, nsRect* aRect)
 {
   nsCOMPtr<nsIDOMNode> focusNode;
   nsresult rv = aSelection->GetFocusNode(getter_AddRefs(focusNode));
   if (NS_FAILED(rv) || !focusNode)
     return nullptr;
 
   int32_t focusOffset;
   rv = aSelection->GetFocusOffset(&focusOffset);
   if (NS_FAILED(rv))
     return nullptr;
     
   nsCOMPtr<nsIContent> contentNode = do_QueryInterface(focusNode);
   if (!contentNode)
     return nullptr;
 
-  nsRefPtr<nsFrameSelection> frameSelection = GetFrameSelection();
-  if (!frameSelection)
-    return nullptr;
+  nsFrameSelection* frameSelection =
+      static_cast<Selection*>(aSelection)->GetFrameSelection();
   uint8_t bidiLevel = frameSelection->GetCaretBidiLevel();
   nsIFrame* frame;
   int32_t frameOffset;
   rv = GetCaretFrameForNodeOffset(frameSelection, contentNode, focusOffset,
                                   frameSelection->GetHint(), bidiLevel,
                                   &frame, &frameOffset);
   if (NS_FAILED(rv) || !frame)
     return nullptr;
--- a/layout/base/nsCaret.h
+++ b/layout/base/nsCaret.h
@@ -83,25 +83,16 @@ class nsCaret : public nsISelectionListe
      *  Draw the caret explicitly, at the specified node and offset.
      *  To avoid drawing glitches, you should call EraseCaret()
      *  after each call to DrawAtPosition().
      *
      *  Note: This call breaks the caret's ability to blink at all.
      **/
     nsresult DrawAtPosition(nsIDOMNode* aNode, int32_t aOffset);
 
-    /**
-     * Gets the position and size of the caret that would be drawn for
-     * the focus node/offset of aSelection (assuming it would be drawn,
-     * i.e., disregarding blink status). The geometry is stored in aRect,
-     * and we return the frame aRect is relative to.
-     * @param aRect must be non-null
-     */
-    nsIFrame* GetGeometry(nsISelection* aSelection,
-                          nsRect* aRect);
     /** GetCaretFrame
      *  Get the current frame that the caret should be drawn in. If the caret is
      *  not currently visible (i.e., it is between blinks), then this will
      *  return null.
      *
      *  @param aOffset is result of the caret offset in the content.
      */
     nsIFrame* GetCaretFrame(int32_t *aOffset = nullptr);
@@ -110,28 +101,43 @@ class nsCaret : public nsISelectionListe
      *  non-null.
      */
     nsRect GetCaretRect()
     {
       nsRect r;
       r.UnionRect(mCaretRect, GetHookRect());
       return r;
     }
+    nsIFrame* GetGeometry(nsRect* aRect)
+    {
+      return GetGeometry(GetCaretDOMSelection(), aRect);
+    }
 
     /** PaintCaret
      *  Actually paint the caret onto the given rendering context.
      */
     void PaintCaret(nsDisplayListBuilder *aBuilder,
                     nsRenderingContext *aCtx,
                     nsIFrame *aForFrame,
                     const nsPoint &aOffset);
 
     //nsISelectionListener interface
     NS_DECL_NSISELECTIONLISTENER
 
+    /**
+     * Gets the position and size of the caret that would be drawn for
+     * the focus node/offset of aSelection (assuming it would be drawn,
+     * i.e., disregarding blink status). The geometry is stored in aRect,
+     * and we return the frame aRect is relative to.
+     * Only looks at the focus node of aSelection, so you can call it even if
+     * aSelection is not collapsed.
+     * @param aRect must be non-null
+     */
+    static nsIFrame* GetGeometry(nsISelection* aSelection,
+                                 nsRect* aRect);
     static nsresult GetCaretFrameForNodeOffset(nsFrameSelection* aFrameSelection,
                                                nsIContent* aContentNode,
                                                int32_t aOffset,
                                                nsFrameSelection::HINT aFrameHint,
                                                uint8_t aBidiLevel,
                                                nsIFrame** aReturnFrame,
                                                int32_t* aReturnOffset);
 
@@ -151,21 +157,22 @@ protected:
                                          nsFrameSelection::HINT aFrameHint,
                                          uint8_t aBidiLevel,
                                          bool aInvalidate);
 
     struct Metrics {
       nscoord mBidiIndicatorSize; // width and height of bidi indicator
       nscoord mCaretWidth;        // full caret width including bidi indicator
     };
-    Metrics ComputeMetrics(nsIFrame* aFrame, int32_t aOffset, nscoord aCaretHeight);
-    nsresult GetGeometryForFrame(nsIFrame* aFrame,
-                                 int32_t   aFrameOffset,
-                                 nsRect*   aRect,
-                                 nscoord*  aBidiIndicatorSize);
+    static Metrics ComputeMetrics(nsIFrame* aFrame, int32_t aOffset,
+                                  nscoord aCaretHeight);
+    static nsresult GetGeometryForFrame(nsIFrame* aFrame,
+                                        int32_t   aFrameOffset,
+                                        nsRect*   aRect,
+                                        nscoord*  aBidiIndicatorSize);
 
     // Returns true if the caret should be drawn. When |mDrawn| is true,
     // this returns true, so that we erase the drawn caret. If |aIgnoreDrawnState|
     // is true, we don't take into account whether the caret is currently
     // drawn or not. This can be used to determine if the caret is drawn when
     // it shouldn't be.
     bool          MustDrawCaret(bool aIgnoreDrawnState);
 
--- a/layout/base/nsPresShell.cpp
+++ b/layout/base/nsPresShell.cpp
@@ -8130,17 +8130,17 @@ PresShell::PrepareToUseCaretPosition(nsI
                                          nsISelectionController::SCROLL_SYNCHRONOUS);
     NS_ENSURE_SUCCESS(rv, false);
   }
 
   nsPresContext* presContext = GetPresContext();
 
   // get caret position relative to the closest view
   nsRect caretCoords;
-  nsIFrame* caretFrame = caret->GetGeometry(domSelection, &caretCoords);
+  nsIFrame* caretFrame = caret->GetGeometry(&caretCoords);
   if (!caretFrame)
     return false;
   nsPoint viewOffset;
   nsView* view = caretFrame->GetClosestView(&viewOffset);
   if (!view)
     return false;
   // and then get the caret coords relative to the event widget
   if (aEventWidget) {
--- a/layout/generic/nsSelection.cpp
+++ b/layout/generic/nsSelection.cpp
@@ -429,17 +429,17 @@ nsFrameSelection::FetchDesiredX(nscoord 
     return NS_ERROR_NULL_POINTER;
 
   int8_t index = GetIndexFromSelectionType(nsISelectionController::SELECTION_NORMAL);
   nsresult result = caret->SetCaretDOMSelection(mDomSelections[index]);
   if (NS_FAILED(result))
     return result;
 
   nsRect coord;
-  nsIFrame* caretFrame = caret->GetGeometry(mDomSelections[index], &coord);
+  nsIFrame* caretFrame = caret->GetGeometry(&coord);
   if (!caretFrame)
     return NS_ERROR_FAILURE;
   nsPoint viewOffset(0, 0);
   nsView* view = nullptr;
   caretFrame->GetOffsetFromView(viewOffset, &view);
   if (view)
     coord.x += viewOffset.x;
 
@@ -1864,20 +1864,18 @@ nsFrameSelection::CommonPageMove(bool aF
     return;
 
   // find out where the caret is.
   // we should know mDesiredX value of nsFrameSelection, but I havent seen that behavior in other windows applications yet.
   nsISelection* domSel = GetSelection(nsISelectionController::SELECTION_NORMAL);
   if (!domSel) 
     return;
 
-  nsRefPtr<nsCaret> caret = mShell->GetCaret();
-
   nsRect caretPos;
-  nsIFrame* caretFrame = caret->GetGeometry(domSel, &caretPos);
+  nsIFrame* caretFrame = nsCaret::GetGeometry(domSel, &caretPos);
   if (!caretFrame) 
     return;
   
   //need to adjust caret jump by percentage scroll
   nsSize scrollDelta = aScrollableFrame->GetPageScrollAmount();
 
   if (aForward)
     caretPos.y += scrollDelta.height;