Bug 685395 part.5 Reomve IME state in nsIContent r=roc, sr=matspal
authorMasayuki Nakano <masayuki@d-toybox.com>
Sun, 27 Nov 2011 20:51:53 +0900
changeset 80856 98c4d6ce4b9eb22340405fc8eb7b5a9131635dba
parent 80855 029a09f71d7936e96ab6f018355f79949434dcbb
child 80857 00bb426f75ef3023e26322be3dedb3abe6432872
push id21536
push usermak77@bonardo.net
push dateMon, 28 Nov 2011 13:11:29 +0000
treeherdermozilla-central@accfde65e3c7 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersroc, matspal
bugs685395
milestone11.0a1
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 685395 part.5 Reomve IME state in nsIContent r=roc, sr=matspal
content/base/public/nsIContent.h
content/base/src/nsGenericElement.cpp
content/events/src/nsIMEStateManager.cpp
content/events/src/nsIMEStateManager.h
content/html/content/src/nsGenericHTMLElement.cpp
content/html/content/src/nsGenericHTMLElement.h
content/html/content/src/nsHTMLObjectElement.cpp
content/html/content/src/nsHTMLSharedObjectElement.cpp
editor/idl/nsIEditorIMESupport.idl
editor/libeditor/base/nsEditor.cpp
editor/libeditor/base/nsEditor.h
editor/libeditor/html/nsHTMLEditor.cpp
editor/libeditor/html/nsHTMLEditor.h
widget/public/nsIWidget.h
--- a/content/base/public/nsIContent.h
+++ b/content/base/public/nsIContent.h
@@ -58,37 +58,42 @@ class nsTextFragment;
 class nsIDocShell;
 class nsIFrame;
 class nsISMILAttr;
 class nsIDOMCSSStyleDeclaration;
 
 namespace mozilla {
 namespace css {
 class StyleRule;
-}
-}
+} // namespace css
+namespace widget {
+struct IMEState;
+} // namespace widget
+} // namespace mozilla
 
 enum nsLinkState {
   eLinkState_Unknown    = 0,
   eLinkState_Unvisited  = 1,
   eLinkState_Visited    = 2,
   eLinkState_NotLink    = 3
 };
 
 // IID for the nsIContent interface
 #define NS_ICONTENT_IID \
