mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-24 21:31:04 +00:00
Bug 1342552 - IMEStateManager should cache nsIWidget for sPresContext and use it. r=smaug
IMEStateManager should cache nsIWidget for sPresContext at caching sPresContext. Then, even if sPresContext has gone, IMEStateManager can clean up with the nsIWidget cache. Unfortunately, editor has some bugs about calling IMEStateManager::UpdateIMEState(). That is, calling it *before* IMEStateManager::OnFocusChange(). In such case, this patch makes UpdateIMEState() ignore the call. MozReview-Commit-ID: 1cydI03WyB8
This commit is contained in:
parent
b7520a7dec
commit
d04632f559
@ -9,6 +9,7 @@
|
||||
#include "mozilla/IMEStateManager.h"
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/EditorBase.h"
|
||||
#include "mozilla/EventListenerManager.h"
|
||||
#include "mozilla/EventStates.h"
|
||||
#include "mozilla/MouseEvents.h"
|
||||
@ -29,7 +30,6 @@
|
||||
#include "nsIContent.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsIDOMMouseEvent.h"
|
||||
#include "nsIEditor.h"
|
||||
#include "nsIForm.h"
|
||||
#include "nsIFormControl.h"
|
||||
#include "nsINode.h"
|
||||
@ -138,6 +138,7 @@ GetIMEStateSetOpenName(IMEState::Open aOpen)
|
||||
|
||||
StaticRefPtr<nsIContent> IMEStateManager::sContent;
|
||||
StaticRefPtr<nsPresContext> IMEStateManager::sPresContext;
|
||||
nsIWidget* IMEStateManager::sWidget = nullptr;
|
||||
nsIWidget* IMEStateManager::sFocusedIMEWidget = nullptr;
|
||||
nsIWidget* IMEStateManager::sActiveInputContextWidget = nullptr;
|
||||
StaticRefPtr<TabParent> IMEStateManager::sActiveTabParent;
|
||||
@ -199,6 +200,9 @@ IMEStateManager::OnTabParentDestroying(TabParent* aTabParent)
|
||||
void
|
||||
IMEStateManager::WidgetDestroyed(nsIWidget* aWidget)
|
||||
{
|
||||
if (sWidget == aWidget) {
|
||||
sWidget = nullptr;
|
||||
}
|
||||
if (sFocusedIMEWidget == aWidget) {
|
||||
sFocusedIMEWidget = nullptr;
|
||||
}
|
||||
@ -296,13 +300,13 @@ IMEStateManager::OnDestroyPresContext(nsPresContext* aPresContext)
|
||||
|
||||
DestroyIMEContentObserver();
|
||||
|
||||
nsCOMPtr<nsIWidget> widget = sPresContext->GetRootWidget();
|
||||
if (widget) {
|
||||
if (sWidget) {
|
||||
IMEState newState = GetNewIMEState(sPresContext, nullptr);
|
||||
InputContextAction action(InputContextAction::CAUSE_UNKNOWN,
|
||||
InputContextAction::LOST_FOCUS);
|
||||
SetIMEState(newState, nullptr, widget, action);
|
||||
SetIMEState(newState, nullptr, sWidget, action);
|
||||
}
|
||||
sWidget = nullptr;
|
||||
sContent = nullptr;
|
||||
sPresContext = nullptr;
|
||||
sActiveTabParent = nullptr;
|
||||
@ -330,8 +334,6 @@ IMEStateManager::OnRemoveContent(nsPresContext* aPresContext,
|
||||
// is called during the content being removed. Then, the native
|
||||
// composition events which are caused by following APIs are ignored due
|
||||
// to unsafe to run script (in PresShell::HandleEvent()).
|
||||
DebugOnly<void*> widget = aPresContext->GetRootWidget();
|
||||
MOZ_ASSERT(widget, "Why is there no widget?");
|
||||
nsresult rv =
|
||||
compositionInContent->NotifyIME(REQUEST_TO_CANCEL_COMPOSITION);
|
||||
if (NS_FAILED(rv)) {
|
||||
@ -353,14 +355,14 @@ IMEStateManager::OnRemoveContent(nsPresContext* aPresContext,
|
||||
DestroyIMEContentObserver();
|
||||
|
||||
// Current IME transaction should commit
|
||||
nsCOMPtr<nsIWidget> widget = sPresContext->GetRootWidget();
|
||||
if (widget) {
|
||||
if (sWidget) {
|
||||
IMEState newState = GetNewIMEState(sPresContext, nullptr);
|
||||
InputContextAction action(InputContextAction::CAUSE_UNKNOWN,
|
||||
InputContextAction::LOST_FOCUS);
|
||||
SetIMEState(newState, nullptr, widget, action);
|
||||
SetIMEState(newState, nullptr, sWidget, action);
|
||||
}
|
||||
|
||||
sWidget = nullptr;
|
||||
sContent = nullptr;
|
||||
sPresContext = nullptr;
|
||||
sActiveTabParent = nullptr;
|
||||
@ -368,6 +370,15 @@ IMEStateManager::OnRemoveContent(nsPresContext* aPresContext,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// static
|
||||
bool
|
||||
IMEStateManager::CanHandleWith(nsPresContext* aPresContext)
|
||||
{
|
||||
return aPresContext &&
|
||||
aPresContext->GetPresShell() &&
|
||||
!aPresContext->PresShell()->IsDestroying();
|
||||
}
|
||||
|
||||
// static
|
||||
nsresult
|
||||
IMEStateManager::OnChangeFocus(nsPresContext* aPresContext,
|
||||
@ -391,23 +402,36 @@ IMEStateManager::OnChangeFocusInternal(nsPresContext* aPresContext,
|
||||
RefPtr<TabParent> newTabParent = TabParent::GetFrom(aContent);
|
||||
|
||||
MOZ_LOG(sISMLog, LogLevel::Info,
|
||||
("OnChangeFocusInternal(aPresContext=0x%p, "
|
||||
("OnChangeFocusInternal(aPresContext=0x%p (available: %s), "
|
||||
"aContent=0x%p (TabParent=0x%p), aAction={ mCause=%s, mFocusChange=%s }), "
|
||||
"sPresContext=0x%p, sContent=0x%p, sActiveTabParent=0x%p, "
|
||||
"sPresContext=0x%p (available: %s), sContent=0x%p, "
|
||||
"sWidget=0x%p (available: %s), sActiveTabParent=0x%p, "
|
||||
"sActiveIMEContentObserver=0x%p, sInstalledMenuKeyboardListener=%s",
|
||||
aPresContext, aContent, newTabParent.get(),
|
||||
GetActionCauseName(aAction.mCause),
|
||||
aPresContext, GetBoolName(CanHandleWith(aPresContext)), aContent,
|
||||
newTabParent.get(), GetActionCauseName(aAction.mCause),
|
||||
GetActionFocusChangeName(aAction.mFocusChange),
|
||||
sPresContext.get(), sContent.get(), sActiveTabParent.get(),
|
||||
sActiveIMEContentObserver.get(),
|
||||
sPresContext.get(), GetBoolName(CanHandleWith(sPresContext)),
|
||||
sContent.get(), sWidget, GetBoolName(sWidget && !sWidget->Destroyed()),
|
||||
sActiveTabParent.get(), sActiveIMEContentObserver.get(),
|
||||
GetBoolName(sInstalledMenuKeyboardListener)));
|
||||
|
||||
// If new aPresShell has been destroyed, this should handle the focus change
|
||||
// as nobody is getting focus.
|
||||
if (NS_WARN_IF(aPresContext && !CanHandleWith(aPresContext))) {
|
||||
MOZ_LOG(sISMLog, LogLevel::Warning,
|
||||
(" OnChangeFocusInternal(), called with destroyed PresShell, "
|
||||
"handling this call as nobody getting focus"));
|
||||
aPresContext = nullptr;
|
||||
aContent = nullptr;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIWidget> oldWidget = sWidget;
|
||||
nsCOMPtr<nsIWidget> newWidget =
|
||||
aPresContext ? aPresContext->GetRootWidget() : nullptr;
|
||||
bool focusActuallyChanging =
|
||||
(sContent != aContent || sPresContext != aPresContext ||
|
||||
sActiveTabParent != newTabParent);
|
||||
oldWidget != newWidget || sActiveTabParent != newTabParent);
|
||||
|
||||
nsCOMPtr<nsIWidget> oldWidget =
|
||||
sPresContext ? sPresContext->GetRootWidget() : nullptr;
|
||||
if (oldWidget && focusActuallyChanging) {
|
||||
// If we're deactivating, we shouldn't commit composition forcibly because
|
||||
// the user may want to continue the composition.
|
||||
@ -441,16 +465,17 @@ IMEStateManager::OnChangeFocusInternal(nsPresContext* aPresContext,
|
||||
Unused << sActiveTabParent->SendStopIMEStateManagement();
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIWidget> widget =
|
||||
(sPresContext == aPresContext) ? oldWidget.get() :
|
||||
aPresContext->GetRootWidget();
|
||||
if (NS_WARN_IF(!widget)) {
|
||||
if (NS_WARN_IF(!newWidget)) {
|
||||
MOZ_LOG(sISMLog, LogLevel::Error,
|
||||
(" OnChangeFocusInternal(), FAILED due to "
|
||||
"no widget to manage its IME state"));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Update the cached widget since root view of the presContext may be
|
||||
// changed to different view.
|
||||
sWidget = newWidget;
|
||||
|
||||
// If a child process has focus, we should disable IME state until the child
|
||||
// process actually gets focus because if user types keys before that they
|
||||
// are handled by IME.
|
||||
@ -470,7 +495,7 @@ IMEStateManager::OnChangeFocusInternal(nsPresContext* aPresContext,
|
||||
SendMenuKeyboardListenerInstalled(sInstalledMenuKeyboardListener);
|
||||
setIMEState = sInstalledMenuKeyboardListener;
|
||||
} else if (focusActuallyChanging) {
|
||||
InputContext context = widget->GetInputContext();
|
||||
InputContext context = newWidget->GetInputContext();
|
||||
if (context.mIMEState.mEnabled == IMEState::DISABLED) {
|
||||
setIMEState = false;
|
||||
MOZ_LOG(sISMLog, LogLevel::Debug,
|
||||
@ -500,7 +525,7 @@ IMEStateManager::OnChangeFocusInternal(nsPresContext* aPresContext,
|
||||
if (!focusActuallyChanging) {
|
||||
// actual focus isn't changing, but if IME enabled state is changing,
|
||||
// we should do it.
|
||||
InputContext context = widget->GetInputContext();
|
||||
InputContext context = newWidget->GetInputContext();
|
||||
if (context.mIMEState.mEnabled == newState.mEnabled) {
|
||||
MOZ_LOG(sISMLog, LogLevel::Debug,
|
||||
(" OnChangeFocusInternal(), "
|
||||
@ -524,7 +549,7 @@ IMEStateManager::OnChangeFocusInternal(nsPresContext* aPresContext,
|
||||
}
|
||||
|
||||
// Update IME state for new focus widget
|
||||
SetIMEState(newState, aContent, widget, aAction);
|
||||
SetIMEState(newState, aContent, newWidget, aAction);
|
||||
}
|
||||
|
||||
sActiveTabParent = newTabParent;
|
||||
@ -626,22 +651,27 @@ IMEStateManager::OnClickInEditor(nsPresContext* aPresContext,
|
||||
{
|
||||
MOZ_LOG(sISMLog, LogLevel::Info,
|
||||
("OnClickInEditor(aPresContext=0x%p, aContent=0x%p, aMouseEvent=0x%p), "
|
||||
"sPresContext=0x%p, sContent=0x%p",
|
||||
aPresContext, aContent, aMouseEvent, sPresContext.get(), sContent.get()));
|
||||
"sPresContext=0x%p, sContent=0x%p, sWidget=0x%p (available: %s)",
|
||||
aPresContext, aContent, aMouseEvent, sPresContext.get(), sContent.get(),
|
||||
sWidget, GetBoolName(sWidget && !sWidget->Destroyed())));
|
||||
|
||||
if (NS_WARN_IF(!aMouseEvent)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (sPresContext != aPresContext || sContent != aContent) {
|
||||
if (sPresContext != aPresContext || sContent != aContent ||
|
||||
NS_WARN_IF(!sPresContext) || NS_WARN_IF(!sWidget) ||
|
||||
NS_WARN_IF(sWidget->Destroyed())) {
|
||||
MOZ_LOG(sISMLog, LogLevel::Debug,
|
||||
(" OnClickInEditor(), "
|
||||
"the mouse event isn't fired on the editor managed by ISM"));
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIWidget> widget = aPresContext->GetRootWidget();
|
||||
NS_ENSURE_TRUE_VOID(widget);
|
||||
nsCOMPtr<nsIWidget> widget(sWidget);
|
||||
|
||||
MOZ_ASSERT(!sPresContext->GetRootWidget() ||
|
||||
sPresContext->GetRootWidget() == widget);
|
||||
|
||||
if (!aMouseEvent->IsTrusted()) {
|
||||
MOZ_LOG(sISMLog, LogLevel::Debug,
|
||||
@ -753,16 +783,18 @@ IMEStateManager::OnEditorDestroying(nsIEditor* aEditor)
|
||||
void
|
||||
IMEStateManager::UpdateIMEState(const IMEState& aNewIMEState,
|
||||
nsIContent* aContent,
|
||||
nsIEditor* aEditor)
|
||||
EditorBase& aEditorBase)
|
||||
{
|
||||
MOZ_LOG(sISMLog, LogLevel::Info,
|
||||
("UpdateIMEState(aNewIMEState={ mEnabled=%s, "
|
||||
"mOpen=%s }, aContent=0x%p, aEditor=0x%p), "
|
||||
"sPresContext=0x%p, sContent=0x%p, sActiveIMEContentObserver=0x%p, "
|
||||
"sIsGettingNewIMEState=%s",
|
||||
"mOpen=%s }, aContent=0x%p, aEditorBase=0x%p), "
|
||||
"sPresContext=0x%p, sContent=0x%p, sWidget=0x%p (available: %s), "
|
||||
"sActiveIMEContentObserver=0x%p, sIsGettingNewIMEState=%s",
|
||||
GetIMEStateEnabledName(aNewIMEState.mEnabled),
|
||||
GetIMEStateSetOpenName(aNewIMEState.mOpen), aContent, aEditor,
|
||||
sPresContext.get(), sContent.get(), sActiveIMEContentObserver.get(),
|
||||
GetIMEStateSetOpenName(aNewIMEState.mOpen), aContent, &aEditorBase,
|
||||
sPresContext.get(), sContent.get(),
|
||||
sWidget, GetBoolName(sWidget && !sWidget->Destroyed()),
|
||||
sActiveIMEContentObserver.get(),
|
||||
GetBoolName(sIsGettingNewIMEState)));
|
||||
|
||||
if (sIsGettingNewIMEState) {
|
||||
@ -772,20 +804,58 @@ IMEStateManager::UpdateIMEState(const IMEState& aNewIMEState,
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIPresShell> presShell = aEditorBase.GetPresShell();
|
||||
if (NS_WARN_IF(!presShell)) {
|
||||
MOZ_LOG(sISMLog, LogLevel::Error,
|
||||
(" UpdateIMEState(), FAILED due to "
|
||||
"editor doesn't have PresShell"));
|
||||
return;
|
||||
}
|
||||
|
||||
nsPresContext* presContext = presShell->GetPresContext();
|
||||
if (NS_WARN_IF(!presContext)) {
|
||||
MOZ_LOG(sISMLog, LogLevel::Error,
|
||||
(" UpdateIMEState(), FAILED due to "
|
||||
"editor doesn't have PresContext"));
|
||||
return;
|
||||
}
|
||||
|
||||
// IMEStateManager::UpdateIMEState() should be called after
|
||||
// IMEStateManager::OnChangeFocus() is called for setting focus to aContent
|
||||
// and aEditorBase. However, when aEditorBase is an HTMLEditor, this may be
|
||||
// called by nsIEditor::PostCreate() before IMEStateManager::OnChangeFocus().
|
||||
// Similarly, when aEditorBase is a TextEditor, this may be called by
|
||||
// nsIEditor::SetFlags(). In such cases, this method should do nothing
|
||||
// because input context should be updated when
|
||||
// IMEStateManager::OnChangeFocus() is called later.
|
||||
if (sPresContext != presContext) {
|
||||
MOZ_LOG(sISMLog, LogLevel::Warning,
|
||||
(" UpdateIMEState(), does nothing due to "
|
||||
"the editor hasn't managed by IMEStateManager yet"));
|
||||
return;
|
||||
}
|
||||
|
||||
// If IMEStateManager doesn't manage any document, this cannot update IME
|
||||
// state of any widget.
|
||||
if (NS_WARN_IF(!sPresContext)) {
|
||||
MOZ_LOG(sISMLog, LogLevel::Error,
|
||||
(" UpdateIMEState(), FAILED due to "
|
||||
"no managing nsPresContext"));
|
||||
return;
|
||||
}
|
||||
nsCOMPtr<nsIWidget> widget = sPresContext->GetRootWidget();
|
||||
if (NS_WARN_IF(!widget)) {
|
||||
|
||||
if (NS_WARN_IF(!sWidget) || NS_WARN_IF(sWidget->Destroyed())) {
|
||||
MOZ_LOG(sISMLog, LogLevel::Error,
|
||||
(" UpdateIMEState(), FAILED due to "
|
||||
"no widget for the managing nsPresContext"));
|
||||
"the widget for the managing nsPresContext has gone"));
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIWidget> widget(sWidget);
|
||||
|
||||
MOZ_ASSERT(!sPresContext->GetRootWidget() ||
|
||||
sPresContext->GetRootWidget() == widget);
|
||||
|
||||
// Even if there is active IMEContentObserver, it may not be observing the
|
||||
// editor with current editable root content due to reframed. In such case,
|
||||
// We should try to reinitialize the IMEContentObserver.
|
||||
@ -794,11 +864,17 @@ IMEStateManager::UpdateIMEState(const IMEState& aNewIMEState,
|
||||
(" UpdateIMEState(), try to reinitialize the "
|
||||
"active IMEContentObserver"));
|
||||
if (!sActiveIMEContentObserver->MaybeReinitialize(widget, sPresContext,
|
||||
aContent, aEditor)) {
|
||||
aContent, &aEditorBase)) {
|
||||
MOZ_LOG(sISMLog, LogLevel::Error,
|
||||
(" UpdateIMEState(), failed to reinitialize the "
|
||||
"active IMEContentObserver"));
|
||||
}
|
||||
if (NS_WARN_IF(widget->Destroyed())) {
|
||||
MOZ_LOG(sISMLog, LogLevel::Error,
|
||||
(" UpdateIMEState(), widget has gone during reinitializing the "
|
||||
"active IMEContentObserver"));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// If there is no active IMEContentObserver or it isn't observing the
|
||||
@ -809,10 +885,20 @@ IMEStateManager::UpdateIMEState(const IMEState& aNewIMEState,
|
||||
|
||||
bool updateIMEState =
|
||||
(widget->GetInputContext().mIMEState.mEnabled != aNewIMEState.mEnabled);
|
||||
if (NS_WARN_IF(widget->Destroyed())) {
|
||||
MOZ_LOG(sISMLog, LogLevel::Error,
|
||||
(" UpdateIMEState(), widget has gone during getting input context"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (updateIMEState) {
|
||||
// commit current composition before modifying IME state.
|
||||
NotifyIME(REQUEST_TO_COMMIT_COMPOSITION, widget);
|
||||
if (NS_WARN_IF(widget->Destroyed())) {
|
||||
MOZ_LOG(sISMLog, LogLevel::Error,
|
||||
(" UpdateIMEState(), widget has gone during committing composition"));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (createTextStateManager) {
|
||||
@ -823,13 +909,18 @@ IMEStateManager::UpdateIMEState(const IMEState& aNewIMEState,
|
||||
InputContextAction action(InputContextAction::CAUSE_UNKNOWN,
|
||||
InputContextAction::FOCUS_NOT_CHANGED);
|
||||
SetIMEState(aNewIMEState, aContent, widget, action);
|
||||
if (NS_WARN_IF(widget->Destroyed())) {
|
||||
MOZ_LOG(sISMLog, LogLevel::Error,
|
||||
(" UpdateIMEState(), widget has gone during setting input context"));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (createTextStateManager) {
|
||||
// XXX In this case, it might not be enough safe to notify IME of anything.
|
||||
// So, don't try to flush pending notifications of IMEContentObserver
|
||||
// here.
|
||||
CreateIMEContentObserver(aEditor);
|
||||
CreateIMEContentObserver(&aEditorBase);
|
||||
}
|
||||
}
|
||||
|
||||
@ -843,6 +934,13 @@ IMEStateManager::GetNewIMEState(nsPresContext* aPresContext,
|
||||
"sInstalledMenuKeyboardListener=%s",
|
||||
aPresContext, aContent, GetBoolName(sInstalledMenuKeyboardListener)));
|
||||
|
||||
if (!CanHandleWith(aPresContext)) {
|
||||
MOZ_LOG(sISMLog, LogLevel::Debug,
|
||||
(" GetNewIMEState() returns DISABLED because "
|
||||
"the nsPresContext has been destroyed"));
|
||||
return IMEState(IMEState::DISABLED);
|
||||
}
|
||||
|
||||
// On Printing or Print Preview, we don't need IME.
|
||||
if (aPresContext->Type() == nsPresContext::eContext_PrintPreview ||
|
||||
aPresContext->Type() == nsPresContext::eContext_Print) {
|
||||
@ -921,7 +1019,8 @@ IMEStateManager::SetInputContextForChildProcess(
|
||||
("SetInputContextForChildProcess(aTabParent=0x%p, "
|
||||
"aInputContext={ mIMEState={ mEnabled=%s, mOpen=%s }, "
|
||||
"mHTMLInputType=\"%s\", mHTMLInputInputmode=\"%s\", mActionHint=\"%s\" }, "
|
||||
"aAction={ mCause=%s, mAction=%s }), sPresContext=0x%p, "
|
||||
"aAction={ mCause=%s, mAction=%s }), "
|
||||
"sPresContext=0x%p (available: %s), sWidget=0x%p (available: %s), "
|
||||
"sActiveTabParent=0x%p",
|
||||
aTabParent, GetIMEStateEnabledName(aInputContext.mIMEState.mEnabled),
|
||||
GetIMEStateSetOpenName(aInputContext.mIMEState.mOpen),
|
||||
@ -930,7 +1029,9 @@ IMEStateManager::SetInputContextForChildProcess(
|
||||
NS_ConvertUTF16toUTF8(aInputContext.mActionHint).get(),
|
||||
GetActionCauseName(aAction.mCause),
|
||||
GetActionFocusChangeName(aAction.mFocusChange),
|
||||
sPresContext.get(), sActiveTabParent.get()));
|
||||
sPresContext.get(), GetBoolName(CanHandleWith(sPresContext)),
|
||||
sWidget, GetBoolName(sWidget && !sWidget->Destroyed()),
|
||||
sActiveTabParent.get()));
|
||||
|
||||
if (aTabParent != sActiveTabParent) {
|
||||
MOZ_LOG(sISMLog, LogLevel::Error,
|
||||
@ -939,21 +1040,24 @@ IMEStateManager::SetInputContextForChildProcess(
|
||||
return;
|
||||
}
|
||||
|
||||
if (NS_WARN_IF(!sPresContext)) {
|
||||
if (NS_WARN_IF(!CanHandleWith(sPresContext))) {
|
||||
MOZ_LOG(sISMLog, LogLevel::Error,
|
||||
(" SetInputContextForChildProcess(), FAILED, "
|
||||
"due to no focused presContext"));
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIWidget> widget = sPresContext->GetRootWidget();
|
||||
if (NS_WARN_IF(!widget)) {
|
||||
if (NS_WARN_IF(!sWidget) || NS_WARN_IF(sWidget->Destroyed())) {
|
||||
MOZ_LOG(sISMLog, LogLevel::Error,
|
||||
(" SetInputContextForChildProcess(), FAILED, "
|
||||
"due to no widget in the focused presContext"));
|
||||
"due to the widget for the nsPresContext has gone"));
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIWidget> widget(sWidget);
|
||||
|
||||
MOZ_ASSERT(!sPresContext->GetRootWidget() ||
|
||||
sPresContext->GetRootWidget() == widget);
|
||||
MOZ_ASSERT(aInputContext.mOrigin == InputContext::ORIGIN_CONTENT);
|
||||
|
||||
SetInputContext(widget, aInputContext, aAction);
|
||||
@ -1081,8 +1185,9 @@ IMEStateManager::SetInputContext(nsIWidget* aWidget,
|
||||
|
||||
MOZ_RELEASE_ASSERT(aWidget);
|
||||
|
||||
aWidget->SetInputContext(aInputContext, aAction);
|
||||
sActiveInputContextWidget = aWidget;
|
||||
nsCOMPtr<nsIWidget> widget(aWidget);
|
||||
widget->SetInputContext(aInputContext, aAction);
|
||||
sActiveInputContextWidget = widget;
|
||||
}
|
||||
|
||||
// static
|
||||
@ -1332,7 +1437,7 @@ IMEStateManager::NotifyIME(const IMENotification& aNotification,
|
||||
}
|
||||
|
||||
switch (aNotification.mMessage) {
|
||||
case NOTIFY_IME_OF_FOCUS:
|
||||
case NOTIFY_IME_OF_FOCUS: {
|
||||
if (sFocusedIMEWidget) {
|
||||
if (NS_WARN_IF(!sRemoteHasFocus && !aOriginIsRemote)) {
|
||||
MOZ_LOG(sISMLog, LogLevel::Error,
|
||||
@ -1351,7 +1456,9 @@ IMEStateManager::NotifyIME(const IMENotification& aNotification,
|
||||
}
|
||||
sRemoteHasFocus = aOriginIsRemote;
|
||||
sFocusedIMEWidget = aWidget;
|
||||
return aWidget->NotifyIME(aNotification);
|
||||
nsCOMPtr<nsIWidget> widget(aWidget);
|
||||
return widget->NotifyIME(aNotification);
|
||||
}
|
||||
case NOTIFY_IME_OF_BLUR: {
|
||||
if (!sRemoteHasFocus && aOriginIsRemote) {
|
||||
MOZ_LOG(sISMLog, LogLevel::Info,
|
||||
@ -1392,7 +1499,7 @@ IMEStateManager::NotifyIME(const IMENotification& aNotification,
|
||||
case NOTIFY_IME_OF_TEXT_CHANGE:
|
||||
case NOTIFY_IME_OF_POSITION_CHANGE:
|
||||
case NOTIFY_IME_OF_MOUSE_BUTTON_EVENT:
|
||||
case NOTIFY_IME_OF_COMPOSITION_EVENT_HANDLED:
|
||||
case NOTIFY_IME_OF_COMPOSITION_EVENT_HANDLED: {
|
||||
if (!sRemoteHasFocus && aOriginIsRemote) {
|
||||
MOZ_LOG(sISMLog, LogLevel::Info,
|
||||
(" NotifyIME(), received content change "
|
||||
@ -1419,7 +1526,9 @@ IMEStateManager::NotifyIME(const IMENotification& aNotification,
|
||||
"nothing to do..."));
|
||||
return NS_OK;
|
||||
}
|
||||
return aWidget->NotifyIME(aNotification);
|
||||
nsCOMPtr<nsIWidget> widget(aWidget);
|
||||
return widget->NotifyIME(aNotification);
|
||||
}
|
||||
default:
|
||||
// Other notifications should be sent only when there is composition.
|
||||
// So, we need to handle the others below.
|
||||
@ -1464,7 +1573,9 @@ IMEStateManager::NotifyIME(IMEMessage aMessage,
|
||||
("NotifyIME(aMessage=%s, aPresContext=0x%p, aOriginIsRemote=%s)",
|
||||
ToChar(aMessage), aPresContext, GetBoolName(aOriginIsRemote)));
|
||||
|
||||
NS_ENSURE_TRUE(aPresContext, NS_ERROR_INVALID_ARG);
|
||||
if (NS_WARN_IF(!CanHandleWith(aPresContext))) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
nsIWidget* widget = aPresContext->GetRootWidget();
|
||||
if (NS_WARN_IF(!widget)) {
|
||||
@ -1559,9 +1670,12 @@ IMEStateManager::CreateIMEContentObserver(nsIEditor* aEditor)
|
||||
{
|
||||
MOZ_LOG(sISMLog, LogLevel::Info,
|
||||
("CreateIMEContentObserver(aEditor=0x%p), "
|
||||
"sPresContext=0x%p, sContent=0x%p, sActiveIMEContentObserver=0x%p, "
|
||||
"sPresContext=0x%p, sContent=0x%p, sWidget=0x%p (available: %s), "
|
||||
"sActiveIMEContentObserver=0x%p, "
|
||||
"sActiveIMEContentObserver->IsManaging(sPresContext, sContent)=%s",
|
||||
aEditor, sPresContext.get(), sContent.get(), sActiveIMEContentObserver.get(),
|
||||
aEditor, sPresContext.get(), sContent.get(),
|
||||
sWidget, GetBoolName(sWidget && !sWidget->Destroyed()),
|
||||
sActiveIMEContentObserver.get(),
|
||||
GetBoolName(sActiveIMEContentObserver ?
|
||||
sActiveIMEContentObserver->IsManaging(sPresContext, sContent) : false)));
|
||||
|
||||
@ -1573,14 +1687,15 @@ IMEStateManager::CreateIMEContentObserver(nsIEditor* aEditor)
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIWidget> widget = sPresContext->GetRootWidget();
|
||||
if (!widget) {
|
||||
if (!sWidget || NS_WARN_IF(sWidget->Destroyed())) {
|
||||
MOZ_LOG(sISMLog, LogLevel::Error,
|
||||
(" CreateIMEContentObserver(), FAILED due to "
|
||||
"there is a root widget for the nsPresContext"));
|
||||
"the widget for the nsPresContext has gone"));
|
||||
return; // Sometimes, there are no widgets.
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIWidget> widget(sWidget);
|
||||
|
||||
// If it's not text editable, we don't need to create IMEContentObserver.
|
||||
if (!IsIMEObserverNeeded(widget->GetInputContext().mIMEState)) {
|
||||
MOZ_LOG(sISMLog, LogLevel::Debug,
|
||||
@ -1589,6 +1704,15 @@ IMEStateManager::CreateIMEContentObserver(nsIEditor* aEditor)
|
||||
return;
|
||||
}
|
||||
|
||||
if (NS_WARN_IF(widget->Destroyed())) {
|
||||
MOZ_LOG(sISMLog, LogLevel::Error,
|
||||
(" CreateIMEContentObserver(), FAILED due to "
|
||||
"the widget for the nsPresContext has gone"));
|
||||
return;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(sPresContext->GetRootWidget() == widget);
|
||||
|
||||
MOZ_LOG(sISMLog, LogLevel::Debug,
|
||||
(" CreateIMEContentObserver() is creating an "
|
||||
"IMEContentObserver instance..."));
|
||||
|
@ -13,13 +13,13 @@
|
||||
#include "nsIWidget.h"
|
||||
|
||||
class nsIContent;
|
||||
class nsIEditor;
|
||||
class nsINode;
|
||||
class nsPresContext;
|
||||
class nsISelection;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class EditorBase;
|
||||
class EventDispatchingCallback;
|
||||
class IMEContentObserver;
|
||||
class TextCompositionArray;
|
||||
@ -134,7 +134,7 @@ public:
|
||||
// widget. So, the caller must have focus.
|
||||
static void UpdateIMEState(const IMEState &aNewIMEState,
|
||||
nsIContent* aContent,
|
||||
nsIEditor* aEditor);
|
||||
EditorBase& aEditorBase);
|
||||
|
||||
// This method is called when user operates mouse button in focused editor
|
||||
// and before the editor handles it.
|
||||
@ -265,11 +265,29 @@ protected:
|
||||
|
||||
static nsIContent* GetRootContent(nsPresContext* aPresContext);
|
||||
|
||||
/**
|
||||
* CanHandleWith() returns false if aPresContext is nullptr or it's destroyed.
|
||||
*/
|
||||
static bool CanHandleWith(nsPresContext* aPresContext);
|
||||
|
||||
// sContent and sPresContext are the focused content and PresContext. If a
|
||||
// document has focus but there is no focused element, sContent may be
|
||||
// nullptr.
|
||||
static StaticRefPtr<nsIContent> sContent;
|
||||
static StaticRefPtr<nsPresContext> sPresContext;
|
||||
// sWidget is cache for the root widget of sPresContext. Even afer
|
||||
// sPresContext has gone, we need to clean up some IME state on the widget
|
||||
// if the widget is available.
|
||||
static nsIWidget* sWidget;
|
||||
// sFocusedIMEWidget is, the widget which was sent to "focus" notification
|
||||
// from IMEContentObserver and not yet sent "blur" notification.
|
||||
// So, if this is not nullptr, the widget needs to receive "blur"
|
||||
// notification.
|
||||
static nsIWidget* sFocusedIMEWidget;
|
||||
// sActiveInputContextWidget is the last widget whose SetInputContext() is
|
||||
// called.
|
||||
// called. This is important to reduce sync IPC cost with parent process.
|
||||
// If IMEStateManager set input context to different widget, PuppetWidget can
|
||||
// return cached input context safely.
|
||||
static nsIWidget* sActiveInputContextWidget;
|
||||
static StaticRefPtr<TabParent> sActiveTabParent;
|
||||
// sActiveIMEContentObserver points to the currently active
|
||||
|
@ -328,7 +328,7 @@ EditorBase::PostCreate()
|
||||
rv = GetPreferredIMEState(&newState);
|
||||
NS_ENSURE_SUCCESS(rv, NS_OK);
|
||||
nsCOMPtr<nsIContent> content = GetFocusedContentForIME();
|
||||
IMEStateManager::UpdateIMEState(newState, content, this);
|
||||
IMEStateManager::UpdateIMEState(newState, content, *this);
|
||||
}
|
||||
|
||||
// FYI: This call might cause destroying this editor.
|
||||
@ -523,7 +523,7 @@ EditorBase::SetFlags(uint32_t aFlags)
|
||||
// NOTE: When the enabled state isn't going to be modified, this method
|
||||
// is going to do nothing.
|
||||
nsCOMPtr<nsIContent> content = GetFocusedContentForIME();
|
||||
IMEStateManager::UpdateIMEState(newState, content, this);
|
||||
IMEStateManager::UpdateIMEState(newState, content, *this);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user