Patch for bug 35296: SetCaretEnabled() takes too long

Patch by Leon.Zhang@sun.com
r=sfraser, sr=kin
This commit is contained in:
henry.jia%sun.com 2003-04-02 05:48:09 +00:00
Родитель e21a8221f4
Коммит b7df6947aa
8 изменённых файлов: 72 добавлений и 43 удалений

Просмотреть файл

@ -746,11 +746,30 @@ nsEditor::EndPlaceHolderTransaction()
NS_PRECONDITION(mPlaceHolderBatch > 0, "zero or negative placeholder batch count when ending batch!"); NS_PRECONDITION(mPlaceHolderBatch > 0, "zero or negative placeholder batch count when ending batch!");
if (mPlaceHolderBatch == 1) if (mPlaceHolderBatch == 1)
{ {
nsCOMPtr<nsIPresShell> ps = do_QueryReferent(mPresShellWeak);
nsCOMPtr<nsICaret> caret;
if (!ps)
return NS_ERROR_FAILURE;
nsresult rv = ps->GetCaret(getter_AddRefs(caret));
if (NS_FAILED(rv))
return rv;
// optimizing drawcaret starts
if (caret) {
caret->SetOptimizeDrawCaret(PR_TRUE);
}
// time to turn off the batch // time to turn off the batch
EndUpdateViewBatch(); EndUpdateViewBatch();
// make sure selection is in view // make sure selection is in view
ScrollSelectionIntoView(PR_FALSE); ScrollSelectionIntoView(PR_FALSE);
// optimizing drawcaret stops
if (caret) {
caret->SetOptimizeDrawCaret(PR_FALSE);
}
if (mSelState) if (mSelState)
{ {
// we saved the selection state, but never got to hand it to placeholder // we saved the selection state, but never got to hand it to placeholder
@ -4340,15 +4359,6 @@ nsresult nsEditor::EndUpdateViewBatch()
if (!caret) if (!caret)
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
StCaretHider caretHider(caret);
nsCOMPtr<nsISelection>selection;
nsresult selectionResult = GetSelection(getter_AddRefs(selection));
if (NS_SUCCEEDED(selectionResult) && selection) {
nsCOMPtr<nsISelectionPrivate>selPrivate(do_QueryInterface(selection));
selPrivate->EndBatchChanges();
}
if (mViewManager) if (mViewManager)
{ {
mUpdateCount--; mUpdateCount--;
@ -4361,6 +4371,8 @@ nsresult nsEditor::EndUpdateViewBatch()
if (NS_FAILED(rv)) if (NS_FAILED(rv))
return rv; return rv;
StCaretHider caretHider(caret);
// Make sure we enable reflowing before we call // Make sure we enable reflowing before we call
// mViewManager->EndUpdateViewBatch(). This will make sure that any // mViewManager->EndUpdateViewBatch(). This will make sure that any
// new updates caused by a reflow, that may happen during the // new updates caused by a reflow, that may happen during the
@ -4386,6 +4398,13 @@ nsresult nsEditor::EndUpdateViewBatch()
} }
} }
nsCOMPtr<nsISelection>selection;
nsresult selectionResult = GetSelection(getter_AddRefs(selection));
if (NS_SUCCEEDED(selectionResult) && selection) {
nsCOMPtr<nsISelectionPrivate>selPrivate(do_QueryInterface(selection));
selPrivate->EndBatchChanges();
}
return NS_OK; return NS_OK;
} }

Просмотреть файл

