forked from mirrors/gecko-dev
Bug 1870960 - Make IMEStateManager stop using nsPresContext::GetTextInputHandlingWidget() as far as possible r=smaug
If given `nsPresContext` is for a lazy loading `<iframe>` and the frame has not been loaded yet, its `GetTextInputHandlingWidget()` may return `nullptr`. However, `IMEStateManager::sTextInputHandlingWidget` may have already cache it. Therefore, `IMEStateManager` should use: * `sTextInputHandlingWidget` if it's available * otherwise, `nsPresContext::GetTextInputHandlingWidget()` Differential Revision: https://phabricator.services.mozilla.com/D197991
This commit is contained in:
parent
24db8f79b3
commit
85697ec93c
4 changed files with 71 additions and 56 deletions
|
|
@ -6,16 +6,17 @@
|
||||||
|
|
||||||
#include "IMEStateManager.h"
|
#include "IMEStateManager.h"
|
||||||
|
|
||||||
#include "mozilla/Logging.h"
|
#include "IMEContentObserver.h"
|
||||||
|
|
||||||
#include "mozilla/Attributes.h"
|
#include "mozilla/Attributes.h"
|
||||||
#include "mozilla/AutoRestore.h"
|
#include "mozilla/AutoRestore.h"
|
||||||
#include "mozilla/EditorBase.h"
|
#include "mozilla/EditorBase.h"
|
||||||
#include "mozilla/EventListenerManager.h"
|
#include "mozilla/EventListenerManager.h"
|
||||||
#include "mozilla/EventStateManager.h"
|
#include "mozilla/EventStateManager.h"
|
||||||
#include "mozilla/HTMLEditor.h"
|
#include "mozilla/HTMLEditor.h"
|
||||||
|
#include "mozilla/Logging.h"
|
||||||
#include "mozilla/MouseEvents.h"
|
#include "mozilla/MouseEvents.h"
|
||||||
#include "mozilla/PresShell.h"
|
#include "mozilla/PresShell.h"
|
||||||
|
#include "mozilla/RefPtr.h"
|
||||||
#include "mozilla/StaticPrefs_dom.h"
|
#include "mozilla/StaticPrefs_dom.h"
|
||||||
#include "mozilla/StaticPrefs_intl.h"
|
#include "mozilla/StaticPrefs_intl.h"
|
||||||
#include "mozilla/TextComposition.h"
|
#include "mozilla/TextComposition.h"
|
||||||
|
|
@ -27,12 +28,11 @@
|
||||||
#include "mozilla/dom/Document.h"
|
#include "mozilla/dom/Document.h"
|
||||||
#include "mozilla/dom/Element.h"
|
#include "mozilla/dom/Element.h"
|
||||||
#include "mozilla/dom/HTMLFormElement.h"
|
#include "mozilla/dom/HTMLFormElement.h"
|
||||||
|
#include "mozilla/dom/HTMLInputElement.h"
|
||||||
#include "mozilla/dom/HTMLTextAreaElement.h"
|
#include "mozilla/dom/HTMLTextAreaElement.h"
|
||||||
#include "mozilla/dom/MouseEventBinding.h"
|
#include "mozilla/dom/MouseEventBinding.h"
|
||||||
#include "mozilla/dom/UserActivation.h"
|
#include "mozilla/dom/UserActivation.h"
|
||||||
|
#include "mozilla/widget/IMEData.h"
|
||||||
#include "HTMLInputElement.h"
|
|
||||||
#include "IMEContentObserver.h"
|
|
||||||
|
|
||||||
#include "nsCOMPtr.h"
|
#include "nsCOMPtr.h"
|
||||||
#include "nsContentUtils.h"
|
#include "nsContentUtils.h"
|
||||||
|
|
@ -822,15 +822,9 @@ void IMEStateManager::OnClickInEditor(nsPresContext& aPresContext,
|
||||||
|
|
||||||
const OwningNonNull<nsIWidget> textInputHandlingWidget =
|
const OwningNonNull<nsIWidget> textInputHandlingWidget =
|
||||||
*sTextInputHandlingWidget;
|
*sTextInputHandlingWidget;
|
||||||
|
MOZ_ASSERT_IF(sFocusedPresContext->GetTextInputHandlingWidget(),
|
||||||
#ifdef DEBUG
|
sFocusedPresContext->GetTextInputHandlingWidget() ==
|
||||||
{
|
textInputHandlingWidget.get());
|
||||||
nsCOMPtr<nsIWidget> currentTextInputHandlingWidget =
|
|
||||||
sFocusedPresContext->GetTextInputHandlingWidget();
|
|
||||||
MOZ_ASSERT(!currentTextInputHandlingWidget ||
|
|
||||||
currentTextInputHandlingWidget == textInputHandlingWidget);
|
|
||||||
}
|
|
||||||
#endif // DEBUG
|
|
||||||
|
|
||||||
if (!aMouseEvent.IsTrusted()) {
|
if (!aMouseEvent.IsTrusted()) {
|
||||||
MOZ_LOG(sISMLog, LogLevel::Debug,
|
MOZ_LOG(sISMLog, LogLevel::Debug,
|
||||||
|
|
@ -1103,15 +1097,9 @@ void IMEStateManager::MaybeOnEditableStateDisabled(nsPresContext& aPresContext,
|
||||||
|
|
||||||
const OwningNonNull<nsIWidget> textInputHandlingWidget =
|
const OwningNonNull<nsIWidget> textInputHandlingWidget =
|
||||||
*sTextInputHandlingWidget;
|
*sTextInputHandlingWidget;
|
||||||
|
MOZ_ASSERT_IF(sFocusedPresContext->GetTextInputHandlingWidget(),
|
||||||
#ifdef DEBUG
|
sFocusedPresContext->GetTextInputHandlingWidget() ==
|
||||||
{
|
textInputHandlingWidget.get());
|
||||||
nsCOMPtr<nsIWidget> currentTextInputHandlingWidget =
|
|
||||||
aPresContext.GetTextInputHandlingWidget();
|
|
||||||
MOZ_ASSERT(!currentTextInputHandlingWidget ||
|
|
||||||
currentTextInputHandlingWidget == textInputHandlingWidget);
|
|
||||||
}
|
|
||||||
#endif // DEBUG
|
|
||||||
|
|
||||||
const IMEState newIMEState = GetNewIMEState(aPresContext, aElement);
|
const IMEState newIMEState = GetNewIMEState(aPresContext, aElement);
|
||||||
// If IME state becomes editable, HTMLEditor should also be initialized with
|
// If IME state becomes editable, HTMLEditor should also be initialized with
|
||||||
|
|
@ -1222,15 +1210,9 @@ void IMEStateManager::UpdateIMEState(const IMEState& aNewIMEState,
|
||||||
|
|
||||||
const OwningNonNull<nsIWidget> textInputHandlingWidget =
|
const OwningNonNull<nsIWidget> textInputHandlingWidget =
|
||||||
*sTextInputHandlingWidget;
|
*sTextInputHandlingWidget;
|
||||||
|
MOZ_ASSERT_IF(sFocusedPresContext->GetTextInputHandlingWidget(),
|
||||||
#ifdef DEBUG
|
sFocusedPresContext->GetTextInputHandlingWidget() ==
|
||||||
{
|
textInputHandlingWidget.get());
|
||||||
nsCOMPtr<nsIWidget> currentTextInputHandlingWidget =
|
|
||||||
sFocusedPresContext->GetTextInputHandlingWidget();
|
|
||||||
MOZ_ASSERT(!currentTextInputHandlingWidget ||
|
|
||||||
currentTextInputHandlingWidget == textInputHandlingWidget);
|
|
||||||
}
|
|
||||||
#endif // DEBUG
|
|
||||||
|
|
||||||
// TODO: Investigate if we could put off to initialize IMEContentObserver
|
// TODO: Investigate if we could put off to initialize IMEContentObserver
|
||||||
// later because a lot of callers need to be marked as
|
// later because a lot of callers need to be marked as
|
||||||
|
|
@ -1509,14 +1491,9 @@ void IMEStateManager::SetInputContextForChildProcess(
|
||||||
|
|
||||||
const OwningNonNull<nsIWidget> textInputHandlingWidget =
|
const OwningNonNull<nsIWidget> textInputHandlingWidget =
|
||||||
*sTextInputHandlingWidget;
|
*sTextInputHandlingWidget;
|
||||||
#ifdef DEBUG
|
MOZ_ASSERT_IF(sFocusedPresContext->GetTextInputHandlingWidget(),
|
||||||
{
|
sFocusedPresContext->GetTextInputHandlingWidget() ==
|
||||||
nsCOMPtr<nsIWidget> currentTextInputHandlingWidget =
|
textInputHandlingWidget.get());
|
||||||
sFocusedPresContext->GetTextInputHandlingWidget();
|
|
||||||
MOZ_ASSERT(!currentTextInputHandlingWidget ||
|
|
||||||
currentTextInputHandlingWidget == textInputHandlingWidget);
|
|
||||||
}
|
|
||||||
#endif // DEBUG
|
|
||||||
MOZ_ASSERT(aInputContext.mOrigin == InputContext::ORIGIN_CONTENT);
|
MOZ_ASSERT(aInputContext.mOrigin == InputContext::ORIGIN_CONTENT);
|
||||||
|
|
||||||
sActiveChildInputContext = aInputContext;
|
sActiveChildInputContext = aInputContext;
|
||||||
|
|
@ -2074,6 +2051,11 @@ nsresult IMEStateManager::NotifyIME(const IMENotification& aNotification,
|
||||||
nsCOMPtr<nsIWidget> browserParentWidget =
|
nsCOMPtr<nsIWidget> browserParentWidget =
|
||||||
aBrowserParent->GetTextInputHandlingWidget();
|
aBrowserParent->GetTextInputHandlingWidget();
|
||||||
MOZ_ASSERT(browserParentWidget == aWidget);
|
MOZ_ASSERT(browserParentWidget == aWidget);
|
||||||
|
} else {
|
||||||
|
MOZ_ASSERT(sFocusedPresContext);
|
||||||
|
MOZ_ASSERT_IF(
|
||||||
|
sFocusedPresContext->GetTextInputHandlingWidget(),
|
||||||
|
sFocusedPresContext->GetTextInputHandlingWidget() == aWidget);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
sFocusedIMEBrowserParent = aBrowserParent;
|
sFocusedIMEBrowserParent = aBrowserParent;
|
||||||
|
|
@ -2197,16 +2179,30 @@ nsresult IMEStateManager::NotifyIME(IMEMessage aMessage,
|
||||||
MOZ_LOG(sISMLog, LogLevel::Info,
|
MOZ_LOG(sISMLog, LogLevel::Info,
|
||||||
("NotifyIME(aMessage=%s, aPresContext=0x%p, aBrowserParent=0x%p)",
|
("NotifyIME(aMessage=%s, aPresContext=0x%p, aBrowserParent=0x%p)",
|
||||||
ToChar(aMessage), aPresContext, aBrowserParent));
|
ToChar(aMessage), aPresContext, aBrowserParent));
|
||||||
|
// This assertion is just for clarify which message may be set, so feel free
|
||||||
|
// to add other messages if you want.
|
||||||
|
MOZ_ASSERT(aMessage == REQUEST_TO_CANCEL_COMPOSITION ||
|
||||||
|
aMessage == REQUEST_TO_COMMIT_COMPOSITION ||
|
||||||
|
aMessage == NOTIFY_IME_OF_COMPOSITION_EVENT_HANDLED);
|
||||||
|
// However, these messages require additional information. Therefore, this
|
||||||
|
// overload shouldn't be used for them.
|
||||||
|
MOZ_ASSERT(aMessage != NOTIFY_IME_OF_FOCUS &&
|
||||||
|
aMessage != NOTIFY_IME_OF_BLUR &&
|
||||||
|
aMessage != NOTIFY_IME_OF_TEXT_CHANGE &&
|
||||||
|
aMessage != NOTIFY_IME_OF_SELECTION_CHANGE &&
|
||||||
|
aMessage != NOTIFY_IME_OF_MOUSE_BUTTON_EVENT);
|
||||||
|
|
||||||
if (NS_WARN_IF(!CanHandleWith(aPresContext))) {
|
if (NS_WARN_IF(!CanHandleWith(aPresContext))) {
|
||||||
return NS_ERROR_INVALID_ARG;
|
return NS_ERROR_INVALID_ARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsCOMPtr<nsIWidget> widget = aPresContext->GetTextInputHandlingWidget();
|
nsCOMPtr<nsIWidget> widget =
|
||||||
|
aPresContext == sFocusedPresContext && sTextInputHandlingWidget
|
||||||
|
? sTextInputHandlingWidget
|
||||||
|
: aPresContext->GetTextInputHandlingWidget();
|
||||||
if (NS_WARN_IF(!widget)) {
|
if (NS_WARN_IF(!widget)) {
|
||||||
MOZ_LOG(sISMLog, LogLevel::Error,
|
MOZ_LOG(sISMLog, LogLevel::Error,
|
||||||
(" NotifyIME(), FAILED due to no widget for the "
|
(" NotifyIME(), FAILED due to no widget for the nsPresContext"));
|
||||||
"nsPresContext"));
|
|
||||||
return NS_ERROR_NOT_AVAILABLE;
|
return NS_ERROR_NOT_AVAILABLE;
|
||||||
}
|
}
|
||||||
return NotifyIME(aMessage, widget, aBrowserParent);
|
return NotifyIME(aMessage, widget, aBrowserParent);
|
||||||
|
|
@ -2314,14 +2310,9 @@ void IMEStateManager::CreateIMEContentObserver(EditorBase& aEditorBase,
|
||||||
|
|
||||||
const OwningNonNull<nsIWidget> textInputHandlingWidget =
|
const OwningNonNull<nsIWidget> textInputHandlingWidget =
|
||||||
*sTextInputHandlingWidget;
|
*sTextInputHandlingWidget;
|
||||||
|
MOZ_ASSERT_IF(sFocusedPresContext->GetTextInputHandlingWidget(),
|
||||||
#ifdef DEBUG
|
sFocusedPresContext->GetTextInputHandlingWidget() ==
|
||||||
{
|
textInputHandlingWidget.get());
|
||||||
nsCOMPtr<nsIWidget> currentTextInputHandlingWidget =
|
|
||||||
sFocusedPresContext->GetTextInputHandlingWidget();
|
|
||||||
MOZ_ASSERT(currentTextInputHandlingWidget == textInputHandlingWidget);
|
|
||||||
}
|
|
||||||
#endif // DEBUG
|
|
||||||
|
|
||||||
MOZ_LOG(sISMLog, LogLevel::Debug,
|
MOZ_LOG(sISMLog, LogLevel::Debug,
|
||||||
(" CreateIMEContentObserver() is creating an "
|
(" CreateIMEContentObserver() is creating an "
|
||||||
|
|
|
||||||
|
|
@ -125,6 +125,14 @@ class IMEStateManager {
|
||||||
return sActiveInputContextWidget;
|
return sActiveInputContextWidget;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a widget which is for handling text input. This should be valid
|
||||||
|
* while an editable element has focus or an editable document has focus.
|
||||||
|
*/
|
||||||
|
static nsIWidget* GetWidgetForTextInputHandling() {
|
||||||
|
return sTextInputHandlingWidget;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SetIMEContextForChildProcess() is called when aBrowserParent receives
|
* SetIMEContextForChildProcess() is called when aBrowserParent receives
|
||||||
* SetInputContext() from the remote process.
|
* SetInputContext() from the remote process.
|
||||||
|
|
|
||||||
|
|
@ -652,11 +652,7 @@ nsresult EditorEventListener::KeyPress(WidgetKeyboardEvent* aKeyboardEvent) {
|
||||||
return aKeyboardEvent->mWidget;
|
return aKeyboardEvent->mWidget;
|
||||||
}
|
}
|
||||||
// If the event is created by chrome script, the widget is always nullptr.
|
// If the event is created by chrome script, the widget is always nullptr.
|
||||||
nsPresContext* presContext = GetPresContext();
|
return IMEStateManager::GetWidgetForTextInputHandling();
|
||||||
if (NS_WARN_IF(!presContext)) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
return presContext->GetTextInputHandlingWidget();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if (DetachedFromEditor()) {
|
if (DetachedFromEditor()) {
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
<!doctype html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<style>
|
||||||
|
*::first-letter {}
|
||||||
|
</style>
|
||||||
|
<script>
|
||||||
|
addEventListener("load", () => {
|
||||||
|
const iframe = document.querySelector("iframe");
|
||||||
|
iframe.contentWindow.focus();
|
||||||
|
document.styleSheets[0].deleteRule(0);
|
||||||
|
iframe.contentWindow.document.designMode = "on";
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<iframe loading="lazy">
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
Loading…
Reference in a new issue