-{ 0x3128b3a0, 0xb609, 0x44e3, \
-  { 0xad, 0x91, 0xdc, 0xf1, 0x4a, 0x3f, 0xf6, 0xa0 } }
+{ 0xed40a3e5, 0xd7ed, 0x473e, \
+ { 0x85, 0xe3, 0x82, 0xc3, 0xf0, 0x41, 0xdb, 0x52 } }
 
 /**
  * A node of content in a document's content model. This interface
  * is supported by all content objects.
  */
 class nsIContent : public nsINode {
 public:
+  typedef mozilla::widget::IMEState IMEState;
+
 #ifdef MOZILLA_INTERNAL_API
   // If you're using the external API, the only thing you can know about
   // nsIContent is that it exists with an IID
 
   nsIContent(already_AddRefed<nsINodeInfo> aNodeInfo)
     : nsINode(aNodeInfo),
       mPrimaryFrame(nsnull)
   {
@@ -599,50 +604,28 @@ public:
                                 bool aIsTrustedEvent)
   {
   }
 
   /*
    * Get desired IME state for the content.
    *
    * @return The desired IME status for the content.
-   *         This is a combination of IME_STATUS_* flags,
-   *         controlling what happens to IME when the content takes focus.
-   *         If this is IME_STATUS_NONE, IME remains in its current state.
-   *         IME_STATUS_ENABLE and IME_STATUS_DISABLE must not be set
-   *         together; likewise IME_STATUS_OPEN and IME_STATUS_CLOSE must
-   *         not be set together.
-   *         If you return IME_STATUS_DISABLE, you should not set the
-   *         OPEN or CLOSE flag; that way, when IME is next enabled,
-   *         the previous OPEN/CLOSE state will be restored (unless the newly
-   *         focused content specifies the OPEN/CLOSE state by setting the OPEN
-   *         or CLOSE flag with the ENABLE flag).
-   *         IME_STATUS_PASSWORD should be returned only from password editor,
-   *         this value has a special meaning. It is used as alternative of
-   *         IME_STATUS_DISABLED.
-   *         IME_STATUS_PLUGIN should be returned only when plug-in has focus.
-   *         When a plug-in is focused content, we should send native events
-   *         directly. Because we don't process some native events, but they may
-   *         be needed by the plug-in.
+   *         This is a combination of an IME enabled value and
+   *         an IME open value of widget::IMEState.
+   *         If you return DISABLED, you should not set the OPEN and CLOSE
+   *         value.
+   *         PASSWORD should be returned only from password editor, this value
+   *         has a special meaning. It is used as alternative of DISABLED.
+   *         PLUGIN should be returned only when plug-in has focus.  When a
+   *         plug-in is focused content, we should send native events directly.
+   *         Because we don't process some native events, but they may be needed
+   *         by the plug-in.
    */
-  enum {
-    IME_STATUS_NONE     = 0x0000,
-    IME_STATUS_ENABLE   = 0x0001,
-    IME_STATUS_DISABLE  = 0x0002,
-    IME_STATUS_PASSWORD = 0x0004,
-    IME_STATUS_PLUGIN   = 0x0008,
-    IME_STATUS_OPEN     = 0x0010,
-    IME_STATUS_CLOSE    = 0x0020
-  };
-  enum {
-    IME_STATUS_MASK_ENABLED = IME_STATUS_ENABLE | IME_STATUS_DISABLE |
-                              IME_STATUS_PASSWORD | IME_STATUS_PLUGIN,
-    IME_STATUS_MASK_OPENED  = IME_STATUS_OPEN | IME_STATUS_CLOSE
-  };
-  virtual PRUint32 GetDesiredIMEState();
+  virtual IMEState GetDesiredIMEState();
 
   /**
    * Gets content node with the binding (or native code, possibly on the
    * frame) responsible for our construction (and existence).  Used by
    * anonymous content (both XBL-generated and native-anonymous).
    *
    * null for all explicit content (i.e., content reachable from the top
    * of its GetParent() chain via child lists).
--- a/content/base/src/nsGenericElement.cpp
+++ b/content/base/src/nsGenericElement.cpp
@@ -104,16 +104,17 @@
 #include "nsGkAtoms.h"
 #include "nsContentUtils.h"
 #include "nsIJSContextStack.h"
 
 #include "nsIServiceManager.h"
 #include "nsIDOMEventListener.h"
 #include "nsIWebNavigation.h"
 #include "nsIBaseWindow.h"
+#include "nsIWidget.h"
 
 #include "jsapi.h"
 
 #include "nsNodeInfoManager.h"
 #include "nsICategoryManager.h"
 #include "nsIDOMDocumentType.h"
 #include "nsIDOMUserDataHandler.h"
 #include "nsGenericHTMLElement.h"
@@ -1358,53 +1359,50 @@ nsIContent::GetFlattenedTreeParent() con
       doc->BindingManager()->GetNestedInsertionPoint(parent, this);
     if (insertionElement) {
       parent = insertionElement;
     }
   }
   return parent;
 }
 
-PRUint32
+nsIContent::IMEState
 nsIContent::GetDesiredIMEState()
 {
   if (!IsEditableInternal()) {
-    return IME_STATUS_DISABLE;
+    return IMEState(IMEState::DISABLED);
   }
   // NOTE: The content for independent editors (e.g., input[type=text],
   // textarea) must override this method, so, we don't need to worry about
   // that here.
   nsIContent *editableAncestor = GetEditingHost();
 
   // This is in another editable content, use the result of it.
   if (editableAncestor && editableAncestor != this) {
     return editableAncestor->GetDesiredIMEState();
   }
   nsIDocument* doc = GetCurrentDoc();
   if (!doc) {
-    return IME_STATUS_DISABLE;
+    return IMEState(IMEState::DISABLED);
   }
   nsIPresShell* ps = doc->GetShell();
   if (!ps) {
-    return IME_STATUS_DISABLE;
+    return IMEState(IMEState::DISABLED);
   }
   nsPresContext* pc = ps->GetPresContext();
   if (!pc) {
-    return IME_STATUS_DISABLE;
+    return IMEState(IMEState::DISABLED);
   }
   nsIEditor* editor = GetHTMLEditor(pc);
   nsCOMPtr<nsIEditorIMESupport> imeEditor = do_QueryInterface(editor);
   if (!imeEditor) {
-    return IME_STATUS_DISABLE;
-  }
-  // Use "enable" for the default value because IME is disabled unexpectedly,
-  // it makes serious a11y problem.
-  PRUint32 state = IME_STATUS_ENABLE;
-  nsresult rv = imeEditor->GetPreferredIMEState(&state);
-  NS_ENSURE_SUCCESS(rv, IME_STATUS_ENABLE);
+    return IMEState(IMEState::DISABLED);
+  }
+  IMEState state;
+  imeEditor->GetPreferredIMEState(&state);
   return state;
 }
 
 bool
 nsIContent::HasIndependentSelection()
 {
   nsIFrame* frame = GetPrimaryFrame();
   return (frame && frame->GetStateBits() & NS_FRAME_INDEPENDENT_SELECTION);
--- a/content/events/src/nsIMEStateManager.cpp
+++ b/content/events/src/nsIMEStateManager.cpp
@@ -64,36 +64,16 @@
 #include "nsIObserverService.h"
 #include "mozilla/Services.h"
 #include "nsIFormControl.h"
 #include "nsIForm.h"
 #include "nsHTMLFormElement.h"
 
 using namespace mozilla::widget;
 
-static
-/* static */
-IMEState::Enabled
-GetWidgetStatusFromIMEStatus(PRUint32 aState)
-{
-  switch (aState & nsIContent::IME_STATUS_MASK_ENABLED) {
-    case nsIContent::IME_STATUS_DISABLE:
-      return IMEState::DISABLED;
-    case nsIContent::IME_STATUS_ENABLE:
-      return IMEState::ENABLED;
-    case nsIContent::IME_STATUS_PASSWORD:
-      return IMEState::PASSWORD;
-    case nsIContent::IME_STATUS_PLUGIN:
-      return IMEState::PLUGIN;
-    default:
-      NS_ERROR("The given state doesn't have valid enable state");
-      return IMEState::ENABLED;
-  }
-}
-
 /******************************************************************/
 /* nsIMEStateManager                                              */
 /******************************************************************/
 
 nsIContent*    nsIMEStateManager::sContent      = nsnull;
 nsPresContext* nsIMEStateManager::sPresContext  = nsnull;
 bool           nsIMEStateManager::sInstalledMenuKeyboardListener = false;
 bool           nsIMEStateManager::sInSecureInputMode = false;
@@ -103,17 +83,17 @@ nsTextStateManager* nsIMEStateManager::s
 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);