@ -334,10 +334,6 @@ nsHTMLEditRules::BeforeEdit(PRInt32 action, nsIEditor::EDirection aDirection)
nsrange->NSDetach(); // ditto for mUtilRange. nsrange->NSDetach(); // ditto for mUtilRange.
} }
// turn off caret
nsCOMPtr<nsISelectionController> selCon;
mHTMLEditor->GetSelectionController(getter_AddRefs(selCon));
if (selCon) selCon->SetCaretEnabled(PR_FALSE);
// check that selection is in subtree defined by body node // check that selection is in subtree defined by body node
ConfirmSelectionInBody(); ConfirmSelectionInBody();
// let rules remember the top level action // let rules remember the top level action
@ -365,10 +361,6 @@ nsHTMLEditRules::AfterEdit(PRInt32 action, nsIEditor::EDirection aDirection)
// free up selectionState range item // free up selectionState range item
(mHTMLEditor->mRangeUpdater).DropRangeItem(&mRangeItem); (mHTMLEditor->mRangeUpdater).DropRangeItem(&mRangeItem);
// turn on caret
nsCOMPtr<nsISelectionController> selCon;
mHTMLEditor->GetSelectionController(getter_AddRefs(selCon));
if (selCon) selCon->SetCaretEnabled(PR_TRUE);
/* After inserting text the cursor Bidi level must be set to the level of the inserted text. /* After inserting text the cursor Bidi level must be set to the level of the inserted text.
* This is difficult, because we cannot know what the level is until after the Bidi algorithm * This is difficult, because we cannot know what the level is until after the Bidi algorithm
* is applied to the whole paragraph. * is applied to the whole paragraph.

Просмотреть файл

@ -92,6 +92,7 @@ nsCaret::nsCaret()
, mDrawn(PR_FALSE) , mDrawn(PR_FALSE)
, mReadOnly(PR_FALSE) , mReadOnly(PR_FALSE)
, mShowDuringSelection(PR_FALSE) , mShowDuringSelection(PR_FALSE)
, mOptimizeDrawCaret(PR_FALSE)
, mCachedOffsetValid(PR_FALSE) , mCachedOffsetValid(PR_FALSE)
, mLastCaretFrame(nsnull) , mLastCaretFrame(nsnull)
, mLastCaretView(nsnull) , mLastCaretView(nsnull)
@ -445,6 +446,11 @@ NS_IMETHODIMP nsCaret::DrawAtPosition(nsIDOMNode* aNode, PRInt32 aOffset)
return NS_OK; return NS_OK;
} }
NS_IMETHODIMP nsCaret::SetOptimizeDrawCaret(PRBool aOptimzeDrawCaret)
{
mOptimizeDrawCaret = aOptimzeDrawCaret;
return NS_OK;
}
#ifdef XP_MAC #ifdef XP_MAC
#pragma mark - #pragma mark -
@ -1069,19 +1075,14 @@ void nsCaret::GetCaretRectAndInvert()
{ {
nsRect caretRect = frameRect; nsRect caretRect = frameRect;
// if mCachedOffsetValid, apply cached FrameOffset, else compute it again // if use cache and cache is ready, apply it, else refresh it
if (!mCachedOffsetValid) if (!mOptimizeDrawCaret || !mCachedOffsetValid) {
{ mLastCaretFrame->GetPointFromOffset(presContext, mRendContext,mLastContentOffset, &mCachedFrameOffset);
mLastCaretFrame->GetPointFromOffset(presContext, mRendContext, mLastContentOffset, &mCachedFrameOffset); mCachedOffsetValid = mOptimizeDrawCaret;
// XXX: The following line was commented out to disable the
// offset caching code because it causes bad caret
// placement. (bug 194774)
//
// mCachedOffsetValid = PR_TRUE;
} }
caretRect += mCachedFrameOffset; caretRect += mCachedFrameOffset;
if (mCaretTwipsWidth < 0) // need to re-compute the pixel width if (mCaretTwipsWidth < 0) // need to re-compute the pixel width
{ {
float tDevUnitsToTwips = 15; float tDevUnitsToTwips = 15;

Просмотреть файл

@ -65,6 +65,8 @@ class nsCaret : public nsICaret,
NS_IMETHOD SetVisibilityDuringSelection(PRBool aVisibility); NS_IMETHOD SetVisibilityDuringSelection(PRBool aVisibility);
NS_IMETHOD DrawAtPosition(nsIDOMNode* aNode, PRInt32 aOffset); NS_IMETHOD DrawAtPosition(nsIDOMNode* aNode, PRInt32 aOffset);
NS_IMETHOD SetOptimizeDrawCaret(PRBool aOptimzeDrawCaret);
//nsISelectionListener interface //nsISelectionListener interface
NS_IMETHOD NotifySelectionChanged(nsIDOMDocument *aDoc, nsISelection *aSel, short aReason); NS_IMETHOD NotifySelectionChanged(nsIDOMDocument *aDoc, nsISelection *aSel, short aReason);
@ -103,9 +105,10 @@ protected:
PRPackedBool mReadOnly; // it the caret in readonly state (draws differently) PRPackedBool mReadOnly; // it the caret in readonly state (draws differently)
PRPackedBool mShowDuringSelection; // show when text is selected PRPackedBool mShowDuringSelection; // show when text is selected
PRPackedBool mCachedOffsetValid; //whether the cached frame offset is valid PRPackedBool mOptimizeDrawCaret; // flag for optimizing draw caret
nsPoint mCachedFrameOffset; //cached frame offset PRPackedBool mCachedOffsetValid; // whether the cached frame offset is valid
nsPoint mCachedFrameOffset; // cached frame offset
nsRect mCaretRect; // the last caret rect nsRect mCaretRect; // the last caret rect
nsIFrame* mLastCaretFrame; // store the frame the caret was last drawn in. nsIFrame* mLastCaretFrame; // store the frame the caret was last drawn in.
nsIView* mLastCaretView; // last view that we used for drawing. Cached so we can tell when we need to make a new RC nsIView* mLastCaretView; // last view that we used for drawing. Cached so we can tell when we need to make a new RC

Просмотреть файл

@ -125,6 +125,11 @@ public:
**/ **/
NS_IMETHOD DrawAtPosition(nsIDOMNode* aNode, PRInt32 aOffset) = 0; NS_IMETHOD DrawAtPosition(nsIDOMNode* aNode, PRInt32 aOffset) = 0;
/** SetOptimizeDrawCaret
* To start or stop process of optimizing draw caret
*/
NS_IMETHOD SetOptimizeDrawCaret(PRBool aOptimzeDrawCaret) = 0;
}; };
nsresult nsresult

