bug 1112212 - Set flag in InputContext for IME-unaware webapps; r=masayuki
authorJim Chen <nchen@mozilla.com>
Sat, 10 Jan 2015 12:41:57 -0500
changeset 223187 00c219a74edefbeb1b9187aab91a3927ec4e119c
parent 223186 d3e8e73bafdebd002ffc69a9684c93ac3718ecbe
child 223188 779b73087f78ad76aba77dd3d01a5f0a20f2c261
push id10769
push usercbook@mozilla.com
push dateMon, 12 Jan 2015 14:15:52 +0000
treeherderfx-team@0e9765732906 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmasayuki
bugs1112212
milestone37.0a1
bug 1112212 - Set flag in InputContext for IME-unaware webapps; r=masayuki
dom/events/IMEStateManager.cpp
dom/events/IMEStateManager.h
modules/libpref/init/all.js
widget/nsIWidget.h
--- a/dom/events/IMEStateManager.cpp
+++ b/dom/events/IMEStateManager.cpp
@@ -4,16 +4,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "prlog.h"
 
 #include "mozilla/IMEStateManager.h"
 
 #include "mozilla/Attributes.h"
+#include "mozilla/EventListenerManager.h"
 #include "mozilla/EventStates.h"
 #include "mozilla/MouseEvents.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/Services.h"
 #include "mozilla/TextComposition.h"
 #include "mozilla/TextEvents.h"
 #include "mozilla/dom/HTMLFormElement.h"
 
@@ -176,31 +177,36 @@ GetNotifyIMEMessageName(IMEMessage aMess
 }
 #endif // #ifdef PR_LOGGING
 
 nsIContent* IMEStateManager::sContent = nullptr;
 nsPresContext* IMEStateManager::sPresContext = nullptr;
 bool IMEStateManager::sInstalledMenuKeyboardListener = false;
 bool IMEStateManager::sIsTestingIME = false;
 bool IMEStateManager::sIsGettingNewIMEState = false;
+bool IMEStateManager::sCheckForIMEUnawareWebApps = false;
 
 // sActiveIMEContentObserver points to the currently active IMEContentObserver.
 // sActiveIMEContentObserver is null if there is no focused editor.
 IMEContentObserver* IMEStateManager::sActiveIMEContentObserver = nullptr;
 TextCompositionArray* IMEStateManager::sTextCompositions = nullptr;
 
 // static
 void
 IMEStateManager::Init()
 {
 #ifdef PR_LOGGING
   if (!sISMLog) {
     sISMLog = PR_NewLogModule("IMEStateManager");
   }
 #endif
+  Preferences::AddBoolVarCache(
+    &sCheckForIMEUnawareWebApps,
+    "intl.ime.hack.on_ime_unaware_apps.fire_key_events_for_composition",
+    false);
 }
 
 // static
 void
 IMEStateManager::Shutdown()
 {
   PR_LOG(sISMLog, PR_LOG_ALWAYS,
     ("ISM: IMEStateManager::Shutdown(), "
@@ -742,16 +748,35 @@ public:
     }
     return NS_OK;
   }
 
 private:
   uint32_t mState;
 };
 
