mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-23 04:41:11 +00:00
Bug 1922149 - Make HTMLEditor::ComputeEditingHostInternal
use common ancestor of all selection ranges r=m_kato
Selection ranges can cross editing host boundaries if no editing host has focus. Therefore, `Selection.focusNode` may be in an editing host but there may be no active/focused editing host. The computation may be expensive if there are a lot of ranges and selecting in slotted shadow tree. However, it's rare case, so, I think it's okay for now. Differential Revision: https://phabricator.services.mozilla.com/D224282
This commit is contained in:
parent
033db44f68
commit
ee7a27d122
@ -20,6 +20,7 @@
|
||||
#include "nsComputedDOMStyle.h"
|
||||
#include "nsDebug.h"
|
||||
#include "nsError.h"
|
||||
#include "nsFocusManager.h"
|
||||
#include "nsGenericHTMLElement.h"
|
||||
#include "nsGkAtoms.h"
|
||||
#include "nsAtom.h"
|
||||
@ -380,7 +381,8 @@ nsresult HTMLEditor::RefreshEditingUI() {
|
||||
if (editingHost && editingHost->IsContentEditablePlainTextOnly()) {
|
||||
return NS_OK;
|
||||
}
|
||||
MOZ_ASSERT(editingHost == selectionContainerElement->GetEditingHost());
|
||||
MOZ_ASSERT_IF(editingHost,
|
||||
editingHost == selectionContainerElement->GetEditingHost());
|
||||
|
||||
// what's its tag?
|
||||
RefPtr<Element> focusElement = std::move(selectionContainerElement);
|
||||
|
@ -7033,12 +7033,28 @@ Element* HTMLEditor::ComputeEditingHostInternal(
|
||||
if (aContent) {
|
||||
return aContent;
|
||||
}
|
||||
// If the selection has focus node, let's look for its editing host because
|
||||
// selection ranges may be visible for users.
|
||||
nsIContent* const selectionFocusNode = nsIContent::FromNodeOrNull(
|
||||
SelectionRef().GetMayCrossShadowBoundaryFocusNode());
|
||||
if (selectionFocusNode) {
|
||||
return selectionFocusNode;
|
||||
// If there are selection ranges, let's look for their common ancestor's
|
||||
// editing host because selection ranges may be visible for users.
|
||||
nsIContent* selectionCommonAncestor = nullptr;
|
||||
for (uint32_t i : IntegerRange(SelectionRef().RangeCount())) {
|
||||
nsRange* range = SelectionRef().GetRangeAt(i);
|
||||
MOZ_ASSERT(range);
|
||||
nsIContent* commonAncestor =
|
||||
nsIContent::FromNodeOrNull(range->GetCommonAncestorContainer(
|
||||
IgnoreErrors(), AllowRangeCrossShadowBoundary::Yes));
|
||||
if (MOZ_UNLIKELY(!commonAncestor)) {
|
||||
continue;
|
||||
}
|
||||
if (!selectionCommonAncestor) {
|
||||
selectionCommonAncestor = commonAncestor;
|
||||
} else {
|
||||
selectionCommonAncestor =
|
||||
nsContentUtils::GetCommonFlattenedTreeAncestorForSelection(
|
||||
commonAncestor, selectionCommonAncestor);
|
||||
}
|
||||
}
|
||||
if (selectionCommonAncestor) {
|
||||
return selectionCommonAncestor;
|
||||
}
|
||||
// Otherwise, let's use the focused element in the window.
|
||||
nsPIDOMWindowInner* const innerWindow = document->GetInnerWindow();
|
||||
|
@ -0,0 +1,18 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<script>
|
||||
"use strict";
|
||||
|
||||
document.addEventListener("DOMContentLoaded", () => {
|
||||
document.execCommand("enableObjectResizing");
|
||||
document.execCommand("selectAll");
|
||||
});
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<figcaption contenteditable="true">
|
||||
<canvas>
|
||||
</canvas></figcaption></body>
|
||||
</html>
|
Loading…
Reference in New Issue
Block a user