+    IMEState newState = GetNewIMEState(sPresContext, nsnull);
     InputContextAction action(InputContextAction::CAUSE_UNKNOWN,
                               InputContextAction::LOST_FOCUS);
     SetIMEState(newState, nsnull, widget, action);
   }
   sContent = nsnull;
   sPresContext = nsnull;
   OnTextStateBlur(nsnull, nsnull);
   return NS_OK;
@@ -130,17 +110,17 @@ nsIMEStateManager::OnRemoveContent(nsPre
     return NS_OK;
 
   // 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);
+    IMEState newState = GetNewIMEState(sPresContext, nsnull);
     InputContextAction action(InputContextAction::CAUSE_UNKNOWN,
                               InputContextAction::LOST_FOCUS);
     SetIMEState(newState, nsnull, widget, action);
   }
 
   sContent = nsnull;
   sPresContext = nsnull;
 
@@ -186,55 +166,47 @@ nsIMEStateManager::OnChangeFocusInternal
   } else {
     if (contentIsPassword) {
       if (NS_SUCCEEDED(widget->BeginSecureKeyboardInput())) {
         sInSecureInputMode = true;
       }
     }
   }
 
-  PRUint32 newState = GetNewIMEState(aPresContext, aContent);
+  IMEState newState = GetNewIMEState(aPresContext, aContent);
   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;
-    }
     InputContext context = widget->GetInputContext();
-    if (context.mIMEState.mEnabled ==
-          GetWidgetStatusFromIMEStatus(newEnabledState)) {
+    if (context.mIMEState.mEnabled == newState.mEnabled) {
       // the enabled state isn't changing.
       return NS_OK;
     }
     aAction.mFocusChange = InputContextAction::FOCUS_NOT_CHANGED;
   } else if (aAction.mFocusChange == InputContextAction::FOCUS_NOT_CHANGED) {
     // If aContent isn't null or aContent is null but editable, somebody gets
     // focus.
-    bool gotFocus = aContent || (newState & nsIContent::IME_STATUS_ENABLE);
+    bool gotFocus = aContent || (newState.mEnabled == IMEState::ENABLED);
     aAction.mFocusChange =
       gotFocus ? InputContextAction::GOT_FOCUS : InputContextAction::LOST_FOCUS;
   }
 
   // Current IME transaction should commit
   if (sPresContext) {
     nsCOMPtr<nsIWidget> oldWidget;
     if (sPresContext == aPresContext)
       oldWidget = widget;
     else
       oldWidget = GetWidget(sPresContext);
     if (oldWidget)
       oldWidget->ResetInputState();
   }
 
-  if (newState != nsIContent::IME_STATUS_NONE) {
-    // Update IME state for new focus widget
-    SetIMEState(newState, aContent, widget, aAction);
-  }
+  // Update IME state for new focus widget
+  SetIMEState(newState, aContent, widget, aAction);
 
   sPresContext = aPresContext;
   sContent = aContent;
 
   return NS_OK;
 }
 
 void
@@ -244,65 +216,65 @@ nsIMEStateManager::OnInstalledMenuKeyboa
 
   InputContextAction action(InputContextAction::CAUSE_UNKNOWN,
     aInstalling ? InputContextAction::MENU_GOT_PSEUDO_FOCUS :
                   InputContextAction::MENU_LOST_PSEUDO_FOCUS);
   OnChangeFocusInternal(sPresContext, sContent, action);
 }
 
 void