+static bool
+MayBeIMEUnawareWebApp(nsINode* aNode)
+{
+  bool haveKeyEventsListener = false;
+
+  while (aNode) {
+    EventListenerManager* const mgr = aNode->GetExistingListenerManager();
+    if (mgr) {
+      if (mgr->MayHaveInputOrCompositionEventListener()) {
+        return false;
+      }
+      haveKeyEventsListener |= mgr->MayHaveKeyEventListener();
+    }
+    aNode = aNode->GetParentNode();
+  }
+
+  return haveKeyEventsListener;
+}
+
 // static
 void
 IMEStateManager::SetIMEState(const IMEState& aState,
                              nsIContent* aContent,
                              nsIWidget* aWidget,
                              InputContextAction aAction)
 {
   PR_LOG(sISMLog, PR_LOG_ALWAYS,
@@ -764,16 +789,19 @@ IMEStateManager::SetIMEState(const IMESt
 
   NS_ENSURE_TRUE_VOID(aWidget);
 
   InputContext oldContext = aWidget->GetInputContext();
 
   InputContext context;
   context.mIMEState = aState;
 
+  context.mMayBeIMEUnaware = context.mIMEState.IsEditable() &&
+    sCheckForIMEUnawareWebApps && MayBeIMEUnawareWebApp(aContent);
+
   if (aContent && aContent->GetNameSpaceID() == kNameSpaceID_XHTML &&
       (aContent->Tag() == nsGkAtoms::input ||
        aContent->Tag() == nsGkAtoms::textarea)) {
     if (aContent->Tag() != nsGkAtoms::textarea) {
       // <input type=number> has an anonymous <input type=text> descendant
       // that gets focus whenever anyone tries to focus the number control. We
       // need to check if aContent is one of those anonymous text controls and,
       // if so, use the number control instead:
--- a/dom/events/IMEStateManager.h
+++ b/dom/events/IMEStateManager.h
@@ -159,16 +159,17 @@ protected:
 
   static bool IsEditableIMEState(nsIWidget* aWidget);
 
   static nsIContent*    sContent;
   static nsPresContext* sPresContext;
   static bool           sInstalledMenuKeyboardListener;
   static bool           sIsTestingIME;
   static bool           sIsGettingNewIMEState;
+  static bool           sCheckForIMEUnawareWebApps;
 
   class MOZ_STACK_CLASS GettingNewIMEStateBlocker MOZ_FINAL
   {
   public:
     GettingNewIMEStateBlocker()
       : mOldValue(IMEStateManager::sIsGettingNewIMEState)
     {
       IMEStateManager::sIsGettingNewIMEState = true;
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -1703,16 +1703,23 @@ pref("intl.charset.fallback.tld",       
 pref("intl.ellipsis",                       "chrome://global-platform/locale/intl.properties");
 pref("intl.locale.matchOS",                 false);
 // fallback charset list for Unicode conversion (converting from Unicode)
 // currently used for mail send only to handle symbol characters (e.g Euro, trademark, smartquotes)
 // for ISO-8859-1
 pref("intl.fallbackCharsetList.ISO-8859-1", "windows-1252");
 pref("font.language.group",                 "chrome://global/locale/intl.properties");
 
+// Android-specific pref to use key-events-only mode for IME-unaware webapps.
+#ifdef MOZ_WIDGET_ANDROID
+pref("intl.ime.hack.on_ime_unaware_apps.fire_key_events_for_composition", true);
+#else
+pref("intl.ime.hack.on_ime_unaware_apps.fire_key_events_for_composition", false);
+#endif
+
 // these locales have right-to-left UI
 pref("intl.uidirection.ar", "rtl");
 pref("intl.uidirection.he", "rtl");
 pref("intl.uidirection.fa", "rtl");
 pref("intl.uidirection.ug", "rtl");
 pref("intl.uidirection.ur", "rtl");
 
 // use en-US hyphenation by default for content tagged with plain lang="en"
--- a/widget/nsIWidget.h
+++ b/widget/nsIWidget.h
@@ -402,17 +402,20 @@ struct IMEState {
   // has focus.
   bool MaybeEditable() const
   {
     return IsEditable() || mEnabled == PLUGIN;
   }
 };
 
 struct InputContext {
-  InputContext() : mNativeIMEContext(nullptr) {}
+  InputContext()
+    : mNativeIMEContext(nullptr)
+    , mMayBeIMEUnaware(false)
+  {}
 
   bool IsPasswordEditor() const
   {
     return mHTMLInputType.LowerCaseEqualsLiteral("password");
   }
 
   IMEState mIMEState;
 
@@ -424,16 +427,21 @@ struct InputContext {
 
   /* A hint for the action that is performed when the input is submitted */
   nsString mActionHint;
 
   /* Native IME context for the widget.  This doesn't come from the argument of
      SetInputContext().  If there is only one context in the process, this may
      be nullptr. */
   void* mNativeIMEContext;
+
+  /* True if the webapp may be unaware of IME events such as input event or
+   * composiion events. This enables a key-events-only mode on Android for
+   * compatibility with webapps relying on key listeners. */
+  bool mMayBeIMEUnaware;
 };
 
 struct InputContextAction {
   /**
    * mCause indicates what action causes calling nsIWidget::SetInputContext().
    * It must be one of following values.
    */
   enum Cause {