Bug 805357 part.1 nsIMEStateManager should always call nsIWidget::OnIMEFocusChange(false) when our editor loses focus r=smaug

This commit is contained in:
Masayuki Nakano 2012-10-31 08:22:22 +09:00
parent 6362a6cc75
commit 36985553ef
3 changed files with 53 additions and 23 deletions

View File

@ -116,6 +116,9 @@ nsIMEStateManager::OnDestroyPresContext(nsPresContext* aPresContext)
return NS_OK;
nsCOMPtr<nsIWidget> widget = sPresContext->GetNearestWidget();
if (widget) {
if (IsEditableIMEState(widget)) {
widget->OnIMEFocusChange(false);
}
IMEState newState = GetNewIMEState(sPresContext, nullptr);
InputContextAction action(InputContextAction::CAUSE_UNKNOWN,
InputContextAction::LOST_FOCUS);
@ -175,6 +178,9 @@ nsIMEStateManager::OnRemoveContent(nsPresContext* aPresContext,
// Current IME transaction should commit
nsCOMPtr<nsIWidget> widget = sPresContext->GetNearestWidget();
if (widget) {
if (IsEditableIMEState(widget)) {
widget->OnIMEFocusChange(false);
}
IMEState newState = GetNewIMEState(sPresContext, nullptr);
InputContextAction action(InputContextAction::CAUSE_UNKNOWN,
InputContextAction::LOST_FOCUS);
@ -202,6 +208,23 @@ nsIMEStateManager::OnChangeFocusInternal(nsPresContext* aPresContext,
nsIContent* aContent,
InputContextAction aAction)
{
bool focusActuallyChanging =
(sContent != aContent || sPresContext != aPresContext);
nsCOMPtr<nsIWidget> oldWidget =
sPresContext ? sPresContext->GetNearestWidget() : nullptr;
if (oldWidget && focusActuallyChanging) {
// If we're deactivating, we shouldn't commit composition forcibly because
// the user may want to continue the composition.
if (aPresContext) {
NotifyIME(REQUEST_TO_COMMIT_COMPOSITION, oldWidget);
}
// Notify IME of losing focus even if we're deactivating.
if (IsEditableIMEState(oldWidget)) {
oldWidget->OnIMEFocusChange(false);
}
}
if (sTextStateObserver &&
!sTextStateObserver->IsManaging(aPresContext, aContent)) {
DestroyTextStateManager();
@ -211,7 +234,9 @@ nsIMEStateManager::OnChangeFocusInternal(nsPresContext* aPresContext,
return NS_OK;
}
nsCOMPtr<nsIWidget> widget = aPresContext->GetNearestWidget();
nsCOMPtr<nsIWidget> widget =
(sPresContext == aPresContext) ? oldWidget.get() :
aPresContext->GetNearestWidget();
if (!widget) {
return NS_OK;
}
@ -240,7 +265,7 @@ nsIMEStateManager::OnChangeFocusInternal(nsPresContext* aPresContext,
}
IMEState newState = GetNewIMEState(aPresContext, aContent);
if (aPresContext == sPresContext && aContent == sContent) {
if (!focusActuallyChanging) {
// actual focus isn't changing, but if IME enabled state is changing,
// we should do it.
InputContext context = widget->GetInputContext();
@ -249,6 +274,12 @@ nsIMEStateManager::OnChangeFocusInternal(nsPresContext* aPresContext,
return NS_OK;
}
aAction.mFocusChange = InputContextAction::FOCUS_NOT_CHANGED;
// Even if focus isn't changing actually, we should commit current
// composition here since the IME state is changing.
if (sPresContext && oldWidget && !focusActuallyChanging) {
NotifyIME(REQUEST_TO_COMMIT_COMPOSITION, oldWidget);
}
} else if (aAction.mFocusChange == InputContextAction::FOCUS_NOT_CHANGED) {
// If aContent isn't null or aContent is null but editable, somebody gets
// focus.
@ -257,18 +288,6 @@ nsIMEStateManager::OnChangeFocusInternal(nsPresContext* aPresContext,
gotFocus ? InputContextAction::GOT_FOCUS : InputContextAction::LOST_FOCUS;
}
// Current IME transaction should commit
if (sPresContext) {
nsCOMPtr<nsIWidget> oldWidget;
if (sPresContext == aPresContext)
oldWidget = widget;
else
oldWidget = sPresContext->GetNearestWidget();
if (oldWidget) {
NotifyIME(REQUEST_TO_COMMIT_COMPOSITION, oldWidget);
}
}
// Update IME state for new focus widget
SetIMEState(newState, aContent, widget, aAction);
@ -936,6 +955,22 @@ nsIMEStateManager::GetRootEditableNode(nsPresContext* aPresContext,
return nullptr;
}
bool
nsIMEStateManager::IsEditableIMEState(nsIWidget* aWidget)
{
switch (aWidget->GetInputContext().mIMEState.mEnabled) {
case widget::IMEState::ENABLED:
case widget::IMEState::PASSWORD:
return true;
case widget::IMEState::PLUGIN:
case widget::IMEState::DISABLED:
return false;
default:
MOZ_NOT_REACHED("Unknown IME enable state");
return false;
}
}
void
nsIMEStateManager::DestroyTextStateManager()
{
@ -944,7 +979,6 @@ nsIMEStateManager::DestroyTextStateManager()
}
sTextStateObserver->mDestroying = true;
sTextStateObserver->mWidget->OnIMEFocusChange(false);
sTextStateObserver->Destroy();
NS_RELEASE(sTextStateObserver);
}
@ -964,11 +998,7 @@ nsIMEStateManager::CreateTextStateManager()
}
// If it's not text ediable, we don't need to create nsTextStateManager.
switch (widget->GetInputContext().mIMEState.mEnabled) {
case widget::IMEState::ENABLED:
case widget::IMEState::PASSWORD:
break;
default:
if (!IsEditableIMEState(widget)) {
return;
}

View File

@ -123,6 +123,8 @@ protected:
static nsINode* GetRootEditableNode(nsPresContext* aPresContext,
nsIContent* aContent);
static bool IsEditableIMEState(nsIWidget* aWidget);
static nsIContent* sContent;
static nsPresContext* sPresContext;
static bool sInstalledMenuKeyboardListener;

View File

@ -2971,8 +2971,6 @@ IMEInputHandler::OnFocusChangeInGecko(bool aFocus)
// This is called when the native focus is changed and when the native focus
// isn't changed but the focus is changed in Gecko.
// XXX currently, we're not called this method with false, we need to
// improve the nsIMEStateManager implementation.
if (!aFocus) {
if (sFocusedIMEHandler == this)
sFocusedIMEHandler = nullptr;