Bug 1947508 - Give some slack to the caret blink timer. r=dholbert

Something like this perhaps? Given the usual caret blink rate this
should be enough. We can reduce the slack if needed.

Differential Revision: https://phabricator.services.mozilla.com/D237768
This commit is contained in:
Emilio Cobos Álvarez
2025-02-12 11:41:01 +00:00
parent 752f67a0b6
commit f326e14b4b
2 changed files with 31 additions and 3 deletions

View File

@@ -601,6 +601,11 @@ nsCaret::NotifySelectionChanged(Document*, Selection* aDomSel, int16_t aReason,
}
void nsCaret::ResetBlinking() {
// How many milliseconds we allow the timer to get off-sync when resetting
// blinking too often. 50 is not likely to be user observable in practice,
// it's ~4 animation frames at 60fps.
static const auto kBlinkTimerSlack = TimeDuration::FromMilliseconds(50);
mIsBlinkOn = true;
if (mReadOnly || !IsVisible()) {
@@ -608,17 +613,28 @@ void nsCaret::ResetBlinking() {
return;
}
const auto blinkTime = LookAndFeel::CaretBlinkTime();
if (blinkTime <= 0) {
const int32_t oldBlinkTime = mBlinkTime;
mBlinkTime = LookAndFeel::CaretBlinkTime();
if (mBlinkTime <= 0) {
StopBlinking();
return;
}
mBlinkCount = LookAndFeel::CaretBlinkCount();
const auto now = TimeStamp::NowLoRes();
const bool mustResetTimer = mBlinkTime != oldBlinkTime ||
mLastBlinkTimerReset.IsNull() ||
(now - mLastBlinkTimerReset) > kBlinkTimerSlack;
if (!mustResetTimer) {
return;
}
if (!mBlinkTimer) {
mBlinkTimer = NS_NewTimer();
}
mBlinkTimer->InitWithNamedFuncCallback(CaretBlinkCallback, this, blinkTime,
mLastBlinkTimerReset = now;
mBlinkTimer->InitWithNamedFuncCallback(CaretBlinkCallback, this, mBlinkTime,
nsITimer::TYPE_REPEATING_SLACK,
"CaretBlinkCallback");
}
@@ -626,6 +642,7 @@ void nsCaret::ResetBlinking() {
void nsCaret::StopBlinking() {
if (mBlinkTimer) {
mBlinkTimer->Cancel();
mLastBlinkTimerReset = TimeStamp();
}
}
@@ -696,6 +713,7 @@ void nsCaret::CaretBlinkCallback(nsITimer* aTimer, void* aClosure) {
if (!theCaret) {
return;
}
theCaret->mLastBlinkTimerReset = TimeStamp();
theCaret->mIsBlinkOn = !theCaret->mIsBlinkOn;
theCaret->SchedulePaint();

View File

@@ -202,6 +202,11 @@ class nsCaret final : public nsISelectionListener {
mozilla::WeakPtr<mozilla::dom::Selection> mDomSelectionWeak;
nsCOMPtr<nsITimer> mBlinkTimer;
// Last time we reset the blink timer. We give it some slack to avoid
// resetting it too often. This gets cleared when CaretBlinkCallback fires,
// because the point of this variable is just to avoid resetting too many
// times in a single blink cycle.
mozilla::TimeStamp mLastBlinkTimerReset;
CaretPosition mCaretPosition;
@@ -214,6 +219,11 @@ class nsCaret final : public nsISelectionListener {
* blinking.
*/
int32_t mBlinkCount = -1;
/**
* Current blink time (the value that LookAndFeel::CaretBlinkTime() gave us
* when we most recently reset our blinking).
*/
int32_t mBlinkTime = -1;
/**
* mHideCount is not 0, it means that somebody doesn't want the caret
* to be visible. See AddForceHide() and RemoveForceHide().