summaryrefslogtreecommitdiff
path: root/chromium/third_party/blink/renderer/core/display_lock/display_lock_utilities.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/third_party/blink/renderer/core/display_lock/display_lock_utilities.cc')
-rw-r--r--chromium/third_party/blink/renderer/core/display_lock/display_lock_utilities.cc176
1 files changed, 143 insertions, 33 deletions
diff --git a/chromium/third_party/blink/renderer/core/display_lock/display_lock_utilities.cc b/chromium/third_party/blink/renderer/core/display_lock/display_lock_utilities.cc
index 81ff80d17e2..183b36b0f3c 100644
--- a/chromium/third_party/blink/renderer/core/display_lock/display_lock_utilities.cc
+++ b/chromium/third_party/blink/renderer/core/display_lock/display_lock_utilities.cc
@@ -12,9 +12,12 @@
#include "third_party/blink/renderer/core/dom/text.h"
#include "third_party/blink/renderer/core/editing/editing_boundary.h"
#include "third_party/blink/renderer/core/editing/editing_utilities.h"
+#include "third_party/blink/renderer/core/inspector/inspector_trace_events.h"
#include "third_party/blink/renderer/core/layout/layout_embedded_content.h"
#include "third_party/blink/renderer/core/layout/layout_view.h"
+#include <set>
+
namespace blink {
namespace {
@@ -32,9 +35,9 @@ bool UpdateStyleAndLayoutForRangeIfNeeded(const EphemeralRangeInFlatTree& range,
DisplayLockActivationReason reason) {
if (range.IsNull() || range.IsCollapsed())
return false;
- if (!RuntimeEnabledFeatures::DisplayLockingEnabled(&range.GetDocument()) ||
+ if (!RuntimeEnabledFeatures::CSSSubtreeVisibilityEnabled() ||
range.GetDocument().LockedDisplayLockCount() ==
- range.GetDocument().ActivationBlockingDisplayLockCount())
+ range.GetDocument().DisplayLockBlockingAllActivationCount())
return false;
Vector<DisplayLockContext::ScopedForcedUpdate> scoped_forced_update_list_;
for (Node& node : range.Nodes()) {
@@ -50,21 +53,35 @@ bool UpdateStyleAndLayoutForRangeIfNeeded(const EphemeralRangeInFlatTree& range,
->GetScopedForcedUpdate());
}
}
- if (!scoped_forced_update_list_.IsEmpty())
- range.GetDocument().UpdateStyleAndLayout();
+ if (!scoped_forced_update_list_.IsEmpty()) {
+ range.GetDocument().UpdateStyleAndLayout(
+ DocumentUpdateReason::kDisplayLock);
+ }
return !scoped_forced_update_list_.IsEmpty();
}
+void PopulateAncestorContexts(Node* node,
+ std::set<DisplayLockContext*>* contexts) {
+ DCHECK(node);
+ for (Node& ancestor : FlatTreeTraversal::InclusiveAncestorsOf(*node)) {
+ auto* ancestor_element = DynamicTo<Element>(ancestor);
+ if (!ancestor_element)
+ continue;
+ if (auto* context = ancestor_element->GetDisplayLockContext())
+ contexts->insert(context);
+ }
+}
+
} // namespace
bool DisplayLockUtilities::ActivateFindInPageMatchRangeIfNeeded(
const EphemeralRangeInFlatTree& range) {
- if (!RuntimeEnabledFeatures::DisplayLockingEnabled(&range.GetDocument()))
+ if (!RuntimeEnabledFeatures::CSSSubtreeVisibilityEnabled())
return false;
DCHECK(!range.IsNull());
DCHECK(!range.IsCollapsed());
if (range.GetDocument().LockedDisplayLockCount() ==
- range.GetDocument().ActivationBlockingDisplayLockCount())
+ range.GetDocument().DisplayLockBlockingAllActivationCount())
return false;
// Find-in-page matches can't span multiple block-level elements (because the
// text will be broken by newlines between blocks), so first we find the
@@ -73,9 +90,13 @@ bool DisplayLockUtilities::ActivateFindInPageMatchRangeIfNeeded(
// case we are traversing from the start position of the range.
Element* enclosing_block =
EnclosingBlock(range.StartPosition(), kCannotCrossEditingBoundary);
+ // Note that we don't check the `range.EndPosition()` since we just activate
+ // the beginning of the range. In find-in-page cases, the end position is the
+ // same since the matches cannot cross block boundaries. However, in
+ // scroll-to-text, the range might be different, but we still just activate
+ // the beginning of the range. See
+ // https://github.com/WICG/display-locking/issues/125 for more details.
DCHECK(enclosing_block);
- DCHECK_EQ(enclosing_block,
- EnclosingBlock(range.EndPosition(), kCannotCrossEditingBoundary));
return enclosing_block->ActivateDisplayLockIfNeeded(
DisplayLockActivationReason::kFindInPage);
}
@@ -84,9 +105,9 @@ bool DisplayLockUtilities::ActivateSelectionRangeIfNeeded(
const EphemeralRangeInFlatTree& range) {
if (range.IsNull() || range.IsCollapsed())
return false;
- if (!RuntimeEnabledFeatures::DisplayLockingEnabled(&range.GetDocument()) ||
+ if (!RuntimeEnabledFeatures::CSSSubtreeVisibilityEnabled() ||
range.GetDocument().LockedDisplayLockCount() ==
- range.GetDocument().ActivationBlockingDisplayLockCount())
+ range.GetDocument().DisplayLockBlockingAllActivationCount())
return false;
UpdateStyleAndLayoutForRangeIfNeeded(range,
DisplayLockActivationReason::kSelection);
@@ -112,10 +133,9 @@ DisplayLockUtilities::ActivatableLockedInclusiveAncestors(
DisplayLockActivationReason reason) {
HeapVector<Member<Element>> elements_to_activate;
const_cast<Node*>(&node)->UpdateDistributionForFlatTreeTraversal();
- if (!RuntimeEnabledFeatures::DisplayLockingEnabled(
- node.GetExecutionContext()) ||
+ if (!RuntimeEnabledFeatures::CSSSubtreeVisibilityEnabled() ||
node.GetDocument().LockedDisplayLockCount() ==
- node.GetDocument().ActivationBlockingDisplayLockCount())
+ node.GetDocument().DisplayLockBlockingAllActivationCount())
return elements_to_activate;
for (Node& ancestor : FlatTreeTraversal::InclusiveAncestorsOf(node)) {
@@ -140,8 +160,7 @@ DisplayLockUtilities::ActivatableLockedInclusiveAncestors(
DisplayLockUtilities::ScopedChainForcedUpdate::ScopedChainForcedUpdate(
const Node* node,
bool include_self) {
- if (!RuntimeEnabledFeatures::DisplayLockingEnabled(
- node->GetExecutionContext()))
+ if (!RuntimeEnabledFeatures::CSSSubtreeVisibilityEnabled())
return;
CreateParentFrameScopeIfNeeded(node);
@@ -197,8 +216,7 @@ const Element* DisplayLockUtilities::NearestLockedInclusiveAncestor(
auto* element = DynamicTo<Element>(node);
if (!element)
return NearestLockedExclusiveAncestor(node);
- if (!RuntimeEnabledFeatures::DisplayLockingEnabled(
- node.GetExecutionContext()) ||
+ if (!RuntimeEnabledFeatures::CSSSubtreeVisibilityEnabled() ||
!node.isConnected() || node.GetDocument().LockedDisplayLockCount() == 0 ||
!node.CanParticipateInFlatTree()) {
return nullptr;
@@ -217,8 +235,7 @@ Element* DisplayLockUtilities::NearestLockedInclusiveAncestor(Node& node) {
Element* DisplayLockUtilities::NearestLockedExclusiveAncestor(
const Node& node) {
- if (!RuntimeEnabledFeatures::DisplayLockingEnabled(
- node.GetExecutionContext()) ||
+ if (!RuntimeEnabledFeatures::CSSSubtreeVisibilityEnabled() ||
!node.isConnected() || node.GetDocument().LockedDisplayLockCount() == 0 ||
!node.CanParticipateInFlatTree()) {
return nullptr;
@@ -240,8 +257,7 @@ Element* DisplayLockUtilities::NearestLockedExclusiveAncestor(
Element* DisplayLockUtilities::HighestLockedInclusiveAncestor(
const Node& node) {
- if (!RuntimeEnabledFeatures::DisplayLockingEnabled(
- node.GetExecutionContext()) ||
+ if (!RuntimeEnabledFeatures::CSSSubtreeVisibilityEnabled() ||
node.GetDocument().LockedDisplayLockCount() == 0 ||
!node.CanParticipateInFlatTree()) {
return nullptr;
@@ -262,8 +278,7 @@ Element* DisplayLockUtilities::HighestLockedInclusiveAncestor(
Element* DisplayLockUtilities::HighestLockedExclusiveAncestor(
const Node& node) {
- if (!RuntimeEnabledFeatures::DisplayLockingEnabled(
- node.GetExecutionContext()) ||
+ if (!RuntimeEnabledFeatures::CSSSubtreeVisibilityEnabled() ||
node.GetDocument().LockedDisplayLockCount() == 0 ||
!node.CanParticipateInFlatTree()) {
return nullptr;
@@ -296,29 +311,29 @@ Element* DisplayLockUtilities::NearestLockedExclusiveAncestor(
return nullptr;
}
-bool DisplayLockUtilities::IsInNonActivatableLockedSubtree(const Node& node) {
- if (!RuntimeEnabledFeatures::DisplayLockingEnabled(
+bool DisplayLockUtilities::IsInUnlockedOrActivatableSubtree(
+ const Node& node,
+ DisplayLockActivationReason activation_reason) {
+ if (!RuntimeEnabledFeatures::CSSSubtreeVisibilityEnabled(
node.GetExecutionContext()) ||
node.GetDocument().LockedDisplayLockCount() == 0 ||
- node.GetDocument().ActivationBlockingDisplayLockCount() == 0 ||
+ node.GetDocument().DisplayLockBlockingAllActivationCount() == 0 ||
!node.CanParticipateInFlatTree()) {
- return false;
+ return true;
}
for (auto* element = NearestLockedExclusiveAncestor(node); element;
element = NearestLockedExclusiveAncestor(*element)) {
- if (!element->GetDisplayLockContext()->IsActivatable(
- DisplayLockActivationReason::kAny)) {
- return true;
+ if (!element->GetDisplayLockContext()->IsActivatable(activation_reason)) {
+ return false;
}
}
- return false;
+ return true;
}
bool DisplayLockUtilities::IsInLockedSubtreeCrossingFrames(
const Node& source_node) {
- if (!RuntimeEnabledFeatures::DisplayLockingEnabled(
- source_node.GetExecutionContext()))
+ if (!RuntimeEnabledFeatures::CSSSubtreeVisibilityEnabled())
return false;
const Node* node = &source_node;
@@ -347,4 +362,99 @@ bool DisplayLockUtilities::IsInLockedSubtreeCrossingFrames(
return false;
}
+void DisplayLockUtilities::ElementLostFocus(Element* element) {
+ if (!RuntimeEnabledFeatures::CSSSubtreeVisibilityEnabled() ||
+ (element && element->GetDocument().DisplayLockCount() == 0))
+ return;
+ for (; element; element = FlatTreeTraversal::ParentElement(*element)) {
+ auto* context = element->GetDisplayLockContext();
+ if (context)
+ context->NotifySubtreeLostFocus();
+ }
+}
+void DisplayLockUtilities::ElementGainedFocus(Element* element) {
+ if (!RuntimeEnabledFeatures::CSSSubtreeVisibilityEnabled() ||
+ (element && element->GetDocument().DisplayLockCount() == 0))
+ return;
+
+ for (; element; element = FlatTreeTraversal::ParentElement(*element)) {
+ auto* context = element->GetDisplayLockContext();
+ if (context)
+ context->NotifySubtreeGainedFocus();
+ }
+}
+
+void DisplayLockUtilities::SelectionChanged(
+ const EphemeralRangeInFlatTree& old_selection,
+ const EphemeralRangeInFlatTree& new_selection) {
+ if (!RuntimeEnabledFeatures::CSSSubtreeVisibilityEnabled() ||
+ (!old_selection.IsNull() &&
+ old_selection.GetDocument().DisplayLockCount() == 0) ||
+ (!new_selection.IsNull() &&
+ new_selection.GetDocument().DisplayLockCount() == 0))
+ return;
+
+ TRACE_EVENT0("blink", "DisplayLockUtilities::SelectionChanged");
+ std::set<Node*> old_nodes;
+ for (Node& node : old_selection.Nodes())
+ old_nodes.insert(&node);
+
+ std::set<Node*> new_nodes;
+ for (Node& node : new_selection.Nodes())
+ new_nodes.insert(&node);
+
+ std::set<DisplayLockContext*> lost_selection_contexts;
+ std::set<DisplayLockContext*> gained_selection_contexts;
+
+ // Skip common nodes and extract contexts from nodes that lost selection and
+ // contexts from nodes that gained selection.
+ // This is similar to std::set_symmetric_difference except that we need to
+ // know which set the resulting item came from. In this version, we simply do
+ // the relevant operation on each of the items instead of storing the
+ // difference.
+ std::set<Node*>::iterator old_it = old_nodes.begin();
+ std::set<Node*>::iterator new_it = new_nodes.begin();
+ while (old_it != old_nodes.end() && new_it != new_nodes.end()) {
+ // Compare the addresses since that's how the nodes are ordered in the set.
+ if (*old_it < *new_it) {
+ PopulateAncestorContexts(*old_it++, &lost_selection_contexts);
+ } else if (*old_it > *new_it) {
+ PopulateAncestorContexts(*new_it++, &gained_selection_contexts);
+ } else {
+ ++old_it;
+ ++new_it;
+ }
+ }
+ while (old_it != old_nodes.end())
+ PopulateAncestorContexts(*old_it++, &lost_selection_contexts);
+ while (new_it != new_nodes.end())
+ PopulateAncestorContexts(*new_it++, &gained_selection_contexts);
+
+ // Now do a similar thing with contexts: skip common ones, and mark the ones
+ // that lost selection or gained selection as such.
+ std::set<DisplayLockContext*>::iterator lost_it =
+ lost_selection_contexts.begin();
+ std::set<DisplayLockContext*>::iterator gained_it =
+ gained_selection_contexts.begin();
+ while (lost_it != lost_selection_contexts.end() &&
+ gained_it != gained_selection_contexts.end()) {
+ if (*lost_it < *gained_it) {
+ (*lost_it++)->NotifySubtreeLostSelection();
+ } else if (*lost_it > *gained_it) {
+ (*gained_it++)->NotifySubtreeGainedSelection();
+ } else {
+ ++lost_it;
+ ++gained_it;
+ }
+ }
+ while (lost_it != lost_selection_contexts.end())
+ (*lost_it++)->NotifySubtreeLostSelection();
+ while (gained_it != gained_selection_contexts.end())
+ (*gained_it++)->NotifySubtreeGainedSelection();
+}
+
+void DisplayLockUtilities::SelectionRemovedFromDocument(Document& document) {
+ document.NotifySelectionRemovedFromDisplayLocks();
+}
+
} // namespace blink