Bug 581596 - Create GetInputMode API, r=masayuki,roc sr=roc a=blocking-fennec
authorMichael Wu <mwu@mozilla.com>
Mon, 22 Nov 2010 22:48:45 -0800
changeset 58019 6ed1bf8ddeec122096e4a261dd621267a89675da
parent 58018 92bb7d084e2b4c91a375631bb6b0706d9a7d9851
child 58020 0b2b0417c11f7ecdc7e0baad92a8149790696613
push idunknown
push userunknown
push dateunknown
reviewersmasayuki, roc, 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 - Create GetInputMode API, r=masayuki,roc sr=roc a=blocking-fennec
content/events/src/nsIMEStateManager.cpp
dom/base/nsDOMClassInfo.cpp
dom/base/nsDOMWindowUtils.cpp
dom/base/nsDOMWindowUtils.h
dom/base/nsGlobalWindow.cpp
dom/interfaces/base/nsIDOMWindowUtils.idl
dom/ipc/TabParent.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/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
widget/tests/test_imestate.html
--- a/content/events/src/nsIMEStateManager.cpp
+++ b/content/events/src/nsIMEStateManager.cpp
@@ -134,22 +134,23 @@ nsIMEStateManager::OnChangeFocus(nsPresC
   if (aPresContext == sPresContext && aContent == sContent) {
     // actual focus isn't changing, but if IME enabled state is changing,
     // we should do it.
     PRUint32 newEnabledState = newState & nsIContent::IME_STATUS_MASK_ENABLED;
     if (newEnabledState == 0) {
       // the enabled state isn't changing, we should do nothing.
       return NS_OK;
     }
-    PRUint32 enabled;
-    if (NS_FAILED(widget->GetIMEEnabled(&enabled))) {
+    nsIWidget_MOZILLA_2_0_BRANCH* widget2 = static_cast<nsIWidget_MOZILLA_2_0_BRANCH*>(widget.get());
+    IMEContext context;
+    if (!widget2 || NS_FAILED(widget2->GetInputMode(context))) {
       // this platform doesn't support IME controlling
       return NS_OK;
     }
-    if (enabled ==
+    if (context.mStatus ==
         nsContentUtils::GetWidgetStatusFromIMEStatus(newEnabledState)) {
       // the enabled state isn't changing.
       return NS_OK;
     }
   }
 
   // Current IME transaction should commit
   if (sPresContext) {
@@ -190,23 +191,24 @@ nsIMEStateManager::UpdateIMEState(PRUint
   NS_PRECONDITION(aNewIMEState != 0, "aNewIMEState doesn't specify new state.");
   nsCOMPtr<nsIWidget> widget = GetWidget(sPresContext);
   if (!widget) {
     NS_WARNING("focused widget is not found");
     return;
   }
 
   // Don't update IME state when enabled state isn't actually changed.
-  PRUint32 currentEnabledState;
-  nsresult rv = widget->GetIMEEnabled(&currentEnabledState);
+  nsIWidget_MOZILLA_2_0_BRANCH* widget2 = static_cast<nsIWidget_MOZILLA_2_0_BRANCH*>(widget.get());
+  IMEContext context;
+  nsresult rv = widget2->GetInputMode(context);
   if (NS_FAILED(rv)) {
     return; // This platform doesn't support controling the IME state.
   }
   PRUint32 newEnabledState = aNewIMEState & nsIContent::IME_STATUS_MASK_ENABLED;
-  if (currentEnabledState ==
+  if (context.mStatus ==
         nsContentUtils::GetWidgetStatusFromIMEStatus(newEnabledState)) {
     return;
   }
 
   // commit current composition
   widget->ResetInputState();
 
   SetIMEState(aNewIMEState, aContent, widget);
@@ -260,18 +262,16 @@ private:
 };
 
 void
 nsIMEStateManager::SetIMEState(PRUint32 aState,
                                nsIContent* aContent,
                                nsIWidget* aWidget)
 {
   if (aState & nsIContent::IME_STATUS_MASK_ENABLED) {
-    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;
 
--- a/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -2245,16 +2245,17 @@ nsDOMClassInfo::Init()
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMEventTarget)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMViewCSS)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMAbstractView)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMStorageWindow)
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(WindowUtils, nsIDOMWindowUtils)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMWindowUtils)
+    DOM_CLASSINFO_MAP_ENTRY(nsIDOMWindowUtils_MOZILLA_2_0_BRANCH)
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(Location, nsIDOMLocation)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMLocation)
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(Navigator, nsIDOMNavigator)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMNavigator)
--- a/dom/base/nsDOMWindowUtils.cpp
+++ b/dom/base/nsDOMWindowUtils.cpp
@@ -92,16 +92,17 @@ static PRBool IsUniversalXPConnectCapabl
   return hasCap;
 }
 
 DOMCI_DATA(WindowUtils, nsDOMWindowUtils)
 
 NS_INTERFACE_MAP_BEGIN(nsDOMWindowUtils)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMWindowUtils)
   NS_INTERFACE_MAP_ENTRY(nsIDOMWindowUtils)
+  NS_INTERFACE_MAP_ENTRY(nsIDOMWindowUtils_MOZILLA_2_0_BRANCH)
   NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(WindowUtils)
 NS_INTERFACE_MAP_END
 
 NS_IMPL_ADDREF(nsDOMWindowUtils)
 NS_IMPL_RELEASE(nsDOMWindowUtils)
 
 nsDOMWindowUtils::nsDOMWindowUtils(nsGlobalWindow *aWindow)
