diff --git a/dom/events/EventListenerManager.cpp b/dom/events/EventListenerManager.cpp index 46880ad1975..3c573c05e6c 100644 --- a/dom/events/EventListenerManager.cpp +++ b/dom/events/EventListenerManager.cpp @@ -101,8 +101,6 @@ EventListenerManager::EventListenerManager(EventTarget* aTarget) , mMayHaveScrollWheelEventListener(false) , mMayHaveMouseEnterLeaveEventListener(false) , mMayHavePointerEnterLeaveEventListener(false) - , mMayHaveKeyEventListener(false) - , mMayHaveInputOrCompositionEventListener(false) , mClearingListeners(false) , mIsMainThreadELM(NS_IsMainThread()) , mNoListenerForEvent(0) @@ -388,21 +386,7 @@ EventListenerManager::AddEventListenerInternal( window->SetHasGamepadEventListener(); } #endif - } else if (aTypeAtom == nsGkAtoms::onkeydown || - aTypeAtom == nsGkAtoms::onkeypress || - aTypeAtom == nsGkAtoms::onkeyup) { - if (!aFlags.mInSystemGroup) { - mMayHaveKeyEventListener = true; - } - } else if (aTypeAtom == nsGkAtoms::oncompositionend || - aTypeAtom == nsGkAtoms::oncompositionstart || - aTypeAtom == nsGkAtoms::oncompositionupdate || - aTypeAtom == nsGkAtoms::oninput) { - if (!aFlags.mInSystemGroup) { - mMayHaveInputOrCompositionEventListener = true; - } } - if (aTypeAtom && mTarget) { mTarget->EventListenerAdded(aTypeAtom); } diff --git a/dom/events/EventListenerManager.h b/dom/events/EventListenerManager.h index 898b1dd6e49..dadceb110ea 100644 --- a/dom/events/EventListenerManager.h +++ b/dom/events/EventListenerManager.h @@ -403,19 +403,6 @@ public: bool MayHaveMouseEnterLeaveEventListener() { return mMayHaveMouseEnterLeaveEventListener; } bool MayHavePointerEnterLeaveEventListener() { return mMayHavePointerEnterLeaveEventListener; } - /** - * Returns true if there may be a key event listener (keydown, keypress, - * or keyup) registered, or false if there definitely isn't. - */ - bool MayHaveKeyEventListener() { return mMayHaveKeyEventListener; } - - /** - * Returns true if there may be an advanced input event listener (input, - * compositionstart, compositionupdate, or compositionend) registered, - * or false if there definitely isn't. - */ - bool MayHaveInputOrCompositionEventListener() { return mMayHaveInputOrCompositionEventListener; } - size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const; uint32_t ListenerCount() const @@ -566,11 +553,9 @@ protected: uint32_t mMayHaveScrollWheelEventListener : 1; uint32_t mMayHaveMouseEnterLeaveEventListener : 1; uint32_t mMayHavePointerEnterLeaveEventListener : 1; - uint32_t mMayHaveKeyEventListener : 1; - uint32_t mMayHaveInputOrCompositionEventListener : 1; uint32_t mClearingListeners : 1; uint32_t mIsMainThreadELM : 1; - uint32_t mNoListenerForEvent : 20; + uint32_t mNoListenerForEvent : 23; nsAutoTObserverArray mListeners; dom::EventTarget* mTarget; // WEAK diff --git a/dom/events/IMEStateManager.cpp b/dom/events/IMEStateManager.cpp index f60043e4ee8..9915d801732 100644 --- a/dom/events/IMEStateManager.cpp +++ b/dom/events/IMEStateManager.cpp @@ -9,7 +9,6 @@ #include "mozilla/IMEStateManager.h" #include "mozilla/Attributes.h" -#include "mozilla/EventListenerManager.h" #include "mozilla/EventStates.h" #include "mozilla/MouseEvents.h" #include "mozilla/Preferences.h" @@ -183,7 +182,6 @@ 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. @@ -199,10 +197,6 @@ IMEStateManager::Init() sISMLog = PR_NewLogModule("IMEStateManager"); } #endif - Preferences::AddBoolVarCache( - &sCheckForIMEUnawareWebApps, - "intl.ime.hack.on_ime_unaware_apps.fire_key_events_for_composition", - false); } // static @@ -775,25 +769,6 @@ 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, @@ -816,9 +791,6 @@ IMEStateManager::SetIMEState(const IMEState& aState, 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)) { diff --git a/dom/events/IMEStateManager.h b/dom/events/IMEStateManager.h index c16d71f55d6..01ad078ac38 100644 --- a/dom/events/IMEStateManager.h +++ b/dom/events/IMEStateManager.h @@ -164,7 +164,6 @@ protected: static bool sInstalledMenuKeyboardListener; static bool sIsTestingIME; static bool sIsGettingNewIMEState; - static bool sCheckForIMEUnawareWebApps; class MOZ_STACK_CLASS GettingNewIMEStateBlocker MOZ_FINAL { diff --git a/mobile/android/base/GeckoEvent.java b/mobile/android/base/GeckoEvent.java index 4352144e61c..146f4494527 100644 --- a/mobile/android/base/GeckoEvent.java +++ b/mobile/android/base/GeckoEvent.java @@ -263,9 +263,9 @@ public class GeckoEvent { return GeckoEvent.get(NativeGeckoEvent.NOOP); } - public static GeckoEvent createKeyEvent(KeyEvent k, int action, int metaState) { + public static GeckoEvent createKeyEvent(KeyEvent k, int metaState) { GeckoEvent event = GeckoEvent.get(NativeGeckoEvent.KEY_EVENT); - event.initKeyEvent(k, action, metaState); + event.initKeyEvent(k, metaState); return event; } @@ -284,11 +284,8 @@ public class GeckoEvent { return GeckoEvent.get(NativeGeckoEvent.COMPOSITOR_RESUME); } - private void initKeyEvent(KeyEvent k, int action, int metaState) { - // Use a separate action argument so we can override the key's original action, - // e.g. change ACTION_MULTIPLE to ACTION_DOWN. That way we don't have to allocate - // a new key event just to change its action field. - mAction = action; + private void initKeyEvent(KeyEvent k, int metaState) { + mAction = k.getAction(); mTime = k.getEventTime(); // Normally we expect k.getMetaState() to reflect the current meta-state; however, // some software-generated key events may not have k.getMetaState() set, e.g. key @@ -623,7 +620,7 @@ public class GeckoEvent { public static GeckoEvent createIMEKeyEvent(KeyEvent k) { GeckoEvent event = GeckoEvent.get(NativeGeckoEvent.IME_KEY_EVENT); - event.initKeyEvent(k, k.getAction(), 0); + event.initKeyEvent(k, 0); return event; } diff --git a/mobile/android/base/GeckoInputConnection.java b/mobile/android/base/GeckoInputConnection.java index 9499bd3a107..691bcc24f3d 100644 --- a/mobile/android/base/GeckoInputConnection.java +++ b/mobile/android/base/GeckoInputConnection.java @@ -590,6 +590,8 @@ class GeckoInputConnection outAttrs.inputType |= InputType.TYPE_TEXT_VARIATION_URI; else if (mIMETypeHint.equalsIgnoreCase("email")) outAttrs.inputType |= InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS; + else if (mIMETypeHint.equalsIgnoreCase("search")) + outAttrs.imeOptions = EditorInfo.IME_ACTION_SEARCH; else if (mIMETypeHint.equalsIgnoreCase("tel")) outAttrs.inputType = InputType.TYPE_CLASS_PHONE; else if (mIMETypeHint.equalsIgnoreCase("number") || @@ -634,8 +636,7 @@ class GeckoInputConnection outAttrs.imeOptions = EditorInfo.IME_ACTION_DONE; else if (mIMEActionHint.equalsIgnoreCase("next")) outAttrs.imeOptions = EditorInfo.IME_ACTION_NEXT; - else if (mIMEActionHint.equalsIgnoreCase("search") || - mIMETypeHint.equalsIgnoreCase("search")) + else if (mIMEActionHint.equalsIgnoreCase("search")) outAttrs.imeOptions = EditorInfo.IME_ACTION_SEARCH; else if (mIMEActionHint.equalsIgnoreCase("send")) outAttrs.imeOptions = EditorInfo.IME_ACTION_SEND; @@ -815,14 +816,13 @@ class GeckoInputConnection !shouldProcessKey(keyCode, event)) { return false; } - final int action = down ? KeyEvent.ACTION_DOWN : KeyEvent.ACTION_UP; event = translateKey(keyCode, event); keyCode = event.getKeyCode(); View view = getView(); if (view == null) { InputThreadUtils.sInstance.sendEventFromUiThread(ThreadUtils.getUiHandler(), - mEditableClient, GeckoEvent.createKeyEvent(event, action, 0)); + mEditableClient, GeckoEvent.createKeyEvent(event, 0)); return true; } @@ -840,7 +840,7 @@ class GeckoInputConnection (down && !keyListener.onKeyDown(view, uiEditable, keyCode, event)) || (!down && !keyListener.onKeyUp(view, uiEditable, keyCode, event))) { InputThreadUtils.sInstance.sendEventFromUiThread(uiHandler, mEditableClient, - GeckoEvent.createKeyEvent(event, action, TextKeyListener.getMetaState(uiEditable))); + GeckoEvent.createKeyEvent(event, TextKeyListener.getMetaState(uiEditable))); if (skip && down) { // Usually, the down key listener call above adjusts meta states for us. // However, if we skip that call above, we have to manually adjust meta @@ -864,43 +864,27 @@ class GeckoInputConnection return processKey(keyCode, event, false); } - /** - * Get a key that represents a given character. - */ - private KeyEvent getCharKeyEvent(final char c) { - final long time = SystemClock.uptimeMillis(); - return new KeyEvent(time, time, KeyEvent.ACTION_MULTIPLE, - KeyEvent.KEYCODE_UNKNOWN, /* repeat */ 0) { - @Override - public int getUnicodeChar() { - return c; - } - - @Override - public int getUnicodeChar(int metaState) { - return c; - } - }; - } - @Override public boolean onKeyMultiple(int keyCode, int repeatCount, final KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_UNKNOWN) { // KEYCODE_UNKNOWN means the characters are in KeyEvent.getCharacters() - final String str = event.getCharacters(); - for (int i = 0; i < str.length(); i++) { - final KeyEvent charEvent = getCharKeyEvent(str.charAt(i)); - if (!processKey(KeyEvent.KEYCODE_UNKNOWN, charEvent, /* down */ true) || - !processKey(KeyEvent.KEYCODE_UNKNOWN, charEvent, /* down */ false)) { - return false; - } + View view = getView(); + if (view != null) { + InputThreadUtils.sInstance.runOnIcThread( + view.getRootView().getHandler(), mEditableClient, + new Runnable() { + @Override public void run() { + // Don't call GeckoInputConnection.commitText because it can + // post a key event back to onKeyMultiple, causing a loop + GeckoInputConnection.super.commitText(event.getCharacters(), 1); + } + }); } return true; } - while ((repeatCount--) != 0) { - if (!processKey(keyCode, event, /* down */ true) || - !processKey(keyCode, event, /* down */ false)) { + if (!processKey(keyCode, event, true) || + !processKey(keyCode, event, false)) { return false; } } diff --git a/modules/libpref/init/all.js b/modules/libpref/init/all.js index ed6e9b3dd0f..67a8515b198 100644 --- a/modules/libpref/init/all.js +++ b/modules/libpref/init/all.js @@ -1710,13 +1710,6 @@ pref("intl.locale.matchOS", false); 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"); diff --git a/widget/android/nsWindow.cpp b/widget/android/nsWindow.cpp index b774d1ea6fe..1479a8de20f 100644 --- a/widget/android/nsWindow.cpp +++ b/widget/android/nsWindow.cpp @@ -2124,6 +2124,8 @@ nsWindow::SetInputContext(const InputContext& aContext, aContext.mIMEState.mEnabled, aContext.mIMEState.mOpen, aAction.mCause, aAction.mFocusChange); + mInputContext = aContext; + // Ensure that opening the virtual keyboard is allowed for this specific // InputContext depending on the content.ime.strict.policy pref if (aContext.mIMEState.mEnabled != IMEState::DISABLED && @@ -2141,19 +2143,8 @@ nsWindow::SetInputContext(const InputContext& aContext, if (aContext.mIMEState.mEnabled == IMEState::PLUGIN && aContext.mIMEState.mOpen != IMEState::OPEN) { enabled = IMEState::DISABLED; - - } else if (aContext.mMayBeIMEUnaware) { - // Normal text editing using Android virtual keyboards doesn't always - // generate key events. However, when an input field has key event - // listeners but not input/composition event listeners, the page expects - // to receive key events for every input. Therefore, for better web - // compatibility, we use a special mode that always generates key events - // in this situation. This "key-events-only" mode is the same as the - // "plugin" mode, so switch to plugin mode if we are forcing key events. - enabled = IMEState::PLUGIN; } - mInputContext = aContext; mInputContext.mIMEState.mEnabled = enabled; if (enabled == IMEState::ENABLED && aAction.UserMightRequestOpenVKB()) { diff --git a/widget/nsIWidget.h b/widget/nsIWidget.h index 27205f24542..e79759ddd23 100644 --- a/widget/nsIWidget.h +++ b/widget/nsIWidget.h @@ -410,7 +410,6 @@ struct IMEState { struct InputContext { InputContext() : mNativeIMEContext(nullptr) - , mMayBeIMEUnaware(false) , mOrigin(XRE_IsParentProcess() ? ORIGIN_MAIN : ORIGIN_CONTENT) {} @@ -435,11 +434,6 @@ struct InputContext { 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; - /** * mOrigin indicates whether this focus event refers to main or remote content. */