Bug 581596 - Add new SetInputMode api, r=roc,masayuki sr=roc a=blocking-fennec
authorMichael Wu <mwu@mozilla.com>
Mon, 22 Nov 2010 22:48:03 -0800
changeset 58017 674eb3bc24a5c75d004a4f99c1050e638da4961e
parent 58016 8c65bc38729a28a9e1f4d666813cd754e1451ebc
child 58018 92bb7d084e2b4c91a375631bb6b0706d9a7d9851
push id1
push usershaver@mozilla.com
push dateTue, 04 Jan 2011 17:58:04 +0000
reviewersroc, masayuki, roc, blocking-fennec
bugs581596
milestone2.0b8pre
Bug 581596 - Add new SetInputMode api, r=roc,masayuki sr=roc a=blocking-fennec
content/events/src/nsIMEStateManager.cpp
content/events/src/nsIMEStateManager.h
dom/ipc/PBrowser.ipdl
dom/ipc/TabParent.cpp
dom/ipc/TabParent.h
editor/libeditor/base/nsEditor.cpp
widget/public/nsIWidget.h
widget/src/android/nsWindow.cpp
widget/src/android/nsWindow.h
widget/src/cocoa/nsChildView.h
widget/src/cocoa/nsChildView.mm
widget/src/gtk2/nsGtkIMModule.cpp
widget/src/gtk2/nsGtkIMModule.h
widget/src/gtk2/nsWindow.cpp
widget/src/gtk2/nsWindow.h
widget/src/qt/nsWindow.cpp
widget/src/qt/nsWindow.h
widget/src/windows/nsTextStore.cpp
widget/src/windows/nsTextStore.h
widget/src/windows/nsWindow.cpp
widget/src/windows/nsWindow.h
widget/src/xpwidgets/PuppetWidget.cpp
widget/src/xpwidgets/PuppetWidget.h
widget/src/xpwidgets/nsBaseWidget.cpp
widget/src/xpwidgets/nsBaseWidget.h
--- a/content/events/src/nsIMEStateManager.cpp
+++ b/content/events/src/nsIMEStateManager.cpp
@@ -80,17 +80,17 @@ nsresult
 nsIMEStateManager::OnDestroyPresContext(nsPresContext* aPresContext)
 {
   NS_ENSURE_ARG_POINTER(aPresContext);
   if (aPresContext != sPresContext)
     return NS_OK;
   nsCOMPtr<nsIWidget> widget = GetWidget(sPresContext);
   if (widget) {
     PRUint32 newState = GetNewIMEState(sPresContext, nsnull);
-    SetIMEState(newState, widget);
+    SetIMEState(newState, nsnull, widget);
   }
   sContent = nsnull;
   sPresContext = nsnull;
   OnTextStateBlur(nsnull, nsnull);
   return NS_OK;
 }
 
 nsresult
@@ -105,17 +105,17 @@ nsIMEStateManager::OnRemoveContent(nsPre
 
   // Current IME transaction should commit
   nsCOMPtr<nsIWidget> widget = GetWidget(sPresContext);
   if (widget) {
     nsresult rv = widget->CancelIMEComposition();
     if (NS_FAILED(rv))
       widget->ResetInputState();
     PRUint32 newState = GetNewIMEState(sPresContext, nsnull);
-    SetIMEState(newState, widget);
+    SetIMEState(newState, nsnull, widget);
   }
 
   sContent = nsnull;
   sPresContext = nsnull;
 
   return NS_OK;
 }
 
@@ -159,34 +159,34 @@ nsIMEStateManager::OnChangeFocus(nsPresC
     else
       oldWidget = GetWidget(sPresContext);
     if (oldWidget)
       oldWidget->ResetInputState();
   }
 
   if (newState != nsIContent::IME_STATUS_NONE) {
     // Update IME state for new focus widget
-    SetIMEState(newState, widget);
+    SetIMEState(newState, aContent, widget);
   }
 
   sPresContext = aPresContext;
   sContent = aContent;
 
   return NS_OK;
 }
 
 void
 nsIMEStateManager::OnInstalledMenuKeyboardListener(PRBool aInstalling)
 {
   sInstalledMenuKeyboardListener = aInstalling;
   OnChangeFocus(sPresContext, sContent);
 }
 
 void