-nsIMEStateManager::UpdateIMEState(PRUint32 aNewIMEState, nsIContent* aContent)
+nsIMEStateManager::UpdateIMEState(const IMEState &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) {
     NS_WARNING("focused widget is not found");
     return;
   }
 
   // Don't update IME state when enabled state isn't actually changed.
   InputContext context = widget->GetInputContext();
-  PRUint32 newEnabledState = aNewIMEState & nsIContent::IME_STATUS_MASK_ENABLED;
-  if (context.mIMEState.mEnabled ==
-        GetWidgetStatusFromIMEStatus(newEnabledState)) {
+  if (context.mIMEState.mEnabled == aNewIMEState.mEnabled) {
     return;
   }
 
   // commit current composition
   widget->ResetInputState();
 
   InputContextAction action(InputContextAction::CAUSE_UNKNOWN,
                             InputContextAction::FOCUS_NOT_CHANGED);
   SetIMEState(aNewIMEState, aContent, widget, action);
 }
 
-PRUint32
+IMEState
 nsIMEStateManager::GetNewIMEState(nsPresContext* aPresContext,
                                   nsIContent*    aContent)
 {
   // On Printing or Print Preview, we don't need IME.
   if (aPresContext->Type() == nsPresContext::eContext_PrintPreview ||
       aPresContext->Type() == nsPresContext::eContext_Print) {
-    return nsIContent::IME_STATUS_DISABLE;
+    return IMEState(IMEState::DISABLED);
   }
 
-  if (sInstalledMenuKeyboardListener)
-    return nsIContent::IME_STATUS_DISABLE;
+  if (sInstalledMenuKeyboardListener) {
+    return IMEState(IMEState::DISABLED);
+  }
 
   if (!aContent) {
     // Even if there are no focused content, the focused document might be
     // editable, such case is design mode.
     nsIDocument* doc = aPresContext->Document();
-    if (doc && doc->HasFlag(NODE_IS_EDITABLE))
-      return nsIContent::IME_STATUS_ENABLE;
-    return nsIContent::IME_STATUS_DISABLE;
+    if (doc && doc->HasFlag(NODE_IS_EDITABLE)) {
+      return IMEState(IMEState::ENABLED);
+    }
+    return IMEState(IMEState::DISABLED);
   }
 
   return aContent->GetDesiredIMEState();
 }
 
 // Helper class, used for IME enabled state change notification
 class IMEEnabledStateChangedEvent : public nsRunnable {
 public:
@@ -321,25 +293,27 @@ public:
     return NS_OK;
   }
 
 private:
   PRUint32 mState;
 };
 
 void
