Bug 1770133 - part 4: Make `IMEContentObserver` use `dom::Element` instead of `nsIContent` for root r=m_kato

The root is always an element node.  So, it should take and store the root node
as `dom::Element` rather than `nsIContent`.

Differential Revision: https://phabricator.services.mozilla.com/D147135
This commit is contained in:
Masayuki Nakano 2022-05-26 07:03:20 +00:00
Родитель f93d054430
Коммит 6440fbddc3
8 изменённых файлов: 163 добавлений и 157 удалений

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

@ -2124,7 +2124,7 @@ nsDOMWindowUtils::GetNodeObservedByIMEContentObserver(nsINode** aNode) {
*aNode = nullptr;
return NS_OK;
}
*aNode = do_AddRef(observer->GetObservingContent()).take();
*aNode = do_AddRef(observer->GetObservingElement()).take();
return NS_OK;
}

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

@ -3029,9 +3029,11 @@ nsresult ContentEventHandler::OnSelectionEvent(WidgetSelectionEvent* aEvent) {
// XXX why do we need to get them from ISM? This method should work fine
// without ISM.
RefPtr<Selection> sel;
nsresult rv = IMEStateManager::GetFocusSelectionAndRoot(
getter_AddRefs(sel), getter_AddRefs(mRootContent));
RefPtr<Element> rootElement;
nsresult rv = IMEStateManager::GetFocusSelectionAndRootElement(
getter_AddRefs(sel), getter_AddRefs(rootElement));
mSelection = sel;
mRootContent = rootElement;
if (rv != NS_ERROR_NOT_AVAILABLE) {
NS_ENSURE_SUCCESS(rv, rv);
} else {

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

@ -85,7 +85,7 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(IMEContentObserver)
tmp->UnregisterObservers();
NS_IMPL_CYCLE_COLLECTION_UNLINK(mSelection)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mRootContent)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mRootElement)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mEditableNode)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocShell)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mEditorBase)
@ -102,7 +102,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(IMEContentObserver)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWidget)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFocusedWidget)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSelection)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mRootContent)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mRootElement)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mEditableNode)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocShell)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mEditorBase)
@ -143,7 +143,7 @@ IMEContentObserver::IMEContentObserver()
}
void IMEContentObserver::Init(nsIWidget& aWidget, nsPresContext& aPresContext,
nsIContent* aContent, EditorBase& aEditorBase) {
Element* aElement, EditorBase& aEditorBase) {
State state = GetState();
if (NS_WARN_IF(state == eState_Observing)) {
return; // Nothing to do.
@ -163,7 +163,7 @@ void IMEContentObserver::Init(nsIWidget& aWidget, nsPresContext& aPresContext,
mWidget = &aWidget;
mIMENotificationRequests = &mWidget->IMENotificationRequestsRef();
if (!InitWithEditor(aPresContext, aContent, aEditorBase)) {
if (!InitWithEditor(aPresContext, aElement, aEditorBase)) {
MOZ_LOG(sIMECOLog, LogLevel::Error,
("0x%p Init() FAILED, due to InitWithEditor() "
"failure",
@ -214,10 +214,10 @@ void IMEContentObserver::OnIMEReceivedFocus() {
// NOTIFY_IME_OF_FOCUS might cause recreating IMEContentObserver
// instance via IMEStateManager::UpdateIMEState(). So, this
// instance might already have been destroyed, check it.
if (!mRootContent) {
if (!mRootElement) {
MOZ_LOG(sIMECOLog, LogLevel::Warning,
("0x%p OnIMEReceivedFocus(), "
"but mRootContent has already been cleared, so does nothing",
"but mRootElement has already been cleared, so does nothing",
this));
return;
}
@ -235,9 +235,9 @@ void IMEContentObserver::OnIMEReceivedFocus() {
}
bool IMEContentObserver::InitWithEditor(nsPresContext& aPresContext,
nsIContent* aContent,
Element* aElement,
EditorBase& aEditorBase) {
mEditableNode = IMEStateManager::GetRootEditableNode(&aPresContext, aContent);
mEditableNode = IMEStateManager::GetRootEditableNode(aPresContext, aElement);
if (NS_WARN_IF(!mEditableNode)) {
return false;
}
@ -275,18 +275,20 @@ bool IMEContentObserver::InitWithEditor(nsPresContext& aPresContext,
}
nsCOMPtr<nsINode> startContainer = selRange->GetStartContainer();
mRootContent = startContainer->GetSelectionRootContent(presShell);
mRootElement = Element::FromNodeOrNull(
startContainer->GetSelectionRootContent(presShell));
} else {
nsCOMPtr<nsINode> editableNode = mEditableNode;
mRootContent = editableNode->GetSelectionRootContent(presShell);
mRootElement = Element::FromNodeOrNull(
editableNode->GetSelectionRootContent(presShell));
}
if (!mRootContent && mEditableNode->IsDocument()) {
if (!mRootElement && mEditableNode->IsDocument()) {
// The document node is editable, but there are no contents, this document
// is not editable.
return false;
}
if (NS_WARN_IF(!mRootContent)) {
if (NS_WARN_IF(!mRootElement)) {
return false;
}
@ -304,7 +306,7 @@ void IMEContentObserver::Clear() {
mEditorBase = nullptr;
mSelection = nullptr;
mEditableNode = nullptr;
mRootContent = nullptr;
mRootElement = nullptr;
mDocShell = nullptr;
// Should be safe to clear mDocumentObserver here even though it grabs
// this instance in most cases because this is called by Init() or Destroy().
@ -316,7 +318,7 @@ void IMEContentObserver::Clear() {
void IMEContentObserver::ObserveEditableNode() {
MOZ_RELEASE_ASSERT(mSelection);
MOZ_RELEASE_ASSERT(mRootContent);
MOZ_RELEASE_ASSERT(mRootElement);
MOZ_RELEASE_ASSERT(GetState() != eState_Observing);
// If this is called before sending NOTIFY_IME_OF_FOCUS (it's possible when
@ -336,10 +338,10 @@ void IMEContentObserver::ObserveEditableNode() {
mEditorBase->SetIMEContentObserver(this);
}
mRootContent->AddMutationObserver(this);
mRootElement->AddMutationObserver(this);
// If it's in a document (should be so), we can use document observer to
// reduce redundant computation of text change offsets.
Document* doc = mRootContent->GetComposedDoc();
Document* doc = mRootElement->GetComposedDoc();
if (doc) {
RefPtr<DocumentObserver> documentObserver = mDocumentObserver;
documentObserver->Observe(doc);
@ -402,8 +404,8 @@ void IMEContentObserver::UnregisterObservers() {
mFocusedWidget = nullptr;
}
if (mRootContent) {
mRootContent->RemoveMutationObserver(this);
if (mRootElement) {
mRootElement->RemoveMutationObserver(this);
}
if (mDocumentObserver) {
@ -446,62 +448,62 @@ void IMEContentObserver::DisconnectFromEventStateManager() { mESM = nullptr; }
bool IMEContentObserver::MaybeReinitialize(nsIWidget& aWidget,
nsPresContext& aPresContext,
nsIContent* aContent,
Element* aElement,
EditorBase& aEditorBase) {
if (!IsObservingContent(&aPresContext, aContent)) {
if (!IsObservingContent(aPresContext, aElement)) {
return false;
}
if (GetState() == eState_StoppedObserving) {
Init(aWidget, aPresContext, aContent, aEditorBase);
Init(aWidget, aPresContext, aElement, aEditorBase);
}
return IsManaging(&aPresContext, aContent);
return IsManaging(aPresContext, aElement);
}
bool IMEContentObserver::IsManaging(nsPresContext* aPresContext,
nsIContent* aContent) const {
bool IMEContentObserver::IsManaging(const nsPresContext& aPresContext,
const Element* aElement) const {
return GetState() == eState_Observing &&
IsObservingContent(aPresContext, aContent);
IsObservingContent(aPresContext, aElement);
}
bool IMEContentObserver::IsBeingInitializedFor(nsPresContext* aPresContext,
nsIContent* aContent) const {
bool IMEContentObserver::IsBeingInitializedFor(
const nsPresContext& aPresContext, const Element* aElement) const {
return GetState() == eState_Initializing &&
IsObservingContent(aPresContext, aContent);
IsObservingContent(aPresContext, aElement);
}
bool IMEContentObserver::IsManaging(const TextComposition* aComposition) const {
bool IMEContentObserver::IsManaging(
const TextComposition& aTextComposition) const {
if (GetState() != eState_Observing) {
return false;
}
nsPresContext* presContext = aComposition->GetPresContext();
nsPresContext* const presContext = aTextComposition.GetPresContext();
if (NS_WARN_IF(!presContext)) {
return false;
}
if (presContext != GetPresContext()) {
return false; // observing different document
}
nsINode* targetNode = aComposition->GetEventTargetNode();
nsIContent* targetContent =
targetNode && targetNode->IsContent() ? targetNode->AsContent() : nullptr;
return IsObservingContent(presContext, targetContent);
return IsObservingContent(
*presContext,
Element::FromNodeOrNull(aTextComposition.GetEventTargetNode()));
}
IMEContentObserver::State IMEContentObserver::GetState() const {
if (!mSelection || !mRootContent || !mEditableNode) {
if (!mSelection || !mRootElement || !mEditableNode) {
return eState_NotObserving; // failed to initialize or finalized.
}
if (!mRootContent->IsInComposedDoc()) {
if (!mRootElement->IsInComposedDoc()) {
// the focused editor has already been reframed.
return eState_StoppedObserving;
}
return mIsObserving ? eState_Observing : eState_Initializing;
}
bool IMEContentObserver::IsObservingContent(nsPresContext* aPresContext,
nsIContent* aContent) const {
bool IMEContentObserver::IsObservingContent(const nsPresContext& aPresContext,
const Element* aElement) const {
return mEditableNode ==
IMEStateManager::GetRootEditableNode(aPresContext, aContent);
IMEStateManager::GetRootEditableNode(aPresContext, aElement);
}
bool IMEContentObserver::IsEditorHandlingEventForComposition() const {
@ -527,15 +529,15 @@ bool IMEContentObserver::IsEditorComposing() const {
return mEditorBase->IsIMEComposing();
}
nsresult IMEContentObserver::GetSelectionAndRoot(
Selection** aSelection, nsIContent** aRootContent) const {
nsresult IMEContentObserver::GetSelectionAndRoot(Selection** aSelection,
Element** aRootElement) const {
if (!mEditableNode || !mSelection) {
return NS_ERROR_NOT_AVAILABLE;
}
NS_ASSERTION(mSelection && mRootContent, "uninitialized content observer");
NS_ASSERTION(mSelection && mRootElement, "uninitialized content observer");
NS_ADDREF(*aSelection = mSelection);
NS_ADDREF(*aRootContent = mRootContent);
NS_ADDREF(*aRootElement = mRootElement);
return NS_OK;
}
@ -605,7 +607,7 @@ nsresult IMEContentObserver::HandleQueryContentEvent(
OffsetAndDataFor::SelectedString);
aEvent->mReply->mReversed = mSelectionData.mReversed;
}
aEvent->mReply->mContentsRoot = mRootContent;
aEvent->mReply->mContentsRoot = mRootElement;
aEvent->mReply->mWritingMode = mSelectionData.GetWritingMode();
// The selection cache in IMEContentObserver must always have been in
// an editing host (or an editable annoymous <div> element). Therefore,
@ -667,25 +669,25 @@ nsresult IMEContentObserver::HandleQueryContentEvent(
}
if (aEvent->Succeeded() &&
NS_WARN_IF(aEvent->mReply->mContentsRoot != mRootContent)) {
NS_WARN_IF(aEvent->mReply->mContentsRoot != mRootElement)) {
// Focus has changed unexpectedly, so make the query fail.
aEvent->mReply.reset();
}
return rv;
}
bool IMEContentObserver::OnMouseButtonEvent(nsPresContext* aPresContext,
WidgetMouseEvent* aMouseEvent) {
bool IMEContentObserver::OnMouseButtonEvent(nsPresContext& aPresContext,
WidgetMouseEvent& aMouseEvent) {
if (!mIMENotificationRequests ||
!mIMENotificationRequests->WantMouseButtonEventOnChar()) {
return false;
}
if (!aMouseEvent->IsTrusted() || aMouseEvent->DefaultPrevented() ||
!aMouseEvent->mWidget) {
if (!aMouseEvent.IsTrusted() || aMouseEvent.DefaultPrevented() ||
!aMouseEvent.mWidget) {
return false;
}
// Now, we need to notify only mouse down and mouse up event.
switch (aMouseEvent->mMessage) {
switch (aMouseEvent.mMessage) {
case eMouseUp:
case eMouseDown:
break;
@ -696,12 +698,10 @@ bool IMEContentObserver::OnMouseButtonEvent(nsPresContext* aPresContext,
return false;
}
RefPtr<IMEContentObserver> kungFuDeathGrip(this);
WidgetQueryContentEvent queryCharAtPointEvent(true, eQueryCharacterAtPoint,
aMouseEvent->mWidget);
queryCharAtPointEvent.mRefPoint = aMouseEvent->mRefPoint;
ContentEventHandler handler(aPresContext);
aMouseEvent.mWidget);
queryCharAtPointEvent.mRefPoint = aMouseEvent.mRefPoint;
ContentEventHandler handler(&aPresContext);
handler.OnQueryCharacterAtPoint(&queryCharAtPointEvent);
if (NS_WARN_IF(queryCharAtPointEvent.Failed()) ||
queryCharAtPointEvent.DidNotFindChar()) {
@ -724,23 +724,23 @@ bool IMEContentObserver::OnMouseButtonEvent(nsPresContext* aPresContext,
}
// The refPt is relative to its widget.
// We should notify it with offset in the widget.
if (aMouseEvent->mWidget != mWidget) {
if (aMouseEvent.mWidget != mWidget) {
queryCharAtPointEvent.mRefPoint +=
aMouseEvent->mWidget->WidgetToScreenOffset() -
aMouseEvent.mWidget->WidgetToScreenOffset() -
mWidget->WidgetToScreenOffset();
}
IMENotification notification(NOTIFY_IME_OF_MOUSE_BUTTON_EVENT);
notification.mMouseButtonEventData.mEventMessage = aMouseEvent->mMessage;
notification.mMouseButtonEventData.mEventMessage = aMouseEvent.mMessage;
notification.mMouseButtonEventData.mOffset =
queryCharAtPointEvent.mReply->StartOffset();
notification.mMouseButtonEventData.mCursorPos =
queryCharAtPointEvent.mRefPoint;
notification.mMouseButtonEventData.mCharRect =
queryCharAtPointEvent.mReply->mRect;
notification.mMouseButtonEventData.mButton = aMouseEvent->mButton;
notification.mMouseButtonEventData.mButtons = aMouseEvent->mButtons;
notification.mMouseButtonEventData.mModifiers = aMouseEvent->mModifiers;
notification.mMouseButtonEventData.mButton = aMouseEvent.mButton;
notification.mMouseButtonEventData.mButtons = aMouseEvent.mButtons;
notification.mMouseButtonEventData.mModifiers = aMouseEvent.mModifiers;
nsresult rv = IMEStateManager::NotifyIME(notification, mWidget);
if (NS_WARN_IF(NS_FAILED(rv))) {
@ -749,7 +749,7 @@ bool IMEContentObserver::OnMouseButtonEvent(nsPresContext* aPresContext,
bool consumed = (rv == NS_SUCCESS_EVENT_CONSUMED);
if (consumed) {
aMouseEvent->PreventDefault();
aMouseEvent.PreventDefault();
}
return consumed;
}
@ -765,7 +765,7 @@ void IMEContentObserver::CharacterDataWillChange(
"mPreCharacterDataChangeLength");
if (!NeedsTextChangeNotification() ||
!nsContentUtils::IsInSameAnonymousTree(mRootContent, aContent)) {
!nsContentUtils::IsInSameAnonymousTree(mRootElement, aContent)) {
return;
}
@ -802,7 +802,7 @@ void IMEContentObserver::CharacterDataChanged(
}
if (!NeedsTextChangeNotification() ||
!nsContentUtils::IsInSameAnonymousTree(mRootContent, aContent)) {
!nsContentUtils::IsInSameAnonymousTree(mRootElement, aContent)) {
return;
}
@ -822,8 +822,8 @@ void IMEContentObserver::CharacterDataChanged(
uint32_t offset = 0;
// get offsets of change and fire notification
nsresult rv = ContentEventHandler::GetFlatTextLengthInRange(
NodePosition(mRootContent, 0u),
NodePosition(aContent, aInfo.mChangeStart), mRootContent, &offset,
NodePosition(mRootElement, 0u),
NodePosition(aContent, aInfo.mChangeStart), mRootElement, &offset,
LINE_BREAK_TYPE_NATIVE);
if (NS_WARN_IF(NS_FAILED(rv))) {
return;
@ -846,7 +846,7 @@ void IMEContentObserver::NotifyContentAdded(nsINode* aContainer,
nsIContent* aFirstContent,
nsIContent* aLastContent) {
if (!NeedsTextChangeNotification() ||
!nsContentUtils::IsInSameAnonymousTree(mRootContent, aFirstContent)) {
!nsContentUtils::IsInSameAnonymousTree(mRootElement, aFirstContent)) {
return;
}
@ -899,9 +899,9 @@ void IMEContentObserver::NotifyContentAdded(nsINode* aContainer,
aFirstContent->GetPreviousSibling())) {
mEndOfAddedTextCache.Clear();
rv = ContentEventHandler::GetFlatTextLengthInRange(
NodePosition(mRootContent, 0u),
NodePosition(mRootElement, 0u),
NodePositionBefore(aContainer, PointBefore(aContainer, aFirstContent)),
mRootContent, &offset, LINE_BREAK_TYPE_NATIVE);
mRootElement, &offset, LINE_BREAK_TYPE_NATIVE);
if (NS_WARN_IF(NS_FAILED((rv)))) {
return;
}
@ -913,7 +913,7 @@ void IMEContentObserver::NotifyContentAdded(nsINode* aContainer,
uint32_t addingLength = 0;
rv = ContentEventHandler::GetFlatTextLengthInRange(
NodePositionBefore(aContainer, PointBefore(aContainer, aFirstContent)),
NodePosition(aContainer, aLastContent), mRootContent, &addingLength,
NodePosition(aContainer, aLastContent), mRootElement, &addingLength,
LINE_BREAK_TYPE_NATIVE);
if (NS_WARN_IF(NS_FAILED((rv)))) {
mEndOfAddedTextCache.Clear();
@ -950,7 +950,7 @@ void IMEContentObserver::ContentInserted(nsIContent* aChild) {
void IMEContentObserver::ContentRemoved(nsIContent* aChild,
nsIContent* aPreviousSibling) {
if (!NeedsTextChangeNotification() ||
!nsContentUtils::IsInSameAnonymousTree(mRootContent, aChild)) {
!nsContentUtils::IsInSameAnonymousTree(mRootElement, aChild)) {
return;
}
@ -967,8 +967,8 @@ void IMEContentObserver::ContentRemoved(nsIContent* aChild,
// by open tag of aContainer. Be careful when aPreviousSibling is nullptr.
rv = ContentEventHandler::GetFlatTextLengthInRange(
NodePosition(mRootContent, 0u),
NodePosition(containerNode, aPreviousSibling), mRootContent, &offset,
NodePosition(mRootElement, 0u),
NodePosition(containerNode, aPreviousSibling), mRootElement, &offset,
LINE_BREAK_TYPE_NATIVE);
if (NS_WARN_IF(NS_FAILED(rv))) {
mStartOfRemovingTextRangeCache.Clear();
@ -987,7 +987,7 @@ void IMEContentObserver::ContentRemoved(nsIContent* aChild,
} else {
nsresult rv = ContentEventHandler::GetFlatTextLengthInRange(
NodePositionBefore(aChild, 0u),
NodePosition(aChild, aChild->GetChildCount()), mRootContent,
NodePosition(aChild, aChild->GetChildCount()), mRootElement,
&textLength, LINE_BREAK_TYPE_NATIVE, true);
if (NS_WARN_IF(NS_FAILED(rv))) {
mStartOfRemovingTextRangeCache.Clear();
@ -1018,7 +1018,7 @@ bool IMEContentObserver::IsNextNodeOfLastAddedNode(nsINode* aParent,
nsIContent* aChild) const {
MOZ_ASSERT(aParent);
MOZ_ASSERT(aChild && aChild->GetParentNode() == aParent);
MOZ_ASSERT(mRootContent);
MOZ_ASSERT(mRootElement);
MOZ_ASSERT(HasAddedNodesDuringDocumentChange());
// If the parent node isn't changed, we can check that mLastAddedContent has
@ -1047,7 +1047,7 @@ bool IMEContentObserver::IsNextNodeOfLastAddedNode(nsINode* aParent,
// Otherwise, we need to check it even with slow path.
nsIContent* nextContentOfLastAddedContent =
mLastAddedContent->GetNextNode(mRootContent->GetParentNode());
mLastAddedContent->GetNextNode(mRootElement->GetParentNode());
if (NS_WARN_IF(!nextContentOfLastAddedContent)) {
return false;
}
@ -1074,10 +1074,10 @@ void IMEContentObserver::MaybeNotifyIMEOfAddedTextDuringDocumentChange() {
// editor.
uint32_t offset;
nsresult rv = ContentEventHandler::GetFlatTextLengthInRange(
NodePosition(mRootContent, 0u),
NodePosition(mRootElement, 0u),
NodePosition(mFirstAddedContainer,
PointBefore(mFirstAddedContainer, mFirstAddedContent)),
mRootContent, &offset, LINE_BREAK_TYPE_NATIVE);
mRootElement, &offset, LINE_BREAK_TYPE_NATIVE);
if (NS_WARN_IF(NS_FAILED(rv))) {
ClearAddedNodesDuringDocumentChange();
return;
@ -1088,7 +1088,7 @@ void IMEContentObserver::MaybeNotifyIMEOfAddedTextDuringDocumentChange() {
rv = ContentEventHandler::GetFlatTextLengthInRange(
NodePosition(mFirstAddedContainer,
PointBefore(mFirstAddedContainer, mFirstAddedContent)),
NodePosition(mLastAddedContainer, mLastAddedContent), mRootContent,
NodePosition(mLastAddedContainer, mLastAddedContent), mRootElement,
&length, LINE_BREAK_TYPE_NATIVE);
if (NS_WARN_IF(NS_FAILED(rv))) {
ClearAddedNodesDuringDocumentChange();
@ -1289,7 +1289,7 @@ bool IMEContentObserver::UpdateSelectionCache(bool aRequireFlush /* = true */) {
handler.OnQuerySelectedText(&querySelectedTextEvent);
if (NS_WARN_IF(querySelectedTextEvent.Failed()) ||
NS_WARN_IF(querySelectedTextEvent.mReply->mContentsRoot !=
mRootContent)) {
mRootElement)) {
return false;
}

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

@ -9,6 +9,7 @@
#include "mozilla/Attributes.h"
#include "mozilla/EditorBase.h"
#include "mozilla/dom/Element.h"
#include "mozilla/dom/Selection.h"
#include "nsCOMPtr.h"
#include "nsCycleCollectionParticipant.h"
@ -67,8 +68,8 @@ class IMEContentObserver final : public nsStubMutationObserver,
*/
void OnSelectionChange(dom::Selection& aSelection);
MOZ_CAN_RUN_SCRIPT bool OnMouseButtonEvent(nsPresContext* aPresContext,
WidgetMouseEvent* aMouseEvent);
MOZ_CAN_RUN_SCRIPT bool OnMouseButtonEvent(nsPresContext& aPresContext,
WidgetMouseEvent& aMouseEvent);
MOZ_CAN_RUN_SCRIPT nsresult
HandleQueryContentEvent(WidgetQueryContentEvent* aEvent);
@ -81,12 +82,12 @@ class IMEContentObserver final : public nsStubMutationObserver,
*
* @param aWidget The widget which can access native IME.
* @param aPresContext The PresContext which has aContent.
* @param aContent An editable element or nullptr if this will observe
* @param aElement An editable element or nullptr if this will observe
* design mode document.
* @param aEditorBase The editor which is associated with aContent.
*/
MOZ_CAN_RUN_SCRIPT void Init(nsIWidget& aWidget, nsPresContext& aPresContext,
nsIContent* aContent, EditorBase& aEditorBase);
dom::Element* aElement, EditorBase& aEditorBase);
/**
* Destroy() finalizes the instance, i.e., stops observing contents and
@ -121,13 +122,14 @@ class IMEContentObserver final : public nsStubMutationObserver,
*/
MOZ_CAN_RUN_SCRIPT bool MaybeReinitialize(nsIWidget& aWidget,
nsPresContext& aPresContext,
nsIContent* aContent,
dom::Element* aElement,
EditorBase& aEditorBase);
bool IsManaging(nsPresContext* aPresContext, nsIContent* aContent) const;
bool IsBeingInitializedFor(nsPresContext* aPresContext,
nsIContent* aContent) const;
bool IsManaging(const TextComposition* aTextComposition) const;
bool IsManaging(const nsPresContext& aPresContext,
const dom::Element* aElement) const;
bool IsBeingInitializedFor(const nsPresContext& aPresContext,
const dom::Element* aElement) const;
bool IsManaging(const TextComposition& aTextComposition) const;
bool WasInitializedWith(const EditorBase& aEditorBase) const {
return mEditorBase == &aEditorBase;
}
@ -141,7 +143,7 @@ class IMEContentObserver final : public nsStubMutationObserver,
void UnsuppressNotifyingIME();
nsPresContext* GetPresContext() const;
nsresult GetSelectionAndRoot(dom::Selection** aSelection,
nsIContent** aRoot) const;
dom::Element** aRootElement) const;
/**
* TryToFlushPendingNotifications() should be called when pending events
@ -167,8 +169,8 @@ class IMEContentObserver final : public nsStubMutationObserver,
void BeforeEditAction();
void CancelEditAction();
nsIContent* GetObservingContent() const {
return mIsObserving ? mRootContent.get() : nullptr;
dom::Element* GetObservingElement() const {
return mIsObserving ? mRootElement.get() : nullptr;
}
private:
@ -182,15 +184,15 @@ class IMEContentObserver final : public nsStubMutationObserver,
};
State GetState() const;
MOZ_CAN_RUN_SCRIPT bool InitWithEditor(nsPresContext& aPresContext,
nsIContent* aContent,
dom::Element* aElement,
EditorBase& aEditorBase);
void OnIMEReceivedFocus();
void Clear();
bool IsObservingContent(nsPresContext* aPresContext,
nsIContent* aContent) const;
bool IsReflowLocked() const;
bool IsSafeToNotifyIME() const;
bool IsEditorComposing() const;
[[nodiscard]] bool IsObservingContent(const nsPresContext& aPresContext,
const dom::Element* aElement) const;
[[nodiscard]] bool IsReflowLocked() const;
[[nodiscard]] bool IsSafeToNotifyIME() const;
[[nodiscard]] bool IsEditorComposing() const;
// Following methods are called by DocumentObserver when
// beginning to update the contents and ending updating the contents.
@ -299,7 +301,7 @@ class IMEContentObserver final : public nsStubMutationObserver,
// On the other hand, mWidget is its parent which handles IME.
nsCOMPtr<nsIWidget> mFocusedWidget;
RefPtr<dom::Selection> mSelection;
nsCOMPtr<nsIContent> mRootContent;
RefPtr<dom::Element> mRootElement;
nsCOMPtr<nsINode> mEditableNode;
nsCOMPtr<nsIDocShell> mDocShell;
RefPtr<EditorBase> mEditorBase;

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

@ -4,9 +4,9 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/Logging.h"
#include "IMEStateManager.h"
#include "mozilla/IMEStateManager.h"
#include "mozilla/Logging.h"
#include "mozilla/Attributes.h"
#include "mozilla/AutoRestore.h"
@ -550,7 +550,7 @@ nsresult IMEStateManager::OnChangeFocusInternal(nsPresContext* aPresContext,
// Otherwise, i.e., new focused content is in this process, let's check
// whether the new focused content is already being managed by the
// active IME content observer.
else if (!sActiveIMEContentObserver->IsManaging(aPresContext, aElement)) {
else if (!sActiveIMEContentObserver->IsManaging(*aPresContext, aElement)) {
DestroyIMEContentObserver();
}
}
@ -733,7 +733,7 @@ bool IMEStateManager::OnMouseButtonEventInEditor(
return false;
}
if (!sActiveIMEContentObserver->IsManaging(&aPresContext, aElement)) {
if (!sActiveIMEContentObserver->IsManaging(aPresContext, aElement)) {
MOZ_LOG(sISMLog, LogLevel::Debug,
(" OnMouseButtonEventInEditor(), "
"the active IMEContentObserver isn't managing the editor"));
@ -741,7 +741,7 @@ bool IMEStateManager::OnMouseButtonEventInEditor(
}
OwningNonNull<IMEContentObserver> observer = *sActiveIMEContentObserver;
bool consumed = observer->OnMouseButtonEvent(&aPresContext, &aMouseEvent);
bool consumed = observer->OnMouseButtonEvent(aPresContext, aMouseEvent);
MOZ_LOG(sISMLog, LogLevel::Info,
(" OnMouseButtonEventInEditor(), "
"mouse event (mMessage=%s, mButton=%d) is %s",
@ -877,7 +877,7 @@ void IMEStateManager::OnFocusInEditor(nsPresContext& aPresContext,
// If the IMEContentObserver instance isn't managing the editor actually,
// we need to recreate the instance.
if (sActiveIMEContentObserver) {
if (sActiveIMEContentObserver->IsManaging(&aPresContext, aElement)) {
if (sActiveIMEContentObserver->IsManaging(aPresContext, aElement)) {
MOZ_LOG(
sISMLog, LogLevel::Debug,
(" OnFocusInEditor(), "
@ -887,7 +887,7 @@ void IMEStateManager::OnFocusInEditor(nsPresContext& aPresContext,
// If the IMEContentObserver has not finished initializing itself yet,
// we don't need to recreate it because the following
// TryToFlushPendingNotifications call must make it initialized.
if (!sActiveIMEContentObserver->IsBeingInitializedFor(&aPresContext,
if (!sActiveIMEContentObserver->IsBeingInitializedFor(aPresContext,
aElement)) {
DestroyIMEContentObserver();
}
@ -953,7 +953,7 @@ void IMEStateManager::OnReFocus(nsPresContext& aPresContext,
}
if (!sActiveIMEContentObserver ||
!sActiveIMEContentObserver->IsManaging(&aPresContext, &aElement)) {
!sActiveIMEContentObserver->IsManaging(aPresContext, &aElement)) {
MOZ_LOG(sISMLog, LogLevel::Debug,
(" OnReFocus(), there is no valid IMEContentObserver, so we don't "
"manage this. Ignore this"));
@ -1104,7 +1104,7 @@ void IMEStateManager::UpdateIMEState(const IMEState& aNewIMEState,
// editor correctly, we should recreate it.
const bool createTextStateManager =
(!sActiveIMEContentObserver ||
!sActiveIMEContentObserver->IsManaging(sFocusedPresContext, aElement));
!sActiveIMEContentObserver->IsManaging(*sFocusedPresContext, aElement));
const bool updateIMEState =
aOptions.contains(UpdateIMEStateOption::ForceUpdate) ||
@ -2003,39 +2003,37 @@ bool IMEStateManager::IsEditable(nsINode* node) {
}
// static
nsINode* IMEStateManager::GetRootEditableNode(const nsPresContext* aPresContext,
const nsIContent* aContent) {
if (aContent) {
nsINode* IMEStateManager::GetRootEditableNode(const nsPresContext& aPresContext,
const Element* aElement) {
if (aElement) {
// If the focused content is in design mode, return is composed document
// because aContent may be in UA widget shadow tree.
if (aContent->IsInDesignMode()) {
return aContent->GetComposedDoc();
// because aElement may be in UA widget shadow tree.
if (aElement->IsInDesignMode()) {
return aElement->GetComposedDoc();
}
nsINode* root = nullptr;
nsINode* node = const_cast<nsIContent*>(aContent);
while (node && IsEditable(node)) {
nsINode* candidateRootNode = const_cast<Element*>(aElement);
for (nsINode* node = candidateRootNode; node && IsEditable(node);
node = node->GetParentNode()) {
// If the node has independent selection like <input type="text"> or
// <textarea>, the node should be the root editable node for aContent.
// <textarea>, the node should be the root editable node for aElement.
// FYI: <select> element also has independent selection but IsEditable()
// returns false.
// XXX: If somebody adds new editable element which has independent
// selection but doesn't own editor, we'll need more checks here.
// XXX: If aContent is not in native anonymous subtree, checking
// XXX: If aElement is not in native anonymous subtree, checking
// independent selection must be wrong, see bug 1731005.
if (node->IsContent() && node->AsContent()->HasIndependentSelection()) {
return node;
}
root = node;
node = node->GetParentNode();
candidateRootNode = node;
}
return root;
return candidateRootNode;
}
if (aPresContext && aPresContext->Document() &&
aPresContext->Document()->IsInDesignMode()) {
return aPresContext->Document();
}
return nullptr;
return aPresContext.Document() && aPresContext.Document()->IsInDesignMode()
? aPresContext.Document()
: nullptr;
}
// static
@ -2078,16 +2076,16 @@ void IMEStateManager::CreateIMEContentObserver(EditorBase& aEditorBase,
GetBoolName(sTextInputHandlingWidget &&
!sTextInputHandlingWidget->Destroyed()),
sActiveIMEContentObserver.get(),
GetBoolName(sActiveIMEContentObserver
? sActiveIMEContentObserver->IsManaging(
sFocusedPresContext, sFocusedElement)
: false)));
GetBoolName(sActiveIMEContentObserver && sFocusedPresContext &&
sActiveIMEContentObserver->IsManaging(
*sFocusedPresContext, sFocusedElement))));
if (NS_WARN_IF(sActiveIMEContentObserver)) {
MOZ_LOG(sISMLog, LogLevel::Error,
(" CreateIMEContentObserver(), FAILED due to "
"there is already an active IMEContentObserver"));
MOZ_ASSERT(sActiveIMEContentObserver->IsManaging(sFocusedPresContext,
MOZ_ASSERT(sFocusedPresContext);
MOZ_ASSERT(sActiveIMEContentObserver->IsManaging(*sFocusedPresContext,
sFocusedElement));
return;
}
@ -2151,13 +2149,13 @@ void IMEStateManager::CreateIMEContentObserver(EditorBase& aEditorBase,
}
// static
nsresult IMEStateManager::GetFocusSelectionAndRoot(Selection** aSelection,
nsIContent** aRootContent) {
nsresult IMEStateManager::GetFocusSelectionAndRootElement(
Selection** aSelection, Element** aRootElement) {
if (!sActiveIMEContentObserver) {
return NS_ERROR_NOT_AVAILABLE;
}
return sActiveIMEContentObserver->GetSelectionAndRoot(aSelection,
aRootContent);
aRootElement);
}
// static

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

@ -182,8 +182,8 @@ class IMEStateManager {
// control compared to having the two methods incorporated into OnChangeFocus
// Get the focused editor's selection and root
static nsresult GetFocusSelectionAndRoot(dom::Selection** aSel,
nsIContent** aRoot);
static nsresult GetFocusSelectionAndRootElement(dom::Selection** aSel,
dom::Element** aRootElement);
// This method updates the current IME state. However, if the enabled state
// isn't changed by the new state, this method does nothing.
// Note that this method changes the IME state of the active element in the
@ -296,8 +296,8 @@ class IMEStateManager {
static nsresult NotifyIME(IMEMessage aMessage, nsPresContext* aPresContext,
BrowserParent* aBrowserParent = nullptr);
static nsINode* GetRootEditableNode(const nsPresContext* aPresContext,
const nsIContent* aContent);
static nsINode* GetRootEditableNode(const nsPresContext& aPresContext,
const dom::Element* aElement);
/**
* Returns active IMEContentObserver but may be nullptr if focused content

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

@ -545,7 +545,7 @@ uint32_t TextComposition::GetSelectionStartOffset() {
IMEStateManager::GetActiveContentObserver();
bool doQuerySelection = true;
if (contentObserver) {
if (contentObserver->IsManaging(this)) {
if (contentObserver->IsManaging(*this)) {
doQuerySelection = false;
contentObserver->HandleQueryContentEvent(&querySelectedTextEvent);
}
@ -621,7 +621,7 @@ void TextComposition::MaybeNotifyIMEOfCompositionEventHandled(
// event handled. Although, this is a bug but it should be okay since
// destroying IMEContentObserver notifies IME of blur. So, native IME
// handler can treat it as this notification too.
if (contentObserver && contentObserver->IsManaging(this)) {
if (contentObserver && contentObserver->IsManaging(*this)) {
contentObserver->MaybeNotifyCompositionEventHandled();
return;
}

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

@ -739,19 +739,23 @@ nsresult nsGenericHTMLElement::AfterSetAttr(
StaticPrefs::dom_forms_enterkeyhint())) {
nsPIDOMWindowOuter* window = OwnerDoc()->GetWindow();
if (window && window->GetFocusedElement() == this) {
IMEContentObserver* observer =
IMEStateManager::GetActiveContentObserver();
nsPresContext* presContext = GetPresContext(eForComposedDoc);
if (observer && observer->IsManaging(presContext, this)) {
if (RefPtr<EditorBase> editor =
nsContentUtils::GetActiveEditor(window)) {
IMEState newState;
editor->GetPreferredIMEState(&newState);
OwningNonNull<nsGenericHTMLElement> kungFuDeathGrip(*this);
IMEStateManager::UpdateIMEState(
newState, kungFuDeathGrip, *editor,
{IMEStateManager::UpdateIMEStateOption::ForceUpdate,
IMEStateManager::UpdateIMEStateOption::DontCommitComposition});
if (IMEContentObserver* observer =
IMEStateManager::GetActiveContentObserver()) {
if (const nsPresContext* presContext =
GetPresContext(eForComposedDoc)) {
if (observer->IsManaging(*presContext, this)) {
if (RefPtr<EditorBase> editor =
nsContentUtils::GetActiveEditor(window)) {
IMEState newState;
editor->GetPreferredIMEState(&newState);
OwningNonNull<nsGenericHTMLElement> kungFuDeathGrip(*this);
IMEStateManager::UpdateIMEState(
newState, kungFuDeathGrip, *editor,
{IMEStateManager::UpdateIMEStateOption::ForceUpdate,
IMEStateManager::UpdateIMEStateOption::
DontCommitComposition});
}
}
}
}
}