@@ -939,35 +940,61 @@ nsDOMWindowUtils::GetIMEIsOpen(PRBool *a
 {
   NS_ENSURE_ARG_POINTER(aState);
 
   nsCOMPtr<nsIWidget> widget = GetWidget();
   if (!widget)
     return NS_ERROR_FAILURE;
 
   // Open state should not be available when IME is not enabled.
-  PRUint32 enabled;
-  nsresult rv = widget->GetIMEEnabled(&enabled);
+  nsIWidget_MOZILLA_2_0_BRANCH* widget2 = static_cast<nsIWidget_MOZILLA_2_0_BRANCH*>(widget.get());
+  IMEContext context;
+  nsresult rv = widget2->GetInputMode(context);
   NS_ENSURE_SUCCESS(rv, rv);
-  if (enabled != nsIWidget::IME_STATUS_ENABLED)
+  if (context.mStatus != nsIWidget::IME_STATUS_ENABLED)
     return NS_ERROR_NOT_AVAILABLE;
 
   return widget->GetIMEOpenState(aState);
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::GetIMEStatus(PRUint32 *aState)
 {
   NS_ENSURE_ARG_POINTER(aState);
 
   nsCOMPtr<nsIWidget> widget = GetWidget();
   if (!widget)
     return NS_ERROR_FAILURE;
 
-  return widget->GetIMEEnabled(aState);
+  nsIWidget_MOZILLA_2_0_BRANCH* widget2 = static_cast<nsIWidget_MOZILLA_2_0_BRANCH*>(widget.get());
+  IMEContext context;
+  nsresult rv = widget2->GetInputMode(context);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  *aState = context.mStatus;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDOMWindowUtils::GetFocusedInputType(char** aType)
+{
+  NS_ENSURE_ARG_POINTER(aType);
+
+  nsCOMPtr<nsIWidget> widget = GetWidget();
+  if (!widget) {
+    return NS_ERROR_FAILURE;
+  }
+
+  nsIWidget_MOZILLA_2_0_BRANCH* widget2 = static_cast<nsIWidget_MOZILLA_2_0_BRANCH*>(widget.get());
+  IMEContext context;
+  nsresult rv = widget2->GetInputMode(context);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  *aType = ToNewCString(context.mHTMLInputType);
+  return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::GetScreenPixelsPerCSSPixel(float* aScreenPixels)
 {
   *aScreenPixels = 1;
 
   if (!nsContentUtils::IsCallerTrustedForRead())
--- a/dom/base/nsDOMWindowUtils.h
+++ b/dom/base/nsDOMWindowUtils.h
@@ -39,23 +39,25 @@
 #include "nsWeakReference.h"
 
 #include "nsIDOMWindowUtils.h"
 
 class nsGlobalWindow;
 class nsIPresShell;
 
 class nsDOMWindowUtils : public nsIDOMWindowUtils,
+                         public nsIDOMWindowUtils_MOZILLA_2_0_BRANCH,
                          public nsSupportsWeakReference
 {
 public:
   nsDOMWindowUtils(nsGlobalWindow *aWindow);
   ~nsDOMWindowUtils();
   NS_DECL_ISUPPORTS
   NS_DECL_NSIDOMWINDOWUTILS
+  NS_DECL_NSIDOMWINDOWUTILS_MOZILLA_2_0_BRANCH
 
 protected:
   nsRefPtr<nsGlobalWindow> mWindow;
 
   // If aOffset is non-null, it gets filled in with the offset of the root
   // frame of our window to the nearest widget in the app units of our window.
   // Add this offset to any event offset we're given to make it relative to the
   // widget returned by GetWidget.
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -7891,17 +7891,18 @@ nsGlobalWindow::GetInterface(const nsIID
     if (mDoc) {
       nsIScriptEventManager* mgr = mDoc->GetScriptEventManager();
       if (mgr) {
         *aSink = mgr;
         NS_ADDREF(((nsISupports *) *aSink));
       }
     }
   }
-  else if (aIID.Equals(NS_GET_IID(nsIDOMWindowUtils))) {
+  else if (aIID.Equals(NS_GET_IID(nsIDOMWindowUtils)) ||
+           aIID.Equals(NS_GET_IID(nsIDOMWindowUtils_MOZILLA_2_0_BRANCH))) {
     FORWARD_TO_OUTER(GetInterface, (aIID, aSink), NS_ERROR_NOT_INITIALIZED);
 
     nsCOMPtr<nsISupports> utils(do_QueryReferent(mWindowUtils));
     if (utils) {
       *aSink = utils;
       NS_ADDREF(((nsISupports *) *aSink));
     } else {
       nsDOMWindowUtils *utilObj = new nsDOMWindowUtils(this);
--- a/dom/interfaces/base/nsIDOMWindowUtils.idl
+++ b/dom/interfaces/base/nsIDOMWindowUtils.idl
@@ -60,17 +60,17 @@ interface nsIDOMNode;
 interface nsIDOMNodeList;
 interface nsIDOMElement;
 interface nsIDOMHTMLCanvasElement;
 interface nsIDOMEvent;
 interface nsITransferable;
 interface nsIQueryContentEventResult;
 interface nsIDOMWindow;
 
-[scriptable, uuid(def3fbe8-961b-4c8b-8cac-eb6a4e604bb5)]
+[scriptable, uuid(85fa978a-fc91-4513-9f11-8911e671577f)]
 interface nsIDOMWindowUtils : nsISupports {
 
   /**
    * Image animation mode of the window. When this attribute's value
    * is changed, the implementation should set all images in the window
    * to the given value. That is, when set to kDontAnimMode, all images
    * will stop animating. The attribute's value must be one of the
    * animationMode values from imgIContainer.
@@ -816,8 +816,16 @@ interface nsIDOMWindowUtils : nsISupport
    * nsStyleAnimation::ComputeDistance for the given element and
    * property.
    */
   double computeAnimationDistance(in nsIDOMElement element,
                                   in AString property,
                                   in AString value1,
                                   in AString value2);
 };
+
+[scriptable, uuid(3a0334aa-b9cc-4b32-9b6c-599cd4e40d5b)]
+interface nsIDOMWindowUtils_MOZILLA_2_0_BRANCH : nsISupports {
+  /**
+   * Get the type of the currently focused html input, if any.
+   */
+  readonly attribute string focusedInputType;
+};
--- a/dom/ipc/TabParent.cpp
+++ b/dom/ipc/TabParent.cpp
@@ -477,18 +477,25 @@ TabParent::RecvEndIMEComposition(const P
   mIMECompositionText.Truncate(0);  
   return true;
 }
 
 bool
 TabParent::RecvGetIMEEnabled(PRUint32* aValue)
 {
   nsCOMPtr<nsIWidget> widget = GetWidget();
-  if (widget)
-    widget->GetIMEEnabled(aValue);
+  if (!widget)
+    return true;
+
+  nsIWidget_MOZILLA_2_0_BRANCH* widget2 = static_cast<nsIWidget_MOZILLA_2_0_BRANCH*>(widget.get());
+  IMEContext context;
+  if (widget2) {
+    widget2->GetInputMode(context);
+    *aValue = context.mStatus;
+  }
   return true;
 }
 
 bool
 TabParent::RecvSetInputMode(const PRUint32& aValue, const nsString& aType)
 {
   nsCOMPtr<nsIWidget> widget = GetWidget();
   if (!widget || !AllowContentIME())
--- a/widget/public/nsIWidget.h
+++ b/widget/public/nsIWidget.h
@@ -1368,13 +1368,18 @@ class nsIWidget_MOZILLA_2_0_BRANCH : pub
 
     /*
      * 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;
+
+    /*
+     * Get IME is 'Enabled' or 'Disabled' or 'Password' and other input context
+     */
+    NS_IMETHOD GetInputMode(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
@@ -1645,25 +1645,25 @@ nsWindow::ResetInputState()
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsWindow::SetInputMode(const IMEContext& aContext)
 {
     ALOGIME("IME: SetInputMode: s=%d", aContext.mStatus);
 
-    mIMEEnabled = aContext.mStatus;
-    AndroidBridge::NotifyIMEEnabled(int(mIMEEnabled), aContext.mHTMLInputType);
+    mIMEContext = aContext;
+    AndroidBridge::NotifyIMEEnabled(int(aContext.mStatus), aContext.mHTMLInputType);
     return NS_OK;
 }
 
 NS_IMETHODIMP
-nsWindow::GetIMEEnabled(PRUint32* aState)
+nsWindow::GetInputMode(IMEContext& aContext)
 {
-    *aState = mIMEEnabled;
+    aContext = mIMEContext;
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsWindow::CancelIMEComposition()
 {
     ALOGIME("IME: CancelIMEComposition");
 
--- a/widget/src/android/nsWindow.h
+++ b/widget/src/android/nsWindow.h
@@ -149,17 +149,17 @@ public:
                                    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 SetInputMode(const IMEContext& aContext);
-    NS_IMETHOD GetIMEEnabled(PRUint32* aState);
+    NS_IMETHOD GetInputMode(IMEContext& aContext);
     NS_IMETHOD CancelIMEComposition();
 
     NS_IMETHOD OnIMEFocusChange(PRBool aFocus);
     NS_IMETHOD OnIMETextChange(PRUint32 aStart, PRUint32 aOldEnd, PRUint32 aNewEnd);
     NS_IMETHOD OnIMESelectionChange(void);
     virtual nsIMEUpdatePreference GetIMEUpdatePreference();
 
     LayerManager* GetLayerManager(bool* aAllowRetaining = nsnull);
@@ -187,21 +187,22 @@ protected:
     nsAutoPtr<nsIntPoint> mStartPoint;
 
     // Multitouch swipe thresholds in screen pixels
     double mSwipeMaxPinchDelta;
     double mSwipeMinDistance;
 
     nsCOMPtr<nsIdleService> mIdleService;
 
-    PRUint32 mIMEEnabled;
     PRBool mIMEComposing;
     nsString mIMEComposingText;
     nsAutoTArray<nsTextRange, 4> mIMERanges;
 
+    IMEContext mIMEContext;
+
     static void DumpWindows();
     static void DumpWindows(const nsTArray<nsWindow*>& wins, int indent = 0);
     static void LogWindow(nsWindow *win, int index, int indent);
 
 private:
     void InitKeyEvent(nsKeyEvent& event, mozilla::AndroidGeckoEvent& key);
     void DispatchGestureEvent(mozilla::AndroidGeckoEvent *ae);
     void DispatchGestureEvent(PRUint32 msg, PRUint32 direction, double delta,
--- a/widget/src/cocoa/nsChildView.h
+++ b/widget/src/cocoa/nsChildView.h
@@ -348,17 +348,17 @@ public:
 
   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        SetInputMode(const IMEContext& aContext);
-  NS_IMETHOD        GetIMEEnabled(PRUint32* aState);
+  NS_IMETHOD        GetInputMode(IMEContext& aContext);
   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);
   NS_IMETHOD        StartDrawPlugin();
@@ -434,16 +434,17 @@ protected:
     nsCOMPtr<nsIWidget> widget = do_CreateInstance(kCPopUpCID);
     return widget.forget();
   }
 
 protected:
 
   NSView<mozView>*      mView;      // my parallel cocoa view (ChildView or NativeScrollbarView), [STRONG]
   nsCocoaTextInputHandler mTextInputHandler;
+  IMEContext            mIMEContext;
 
   NSView<mozView>*      mParentView;
   nsIWidget*            mParentWidget;
 
 #ifdef ACCESSIBILITY
   // weak ref to this childview's associated mozAccessible for speed reasons 
   // (we get queried for it *a lot* but don't want to own it)
   nsWeakPtr             mAccessible;
--- a/widget/src/cocoa/nsChildView.mm
+++ b/widget/src/cocoa/nsChildView.mm
@@ -1965,16 +1965,17 @@ NS_IMETHODIMP nsChildView::GetIMEOpenSta
 }
 
 NS_IMETHODIMP nsChildView::SetInputMode(const IMEContext& aContext)
 {
 #ifdef DEBUG_IME
   NSLog(@"**** SetInputMode mStatus = %d", aContext.mStatus);
 #endif
 
+  mIMEContext = aContext;
   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);
@@ -1985,29 +1986,23 @@ NS_IMETHODIMP nsChildView::SetInputMode(
       mTextInputHandler.EnableIME(PR_FALSE);
       break;
     default:
       NS_ERROR("not implemented!");
   }
   return NS_OK;
 }
 
-NS_IMETHODIMP nsChildView::GetIMEEnabled(PRUint32* aState)
+NS_IMETHODIMP nsChildView::GetInputMode(IMEContext& aContext)
 {
 #ifdef DEBUG_IME
-  NSLog(@"**** GetIMEEnabled");
+  NSLog(@"**** GetInputMode");
 #endif
 
-  if (mTextInputHandler.IsIMEEnabled()) {
-    *aState = nsIWidget::IME_STATUS_ENABLED;
-  } else if (mTextInputHandler.IsASCIICapableOnly()) {
-    *aState = nsIWidget::IME_STATUS_PASSWORD;
-  } else {
-    *aState = nsIWidget::IME_STATUS_DISABLED;
-  }
+  aContext = mIMEContext;
   return NS_OK;
 }
 
 // Destruct and don't commit the IME composition string.
 NS_IMETHODIMP nsChildView::CancelIMEComposition()
 {
 #ifdef DEBUG_IME
   NSLog(@"**** CancelIMEComposition");
--- a/widget/src/gtk2/nsGtkIMModule.cpp
+++ b/widget/src/gtk2/nsGtkIMModule.cpp
@@ -103,26 +103,27 @@ static PRBool gIsVirtualKeyboardOpened =
 #endif
 
 nsGtkIMModule::nsGtkIMModule(nsWindow* aOwnerWindow) :
     mOwnerWindow(aOwnerWindow), mLastFocusedWindow(nsnull),
     mContext(nsnull),
 #ifndef NS_IME_ENABLED_ON_PASSWORD_FIELD
     mSimpleContext(nsnull),
 #endif
-    mDummyContext(nsnull), mEnabled(nsIWidget::IME_STATUS_ENABLED),
+    mDummyContext(nsnull),
     mCompositionStart(PR_UINT32_MAX), mProcessingKeyEvent(nsnull),
     mIsComposing(PR_FALSE), mIsIMFocused(PR_FALSE),
     mIgnoreNativeCompositionEvent(PR_FALSE)
 {
 #ifdef PR_LOGGING
     if (!gGtkIMLog) {
         gGtkIMLog = PR_NewLogModule("nsGtkIMModuleWidgets");
     }
 #endif
+    mIMEContext.mStatus = nsIWidget::IME_STATUS_ENABLED;
     Init();
 }
 
 void
 nsGtkIMModule::Init()
 {
     PR_LOG(gGtkIMLog, PR_LOG_ALWAYS,
         ("GtkIMModule(%p): Init, mOwnerWindow=%p",
@@ -248,17 +249,17 @@ nsGtkIMModule::OnDestroyWindow(nsWindow*
         // so no need for another workaround_gtk_im_display_closed.
         gtk_im_context_set_client_window(mDummyContext, nsnull);
         g_object_unref(G_OBJECT(mDummyContext));
         mDummyContext = nsnull;
     }
 
     mOwnerWindow = nsnull;
     mLastFocusedWindow = nsnull;
-    mEnabled = nsIWidget::IME_STATUS_DISABLED;
+    mIMEContext.mStatus = nsIWidget::IME_STATUS_DISABLED;
 
     PR_LOG(gGtkIMLog, PR_LOG_ALWAYS,
         ("    SUCCEEDED, Completely destroyed"));
 }
 
 // Work around gtk bug http://bugzilla.gnome.org/show_bug.cgi?id=483223:
 // (and the similar issue of GTK+ IIIM)
 // The GTK+ XIM and IIIM modules register handlers for the "closed" signal
@@ -509,17 +510,17 @@ nsGtkIMModule::CancelIMEComposition(nsWi
     CommitCompositionBy(EmptyString());
 
     return NS_OK;
 }
 
 nsresult
 nsGtkIMModule::SetInputMode(nsWindow* aCaller, const IMEContext* aContext)
 {
-    if (aContext->mStatus == mEnabled || NS_UNLIKELY(IsDestroyed())) {
+    if (aContext->mStatus == mIMEContext.mStatus || NS_UNLIKELY(IsDestroyed())) {
         return NS_OK;
     }
 
     PR_LOG(gGtkIMLog, PR_LOG_ALWAYS,
         ("GtkIMModule(%p): SetInputMode, aCaller=%p, aState=%s mHTMLInputType=%s",
          this, aCaller, GetEnabledStateName(aContext->mStatus), aContext->mHTMLInputType.get()));
 
     if (aCaller != mLastFocusedWindow) {
@@ -532,29 +533,29 @@ nsGtkIMModule::SetInputMode(nsWindow* aC
     if (!mContext) {
         PR_LOG(gGtkIMLog, PR_LOG_ALWAYS,
             ("    FAILED, there are no context"));
         return NS_ERROR_NOT_AVAILABLE;
     }
 
 
     if (sLastFocusedModule != this) {
-        mEnabled = aContext->mStatus;
+        mIMEContext = *aContext;
         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 = aContext->mStatus;
+    mIMEContext = *aContext;
 
     // 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
@@ -562,20 +563,20 @@ nsGtkIMModule::SetInputMode(nsWindow* aC
     if (im) {
         if (IsEnabled()) {
             // It is not desired that the hildon's autocomplete mechanism displays
             // user previous entered passwds, so lets make completions invisible
             // in these cases.
             int mode;
             g_object_get(G_OBJECT(im), "hildon-input-mode", &mode, NULL);
 
-            if (mEnabled == nsIWidget::IME_STATUS_ENABLED ||
-                mEnabled == nsIWidget::IME_STATUS_PLUGIN) {
+            if (mIMEContext.mStatus == nsIWidget::IME_STATUS_ENABLED ||
+                mIMEContext.mStatus == nsIWidget::IME_STATUS_PLUGIN) {
                 mode &= ~HILDON_GTK_INPUT_MODE_INVISIBLE;
-            } else if (mEnabled == nsIWidget::IME_STATUS_PASSWORD) {
+            } else if (mIMEContext.mStatus == nsIWidget::IME_STATUS_PASSWORD) {
                mode |= HILDON_GTK_INPUT_MODE_INVISIBLE;
             }
 
             // Turn off auto-capitalization for editboxes
             mode &= ~HILDON_GTK_INPUT_MODE_AUTOCAP;
 
             // Turn off predictive dictionaries for editboxes
             mode &= ~HILDON_GTK_INPUT_MODE_DICTIONARY;
@@ -610,20 +611,20 @@ nsGtkIMModule::SetInputMode(nsWindow* aC
                                          rectBuf.get());
     }
 #endif
 
     return NS_OK;
 }
 
 nsresult
-nsGtkIMModule::GetIMEEnabled(PRUint32* aState)
+nsGtkIMModule::GetInputMode(IMEContext* aContext)
 {
-    NS_ENSURE_ARG_POINTER(aState);
-    *aState = mEnabled;
+    NS_ENSURE_ARG_POINTER(aContext);
+    *aContext = mIMEContext;
     return NS_OK;
 }
 
 /* static */
 PRBool
 nsGtkIMModule::IsVirtualKeyboardOpened()
 {
 #ifdef MOZ_PLATFORM_MAEMO
@@ -636,40 +637,40 @@ nsGtkIMModule::IsVirtualKeyboardOpened()
 GtkIMContext*
 nsGtkIMModule::GetContext()
 {
     if (IsEnabled()) {
         return mContext;
     }
 
 #ifndef NS_IME_ENABLED_ON_PASSWORD_FIELD
-    if (mEnabled == nsIWidget::IME_STATUS_PASSWORD) {
+    if (mIMEContext.mStatus == nsIWidget::IME_STATUS_PASSWORD) {
         return mSimpleContext;
     }
 #endif // NS_IME_ENABLED_ON_PASSWORD_FIELD
 
     return mDummyContext;
 }
 
 PRBool
 nsGtkIMModule::IsEnabled()
 {
-    return mEnabled == nsIWidget::IME_STATUS_ENABLED ||
+    return mIMEContext.mStatus == nsIWidget::IME_STATUS_ENABLED ||
 #ifdef NS_IME_ENABLED_ON_PASSWORD_FIELD
-           mEnabled == nsIWidget::IME_STATUS_PASSWORD ||
+           mIMEContext.mStatus == nsIWidget::IME_STATUS_PASSWORD ||
 #endif // NS_IME_ENABLED_ON_PASSWORD_FIELD
-           mEnabled == nsIWidget::IME_STATUS_PLUGIN;
+           mIMEContext.mStatus == nsIWidget::IME_STATUS_PLUGIN;
 }
 
 PRBool
 nsGtkIMModule::IsEditable()
 {
-    return mEnabled == nsIWidget::IME_STATUS_ENABLED ||
-           mEnabled == nsIWidget::IME_STATUS_PLUGIN ||
-           mEnabled == nsIWidget::IME_STATUS_PASSWORD;
+    return mIMEContext.mStatus == nsIWidget::IME_STATUS_ENABLED ||
+           mIMEContext.mStatus == nsIWidget::IME_STATUS_PLUGIN ||
+           mIMEContext.mStatus == nsIWidget::IME_STATUS_PASSWORD;
 }
 
 void
 nsGtkIMModule::Focus()
 {
     PR_LOG(gGtkIMLog, PR_LOG_ALWAYS,
         ("GtkIMModule(%p): Focus, sLastFocusedModule=%p",
          this, sLastFocusedModule));
--- a/widget/src/gtk2/nsGtkIMModule.h
+++ b/widget/src/gtk2/nsGtkIMModule.h
@@ -103,17 +103,17 @@ public:
     // 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 SetInputMode(nsWindow* aCaller, const IMEContext* aContext);
-    nsresult GetIMEEnabled(PRUint32* aState);
+    nsresult GetInputMode(IMEContext* aContext);
     nsresult CancelIMEComposition(nsWindow* aCaller);
 
     // If a software keyboard has been opened, this returns TRUE.
     // Otherwise, FALSE.
     static PRBool IsVirtualKeyboardOpened();
 
 protected:
     // Owner of an instance of this class. This should be top level window.
@@ -138,19 +138,19 @@ protected:
     GtkIMContext       *mSimpleContext;
 #endif // NS_IME_ENABLED_ON_PASSWORD_FIELD
 
     // mDummyContext is a dummy context and will be used in Focus()
     // when the state of mEnabled means disabled.  This context's IME state is
     // always "closed", so it closes IME forcedly.
     GtkIMContext       *mDummyContext;
 
-    // IME enabled state in this window.  The values is nsIWidget::IME_STATUS_*.
+    // IME enabled state and other things defined in IMEContext.
     // Use following helper methods if you don't need the detail of the status.
-    PRUint32           mEnabled;
+    IMEContext mIMEContext;
 
     // mCompositionStart is the start offset of the composition string in the
     // current content.  When <textarea> or <input> have focus, it means offset
     // from the first character of them.  When a HTML editor has focus, it
     // means offset from the first character of the root element of the editor.
     PRUint32 mCompositionStart;
 
     // mCompositionString is the current composing string. Even if this is
--- a/widget/src/gtk2/nsWindow.cpp
+++ b/widget/src/gtk2/nsWindow.cpp
@@ -6442,24 +6442,23 @@ nsWindow::ResetInputState()
 
 NS_IMETHODIMP
 nsWindow::SetInputMode(const IMEContext& aContext)
 {
     return mIMModule ? mIMModule->SetInputMode(this, &aContext) : NS_OK;
 }
 
 NS_IMETHODIMP
-nsWindow::GetIMEEnabled(PRUint32* aState)
-{
-  NS_ENSURE_ARG_POINTER(aState);
+nsWindow::GetInputMode(IMEContext& aContext)
+{
   if (!mIMModule) {
-      *aState = nsIWidget::IME_STATUS_DISABLED;
+      aContext.mStatus = nsIWidget::IME_STATUS_DISABLED;
       return NS_OK;
   }
-  return mIMModule->GetIMEEnabled(aState);
+  return mIMModule->GetInputMode(&aContext);
 }
 
 NS_IMETHODIMP
 nsWindow::CancelIMEComposition()
 {
     return mIMModule ? mIMModule->CancelIMEComposition(this) : NS_OK;
 }
 
--- a/widget/src/gtk2/nsWindow.h
+++ b/widget/src/gtk2/nsWindow.h
@@ -319,17 +319,17 @@ public:
 
     // If this dispatched the keydown event actually, this returns TRUE,
     // otherwise, FALSE.
     PRBool             DispatchKeyDownEvent(GdkEventKey *aEvent,
                                             PRBool *aIsCancelled);
 
     NS_IMETHOD ResetInputState();
     NS_IMETHOD SetInputMode(const IMEContext& aContext);
-    NS_IMETHOD GetIMEEnabled(PRUint32* aState);
+    NS_IMETHOD GetInputMode(IMEContext& aContext);
     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);
    virtual nsTransparencyMode GetTransparencyMode();
--- a/widget/src/qt/nsWindow.cpp
+++ b/widget/src/qt/nsWindow.cpp
@@ -2957,16 +2957,17 @@ nsWindow::AreBoundsSane(void)
     return PR_FALSE;
 }
 
 NS_IMETHODIMP
 nsWindow::SetInputMode(const IMEContext& aContext)
 {
     NS_ENSURE_TRUE(mWidget, NS_ERROR_FAILURE);
 
+    mIMEContext = aContext;
     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);
@@ -2978,22 +2979,19 @@ nsWindow::SetInputMode(const IMEContext&
             mWidget->hideVKB();
             break;
     }
 
     return NS_OK;
 }
 
 NS_IMETHODIMP
-nsWindow::GetIMEEnabled(PRUint32* aState)
+nsWindow::GetInputMode(IMEContext& aContext)
 {
-    NS_ENSURE_ARG_POINTER(aState);
-    NS_ENSURE_TRUE(mWidget, NS_ERROR_FAILURE);
-
-    *aState = mWidget->isVKBOpen() ? IME_STATUS_ENABLED : IME_STATUS_DISABLED;
+    aContext = mIMEContext;
     return NS_OK;
 }
 
 void
 nsWindow::UserActivity()
 {
   if (!mIdleService) {
     mIdleService = do_GetService("@mozilla.org/widget/idleservice;1");
--- a/widget/src/qt/nsWindow.h
+++ b/widget/src/qt/nsWindow.h
@@ -195,17 +195,17 @@ public:
                                            PRBool aConsumeRollupEvent);
 
     NS_IMETHOD         SetWindowClass(const nsAString& xulWinType);
 
     NS_IMETHOD         GetAttention(PRInt32 aCycleCount);
     NS_IMETHOD         BeginResizeDrag   (nsGUIEvent* aEvent, PRInt32 aHorizontal, PRInt32 aVertical);
 
     NS_IMETHODIMP      SetInputMode(const IMEContext& aContext);
-    NS_IMETHODIMP      GetIMEEnabled(PRUint32* aState);
+    NS_IMETHODIMP      GetInputMode(IMEContext& aContext);
 
     //
     // utility methods
     //
     void               QWidgetDestroyed();
 
     /***** from CommonWidget *****/
 
@@ -247,16 +247,18 @@ protected:
     // Has anyone set an x/y location for this widget yet? Toplevels
     // shouldn't be automatically set to 0,0 for first show.
     PRBool              mPlaced;
 
     // Remember the last sizemode so that we can restore it when
     // leaving fullscreen
     nsSizeMode         mLastSizeMode;
 
+    IMEContext          mIMEContext;
+
     /**
      * Event handlers (proxied from the actual qwidget).
      * They follow normal Qt widget semantics.
      */
     void Initialize(MozQWidget *widget);
     friend class nsQtEventDispatcher;
     friend class InterceptContainer;
     friend class MozQWidget;
--- a/widget/src/windows/nsWindow.cpp
+++ b/widget/src/windows/nsWindow.cpp
@@ -404,17 +404,17 @@ nsWindow::nsWindow() : nsBaseWidget()
   mLastSize.width       = 0;
   mLastSize.height      = 0;
   mOldStyle             = 0;
   mOldExStyle           = 0;
   mPainting             = 0;
   mExitToNonClientArea  = 0;
   mLastKeyboardLayout   = 0;
   mBlurSuppressLevel    = 0;
-  mIMEEnabled           = nsIWidget::IME_STATUS_ENABLED;
+  mIMEContext.mStatus   = nsIWidget::IME_STATUS_ENABLED;
 #ifdef MOZ_XUL
   mTransparentSurface   = nsnull;
   mMemoryDC             = nsnull;
   mTransparencyMode     = eTransparencyOpaque;
 #if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN
   memset(&mGlassMargins, 0, sizeof mGlassMargins);
 #endif // #if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN
 #endif
@@ -7541,39 +7541,39 @@ NS_IMETHODIMP nsWindow::SetInputMode(con
 #ifdef DEBUG_KBSTATE
   printf("SetInputMode: %s\n", (status == nsIWidget::IME_STATUS_ENABLED ||
                                 status == nsIWidget::IME_STATUS_PLUGIN) ? 
                                "Enabled" : "Disabled");
 #endif 
   if (nsIMM32Handler::IsComposing()) {
     ResetInputState();
   }
-  mIMEEnabled = status;
+  mIMEContext = aContext;
   PRBool enable = (status == nsIWidget::IME_STATUS_ENABLED ||
                    status == nsIWidget::IME_STATUS_PLUGIN);
 
 #if defined(WINCE_HAVE_SOFTKB)
   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");
 
   return NS_OK;
 }
 
-NS_IMETHODIMP nsWindow::GetIMEEnabled(PRUint32* aState)
+NS_IMETHODIMP nsWindow::GetInputMode(IMEContext& aContext)
 {
 #ifdef DEBUG_KBSTATE
-  printf("GetIMEEnabled: %s\n", mIMEEnabled? "Enabled": "Disabled");
+  printf("GetInputMode: %s\n", mIMEContext.mStatus ? "Enabled" : "Disabled");
 #endif 
-  *aState = mIMEEnabled;
+  aContext = mIMEContext;
   return NS_OK;
 }
 
 NS_IMETHODIMP nsWindow::CancelIMEComposition()
 {
 #ifdef DEBUG_KBSTATE
   printf("CancelIMEComposition\n");
 #endif 
@@ -7596,17 +7596,17 @@ nsWindow::GetToggledKeyState(PRUint32 aK
   *aLEDState = (::GetKeyState(aKeyCode) & 1) != 0;
   return NS_OK;
 }
 
 #ifdef NS_ENABLE_TSF
 NS_IMETHODIMP
 nsWindow::OnIMEFocusChange(PRBool aFocus)
 {
-  nsresult rv = nsTextStore::OnFocusChange(aFocus, this, mIMEEnabled);
+  nsresult rv = nsTextStore::OnFocusChange(aFocus, this, mIMEContext.mStatus);
   if (rv == NS_ERROR_NOT_AVAILABLE)
     rv = NS_ERROR_NOT_IMPLEMENTED; // TSF is not enabled, maybe.
   return rv;
 }
 
 NS_IMETHODIMP
 nsWindow::OnIMETextChange(PRUint32 aStart,
                           PRUint32 aOldEnd,
--- a/widget/src/windows/nsWindow.h
+++ b/widget/src/windows/nsWindow.h
@@ -178,17 +178,17 @@ public:
                                                    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              SetInputMode(const IMEContext& aContext);
-  NS_IMETHOD              GetIMEEnabled(PRUint32* aState);
+  NS_IMETHOD              GetInputMode(IMEContext& aContext);
   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();
   virtual void            UpdatePossiblyTransparentRegion(const nsIntRegion &aDirtyRegion, const nsIntRegion& aPossiblyTransparentRegion);
@@ -248,19 +248,18 @@ public:
   WindowHook&             GetWindowHook() { return mWindowHook; }
   nsWindow*               GetParentWindow(PRBool aIncludeOwner);
 
   /**
    * Misc.
    */
   virtual PRBool          AutoErase(HDC dc);
   nsIntPoint*             GetLastPoint() { return &mLastPoint; }
-  PRBool                  GetIMEEnabled() { return mIMEEnabled; }
   // needed in nsIMM32Handler.cpp
-  PRBool                  PluginHasFocus() { return mIMEEnabled == nsIWidget::IME_STATUS_PLUGIN; }
+  PRBool                  PluginHasFocus() { return mIMEContext.mStatus == nsIWidget::IME_STATUS_PLUGIN; }
   PRBool                  IsTopLevelWidget() { return mIsTopWidgetWindow; }
 
 #if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_WIN7
   PRBool HasTaskbarIconBeenCreated() { return mHasTaskbarIconBeenCreated; }
   // Called when either the nsWindow or an nsITaskbarTabPreview receives the noticiation that this window
   // has its icon placed on the taskbar.
   void SetHasTaskbarIconBeenCreated(PRBool created = PR_TRUE) { mHasTaskbarIconBeenCreated = created; }
 
@@ -478,17 +477,17 @@ protected:
   PRPackedBool          mDisplayPanFeedback;
   PRPackedBool          mHideChrome;
   PRPackedBool          mIsRTL;
   PRPackedBool          mFullscreenMode;
   PRUint32              mBlurSuppressLevel;
   DWORD_PTR             mOldStyle;
   DWORD_PTR             mOldExStyle;
   HIMC                  mOldIMC;
-  PRUint32              mIMEEnabled;
+  IMEContext            mIMEContext;
   nsNativeDragTarget*   mNativeDragTarget;
   HKL                   mLastKeyboardLayout;
   nsPopupType           mPopupType;
   nsSizeMode            mOldSizeMode;
   WindowHook            mWindowHook;
   static PRUint32       sInstanceCount;
   static TriStateBool   sCanQuit;
   static nsWindow*      sCurrentWindow;
--- a/widget/src/xpwidgets/PuppetWidget.cpp
+++ b/widget/src/xpwidgets/PuppetWidget.cpp
@@ -383,20 +383,20 @@ PuppetWidget::GetIMEOpenState(PRBool *aS
 {
   if (mTabChild &&
       mTabChild->SendGetIMEOpenState(aState))
     return NS_OK;
   return NS_ERROR_FAILURE;
 }
 
 NS_IMETHODIMP
-PuppetWidget::GetIMEEnabled(PRUint32 *aState)
+PuppetWidget::GetInputMode(IMEContext& aContext)
 {
   if (mTabChild &&
-      mTabChild->SendGetIMEEnabled(aState))
+      mTabChild->SendGetIMEEnabled(&aContext.mStatus))
     return NS_OK;
   return NS_ERROR_FAILURE;
 }
 
 NS_IMETHODIMP
 PuppetWidget::OnIMEFocusChange(PRBool aFocus)
 {
   if (!mTabChild)
--- a/widget/src/xpwidgets/PuppetWidget.h
+++ b/widget/src/xpwidgets/PuppetWidget.h
@@ -167,17 +167,17 @@ public:
   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 SetInputMode(const IMEContext& aContext);
-  NS_IMETHOD GetIMEEnabled(PRUint32 *aState);
+  NS_IMETHOD GetInputMode(IMEContext& aContext);
   NS_IMETHOD CancelComposition();
   NS_IMETHOD OnIMEFocusChange(PRBool aFocus);
   NS_IMETHOD OnIMETextChange(PRUint32 aOffset, PRUint32 aEnd,
                              PRUint32 aNewEnd);
   NS_IMETHOD OnIMESelectionChange(void);
 
 private:
   nsresult DispatchPaintEvent();
--- a/widget/src/xpwidgets/nsBaseWidget.cpp
+++ b/widget/src/xpwidgets/nsBaseWidget.cpp
@@ -1174,16 +1174,27 @@ nsBaseWidget::BeginMoveDrag(nsMouseEvent
 NS_IMETHODIMP
 nsBaseWidget::SetIMEEnabled(PRUint32 aState)
 {
   IMEContext context;
   context.mStatus = aState;
   return SetInputMode(context);
 }
  
+NS_IMETHODIMP
+nsBaseWidget::GetIMEEnabled(PRUint32* aState)
+{
+  IMEContext context;
+  nsresult rv = GetInputMode(context);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  *aState = context.mStatus;
+  return NS_OK;
+}
+ 
 #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
 // for a DebugPrintEvent() function that uses
--- a/widget/src/xpwidgets/nsBaseWidget.h
+++ b/widget/src/xpwidgets/nsBaseWidget.h
@@ -137,18 +137,19 @@ public:
   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              SetInputMode(const IMEContext& aContext) { return NS_ERROR_NOT_IMPLEMENTED; }
+  NS_IMETHOD              GetInputMode(IMEContext& aContext) { return NS_ERROR_NOT_IMPLEMENTED; }
   NS_IMETHOD              SetIMEEnabled(PRUint32 aState);
-  NS_IMETHOD              GetIMEEnabled(PRUint32* aState) { return NS_ERROR_NOT_IMPLEMENTED; }
+  NS_IMETHOD              GetIMEEnabled(PRUint32* aState);
   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; }
   NS_IMETHOD              OnIMESelectionChange(void) { return NS_ERROR_NOT_IMPLEMENTED; }
--- a/widget/tests/test_imestate.html
+++ b/widget/tests/test_imestate.html
@@ -20,16 +20,23 @@
   <input type="checkbox" id="checkbox"/><br/>
   <input type="radio"    id="radio"/><br/>
   <input type="submit"   id="submit"/><br/>
   <input type="reset"    id="reset"/><br/>
   <input type="file"     id="file"/><br/>
   <input type="button"   id="ibutton"/><br/>
   <input type="image"    id="image" alt="image"/><br/>
 
+  <!-- html5 input elements -->
+  <input type="url"      id="url"/><br/>
+  <input type="email"    id="email"/><br/>
+  <input type="search"   id="search"/><br/>
+  <input type="tel"      id="tel"/><br/>
+  <input type="number"   id="number"/><br/>
+
   <!-- form controls -->
   <button id="button">button</button><br/>
   <textarea id="textarea">textarea</textarea><br/>
   <textarea id="textarea_readonly" readonly="readonly">textarea[readonly]</textarea><br/>
   <select id="select">
     <option value="option" selected="selected"/>
   </select><br/>
   <select id="select_multiple" multiple="multiple">
@@ -41,16 +48,47 @@
   <a id="a_href" href="about:blank">a[href]</a><br/>
 
   <!-- ime-mode test -->
   <input type="text" id="ime_mode_auto"     style="ime-mode: auto;"/><br/>
   <input type="text" id="ime_mode_normal"   style="ime-mode: normal;"/><br/>
   <input type="text" id="ime_mode_active"   style="ime-mode: active;"/><br/>
   <input type="text" id="ime_mode_inactive" style="ime-mode: inactive;"/><br/>
   <input type="text" id="ime_mode_disabled" style="ime-mode: disabled;"/><br/>
+
+  <input type="text" id="ime_mode_auto_url"     style="ime-mode: auto;"/><br/>
+  <input type="text" id="ime_mode_normal_url"   style="ime-mode: normal;"/><br/>
+  <input type="text" id="ime_mode_active_url"   style="ime-mode: active;"/><br/>
+  <input type="text" id="ime_mode_inactive_url" style="ime-mode: inactive;"/><br/>
+  <input type="text" id="ime_mode_disabled_url" style="ime-mode: disabled;"/><br/>
+
+  <input type="text" id="ime_mode_auto_email"     style="ime-mode: auto;"/><br/>
+  <input type="text" id="ime_mode_normal_email"   style="ime-mode: normal;"/><br/>
+  <input type="text" id="ime_mode_active_email"   style="ime-mode: active;"/><br/>
+  <input type="text" id="ime_mode_inactive_email" style="ime-mode: inactive;"/><br/>
+  <input type="text" id="ime_mode_disabled_email" style="ime-mode: disabled;"/><br/>
+
+  <input type="text" id="ime_mode_auto_search"     style="ime-mode: auto;"/><br/>
+  <input type="text" id="ime_mode_normal_search"   style="ime-mode: normal;"/><br/>
+  <input type="text" id="ime_mode_active_search"   style="ime-mode: active;"/><br/>
+  <input type="text" id="ime_mode_inactive_search" style="ime-mode: inactive;"/><br/>
+  <input type="text" id="ime_mode_disabled_search" style="ime-mode: disabled;"/><br/>
+
+  <input type="text" id="ime_mode_auto_tel"     style="ime-mode: auto;"/><br/>
+  <input type="text" id="ime_mode_normal_tel"   style="ime-mode: normal;"/><br/>
+  <input type="text" id="ime_mode_active_tel"   style="ime-mode: active;"/><br/>
+  <input type="text" id="ime_mode_inactive_tel" style="ime-mode: inactive;"/><br/>
+  <input type="text" id="ime_mode_disabled_tel" style="ime-mode: disabled;"/><br/>
+
+  <input type="text" id="ime_mode_auto_number"     style="ime-mode: auto;"/><br/>
+  <input type="text" id="ime_mode_normal_number"   style="ime-mode: normal;"/><br/>
+  <input type="text" id="ime_mode_active_number"   style="ime-mode: active;"/><br/>
+  <input type="text" id="ime_mode_inactive_number" style="ime-mode: inactive;"/><br/>
+  <input type="text" id="ime_mode_disabled_number" style="ime-mode: disabled;"/><br/>
+
   <input type="password" id="ime_mode_auto_p"     style="ime-mode: auto;"/><br/>
   <input type="password" id="ime_mode_normal_p"   style="ime-mode: normal;"/><br/>
   <input type="password" id="ime_mode_active_p"   style="ime-mode: active;"/><br/>
   <input type="password" id="ime_mode_inactive_p" style="ime-mode: inactive;"/><br/>
   <input type="password" id="ime_mode_disabled_p" style="ime-mode: disabled;"/><br/>
   <textarea id="ime_mode_auto_t"     style="ime-mode: auto;">textarea</textarea><br/>
   <textarea id="ime_mode_normal_t"   style="ime-mode: normal;">textarea</textarea><br/>
   <textarea id="ime_mode_active_t"   style="ime-mode: active;">textarea</textarea><br/>
@@ -76,16 +114,22 @@
 
 <script class="testbody" type="application/javascript">
 
 SimpleTest.waitForExplicitFinish();
 
 var gUtils = window.
       QueryInterface(Components.interfaces.nsIInterfaceRequestor).
       getInterface(Components.interfaces.nsIDOMWindowUtils);
+var gUtils2 = gUtils.QueryInterface(Components.interfaces.nsIDOMWindowUtils_MOZILLA_2_0_BRANCH);
+/*
+var gUtils2 = window.
+      QueryInterface(Components.interfaces.nsIInterfaceRequestor).
+      getInterface(Components.interfaces.nsIDOMWindowUtils_MOZILLA_2_0_BRANCH);
+*/
 var gFM = Components.classes["@mozilla.org/focus-manager;1"].
       getService(Components.interfaces.nsIFocusManager);
 const kIMEEnabledSupported = navigator.platform.indexOf("Mac") == 0 ||
                              navigator.platform.indexOf("Win") == 0 ||
                              navigator.platform.indexOf("Linux") == 0;
 
 // We support to control IME open state on Windows and Mac actually.  However,
 // we cannot test it on Mac if the current keyboard layout is not CJK. And also
@@ -148,18 +192,26 @@ function runBasicTest(aIsEditable, aInDe
 
     // IME Enabled state testing
     var enabled = gUtils.IME_STATUS_ENABLED;
     if (kIMEEnabledSupported) {
       if (!moveFocus(aTest)) {
         return;
       }
       enabled = gUtils.IMEStatus;
+      inputtype = gUtils2.focusedInputType;
       is(enabled, aTest.expectedEnabled,
          aDescription + ": " + aTest.description + ", wrong enabled state");
+      if (aTest.expectedType && !aInDesignMode) {
+        is(inputtype, aTest.expectedType,
+           aDescription + ": " + aTest.description + ", wrong input type");
+      } else if (aInDesignMode) {
+        is(inputtype, "",
+           aDescription + ": " + aTest.description + ", wrong input type")
+      }
     }
 
     if (!kIMEOpenSupported || enabled != gUtils.IME_STATUS_ENABLED ||
         aTest.expectedEnabled != gUtils.IME_STATUS_ENABLED) {
       return;
     }
 
     // IME Open state testing
@@ -186,25 +238,27 @@ function runBasicTest(aIsEditable, aInDe
   const kEnabledStateOnPasswordField =
     aInDesignMode ? gUtils.IME_STATUS_ENABLED : gUtils.IME_STATUS_PASSWORD;
   const kEnabledStateOnReadonlyField =
     aInDesignMode ? gUtils.IME_STATUS_ENABLED : gUtils.IME_STATUS_DISABLED;
   const kTests = [
     { id: "text",
       description: "input[type=text]",
       focusable: !aInDesignMode,
-      expectedEnabled: gUtils.IME_STATUS_ENABLED },
+      expectedEnabled: gUtils.IME_STATUS_ENABLED,
+      expectedType: "text" },
     { id: "text_readonly",
       description: "input[type=text][readonly]",
       focusable: !aInDesignMode,
       expectedEnabled: kEnabledStateOnReadonlyField },
     { id: "password",
       description: "input[type=password]",
       focusable: !aInDesignMode,
-      expectedEnabled: kEnabledStateOnPasswordField },
+      expectedEnabled: kEnabledStateOnPasswordField,
+      expectedType: "password" },
     { id: "password_readonly",
       description: "input[type=password][readonly]",
       focusable: !aInDesignMode,
       expectedEnabled: kEnabledStateOnReadonlyField },
     { id: "checkbox",
       description: "input[type=checkbox]",
       focusable: !aInDesignMode,
       expectedEnabled: kEnabledStateOnNonEditableElement },
@@ -227,16 +281,41 @@ function runBasicTest(aIsEditable, aInDe
     { id: "button",
       description: "input[type=button]",
       focusable: !aInDesignMode,
       expectedEnabled: kEnabledStateOnNonEditableElement },
     { id: "image",
       description: "input[type=image]",
       focusable: !aInDesignMode,
       expectedEnabled: kEnabledStateOnNonEditableElement },
+    { id: "url",
+      description: "input[type=url]",
+      focusable: !aInDesignMode,
+      expectedEnabled: gUtils.IME_STATUS_ENABLED,
+      expectedType: "url" },
+    { id: "email",
+      description: "input[type=email]",
+      focusable: !aInDesignMode,
+      expectedEnabled: gUtils.IME_STATUS_ENABLED,
+      expectedType: "email" },
+    { id: "search",
+      description: "input[type=search]",
+      focusable: !aInDesignMode,
+      expectedEnabled: gUtils.IME_STATUS_ENABLED,
+      expectedType: "search" },
+    { id: "tel",
+      description: "input[type=tel]",
+      focusable: !aInDesignMode,
+      expectedEnabled: gUtils.IME_STATUS_ENABLED,
+      expectedType: "tel" },
+    { id: "number",
+      description: "input[type=number]",
+      focusable: !aInDesignMode,
+      expectedEnabled: gUtils.IME_STATUS_ENABLED,
+      expectedType: "number" },
 
     // form controls
     { id: "button",
       description: "button",
       focusable: !aInDesignMode,
       expectedEnabled: kEnabledStateOnNonEditableElement },
     { id: "textarea",
       description: "textarea",
@@ -279,16 +358,132 @@ function runBasicTest(aIsEditable, aInDe
       description: "input[type=text][style=\"ime-mode: inactive;\"]",
       expectedEnabled: gUtils.IME_STATUS_ENABLED,
       focusable: !aInDesignMode,
       changeOpened: true, expectedOpened: false },
     { id: "ime_mode_disabled",
       description: "input[type=text][style=\"ime-mode: disabled;\"]",
       focusable: !aInDesignMode,
       expectedEnabled: kEnabledStateOnPasswordField },
+
+    { id: "ime_mode_auto_url",
+      description: "input[type=url][style=\"ime-mode: auto;\"]",
+      focusable: !aInDesignMode,
+      expectedEnabled: gUtils.IME_STATUS_ENABLED },
+    { id: "ime_mode_normal_url",
+      description: "input[type=url][style=\"ime-mode: normal;\"]",
+      focusable: !aInDesignMode,
+      expectedEnabled: gUtils.IME_STATUS_ENABLED },
+    { id: "ime_mode_active_url",
+      description: "input[type=url][style=\"ime-mode: active;\"]",
+      expectedEnabled: gUtils.IME_STATUS_ENABLED,
+      focusable: !aInDesignMode,
+      changeOpened: true, expectedOpened: true },
+    { id: "ime_mode_inactive_url",
+      description: "input[type=url][style=\"ime-mode: inactive;\"]",
+      expectedEnabled: gUtils.IME_STATUS_ENABLED,
+      focusable: !aInDesignMode,
+      changeOpened: true, expectedOpened: false },
+    { id: "ime_mode_disabled_url",
+      description: "input[type=url][style=\"ime-mode: disabled;\"]",
+      focusable: !aInDesignMode,
+      expectedEnabled: kEnabledStateOnPasswordField },
+
+    { id: "ime_mode_auto_email",
+      description: "input[type=email][style=\"ime-mode: auto;\"]",
+      focusable: !aInDesignMode,
+      expectedEnabled: gUtils.IME_STATUS_ENABLED },
+    { id: "ime_mode_normal_email",
+      description: "input[type=email][style=\"ime-mode: normal;\"]",
+      focusable: !aInDesignMode,
+      expectedEnabled: gUtils.IME_STATUS_ENABLED },
+    { id: "ime_mode_active_email",
+      description: "input[type=email][style=\"ime-mode: active;\"]",
+      expectedEnabled: gUtils.IME_STATUS_ENABLED,
+      focusable: !aInDesignMode,
+      changeOpened: true, expectedOpened: true },
+    { id: "ime_mode_inactive_email",
+      description: "input[type=email][style=\"ime-mode: inactive;\"]",
+      expectedEnabled: gUtils.IME_STATUS_ENABLED,
+      focusable: !aInDesignMode,
+      changeOpened: true, expectedOpened: false },
+    { id: "ime_mode_disabled_email",
+      description: "input[type=email][style=\"ime-mode: disabled;\"]",
+      focusable: !aInDesignMode,
+      expectedEnabled: kEnabledStateOnPasswordField },
+
+    { id: "ime_mode_auto_search",
+      description: "input[type=search][style=\"ime-mode: auto;\"]",
+      focusable: !aInDesignMode,
+      expectedEnabled: gUtils.IME_STATUS_ENABLED },
+    { id: "ime_mode_normal_search",
+      description: "input[type=search][style=\"ime-mode: normal;\"]",
+      focusable: !aInDesignMode,
+      expectedEnabled: gUtils.IME_STATUS_ENABLED },
+    { id: "ime_mode_active_search",
+      description: "input[type=search][style=\"ime-mode: active;\"]",
+      expectedEnabled: gUtils.IME_STATUS_ENABLED,
+      focusable: !aInDesignMode,
+      changeOpened: true, expectedOpened: true },
+    { id: "ime_mode_inactive_search",
+      description: "input[type=search][style=\"ime-mode: inactive;\"]",
+      expectedEnabled: gUtils.IME_STATUS_ENABLED,
+      focusable: !aInDesignMode,
+      changeOpened: true, expectedOpened: false },
+    { id: "ime_mode_disabled_search",
+      description: "input[type=search][style=\"ime-mode: disabled;\"]",
+      focusable: !aInDesignMode,
+      expectedEnabled: kEnabledStateOnPasswordField },
+
+    { id: "ime_mode_auto_tel",
+      description: "input[type=tel][style=\"ime-mode: auto;\"]",
+      focusable: !aInDesignMode,
+      expectedEnabled: gUtils.IME_STATUS_ENABLED },
+    { id: "ime_mode_normal_tel",
+      description: "input[type=tel][style=\"ime-mode: normal;\"]",
+      focusable: !aInDesignMode,
+      expectedEnabled: gUtils.IME_STATUS_ENABLED },
+    { id: "ime_mode_active_tel",
+      description: "input[type=tel][style=\"ime-mode: active;\"]",
+      expectedEnabled: gUtils.IME_STATUS_ENABLED,
+      focusable: !aInDesignMode,
+      changeOpened: true, expectedOpened: true },
+    { id: "ime_mode_inactive_tel",
+      description: "input[type=tel][style=\"ime-mode: inactive;\"]",
+      expectedEnabled: gUtils.IME_STATUS_ENABLED,
+      focusable: !aInDesignMode,
+      changeOpened: true, expectedOpened: false },
+    { id: "ime_mode_disabled_tel",
+      description: "input[type=tel][style=\"ime-mode: disabled;\"]",
+      focusable: !aInDesignMode,
+      expectedEnabled: kEnabledStateOnPasswordField },
+
+    { id: "ime_mode_auto_number",
+      description: "input[type=number][style=\"ime-mode: auto;\"]",
+      focusable: !aInDesignMode,
+      expectedEnabled: gUtils.IME_STATUS_ENABLED },
+    { id: "ime_mode_normal_number",
+      description: "input[type=number][style=\"ime-mode: normal;\"]",
+      focusable: !aInDesignMode,
+      expectedEnabled: gUtils.IME_STATUS_ENABLED },
+    { id: "ime_mode_active_number",
+      description: "input[type=number][style=\"ime-mode: active;\"]",
+      expectedEnabled: gUtils.IME_STATUS_ENABLED,
+      focusable: !aInDesignMode,
+      changeOpened: true, expectedOpened: true },
+    { id: "ime_mode_inactive_number",
+      description: "input[type=number][style=\"ime-mode: inactive;\"]",
+      expectedEnabled: gUtils.IME_STATUS_ENABLED,
+      focusable: !aInDesignMode,
+      changeOpened: true, expectedOpened: false },
+    { id: "ime_mode_disabled_number",
+      description: "input[type=number][style=\"ime-mode: disabled;\"]",
+      focusable: !aInDesignMode,
+      expectedEnabled: kEnabledStateOnPasswordField },
+
     { id: "ime_mode_auto_p",
       description: "input[type=password][style=\"ime-mode: auto;\"]",
       focusable: !aInDesignMode,
       expectedEnabled: kEnabledStateOnPasswordField },
     { id: "ime_mode_normal_p",
       description: "input[type=password][style=\"ime-mode: normal;\"]",
       focusable: !aInDesignMode,
       expectedEnabled: gUtils.IME_STATUS_ENABLED },
@@ -419,31 +614,127 @@ function runTypeChangingTest()
       type: "file",     expected: gUtils.IME_STATUS_DISABLED,
       description: "[type=\"file\"]" },
     { id: "ibutton",
       type: "button",   expected: gUtils.IME_STATUS_DISABLED,
       description: "[type=\"button\"]" },
     { id: "image",
       type: "image",    expected: gUtils.IME_STATUS_DISABLED,
       description: "[type=\"image\"]" },
+    { id: "url",
+      type: "url",     expected: gUtils.IME_STATUS_ENABLED,
+      description: "[type=\"url\"]" },
+    { id: "email",
+      type: "email",     expected: gUtils.IME_STATUS_ENABLED,
+      description: "[type=\"email\"]" },
+    { id: "search",
+      type: "search",     expected: gUtils.IME_STATUS_ENABLED,
+      description: "[type=\"search\"]" },
+    { id: "tel",
+      type: "tel",     expected: gUtils.IME_STATUS_ENABLED,
+      description: "[type=\"tel\"]" },
+    { id: "number",
+      type: "number",     expected: gUtils.IME_STATUS_ENABLED,
+      description: "[type=\"number\"]" },
     { id: "ime_mode_auto",
       type: "text",     expected: gUtils.IME_STATUS_ENABLED,  imeMode:  true,
       description: "[type=\"text\"][ime-mode: auto;]" },
     { id: "ime_mode_normal",
       type: "text",     expected: gUtils.IME_STATUS_ENABLED,  imeMode:  true,
       description: "[type=\"text\"][ime-mode: normal;]" },
     { id: "ime_mode_active",
       type: "text",     expected: gUtils.IME_STATUS_ENABLED,  imeMode:  true,
       description: "[type=\"text\"][ime-mode: active;]" },
     { id: "ime_mode_inactive",
       type: "text",     expected: gUtils.IME_STATUS_ENABLED,  imeMode:  true,
       description: "[type=\"text\"][ime-mode: inactive;]" },
     { id: "ime_mode_disabled",
       type: "text",     expected: gUtils.IME_STATUS_PASSWORD, imeMode:  true,
       description: "[type=\"text\"][ime-mode: disabled;]" },
+
+    { id: "ime_mode_auto_url",
+      type: "url",     expected: gUtils.IME_STATUS_ENABLED,  imeMode:  true,
+      description: "[type=\"url\"][ime-mode: auto;]" },
+    { id: "ime_mode_normal_url",
+      type: "url",     expected: gUtils.IME_STATUS_ENABLED,  imeMode:  true,
+      description: "[type=\"url\"][ime-mode: normal;]" },
+    { id: "ime_mode_active_url",
+      type: "url",     expected: gUtils.IME_STATUS_ENABLED,  imeMode:  true,
+      description: "[type=\"url\"][ime-mode: active;]" },
+    { id: "ime_mode_inactive_url",
+      type: "url",     expected: gUtils.IME_STATUS_ENABLED,  imeMode:  true,
+      description: "[type=\"url\"][ime-mode: inactive;]" },
+    { id: "ime_mode_disabled_url",
+      type: "url",     expected: gUtils.IME_STATUS_PASSWORD, imeMode:  true,
+      description: "[type=\"url\"][ime-mode: disabled;]" },
+
+    { id: "ime_mode_auto_email",
+      type: "email",     expected: gUtils.IME_STATUS_ENABLED,  imeMode:  true,
+      description: "[type=\"email\"][ime-mode: auto;]" },
+    { id: "ime_mode_normal_email",
+      type: "email",     expected: gUtils.IME_STATUS_ENABLED,  imeMode:  true,
+      description: "[type=\"email\"][ime-mode: normal;]" },
+    { id: "ime_mode_active_email",
+      type: "email",     expected: gUtils.IME_STATUS_ENABLED,  imeMode:  true,
+      description: "[type=\"email\"][ime-mode: active;]" },
+    { id: "ime_mode_inactive_email",
+      type: "email",     expected: gUtils.IME_STATUS_ENABLED,  imeMode:  true,
+      description: "[type=\"email\"][ime-mode: inactive;]" },
+    { id: "ime_mode_disabled_email",
+      type: "email",     expected: gUtils.IME_STATUS_PASSWORD, imeMode:  true,
+      description: "[type=\"email\"][ime-mode: disabled;]" },
+
+    { id: "ime_mode_auto_search",
+      type: "search",     expected: gUtils.IME_STATUS_ENABLED,  imeMode:  true,
+      description: "[type=\"search\"][ime-mode: auto;]" },
+    { id: "ime_mode_normal_search",
+      type: "search",     expected: gUtils.IME_STATUS_ENABLED,  imeMode:  true,
+      description: "[type=\"search\"][ime-mode: normal;]" },
+    { id: "ime_mode_active_search",
+      type: "search",     expected: gUtils.IME_STATUS_ENABLED,  imeMode:  true,
+      description: "[type=\"search\"][ime-mode: active;]" },
+    { id: "ime_mode_inactive_search",
+      type: "search",     expected: gUtils.IME_STATUS_ENABLED,  imeMode:  true,
+      description: "[type=\"search\"][ime-mode: inactive;]" },
+    { id: "ime_mode_disabled_search",
+      type: "search",     expected: gUtils.IME_STATUS_PASSWORD, imeMode:  true,
+      description: "[type=\"search\"][ime-mode: disabled;]" },
+
+    { id: "ime_mode_auto_tel",
+      type: "tel",     expected: gUtils.IME_STATUS_ENABLED,  imeMode:  true,
+      description: "[type=\"tel\"][ime-mode: auto;]" },
+    { id: "ime_mode_normal_tel",
+      type: "tel",     expected: gUtils.IME_STATUS_ENABLED,  imeMode:  true,
+      description: "[type=\"tel\"][ime-mode: normal;]" },
+    { id: "ime_mode_active_tel",
+      type: "tel",     expected: gUtils.IME_STATUS_ENABLED,  imeMode:  true,
+      description: "[type=\"tel\"][ime-mode: active;]" },
+    { id: "ime_mode_inactive_tel",
+      type: "tel",     expected: gUtils.IME_STATUS_ENABLED,  imeMode:  true,
+      description: "[type=\"tel\"][ime-mode: inactive;]" },
+    { id: "ime_mode_disabled_tel",
+      type: "tel",     expected: gUtils.IME_STATUS_PASSWORD, imeMode:  true,
+      description: "[type=\"tel\"][ime-mode: disabled;]" },
+
+    { id: "ime_mode_auto_number",
+      type: "number",     expected: gUtils.IME_STATUS_ENABLED,  imeMode:  true,
+      description: "[type=\"number\"][ime-mode: auto;]" },
+    { id: "ime_mode_normal_number",
+      type: "number",     expected: gUtils.IME_STATUS_ENABLED,  imeMode:  true,
+      description: "[type=\"number\"][ime-mode: normal;]" },
+    { id: "ime_mode_active_number",
+      type: "number",     expected: gUtils.IME_STATUS_ENABLED,  imeMode:  true,
+      description: "[type=\"number\"][ime-mode: active;]" },
+    { id: "ime_mode_inactive_number",
+      type: "number",     expected: gUtils.IME_STATUS_ENABLED,  imeMode:  true,
+      description: "[type=\"number\"][ime-mode: inactive;]" },
+    { id: "ime_mode_disabled_number",
+      type: "number",     expected: gUtils.IME_STATUS_PASSWORD, imeMode:  true,
+      description: "[type=\"number\"][ime-mode: disabled;]" },
+
     { id: "ime_mode_auto_p",
       type: "password", expected: gUtils.IME_STATUS_PASSWORD,  imeMode:  true,
       description: "[type=\"password\"][ime-mode: auto;]" },
     { id: "ime_mode_normal_p",
       type: "password", expected: gUtils.IME_STATUS_ENABLED,  imeMode:  true,
       description: "[type=\"password\"][ime-mode: normal;]" },
     { id: "ime_mode_active_p",
       type: "password", expected: gUtils.IME_STATUS_ENABLED,  imeMode:  true,
@@ -461,17 +752,22 @@ function runTypeChangingTest()
     { type: "text",     expected: gUtils.IME_STATUS_ENABLED  },
     { type: "password", expected: gUtils.IME_STATUS_PASSWORD },
     { type: "checkbox", expected: gUtils.IME_STATUS_DISABLED },
     { type: "radio",    expected: gUtils.IME_STATUS_DISABLED },
     { type: "submit",   expected: gUtils.IME_STATUS_DISABLED },
     { type: "reset",    expected: gUtils.IME_STATUS_DISABLED },
     { type: "file",     expected: gUtils.IME_STATUS_DISABLED },
     { type: "button",   expected: gUtils.IME_STATUS_DISABLED },
-    { type: "image",    expected: gUtils.IME_STATUS_DISABLED }
+    { type: "image",    expected: gUtils.IME_STATUS_DISABLED },
+    { type: "url",      expected: gUtils.IME_STATUS_ENABLED  },
+    { type: "email",    expected: gUtils.IME_STATUS_ENABLED  },
+    { type: "search",   expected: gUtils.IME_STATUS_ENABLED  },
+    { type: "tel",      expected: gUtils.IME_STATUS_ENABLED  },
+    { type: "number",   expected: gUtils.IME_STATUS_ENABLED  }
   ];
 
   function getExpectedIMEEnabled(aNewType, aInputControl)
   {
     if (aNewType.expected == gUtils.IME_STATUS_DISABLED ||
         aInputControl.isReadonly)
       return gUtils.IME_STATUS_DISABLED;
     return aInputControl.imeMode ? aInputControl.expected : aNewType.expected;
@@ -486,17 +782,20 @@ function runTypeChangingTest()
       var e = document.getElementById(kInput.id);
       e.focus();
       for (var k = 0; k < kInputTypes.length; k++) {
         const kType = kInputTypes[k];
         var typeChangingDescription =
           "\"" + e.getAttribute("type") + "\" to \"" + kInput.type + "\"";
         e.setAttribute("type", kInput.type);
         is(gUtils.IMEStatus, kInput.expected,
-           "type attr changing test: " + typeChangingDescription +
+           "type attr changing test (IMEStatus): " + typeChangingDescription +
+             " (" +  kInput.description + ")");
+        is(gUtils2.focusedInputType, kInput.type,
+           "type attr changing test (type): " + typeChangingDescription +
              " (" +  kInput.description + ")");
 
         const kTestOpenState = kIMEOpenSupported &&
                 gUtils.IMEStatus == gUtils.IME_STATUS_ENABLED &&
                 getExpectedIMEEnabled(kType, kInput) == gUtils.IME_STATUS_ENABLED;
         if (kTestOpenState) {
           gUtils.IMEIsOpen = kOpened;
         }
@@ -504,17 +803,20 @@ function runTypeChangingTest()
         typeChangingDescription =
           "\"" + e.getAttribute("type") + "\" to \"" + kType.type + "\"";
         if (kType.type != "")
           e.setAttribute("type", kType.type);
         else
           e.removeAttribute("type");
 
         is(gUtils.IMEStatus, getExpectedIMEEnabled(kType, kInput),
-           "type attr changing test: " + typeChangingDescription +
+           "type attr changing test (IMEStatus): " + typeChangingDescription +
+             " (" +  kInput.description + ")");
+        is(gUtils2.focusedInputType, kType.type,
+           "type attr changing test (type): " + typeChangingDescription +
              " (" +  kInput.description + ")");
         if (kTestOpenState && gUtils.IMEStatus == gUtils.IME_STATUS_ENABLED) {
           is(gUtils.IMEIsOpen, kOpened,
              "type attr changing test (open state is changed): " +
                typeChangingDescription + " (" +  kInput.description + ")");
         }
       }
       // reset the type to default
@@ -530,16 +832,26 @@ function runReadonlyChangingTest()
   if (!kIMEEnabledSupported)
     return;
 
   const kInputControls = [
     { id: "text",
       type: "text",     expected: gUtils.IME_STATUS_ENABLED  },
     { id: "password",
       type: "password", expected: gUtils.IME_STATUS_PASSWORD },
+    { id: "url",
+      type: "url",      expected: gUtils.IME_STATUS_ENABLED  },
+    { id: "email",
+      type: "email",    expected: gUtils.IME_STATUS_ENABLED  },
+    { id: "search",
+      type: "search",   expected: gUtils.IME_STATUS_ENABLED  },
+    { id: "tel",
+      type: "tel",      expected: gUtils.IME_STATUS_ENABLED  },
+    { id: "number",
+      type: "number",   expected: gUtils.IME_STATUS_ENABLED  },
     { id: "textarea",
       type: "textarea", expected: gUtils.IME_STATUS_ENABLED  }
   ];
   const kOpenedState = [ true, false ];
 
   for (var i = 0; i < kOpenedState.length; i++) {
     const kOpened = kOpenedState[i];
     for (var j = 0; j < kInputControls.length; j++) {