From b775a569684db506842cccb0bfb435c52da4d248 Mon Sep 17 00:00:00 2001 From: Masayuki Nakano Date: Thu, 17 Jul 2014 14:08:44 +0900 Subject: [PATCH] Bug 1037346 IMEStateManager should ignore a call of UpdateIMEState() which is caused by a call of nsIContent::GetDesiredIMEState() r=smaug --- dom/events/IMEStateManager.cpp | 21 +++++++++++++++++++-- dom/events/IMEStateManager.h | 17 +++++++++++++++++ 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/dom/events/IMEStateManager.cpp b/dom/events/IMEStateManager.cpp index bb11a62c1e7..a618055e23f 100644 --- a/dom/events/IMEStateManager.cpp +++ b/dom/events/IMEStateManager.cpp @@ -191,6 +191,7 @@ nsIContent* IMEStateManager::sContent = nullptr; nsPresContext* IMEStateManager::sPresContext = nullptr; bool IMEStateManager::sInstalledMenuKeyboardListener = false; bool IMEStateManager::sIsTestingIME = false; +bool IMEStateManager::sIsGettingNewIMEState = false; // sActiveIMEContentObserver points to the currently active IMEContentObserver. // sActiveIMEContentObserver is null if there is no focused editor. @@ -568,10 +569,19 @@ IMEStateManager::UpdateIMEState(const IMEState& aNewIMEState, PR_LOG(sISMLog, PR_LOG_ALWAYS, ("ISM: IMEStateManager::UpdateIMEState(aNewIMEState={ mEnabled=%s, " "mOpen=%s }, aContent=0x%p), " - "sPresContext=0x%p, sContent=0x%p, sActiveIMEContentObserver=0x%p", + "sPresContext=0x%p, sContent=0x%p, sActiveIMEContentObserver=0x%p, " + "sIsGettingNewIMEState=%s", GetIMEStateEnabledName(aNewIMEState.mEnabled), GetIMEStateSetOpenName(aNewIMEState.mOpen), aContent, - sPresContext, sContent, sActiveIMEContentObserver)); + sPresContext, sContent, sActiveIMEContentObserver, + GetBoolName(sIsGettingNewIMEState))); + + if (sIsGettingNewIMEState) { + PR_LOG(sISMLog, PR_LOG_DEBUG, + ("ISM: IMEStateManager::UpdateIMEState(), " + "does nothing because of called while getting new IME state")); + return; + } if (NS_WARN_IF(!sPresContext)) { PR_LOG(sISMLog, PR_LOG_ERROR, @@ -659,6 +669,13 @@ IMEStateManager::GetNewIMEState(nsPresContext* aPresContext, return IMEState(IMEState::DISABLED); } + // nsIContent::GetDesiredIMEState() may cause a call of UpdateIMEState() + // from nsEditor::PostCreate() because GetDesiredIMEState() needs to retrieve + // an editor instance for the element if it's editable element. + // For avoiding such nested IME state updates, we should set + // sIsGettingNewIMEState here and UpdateIMEState() should check it. + GettingNewIMEStateBlocker blocker; + IMEState newIMEState = aContent->GetDesiredIMEState(); PR_LOG(sISMLog, PR_LOG_DEBUG, ("ISM: IMEStateManager::GetNewIMEState() returns { mEnabled=%s, " diff --git a/dom/events/IMEStateManager.h b/dom/events/IMEStateManager.h index e5bc87b7140..a6e8864c53d 100644 --- a/dom/events/IMEStateManager.h +++ b/dom/events/IMEStateManager.h @@ -146,6 +146,23 @@ protected: static nsPresContext* sPresContext; static bool sInstalledMenuKeyboardListener; static bool sIsTestingIME; + static bool sIsGettingNewIMEState; + + class MOZ_STACK_CLASS GettingNewIMEStateBlocker MOZ_FINAL + { + public: + GettingNewIMEStateBlocker() + : mOldValue(IMEStateManager::sIsGettingNewIMEState) + { + IMEStateManager::sIsGettingNewIMEState = true; + } + ~GettingNewIMEStateBlocker() + { + IMEStateManager::sIsGettingNewIMEState = mOldValue; + } + private: + bool mOldValue; + }; static IMEContentObserver* sActiveIMEContentObserver;