-nsIMEStateManager::UpdateIMEState(PRUint32 aNewIMEState)
+nsIMEStateManager::UpdateIMEState(PRUint32 aNewIMEState, nsIContent* aContent)
 {
   if (!sPresContext) {
     NS_WARNING("ISM doesn't know which editor has focus");
     return;
   }
   NS_PRECONDITION(aNewIMEState != 0, "aNewIMEState doesn't specify new state.");
   nsCOMPtr<nsIWidget> widget = GetWidget(sPresContext);
   if (!widget) {
@@ -204,17 +204,17 @@ nsIMEStateManager::UpdateIMEState(PRUint
   if (currentEnabledState ==
         nsContentUtils::GetWidgetStatusFromIMEStatus(newEnabledState)) {
     return;
   }
 
   // commit current composition
   widget->ResetInputState();
 
-  SetIMEState(aNewIMEState, widget);
+  SetIMEState(aNewIMEState, aContent, widget);
 }
 
 PRUint32
 nsIMEStateManager::GetNewIMEState(nsPresContext* aPresContext,
                                   nsIContent*    aContent)
 {
   // On Printing or Print Preview, we don't need IME.
   if (aPresContext->Type() == nsPresContext::eContext_PrintPreview ||
@@ -256,22 +256,36 @@ public:
   }
 
 private:
   PRUint32 mState;
 };
 
 void
 nsIMEStateManager::SetIMEState(PRUint32 aState,
+                               nsIContent* aContent,
                                nsIWidget* aWidget)
 {
   if (aState & nsIContent::IME_STATUS_MASK_ENABLED) {
-    PRUint32 state =
-      nsContentUtils::GetWidgetStatusFromIMEStatus(aState);
-    aWidget->SetIMEEnabled(state);
+    nsresult rv;
+
+    nsIWidget_MOZILLA_2_0_BRANCH* widget2 = static_cast<nsIWidget_MOZILLA_2_0_BRANCH*>(aWidget);
+    if (!widget2)
+      return;
+
+    PRUint32 state = nsContentUtils::GetWidgetStatusFromIMEStatus(aState);
+    IMEContext context;
+    context.mStatus = state;
+
+    if (aContent && aContent->Tag() == nsGkAtoms::input) {
+      aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::type,
+                        context.mHTMLInputType);
+    }
+
+    widget2->SetInputMode(context);
 
     nsContentUtils::AddScriptRunner(new IMEEnabledStateChangedEvent(state));
   }
   if (aState & nsIContent::IME_STATUS_MASK_OPENED) {
     PRBool open = !!(aState & nsIContent::IME_STATUS_OPEN);
     aWidget->SetIMEOpenState(open);
   }
 }
--- a/content/events/src/nsIMEStateManager.h
+++ b/content/events/src/nsIMEStateManager.h
@@ -81,20 +81,21 @@ public:
   static nsresult GetFocusSelectionAndRoot(nsISelection** aSel,
                                            nsIContent** aRoot);
   // This method updates the current IME state.  However, if the enabled state
   // isn't changed by the new state, this method does nothing.
   // Note that this method changes the IME state of the active element in the
   // widget.  So, the caller must have focus.
   // aNewIMEState must have an enabled state of nsIContent::IME_STATUS_*.
   // And optionally, it can have an open state of nsIContent::IME_STATUS_*.
-  static void UpdateIMEState(PRUint32 aNewIMEState);
+  static void UpdateIMEState(PRUint32 aNewIMEState, nsIContent* aContent);
 
 protected:
-  static void SetIMEState(PRUint32 aState, nsIWidget* aWidget);
+  static void SetIMEState(PRUint32 aState, nsIContent* aContent,
+                          nsIWidget* aWidget);
   static PRUint32 GetNewIMEState(nsPresContext* aPresContext,
                                  nsIContent* aContent);
 
   static nsIWidget* GetWidget(nsPresContext* aPresContext);
 
   static nsIContent*    sContent;
   static nsPresContext* sPresContext;
   static PRBool         sInstalledMenuKeyboardListener;
--- a/dom/ipc/PBrowser.ipdl
+++ b/dom/ipc/PBrowser.ipdl
@@ -164,17 +164,17 @@ parent:
      *    widget should return empty string for composition
      *  if cancel is PR_FALSE,
      *    widget should return the current composition text
      */
     sync EndIMEComposition(PRBool cancel) returns (nsString composition);
 
     sync GetIMEEnabled() returns (PRUint32 value);
 
-    SetIMEEnabled(PRUint32 value);
+    SetInputMode(PRUint32 value, nsString type);
 
     sync GetIMEOpenState() returns (PRBool value);
 
     SetIMEOpenState(PRBool value);
 
     PContentPermissionRequest(nsCString aType, URI uri);
 
     PContentDialog(PRUint32 aType, nsCString aName, nsCString aFeatures,
--- a/dom/ipc/TabParent.cpp
+++ b/dom/ipc/TabParent.cpp
@@ -483,29 +483,36 @@ TabParent::RecvGetIMEEnabled(PRUint32* a
 {
   nsCOMPtr<nsIWidget> widget = GetWidget();
   if (widget)
     widget->GetIMEEnabled(aValue);
   return true;
 }
 
 bool
-TabParent::RecvSetIMEEnabled(const PRUint32& aValue)
+TabParent::RecvSetInputMode(const PRUint32& aValue, const nsString& aType)
 {
   nsCOMPtr<nsIWidget> widget = GetWidget();
-  if (widget && AllowContentIME()) {
-    widget->SetIMEEnabled(aValue);
+  if (!widget || !AllowContentIME())
+    return true;
+
+  nsIWidget_MOZILLA_2_0_BRANCH* widget2 = static_cast<nsIWidget_MOZILLA_2_0_BRANCH*>(widget.get());
 
-    nsCOMPtr<nsIObserverService> observerService = mozilla::services::GetObserverService();
-    if (observerService) {
-      nsAutoString state;
-      state.AppendInt(aValue);
-      observerService->NotifyObservers(nsnull, "ime-enabled-state-changed", state.get());
-    }
-  }
+  IMEContext context;
+  context.mStatus = aValue;
+  context.mHTMLInputType.Assign(aType);
+  widget2->SetInputMode(context);
+
+  nsCOMPtr<nsIObserverService> observerService = mozilla::services::GetObserverService();
+  if (!observerService)
+    return true;
+
+  nsAutoString state;
+  state.AppendInt(aValue);
+  observerService->NotifyObservers(nsnull, "ime-enabled-state-changed", state.get());
 
   return true;
 }
 
 bool
 TabParent::RecvGetIMEOpenState(PRBool* aValue)
 {
   nsCOMPtr<nsIWidget> widget = GetWidget();
--- a/dom/ipc/TabParent.h
+++ b/dom/ipc/TabParent.h
@@ -97,17 +97,17 @@ public:
                                          const PRUint32& aNewEnd);
     virtual bool RecvNotifyIMESelection(const PRUint32& aSeqno,
                                         const PRUint32& aAnchor,
                                         const PRUint32& aFocus);
     virtual bool RecvNotifyIMETextHint(const nsString& aText);
     virtual bool RecvEndIMEComposition(const PRBool& aCancel,
                                        nsString* aComposition);
     virtual bool RecvGetIMEEnabled(PRUint32* aValue);
-    virtual bool RecvSetIMEEnabled(const PRUint32& aValue);
+    virtual bool RecvSetInputMode(const PRUint32& aValue, const nsString& aType);
     virtual bool RecvGetIMEOpenState(PRBool* aValue);
     virtual bool RecvSetIMEOpenState(const PRBool& aValue);
     virtual PContentDialogParent* AllocPContentDialog(const PRUint32& aType,
                                                       const nsCString& aName,
                                                       const nsCString& aFeatures,
                                                       const InfallibleTArray<int>& aIntParams,
                                                       const InfallibleTArray<nsString>& aStringParams);
     virtual bool DeallocPContentDialog(PContentDialogParent* aDialog)
--- a/editor/libeditor/base/nsEditor.cpp
+++ b/editor/libeditor/base/nsEditor.cpp
@@ -479,17 +479,17 @@ nsEditor::SetFlags(PRUint32 aFlags)
   if (focusedContent) {
     // Use "enable" for the default value because if IME is disabled
     // unexpectedly, it makes serious a11y problem.
     PRUint32 newState = nsIContent::IME_STATUS_ENABLE;
     nsresult rv = GetPreferredIMEState(&newState);
     if (NS_SUCCEEDED(rv)) {
       // NOTE: When the enabled state isn't going to be modified, this method
       // is going to do nothing.
-      nsIMEStateManager::UpdateIMEState(newState);
+      nsIMEStateManager::UpdateIMEState(newState, focusedContent);
     }
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsEditor::GetIsDocumentEditable(PRBool *aIsDocumentEditable)
--- a/widget/public/nsIWidget.h
+++ b/widget/public/nsIWidget.h
@@ -39,16 +39,17 @@
 #define nsIWidget_h__
 
 #include "nsISupports.h"
 #include "nsColor.h"
 #include "nsCoord.h"
 #include "nsRect.h"
 #include "nsPoint.h"
 #include "nsRegion.h"
+#include "nsString.h"
 
 #include "prthread.h"
 #include "nsEvent.h"
 #include "nsCOMPtr.h"
 #include "nsITheme.h"
 #include "nsNativeWidget.h"
 #include "nsWidgetInitData.h"
 #include "nsTArray.h"
@@ -117,16 +118,21 @@ typedef nsEventStatus (* EVENT_CALLBACK)
 #define NS_NATIVE_TSF_DISPLAY_ATTR_MGR 102
 #endif
 
 // cc443f0b-af39-415d-9c4b-7e06eaa8b13b
 #define NS_IWIDGET_IID \
   { 0xcc443f0b, 0xaf39, 0x415d, \
     { 0x9c, 0x4b, 0x7e, 0x06, 0xea, 0xa8, 0xb1, 0x3b } }
 
+// d64532e0-03d6-421c-8e63-da2cff624825
+#define NS_IWIDGET_MOZILLA_2_0_BRANCH_IID \
+  { 0xd64532e0, 0x03d6, 0x421c, \
+    { 0x8e, 0x63, 0xda, 0x2c, 0xff, 0x62, 0x48, 0x25 } }
+
 /*
  * Window shadow styles
  * Also used for the -moz-window-shadow CSS property
  */
 
 #define NS_STYLE_WINDOW_SHADOW_NONE             0
 #define NS_STYLE_WINDOW_SHADOW_DEFAULT          1
 #define NS_STYLE_WINDOW_SHADOW_MENU             2
@@ -223,16 +229,28 @@ struct nsIMEUpdatePreference {
     : mWantUpdates(aWantUpdates), mWantHints(aWantHints)
   {
   }
   PRPackedBool mWantUpdates;
   PRPackedBool mWantHints;
 };
 
 
+/* 
+ * Contains IMEStatus plus information about the current 
+ * input context that the IME can use as hints if desired.
+ */
+struct IMEContext {
+  PRUint32 mStatus;
+
+  /* The type of the input if the input is a html input field */
+  nsString mHTMLInputType;
+};
+
+
 /**
  * The base class for all the widgets. It provides the interface for
  * all basic and necessary functionality.
  */
 class nsIWidget : public nsISupports {
 #ifdef MOZ_IPC
   protected:
     typedef mozilla::dom::PBrowserChild PBrowserChild;
@@ -1339,9 +1357,24 @@ protected:
     nsCOMPtr<nsIWidget> mFirstChild;
     nsIWidget* mLastChild;
     nsCOMPtr<nsIWidget> mNextSibling;
     nsIWidget* mPrevSibling;
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsIWidget, NS_IWIDGET_IID)
 
+class nsIWidget_MOZILLA_2_0_BRANCH : public nsIWidget {
+  public:
+    NS_DECLARE_STATIC_IID_ACCESSOR(NS_IWIDGET_MOZILLA_2_0_BRANCH_IID)
+
+    /*
+     * Notifies the IME if the input context changes.
+     *
+     * aContext cannot be null.
+     * Set mStatus to 'Enabled' or 'Disabled' or 'Password'.
+     */
+    NS_IMETHOD SetInputMode(const IMEContext& aContext) = 0;
+};
+
+NS_DEFINE_STATIC_IID_ACCESSOR(nsIWidget_MOZILLA_2_0_BRANCH, NS_IWIDGET_MOZILLA_2_0_BRANCH_IID)
+
 #endif // nsIWidget_h__
--- a/widget/src/android/nsWindow.cpp
+++ b/widget/src/android/nsWindow.cpp
@@ -1641,22 +1641,22 @@ nsWindow::ResetInputState()
         DispatchEvent(&event);
     }
 
     AndroidBridge::NotifyIME(AndroidBridge::NOTIFY_IME_RESETINPUTSTATE, 0);
     return NS_OK;
 }
 
 NS_IMETHODIMP
-nsWindow::SetIMEEnabled(PRUint32 aState)
+nsWindow::SetInputMode(const IMEContext& aContext)
 {
-    ALOGIME("IME: SetIMEEnabled: s=%d", aState);
+    ALOGIME("IME: SetInputMode: s=%d", aContext.mStatus);
 
-    mIMEEnabled = aState;
-    AndroidBridge::NotifyIME(AndroidBridge::NOTIFY_IME_SETENABLED, int(aState));
+    mIMEEnabled = aContext.mStatus;
+    AndroidBridge::NotifyIME(AndroidBridge::NOTIFY_IME_SETENABLED, int(mIMEEnabled));
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsWindow::GetIMEEnabled(PRUint32* aState)
 {
     *aState = mIMEEnabled;
     return NS_OK;
--- a/widget/src/android/nsWindow.h
+++ b/widget/src/android/nsWindow.h
@@ -148,17 +148,17 @@ public:
                                    nsIMenuRollup *aMenuRollup,
                                    PRBool aDoCapture,
                                    PRBool aConsumeRollupEvent) { return NS_ERROR_NOT_IMPLEMENTED; }
 
     NS_IMETHOD GetAttention(PRInt32 aCycleCount) { return NS_ERROR_NOT_IMPLEMENTED; }
     NS_IMETHOD BeginResizeDrag(nsGUIEvent* aEvent, PRInt32 aHorizontal, PRInt32 aVertical) { return NS_ERROR_NOT_IMPLEMENTED; }
 
     NS_IMETHOD ResetInputState();
-    NS_IMETHOD SetIMEEnabled(PRUint32 aState);
+    NS_IMETHOD SetInputMode(const IMEContext& aContext);
     NS_IMETHOD GetIMEEnabled(PRUint32* aState);
     NS_IMETHOD CancelIMEComposition();
 
     NS_IMETHOD OnIMEFocusChange(PRBool aFocus);
     NS_IMETHOD OnIMETextChange(PRUint32 aStart, PRUint32 aOldEnd, PRUint32 aNewEnd);
     NS_IMETHOD OnIMESelectionChange(void);
     virtual nsIMEUpdatePreference GetIMEUpdatePreference();
 
--- a/widget/src/cocoa/nsChildView.h
+++ b/widget/src/cocoa/nsChildView.h
@@ -347,17 +347,17 @@ public:
   virtual PRBool HasPendingInputEvent();
 
   NS_IMETHOD        ActivateNativeMenuItemAt(const nsAString& indexString);
   NS_IMETHOD        ForceUpdateNativeMenuAt(const nsAString& indexString);
 
   NS_IMETHOD        ResetInputState();
   NS_IMETHOD        SetIMEOpenState(PRBool aState);
   NS_IMETHOD        GetIMEOpenState(PRBool* aState);
-  NS_IMETHOD        SetIMEEnabled(PRUint32 aState);
+  NS_IMETHOD        SetInputMode(const IMEContext& aContext);
   NS_IMETHOD        GetIMEEnabled(PRUint32* aState);
   NS_IMETHOD        CancelIMEComposition();
   NS_IMETHOD        GetToggledKeyState(PRUint32 aKeyCode,
                                        PRBool* aLEDState);
   NS_IMETHOD        OnIMEFocusChange(PRBool aFocus);
 
   // nsIPluginWidget
   NS_IMETHOD        GetPluginClipRect(nsIntRect& outClipRect, nsIntPoint& outOrigin, PRBool& outWidgetVisible);
--- a/widget/src/cocoa/nsChildView.mm
+++ b/widget/src/cocoa/nsChildView.mm
@@ -1959,23 +1959,23 @@ NS_IMETHODIMP nsChildView::GetIMEOpenSta
 #ifdef DEBUG_IME
   NSLog(@"**** GetIMEOpenState");
 #endif
 
   *aState = mTextInputHandler.IsIMEOpened();
   return NS_OK;
 }
 
-NS_IMETHODIMP nsChildView::SetIMEEnabled(PRUint32 aState)
+NS_IMETHODIMP nsChildView::SetInputMode(const IMEContext& aContext)
 {
 #ifdef DEBUG_IME
-  NSLog(@"**** SetIMEEnabled aState = %d", aState);
+  NSLog(@"**** SetInputMode mStatus = %d", aContext.mStatus);
 #endif
 
-  switch (aState) {
+  switch (aContext.mStatus) {
     case nsIWidget::IME_STATUS_ENABLED:
     case nsIWidget::IME_STATUS_PLUGIN:
       mTextInputHandler.SetASCIICapableOnly(PR_FALSE);
       mTextInputHandler.EnableIME(PR_TRUE);
       break;
     case nsIWidget::IME_STATUS_DISABLED:
       mTextInputHandler.SetASCIICapableOnly(PR_FALSE);
       mTextInputHandler.EnableIME(PR_FALSE);
--- a/widget/src/gtk2/nsGtkIMModule.cpp
+++ b/widget/src/gtk2/nsGtkIMModule.cpp
@@ -507,54 +507,54 @@ nsGtkIMModule::CancelIMEComposition(nsWi
 
     ResetIME();
     CommitCompositionBy(EmptyString());
 
     return NS_OK;
 }
 
 nsresult
-nsGtkIMModule::SetIMEEnabled(nsWindow* aCaller, PRUint32 aState)
+nsGtkIMModule::SetInputMode(nsWindow* aCaller, const IMEContext* aContext)
 {
-    if (aState == mEnabled || NS_UNLIKELY(IsDestroyed())) {
+    if (aContext->mStatus == mEnabled || NS_UNLIKELY(IsDestroyed())) {
         return NS_OK;
     }
 
     PR_LOG(gGtkIMLog, PR_LOG_ALWAYS,
-        ("GtkIMModule(%p): SetIMEEnabled, aCaller=%p, aState=%s",
-         this, aCaller, GetEnabledStateName(aState)));
+        ("GtkIMModule(%p): SetInputMode, aCaller=%p, aState=%s mHTMLInputType=%s",
+         this, aCaller, GetEnabledStateName(aContext->mStatus), aContext->mHTMLInputType.get()));
 
     if (aCaller != mLastFocusedWindow) {
         PR_LOG(gGtkIMLog, PR_LOG_ALWAYS,
             ("    FAILED, the caller isn't focused window, mLastFocusedWindow=%p",
              mLastFocusedWindow));
         return NS_OK;
     }
 
     if (!mContext) {
         PR_LOG(gGtkIMLog, PR_LOG_ALWAYS,
             ("    FAILED, there are no context"));
         return NS_ERROR_NOT_AVAILABLE;
     }
 
 
     if (sLastFocusedModule != this) {
-        mEnabled = aState;
+        mEnabled = aContext->mStatus;
         PR_LOG(gGtkIMLog, PR_LOG_ALWAYS,
             ("    SUCCEEDED, but we're not active"));
         return NS_OK;
     }
 
     // Release current IME focus if IME is enabled.
     if (IsEditable()) {
         ResetInputState(mLastFocusedWindow);
         Blur();
     }
 
-    mEnabled = aState;
+    mEnabled = aContext->mStatus;
 
     // Even when aState is not enabled state, we need to set IME focus.
     // Because some IMs are updating the status bar of them at this time.
     // Be aware, don't use aWindow here because this method shouldn't move
     // focus actually.
     Focus();
 
 #ifdef MOZ_PLATFORM_MAEMO
--- a/widget/src/gtk2/nsGtkIMModule.h
+++ b/widget/src/gtk2/nsGtkIMModule.h
@@ -102,17 +102,17 @@ public:
     // native key release event.  If this returns TRUE, the key event was
     // filtered by IME.  Otherwise, this returns FALSE.
     // NOTE: When the keypress event starts composition, this returns TRUE but
     //       this dispatches keydown event before compositionstart event.
     PRBool OnKeyEvent(nsWindow* aWindow, GdkEventKey* aEvent);
 
     // IME related nsIWidget methods.
     nsresult ResetInputState(nsWindow* aCaller);
-    nsresult SetIMEEnabled(nsWindow* aCaller, PRUint32 aState);
+    nsresult SetInputMode(nsWindow* aCaller, const IMEContext* aContext);
     nsresult GetIMEEnabled(PRUint32* aState);
     nsresult CancelIMEComposition(nsWindow* aCaller);
 
     // If a software keyboard has been opened, this returns TRUE.
     // Otherwise, FALSE.
     static PRBool IsVirtualKeyboardOpened();
 
 protected:
--- a/widget/src/gtk2/nsWindow.cpp
+++ b/widget/src/gtk2/nsWindow.cpp
@@ -6436,19 +6436,19 @@ nsChildWindow::~nsChildWindow()
 
 NS_IMETHODIMP
 nsWindow::ResetInputState()
 {
     return mIMModule ? mIMModule->ResetInputState(this) : NS_OK;
 }
 
 NS_IMETHODIMP
-nsWindow::SetIMEEnabled(PRUint32 aState)
-{
-    return mIMModule ? mIMModule->SetIMEEnabled(this, aState) : NS_OK;
+nsWindow::SetInputMode(const IMEContext& aContext)
+{
+    return mIMModule ? mIMModule->SetInputMode(this, &aContext) : NS_OK;
 }
 
 NS_IMETHODIMP
 nsWindow::GetIMEEnabled(PRUint32* aState)
 {
   NS_ENSURE_ARG_POINTER(aState);
   if (!mIMModule) {
       *aState = nsIWidget::IME_STATUS_DISABLED;
--- a/widget/src/gtk2/nsWindow.h
+++ b/widget/src/gtk2/nsWindow.h
@@ -318,17 +318,17 @@ public:
     PRBool             IsDestroyed() { return mIsDestroyed; }
 
     // If this dispatched the keydown event actually, this returns TRUE,
     // otherwise, FALSE.
     PRBool             DispatchKeyDownEvent(GdkEventKey *aEvent,
                                             PRBool *aIsCancelled);
 
     NS_IMETHOD ResetInputState();
-    NS_IMETHOD SetIMEEnabled(PRUint32 aState);
+    NS_IMETHOD SetInputMode(const IMEContext& aContext);
     NS_IMETHOD GetIMEEnabled(PRUint32* aState);
     NS_IMETHOD CancelIMEComposition();
     NS_IMETHOD OnIMEFocusChange(PRBool aFocus);
     NS_IMETHOD GetToggledKeyState(PRUint32 aKeyCode, PRBool* aLEDState);
 
    void                ResizeTransparencyBitmap(PRInt32 aNewWidth, PRInt32 aNewHeight);
    void                ApplyTransparencyBitmap();
    virtual void        SetTransparencyMode(nsTransparencyMode aMode);
--- a/widget/src/qt/nsWindow.cpp
+++ b/widget/src/qt/nsWindow.cpp
@@ -2953,21 +2953,21 @@ nsWindow::AreBoundsSane(void)
 {
     if (mBounds.width > 0 && mBounds.height > 0)
         return PR_TRUE;
 
     return PR_FALSE;
 }
 
 NS_IMETHODIMP
-nsWindow::SetIMEEnabled(PRUint32 aState)
+nsWindow::SetInputMode(const IMEContext& aContext)
 {
     NS_ENSURE_TRUE(mWidget, NS_ERROR_FAILURE);
 
-    switch (aState) {
+    switch (aContext.mStatus) {
         case nsIWidget::IME_STATUS_ENABLED:
         case nsIWidget::IME_STATUS_PASSWORD:
             {
                 PRInt32 openDelay = 200;
                 nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
                 if (prefs)
                   prefs->GetIntPref("ui.vkb.open.delay", &openDelay);
 
--- a/widget/src/qt/nsWindow.h
+++ b/widget/src/qt/nsWindow.h
@@ -194,17 +194,17 @@ public:
                                            PRBool aDoCapture,
                                            PRBool aConsumeRollupEvent);
 
     NS_IMETHOD         SetWindowClass(const nsAString& xulWinType);
 
     NS_IMETHOD         GetAttention(PRInt32 aCycleCount);
     NS_IMETHOD         BeginResizeDrag   (nsGUIEvent* aEvent, PRInt32 aHorizontal, PRInt32 aVertical);
 
-    NS_IMETHODIMP      SetIMEEnabled(PRUint32 aState);
+    NS_IMETHODIMP      SetInputMode(const IMEContext& aContext);
     NS_IMETHODIMP      GetIMEEnabled(PRUint32* aState);
 
     //
     // utility methods
     //
     void               QWidgetDestroyed();
 
     /***** from CommonWidget *****/
--- a/widget/src/windows/nsTextStore.cpp
+++ b/widget/src/windows/nsTextStore.cpp
@@ -94,17 +94,17 @@ nsTextStore::Create(nsWindow* aWindow,
                                     getter_AddRefs(mDocumentMgr));
     NS_ENSURE_TRUE(SUCCEEDED(hr), PR_FALSE);
     mWindow = aWindow;
     // Create context and add it to document manager
     hr = mDocumentMgr->CreateContext(sTsfClientId, 0,
                                      static_cast<ITextStoreACP*>(this),
                                      getter_AddRefs(mContext), &mEditCookie);
     if (SUCCEEDED(hr)) {
-      SetIMEEnabledInternal(aIMEState);
+      SetInputModeInternal(aIMEState);
       hr = mDocumentMgr->Push(mContext);
     }
     if (SUCCEEDED(hr)) {
       PR_LOG(sTextStoreLog, PR_LOG_ALWAYS,
              ("TSF: Created, window=%08x\n", aWindow));
       return PR_TRUE;
     }
     mContext = NULL;
@@ -1587,20 +1587,20 @@ nsTextStore::GetIMEOpenState(void)
   if (SUCCEEDED(comp->GetValue(&variant)) && variant.vt == VT_I4)
     return variant.lVal != 0;
 
   ::VariantClear(&variant); // clear up in case variant.vt != VT_I4
   return PR_FALSE;
 }
 
 void
-nsTextStore::SetIMEEnabledInternal(PRUint32 aState)
+nsTextStore::SetInputModeInternal(PRUint32 aState)
 {
   PR_LOG(sTextStoreLog, PR_LOG_ALWAYS,
-         ("TSF: SetIMEEnabled, state=%lu\n", aState));
+         ("TSF: SetInputMode, state=%lu\n", aState));
 
   VARIANT variant;
   variant.vt = VT_I4;
   variant.lVal = aState != nsIWidget::IME_STATUS_ENABLED;
 
   // Set two contexts, the base context (mContext) and the top
   // if the top context is not the same as the base context
   nsRefPtr<ITfContext> context = mContext;
--- a/widget/src/windows/nsTextStore.h
+++ b/widget/src/windows/nsTextStore.h
@@ -38,16 +38,17 @@
 
 #ifndef NSTEXTSTORE_H_
 #define NSTEXTSTORE_H_
 
 #include "nsAutoPtr.h"
 #include "nsString.h"
 #include "nsCOMPtr.h"
 #include "nsITimer.h"
+#include "nsIWidget.h"
 
 #include <msctf.h>
 #include <textstor.h>
 
 struct ITfThreadMgr;
 struct ITfDocumentMgr;
 struct ITfDisplayAttributeMgr;
 struct ITfCategoryMgr;
@@ -116,20 +117,20 @@ public:
   static PRBool   GetIMEOpenState(void);
 
   static void     CommitComposition(PRBool aDiscard)
   {
     if (!sTsfTextStore) return;
     sTsfTextStore->CommitCompositionInternal(aDiscard);
   }
 
-  static void     SetIMEEnabled(PRUint32 aState)
+  static void     SetInputMode(const IMEContext& aContext)
   {
     if (!sTsfTextStore) return;
-    sTsfTextStore->SetIMEEnabledInternal(aState);
+    sTsfTextStore->SetInputModeInternal(aContext.mStatus);
   }
 
   static nsresult OnFocusChange(PRBool, nsWindow*, PRUint32);
 
   static nsresult OnTextChange(PRUint32 aStart,
                                PRUint32 aOldEnd,
                                PRUint32 aNewEnd)
   {
@@ -185,17 +186,17 @@ protected:
   // If aDispatchTextEvent is true, this method will dispatch text event if
   // this is called during IME composing.  aDispatchTextEvent should be true
   // only when this is called from SetSelection.  Because otherwise, the text
   // event should not be sent from here.
   HRESULT  SetSelectionInternal(const TS_SELECTION_ACP*,
                                 PRBool aDispatchTextEvent = PR_FALSE);
   HRESULT  OnStartCompositionInternal(ITfCompositionView*, ITfRange*, PRBool);
   void     CommitCompositionInternal(PRBool);
-  void     SetIMEEnabledInternal(PRUint32 aState);
+  void     SetInputModeInternal(PRUint32 aState);
   nsresult OnTextChangeInternal(PRUint32, PRUint32, PRUint32);
   void     OnTextChangeMsgInternal(void);
   nsresult OnSelectionChangeInternal(void);
   HRESULT  GetDisplayAttribute(ITfProperty* aProperty,
                                ITfRange* aRange,
                                TF_DISPLAYATTRIBUTE* aResult);
   HRESULT  UpdateCompositionExtent(ITfRange* pRangeNew);
   HRESULT  SendTextEventForCompositionString();
--- a/widget/src/windows/nsWindow.cpp
+++ b/widget/src/windows/nsWindow.cpp
@@ -7527,35 +7527,36 @@ NS_IMETHODIMP nsWindow::GetIMEOpenState(
 
 #ifdef NS_ENABLE_TSF
   *aState |= nsTextStore::GetIMEOpenState();
 #endif //NS_ENABLE_TSF
 
   return NS_OK;
 }
 
-NS_IMETHODIMP nsWindow::SetIMEEnabled(PRUint32 aState)
-{
+NS_IMETHODIMP nsWindow::SetInputMode(const IMEContext& aContext)
+{
+  PRUint32 status = aContext.mStatus;
 #ifdef NS_ENABLE_TSF
-  nsTextStore::SetIMEEnabled(aState);
+  nsTextStore::SetInputMode(aContext);
 #endif //NS_ENABLE_TSF
 #ifdef DEBUG_KBSTATE
-  printf("SetIMEEnabled: %s\n", (aState == nsIWidget::IME_STATUS_ENABLED ||
-                                 aState == nsIWidget::IME_STATUS_PLUGIN)? 
-                                "Enabled": "Disabled");
+  printf("SetInputMode: %s\n", (status == nsIWidget::IME_STATUS_ENABLED ||
+                                status == nsIWidget::IME_STATUS_PLUGIN) ? 
+                               "Enabled" : "Disabled");
 #endif 
   if (nsIMM32Handler::IsComposing()) {
     ResetInputState();
   }
-  mIMEEnabled = aState;
-  PRBool enable = (aState == nsIWidget::IME_STATUS_ENABLED ||
-                   aState == nsIWidget::IME_STATUS_PLUGIN);
+  mIMEEnabled = status;
+  PRBool enable = (status == nsIWidget::IME_STATUS_ENABLED ||
+                   status == nsIWidget::IME_STATUS_PLUGIN);
 
 #if defined(WINCE_HAVE_SOFTKB)
-  sSoftKeyboardState = (aState != nsIWidget::IME_STATUS_DISABLED);
+  sSoftKeyboardState = (status != nsIWidget::IME_STATUS_DISABLED);
   nsWindowCE::ToggleSoftKB(mWnd, sSoftKeyboardState);
 #endif
 
   if (!enable != !mOldIMC)
     return NS_OK;
   mOldIMC = ::ImmAssociateContext(mWnd, enable ? mOldIMC : NULL);
   NS_ASSERTION(!enable || !mOldIMC, "Another IMC was associated");
 
--- a/widget/src/windows/nsWindow.h
+++ b/widget/src/windows/nsWindow.h
@@ -177,17 +177,17 @@ public:
                                                    const nsAString& aCharacters,
                                                    const nsAString& aUnmodifiedCharacters);
   virtual nsresult        SynthesizeNativeMouseEvent(nsIntPoint aPoint,
                                                      PRUint32 aNativeMessage,
                                                      PRUint32 aModifierFlags);
   NS_IMETHOD              ResetInputState();
   NS_IMETHOD              SetIMEOpenState(PRBool aState);
   NS_IMETHOD              GetIMEOpenState(PRBool* aState);
-  NS_IMETHOD              SetIMEEnabled(PRUint32 aState);
+  NS_IMETHOD              SetInputMode(const IMEContext& aContext);
   NS_IMETHOD              GetIMEEnabled(PRUint32* aState);
   NS_IMETHOD              CancelIMEComposition();
   NS_IMETHOD              GetToggledKeyState(PRUint32 aKeyCode, PRBool* aLEDState);
   NS_IMETHOD              RegisterTouchWindow();
   NS_IMETHOD              UnregisterTouchWindow();
 #ifdef MOZ_XUL
   virtual void            SetTransparencyMode(nsTransparencyMode aMode);
   virtual nsTransparencyMode GetTransparencyMode();
--- a/widget/src/xpwidgets/PuppetWidget.cpp
+++ b/widget/src/xpwidgets/PuppetWidget.cpp
@@ -365,20 +365,20 @@ PuppetWidget::SetIMEOpenState(PRBool aSt
 {
   if (mTabChild &&
       mTabChild->SendSetIMEOpenState(aState))
     return NS_OK;
   return NS_ERROR_FAILURE;
 }
 
 NS_IMETHODIMP
-PuppetWidget::SetIMEEnabled(PRUint32 aState)
+PuppetWidget::SetInputMode(const IMEContext& aContext)
 {
   if (mTabChild &&
-      mTabChild->SendSetIMEEnabled(aState))
+      mTabChild->SendSetInputMode(aContext.mStatus, aContext.mHTMLInputType))
     return NS_OK;
   return NS_ERROR_FAILURE;
 }
 
 NS_IMETHODIMP
 PuppetWidget::GetIMEOpenState(PRBool *aState)
 {
   if (mTabChild &&
--- a/widget/src/xpwidgets/PuppetWidget.h
+++ b/widget/src/xpwidgets/PuppetWidget.h
@@ -166,17 +166,17 @@ public:
 //NS_IMETHOD              CaptureMouse(PRBool aCapture);
   virtual LayerManager*     GetLayerManager(bool* aAllowRetaining = nsnull);
 //  virtual nsIDeviceContext* GetDeviceContext();
   virtual gfxASurface*      GetThebesSurface();
 
   NS_IMETHOD ResetInputState();
   NS_IMETHOD SetIMEOpenState(PRBool aState);
   NS_IMETHOD GetIMEOpenState(PRBool *aState);
-  NS_IMETHOD SetIMEEnabled(PRUint32 aState);
+  NS_IMETHOD SetInputMode(const IMEContext& aContext);
   NS_IMETHOD GetIMEEnabled(PRUint32 *aState);
   NS_IMETHOD CancelComposition();
   NS_IMETHOD OnIMEFocusChange(PRBool aFocus);
   NS_IMETHOD OnIMETextChange(PRUint32 aOffset, PRUint32 aEnd,
                              PRUint32 aNewEnd);
   NS_IMETHOD OnIMESelectionChange(void);
 
 private:
--- a/widget/src/xpwidgets/nsBaseWidget.cpp
+++ b/widget/src/xpwidgets/nsBaseWidget.cpp
@@ -1164,16 +1164,25 @@ nsBaseWidget::BeginResizeDrag(nsGUIEvent
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 NS_IMETHODIMP
 nsBaseWidget::BeginMoveDrag(nsMouseEvent* aEvent)
 {
   return NS_ERROR_NOT_IMPLEMENTED;
 }
+
+// For backwards compatibility only
+NS_IMETHODIMP
+nsBaseWidget::SetIMEEnabled(PRUint32 aState)
+{
+  IMEContext context;
+  context.mStatus = aState;
+  return SetInputMode(context);
+}
  
 #ifdef DEBUG
 //////////////////////////////////////////////////////////////
 //
 // Convert a GUI event message code to a string.
 // Makes it a lot easier to debug events.
 //
 // See gtk/nsWidget.cpp and windows/nsWindow.cpp
--- a/widget/src/xpwidgets/nsBaseWidget.h
+++ b/widget/src/xpwidgets/nsBaseWidget.h
@@ -57,17 +57,17 @@ class gfxContext;
  * Common widget implementation used as base class for native
  * or crossplatform implementations of Widgets. 
  * All cross-platform behavior that all widgets need to implement 
  * should be placed in this class. 
  * (Note: widget implementations are not required to use this
  * class, but it gives them a head start.)
  */
 
-class nsBaseWidget : public nsIWidget
+class nsBaseWidget : public nsIWidget_MOZILLA_2_0_BRANCH
 {
   friend class nsAutoRollup;
 
 protected:
   typedef mozilla::layers::BasicLayerManager BasicLayerManager;
 
 public:
   nsBaseWidget();
@@ -136,17 +136,18 @@ public:
   virtual void            FreeNativeData(void * data, PRUint32 aDataType) {}
   NS_IMETHOD              BeginResizeDrag(nsGUIEvent* aEvent, PRInt32 aHorizontal, PRInt32 aVertical);
   NS_IMETHOD              BeginMoveDrag(nsMouseEvent* aEvent);
   virtual nsresult        ActivateNativeMenuItemAt(const nsAString& indexString) { return NS_ERROR_NOT_IMPLEMENTED; }
   virtual nsresult        ForceUpdateNativeMenuAt(const nsAString& indexString) { return NS_ERROR_NOT_IMPLEMENTED; }
   NS_IMETHOD              ResetInputState() { return NS_OK; }
   NS_IMETHOD              SetIMEOpenState(PRBool aState) { return NS_ERROR_NOT_IMPLEMENTED; }
   NS_IMETHOD              GetIMEOpenState(PRBool* aState) { return NS_ERROR_NOT_IMPLEMENTED; }
-  NS_IMETHOD              SetIMEEnabled(PRUint32 aState) { return NS_ERROR_NOT_IMPLEMENTED; }
+  NS_IMETHOD              SetInputMode(const IMEContext& aContext) { return NS_ERROR_NOT_IMPLEMENTED; }
+  NS_IMETHOD              SetIMEEnabled(PRUint32 aState);
   NS_IMETHOD              GetIMEEnabled(PRUint32* aState) { return NS_ERROR_NOT_IMPLEMENTED; }
   NS_IMETHOD              CancelIMEComposition() { return NS_OK; }
   NS_IMETHOD              SetAcceleratedRendering(PRBool aEnabled);
   virtual PRBool          GetAcceleratedRendering();
   virtual PRBool          GetShouldAccelerate();
   NS_IMETHOD              GetToggledKeyState(PRUint32 aKeyCode, PRBool* aLEDState) { return NS_ERROR_NOT_IMPLEMENTED; }
   NS_IMETHOD              OnIMEFocusChange(PRBool aFocus) { return NS_ERROR_NOT_IMPLEMENTED; }
   NS_IMETHOD              OnIMETextChange(PRUint32 aStart, PRUint32 aOldEnd, PRUint32 aNewEnd) { return NS_ERROR_NOT_IMPLEMENTED; }