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 id17134
push usermwu@mozilla.com
push dateTue, 23 Nov 2010 07:03:37 +0000
treeherdermozilla-central@5c0802167d09 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersroc, masayuki, roc, blocking-fennec
bugs581596
milestone2.0b8pre
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 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; }