Bug 1112212 - Implement key-events-only mode for Android; r=cpeterson
--- a/mobile/android/base/GeckoInputConnection.java
+++ b/mobile/android/base/GeckoInputConnection.java
@@ -585,18 +585,16 @@ class GeckoInputConnection
"password".equalsIgnoreCase(mIMETypeHint))
outAttrs.inputType |= InputType.TYPE_TEXT_VARIATION_PASSWORD;
else if (mIMEState == IME_STATE_PLUGIN)
outAttrs.inputType = InputType.TYPE_NULL; // "send key events" mode
else if (mIMETypeHint.equalsIgnoreCase("url"))
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") ||
mIMETypeHint.equalsIgnoreCase("range"))
outAttrs.inputType = InputType.TYPE_CLASS_NUMBER
| InputType.TYPE_NUMBER_FLAG_SIGNED
| InputType.TYPE_NUMBER_FLAG_DECIMAL;
else if (mIMETypeHint.equalsIgnoreCase("week") ||
@@ -631,17 +629,18 @@ class GeckoInputConnection
}
if (mIMEActionHint.equalsIgnoreCase("go"))
outAttrs.imeOptions = EditorInfo.IME_ACTION_GO;
else if (mIMEActionHint.equalsIgnoreCase("done"))
outAttrs.imeOptions = EditorInfo.IME_ACTION_DONE;
else if (mIMEActionHint.equalsIgnoreCase("next"))
outAttrs.imeOptions = EditorInfo.IME_ACTION_NEXT;
- else if (mIMEActionHint.equalsIgnoreCase("search"))
+ else if (mIMEActionHint.equalsIgnoreCase("search") ||
+ mIMETypeHint.equalsIgnoreCase("search"))
outAttrs.imeOptions = EditorInfo.IME_ACTION_SEARCH;
else if (mIMEActionHint.equalsIgnoreCase("send"))
outAttrs.imeOptions = EditorInfo.IME_ACTION_SEND;
else if (mIMEActionHint.length() > 0) {
if (DEBUG)
Log.w(LOGTAG, "Unexpected mIMEActionHint=\"" + mIMEActionHint + "\"");
outAttrs.actionLabel = mIMEActionHint;
}
--- a/widget/android/nsWindow.cpp
+++ b/widget/android/nsWindow.cpp
@@ -2119,18 +2119,16 @@ nsWindow::SetInputContext(const InputCon
top->mFocus->SetInputContext(aContext, aAction);
return;
}
ALOGIME("IME: SetInputContext: s=0x%X, 0x%X, action=0x%X, 0x%X",
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 &&
aContext.mIMEState.mEnabled != IMEState::PLUGIN &&
Preferences::GetBool("content.ime.strict_policy", false) &&
!aAction.ContentGotFocusByTrustedCause() &&
!aAction.UserMightRequestOpenVKB()) {
return;
@@ -2138,18 +2136,29 @@ nsWindow::SetInputContext(const InputCon
IMEState::Enabled enabled = aContext.mIMEState.mEnabled;
// Only show the virtual keyboard for plugins if mOpen is set appropriately.
// This avoids showing it whenever a plugin is focused. Bug 747492
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()) {
// Don't reset keyboard when we should simply open the vkb
GeckoAppShell::NotifyIME(AndroidBridge::NOTIFY_IME_OPEN_VKB);
return;
}