From fa152a3def2ba146c9d400b6aacd45dc3bde1b07 Mon Sep 17 00:00:00 2001 From: "kin%netscape.com" Date: Thu, 13 Jun 2002 20:35:12 +0000 Subject: [PATCH] Partial fix for bug 141900 (Text entry fields in forms excruciatingly slow.) mozilla/content/base/public/nsISelectionController.idl mozilla/content/base/src/nsSelection.cpp mozilla/editor/composer/src/nsEditorShell.cpp mozilla/editor/idl/nsIPlaintextEditor.idl mozilla/editor/libeditor/base/nsEditor.cpp mozilla/editor/libeditor/base/nsEditor.h mozilla/editor/libeditor/html/nsHTMLDataTransfer.cpp mozilla/editor/libeditor/html/nsHTMLEditor.cpp mozilla/editor/libeditor/text/nsEditorEventListeners.cpp mozilla/editor/libeditor/text/nsPlaintextDataTransfer.cpp mozilla/editor/libeditor/text/nsPlaintextEditor.cpp mozilla/editor/txtsvc/src/nsTextServicesDocument.cpp mozilla/editor/ui/dialogs/content/EdTableProps.js mozilla/embedding/components/find/src/nsWebBrowserFind.cpp mozilla/extensions/xmlterm/base/mozXMLTermSession.cpp mozilla/layout/base/public/nsIFrameSelection.h mozilla/layout/html/base/src/nsPresShell.cpp mozilla/layout/html/forms/src/nsGfxTextControlFrame2.cpp mozilla/mailnews/compose/src/nsMsgCompose.cpp mozilla/xpfe/browser/resources/content/viewPartialSource.js - Added aIsSynchronous arg to the ScrollSelectionIntoView() method of nsISelectionController and nsIFrameSelection. Updated all callers to pass new arg. - Modified selection to post a plevent to call which does the call to ScrollIntoView() in the async ScrollIntoView() case. - Edits in text widgets now use asynchronous reflow, paint, and scroll processing full time. - Removed redundant ScrollSelectionIntoView() calls in the editor event listeners. - Editor IME code now forced to flush reflows and paints before getting caret coordinates. r=jfrancis@netscape.com sr=waterson@netscape.com git-svn-id: svn://10.0.0.236/trunk@123236 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/editor/composer/src/nsEditorShell.cpp | 2 +- mozilla/editor/idl/nsIPlaintextEditor.idl | 18 ++- mozilla/editor/libeditor/base/nsEditor.cpp | 119 ++++++++++-------- mozilla/editor/libeditor/base/nsEditor.h | 17 ++- .../libeditor/html/nsHTMLDataTransfer.cpp | 6 +- .../editor/libeditor/html/nsHTMLEditor.cpp | 56 +++++++-- .../libeditor/text/nsEditorEventListeners.cpp | 25 +--- .../text/nsPlaintextDataTransfer.cpp | 6 +- .../libeditor/text/nsPlaintextEditor.cpp | 49 ++++++-- .../txtsvc/nsTextServicesDocument.cpp | 2 +- .../txtsvc/src/nsTextServicesDocument.cpp | 2 +- .../editor/ui/dialogs/content/EdTableProps.js | 2 +- .../components/find/src/nsWebBrowserFind.cpp | 2 +- .../xmlterm/base/mozXMLTermSession.cpp | 9 +- mozilla/layout/base/nsIFrameSelection.h | 4 +- mozilla/layout/base/nsPresShell.cpp | 9 +- .../layout/base/public/nsIFrameSelection.h | 4 +- mozilla/layout/html/base/src/nsPresShell.cpp | 9 +- .../html/forms/src/nsGfxTextControlFrame2.cpp | 16 ++- mozilla/mailnews/compose/src/nsMsgCompose.cpp | 4 +- .../resources/content/viewPartialSource.js | 3 +- 21 files changed, 221 insertions(+), 143 deletions(-) diff --git a/mozilla/editor/composer/src/nsEditorShell.cpp b/mozilla/editor/composer/src/nsEditorShell.cpp index 68420376e5b..9f41f330ec1 100644 --- a/mozilla/editor/composer/src/nsEditorShell.cpp +++ b/mozilla/editor/composer/src/nsEditorShell.cpp @@ -940,7 +940,7 @@ nsEditorShell::ScrollSelectionIntoView() if (!selCon) return NS_ERROR_UNEXPECTED; return selCon->ScrollSelectionIntoView(nsISelectionController::SELECTION_NORMAL, - nsISelectionController::SELECTION_FOCUS_REGION); + nsISelectionController::SELECTION_FOCUS_REGION, PR_TRUE); } NS_IMETHODIMP diff --git a/mozilla/editor/idl/nsIPlaintextEditor.idl b/mozilla/editor/idl/nsIPlaintextEditor.idl index c9a8fa2c75c..2c0653d9373 100644 --- a/mozilla/editor/idl/nsIPlaintextEditor.idl +++ b/mozilla/editor/idl/nsIPlaintextEditor.idl @@ -56,11 +56,10 @@ interface nsIPlaintextEditor : nsISupports const short eEditorDisabledBit = 4; /* all events are disabled (like scrolling). Editor will not accept focus. */ const short eEditorFilterInputBit = 5; /* text input is limited to certain character types, use mFilter */ const short eEditorMailBit = 6; /* use mail-compose editting rules */ - const short eEditorDisableForcedUpdatesBit = 7; /* prevent immediate view refreshes */ - const short eEditorDisableForcedReflowsBit = 8; /* prevent immediate reflows */ - const short eEditorEnableWrapHackBit = 9; /* allow the editor to set font: monospace on the root node */ - const short eEditorWidgetBit = 10; /* bit for widgets */ - const short eEditorNoCSSBit = 11; /* this HTML editor should not create css styles */ + const short eEditorUseAsyncUpdatesBit = 7; /* prevent immediate reflows and view refreshes */ + const short eEditorEnableWrapHackBit = 8; /* allow the editor to set font: monospace on the root node */ + const short eEditorWidgetBit = 9; /* bit for widgets */ + const short eEditorNoCSSBit = 10; /* this HTML editor should not create css styles */ const long eEditorPlaintextMask = 1; const long eEditorSingleLineMask = 2; @@ -69,11 +68,10 @@ interface nsIPlaintextEditor : nsISupports const long eEditorDisabledMask = 16; const long eEditorFilterInputMask = 32; const long eEditorMailMask = 64; - const long eEditorDisableForcedUpdatesMask = 128; - const long eEditorDisableForcedReflowsMask = 256; - const long eEditorEnableWrapHackMask = 512; - const long eEditorWidgetMask = 1024; - const long eEditorNoCSSMask = 2048; + const long eEditorUseAsyncUpdatesMask = 128; + const long eEditorEnableWrapHackMask = 256; + const long eEditorWidgetMask = 512; + const long eEditorNoCSSMask = 1024; /** * The length of the contents in characters. diff --git a/mozilla/editor/libeditor/base/nsEditor.cpp b/mozilla/editor/libeditor/base/nsEditor.cpp index 3a8c7693c5a..2a2efaa1031 100644 --- a/mozilla/editor/libeditor/base/nsEditor.cpp +++ b/mozilla/editor/libeditor/base/nsEditor.cpp @@ -102,20 +102,10 @@ #include "nsINodeInfo.h" #include "nsINameSpaceManager.h" -// #define HACK_FORCE_REDRAW 1 - #include "nsEditor.h" #include "nsEditorUtils.h" #include "nsISelectionDisplay.h" -#ifdef HACK_FORCE_REDRAW -// INCLUDES FOR EVIL HACK TO FOR REDRAW -// BEGIN -#include "nsIViewManager.h" -#include "nsIView.h" -// END -#endif - static NS_DEFINE_CID(kCRangeCID, NS_RANGE_CID); static NS_DEFINE_CID(kCContentIteratorCID, NS_CONTENTITERATOR_CID); static NS_DEFINE_CID(kCDOMRangeCID, NS_RANGE_CID); @@ -711,9 +701,7 @@ nsEditor::EndPlaceHolderTransaction() // time to turn off the batch EndUpdateViewBatch(); // make sure selection is in view - nsCOMPtr selCon; - if (NS_SUCCEEDED(GetSelectionController(getter_AddRefs(selCon))) && selCon) - selCon->ScrollSelectionIntoView(nsISelectionController::SELECTION_NORMAL, nsISelectionController::SELECTION_FOCUS_REGION); + ScrollSelectionIntoView(PR_FALSE); if (mSelState) { @@ -841,7 +829,6 @@ NS_IMETHODIMP nsEditor::BeginningOfDocument() if (NS_FAILED(result)) return result; result = selection->Collapse(parentNode, offsetInParent); } - ScrollIntoView(PR_TRUE); } else { @@ -1837,6 +1824,43 @@ nsEditor::QueryComposition(nsTextEventReply* aReply) if (NS_SUCCEEDED(result) && caretP) { if (aReply) { caretP->SetCaretDOMSelection(selection); + + // XXX_kin: BEGIN HACK! HACK! HACK! + // XXX_kin: + // XXX_kin: This is lame! The IME stuff needs caret coordinates + // XXX_kin: synchronously, but the editor could be using async + // XXX_kin: updates (reflows and paints) for performance reasons. + // XXX_kin: In order to give IME what it needs, we have to temporarily + // XXX_kin: switch to sync updating during this call so that the + // XXX_kin: nsAutoUpdateViewBatch can force sync reflows and paints + // XXX_kin: so that we get back accurate caret coordinates. + + PRUint32 flags = 0; + + if (NS_SUCCEEDED(GetFlags(&flags)) && + (flags & nsIPlaintextEditor::eEditorUseAsyncUpdatesMask)) + { + PRBool restoreFlags = PR_FALSE; + + if (NS_SUCCEEDED(SetFlags(flags & (~nsIPlaintextEditor::eEditorUseAsyncUpdatesMask)))) + { + // Scope the viewBatch within this |if| block so that we + // force synchronous reflows and paints before restoring + // our editor flags below. + + nsAutoUpdateViewBatch viewBatch(this); + restoreFlags = PR_TRUE; + } + + // Restore the previous set of flags! + + if (restoreFlags) + SetFlags(flags); + } + + + // XXX_kin: END HACK! HACK! HACK! + result = caretP->GetCaretCoordinates(nsICaret::eIMECoordinates, selection, &(aReply->mCursorPosition), &(aReply->mCursorIsCollapsed)); } @@ -2221,9 +2245,33 @@ nsEditor::CloneAttributes(nsIDOMNode *aDestNode, nsIDOMNode *aSourceNode) #pragma mark - #endif -NS_IMETHODIMP nsEditor::ScrollIntoView(PRBool aScrollToBegin) +NS_IMETHODIMP nsEditor::ScrollSelectionIntoView(PRBool aScrollToAnchor) { - return NS_ERROR_NOT_IMPLEMENTED; + nsCOMPtr selCon; + if (NS_SUCCEEDED(GetSelectionController(getter_AddRefs(selCon))) && selCon) + { + PRInt16 region = nsISelectionController::SELECTION_FOCUS_REGION; + + if (aScrollToAnchor) + region = nsISelectionController::SELECTION_ANCHOR_REGION; + + PRBool syncScroll = PR_TRUE; + PRUint32 flags = 0; + + if (NS_SUCCEEDED(GetFlags(&flags))) + { + // If the editor is relying on asynchronous reflows, we have + // to use asynchronous requests to scroll, so that the scrolling happens + // after reflow requests are processed. + + syncScroll = !(flags & nsIPlaintextEditor::eEditorUseAsyncUpdatesMask); + } + + selCon->ScrollSelectionIntoView(nsISelectionController::SELECTION_NORMAL, + region, syncScroll); + } + + return NS_OK; } /** static helper method */ @@ -3709,32 +3757,6 @@ NS_IMETHODIMP nsEditor::ResetModificationCount() return NS_OK; } - -void nsEditor::HACKForceRedraw() -{ -#ifdef HACK_FORCE_REDRAW -// XXXX: Horrible hack! We are doing this because -// of an error in Gecko which is not rendering the -// document after a change via the DOM - gpk 2/11/99 - // BEGIN HACK!!! - nsCOMPtr shell; - - GetPresShell(getter_AddRefs(shell)); - if (shell) { - nsCOMPtr viewmgr; - - shell->GetViewManager(getter_AddRefs(viewmgr)); - if (viewmgr) { - nsIView* view; - viewmgr->GetRootView(view); // views are not refCounted - if (view) { - viewmgr->UpdateView(view,NS_VMREFRESH_IMMEDIATE); - } - } - } - // END HACK -#endif -} //END nsEditor Private methods @@ -4191,11 +4213,7 @@ nsresult nsEditor::BeginUpdateViewBatch() { if (0==mUpdateCount) { -#ifdef HACK_FORCE_REDRAW - mViewManager->DisableRefresh(); -#else mViewManager->BeginUpdateViewBatch(); -#endif nsCOMPtr presShell; rv = GetPresShell(getter_AddRefs(presShell)); if (NS_SUCCEEDED(rv) && presShell) @@ -4259,7 +4277,7 @@ nsresult nsEditor::EndUpdateViewBatch() PRBool forceReflow = PR_TRUE; - if (flags & nsIPlaintextEditor::eEditorDisableForcedReflowsMask) + if (flags & nsIPlaintextEditor::eEditorUseAsyncUpdatesMask) forceReflow = PR_FALSE; nsCOMPtr presShell; @@ -4269,15 +4287,10 @@ nsresult nsEditor::EndUpdateViewBatch() PRUint32 updateFlag = NS_VMREFRESH_IMMEDIATE; - if (flags & nsIPlaintextEditor::eEditorDisableForcedUpdatesMask) + if (flags & nsIPlaintextEditor::eEditorUseAsyncUpdatesMask) updateFlag = NS_VMREFRESH_NO_SYNC; -#ifdef HACK_FORCE_REDRAW - mViewManager->EnableRefresh(updateFlag); - HACKForceRedraw(); -#else mViewManager->EndUpdateViewBatch(updateFlag); -#endif } } diff --git a/mozilla/editor/libeditor/base/nsEditor.h b/mozilla/editor/libeditor/base/nsEditor.h index 86d4692c7e4..eae2525acae 100644 --- a/mozilla/editor/libeditor/base/nsEditor.h +++ b/mozilla/editor/libeditor/base/nsEditor.h @@ -297,12 +297,17 @@ protected: /* Helper for output routines -- we expect subclasses to override this */ NS_IMETHOD GetWrapWidth(PRInt32* aWrapCol); -// XXXX: Horrible hack! We are doing this because -// of an error in Gecko which is not rendering the -// document after a change via the DOM - gpk 2/13/99 - void HACKForceRedraw(void); - - NS_IMETHOD ScrollIntoView(PRBool aScrollToBegin); + /** helper method for scrolling the selection into view after + * an edit operation. aScrollToAnchor should be PR_TRUE if you + * want to scroll to the point where the selection was started. + * If PR_FALSE, it attempts to scroll the end of the selection into view. + * + * Editor methods *should* call this method instead of the versions + * in the various selection interfaces, since this version makes sure + * that the editor's sync/async settings for reflowing, painting, and + * scrolling match. + */ + NS_IMETHOD ScrollSelectionIntoView(PRBool aScrollToAnchor); // stub. see comment in source. virtual PRBool IsBlockNode(nsIDOMNode *aNode); diff --git a/mozilla/editor/libeditor/html/nsHTMLDataTransfer.cpp b/mozilla/editor/libeditor/html/nsHTMLDataTransfer.cpp index af87456cdf4..404f5c0f673 100644 --- a/mozilla/editor/libeditor/html/nsHTMLDataTransfer.cpp +++ b/mozilla/editor/libeditor/html/nsHTMLDataTransfer.cpp @@ -900,11 +900,7 @@ NS_IMETHODIMP nsHTMLEditor::InsertFromTransferable(nsITransferable *transferable // Try to scroll the selection into view if the paste/drop succeeded if (NS_SUCCEEDED(rv)) - { - nsCOMPtr selCon; - if (NS_SUCCEEDED(GetSelectionController(getter_AddRefs(selCon))) && selCon) - selCon->ScrollSelectionIntoView(nsISelectionController::SELECTION_NORMAL, nsISelectionController::SELECTION_FOCUS_REGION); - } + ScrollSelectionIntoView(PR_FALSE); return rv; } diff --git a/mozilla/editor/libeditor/html/nsHTMLEditor.cpp b/mozilla/editor/libeditor/html/nsHTMLEditor.cpp index efdec9f4d26..14a93af93cf 100644 --- a/mozilla/editor/libeditor/html/nsHTMLEditor.cpp +++ b/mozilla/editor/libeditor/html/nsHTMLEditor.cpp @@ -1199,7 +1199,11 @@ NS_IMETHODIMP nsHTMLEditor::HandleKeyPress(nsIDOMKeyEvent* aKeyEvent) PRBool bHandled = PR_FALSE; if (nsHTMLEditUtils::IsTableElement(blockParent)) + { res = TabInTable(isShift, &bHandled); + if (bHandled) + ScrollSelectionIntoView(PR_FALSE); + } else if (nsHTMLEditUtils::IsListItem(blockParent)) { nsAutoString indentstr; @@ -3764,8 +3768,9 @@ NS_IMETHODIMP nsHTMLEditor::SetCompositionString(const nsAString& aCompositionString, nsIPrivateTextRangeList* aTextRangeList,nsTextEventReply* aReply) { NS_ASSERTION(aTextRangeList, "null ptr"); - if(nsnull == aTextRangeList) - return NS_ERROR_NULL_POINTER; + if (nsnull == aTextRangeList) + return NS_ERROR_NULL_POINTER; + nsCOMPtr caretP; // workaround for windows ime bug 23558: we get every ime event twice. @@ -3783,9 +3788,39 @@ nsHTMLEditor::SetCompositionString(const nsAString& aCompositionString, nsIPriva mIMETextRangeList = aTextRangeList; + if (!mPresShellWeak) + return NS_ERROR_NOT_INITIALIZED; + + nsCOMPtr ps = do_QueryReferent(mPresShellWeak); + if (!ps) + return NS_ERROR_NOT_INITIALIZED; + + // XXX_kin: BEGIN HACK! HACK! HACK! + // XXX_kin: + // XXX_kin: This is lame! The IME stuff needs caret coordinates + // XXX_kin: synchronously, but the editor could be using async + // XXX_kin: updates (reflows and paints) for performance reasons. + // XXX_kin: In order to give IME what it needs, we have to temporarily + // XXX_kin: switch to sync updating during this call so that the + // XXX_kin: nsAutoPlaceHolderBatch can force sync reflows, paints, + // XXX_kin: and selection scrolling, so that we get back accurate + // XXX_kin: caret coordinates. + + PRUint32 flags = 0; + PRBool restoreFlags = PR_FALSE; + + if (NS_SUCCEEDED(GetFlags(&flags)) && + (flags & nsIPlaintextEditor::eEditorUseAsyncUpdatesMask)) + { + if (NS_SUCCEEDED(SetFlags(flags & (~nsIPlaintextEditor::eEditorUseAsyncUpdatesMask)))) + restoreFlags = PR_TRUE; + } + + // XXX_kin: END HACK! HACK! HACK! + // we need the nsAutoPlaceHolderBatch destructor called before hitting // GetCaretCoordinates so the states in Frame system sync with content - // therefore, we put the nsAutoPlaceHolderBatch into a inner block + // therefore, we put the nsAutoPlaceHolderBatch into an inner block { nsAutoPlaceHolderBatch batch(this, gIMETxnName); @@ -3793,11 +3828,6 @@ nsHTMLEditor::SetCompositionString(const nsAString& aCompositionString, nsIPriva mIMEBufferLength = aCompositionString.Length(); - if (!mPresShellWeak) - return NS_ERROR_NOT_INITIALIZED; - nsCOMPtr ps = do_QueryReferent(mPresShellWeak); - if (!ps) - return NS_ERROR_NOT_INITIALIZED; ps->GetCaret(getter_AddRefs(caretP)); caretP->SetCaretDOMSelection(selection); @@ -3807,6 +3837,16 @@ nsHTMLEditor::SetCompositionString(const nsAString& aCompositionString, nsIPriva mIMETextNode = nsnull; } } + + // XXX_kin: BEGIN HACK! HACK! HACK! + // XXX_kin: + // XXX_kin: Restore the previous set of flags! + + if (restoreFlags) + SetFlags(flags); + + // XXX_kin: END HACK! HACK! HACK! + result = caretP->GetCaretCoordinates(nsICaret::eIMECoordinates, selection, &(aReply->mCursorPosition), &(aReply->mCursorIsCollapsed)); NS_ASSERTION(NS_SUCCEEDED(result), "cannot get caret position"); diff --git a/mozilla/editor/libeditor/text/nsEditorEventListeners.cpp b/mozilla/editor/libeditor/text/nsEditorEventListeners.cpp index f259288b02f..fd1e18fecd0 100644 --- a/mozilla/editor/libeditor/text/nsEditorEventListeners.cpp +++ b/mozilla/editor/libeditor/text/nsEditorEventListeners.cpp @@ -88,8 +88,6 @@ static NS_DEFINE_CID(kPrefServiceCID, NS_PREF_CID); //#define DEBUG_IME -static nsresult ScrollSelectionIntoView(nsIEditor *aEditor); - /* * nsTextEditorKeyListener implementation */ @@ -238,7 +236,6 @@ nsTextEditorKeyListener::KeyPress(nsIDOMEvent* aKeyEvent) return NS_OK; mEditor->DeleteSelection(nsIEditor::ePrevious); - ScrollSelectionIntoView(mEditor); aKeyEvent->PreventDefault(); // consumed return NS_OK; break; @@ -254,7 +251,6 @@ nsTextEditorKeyListener::KeyPress(nsIDOMEvent* aKeyEvent) if (isAnyModifierKeyButShift || isShiftModifierKey) return NS_OK; mEditor->DeleteSelection(nsIEditor::eNext); - ScrollSelectionIntoView(mEditor); aKeyEvent->PreventDefault(); // consumed return NS_OK; break; @@ -270,7 +266,6 @@ nsTextEditorKeyListener::KeyPress(nsIDOMEvent* aKeyEvent) // else we insert the tab straight through textEditor->HandleKeyPress(keyEvent); - ScrollSelectionIntoView(mEditor); aKeyEvent->PreventDefault(); // consumed return NS_OK; @@ -282,15 +277,13 @@ nsTextEditorKeyListener::KeyPress(nsIDOMEvent* aKeyEvent) if (!(flags & nsIPlaintextEditor::eEditorSingleLineMask)) { textEditor->HandleKeyPress(keyEvent); - ScrollSelectionIntoView(mEditor); aKeyEvent->PreventDefault(); // consumed } return NS_OK; } } - if (NS_SUCCEEDED(textEditor->HandleKeyPress(keyEvent))) - ScrollSelectionIntoView(mEditor); + textEditor->HandleKeyPress(keyEvent); return NS_OK; // we don't PreventDefault() here or keybindings like control-x won't work } @@ -303,21 +296,6 @@ nsTextEditorKeyListener::ProcessShortCutKeys(nsIDOMEvent* aKeyEvent, PRBool& aPr return NS_OK; } -nsresult -ScrollSelectionIntoView(nsIEditor *aEditor) -{ - if (! aEditor) - return NS_ERROR_NULL_POINTER; - - nsCOMPtr selCon; - - nsresult result = aEditor->GetSelectionController(getter_AddRefs(selCon)); - - if (NS_FAILED(result) || ! selCon) - return result ? result: NS_ERROR_FAILURE; - - return selCon->ScrollSelectionIntoView(nsISelectionController::SELECTION_NORMAL, nsISelectionController::SELECTION_FOCUS_REGION); -} /* * nsTextEditorMouseListener implementation @@ -596,7 +574,6 @@ nsTextEditorTextListener::HandleText(nsIDOMEvent* aTextEvent) } } result = imeEditor->SetCompositionString(composedText,textRangeList,textEventReply); - ScrollSelectionIntoView(mEditor); } return result; } diff --git a/mozilla/editor/libeditor/text/nsPlaintextDataTransfer.cpp b/mozilla/editor/libeditor/text/nsPlaintextDataTransfer.cpp index abc27d10d23..5a09cb2a28b 100644 --- a/mozilla/editor/libeditor/text/nsPlaintextDataTransfer.cpp +++ b/mozilla/editor/libeditor/text/nsPlaintextDataTransfer.cpp @@ -182,11 +182,7 @@ NS_IMETHODIMP nsPlaintextEditor::InsertTextFromTransferable(nsITransferable *tra // Try to scroll the selection into view if the paste/drop succeeded if (NS_SUCCEEDED(rv)) - { - nsCOMPtr selCon; - if (NS_SUCCEEDED(GetSelectionController(getter_AddRefs(selCon))) && selCon) - selCon->ScrollSelectionIntoView(nsISelectionController::SELECTION_NORMAL, nsISelectionController::SELECTION_FOCUS_REGION); - } + ScrollSelectionIntoView(PR_FALSE); return rv; } diff --git a/mozilla/editor/libeditor/text/nsPlaintextEditor.cpp b/mozilla/editor/libeditor/text/nsPlaintextEditor.cpp index 7cc1c64aa5a..9d38d6dae12 100644 --- a/mozilla/editor/libeditor/text/nsPlaintextEditor.cpp +++ b/mozilla/editor/libeditor/text/nsPlaintextEditor.cpp @@ -1886,8 +1886,9 @@ NS_IMETHODIMP nsPlaintextEditor::SetCompositionString(const nsAString& aCompositionString, nsIPrivateTextRangeList* aTextRangeList,nsTextEventReply* aReply) { NS_ASSERTION(aTextRangeList, "null ptr"); - if(nsnull == aTextRangeList) - return NS_ERROR_NULL_POINTER; + if (nsnull == aTextRangeList) + return NS_ERROR_NULL_POINTER; + nsCOMPtr caretP; // workaround for windows ime bug 23558: we get every ime event twice. @@ -1905,6 +1906,36 @@ nsPlaintextEditor::SetCompositionString(const nsAString& aCompositionString, nsI mIMETextRangeList = aTextRangeList; + if (!mPresShellWeak) + return NS_ERROR_NOT_INITIALIZED; + + nsCOMPtr ps = do_QueryReferent(mPresShellWeak); + if (!ps) + return NS_ERROR_NOT_INITIALIZED; + + // XXX_kin: BEGIN HACK! HACK! HACK! + // XXX_kin: + // XXX_kin: This is lame! The IME stuff needs caret coordinates + // XXX_kin: synchronously, but the editor could be using async + // XXX_kin: updates (reflows and paints) for performance reasons. + // XXX_kin: In order to give IME what it needs, we have to temporarily + // XXX_kin: switch to sync updating during this call so that the + // XXX_kin: nsAutoPlaceHolderBatch can force sync reflows, paints, + // XXX_kin: and selection scrolling, so that we get back accurate + // XXX_kin: caret coordinates. + + PRUint32 flags = 0; + PRBool restoreFlags = PR_FALSE; + + if (NS_SUCCEEDED(GetFlags(&flags)) && + (flags & nsIPlaintextEditor::eEditorUseAsyncUpdatesMask)) + { + if (NS_SUCCEEDED(SetFlags(flags & (~nsIPlaintextEditor::eEditorUseAsyncUpdatesMask)))) + restoreFlags = PR_TRUE; + } + + // XXX_kin: END HACK! HACK! HACK! + // we need the nsAutoPlaceHolderBatch destructor called before hitting // GetCaretCoordinates so the states in Frame system sync with content // therefore, we put the nsAutoPlaceHolderBatch into a inner block @@ -1915,11 +1946,6 @@ nsPlaintextEditor::SetCompositionString(const nsAString& aCompositionString, nsI mIMEBufferLength = aCompositionString.Length(); - if (!mPresShellWeak) - return NS_ERROR_NOT_INITIALIZED; - nsCOMPtr ps = do_QueryReferent(mPresShellWeak); - if (!ps) - return NS_ERROR_NOT_INITIALIZED; ps->GetCaret(getter_AddRefs(caretP)); caretP->SetCaretDOMSelection(selection); @@ -1930,6 +1956,15 @@ nsPlaintextEditor::SetCompositionString(const nsAString& aCompositionString, nsI } } + // XXX_kin: BEGIN HACK! HACK! HACK! + // XXX_kin: + // XXX_kin: Restore the previous set of flags! + + if (restoreFlags) + SetFlags(flags); + + // XXX_kin: END HACK! HACK! HACK! + result = caretP->GetCaretCoordinates(nsICaret::eIMECoordinates, selection, &(aReply->mCursorPosition), &(aReply->mCursorIsCollapsed)); NS_ASSERTION(NS_SUCCEEDED(result), "cannot get caret position"); diff --git a/mozilla/editor/libeditor/txtsvc/nsTextServicesDocument.cpp b/mozilla/editor/libeditor/txtsvc/nsTextServicesDocument.cpp index 11806e3a7c2..ad483d87f32 100644 --- a/mozilla/editor/libeditor/txtsvc/nsTextServicesDocument.cpp +++ b/mozilla/editor/libeditor/txtsvc/nsTextServicesDocument.cpp @@ -1827,7 +1827,7 @@ nsTextServicesDocument::ScrollSelectionIntoView() LOCK_DOC(this); - result = mSelCon->ScrollSelectionIntoView(nsISelectionController::SELECTION_NORMAL, nsISelectionController::SELECTION_FOCUS_REGION); + result = mSelCon->ScrollSelectionIntoView(nsISelectionController::SELECTION_NORMAL, nsISelectionController::SELECTION_FOCUS_REGION, PR_TRUE); UNLOCK_DOC(this); diff --git a/mozilla/editor/txtsvc/src/nsTextServicesDocument.cpp b/mozilla/editor/txtsvc/src/nsTextServicesDocument.cpp index 11806e3a7c2..ad483d87f32 100644 --- a/mozilla/editor/txtsvc/src/nsTextServicesDocument.cpp +++ b/mozilla/editor/txtsvc/src/nsTextServicesDocument.cpp @@ -1827,7 +1827,7 @@ nsTextServicesDocument::ScrollSelectionIntoView() LOCK_DOC(this); - result = mSelCon->ScrollSelectionIntoView(nsISelectionController::SELECTION_NORMAL, nsISelectionController::SELECTION_FOCUS_REGION); + result = mSelCon->ScrollSelectionIntoView(nsISelectionController::SELECTION_NORMAL, nsISelectionController::SELECTION_FOCUS_REGION, PR_TRUE); UNLOCK_DOC(this); diff --git a/mozilla/editor/ui/dialogs/content/EdTableProps.js b/mozilla/editor/ui/dialogs/content/EdTableProps.js index 636fb31a2be..eb68cdd1ac3 100644 --- a/mozilla/editor/ui/dialogs/content/EdTableProps.js +++ b/mozilla/editor/ui/dialogs/content/EdTableProps.js @@ -709,7 +709,7 @@ function MoveSelection(forward) // the point to bring into view. var selectionController = editorShell.selectionController; if (selectionController) - selectionController.scrollSelectionIntoView(selectionController.SELECTION_NORMAL, selectionController.SELECTION_ANCHOR_REGION); + selectionController.scrollSelectionIntoView(selectionController.SELECTION_NORMAL, selectionController.SELECTION_ANCHOR_REGION, true); // Reinitialize dialog using new cell // if (!gDialog.KeepCurrentData.checked) diff --git a/mozilla/embedding/components/find/src/nsWebBrowserFind.cpp b/mozilla/embedding/components/find/src/nsWebBrowserFind.cpp index 7163cc7f119..a4623c90506 100644 --- a/mozilla/embedding/components/find/src/nsWebBrowserFind.cpp +++ b/mozilla/embedding/components/find/src/nsWebBrowserFind.cpp @@ -327,7 +327,7 @@ void nsWebBrowserFind::SetSelectionAndScroll(nsIDOMRange* aRange, // Scroll if necessary to make the selection visible: aSelCon->ScrollSelectionIntoView (nsISelectionController::SELECTION_NORMAL, - nsISelectionController::SELECTION_FOCUS_REGION); + nsISelectionController::SELECTION_FOCUS_REGION, PR_TRUE); } // Adapted from nsTextServicesDocument::GetDocumentContentRootNode diff --git a/mozilla/extensions/xmlterm/base/mozXMLTermSession.cpp b/mozilla/extensions/xmlterm/base/mozXMLTermSession.cpp index 1d5e5e4b0fa..43735f28a47 100644 --- a/mozilla/extensions/xmlterm/base/mozXMLTermSession.cpp +++ b/mozilla/extensions/xmlterm/base/mozXMLTermSession.cpp @@ -1140,7 +1140,8 @@ NS_IMETHODIMP mozXMLTermSession::ReadAll(mozILineTermAux* lineTermAux, return NS_ERROR_FAILURE; selCon->ScrollSelectionIntoView(nsISelectionController::SELECTION_NORMAL, - nsISelectionController::SELECTION_FOCUS_REGION); + nsISelectionController::SELECTION_FOCUS_REGION, + PR_TRUE); } @@ -1304,7 +1305,8 @@ NS_IMETHODIMP mozXMLTermSession::Abort(mozILineTermAux* lineTermAux, selection->Collapse(textNode, errMsg.Length()); if (NS_SUCCEEDED(result)) { selCon->ScrollSelectionIntoView(nsISelectionController::SELECTION_NORMAL, - nsISelectionController::SELECTION_FOCUS_REGION); + nsISelectionController::SELECTION_FOCUS_REGION, + PR_TRUE); } } } @@ -3523,7 +3525,8 @@ NS_IMETHODIMP mozXMLTermSession::NewScreen(void) return NS_ERROR_FAILURE; result = selCon->ScrollSelectionIntoView(nsISelectionController::SELECTION_NORMAL, - nsISelectionController::SELECTION_FOCUS_REGION); + nsISelectionController::SELECTION_FOCUS_REGION, + PR_TRUE); } return NS_OK; diff --git a/mozilla/layout/base/nsIFrameSelection.h b/mozilla/layout/base/nsIFrameSelection.h index f3518d9a272..18576c3e672 100644 --- a/mozilla/layout/base/nsIFrameSelection.h +++ b/mozilla/layout/base/nsIFrameSelection.h @@ -268,8 +268,10 @@ public: * * @param aType the selection to scroll into view. * @param aRegion the region inside the selection to scroll into view. + * @param aIsSynchronous when PR_TRUE, scrolls the selection into view + * at some point after the method returns.request which is processed */ - NS_IMETHOD ScrollSelectionIntoView(SelectionType aSelectionType, SelectionRegion aRegion)=0; + NS_IMETHOD ScrollSelectionIntoView(SelectionType aSelectionType, SelectionRegion aRegion, PRBool aIsSynchronous)=0; /** RepaintSelection repaints the selected frames that are inside the selection * specified by aSelectionType. diff --git a/mozilla/layout/base/nsPresShell.cpp b/mozilla/layout/base/nsPresShell.cpp index 07f1667feb2..a712b2fc929 100644 --- a/mozilla/layout/base/nsPresShell.cpp +++ b/mozilla/layout/base/nsPresShell.cpp @@ -1084,7 +1084,7 @@ public: NS_IMETHOD SetDisplaySelection(PRInt16 aToggle); NS_IMETHOD GetDisplaySelection(PRInt16 *aToggle); NS_IMETHOD GetSelection(SelectionType aType, nsISelection** aSelection); - NS_IMETHOD ScrollSelectionIntoView(SelectionType aType, SelectionRegion aRegion); + NS_IMETHOD ScrollSelectionIntoView(SelectionType aType, SelectionRegion aRegion, PRBool aIsSynchronous); NS_IMETHOD RepaintSelection(SelectionType aType); NS_IMETHOD GetFrameSelection(nsIFrameSelection** aSelection); @@ -2586,12 +2586,12 @@ PresShell::GetSelection(SelectionType aType, nsISelection **aSelection) } NS_IMETHODIMP -PresShell::ScrollSelectionIntoView(SelectionType aType, SelectionRegion aRegion) +PresShell::ScrollSelectionIntoView(SelectionType aType, SelectionRegion aRegion, PRBool aIsSynchronous) { if (!mSelection) return NS_ERROR_NULL_POINTER; - return mSelection->ScrollSelectionIntoView(aType, aRegion); + return mSelection->ScrollSelectionIntoView(aType, aRegion, aIsSynchronous); } NS_IMETHODIMP @@ -5221,6 +5221,9 @@ PresShell::EndReflowBatching(PRBool aFlushPendingReflows) if (aFlushPendingReflows) { rv = FlushPendingNotifications(PR_FALSE); } + else { + PostReflowEvent(); + } return rv; } diff --git a/mozilla/layout/base/public/nsIFrameSelection.h b/mozilla/layout/base/public/nsIFrameSelection.h index f3518d9a272..18576c3e672 100644 --- a/mozilla/layout/base/public/nsIFrameSelection.h +++ b/mozilla/layout/base/public/nsIFrameSelection.h @@ -268,8 +268,10 @@ public: * * @param aType the selection to scroll into view. * @param aRegion the region inside the selection to scroll into view. + * @param aIsSynchronous when PR_TRUE, scrolls the selection into view + * at some point after the method returns.request which is processed */ - NS_IMETHOD ScrollSelectionIntoView(SelectionType aSelectionType, SelectionRegion aRegion)=0; + NS_IMETHOD ScrollSelectionIntoView(SelectionType aSelectionType, SelectionRegion aRegion, PRBool aIsSynchronous)=0; /** RepaintSelection repaints the selected frames that are inside the selection * specified by aSelectionType. diff --git a/mozilla/layout/html/base/src/nsPresShell.cpp b/mozilla/layout/html/base/src/nsPresShell.cpp index 07f1667feb2..a712b2fc929 100644 --- a/mozilla/layout/html/base/src/nsPresShell.cpp +++ b/mozilla/layout/html/base/src/nsPresShell.cpp @@ -1084,7 +1084,7 @@ public: NS_IMETHOD SetDisplaySelection(PRInt16 aToggle); NS_IMETHOD GetDisplaySelection(PRInt16 *aToggle); NS_IMETHOD GetSelection(SelectionType aType, nsISelection** aSelection); - NS_IMETHOD ScrollSelectionIntoView(SelectionType aType, SelectionRegion aRegion); + NS_IMETHOD ScrollSelectionIntoView(SelectionType aType, SelectionRegion aRegion, PRBool aIsSynchronous); NS_IMETHOD RepaintSelection(SelectionType aType); NS_IMETHOD GetFrameSelection(nsIFrameSelection** aSelection); @@ -2586,12 +2586,12 @@ PresShell::GetSelection(SelectionType aType, nsISelection **aSelection) } NS_IMETHODIMP -PresShell::ScrollSelectionIntoView(SelectionType aType, SelectionRegion aRegion) +PresShell::ScrollSelectionIntoView(SelectionType aType, SelectionRegion aRegion, PRBool aIsSynchronous) { if (!mSelection) return NS_ERROR_NULL_POINTER; - return mSelection->ScrollSelectionIntoView(aType, aRegion); + return mSelection->ScrollSelectionIntoView(aType, aRegion, aIsSynchronous); } NS_IMETHODIMP @@ -5221,6 +5221,9 @@ PresShell::EndReflowBatching(PRBool aFlushPendingReflows) if (aFlushPendingReflows) { rv = FlushPendingNotifications(PR_FALSE); } + else { + PostReflowEvent(); + } return rv; } diff --git a/mozilla/layout/html/forms/src/nsGfxTextControlFrame2.cpp b/mozilla/layout/html/forms/src/nsGfxTextControlFrame2.cpp index 4e4e754a583..de25336230c 100644 --- a/mozilla/layout/html/forms/src/nsGfxTextControlFrame2.cpp +++ b/mozilla/layout/html/forms/src/nsGfxTextControlFrame2.cpp @@ -574,7 +574,7 @@ public: NS_IMETHOD SetSelectionFlags(PRInt16 aInEnable); NS_IMETHOD GetSelectionFlags(PRInt16 *aOutEnable); NS_IMETHOD GetSelection(PRInt16 type, nsISelection **_retval); - NS_IMETHOD ScrollSelectionIntoView(PRInt16 type, PRInt16 region); + NS_IMETHOD ScrollSelectionIntoView(PRInt16 aType, PRInt16 aRegion, PRBool aIsSynchronous); NS_IMETHOD RepaintSelection(PRInt16 type); NS_IMETHOD RepaintSelection(nsIPresContext* aPresContext, SelectionType aSelectionType); NS_IMETHOD SetCaretEnabled(PRBool enabled); @@ -710,10 +710,10 @@ nsTextInputSelectionImpl::GetSelection(PRInt16 type, nsISelection **_retval) } NS_IMETHODIMP -nsTextInputSelectionImpl::ScrollSelectionIntoView(PRInt16 type, PRInt16 region) +nsTextInputSelectionImpl::ScrollSelectionIntoView(PRInt16 aType, PRInt16 aRegion, PRBool aIsSynchronous) { if (mFrameSelection) - return mFrameSelection->ScrollSelectionIntoView(type, region); + return mFrameSelection->ScrollSelectionIntoView(aType, aRegion, aIsSynchronous); return NS_ERROR_NULL_POINTER; } @@ -1806,8 +1806,7 @@ nsGfxTextControlFrame2::InitEditor() // immediate reflows during any editor calls. rv = mEditor->SetFlags(editorFlags | - nsIPlaintextEditor::eEditorDisableForcedUpdatesMask | - nsIPlaintextEditor::eEditorDisableForcedReflowsMask); + nsIPlaintextEditor::eEditorUseAsyncUpdatesMask); if (NS_FAILED(rv)) return rv; @@ -1990,9 +1989,14 @@ nsGfxTextControlFrame2::CreateAnonymousContent(nsIPresContext* aPresContext, if (IsPasswordTextControl()) editorFlags |= nsIPlaintextEditor::eEditorPasswordMask; - //all gfxtextcontrolframe2's are widgets + // All gfxtextcontrolframe2's are widgets editorFlags |= nsIPlaintextEditor::eEditorWidgetMask; + // Use async reflow and painting for text widgets to improve + // performance. + + editorFlags |= nsIPlaintextEditor::eEditorUseAsyncUpdatesMask; + // Now initialize the editor. // // NOTE: Conversion of '\n' to
happens inside the diff --git a/mozilla/mailnews/compose/src/nsMsgCompose.cpp b/mozilla/mailnews/compose/src/nsMsgCompose.cpp index 04486131260..302d96164e9 100644 --- a/mozilla/mailnews/compose/src/nsMsgCompose.cpp +++ b/mozilla/mailnews/compose/src/nsMsgCompose.cpp @@ -640,7 +640,7 @@ NS_IMETHODIMP nsMsgCompose::ConvertAndLoadComposeWindow(nsIEditorShell *aEditorS editor->GetSelectionController(getter_AddRefs(selCon)); if (selCon) - selCon->ScrollSelectionIntoView(nsISelectionController::SELECTION_NORMAL, nsISelectionController::SELECTION_ANCHOR_REGION); + selCon->ScrollSelectionIntoView(nsISelectionController::SELECTION_NORMAL, nsISelectionController::SELECTION_ANCHOR_REGION, PR_TRUE); } if (editor) @@ -2265,7 +2265,7 @@ NS_IMETHODIMP QuotingOutputStreamListener::InsertToCompose(nsIEditorShell *aEdit editor->GetSelectionController(getter_AddRefs(selCon)); if (selCon) - selCon->ScrollSelectionIntoView(nsISelectionController::SELECTION_NORMAL, nsISelectionController::SELECTION_ANCHOR_REGION); + selCon->ScrollSelectionIntoView(nsISelectionController::SELECTION_NORMAL, nsISelectionController::SELECTION_ANCHOR_REGION, PR_TRUE); } } diff --git a/mozilla/xpfe/browser/resources/content/viewPartialSource.js b/mozilla/xpfe/browser/resources/content/viewPartialSource.js index ad9b5ae78ed..e07c14e9d23 100644 --- a/mozilla/xpfe/browser/resources/content/viewPartialSource.js +++ b/mozilla/xpfe/browser/resources/content/viewPartialSource.js @@ -283,7 +283,8 @@ function drawSelection() .getInterface(Components.interfaces.nsISelectionDisplay) .QueryInterface(Components.interfaces.nsISelectionController) .scrollSelectionIntoView(Components.interfaces.nsISelectionController.SELECTION_NORMAL, - Components.interfaces.nsISelectionController.SELECTION_ANCHOR_REGION); + Components.interfaces.nsISelectionController.SELECTION_ANCHOR_REGION, + true); } catch(e) { }