Просмотреть файл

@ -125,6 +125,11 @@ public:
**/ **/
NS_IMETHOD DrawAtPosition(nsIDOMNode* aNode, PRInt32 aOffset) = 0; NS_IMETHOD DrawAtPosition(nsIDOMNode* aNode, PRInt32 aOffset) = 0;
/** SetOptimizeDrawCaret
* To start or stop process of optimizing draw caret
*/
NS_IMETHOD SetOptimizeDrawCaret(PRBool aOptimzeDrawCaret) = 0;
}; };
nsresult nsresult

Просмотреть файл

@ -92,6 +92,7 @@ nsCaret::nsCaret()
, mDrawn(PR_FALSE) , mDrawn(PR_FALSE)
, mReadOnly(PR_FALSE) , mReadOnly(PR_FALSE)
, mShowDuringSelection(PR_FALSE) , mShowDuringSelection(PR_FALSE)
, mOptimizeDrawCaret(PR_FALSE)
, mCachedOffsetValid(PR_FALSE) , mCachedOffsetValid(PR_FALSE)
, mLastCaretFrame(nsnull) , mLastCaretFrame(nsnull)
, mLastCaretView(nsnull) , mLastCaretView(nsnull)
@ -445,6 +446,11 @@ NS_IMETHODIMP nsCaret::DrawAtPosition(nsIDOMNode* aNode, PRInt32 aOffset)
return NS_OK; return NS_OK;
} }
NS_IMETHODIMP nsCaret::SetOptimizeDrawCaret(PRBool aOptimzeDrawCaret)
{
mOptimizeDrawCaret = aOptimzeDrawCaret;
return NS_OK;
}
#ifdef XP_MAC #ifdef XP_MAC
#pragma mark - #pragma mark -
@ -1069,19 +1075,14 @@ void nsCaret::GetCaretRectAndInvert()
{ {
nsRect caretRect = frameRect; nsRect caretRect = frameRect;
// if mCachedOffsetValid, apply cached FrameOffset, else compute it again // if use cache and cache is ready, apply it, else refresh it
if (!mCachedOffsetValid) if (!mOptimizeDrawCaret || !mCachedOffsetValid) {
{ mLastCaretFrame->GetPointFromOffset(presContext, mRendContext,mLastContentOffset, &mCachedFrameOffset);
mLastCaretFrame->GetPointFromOffset(presContext, mRendContext, mLastContentOffset, &mCachedFrameOffset); mCachedOffsetValid = mOptimizeDrawCaret;
// XXX: The following line was commented out to disable the
// offset caching code because it causes bad caret
// placement. (bug 194774)
//
// mCachedOffsetValid = PR_TRUE;
} }
caretRect += mCachedFrameOffset; caretRect += mCachedFrameOffset;
if (mCaretTwipsWidth < 0) // need to re-compute the pixel width if (mCaretTwipsWidth < 0) // need to re-compute the pixel width
{ {
float tDevUnitsToTwips = 15; float tDevUnitsToTwips = 15;

Просмотреть файл

@ -65,6 +65,8 @@ class nsCaret : public nsICaret,
NS_IMETHOD SetVisibilityDuringSelection(PRBool aVisibility); NS_IMETHOD SetVisibilityDuringSelection(PRBool aVisibility);
NS_IMETHOD DrawAtPosition(nsIDOMNode* aNode, PRInt32 aOffset); NS_IMETHOD DrawAtPosition(nsIDOMNode* aNode, PRInt32 aOffset);
NS_IMETHOD SetOptimizeDrawCaret(PRBool aOptimzeDrawCaret);
//nsISelectionListener interface //nsISelectionListener interface
NS_IMETHOD NotifySelectionChanged(nsIDOMDocument *aDoc, nsISelection *aSel, short aReason); NS_IMETHOD NotifySelectionChanged(nsIDOMDocument *aDoc, nsISelection *aSel, short aReason);
@ -103,9 +105,10 @@ protected:
PRPackedBool mReadOnly; // it the caret in readonly state (draws differently) PRPackedBool mReadOnly; // it the caret in readonly state (draws differently)
PRPackedBool mShowDuringSelection; // show when text is selected PRPackedBool mShowDuringSelection; // show when text is selected
PRPackedBool mCachedOffsetValid; //whether the cached frame offset is valid PRPackedBool mOptimizeDrawCaret; // flag for optimizing draw caret
nsPoint mCachedFrameOffset; //cached frame offset PRPackedBool mCachedOffsetValid; // whether the cached frame offset is valid
nsPoint mCachedFrameOffset; // cached frame offset
nsRect mCaretRect; // the last caret rect nsRect mCaretRect; // the last caret rect
nsIFrame* mLastCaretFrame; // store the frame the caret was last drawn in. nsIFrame* mLastCaretFrame; // store the frame the caret was last drawn in.
nsIView* mLastCaretView; // last view that we used for drawing. Cached so we can tell when we need to make a new RC nsIView* mLastCaretView; // last view that we used for drawing. Cached so we can tell when we need to make a new RC