Bug 808287 nsTextStateManager shouldn't notify widget of selection changes and text changes after IME loses focus r=smaug
authorMasayuki Nakano <masayuki@d-toybox.com>
Tue, 13 Nov 2012 10:20:40 +0900
changeset 113149 876764fbf6dc4c2234a725146102c843f0f40ee5
parent 113148 da23f50dc0a9d571f4934ca387622232ab1eb1de
child 113150 b6bd99bf0c1ffba4f030150c7837eed001c7516b
push id23859
push useremorley@mozilla.com
push dateWed, 14 Nov 2012 14:36:31 +0000
treeherdermozilla-central@87928cd21b40 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs808287
milestone19.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
Bug 808287 nsTextStateManager shouldn't notify widget of selection changes and text changes after IME loses focus r=smaug
content/events/src/nsIMEStateManager.cpp
--- a/content/events/src/nsIMEStateManager.cpp
+++ b/content/events/src/nsIMEStateManager.cpp
@@ -770,28 +770,29 @@ void
 nsTextStateManager::Destroy(void)
 {
   if (nsIMEStateManager::sIsTestingIME && mEditableNode) {
     nsIDocument* doc = mEditableNode->OwnerDoc();
     (new nsAsyncDOMEvent(doc, NS_LITERAL_STRING("MozIMEFocusOut"),
                          false, false))->RunDOMEventWhenSafe();
   }
   mWidget->OnIMEFocusChange(false);
+  // Even if there are some pending notification, it'll never notify the widget.
+  mWidget = nullptr;
   if (mObserving && mSel) {
     nsCOMPtr<nsISelectionPrivate> selPrivate(do_QueryInterface(mSel));
     if (selPrivate)
       selPrivate->RemoveSelectionListener(this);
   }
   mSel = nullptr;
   if (mObserving && mRootContent) {
     mRootContent->RemoveMutationObserver(this);
   }
   mRootContent = nullptr;
   mEditableNode = nullptr;
-  mWidget = nullptr;
   mObserving = false;
 }
 
 bool
 nsTextStateManager::IsManaging(nsPresContext* aPresContext,
                                nsIContent* aContent)
 {
   if (!mSel || !mRootContent || !mEditableNode) {
@@ -806,69 +807,69 @@ nsTextStateManager::IsManaging(nsPresCon
 
 NS_IMPL_ISUPPORTS2(nsTextStateManager,
                    nsIMutationObserver,
                    nsISelectionListener)
 
 // Helper class, used for selection change notification
 class SelectionChangeEvent : public nsRunnable {
 public:
-  SelectionChangeEvent(nsIWidget *widget)
-    : mWidget(widget)
+  SelectionChangeEvent(nsTextStateManager *aDispatcher)
+    : mDispatcher(aDispatcher)
   {
-    MOZ_ASSERT(mWidget);
+    MOZ_ASSERT(mDispatcher);
   }
 
   NS_IMETHOD Run() {
-    if(mWidget) {
-        mWidget->OnIMESelectionChange();
+    if (mDispatcher->mWidget) {
+      mDispatcher->mWidget->OnIMESelectionChange();
     }
     return NS_OK;
   }
 
 private:
-  nsCOMPtr<nsIWidget> mWidget;
+  nsRefPtr<nsTextStateManager> mDispatcher;
 };
 
 nsresult
 nsTextStateManager::NotifySelectionChanged(nsIDOMDocument* aDoc,
                                            nsISelection* aSel,
                                            int16_t aReason)
 {
   int32_t count = 0;
   nsresult rv = aSel->GetRangeCount(&count);
   NS_ENSURE_SUCCESS(rv, rv);
   if (count > 0 && mWidget) {
-    nsContentUtils::AddScriptRunner(new SelectionChangeEvent(mWidget));
+    nsContentUtils::AddScriptRunner(new SelectionChangeEvent(this));
   }
   return NS_OK;
 }
 
 // Helper class, used for text change notification
 class TextChangeEvent : public nsRunnable {
 public:
-  TextChangeEvent(nsIWidget *widget,
+  TextChangeEvent(nsTextStateManager* aDispatcher,
                   uint32_t start, uint32_t oldEnd, uint32_t newEnd)
-    : mWidget(widget)
+    : mDispatcher(aDispatcher)
     , mStart(start)
     , mOldEnd(oldEnd)
     , mNewEnd(newEnd)
   {
-    MOZ_ASSERT(mWidget);
+    MOZ_ASSERT(mDispatcher);
   }
 
   NS_IMETHOD Run() {
-    if(mWidget) {
-        mWidget->OnIMETextChange(mStart, mOldEnd, mNewEnd);
+    if (mDispatcher->mWidget) {
+      mDispatcher->mWidget->OnIMETextChange(mStart, mOldEnd, mNewEnd);
     }
     return NS_OK;
   }
 
 private:
-  nsCOMPtr<nsIWidget> mWidget;
+  nsRefPtr<nsTextStateManager> mDispatcher;
   uint32_t mStart, mOldEnd, mNewEnd;
 };
 
 void
 nsTextStateManager::CharacterDataChanged(nsIDocument* aDocument,
                                          nsIContent* aContent,
                                          CharacterDataChangeInfo* aInfo)
 {
@@ -880,17 +881,17 @@ nsTextStateManager::CharacterDataChanged
   if (NS_FAILED(nsContentEventHandler::GetFlatTextOffsetOfRange(
                     mRootContent, aContent, aInfo->mChangeStart, &offset)))
     return;
 
   uint32_t oldEnd = offset + aInfo->mChangeEnd - aInfo->mChangeStart;
   uint32_t newEnd = offset + aInfo->mReplaceLength;
 
   nsContentUtils::AddScriptRunner(
-      new TextChangeEvent(mWidget, offset, oldEnd, newEnd));
+      new TextChangeEvent(this, offset, oldEnd, newEnd));
 }
 
 void
 nsTextStateManager::NotifyContentAdded(nsINode* aContainer,
                                        int32_t aStartIndex,
                                        int32_t aEndIndex)
 {
   uint32_t offset = 0, newOffset = 0;
@@ -902,17 +903,17 @@ nsTextStateManager::NotifyContentAdded(n
   if (NS_FAILED(nsContentEventHandler::GetFlatTextOffsetOfRange(
                     aContainer->GetChildAt(aStartIndex),
                     aContainer, aEndIndex, &newOffset)))
     return;
 
   // fire notification
   if (newOffset)
     nsContentUtils::AddScriptRunner(
-        new TextChangeEvent(mWidget, offset, offset, offset + newOffset));
+        new TextChangeEvent(this, offset, offset, offset + newOffset));
 }
 
 void
 nsTextStateManager::ContentAppended(nsIDocument* aDocument,
                                     nsIContent* aContainer,
                                     nsIContent* aFirstNewContent,
                                     int32_t aNewIndexInContainer)
 {
@@ -951,17 +952,17 @@ nsTextStateManager::ContentRemoved(nsIDo
 
   if (NS_FAILED(nsContentEventHandler::GetFlatTextOffsetOfRange(
                     aChild, aChild, childOffset, &childOffset)))
     return;
 
   // fire notification
   if (childOffset)
     nsContentUtils::AddScriptRunner(
-        new TextChangeEvent(mWidget, offset, offset + childOffset, offset));
+        new TextChangeEvent(this, offset, offset + childOffset, offset));
 }
 
 bool
 nsIMEStateManager::IsEditable(nsINode* node)
 {
   if (node->IsEditable()) {
     return true;
   }