diff --git a/content/base/public/nsContentUtils.h b/content/base/public/nsContentUtils.h index 86f3eff700e7..f6de05c5addd 100644 --- a/content/base/public/nsContentUtils.h +++ b/content/base/public/nsContentUtils.h @@ -1019,6 +1019,10 @@ public: void *mObject; }; + /** + * Convert nsIContent::IME_STATUS_* to nsIKBStateControll::IME_STATUS_* + */ + static PRUint32 GetKBStateControlStatusFromIMEStatus(PRUint32 aState); private: static PRBool InitializeEventTable(); diff --git a/content/base/public/nsIContent.h b/content/base/public/nsIContent.h index 8f1bb56c90a8..342144c88f7c 100644 --- a/content/base/public/nsIContent.h +++ b/content/base/public/nsIContent.h @@ -524,16 +524,21 @@ public: * the previous OPEN/CLOSE state will be restored (unless the newly * focused content specifies the OPEN/CLOSE state by setting the OPEN * or CLOSE flag with the ENABLE flag). + * IME_STATUS_PASSWORD should be returned only from password editor, + * this value has a special meaning. It is used as alternative of + * IME_STATUS_DISABLED. */ enum { - IME_STATUS_NONE = 0x0000, - IME_STATUS_ENABLE = 0x0001, - IME_STATUS_DISABLE = 0x0002, - IME_STATUS_OPEN = 0x0004, - IME_STATUS_CLOSE = 0x0008 + IME_STATUS_NONE = 0x0000, + IME_STATUS_ENABLE = 0x0001, + IME_STATUS_DISABLE = 0x0002, + IME_STATUS_PASSWORD = 0x0004, + IME_STATUS_OPEN = 0x0008, + IME_STATUS_CLOSE = 0x0010 }; enum { - IME_STATUS_MASK_ENABLED = IME_STATUS_ENABLE | IME_STATUS_DISABLE, + IME_STATUS_MASK_ENABLED = IME_STATUS_ENABLE | IME_STATUS_DISABLE | + IME_STATUS_PASSWORD, IME_STATUS_MASK_OPENED = IME_STATUS_OPEN | IME_STATUS_CLOSE }; virtual PRUint32 GetDesiredIMEState() diff --git a/content/base/src/nsContentUtils.cpp b/content/base/src/nsContentUtils.cpp index 9f6b18e84616..e633969776d6 100644 --- a/content/base/src/nsContentUtils.cpp +++ b/content/base/src/nsContentUtils.cpp @@ -136,6 +136,7 @@ static NS_DEFINE_CID(kXTFServiceCID, NS_XTFSERVICE_CID); #include "nsTPtrArray.h" #include "nsGUIEvent.h" #include "nsMutationEvent.h" +#include "nsIKBStateControl.h" #ifdef IBMBIDI #include "nsIBidiKeyboard.h" @@ -3573,3 +3574,20 @@ nsContentUtils::DropScriptObject(PRUint32 aLangID, void *aObject) } return rv; } + +/* static */ +PRUint32 +nsContentUtils::GetKBStateControlStatusFromIMEStatus(PRUint32 aState) +{ + switch (aState & nsIContent::IME_STATUS_MASK_ENABLED) { + case nsIContent::IME_STATUS_DISABLE: + return nsIKBStateControl::IME_STATUS_DISABLED; + case nsIContent::IME_STATUS_ENABLE: + return nsIKBStateControl::IME_STATUS_ENABLED; + case nsIContent::IME_STATUS_PASSWORD: + return nsIKBStateControl::IME_STATUS_PASSWORD; + default: + NS_ERROR("The given state doesn't have valid enable state"); + return nsIKBStateControl::IME_STATUS_ENABLED; + } +} diff --git a/content/events/src/nsIMEStateManager.cpp b/content/events/src/nsIMEStateManager.cpp index 2cd5e49e9727..0b39f6cde79d 100755 --- a/content/events/src/nsIMEStateManager.cpp +++ b/content/events/src/nsIMEStateManager.cpp @@ -53,6 +53,7 @@ #include "nsIKBStateControl.h" #include "nsIFocusController.h" #include "nsIDOMWindow.h" +#include "nsContentUtils.h" /******************************************************************/ /* nsIMEStateManager */ @@ -123,13 +124,13 @@ nsIMEStateManager::OnChangeFocus(nsPresContext* aPresContext, // the enabled state isn't changing, we should do nothing. return NS_OK; } - PRBool enabled; + PRUint32 enabled; if (NS_FAILED(kb->GetIMEEnabled(&enabled))) { // this platform doesn't support IME controlling return NS_OK; } - if ((enabled && newEnabledState == nsIContent::IME_STATUS_ENABLE) || - (!enabled && newEnabledState == nsIContent::IME_STATUS_DISABLE)) { + if (enabled == + nsContentUtils::GetKBStateControlStatusFromIMEStatus(newEnabledState)) { // the enabled state isn't changing. return NS_OK; } @@ -172,9 +173,20 @@ nsIMEStateManager::OnDeactivate(nsPresContext* aPresContext) { NS_ENSURE_ARG_POINTER(aPresContext); NS_ENSURE_TRUE(aPresContext->Document()->GetWindow(), NS_ERROR_FAILURE); - if (sActiveWindow == + if (sActiveWindow != aPresContext->Document()->GetWindow()->GetPrivateRoot()) - sActiveWindow = nsnull; + return NS_OK; + + sActiveWindow = nsnull; +#ifdef NS_KBSC_USE_SHARED_CONTEXT + // Reset the latest content. When the window is activated, the IME state + // may be changed on other applications. + sContent = nsnull; + // We should enable the IME state for other applications. + nsIKBStateControl* kb = GetKBStateControl(aPresContext); + if (kb) + SetIMEState(aPresContext, nsIContent::IME_STATUS_ENABLE, kb); +#endif // NS_KBSC_USE_SHARED_CONTEXT return NS_OK; } @@ -238,8 +250,9 @@ nsIMEStateManager::SetIMEState(nsPresContext* aPresContext, nsIKBStateControl* aKB) { if (aState & nsIContent::IME_STATUS_MASK_ENABLED) { - PRBool enable = (aState & nsIContent::IME_STATUS_ENABLE); - aKB->SetIMEEnabled(enable); + PRUint32 state = + nsContentUtils::GetKBStateControlStatusFromIMEStatus(aState); + aKB->SetIMEEnabled(state); } if (aState & nsIContent::IME_STATUS_MASK_OPENED) { PRBool open = (aState & nsIContent::IME_STATUS_OPEN); diff --git a/editor/libeditor/base/nsEditor.cpp b/editor/libeditor/base/nsEditor.cpp index 189c08be1e2b..3c70497fd9a5 100644 --- a/editor/libeditor/base/nsEditor.cpp +++ b/editor/libeditor/base/nsEditor.cpp @@ -2208,10 +2208,11 @@ nsEditor::GetPreferredIMEState(PRUint32 *aState) PRUint32 flags; if (NS_SUCCEEDED(GetFlags(&flags)) && - flags & (nsIPlaintextEditor::eEditorPasswordMask | - nsIPlaintextEditor::eEditorReadonlyMask | + flags & (nsIPlaintextEditor::eEditorReadonlyMask | nsIPlaintextEditor::eEditorDisabledMask)) *aState = nsIContent::IME_STATUS_DISABLE; + else if (flags & nsIPlaintextEditor::eEditorPasswordMask) + *aState = nsIContent::IME_STATUS_PASSWORD; else *aState = nsIContent::IME_STATUS_ENABLE; return NS_OK; diff --git a/widget/public/nsIKBStateControl.h b/widget/public/nsIKBStateControl.h index ccbffeab11b1..ab308c61307e 100644 --- a/widget/public/nsIKBStateControl.h +++ b/widget/public/nsIKBStateControl.h @@ -41,12 +41,21 @@ #include "nsISupports.h" -// {8C636698-8075-4547-80AD-B032F08EF2D3} +// {BC33E975-C433-4df5-B4BA-041CDE6D1A17} #define NS_IKBSTATECONTROL_IID \ -{ 0x8c636698, 0x8075, 0x4547, \ -{ 0x80, 0xad, 0xb0, 0x32, 0xf0, 0x8e, 0xf2, 0xd3 } } +{ 0xbc33e975, 0xc433, 0x4df5, \ +{ 0xb4, 0xba, 0x04, 0x1c, 0xde, 0x6d, 0x1a, 0x17 } } +#if defined(XP_MACOSX) +/* + * If the all applications use same context for IME, i.e., When gecko changes + * the state of IME, the same changes can be on other processes. + * Then, NS_KBSC_USE_SHARED_CONTEXT should be defined. + */ +#define NS_KBSC_USE_SHARED_CONTEXT 1 +#endif + /** * interface to control keyboard input state */ @@ -86,18 +95,37 @@ class nsIKBStateControl : public nsISupports { NS_IMETHOD GetIMEOpenState(PRBool* aState) = 0; /* - * Set the state to 'Enabled' or 'Disabled'. - * If aState is TRUE, IME enable state is set to 'Enabled'. - * If aState is FALSE, set to 'Disabled'. + * IME enabled states, the aState value of SetIMEEnabled/GetIMEEnabled + * should be one value of following values. */ - NS_IMETHOD SetIMEEnabled(PRBool aState) = 0; + enum { + /* + * 'Disabled' means the user cannot use IME. So, the open state should be + * 'closed' during 'disabled'. + */ + IME_STATUS_DISABLED = 0, + /* + * 'Enabled' means the user can use IME. + */ + IME_STATUS_ENABLED = 1, + /* + * 'Password' state is a special case for the password editors. + * E.g., on mac, the password editors should disable the non-Roman + * keyboard layouts at getting focus. Thus, the password editor may have + * special rules on some platforms. + */ + IME_STATUS_PASSWORD = 2 + }; /* - * Get IME is 'Enabled' or 'Disabled'. - * If IME is 'Enabled', aState is set PR_TRUE. - * If IME is 'Disabled', aState is set PR_FALSE. + * Set the state to 'Enabled' or 'Disabled' or 'Password'. */ - NS_IMETHOD GetIMEEnabled(PRBool* aState) = 0; + NS_IMETHOD SetIMEEnabled(PRUint32 aState) = 0; + + /* + * Get IME is 'Enabled' or 'Disabled' or 'Password'. + */ + NS_IMETHOD GetIMEEnabled(PRUint32* aState) = 0; /* * Destruct and don't commit the IME composition string. diff --git a/widget/src/cocoa/nsChildView.h b/widget/src/cocoa/nsChildView.h index 09da6e3581d5..05f104a41807 100644 --- a/widget/src/cocoa/nsChildView.h +++ b/widget/src/cocoa/nsChildView.h @@ -98,7 +98,6 @@ union nsPluginPort; // needed for NSTextInput implementation NSRange mMarkedRange; NSRange mSelectedRange; - BOOL mInComposition; BOOL mIgnoreDoCommand; BOOL mInHandScroll; // true for as long as we are hand scrolling @@ -126,12 +125,41 @@ union nsPluginPort; // these are sent to the first responder when the window key status changes - (void)viewsWindowDidBecomeKey; - (void)viewsWindowDidResignKey; - -- (BOOL)isComposing; @end +//------------------------------------------------------------------------- +// +// nsTSMManager +// +//------------------------------------------------------------------------- + +class nsTSMManager { +public: + static PRBool IsComposing() { return sComposingView ? PR_TRUE : PR_FALSE; } + static PRBool IsIMEEnabled() { return sIsIMEEnabled; } + + // Note that we cannot get the actual state in TSM. But we can trust this + // value. Because nsIMEStateManager reset this at every focus changing. + static PRBool IsRomanKeyboardsOnly() { return sIsRomanKeyboardsOnly; } + + static PRBool GetIMEOpenState(); + + static void StartComposing(NSView* aComposingView); + static void EndComposing(); + static void EnableIME(PRBool aEnable); + static void SetIMEOpenState(PRBool aOpen); + static void SetRomanKeyboardsOnly(PRBool aRomanOnly); + + static void CommitIME(); + static void CancelIME(); +private: + static PRBool sIsIMEEnabled; + static PRBool sIsRomanKeyboardsOnly; + static NSView* sComposingView; +}; + //------------------------------------------------------------------------- // // nsChildView @@ -157,8 +185,8 @@ public: NS_IMETHOD ResetInputState(); NS_IMETHOD SetIMEOpenState(PRBool aState); NS_IMETHOD GetIMEOpenState(PRBool* aState); - NS_IMETHOD SetIMEEnabled(PRBool aState); - NS_IMETHOD GetIMEEnabled(PRBool* aState); + NS_IMETHOD SetIMEEnabled(PRUint32 aState); + NS_IMETHOD GetIMEEnabled(PRUint32* aState); NS_IMETHOD CancelIMEComposition(); // nsIWidget interface diff --git a/widget/src/cocoa/nsChildView.mm b/widget/src/cocoa/nsChildView.mm index 3ff483482f4f..609b6fd88cea 100644 --- a/widget/src/cocoa/nsChildView.mm +++ b/widget/src/cocoa/nsChildView.mm @@ -78,6 +78,10 @@ extern "C" { CG_EXTERN void CGContextResetClip(CGContextRef); } +PRBool nsTSMManager::sIsIMEEnabled = PR_TRUE; +PRBool nsTSMManager::sIsRomanKeyboardsOnly = PR_FALSE; +NSView* nsTSMManager::sComposingView = nsnull; + static NS_DEFINE_CID(kRegionCID, NS_REGION_CID); static NSView* sLastViewEntered = nil; #ifdef INVALIDATE_DEBUGGING @@ -1575,17 +1579,7 @@ NS_IMETHODIMP nsChildView::ResetInputState() NSLog(@"**** ResetInputState"); #endif - if (![mView isComposing]) - return NS_OK; - - NSInputManager *currentIM = [NSInputManager currentInputManager]; - - // commit the current text - [currentIM unmarkText]; - - // and clear the input manager's string - [currentIM markedTextAbandoned:mView]; - + nsTSMManager::CommitIME(); return NS_OK; } @@ -1593,26 +1587,66 @@ NS_IMETHODIMP nsChildView::ResetInputState() // 'open' means that it can take non-ASCII chars NS_IMETHODIMP nsChildView::SetIMEOpenState(PRBool aState) { - return NS_ERROR_NOT_IMPLEMENTED; +#ifdef DEBUG_IME + NSLog(@"**** SetIMEOpenState aState = %d", aState); +#endif + + nsTSMManager::SetIMEOpenState(aState); + return NS_OK; } // 'open' means that it can take non-ASCII chars NS_IMETHODIMP nsChildView::GetIMEOpenState(PRBool* aState) { - return NS_ERROR_NOT_IMPLEMENTED; +#ifdef DEBUG_IME + NSLog(@"**** GetIMEOpenState"); +#endif + + *aState = nsTSMManager::GetIMEOpenState(); + return NS_OK; } -NS_IMETHODIMP nsChildView::SetIMEEnabled(PRBool aState) +NS_IMETHODIMP nsChildView::SetIMEEnabled(PRUint32 aState) { - return NS_ERROR_NOT_IMPLEMENTED; +#ifdef DEBUG_IME + NSLog(@"**** SetIMEEnabled aState = %d", aState); +#endif + + switch (aState) { + case nsIKBStateControl::IME_STATUS_ENABLED: + nsTSMManager::SetRomanKeyboardsOnly(PR_FALSE); + nsTSMManager::EnableIME(PR_TRUE); + break; + case nsIKBStateControl::IME_STATUS_DISABLED: + nsTSMManager::SetRomanKeyboardsOnly(PR_FALSE); + nsTSMManager::EnableIME(PR_FALSE); + break; + case nsIKBStateControl::IME_STATUS_PASSWORD: + nsTSMManager::SetRomanKeyboardsOnly(PR_TRUE); + nsTSMManager::EnableIME(PR_FALSE); + break; + default: + NS_ERROR("not implemented!"); + } + return NS_OK; } -NS_IMETHODIMP nsChildView::GetIMEEnabled(PRBool* aState) +NS_IMETHODIMP nsChildView::GetIMEEnabled(PRUint32* aState) { - return NS_ERROR_NOT_IMPLEMENTED; +#ifdef DEBUG_IME + NSLog(@"**** GetIMEEnabled"); +#endif + + if (nsTSMManager::IsIMEEnabled()) + *aState = nsIKBStateControl::IME_STATUS_ENABLED; + else if (nsTSMManager::IsRomanKeyboardsOnly()) + *aState = nsIKBStateControl::IME_STATUS_PASSWORD; + else + *aState = nsIKBStateControl::IME_STATUS_DISABLED; + return NS_OK; } @@ -1623,12 +1657,7 @@ NS_IMETHODIMP nsChildView::CancelIMEComposition() NSLog(@"**** CancelIMEComposition"); #endif - if (![mView isComposing]) - return NS_OK; - - NSInputManager *currentIM = [NSInputManager currentInputManager]; - [currentIM markedTextAbandoned:mView]; - + nsTSMManager::CancelIME(); return NS_OK; } @@ -1785,7 +1814,6 @@ NSEvent* globalDragEvent = nil; mMarkedRange.length = 0; mSelectedRange.location = NSNotFound; mSelectedRange.length = 0; - mInComposition = NO; mLastMenuForEventEvent = nil; mDragService = nsnull; } @@ -2915,7 +2943,7 @@ static void ConvertCocoaKeyEventToMacEvent(NSEvent* cocoaEvent, EventRecord& mac [tmpStr getCharacters: bufPtr]; bufPtr[len] = (PRUnichar)'\0'; - if (len == 1 && !mInComposition) { + if (len == 1 && !nsTSMManager::IsComposing()) { // dispatch keypress event with char instead of textEvent nsKeyEvent geckoEvent(PR_TRUE, NS_KEY_PRESS, mGeckoChild); geckoEvent.time = PR_IntervalNow(); @@ -2938,10 +2966,10 @@ static void ConvertCocoaKeyEventToMacEvent(NSEvent* cocoaEvent, EventRecord& mac mGeckoChild->DispatchWindowEvent(geckoEvent); } else { - if (!mInComposition) { + if (!nsTSMManager::IsComposing()) { // send start composition event to gecko [self sendCompositionEvent: NS_COMPOSITION_START]; - mInComposition = YES; + nsTSMManager::StartComposing(self); } // dispatch textevent (is this redundant?) @@ -2952,7 +2980,7 @@ static void ConvertCocoaKeyEventToMacEvent(NSEvent* cocoaEvent, EventRecord& mac // send end composition event to gecko [self sendCompositionEvent: NS_COMPOSITION_END]; - mInComposition = NO; + nsTSMManager::EndComposing(); mSelectedRange = mMarkedRange = NSMakeRange(NSNotFound, 0); } @@ -3009,9 +3037,9 @@ static void ConvertCocoaKeyEventToMacEvent(NSEvent* cocoaEvent, EventRecord& mac mMarkedRange.location = 0; mMarkedRange.length = len; - if (!mInComposition) { + if (!nsTSMManager::IsComposing()) { [self sendCompositionEvent:NS_COMPOSITION_START]; - mInComposition = YES; + nsTSMManager::StartComposing(self); } [self sendTextEvent:bufPtr attributedString:aString @@ -3019,7 +3047,7 @@ static void ConvertCocoaKeyEventToMacEvent(NSEvent* cocoaEvent, EventRecord& mac markedRange:mMarkedRange doCommit:NO]; - if (mInComposition && len == 0) + if (nsTSMManager::IsComposing() && len == 0) [self unmarkText]; if (bufPtr != buffer) @@ -3036,9 +3064,10 @@ static void ConvertCocoaKeyEventToMacEvent(NSEvent* cocoaEvent, EventRecord& mac #endif mSelectedRange = mMarkedRange = NSMakeRange(NSNotFound, 0); - if (mInComposition) { + if (nsTSMManager::IsComposing()) { [self sendCompositionEvent: NS_COMPOSITION_END]; - mInComposition = NO; // brade: do we need to send an end composition event? + // brade: do we need to send an end composition event? + nsTSMManager::EndComposing(); } } @@ -3191,6 +3220,7 @@ static void ConvertCocoaKeyEventToMacEvent(NSEvent* cocoaEvent, EventRecord& mac return; } + PRBool dispatchedKeyPress = PR_FALSE; if (nonDeadKeyPress) { nsKeyEvent geckoEvent(PR_TRUE, NS_KEY_PRESS, nsnull); [self convertKeyEvent:theEvent toGeckoEvent:&geckoEvent]; @@ -3202,17 +3232,26 @@ static void ConvertCocoaKeyEventToMacEvent(NSEvent* cocoaEvent, EventRecord& mac // dispatch the keydown to gecko, so that we trap delete, // control-letter combinations etc before Cocoa tries to use // them for keybindings. - if ((!geckoEvent.isChar || geckoEvent.isControl) && !mInComposition) { + if ((!geckoEvent.isChar || geckoEvent.isControl) && + !nsTSMManager::IsComposing()) { // plugins need a native event, it will either be keyDown or autoKey EventRecord macEvent; ConvertCocoaKeyEventToMacEvent(theEvent, macEvent); geckoEvent.nativeMsg = &macEvent; mIgnoreDoCommand = mGeckoChild->DispatchWindowEvent(geckoEvent); + dispatchedKeyPress = PR_TRUE; } } - [super interpretKeyEvents:[NSArray arrayWithObject:theEvent]]; + // We should send this event to the superclass if IME is enabled. + // Otherwise, we need to suppress IME composition. We can do it by + // not sending this event to the superclass. But in that case, + // we need to call insertText ourselves. + if (nsTSMManager::IsIMEEnabled()) + [super interpretKeyEvents:[NSArray arrayWithObject:theEvent]]; + else if (nonDeadKeyPress && !dispatchedKeyPress) + [self insertText:[theEvent characters]]; mIgnoreDoCommand = NO; mCurKeyEvent = nil; @@ -3242,7 +3281,7 @@ static void ConvertCocoaKeyEventToMacEvent(NSEvent* cocoaEvent, EventRecord& mac - (BOOL)performKeyEquivalent:(NSEvent*)theEvent { // don't bother if we're in composition - if (mInComposition) + if (nsTSMManager::IsComposing()) return NO; // see if the menu system will handle the event @@ -3372,12 +3411,6 @@ static void ConvertCocoaKeyEventToMacEvent(NSEvent* cocoaEvent, EventRecord& mac } -- (BOOL)isComposing -{ - return mInComposition; -} - - // Key code constants enum { @@ -3925,3 +3958,94 @@ static PRBool IsSpecialGeckoKey(UInt32 macKeyCode) #endif /* ACCESSIBILITY */ @end + + +#pragma mark - + + +PRBool +nsTSMManager::GetIMEOpenState() +{ + return GetScriptManagerVariable(smKeyScript) != smRoman ? PR_TRUE : PR_FALSE; +} + + +void +nsTSMManager::StartComposing(NSView* aComposingView) +{ + if (sComposingView && sComposingView != sComposingView) + CommitIME(); + sComposingView = aComposingView; +} + + +void +nsTSMManager::EndComposing() +{ + sComposingView = nsnull; +} + + +void +nsTSMManager::EnableIME(PRBool aEnable) +{ + if (aEnable == sIsIMEEnabled) + return; + CommitIME(); + sIsIMEEnabled = aEnable; +} + + +void +nsTSMManager::SetIMEOpenState(PRBool aOpen) +{ + if (aOpen == GetIMEOpenState()) + return; + CommitIME(); + KeyScript(aOpen ? smKeySwapScript : smKeyRoman); +} + + +#define ENABLE_ROMAN_KYBDS_ONLY -23 +void +nsTSMManager::SetRomanKeyboardsOnly(PRBool aRomanOnly) +{ + if (aRomanOnly == sIsRomanKeyboardsOnly) + return; + CommitIME(); + KeyScript(aRomanOnly ? ENABLE_ROMAN_KYBDS_ONLY : smKeyEnableKybds); + sIsRomanKeyboardsOnly = aRomanOnly; +} + + +void +nsTSMManager::CommitIME() +{ + if (!sComposingView) + return; + + NSInputManager *currentIM = [NSInputManager currentInputManager]; + + // commit the current text + [currentIM unmarkText]; + + // and clear the input manager's string + [currentIM markedTextAbandoned:sComposingView]; + + EndComposing(); +} + + +void +nsTSMManager::CancelIME() +{ + if (!sComposingView) + return; + + NSInputManager *currentIM = [NSInputManager currentInputManager]; + + // clear the input manager's string + [currentIM markedTextAbandoned:sComposingView]; + + EndComposing(); +} diff --git a/widget/src/gtk/nsWidget.cpp b/widget/src/gtk/nsWidget.cpp index e08252d0054a..90d84e1e0b64 100644 --- a/widget/src/gtk/nsWidget.cpp +++ b/widget/src/gtk/nsWidget.cpp @@ -2374,11 +2374,11 @@ NS_IMETHODIMP nsWidget::GetIMEOpenState(PRBool* aState) { return NS_ERROR_NOT_IMPLEMENTED; } -NS_IMETHODIMP nsWidget::SetIMEEnabled(PRBool aState) { +NS_IMETHODIMP nsWidget::SetIMEEnabled(PRUint32 aState) { return NS_ERROR_NOT_IMPLEMENTED; } -NS_IMETHODIMP nsWidget::GetIMEEnabled(PRBool* aState) { +NS_IMETHODIMP nsWidget::GetIMEEnabled(PRUint32* aState) { return NS_ERROR_NOT_IMPLEMENTED; } diff --git a/widget/src/gtk/nsWidget.h b/widget/src/gtk/nsWidget.h index 7718f9e024ed..aa8f385c8712 100644 --- a/widget/src/gtk/nsWidget.h +++ b/widget/src/gtk/nsWidget.h @@ -174,8 +174,8 @@ public: NS_IMETHOD ResetInputState(); NS_IMETHOD SetIMEOpenState(PRBool aState); NS_IMETHOD GetIMEOpenState(PRBool* aState); - NS_IMETHOD SetIMEEnabled(PRBool aState); - NS_IMETHOD GetIMEEnabled(PRBool* aState); + NS_IMETHOD SetIMEEnabled(PRUint32 aState); + NS_IMETHOD GetIMEEnabled(PRUint32* aState); NS_IMETHOD CancelIMEComposition(); void InitEvent(nsGUIEvent& event, nsPoint* aPoint = nsnull); diff --git a/widget/src/gtk2/nsWindow.cpp b/widget/src/gtk2/nsWindow.cpp index 1d035011ba1d..2595f48c11b6 100644 --- a/widget/src/gtk2/nsWindow.cpp +++ b/widget/src/gtk2/nsWindow.cpp @@ -5068,7 +5068,7 @@ nsWindow::IMEDestroyContext(void) } mIMEData->mOwner = nsnull; - mIMEData->mEnabled = PR_FALSE; + mIMEData->mEnabled = nsIKBStateControl::IME_STATUS_DISABLED; if (mIMEData->mContext) { gtk_im_context_set_client_window(mIMEData->mContext, nsnull); @@ -5231,10 +5231,16 @@ nsWindow::IMEGetContext() return IM_get_input_context(this); } +static PRBool +IsIMEEnabledState(PRUint32 aState) +{ + return aState == nsIKBStateControl::IME_STATUS_ENABLED ? PR_TRUE : PR_FALSE; +} + PRBool nsWindow::IMEIsEnabled(void) { - return mIMEData ? mIMEData->mEnabled : PR_FALSE; + return mIMEData ? IsIMEEnabledState(mIMEData->mEnabled) : PR_FALSE; } nsWindow* @@ -5354,13 +5360,19 @@ nsWindow::GetIMEOpenState(PRBool* aState) } NS_IMETHODIMP -nsWindow::SetIMEEnabled(PRBool aState) +nsWindow::SetIMEEnabled(PRUint32 aState) { IMEInitData(); - - if (!mIMEData || mIMEData->mEnabled == aState) + if (!mIMEData) return NS_OK; + PRBool newState = IsIMEEnabledState(aState); + PRBool oldState = IsIMEEnabledState(mIMEData->mEnabled); + if (newState == oldState) { + mIMEData->mEnabled = aState; + return NS_OK; + } + GtkIMContext *focusedIm = nsnull; // XXX Don't we need to check gFocusWindow? nsWindow *focusedWin = gIMEFocusWindow; @@ -5369,7 +5381,7 @@ nsWindow::SetIMEEnabled(PRBool aState) if (focusedIm && focusedIm == mIMEData->mContext) { // Release current IME focus if IME is enabled. - if (mIMEData->mEnabled) { + if (oldState) { focusedWin->ResetInputState(); focusedWin->IMELoseFocus(); } @@ -5380,7 +5392,7 @@ nsWindow::SetIMEEnabled(PRBool aState) // Because some IMs are updating the status bar of them in this time. focusedWin->IMESetFocus(); } else { - if (mIMEData->mEnabled) + if (oldState) ResetInputState(); mIMEData->mEnabled = aState; } @@ -5389,13 +5401,14 @@ nsWindow::SetIMEEnabled(PRBool aState) } NS_IMETHODIMP -nsWindow::GetIMEEnabled(PRBool* aState) +nsWindow::GetIMEEnabled(PRUint32* aState) { NS_ENSURE_ARG_POINTER(aState); IMEInitData(); - *aState = IMEIsEnabled(); + *aState = + mIMEData ? mIMEData->mEnabled : nsIKBStateControl::IME_STATUS_DISABLED; return NS_OK; } diff --git a/widget/src/gtk2/nsWindow.h b/widget/src/gtk2/nsWindow.h index 2720d92ec911..7346685ac29b 100644 --- a/widget/src/gtk2/nsWindow.h +++ b/widget/src/gtk2/nsWindow.h @@ -318,14 +318,14 @@ public: // the decrementer must free the instance. PRUint32 mRefCount; // IME enabled state in this window. - PRPackedBool mEnabled; + PRUint32 mEnabled; nsIMEData(nsWindow* aOwner) { mContext = nsnull; mDummyContext = nsnull; mComposingWindow = nsnull; mOwner = aOwner; mRefCount = 1; - mEnabled = PR_TRUE; + mEnabled = nsIKBStateControl::IME_STATUS_ENABLED; } }; nsIMEData *mIMEData; @@ -334,8 +334,8 @@ public: NS_IMETHOD ResetInputState(); NS_IMETHOD SetIMEOpenState(PRBool aState); NS_IMETHOD GetIMEOpenState(PRBool* aState); - NS_IMETHOD SetIMEEnabled(PRBool aState); - NS_IMETHOD GetIMEEnabled(PRBool* aState); + NS_IMETHOD SetIMEEnabled(PRUint32 aState); + NS_IMETHOD GetIMEEnabled(PRUint32* aState); NS_IMETHOD CancelIMEComposition(); #endif diff --git a/widget/src/mac/nsWindow.cpp b/widget/src/mac/nsWindow.cpp index c5866d6bfcfd..37180a874e6f 100644 --- a/widget/src/mac/nsWindow.cpp +++ b/widget/src/mac/nsWindow.cpp @@ -475,7 +475,7 @@ void* nsWindow::GetNativeData(PRUint32 aDataType) break; case NS_NATIVE_COLORMAP: - //¥TODO + // TODO break; case NS_NATIVE_OFFSETX: @@ -638,7 +638,7 @@ NS_IMETHODIMP nsWindow::SetFont(const nsFont &aFont) //------------------------------------------------------------------------- NS_IMETHODIMP nsWindow::SetColorMap(nsColorMap *aColorMap) { - //¥TODO + // TODO // We may need to move this to nsMacWindow: // I'm not sure all the individual widgets // can have each their own colorMap on Mac. @@ -1107,7 +1107,7 @@ void nsWindow::StartDraw(nsIRenderingContext* aRenderingContext) return; mDrawing = PR_TRUE; - CalcWindowRegions(); //¥REVISIT + CalcWindowRegions(); // REVISIT if (aRenderingContext == nsnull) { @@ -2367,11 +2367,11 @@ NS_IMETHODIMP nsWindow::GetIMEOpenState(PRBool* aState) { return NS_ERROR_NOT_IMPLEMENTED; } -NS_IMETHODIMP nsWindow::SetIMEEnabled(PRBool aState) { +NS_IMETHODIMP nsWindow::SetIMEEnabled(PRUint32 aState) { return NS_ERROR_NOT_IMPLEMENTED; } -NS_IMETHODIMP nsWindow::GetIMEEnabled(PRBool* aState) { +NS_IMETHODIMP nsWindow::GetIMEEnabled(PRUint32* aState) { return NS_ERROR_NOT_IMPLEMENTED; } diff --git a/widget/src/mac/nsWindow.h b/widget/src/mac/nsWindow.h index 46aef8c31da5..80e75417896e 100644 --- a/widget/src/mac/nsWindow.h +++ b/widget/src/mac/nsWindow.h @@ -219,8 +219,8 @@ public: NS_IMETHOD ResetInputState(); NS_IMETHOD SetIMEOpenState(PRBool aState); NS_IMETHOD GetIMEOpenState(PRBool* aState); - NS_IMETHOD SetIMEEnabled(PRBool aState); - NS_IMETHOD GetIMEEnabled(PRBool* aState); + NS_IMETHOD SetIMEEnabled(PRUint32 aState); + NS_IMETHOD GetIMEEnabled(PRUint32* aState); NS_IMETHOD CancelIMEComposition(); protected: diff --git a/widget/src/photon/nsWidget.cpp b/widget/src/photon/nsWidget.cpp index 267c5abd073d..35e691c30d0d 100644 --- a/widget/src/photon/nsWidget.cpp +++ b/widget/src/photon/nsWidget.cpp @@ -239,11 +239,11 @@ NS_IMETHODIMP nsWidget::GetIMEOpenState(PRBool* aState) { return NS_ERROR_NOT_IMPLEMENTED; } -NS_IMETHODIMP nsWidget::SetIMEEnabled(PRBool aState) { +NS_IMETHODIMP nsWidget::SetIMEEnabled(PRUint32 aState) { return NS_ERROR_NOT_IMPLEMENTED; } -NS_IMETHODIMP nsWidget::GetIMEEnabled(PRBool* aState) { +NS_IMETHODIMP nsWidget::GetIMEEnabled(PRUint32* aState) { return NS_ERROR_NOT_IMPLEMENTED; } diff --git a/widget/src/photon/nsWidget.h b/widget/src/photon/nsWidget.h index 94a83462d7e7..668d26ac0de0 100644 --- a/widget/src/photon/nsWidget.h +++ b/widget/src/photon/nsWidget.h @@ -216,8 +216,8 @@ public: NS_IMETHOD ResetInputState(); NS_IMETHOD SetIMEOpenState(PRBool aState); NS_IMETHOD GetIMEOpenState(PRBool* aState); - NS_IMETHOD SetIMEEnabled(PRBool aState); - NS_IMETHOD GetIMEEnabled(PRBool* aState); + NS_IMETHOD SetIMEEnabled(PRUint32 aState); + NS_IMETHOD GetIMEEnabled(PRUint32* aState); NS_IMETHOD CancelIMEComposition(); inline void InitEvent(nsGUIEvent& event, PRUint32 aEventType, nsPoint* aPoint = nsnull) diff --git a/widget/src/windows/nsWindow.cpp b/widget/src/windows/nsWindow.cpp index 83aa5bcfcdd2..ffd648252de7 100644 --- a/widget/src/windows/nsWindow.cpp +++ b/widget/src/windows/nsWindow.cpp @@ -818,6 +818,7 @@ nsWindow::nsWindow() : nsBaseWidget() mOldExStyle = 0; mPainting = 0; mOldIMC = NULL; + mIMEEnabled = nsIKBStateControl::IME_STATUS_ENABLED; mLeadByte = '\0'; mBlurEventSuppressionLevel = 0; @@ -7473,22 +7474,24 @@ NS_IMETHODIMP nsWindow::GetIMEOpenState(PRBool* aState) } //========================================================================== -NS_IMETHODIMP nsWindow::SetIMEEnabled(PRBool aState) +NS_IMETHODIMP nsWindow::SetIMEEnabled(PRUint32 aState) { if (sIMEIsComposing) ResetInputState(); - if (!aState != !mOldIMC) + mIMEEnabled = aState; + PRBool enable = (aState == nsIKBStateControl::IME_STATUS_ENABLED); + if (!enable != !mOldIMC) return NS_OK; - mOldIMC = ::ImmAssociateContext(mWnd, aState ? mOldIMC : NULL); - NS_ASSERTION(!aState || !mOldIMC, "Another IMC was associated"); + mOldIMC = ::ImmAssociateContext(mWnd, enable ? mOldIMC : NULL); + NS_ASSERTION(!enable || !mOldIMC, "Another IMC was associated"); return NS_OK; } //========================================================================== -NS_IMETHODIMP nsWindow::GetIMEEnabled(PRBool* aState) +NS_IMETHODIMP nsWindow::GetIMEEnabled(PRUint32* aState) { - *aState = !mOldIMC; + *aState = mIMEEnabled; return NS_OK; } diff --git a/widget/src/windows/nsWindow.h b/widget/src/windows/nsWindow.h index 88ebce53532d..132f36427445 100644 --- a/widget/src/windows/nsWindow.h +++ b/widget/src/windows/nsWindow.h @@ -230,8 +230,8 @@ public: NS_IMETHOD ResetInputState(); NS_IMETHOD SetIMEOpenState(PRBool aState); NS_IMETHOD GetIMEOpenState(PRBool* aState); - NS_IMETHOD SetIMEEnabled(PRBool aState); - NS_IMETHOD GetIMEEnabled(PRBool* aState); + NS_IMETHOD SetIMEEnabled(PRUint32 aState); + NS_IMETHOD GetIMEEnabled(PRUint32* aState); NS_IMETHOD CancelIMEComposition(); PRBool IMEMouseHandling(PRInt32 aAction, LPARAM lParam); @@ -451,6 +451,7 @@ protected: // To enable/disable IME HIMC mOldIMC; + PRUint32 mIMEEnabled; static HKL gKeyboardLayout; static PRBool gSwitchKeyboardLayout;