Bug 1343451 - part 5: Make GeckoEditableSupport dispatch dummy eKeyDown and eKeyUp event during composition always r=jchen

On Android, GeckoEditableSupport has already dispatched eKeyDown event and
eKeyUp event even during composition.  I.e., the pref which will be enabled
by bug 354358 has already been set to true only on Android.

On the other hand, GeckoEditableSupport does not dispatch them if content
listens to "input", "compositionstart", "compositionupdate" or
"compositionend".  So, different from the other platforms, we need additional
pref to make the new behavior behind pref.

Therefore, this patch adds a new pref,
"intl.ime.hack.on_any_apps.fire_key_events_for_composition", to override
existing "intl.ime.hack.on_ime_unaware_apps.fire_key_events_for_composition"
pref.  And sets mKeyCode and mKeyNameIndex of the dummy KeyboardEvents to
NS_VK_PROCESSKEY and KEY_NAME_INDEX_Process.

MozReview-Commit-ID: Fuy0Ir2xiO5

--HG--
extra : rebase_source : c76b613ea186458ebdf0d67f4bc984e8ac5f1041
This commit is contained in:
Masayuki Nakano 2018-02-27 17:24:35 +09:00
parent 6857169b5e
commit fcb248a698
4 changed files with 59 additions and 22 deletions

View File

