Bug 1629347 - Make `TSFTextStore::SetInputContext()` emulate focus when the menu keyboard event listener is uninstalled r=m_kato

Currently, `IMEStateManager` sets `InputContext` to disable IME when the
menu keyboard event listener is installed, but does not destroy
`IMEContentObserver` which may be in a remote process.  And similarly,
it setns `InputContext` to enable IME when the menu keyboard event listener
is uninstalled, but does not make `IMEContentObserver` which may be in a remote
process send `NOTIFY_IME_OF_FOCUS` again.  Therefore, from point of view of
native IME handlers in widget, `NOTIFY_IME_OF_FOCUS` won't be sent in this
case, but `TSFTextStore::SetInputContext()` expects that it'll be followed
by `NOTIFY_IME_OF_FOCUS` unless it's called for `FOCUS_NOT_CHANGED`.
Therefore, `sEnabledTextStore` is `nullptr` when this bug occurs.

For fixing this bug **quickly**, this patch makes
`TSFTextStore::SetInputContext()` treat  `MENU_LOST_PSEUDO_FOCUS` as
`FOCUS_NOT_CHANGED` to create `TSFTextStore` instance if new state is
"enabled".

Ideally, we should redesign `IMEStateManager` because while menu keyboard
event listener has pseudo focus, web apps may change focus or create something
complicated cases.

Unfortunately, we still cannot write automated tests for `TSFTextStore`
due to bug 1322744.

Differential Revision: https://phabricator.services.mozilla.com/D93469
This commit is contained in:
Masayuki Nakano 2020-10-16 06:14:23 +00:00
Родитель 40b561b9ac
Коммит edfe4e01f5
1 изменённых файлов: 28 добавлений и 15 удалений

Просмотреть файл

@ -6589,28 +6589,41 @@ void TSFTextStore::SetInputContext(nsWindowBase* aWidget,
sEnabledTextStore ? sEnabledTextStore->mWidget.get() : nullptr,
GetBoolName(ThinksHavingFocus())));
// When this is called when the widget is created, there is nothing to do.
if (aAction.mFocusChange == InputContextAction::WIDGET_CREATED) {
return;
}
NS_ENSURE_TRUE_VOID(IsInTSFMode());
if (aAction.mFocusChange != InputContextAction::FOCUS_NOT_CHANGED) {
if (sEnabledTextStore) {
RefPtr<TSFTextStore> textStore(sEnabledTextStore);
textStore->SetInputScope(aContext.mHTMLInputType,
aContext.mHTMLInputInputmode,
aContext.mInPrivateBrowsing);
}
return;
switch (aAction.mFocusChange) {
case InputContextAction::WIDGET_CREATED:
// If this is called when the widget is created, there is nothing to do.
return;
case InputContextAction::FOCUS_NOT_CHANGED:
case InputContextAction::MENU_LOST_PSEUDO_FOCUS:
if (NS_WARN_IF(!IsInTSFMode())) {
return;
}
// In these cases, `NOTIFY_IME_OF_FOCUS` won't be sent. Therefore,
// we need to reset text store for new state right now.
break;
default:
NS_WARNING_ASSERTION(IsInTSFMode(),
"Why is this called when TSF is disabled?");
if (sEnabledTextStore) {
RefPtr<TSFTextStore> textStore(sEnabledTextStore);
textStore->SetInputScope(aContext.mHTMLInputType,
aContext.mHTMLInputInputmode,
aContext.mInPrivateBrowsing);
}
return;
}
// If focus isn't actually changed but the enabled state is changed,
// emulate the focus move.
if (!ThinksHavingFocus() && aContext.mIMEState.IsEditable()) {
MOZ_LOG(sTextStoreLog, LogLevel::Debug,
(" TSFTextStore::SetInputContent() emulates focus for IME "
"state change"));
OnFocusChange(true, aWidget, aContext);
} else if (ThinksHavingFocus() && !aContext.mIMEState.IsEditable()) {
MOZ_LOG(sTextStoreLog, LogLevel::Debug,
(" TSFTextStore::SetInputContent() emulates blur for IME "
"state change"));
OnFocusChange(false, aWidget, aContext);
}
}