-nsIMEStateManager::SetIMEState(PRUint32 aState,
+nsIMEStateManager::SetIMEState(const IMEState &aState,
                                nsIContent* aContent,
                                nsIWidget* aWidget,
                                InputContextAction aAction)
 {
   NS_ENSURE_TRUE(aWidget, );
 
+  InputContext oldContext = aWidget->GetInputContext();
+
   InputContext context;
-  context.mIMEState.mEnabled = GetWidgetStatusFromIMEStatus(aState);
+  context.mIMEState = aState;
 
   if (aContent && aContent->GetNameSpaceID() == kNameSpaceID_XHTML &&
       (aContent->Tag() == nsGkAtoms::input ||
        aContent->Tag() == nsGkAtoms::textarea)) {
     aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::type,
                       context.mHTMLInputType);
     aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::moz_action_hint,
                       context.mActionHint);
@@ -371,23 +345,18 @@ nsIMEStateManager::SetIMEState(PRUint32 
 
   // XXX I think that we should use nsContentUtils::IsCallerChrome() instead
   //     of the process type.
   if (aAction.mCause == InputContextAction::CAUSE_UNKNOWN &&
       XRE_GetProcessType() != GeckoProcessType_Content) {
     aAction.mCause = InputContextAction::CAUSE_UNKNOWN_CHROME;
   }
 
-  if (aState & nsIContent::IME_STATUS_MASK_OPENED) {
-    bool open = !!(aState & nsIContent::IME_STATUS_OPEN);
-    context.mIMEState.mOpen = open ? IMEState::OPEN : IMEState::CLOSED;
-  }
-
   aWidget->SetInputContext(context, aAction);
-  if (aState & nsIContent::IME_STATUS_MASK_ENABLED) {
+  if (oldContext.mIMEState.mEnabled != context.mIMEState.mEnabled) {
     nsContentUtils::AddScriptRunner(
       new IMEEnabledStateChangedEvent(context.mIMEState.mEnabled));
   }
 }
 
 nsIWidget*
 nsIMEStateManager::GetWidget(nsPresContext* aPresContext)
 {
--- a/content/events/src/nsIMEStateManager.h
+++ b/content/events/src/nsIMEStateManager.h
@@ -90,28 +90,28 @@ public:
                                    nsIContent* aContent);
   // Get the focused editor's selection and root
   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, nsIContent* aContent);
+  static void UpdateIMEState(const IMEState &aNewIMEState,
+                             nsIContent* aContent);
 
 protected:
   static nsresult OnChangeFocusInternal(nsPresContext* aPresContext,
                                         nsIContent* aContent,
                                         InputContextAction aAction);
-  static void SetIMEState(PRUint32 aState, nsIContent* aContent,
+  static void SetIMEState(const IMEState &aState,
+                          nsIContent* aContent,
                           nsIWidget* aWidget,
                           InputContextAction aAction);
-  static PRUint32 GetNewIMEState(nsPresContext* aPresContext,
+  static IMEState GetNewIMEState(nsPresContext* aPresContext,
                                  nsIContent* aContent);
 
   static nsIWidget* GetWidget(nsPresContext* aPresContext);
 
   static nsIContent*    sContent;
   static nsPresContext* sPresContext;
   static bool           sInstalledMenuKeyboardListener;
   static bool           sInSecureInputMode;
--- a/content/html/content/src/nsGenericHTMLElement.cpp
+++ b/content/html/content/src/nsGenericHTMLElement.cpp
@@ -66,16 +66,17 @@
 #include "nsIStyleRule.h"
 #include "nsIURL.h"
 #include "nsNetUtil.h"
 #include "nsEscape.h"
 #include "nsIFrame.h"
 #include "nsIScrollableFrame.h"
 #include "nsIView.h"
 #include "nsIViewManager.h"
+#include "nsIWidget.h"
 #include "nsRange.h"
 #include "nsIPresShell.h"
 #include "nsPresContext.h"
 #include "nsIDocShell.h"
 #include "nsIDocShellTreeItem.h"
 #include "nsINameSpaceManager.h"
 #include "nsDOMError.h"
 #include "nsScriptLoader.h"
@@ -2647,27 +2648,27 @@ nsGenericHTMLFormElement::GetFormElement
 nsresult
 nsGenericHTMLFormElement::GetForm(nsIDOMHTMLFormElement** aForm)
 {
   NS_ENSURE_ARG_POINTER(aForm);
   NS_IF_ADDREF(*aForm = mForm);
   return NS_OK;
 }
 
-PRUint32
+nsIContent::IMEState
 nsGenericHTMLFormElement::GetDesiredIMEState()
 {
   nsCOMPtr<nsIEditor> editor = nsnull;
   nsresult rv = GetEditorInternal(getter_AddRefs(editor));
   if (NS_FAILED(rv) || !editor)
     return nsGenericHTMLElement::GetDesiredIMEState();
   nsCOMPtr<nsIEditorIMESupport> imeEditor = do_QueryInterface(editor);
   if (!imeEditor)
     return nsGenericHTMLElement::GetDesiredIMEState();
-  PRUint32 state;
+  IMEState state;
   rv = imeEditor->GetPreferredIMEState(&state);
   if (NS_FAILED(rv))
     return nsGenericHTMLElement::GetDesiredIMEState();
   return state;
 }
 
 bool
 nsGenericHTMLFrameElement::IsHTMLFocusable(bool aWithMouse,
--- a/content/html/content/src/nsGenericHTMLElement.h
+++ b/content/html/content/src/nsGenericHTMLElement.h
@@ -879,17 +879,17 @@ public:
   }
 
   // nsIContent
   virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
                               nsIContent* aBindingParent,
                               bool aCompileEventHandlers);
   virtual void UnbindFromTree(bool aDeep = true,
                               bool aNullParent = true);
-  virtual PRUint32 GetDesiredIMEState();
+  virtual IMEState GetDesiredIMEState();
   virtual nsEventStates IntrinsicState() const;
 
   virtual nsresult PreHandleEvent(nsEventChainPreVisitor& aVisitor);
 
   virtual bool IsDisabled() const;
 
   /**
    * This callback is called by a fieldest on all its elements whenever its
--- a/content/html/content/src/nsHTMLObjectElement.cpp
+++ b/content/html/content/src/nsHTMLObjectElement.cpp
@@ -47,16 +47,17 @@
 #include "nsIDOMDocument.h"
 #include "nsIDOMSVGDocument.h"
 #include "nsIDOMGetSVGDocument.h"
 #include "nsIDOMHTMLObjectElement.h"
 #include "nsFormSubmission.h"
 #include "nsIObjectFrame.h"
 #include "nsNPAPIPluginInstance.h"
 #include "nsIConstraintValidation.h"
+#include "nsIWidget.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 class nsHTMLObjectElement : public nsGenericHTMLFormElement
                           , public nsObjectLoadingContent
                           , public nsIDOMHTMLObjectElement
                           , public nsIConstraintValidation
@@ -111,17 +112,17 @@ public:
                               bool aNullParent = true);
   virtual nsresult SetAttr(PRInt32 aNameSpaceID, nsIAtom *aName,
                            nsIAtom *aPrefix, const nsAString &aValue,
                            bool aNotify);
   virtual nsresult UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aAttribute,
                              bool aNotify);
 
   virtual bool IsHTMLFocusable(bool aWithMouse, bool *aIsFocusable, PRInt32 *aTabIndex);
-  virtual PRUint32 GetDesiredIMEState();
+  virtual IMEState GetDesiredIMEState();
 
   // Overriden nsIFormControl methods
   NS_IMETHOD_(PRUint32) GetType() const
   {
     return NS_FORM_OBJECT;
   }
 
   NS_IMETHOD Reset();
@@ -371,21 +372,21 @@ nsHTMLObjectElement::IsHTMLFocusable(boo
 
   if (aTabIndex && *aIsFocusable) {
     *aTabIndex = attrVal->GetIntegerValue();
   }
 
   return false;
 }
 
-PRUint32
+nsIContent::IMEState
 nsHTMLObjectElement::GetDesiredIMEState()
 {
   if (Type() == eType_Plugin) {
-    return nsIContent::IME_STATUS_PLUGIN;
+    return IMEState(IMEState::PLUGIN);
   }
    
   return nsGenericHTMLFormElement::GetDesiredIMEState();
 }
 
 NS_IMETHODIMP
 nsHTMLObjectElement::Reset()
 {
--- a/content/html/content/src/nsHTMLSharedObjectElement.cpp
+++ b/content/html/content/src/nsHTMLSharedObjectElement.cpp
@@ -45,16 +45,17 @@
 #include "nsIDocument.h"
 #include "nsIDOMDocument.h"
 #include "nsIDOMHTMLAppletElement.h"
 #include "nsIDOMHTMLEmbedElement.h"
 #include "nsThreadUtils.h"
 #include "nsIDOMGetSVGDocument.h"
 #include "nsIDOMSVGDocument.h"
 #include "nsIScriptError.h"
+#include "nsIWidget.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 class nsHTMLSharedObjectElement : public nsGenericHTMLElement
                                 , public nsObjectLoadingContent
                                 , public nsIDOMHTMLAppletElement
                                 , public nsIDOMHTMLEmbedElement
@@ -114,17 +115,17 @@ public:
                               bool aCompileEventHandlers);
   virtual void UnbindFromTree(bool aDeep = true,
                               bool aNullParent = true);
   virtual nsresult SetAttr(PRInt32 aNameSpaceID, nsIAtom *aName,
                            nsIAtom *aPrefix, const nsAString &aValue,
                            bool aNotify);
 
   virtual bool IsHTMLFocusable(bool aWithMouse, bool *aIsFocusable, PRInt32 *aTabIndex);
-  virtual PRUint32 GetDesiredIMEState();
+  virtual IMEState GetDesiredIMEState();
 
   virtual void DoneAddingChildren(bool aHaveNotified);
   virtual bool IsDoneAddingChildren();
 
   virtual bool ParseAttribute(PRInt32 aNamespaceID,
                                 nsIAtom *aAttribute,
                                 const nsAString &aValue,
                                 nsAttrValue &aResult);
@@ -360,21 +361,21 @@ nsHTMLSharedObjectElement::IsHTMLFocusab
 
     // Let the plugin decide, so override.
     return true;
   }
 
   return nsGenericHTMLElement::IsHTMLFocusable(aWithMouse, aIsFocusable, aTabIndex);
 }
 
-PRUint32
+nsIContent::IMEState
 nsHTMLSharedObjectElement::GetDesiredIMEState()
 {
   if (Type() == eType_Plugin) {
-    return nsIContent::IME_STATUS_PLUGIN;
+    return IMEState(IMEState::PLUGIN);
   }
    
   return nsGenericHTMLElement::GetDesiredIMEState();
 }
 
 NS_IMPL_STRING_ATTR(nsHTMLSharedObjectElement, Align, align)
 NS_IMPL_STRING_ATTR(nsHTMLSharedObjectElement, Alt, alt)
 NS_IMPL_STRING_ATTR(nsHTMLSharedObjectElement, Archive, archive)
--- a/editor/idl/nsIEditorIMESupport.idl
+++ b/editor/idl/nsIEditorIMESupport.idl
@@ -34,30 +34,40 @@
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsISupports.idl"
 #include "domstubs.idl"
 
-[scriptable, uuid(a64744c5-d3ff-46ba-b9b1-57f79ff7d97d)]
+%{C++
+namespace mozilla {
+namespace widget {
+struct IMEState;
+} // namespace widget
+} // namespace mozilla
+%}
+
+native IMEState(mozilla::widget::IMEState);
+
+[scriptable, uuid(0ba7f490-afb8-46dd-87fc-bc6137fbc899)]
 
 interface nsIEditorIMESupport : nsISupports
 {
   /**
    * forceCompositionEnd() force the composition end
    */
 
   void forceCompositionEnd();
 
   /**
    * Get preferred IME status of current widget.
    */
 
-  [noscript] void getPreferredIMEState(out unsigned long aState);
+  [noscript] IMEState getPreferredIMEState();
 
   /**
    * whether this editor has active IME transaction
    */
   readonly attribute boolean composing;
 };
 
--- a/editor/libeditor/base/nsEditor.cpp
+++ b/editor/libeditor/base/nsEditor.cpp
@@ -128,16 +128,17 @@
 static bool gNoisy = false;
 #endif
 
 #ifdef DEBUG
 #include "nsIDOMHTMLDocument.h"
 #endif
 
 using namespace mozilla;
+using namespace mozilla::widget;
 
 // Defined in nsEditorRegistration.cpp
 extern nsIParserService *sParserService;
 
 //---------------------------------------------------------------------------
 //
 // nsEditor: base editor class implementation
 //
@@ -487,19 +488,17 @@ nsEditor::SetFlags(PRUint32 aFlags)
     nsresult rv = SyncRealTimeSpell();
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   // Might be changing editable state, so, we need to reset current IME state
   // if we're focused and the flag change causes IME state change.
   nsCOMPtr<nsIContent> focusedContent = GetFocusedContent();
   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;
+    IMEState newState;
     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, focusedContent);
     }
   }
 
