author | Masayuki Nakano <masayuki@d-toybox.com> |
Tue, 19 Aug 2014 20:54:08 +0900 | |
changeset 200360 | 77bf46f52906ecd6c09a13539642be83471661a1 |
parent 200359 | 99f640f313595fc5ce635439fbeb9571b7f36629 |
child 200361 | eb7712477525ae30ecf1d95569abaf5932522c0f |
push id | 27342 |
push user | ryanvm@gmail.com |
push date | Tue, 19 Aug 2014 20:23:11 +0000 |
treeherder | mozilla-central@149d3ce6e020 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | ehsan, smaug |
bugs | 1053048 |
milestone | 34.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/content/html/content/src/nsTextEditorState.cpp +++ b/content/html/content/src/nsTextEditorState.cpp @@ -659,18 +659,16 @@ public: /** SetEditor gives an address to the editor that will be accessed * @param aEditor the editor this listener calls for editing operations */ void SetFrame(nsTextControlFrame *aFrame){mFrame = aFrame;} void SettingValue(bool aValue) { mSettingValue = aValue; } void SetValueChanged(bool aSetValueChanged) { mSetValueChanged = aSetValueChanged; } - bool IsInEditAction() const { return mInEditAction; } - NS_DECL_ISUPPORTS NS_DECL_NSISELECTIONLISTENER NS_DECL_NSIDOMEVENTLISTENER NS_DECL_NSIEDITOROBSERVER @@ -705,36 +703,31 @@ protected: * refrain from calling OnValueChanged. */ bool mSettingValue; /** * Whether we are in the process of a SetValue call that doesn't want * |SetValueChanged| to be called. */ bool mSetValueChanged; - /** - * mInEditAction is true while editor handling an edit action. - */ - bool mInEditAction; }; /* * nsTextInputListener implementation */ nsTextInputListener::nsTextInputListener(nsITextControlElement* aTxtCtrlElement) : mFrame(nullptr) , mTxtCtrlElement(aTxtCtrlElement) , mSelectionWasCollapsed(true) , mHadUndoItems(false) , mHadRedoItems(false) , mSettingValue(false) , mSetValueChanged(true) -, mInEditAction(false) { } nsTextInputListener::~nsTextInputListener() { } NS_IMPL_ISUPPORTS(nsTextInputListener, @@ -891,18 +884,16 @@ nsTextInputListener::HandleEvent(nsIDOME return NS_OK; } // BEGIN nsIEditorObserver NS_IMETHODIMP nsTextInputListener::EditAction() { - mInEditAction = false; - nsWeakFrame weakFrame = mFrame; nsITextControlFrame* frameBase = do_QueryFrame(mFrame); nsTextControlFrame* frame = static_cast<nsTextControlFrame*> (frameBase); NS_ASSERTION(frame, "Where is our frame?"); // // Update the undo / redo menus // @@ -938,24 +929,22 @@ nsTextInputListener::EditAction() } return NS_OK; } NS_IMETHODIMP nsTextInputListener::BeforeEditAction() { - mInEditAction = true; return NS_OK; } NS_IMETHODIMP nsTextInputListener::CancelEditAction() { - mInEditAction = false; return NS_OK; } // END nsIEditorObserver nsresult nsTextInputListener::UpdateTextInputCommands(const nsAString& commandsToUpdate, @@ -1524,20 +1513,21 @@ void nsTextEditorState::UnbindFromFrame(nsTextControlFrame* aFrame) { NS_ENSURE_TRUE_VOID(mBoundFrame); // If it was, however, it should be unbounded from the same frame. NS_ASSERTION(!aFrame || aFrame == mBoundFrame, "Unbinding from the wrong frame"); NS_ENSURE_TRUE_VOID(!aFrame || aFrame == mBoundFrame); - // If the editor is modified, we need to notify it here because editor may be - // destroyed before EditAction() is called if selection listener causes - // flushing layout. - if (mTextListener && mTextListener->IsInEditAction()) { + // If the editor is modified but nsIEditorObserver::EditAction() hasn't been + // called yet, we need to notify it here because editor may be destroyed + // before EditAction() is called if selection listener causes flushing layout. + if (mTextListener && mEditor && mEditorInitialized && + mEditor->GetIsInEditAction()) { mTextListener->EditAction(); } // We need to start storing the value outside of the editor if we're not // going to use it anymore, so retrieve it for now. nsAutoString value; GetValue(value, true);
--- a/dom/events/IMEContentObserver.cpp +++ b/dom/events/IMEContentObserver.cpp @@ -79,17 +79,16 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION( NS_INTERFACE_MAP_END NS_IMPL_CYCLE_COLLECTING_ADDREF(IMEContentObserver) NS_IMPL_CYCLE_COLLECTING_RELEASE(IMEContentObserver) IMEContentObserver::IMEContentObserver() : mESM(nullptr) , mPreCharacterDataChangeLength(-1) - , mIsEditorInTransaction(false) , mIsSelectionChangeEventPending(false) , mSelectionChangeCausedOnlyByComposition(false) , mIsPositionChangeEventPending(false) , mIsFlushingPendingNotifications(false) { #ifdef DEBUG TestMergingTextChangeData(); #endif @@ -906,36 +905,33 @@ IMEContentObserver::AttributeChanged(nsI TextChangeData data(start, start + mPreAttrChangeLength, start + postAttrChangeLength, causedByComposition); MaybeNotifyIMEOfTextChange(data); } NS_IMETHODIMP IMEContentObserver::EditAction() { - mIsEditorInTransaction = false; mEndOfAddedTextCache.Clear(); mStartOfRemovingTextRangeCache.Clear(); FlushMergeableNotifications(); return NS_OK; } NS_IMETHODIMP IMEContentObserver::BeforeEditAction() { - mIsEditorInTransaction = true; mEndOfAddedTextCache.Clear(); mStartOfRemovingTextRangeCache.Clear(); return NS_OK; } NS_IMETHODIMP IMEContentObserver::CancelEditAction() { - mIsEditorInTransaction = false; mEndOfAddedTextCache.Clear(); mStartOfRemovingTextRangeCache.Clear(); FlushMergeableNotifications(); return NS_OK; } void IMEContentObserver::MaybeNotifyIMEOfTextChange(const TextChangeData& aData) @@ -983,20 +979,24 @@ public: private: nsRefPtr<IMEContentObserver> mIMEContentObserver; }; void IMEContentObserver::FlushMergeableNotifications() { - // If we're in handling an edit action, this method will be called later. // If this is already detached from the widget, this doesn't need to notify // anything. - if (mIsEditorInTransaction || !mWidget) { + if (!mWidget) { + return; + } + + // If we're in handling an edit action, this method will be called later. + if (mEditor && mEditor->GetIsInEditAction()) { return; } // Notifying something may cause nested call of this method. For example, // when somebody notified one of the notifications may dispatch query content // event. Then, it causes flushing layout which may cause another layout // change notification.
--- a/dom/events/IMEContentObserver.h +++ b/dom/events/IMEContentObserver.h @@ -212,17 +212,16 @@ private: TextChangeData mTextChangeData; EventStateManager* mESM; nsIMEUpdatePreference mUpdatePreference; uint32_t mPreAttrChangeLength; int64_t mPreCharacterDataChangeLength; - bool mIsEditorInTransaction; bool mIsSelectionChangeEventPending; bool mSelectionChangeCausedOnlyByComposition; bool mIsPositionChangeEventPending; bool mIsFlushingPendingNotifications; }; } // namespace mozilla
--- a/editor/libeditor/nsEditor.cpp +++ b/editor/libeditor/nsEditor.cpp @@ -142,16 +142,17 @@ nsEditor::nsEditor() , mIMETextOffset(0) , mDirection(eNone) , mDocDirtyState(-1) , mSpellcheckCheckboxState(eTriUnset) , mShouldTxnSetSelection(true) , mDidPreDestroy(false) , mDidPostCreate(false) , mDispatchInputEvent(true) +, mIsInEditAction(false) { } nsEditor::~nsEditor() { NS_ASSERTION(!mDocWeak || mDidPreDestroy, "Why PreDestroy hasn't been called?"); mTxnMgr = nullptr; @@ -1827,32 +1828,35 @@ private: bool mIsComposing; }; void nsEditor::NotifyEditorObservers(NotificationForEditorObservers aNotification) { switch (aNotification) { case eNotifyEditorObserversOfEnd: + mIsInEditAction = false; for (int32_t i = 0; i < mEditorObservers.Count(); i++) { mEditorObservers[i]->EditAction(); } if (!mDispatchInputEvent) { return; } FireInputEvent(); break; case eNotifyEditorObserversOfBefore: + mIsInEditAction = true; for (int32_t i = 0; i < mEditorObservers.Count(); i++) { mEditorObservers[i]->BeforeEditAction(); } break; case eNotifyEditorObserversOfCancel: + mIsInEditAction = false; for (int32_t i = 0; i < mEditorObservers.Count(); i++) { mEditorObservers[i]->CancelEditAction(); } break; default: MOZ_CRASH("Handle all notifications here"); break; } @@ -5268,8 +5272,16 @@ nsEditor::GetSuppressDispatchingInputEve } NS_IMETHODIMP nsEditor::SetSuppressDispatchingInputEvent(bool aSuppress) { mDispatchInputEvent = !aSuppress; return NS_OK; } + +NS_IMETHODIMP +nsEditor::GetIsInEditAction(bool* aIsInEditAction) +{ + MOZ_ASSERT(aIsInEditAction, "aIsInEditAction must not be null"); + *aIsInEditAction = mIsInEditAction; + return NS_OK; +}
--- a/editor/libeditor/nsEditor.h +++ b/editor/libeditor/nsEditor.h @@ -890,16 +890,17 @@ protected: EDirection mDirection; // the current direction of editor action int8_t mDocDirtyState; // -1 = not initialized uint8_t mSpellcheckCheckboxState; // a Tristate value bool mShouldTxnSetSelection; // turn off for conservative selection adjustment by txns bool mDidPreDestroy; // whether PreDestroy has been called bool mDidPostCreate; // whether PostCreate has been called bool mDispatchInputEvent; + bool mIsInEditAction; // true while the instance is handling an edit action friend bool NSCanUnload(nsISupports* serviceMgr); friend class nsAutoTxnsConserveSelection; friend class nsAutoSelectionReset; friend class nsAutoRules; friend class nsRangeUpdater; };
--- a/editor/nsIEditor.idl +++ b/editor/nsIEditor.idl @@ -16,17 +16,17 @@ interface nsIDocumentStateListener; interface nsIOutputStream; interface nsITransactionManager; interface nsITransaction; interface nsIEditorObserver; interface nsIEditActionListener; interface nsIInlineSpellChecker; interface nsITransferable; -[scriptable, uuid(65523eab-db1f-44aa-893e-dfe57ad306f0)] +[builtinclass, scriptable, uuid(c3b61bc9-ccdd-4bcd-acd8-1b8dcbe6a247)] interface nsIEditor : nsISupports { %{C++ typedef short EDirection; typedef short EStripWrappers; %} const short eNone = 0; @@ -544,9 +544,16 @@ interface nsIEditor : nsISupports /* Run unit tests. Noop in optimized builds */ void debugUnitTests(out long outNumTests, out long outNumTestsFailed); /* checks if a node is read-only or not */ [notxpcom] boolean isModifiableNode(in nsIDOMNode aNode); /* Set true if you want to suppress dispatching input event. */ attribute boolean suppressDispatchingInputEvent; + + /** + * True if an edit action is being handled (in other words, between calls of + * nsIEditorObserver::BeforeEditAction() and nsIEditorObserver::EditAction() + * or nsIEditorObserver::CancelEditAction(). Otherwise, false. + */ + [infallible, noscript] readonly attribute boolean isInEditAction; };
--- a/editor/nsIHTMLEditor.idl +++ b/editor/nsIHTMLEditor.idl @@ -17,17 +17,17 @@ namespace mozilla { namespace dom { class Element; } } %} [ptr] native Element (mozilla::dom::Element); -[scriptable, uuid(833f30de-94c7-4630-a852-2300ef329d7b)] +[builtinclass, scriptable, uuid(9470bee7-cad3-4382-8fb4-6bdda9f0273a)] interface nsIHTMLEditor : nsISupports { %{C++ typedef short EAlignment; %} // used by GetAlignment()
--- a/editor/nsIPlaintextEditor.idl +++ b/editor/nsIPlaintextEditor.idl @@ -1,16 +1,16 @@ /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "nsISupports.idl" -[scriptable, uuid(07b6d070-ccea-4a00-84b4-f4b94dd9eb52)] +[builtinclass, scriptable, uuid(da8f244b-6ffc-4be1-8b1a-667abfe1d304)] interface nsIPlaintextEditor : nsISupports { // XXX Why aren't these in nsIEditor? // only plain text entry is allowed via events const long eEditorPlaintextMask = 0x0001; // enter key and CR-LF handled specially const long eEditorSingleLineMask = 0x0002;