Flag nsCaret::mPendingDraw if the on-cycle draw was suppressed; update the caret when the pres shell tells us that painting is unsuppressed.
b=520720 r=roc
--- a/layout/base/nsCaret.cpp
+++ b/layout/base/nsCaret.cpp
@@ -86,16 +86,17 @@ static const PRInt32 kMinBidiIndicatorPi
//-----------------------------------------------------------------------------
nsCaret::nsCaret()
: mPresShell(nsnull)
, mBlinkRate(500)
, mVisible(PR_FALSE)
, mDrawn(PR_FALSE)
+, mPendingDraw(PR_FALSE)
, mReadOnly(PR_FALSE)
, mShowDuringSelection(PR_FALSE)
, mIgnoreUserModify(PR_TRUE)
#ifdef IBMBIDI
, mKeyboardRTL(PR_FALSE)
, mLastBidiLevel(0)
#endif
, mLastContentOffset(0)
@@ -956,21 +957,29 @@ void nsCaret::GetViewForRendering(nsIFra
}
}
}
}
*outRenderingView = returnView;
}
-nsresult nsCaret::CheckCaretDrawingState()
+nsresult nsCaret::CheckCaretDrawingState()
{
- // If the caret's drawn when it shouldn't be, erase it.
- if (mDrawn && (!mVisible || !MustDrawCaret(PR_TRUE)))
- EraseCaret();
+ if (mDrawn) {
+ // The caret is drawn; if it shouldn't be, erase it.
+ if (!mVisible || !MustDrawCaret(PR_TRUE))
+ EraseCaret();
+ }
+ else
+ {
+ // The caret is not drawn; if it should be, draw it.
+ if (mPendingDraw && (mVisible && MustDrawCaret(PR_TRUE)))
+ DrawCaret(PR_TRUE);
+ }
return NS_OK;
}
/*-----------------------------------------------------------------------------
MustDrawCaret
Find out if we need to do any caret drawing. This returns true if
@@ -978,32 +987,24 @@ nsresult nsCaret::CheckCaretDrawingState
a) The caret has been drawn, and we need to erase it.
b) The caret is not drawn, and the selection is collapsed.
c) The caret is not hidden due to open XUL popups
(see IsMenuPopupHidingCaret()).
----------------------------------------------------------------------------- */
PRBool nsCaret::MustDrawCaret(PRBool aIgnoreDrawnState)
{
- nsCOMPtr<nsIPresShell> presShell = do_QueryReferent(mPresShell);
- if (presShell) {
- PRBool isPaintingSuppressed;
- presShell->IsPaintingSuppressed(&isPaintingSuppressed);
- if (isPaintingSuppressed)
- return PR_FALSE;
- }
-
if (!aIgnoreDrawnState && mDrawn)
return PR_TRUE;
nsCOMPtr<nsISelection> domSelection = do_QueryReferent(mDomSelectionWeak);
if (!domSelection)
return PR_FALSE;
+
PRBool isCollapsed;
-
if (NS_FAILED(domSelection->GetIsCollapsed(&isCollapsed)))
return PR_FALSE;
if (mShowDuringSelection)
return PR_TRUE; // show the caret even in selections
if (IsMenuPopupHidingCaret())
return PR_FALSE;
@@ -1054,28 +1055,39 @@ PRBool nsCaret::IsMenuPopupHidingCaret()
}
}
#endif
// There are no open menu popups, no need to hide the caret.
return PR_FALSE;
}
-/*-----------------------------------------------------------------------------
-
- DrawCaret
-
------------------------------------------------------------------------------ */
-
void nsCaret::DrawCaret(PRBool aInvalidate)
{
- // do we need to draw the caret at all?
+ // Do we need to draw the caret at all?
if (!MustDrawCaret(PR_FALSE))
return;
+ // Can we draw the caret now?
+ nsCOMPtr<nsIPresShell> presShell = do_QueryReferent(mPresShell);
+ NS_ENSURE_TRUE(presShell, /**/);
+ {
+ PRBool isPaintingSuppressed;
+ presShell->IsPaintingSuppressed(&isPaintingSuppressed);
+ if (isPaintingSuppressed)
+ {
+ if (!mDrawn)
+ mPendingDraw = PR_TRUE;
+
+ // PresShell::UnsuppressAndInvalidate() will call CheckCaretDrawingState()
+ // to get us drawn.
+ return;
+ }
+ }
+
nsCOMPtr<nsIDOMNode> node;
PRInt32 offset;
nsFrameSelection::HINT hint;
PRUint8 bidiLevel;
if (!mDrawn)
{
nsCOMPtr<nsISelection> domSelection = do_QueryReferent(mDomSelectionWeak);
@@ -1097,17 +1109,19 @@ void nsCaret::DrawCaret(PRBool aInvalida
return;
if (NS_FAILED(domSelection->GetFocusOffset(&offset)))
return;
nsCOMPtr<nsFrameSelection> frameSelection = GetFrameSelection();
if (!frameSelection)
return;
+
bidiLevel = frameSelection->GetCaretBidiLevel();
+ mPendingDraw = PR_FALSE;
}
else
{
if (!mLastContent)
{
mDrawn = PR_FALSE;
return;
}
--- a/layout/base/nsCaret.h
+++ b/layout/base/nsCaret.h
@@ -276,23 +276,24 @@ protected:
nsWeakPtr mPresShell;
nsWeakPtr mDomSelectionWeak;
nsCOMPtr<nsITimer> mBlinkTimer;
nsCOMPtr<nsIRenderingContext> mRendContext;
// XXX these fields should go away and the values be acquired as needed,
// probably by ComputeMetrics.
- PRUint32 mBlinkRate; // time for one cyle (off then on), in milliseconds
+ PRUint32 mBlinkRate; // time for one cyle (on then off), in milliseconds
nscoord mCaretWidthCSSPx; // caret width in CSS pixels
float mCaretAspectRatio; // caret width/height aspect ratio
PRPackedBool mVisible; // is the caret blinking
PRPackedBool mDrawn; // Denotes when the caret is physically drawn on the screen.
+ PRPackedBool mPendingDraw; // True when the last on-state draw was suppressed.
PRPackedBool mReadOnly; // it the caret in readonly state (draws differently)
PRPackedBool mShowDuringSelection; // show when text is selected
PRPackedBool mIgnoreUserModify;
#ifdef IBMBIDI
PRPackedBool mKeyboardRTL; // is the keyboard language right-to-left
--- a/layout/base/nsPresShell.cpp
+++ b/layout/base/nsPresShell.cpp
@@ -4636,16 +4636,20 @@ PresShell::UnsuppressAndInvalidate()
mPaintingSuppressed = PR_FALSE;
nsIFrame* rootFrame = FrameManager()->GetRootFrame();
if (rootFrame) {
// let's assume that outline on a root frame is not supported
nsRect rect(nsPoint(0, 0), rootFrame->GetSize());
rootFrame->Invalidate(rect);
+ if (mCaretEnabled && mCaret) {
+ mCaret->CheckCaretDrawingState();
+ }
+
mPresContext->RootPresContext()->UpdatePluginGeometry(rootFrame);
}
// now that painting is unsuppressed, focus may be set on the document
nsPIDOMWindow *win = mDocument->GetWindow();
if (win)
win->SetReadyForFocus();