From 941229d8adc504aa4d6b2abb7963f55fd61525b5 Mon Sep 17 00:00:00 2001 From: Masayuki Nakano Date: Thu, 11 Jul 2013 16:46:36 +0900 Subject: [PATCH] Bug 875674 part.8 Notify IME of focus change in Gecko for resetting IME stored window level r=smichaud --- widget/cocoa/TextInputHandler.h | 8 ++--- widget/cocoa/TextInputHandler.mm | 57 ++++++++++++++------------------ 2 files changed, 28 insertions(+), 37 deletions(-) diff --git a/widget/cocoa/TextInputHandler.h b/widget/cocoa/TextInputHandler.h index 3e67bac0623e..5413bebe41d0 100644 --- a/widget/cocoa/TextInputHandler.h +++ b/widget/cocoa/TextInputHandler.h @@ -955,9 +955,9 @@ protected: // See the comment in nsCocoaTextInputHandler.mm. nsCOMPtr mTimer; enum { - kResetIMEWindowLevel = 1, - kDiscardIMEComposition = 2, - kSyncASCIICapableOnly = 4 + kNotifyIMEOfFocusChangeInGecko = 1, + kDiscardIMEComposition = 2, + kSyncASCIICapableOnly = 4 }; uint32_t mPendingMethods; @@ -1006,7 +1006,7 @@ private: void OpenSystemPreferredLanguageIME(); // Pending methods - void ResetIMEWindowLevel(); + void NotifyIMEOfFocusChangeInGecko(); void DiscardIMEComposition(); void SyncASCIICapableOnly(); diff --git a/widget/cocoa/TextInputHandler.mm b/widget/cocoa/TextInputHandler.mm index 7a5cd5801903..4da550b2043c 100644 --- a/widget/cocoa/TextInputHandler.mm +++ b/widget/cocoa/TextInputHandler.mm @@ -2289,15 +2289,15 @@ IMEInputHandler::GetCurrentTSMDocumentID() ******************************************************************************/ void -IMEInputHandler::ResetIMEWindowLevel() +IMEInputHandler::NotifyIMEOfFocusChangeInGecko() { NS_OBJC_BEGIN_TRY_ABORT_BLOCK; PR_LOG(gLog, PR_LOG_ALWAYS, - ("%p IMEInputHandler::ResetIMEWindowLevel, " - "Destroyed()=%s, IsFocused()=%s, GetCurrentTSMDocumentID()=%p", + ("%p IMEInputHandler::NotifyIMEOfFocusChangeInGecko, " + "Destroyed()=%s, IsFocused()=%s, inputContext=%p", this, TrueOrFalse(Destroyed()), TrueOrFalse(IsFocused()), - GetCurrentTSMDocumentID())); + mView ? [mView inputContext] : nullptr)); if (Destroyed()) { return; @@ -2305,32 +2305,24 @@ IMEInputHandler::ResetIMEWindowLevel() if (!IsFocused()) { // retry at next focus event - mPendingMethods |= kResetIMEWindowLevel; + mPendingMethods |= kNotifyIMEOfFocusChangeInGecko; return; } - TSMDocumentID doc = GetCurrentTSMDocumentID(); - if (!doc) { - // retry - mPendingMethods |= kResetIMEWindowLevel; - NS_WARNING("Application is active but there is no active document"); - ResetTimer(); - return; - } + MOZ_ASSERT(mView); + NSTextInputContext* inputContext = [mView inputContext]; + NS_ENSURE_TRUE_VOID(inputContext); - // We need to set the focused window level to TSMDocument. Then, the popup - // windows of IME (E.g., a candidate list window) will be over the focused - // view. See http://developer.apple.com/technotes/tn2005/tn2128.html#TNTAG1 - NSInteger windowLevel = GetWindowLevel(); - - // Chinese IMEs on 10.5 don't work fine if the level is NSNormalWindowLevel, - // then, we need to increment the value. - if (windowLevel == NSNormalWindowLevel) - windowLevel++; - - ::TSMSetDocumentProperty(GetCurrentTSMDocumentID(), - kTSMDocumentWindowLevelPropertyTag, - sizeof(windowLevel), &windowLevel); + // When an element on a XUL element gets focus from an + // element on the opener window of the element, the owner window + // still has native focus. Therefore, IMEs may store the opener window's + // level at this time because they don't know the actual focus is moved to + // different window. If IMEs try to get the newest window level after the + // focus change, we return the window level of the XUL 's widget. + // Therefore, let's emulate the native focus change. Then, IMEs can refresh + // the stored window level. + [inputContext deactivate]; + [inputContext activate]; NS_OBJC_END_TRY_ABORT_BLOCK; } @@ -2458,8 +2450,9 @@ IMEInputHandler::ExecutePendingMethods() DiscardIMEComposition(); if (pendingMethods & kSyncASCIICapableOnly) SyncASCIICapableOnly(); - if (pendingMethods & kResetIMEWindowLevel) - ResetIMEWindowLevel(); + if (pendingMethods & kNotifyIMEOfFocusChangeInGecko) { + NotifyIMEOfFocusChangeInGecko(); + } mIsInFocusProcessing = false; @@ -3191,11 +3184,9 @@ IMEInputHandler::OnFocusChangeInGecko(bool aFocus) sFocusedIMEHandler = this; mIsInFocusProcessing = true; - // We need to reset the IME's window level by the current focused view of - // Gecko. It may be different from mView. However, we cannot get the - // new focused view here because the focus change process in Gecko hasn't - // been finished yet. So, we should post the job to the todo list. - mPendingMethods |= kResetIMEWindowLevel; + // We need to notify IME of focus change in Gecko as native focus change + // because the window level of the focused element in Gecko may be changed. + mPendingMethods |= kNotifyIMEOfFocusChangeInGecko; ResetTimer(); }