@ -37,7 +37,7 @@ public class testInputConnection extends JavascriptBridgeTest {
mActions.setPref("dom.select_events.enabled", true, /* flush */ false);
mActions.setPref("dom.select_events.textcontrols.enabled", true, /* flush */ false);
// Enable dummy key synthesis.
mActions.setPref("intl.ime.hack.on_ime_unaware_apps.fire_key_events_for_composition",
mActions.setPref("intl.ime.hack.on_any_apps.fire_key_events_for_composition",
true, /* flush */ false);
final String url = mStringHelper.ROBOCOP_INPUT_URL;
@ -212,18 +212,11 @@ public class testInputConnection extends JavascriptBridgeTest {
assertTextAndSelectionAt("Can commit non-key string", ic, "foof", 4);
getJS().syncCall("end_key_log");
if (mType.equals("designMode")) {
// designMode doesn't support dummy key synthesis.
fAssertEquals("Can synthesize keys",
"keydown:o,casm;keypress:o,casm;keyup:o,casm;", // O key
getKeyLog());
} else {
fAssertEquals("Can synthesize keys",
"keydown:Unidentified,casm;keyup:Unidentified,casm;" + // Dummy
"keydown:Process,casm;keyup:Process,casm;" + // Dummy
"keydown:o,casm;keypress:o,casm;keyup:o,casm;" + // O key
"keydown:Unidentified,casm;keyup:Unidentified,casm;", // Dummy
"keydown:Process,casm;keyup:Process,casm;", // Dummy
getKeyLog());
}
ic.deleteSurroundingText(4, 0);
assertTextAndSelectionAt("Can clear text", ic, "", 0);

View File

@ -2386,12 +2386,26 @@ pref("intl.regional_prefs.use_os_locales", 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.
// Android-specific pref to control if keydown and keyup events are fired even
// in during composition. Note that those prefs are ignored if
// "dom.keyboardevent.dispatch_during_composition" is false.
#ifdef MOZ_WIDGET_ANDROID
// If true, dispatch the keydown and keyup events on any web apps even during
// composition.
#ifdef EARLY_BETA_OR_EARLIER
pref("intl.ime.hack.on_any_apps.fire_key_events_for_composition", true);
#else // #ifdef EARLY_BETA_OR_EARLIER
pref("intl.ime.hack.on_any_apps.fire_key_events_for_composition", false);
#endif // #ifdef EARLY_BETA_OR_EARLIER #else
// If true and the above pref is false, dispatch the keydown and keyup events
// only on IME-unaware web apps. So, this supports web apps which listen to
// only keydown or keyup event to get a change to do something at every text
// input.
pref("intl.ime.hack.on_ime_unaware_apps.fire_key_events_for_composition", true);
#else
#else // #ifdef MOZ_WIDGET_ANDROID
pref("intl.ime.hack.on_any_apps.fire_key_events_for_composition", false);
pref("intl.ime.hack.on_ime_unaware_apps.fire_key_events_for_composition", false);
#endif
#endif // #ifdef MOZ_WIDGET_ANDROID #else
// If you use legacy Chinese IME which puts an ideographic space to composition
// string as placeholder, this pref might be useful. If this is true and when

View File

@ -13,6 +13,7 @@
#include "nsISelection.h"
#include "mozilla/IMEStateManager.h"
#include "mozilla/Preferences.h"
#include "mozilla/TextComposition.h"
#include "mozilla/TextEventDispatcherListener.h"
#include "mozilla/TextEvents.h"
@ -558,10 +559,26 @@ ConvertRectArrayToJavaRectFArray(const nsTArray<LayoutDeviceIntRect>& aRects,
namespace mozilla {
namespace widget {
bool GeckoEditableSupport::sDispatchKeyEventsInCompositionForAnyApps = false;
NS_IMPL_ISUPPORTS(GeckoEditableSupport,
TextEventDispatcherListener,
nsISupportsWeakReference)
void
GeckoEditableSupport::ObservePrefs()
{
static bool sIsObservingPref = false;
if (sIsObservingPref) {
return;
}
sIsObservingPref = true;
Preferences::AddBoolVarCache(
&sDispatchKeyEventsInCompositionForAnyApps,
"intl.ime.hack.on_any_apps.fire_key_events_for_composition",
false);
}
RefPtr<TextComposition>
GeckoEditableSupport::GetComposition() const
{
@ -668,7 +685,6 @@ GeckoEditableSupport::OnKeyEvent(int32_t aAction, int32_t aKeyCode,
/*
* Send dummy key events for pages that are unaware of input events,
* to provide web compatibility for pages that depend on key events.
* Our dummy key events have 0 as the keycode.
*/
void
GeckoEditableSupport::SendIMEDummyKeyEvent(nsIWidget* aWidget, EventMessage msg)
@ -678,7 +694,12 @@ GeckoEditableSupport::SendIMEDummyKeyEvent(nsIWidget* aWidget, EventMessage msg)
WidgetKeyboardEvent event(true, msg, aWidget);
event.mTime = PR_Now() / 1000;
MOZ_ASSERT(event.mKeyCode == 0);
// TODO: If we can know scan code of the key event which caused replacing
// composition string, we should set mCodeNameIndex here. Then,
// we should rename this method because it becomes not a "dummy"
// keyboard event.
event.mKeyCode = NS_VK_PROCESSKEY;
event.mKeyNameIndex = KEY_NAME_INDEX_Process;
NS_ENSURE_SUCCESS_VOID(BeginInputTransaction(mDispatcher));
mDispatcher->DispatchKeyboardEvent(msg, event, status);
}
@ -1027,7 +1048,8 @@ GeckoEditableSupport::OnImeReplaceText(int32_t aStart, int32_t aEnd,
AddIMETextChange(dummyChange);
}
if (mInputContext.mMayBeIMEUnaware) {
if (sDispatchKeyEventsInCompositionForAnyApps ||
mInputContext.mMayBeIMEUnaware) {
SendIMEDummyKeyEvent(widget, eKeyDown);
if (!mDispatcher || widget->Destroyed()) {
return;
@ -1046,7 +1068,8 @@ GeckoEditableSupport::OnImeReplaceText(int32_t aStart, int32_t aEnd,
return;
}
if (mInputContext.mMayBeIMEUnaware) {
if (sDispatchKeyEventsInCompositionForAnyApps ||
mInputContext.mMayBeIMEUnaware) {
SendIMEDummyKeyEvent(widget, eKeyUp);
// Widget may be destroyed after dispatching the above event.
}

View File

@ -106,6 +106,10 @@ class GeckoEditableSupport final
bool mIMETextChangedDuringFlush;
bool mIMEMonitorCursor;
static bool sDispatchKeyEventsInCompositionForAnyApps;
void ObservePrefs();
nsIWidget* GetWidget() const
{
return mDispatcher ? mDispatcher->GetWidget() : mWindow;
@ -180,12 +184,15 @@ public:
, mIMESelectionChanged(false)
, mIMETextChangedDuringFlush(false)
, mIMEMonitorCursor(false)
{}
{
ObservePrefs();
}
// Constructor for content process GeckoEditableChild.
GeckoEditableSupport(java::GeckoEditableChild::Param aEditableChild)
: GeckoEditableSupport(nullptr, nullptr, aEditableChild)
{}
{
}
NS_DECL_ISUPPORTS