зеркало из https://github.com/mozilla/gecko-dev.git
Bug 542919 - Refactor the plain text editor initialization to facilitate lazy initialization; r=bzbarsky sr=roc
--HG-- extra : rebase_source : 9c043d3cb30420f061d543e11e3000a1f8e18e27
This commit is contained in:
Родитель
b6cf005ff7
Коммит
3776d4f9f8
|
@ -87,6 +87,13 @@ public:
|
||||||
virtual nsFrameSelection* GetOwnedFrameSelection() = 0;
|
virtual nsFrameSelection* GetOwnedFrameSelection() = 0;
|
||||||
|
|
||||||
virtual nsresult GetPhonetic(nsAString& aPhonetic) = 0;
|
virtual nsresult GetPhonetic(nsAString& aPhonetic) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ensure editor is initialized with the proper flags and the default value.
|
||||||
|
* @throws NS_ERROR_NOT_INITIALIZED if mEditor has not been created
|
||||||
|
* @throws various and sundry other things
|
||||||
|
*/
|
||||||
|
virtual nsresult EnsureEditorInitialized() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1299,38 +1299,6 @@ nsTextControlFrame::CalcIntrinsicSize(nsIRenderingContext* aRenderingContext,
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
nsTextControlFrame::DelayedEditorInit()
|
|
||||||
{
|
|
||||||
nsIDocument* doc = mContent->GetCurrentDoc();
|
|
||||||
if (!doc) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsWeakFrame weakFrame(this);
|
|
||||||
|
|
||||||
// Flush out content on our document. Have to do this, because script
|
|
||||||
// blockers don't prevent the sink flushing out content and notifying in the
|
|
||||||
// process, which can destroy frames.
|
|
||||||
doc->FlushPendingNotifications(Flush_ContentAndNotify);
|
|
||||||
if (!weakFrame.IsAlive()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make sure that editor init doesn't do things that would kill us off
|
|
||||||
// (especially off the script blockers it'll create for its DOM mutations).
|
|
||||||
nsAutoScriptBlocker scriptBlocker;
|
|
||||||
|
|
||||||
// Time to mess with our security context... See comments in GetValue()
|
|
||||||
// for why this is needed.
|
|
||||||
nsCxPusher pusher;
|
|
||||||
pusher.PushNull();
|
|
||||||
|
|
||||||
InitEditor();
|
|
||||||
if (IsFocusedContent(GetContent()))
|
|
||||||
SetFocus(PR_TRUE, PR_FALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
PRInt32
|
PRInt32
|
||||||
nsTextControlFrame::GetWrapCols()
|
nsTextControlFrame::GetWrapCols()
|
||||||
{
|
{
|
||||||
|
@ -1352,23 +1320,58 @@ nsTextControlFrame::GetWrapCols()
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
nsTextControlFrame::InitEditor()
|
nsTextControlFrame::EnsureEditorInitialized()
|
||||||
{
|
{
|
||||||
// This method initializes our editor, if needed.
|
// This method initializes our editor, if needed.
|
||||||
|
|
||||||
// This code used to be called from CreateAnonymousContent(), but
|
// This code used to be called from CreateAnonymousContent(), but
|
||||||
// when the editor set the initial string, it would trigger a
|
// when the editor set the initial string, it would trigger a
|
||||||
// PresShell listener which called FlushPendingNotifications()
|
// PresShell listener which called FlushPendingNotifications()
|
||||||
// during frame construction. This was causing other form controls
|
// during frame construction. This was causing other form controls
|
||||||
// to display wrong values. So we call this from a script runner
|
// to display wrong values. Additionally, calling this every time
|
||||||
// now.
|
// a text frame control is instantiated means that we're effectively
|
||||||
|
// instantiating the editor for all text fields, even if they
|
||||||
|
// never get used.
|
||||||
|
|
||||||
// Check if this method has been called already.
|
// Check if this method has been called already.
|
||||||
// If so, just return early.
|
// If so, just return early.
|
||||||
|
|
||||||
if (mUseEditor)
|
if (mUseEditor)
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
|
|
||||||
|
nsIDocument* doc = mContent->GetCurrentDoc();
|
||||||
|
NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE);
|
||||||
|
|
||||||
|
nsWeakFrame weakFrame(this);
|
||||||
|
|
||||||
|
// Flush out content on our document. Have to do this, because script
|
||||||
|
// blockers don't prevent the sink flushing out content and notifying in the
|
||||||
|
// process, which can destroy frames.
|
||||||
|
doc->FlushPendingNotifications(Flush_ContentAndNotify);
|
||||||
|
NS_ENSURE_TRUE(weakFrame.IsAlive(), NS_ERROR_FAILURE);
|
||||||
|
|
||||||
|
// Make sure that editor init doesn't do things that would kill us off
|
||||||
|
// (especially off the script blockers it'll create for its DOM mutations).
|
||||||
|
nsAutoScriptBlocker scriptBlocker;
|
||||||
|
|
||||||
|
// Time to mess with our security context... See comments in GetValue()
|
||||||
|
// for why this is needed.
|
||||||
|
nsCxPusher pusher;
|
||||||
|
pusher.PushNull();
|
||||||
|
|
||||||
|
// Make sure that we try to focus the content even if the method fails
|
||||||
|
class EnsureSetFocus {
|
||||||
|
public:
|
||||||
|
explicit EnsureSetFocus(nsTextControlFrame* aFrame)
|
||||||
|
: mFrame(aFrame) {}
|
||||||
|
~EnsureSetFocus() {
|
||||||
|
if (IsFocusedContent(mFrame->GetContent()))
|
||||||
|
mFrame->SetFocus(PR_TRUE, PR_FALSE);
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
nsTextControlFrame *mFrame;
|
||||||
|
};
|
||||||
|
EnsureSetFocus makeSureSetFocusHappens(this);
|
||||||
|
|
||||||
// Create an editor
|
// Create an editor
|
||||||
|
|
||||||
nsresult rv;
|
nsresult rv;
|
||||||
|
@ -1499,48 +1502,45 @@ nsTextControlFrame::InitEditor()
|
||||||
// editor.
|
// editor.
|
||||||
mUseEditor = PR_TRUE;
|
mUseEditor = PR_TRUE;
|
||||||
|
|
||||||
// If we have a default value, insert it under the div we created
|
// Set the editor's contents to our default value. We have to be
|
||||||
// above, but be sure to use the editor so that '*' characters get
|
// sure to use the editor so that '*' characters get displayed for
|
||||||
// displayed for password fields, etc. SetValue() will call the
|
// password fields, etc. SetValue() will call the editor for us. We
|
||||||
// editor for us.
|
// want to call this even if defaultValue is empty, since empty text
|
||||||
|
// inputs have a single non-breaking space in the textnode under
|
||||||
|
// mAnonymousDiv, and this space needs to go away as we init the
|
||||||
|
// editor.
|
||||||
|
|
||||||
|
// Avoid causing reentrant painting and reflowing by telling the editor
|
||||||
|
// that we don't want it to force immediate view refreshes or force
|
||||||
|
// immediate reflows during any editor calls.
|
||||||
|
|
||||||
|
rv = mEditor->SetFlags(editorFlags |
|
||||||
|
nsIPlaintextEditor::eEditorUseAsyncUpdatesMask);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
|
// Now call SetValue() which will make the necessary editor calls to set
|
||||||
|
// the default value. Make sure to turn off undo before setting the default
|
||||||
|
// value, and turn it back on afterwards. This will make sure we can't undo
|
||||||
|
// past the default value.
|
||||||
|
|
||||||
|
rv = mEditor->EnableUndo(PR_FALSE);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
|
SetValue(defaultValue);
|
||||||
|
|
||||||
|
rv = mEditor->EnableUndo(PR_TRUE);
|
||||||
|
NS_ASSERTION(NS_SUCCEEDED(rv),"Transaction Manager must have failed");
|
||||||
|
|
||||||
|
// Now restore the original editor flags.
|
||||||
|
rv = mEditor->SetFlags(editorFlags);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
if (!defaultValue.IsEmpty()) {
|
if (!defaultValue.IsEmpty()) {
|
||||||
// Avoid causing reentrant painting and reflowing by telling the editor
|
|
||||||
// that we don't want it to force immediate view refreshes or force
|
|
||||||
// immediate reflows during any editor calls.
|
|
||||||
|
|
||||||
rv = mEditor->SetFlags(editorFlags |
|
|
||||||
nsIPlaintextEditor::eEditorUseAsyncUpdatesMask);
|
|
||||||
|
|
||||||
if (NS_FAILED(rv))
|
|
||||||
return rv;
|
|
||||||
|
|
||||||
// Now call SetValue() which will make the necessary editor calls to set
|
|
||||||
// the default value. Make sure to turn off undo before setting the default
|
|
||||||
// value, and turn it back on afterwards. This will make sure we can't undo
|
|
||||||
// past the default value.
|
|
||||||
|
|
||||||
rv = mEditor->EnableUndo(PR_FALSE);
|
|
||||||
|
|
||||||
if (NS_FAILED(rv))
|
|
||||||
return rv;
|
|
||||||
|
|
||||||
SetValue(defaultValue);
|
|
||||||
|
|
||||||
rv = mEditor->EnableUndo(PR_TRUE);
|
|
||||||
NS_ASSERTION(NS_SUCCEEDED(rv),"Transaction Manager must have failed");
|
|
||||||
|
|
||||||
// Now restore the original editor flags.
|
|
||||||
rv = mEditor->SetFlags(editorFlags);
|
|
||||||
|
|
||||||
// By default the placeholder is shown,
|
// By default the placeholder is shown,
|
||||||
// we should hide it if the default value is not empty.
|
// we should hide it if the default value is not empty.
|
||||||
nsWeakFrame weakFrame(this);
|
nsWeakFrame weakFrame(this);
|
||||||
HidePlaceholder();
|
HidePlaceholder();
|
||||||
NS_ENSURE_STATE(weakFrame.IsAlive());
|
NS_ENSURE_STATE(weakFrame.IsAlive());
|
||||||
|
|
||||||
if (NS_FAILED(rv))
|
|
||||||
return rv;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
nsCOMPtr<nsITransactionManager> transMgr;
|
nsCOMPtr<nsITransactionManager> transMgr;
|
||||||
|
@ -1571,7 +1571,7 @@ nsTextControlFrame::CreateAnonymousContent(nsTArray<nsIContent*>& aElements)
|
||||||
{
|
{
|
||||||
mState |= NS_FRAME_INDEPENDENT_SELECTION;
|
mState |= NS_FRAME_INDEPENDENT_SELECTION;
|
||||||
|
|
||||||
nsIPresShell* shell = PresContext()->GetPresShell();
|
nsIPresShell *shell = PresContext()->GetPresShell();
|
||||||
if (!shell)
|
if (!shell)
|
||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
|
|
||||||
|
@ -2424,7 +2424,7 @@ nsTextControlFrame::AttributeChanged(PRInt32 aNameSpaceID,
|
||||||
if (!(flags & nsIPlaintextEditor::eEditorDisabledMask) &&
|
if (!(flags & nsIPlaintextEditor::eEditorDisabledMask) &&
|
||||||
IsFocusedContent(mContent))
|
IsFocusedContent(mContent))
|
||||||
mSelCon->SetCaretEnabled(PR_TRUE);
|
mSelCon->SetCaretEnabled(PR_TRUE);
|
||||||
}
|
}
|
||||||
mEditor->SetFlags(flags);
|
mEditor->SetFlags(flags);
|
||||||
}
|
}
|
||||||
else if (nsGkAtoms::disabled == aAttribute)
|
else if (nsGkAtoms::disabled == aAttribute)
|
||||||
|
|
|
@ -175,6 +175,13 @@ public:
|
||||||
|
|
||||||
nsresult GetPhonetic(nsAString& aPhonetic);
|
nsresult GetPhonetic(nsAString& aPhonetic);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ensure mEditor is initialized with the proper flags and the default value.
|
||||||
|
* @throws NS_ERROR_NOT_INITIALIZED if mEditor has not been created
|
||||||
|
* @throws various and sundry other things
|
||||||
|
*/
|
||||||
|
virtual nsresult EnsureEditorInitialized();
|
||||||
|
|
||||||
//==== END NSITEXTCONTROLFRAME
|
//==== END NSITEXTCONTROLFRAME
|
||||||
//==== OVERLOAD of nsIFrame
|
//==== OVERLOAD of nsIFrame
|
||||||
virtual nsIAtom* GetType() const;
|
virtual nsIAtom* GetType() const;
|
||||||
|
@ -248,7 +255,7 @@ protected:
|
||||||
mWeakFrame.GetFrame()->PresContext()->GetPresShell();
|
mWeakFrame.GetFrame()->PresContext()->GetPresShell();
|
||||||
PRBool observes = shell->ObservesNativeAnonMutationsForPrint();
|
PRBool observes = shell->ObservesNativeAnonMutationsForPrint();
|
||||||
shell->ObserveNativeAnonMutationsForPrint(PR_TRUE);
|
shell->ObserveNativeAnonMutationsForPrint(PR_TRUE);
|
||||||
mFrame->DelayedEditorInit();
|
mFrame->EnsureEditorInitialized();
|
||||||
shell->ObserveNativeAnonMutationsForPrint(observes);
|
shell->ObserveNativeAnonMutationsForPrint(observes);
|
||||||
}
|
}
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
|
@ -259,10 +266,6 @@ protected:
|
||||||
nsTextControlFrame* mFrame;
|
nsTextControlFrame* mFrame;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Init our editor and then make sure to focus our text input
|
|
||||||
// listener if our content node has focus.
|
|
||||||
void DelayedEditorInit();
|
|
||||||
|
|
||||||
nsresult DOMPointToOffset(nsIDOMNode* aNode, PRInt32 aNodeOffset, PRInt32 *aResult);
|
nsresult DOMPointToOffset(nsIDOMNode* aNode, PRInt32 aNodeOffset, PRInt32 *aResult);
|
||||||
nsresult OffsetToDOMPoint(PRInt32 aOffset, nsIDOMNode** aResult, PRInt32* aPosition);
|
nsresult OffsetToDOMPoint(PRInt32 aOffset, nsIDOMNode** aResult, PRInt32* aPosition);
|
||||||
|
|
||||||
|
@ -272,12 +275,6 @@ protected:
|
||||||
* @return whether this control is scrollable
|
* @return whether this control is scrollable
|
||||||
*/
|
*/
|
||||||
PRBool IsScrollable() const;
|
PRBool IsScrollable() const;
|
||||||
/**
|
|
||||||
* Initialize mEditor with the proper flags and the default value.
|
|
||||||
* @throws NS_ERROR_NOT_INITIALIZED if mEditor has not been created
|
|
||||||
* @throws various and sundry other things
|
|
||||||
*/
|
|
||||||
nsresult InitEditor();
|
|
||||||
/**
|
/**
|
||||||
* Strip all \n, \r and nulls from the given string
|
* Strip all \n, \r and nulls from the given string
|
||||||
* @param aString the string to remove newlines from [in/out]
|
* @param aString the string to remove newlines from [in/out]
|
||||||
|
|
Загрузка…
Ссылка в новой задаче