@@ -2045,46 +2044,47 @@ nsEditor::ForceCompositionEnd()
     res = widget->ResetInputState();
     NS_ENSURE_SUCCESS(res, res);
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsEditor::GetPreferredIMEState(PRUint32 *aState)
+nsEditor::GetPreferredIMEState(IMEState *aState)
 {
   NS_ENSURE_ARG_POINTER(aState);
-  *aState = nsIContent::IME_STATUS_ENABLE;
+  aState->mEnabled = IMEState::ENABLED;
+  aState->mOpen = IMEState::DONT_CHANGE_OPEN_STATE;
 
   if (IsReadonly() || IsDisabled()) {
-    *aState = nsIContent::IME_STATUS_DISABLE;
+    aState->mEnabled = IMEState::DISABLED;
     return NS_OK;
   }
 
   nsCOMPtr<nsIContent> content = do_QueryInterface(GetRoot());
   NS_ENSURE_TRUE(content, NS_ERROR_FAILURE);
 
   nsIFrame* frame = content->GetPrimaryFrame();
   NS_ENSURE_TRUE(frame, NS_ERROR_FAILURE);
 
   switch (frame->GetStyleUIReset()->mIMEMode) {
     case NS_STYLE_IME_MODE_AUTO:
       if (IsPasswordEditor())
-        *aState = nsIContent::IME_STATUS_PASSWORD;
+        aState->mEnabled = IMEState::PASSWORD;
       break;
     case NS_STYLE_IME_MODE_DISABLED:
       // we should use password state for |ime-mode: disabled;|.
-      *aState = nsIContent::IME_STATUS_PASSWORD;
+      aState->mEnabled = IMEState::PASSWORD;
       break;
     case NS_STYLE_IME_MODE_ACTIVE:
-      *aState |= nsIContent::IME_STATUS_OPEN;
+      aState->mOpen = IMEState::OPEN;
       break;
     case NS_STYLE_IME_MODE_INACTIVE:
-      *aState |= nsIContent::IME_STATUS_CLOSE;
+      aState->mOpen = IMEState::CLOSED;
       break;
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsEditor::GetComposing(bool* aResult)
--- a/editor/libeditor/base/nsEditor.h
+++ b/editor/libeditor/base/nsEditor.h
@@ -85,16 +85,22 @@ class AddStyleSheetTxn;
 class RemoveStyleSheetTxn;
 class nsIFile;
 class nsISelectionController;
 class nsIDOMEventTarget;
 class nsCSSStyleSheet;
 class nsKeyEvent;
 class nsIDOMNSEvent;
 
+namespace mozilla {
+namespace widget {
+struct IMEState;
+} // namespace widget
+} // namespace mozilla
+
 #define kMOZEditorBogusNodeAttrAtom nsEditProperty::mozEditorBogusNode
 #define kMOZEditorBogusNodeValue NS_LITERAL_STRING("TRUE")
 
 /** implementation of an editor object.  it will be the controller/focal point 
  *  for the main editor services. i.e. the GUIManager, publishing, transaction 
  *  manager, event interfaces. the idea for the event interfaces is to have them 
  *  delegate the actual commands to the editor independent of the XPFE implementation.
  */
--- a/editor/libeditor/html/nsHTMLEditor.cpp
+++ b/editor/libeditor/html/nsHTMLEditor.cpp
@@ -91,22 +91,24 @@
 // Transactionas
 #include "nsStyleSheetTxns.h"
 
 // Misc
 #include "TextEditorTest.h"
 #include "nsEditorUtils.h"
 #include "nsWSRunObject.h"
 #include "nsGkAtoms.h"
+#include "nsIWidget.h"
 
 #include "nsIFrame.h"
 #include "nsIParserService.h"
 #include "mozilla/dom/Element.h"
 
 using namespace mozilla;
+using namespace mozilla::widget;
 
 // Some utilities to handle annoying overloading of "A" tag for link and named anchor
 static char hrefText[] = "href";
 static char anchorTxt[] = "anchor";
 static char namedanchorText[] = "namedanchor";
 
 nsIRangeUtils* nsHTMLEditor::sRangeHelper;
 
@@ -6037,19 +6039,19 @@ nsHTMLEditor::IsAcceptableInputEvent(nsI
   // Finally, check whether we're actually focused or not.  When we're not
   // focused, we should ignore the dispatched event by script (or something)
   // because content editable element needs selection in itself for editing.
   // However, when we're not focused, it's not guaranteed.
   return IsActiveInDOMWindow();
 }
 
 NS_IMETHODIMP
-nsHTMLEditor::GetPreferredIMEState(PRUint32 *aState)
+nsHTMLEditor::GetPreferredIMEState(IMEState *aState)
 {
+  // HTML editor don't prefer the CSS ime-mode because IE didn't do so too.
+  aState->mOpen = IMEState::DONT_CHANGE_OPEN_STATE;
   if (IsReadonly() || IsDisabled()) {
-    *aState = nsIContent::IME_STATUS_DISABLE;
-    return NS_OK;
-  }
-
-  // HTML editor don't prefer the CSS ime-mode because IE didn't do so too.
-  *aState = nsIContent::IME_STATUS_ENABLE;
+    aState->mEnabled = IMEState::DISABLED;
+  } else {
+    aState->mEnabled = IMEState::ENABLED;
+  }
   return NS_OK;
 }
--- a/editor/libeditor/html/nsHTMLEditor.h
+++ b/editor/libeditor/html/nsHTMLEditor.h
@@ -79,16 +79,22 @@ class nsIDocumentEncoder;
 class nsIClipboard;
 class TypeInState;
 class nsIContentFilter;
 class nsIURL;
 class nsIRangeUtils;
 class nsILinkHandler;
 struct PropItem;
 
+namespace mozilla {
+namespace widget {
+struct IMEState;
+} // namespace widget
+} // namespace mozilla
+
 /**
  * The HTML editor implementation.<br>
  * Use to edit HTML document represented as a DOM tree. 
  */
 class nsHTMLEditor : public nsPlaintextEditor,
                      public nsIHTMLEditor,
                      public nsIHTMLObjectResizer,
                      public nsIHTMLAbsPosEditor,
@@ -156,17 +162,17 @@ public:
   virtual bool IsAcceptableInputEvent(nsIDOMEvent* aEvent);
 
   /* ------------ nsStubMutationObserver overrides --------- */
   NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED
   NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED
   NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED
 
   /* ------------ nsIEditorIMESupport overrides ------------ */
-  NS_IMETHOD GetPreferredIMEState(PRUint32 *aState);
+  NS_IMETHOD GetPreferredIMEState(mozilla::widget::IMEState *aState);
 
   /* ------------ nsIHTMLEditor methods -------------- */
 
   NS_DECL_NSIHTMLEDITOR
 
   /* ------------ nsIHTMLObjectResizer methods -------------- */
   /* -------- Implemented in nsHTMLObjectResizer.cpp -------- */
   NS_DECL_NSIHTMLOBJECTRESIZER
--- a/widget/public/nsIWidget.h
+++ b/widget/public/nsIWidget.h
@@ -300,16 +300,21 @@ struct IMEState {
      * this value, users should be able to open IME by theirselves.
      * Web contents can specify this value by |ime-mode: inactive;|.
      */
     CLOSED
   };
   Open mOpen;
 
   IMEState() : mEnabled(ENABLED), mOpen(DONT_CHANGE_OPEN_STATE) { }
+
+  IMEState(Enabled aEnabled, Open aOpen = DONT_CHANGE_OPEN_STATE) :
+    mEnabled(aEnabled), mOpen(aOpen)
+  {
+  }
 };
 
 struct InputContext {
   IMEState mIMEState;
 
   /* The type of the input if the input is a html input field */
   nsString mHTMLInputType;