Bug 1372761 - Avoid needlessly grabbing the timer thread lock when selections change in order to reset the caret timer; r=mats
authorEhsan Akhgari <ehsan@mozilla.com>
Tue, 13 Jun 2017 20:09:22 -0400
changeset 364109 db8a48dae370605e2b6de21326f882ef839401fd
parent 364108 dfee29c06556ebe2f4ac43cf0744be9e93390d1d
child 364110 6b8a78e3114c46772153bdd4f3e9fb4993e458e9
push id32033
push userarchaeopteryx@coole-files.de
push dateThu, 15 Jun 2017 18:12:50 +0000
treeherdermozilla-central@75be6742abb9 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmats
bugs1372761
milestone56.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 1372761 - Avoid needlessly grabbing the timer thread lock when selections change in order to reset the caret timer; r=mats
layout/base/nsCaret.cpp
layout/base/nsCaret.h
--- a/layout/base/nsCaret.cpp
+++ b/layout/base/nsCaret.cpp
@@ -41,16 +41,19 @@ using namespace mozilla;
 using namespace mozilla::dom;
 using namespace mozilla::gfx;
 
 // The bidi indicator hangs off the caret to one side, to show which
 // 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;
 
+// The default caret blinking rate (in ms of blinking interval)
+static const uint32_t kDefaultCaretBlinkRate = 500;
+
 /**
  * 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*
 CheckForTrailingTextFrameRecursive(nsIFrame* aFrame, nsIFrame* aStopAtFrame)
@@ -115,16 +118,17 @@ static bool
 IsBidiUI()
 {
   return Preferences::GetBool("bidi.browser.ui");
 }
 
 nsCaret::nsCaret()
 : mOverrideOffset(0)
 , mBlinkCount(-1)
+, mBlinkRate(0)
 , mHideCount(0)
 , mIsBlinkOn(false)
 , mVisible(false)
 , mReadOnly(false)
 , mShowDuringSelection(false)
 , mIgnoreUserModify(true)
 {
 }
@@ -631,27 +635,34 @@ void nsCaret::ResetBlinking()
 {
   mIsBlinkOn = true;
 
   if (mReadOnly || !mVisible || mHideCount) {
     StopBlinking();
     return;
   }
 
+  uint32_t blinkRate = static_cast<uint32_t>(
+    LookAndFeel::GetInt(LookAndFeel::eIntID_CaretBlinkTime,
+                        kDefaultCaretBlinkRate));
+  if (mBlinkRate == blinkRate) {
+    // If the rate hasn't changed, then there is nothing to do.
+    return;
+  }
+  mBlinkRate = blinkRate;
+
   if (mBlinkTimer) {
     mBlinkTimer->Cancel();
   } else {
     nsresult  err;
     mBlinkTimer = do_CreateInstance("@mozilla.org/timer;1", &err);
     if (NS_FAILED(err))
       return;
   }
 
-  uint32_t blinkRate = static_cast<uint32_t>(
-    LookAndFeel::GetInt(LookAndFeel::eIntID_CaretBlinkTime, 500));
   if (blinkRate > 0) {
     mBlinkCount = Preferences::GetInt("ui.caretBlinkCount", -1);
     mBlinkTimer->InitWithNamedFuncCallback(CaretBlinkCallback, this, blinkRate,
                                            nsITimer::TYPE_REPEATING_SLACK,
                                            "nsCaret::CaretBlinkCallback_timer");
   }
 }
 
--- a/layout/base/nsCaret.h
+++ b/layout/base/nsCaret.h
@@ -227,16 +227,22 @@ protected:
     int32_t               mOverrideOffset;
     /**
      * mBlinkCount is used to control the number of times to blink the caret
      * before stopping the blink. This is reset each time we reset the
      * blinking.
      */
     int32_t               mBlinkCount;
     /**
+     * mBlinkRate is the rate of the caret blinking the last time we read it.
+     * It is used as a way to optimize whether we need to reset the blinking
+     * timer.
+     */
+    uint32_t              mBlinkRate;
+    /**
      * mHideCount is not 0, it means that somebody doesn't want the caret
      * to be visible.  See AddForceHide() and RemoveForceHide().
      */
     uint32_t              mHideCount;
 
     /**
      * mIsBlinkOn is true when we're in a blink cycle where the caret is on.
      */