Bug 1048752. Part 18: Add nsCaret::SchedulePaint. r=tn
authorRobert O'Callahan <robert@ocallahan.org>
Wed, 06 Aug 2014 17:19:27 +1200
changeset 199955 8d8e4df32ffc6a207824515df719e36d9247ea01
parent 199954 e96157e3af4d776649f96d8e9bfa25d10daf4c80
child 199956 2826371a64dff46111a6d51e3701700a131a2edf
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 18: Add nsCaret::SchedulePaint. r=tn We'll use this later.
layout/base/nsCaret.cpp
layout/base/nsCaret.h
--- a/layout/base/nsCaret.cpp
+++ b/layout/base/nsCaret.cpp
@@ -36,16 +36,17 @@
 // direction the typing is in. It needs to be at least 2x2 to avoid looking like 
 // an insignificant dot
 static const int32_t kMinBidiIndicatorPixels = 2;
 
 #include "nsIBidiKeyboard.h"
 #include "nsContentUtils.h"
 
 using namespace mozilla;
+using namespace mozilla::dom;
 
 /**
  * Find the first frame in an in-order traversal of the frame subtree rooted
  * at aFrame which is either a text frame logically at the end of a line,
  * or which is aStopAtFrame. Return null if no such frame is found. We don't
  * descend into the children of non-eLineParticipant frames.
  */
 static nsIFrame*
@@ -365,16 +366,38 @@ nsCaret::GetGeometry(nsISelection* aSele
                                   &frame, &frameOffset);
   if (NS_FAILED(rv) || !frame)
     return nullptr;
 
   GetGeometryForFrame(frame, frameOffset, aRect, nullptr);
   return frame;
 }
 
+Selection*
+nsCaret::GetSelectionInternal()
+{
+  return static_cast<Selection*>(GetSelection());
+}
+
+void nsCaret::SchedulePaint()
+{
+  nsINode* focusNode = mLastContent ?
+    mLastContent.get() : GetSelectionInternal()->GetFocusNode();
+  if (!focusNode || !focusNode->IsContent()) {
+    return;
+  }
+  nsIFrame* f = focusNode->AsContent()->GetPrimaryFrame();
+  if (!f) {
+    return;
+  }
+  // This may not be the correct continuation frame, but that's OK since we're
+  // just scheduling a paint of the window (or popup).
+  f->SchedulePaint();
+}
+
 void nsCaret::DrawCaretAfterBriefDelay()
 {
   // Make sure readonly caret gets drawn again if it needs to be
   if (!mBlinkTimer) {
     nsresult  err;
     mBlinkTimer = do_CreateInstance("@mozilla.org/timer;1", &err);    
     if (NS_FAILED(err))
       return;
@@ -1095,21 +1118,17 @@ void nsCaret::CaretBlinkCallback(nsITime
   theCaret->DrawCaret(true);
 }
 
 
 //-----------------------------------------------------------------------------
 nsFrameSelection*
 nsCaret::GetFrameSelection()
 {
-  nsCOMPtr<nsISelection> sel = do_QueryReferent(mDomSelectionWeak);
-  if (!sel)
-    return nullptr;
-
-  return static_cast<dom::Selection*>(sel.get())->GetFrameSelection();
+  return GetSelectionInternal()->GetFrameSelection();
 }
 
 void
 nsCaret::SetIgnoreUserModify(bool aIgnoreUserModify)
 {
   if (!aIgnoreUserModify && mIgnoreUserModify && mDrawn) {
     // We're turning off mIgnoreUserModify. If the caret's drawn
     // in a read-only node we must erase it, else the next call
--- a/layout/base/nsCaret.h
+++ b/layout/base/nsCaret.h
@@ -164,28 +164,34 @@ class nsCaret : public nsISelectionListe
                                                nsIFrame** aReturnFrame,
                                                int32_t* aReturnOffset);
 
     size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
 
 protected:
     static void   CaretBlinkCallback(nsITimer *aTimer, void *aClosure);
 
+    // Schedule a repaint for the frame where the caret would appear.
+    // Does not check visibility etc.
+    void          SchedulePaint();
+
     void          KillTimer();
     nsresult      PrimeTimer();
 
     void          StartBlinking();
     void          StopBlinking();
 
     bool          DrawAtPositionWithHint(nsIDOMNode* aNode,
                                          int32_t aOffset,
                                          CaretAssociationHint aFrameHint,
                                          uint8_t aBidiLevel,
                                          bool aInvalidate);
 
+    mozilla::dom::Selection* GetSelectionInternal();
+
     struct Metrics {
       nscoord mBidiIndicatorSize; // width and height of bidi indicator
       nscoord mCaretWidth;        // full caret width including bidi indicator
     };
     static Metrics ComputeMetrics(nsIFrame* aFrame, int32_t aOffset,
                                   nscoord aCaretHeight);
     static nsresult GetGeometryForFrame(nsIFrame* aFrame,
                                         int32_t   aFrameOffset,
@@ -215,18 +221,16 @@ protected:
     // 1. An open popup contains the caret, but a menu popup exists before the
     //    caret-owning popup in the popup list (i.e. a menu is in front of the
     //    popup with the caret). If the menu itself contains the caret we don't
     //    hide it.
     // 2. A menu popup is open, but there is no caret present in any popup.
     // 3. The caret selection is empty.
     bool IsMenuPopupHidingCaret();
 
-protected:
-
     nsWeakPtr             mPresShell;
     nsWeakPtr             mDomSelectionWeak;
 
     nsCOMPtr<nsITimer>    mBlinkTimer;
 
     bool                  mIsBlinking;
 
     bool                  mVisible;           // is the caret blinking