summaryrefslogtreecommitdiff
path: root/chromium/third_party/blink/renderer/core/page/spatial_navigation.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/third_party/blink/renderer/core/page/spatial_navigation.cc')
-rw-r--r--chromium/third_party/blink/renderer/core/page/spatial_navigation.cc61
1 files changed, 43 insertions, 18 deletions
diff --git a/chromium/third_party/blink/renderer/core/page/spatial_navigation.cc b/chromium/third_party/blink/renderer/core/page/spatial_navigation.cc
index 071f9a6a99e..64e1afd4385 100644
--- a/chromium/third_party/blink/renderer/core/page/spatial_navigation.cc
+++ b/chromium/third_party/blink/renderer/core/page/spatial_navigation.cc
@@ -28,6 +28,7 @@
#include "third_party/blink/renderer/core/page/spatial_navigation.h"
+#include "third_party/blink/public/mojom/scroll/scrollbar_mode.mojom-blink.h"
#include "third_party/blink/renderer/core/dom/node_traversal.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/local_frame_view.h"
@@ -43,6 +44,7 @@
#include "third_party/blink/renderer/core/layout/layout_view.h"
#include "third_party/blink/renderer/core/page/frame_tree.h"
#include "third_party/blink/renderer/core/page/page.h"
+#include "third_party/blink/renderer/core/paint/paint_layer.h"
#include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h"
#include "third_party/blink/renderer/platform/geometry/int_rect.h"
@@ -53,6 +55,8 @@ namespace blink {
// std::numeric_limits<double>::lowest() because, if subtracted, it becomes
// NaN which will make all following arithmetic NaN too (an unusable number).
constexpr double kMinDistance = std::numeric_limits<int>::lowest();
+constexpr double kPriorityClassA = kMinDistance;
+constexpr double kPriorityClassB = kMinDistance / 2;
constexpr int kFudgeFactor = 2;
@@ -307,7 +311,7 @@ bool ScrollInDirection(Node* container, SpatialNavigationDirection direction) {
if (!scroller)
return false;
- scroller->ScrollBy(ScrollOffset(dx, dy), kUserScroll);
+ scroller->ScrollBy(ScrollOffset(dx, dy), mojom::blink::ScrollType::kUser);
return true;
}
@@ -399,16 +403,16 @@ bool CanScrollInDirection(const LocalFrame* frame,
LayoutView* layoutView = frame->ContentLayoutObject();
if (!layoutView)
return false;
- ScrollbarMode vertical_mode;
- ScrollbarMode horizontal_mode;
+ mojom::blink::ScrollbarMode vertical_mode;
+ mojom::blink::ScrollbarMode horizontal_mode;
layoutView->CalculateScrollbarModes(horizontal_mode, vertical_mode);
if ((direction == SpatialNavigationDirection::kLeft ||
direction == SpatialNavigationDirection::kRight) &&
- ScrollbarMode::kAlwaysOff == horizontal_mode)
+ mojom::blink::ScrollbarMode::kAlwaysOff == horizontal_mode)
return false;
if ((direction == SpatialNavigationDirection::kUp ||
direction == SpatialNavigationDirection::kDown) &&
- ScrollbarMode::kAlwaysOff == vertical_mode)
+ mojom::blink::ScrollbarMode::kAlwaysOff == vertical_mode)
return false;
ScrollableArea* scrollable_area = frame->View()->GetScrollableArea();
LayoutSize size(scrollable_area->ContentsSize());
@@ -581,11 +585,29 @@ double Alignment(SpatialNavigationDirection direction,
}
}
+bool BothOnTopmostPaintLayerInStackingContext(
+ const FocusCandidate& current_interest,
+ const FocusCandidate& candidate) {
+ if (!current_interest.visible_node)
+ return false;
+
+ const LayoutObject* origin = current_interest.visible_node->GetLayoutObject();
+ const PaintLayer* focused_layer = origin->PaintingLayer();
+ if (!focused_layer || focused_layer->IsRootLayer())
+ return false;
+
+ const LayoutObject* next = candidate.visible_node->GetLayoutObject();
+ const PaintLayer* candidate_layer = next->PaintingLayer();
+ if (focused_layer != candidate_layer)
+ return false;
+
+ return !candidate_layer->HasVisibleDescendant();
+}
+
double ComputeDistanceDataForNode(SpatialNavigationDirection direction,
const FocusCandidate& current_interest,
const FocusCandidate& candidate) {
double distance = 0.0;
- double overlap = 0.0;
PhysicalRect node_rect = candidate.rect_in_root_frame;
PhysicalRect current_rect = current_interest.rect_in_root_frame;
if (node_rect.Contains(current_rect)) {
@@ -596,9 +618,10 @@ double ComputeDistanceDataForNode(SpatialNavigationDirection direction,
}
if (current_rect.Contains(node_rect)) {
- // We give priority to "insiders", candidates that are completely inside the
- // current focus rect, by giving them a negative, < 0, distance number.
- distance = kMinDistance;
+ // We give highest priority to "insiders", candidates that are completely
+ // inside the current focus rect, by giving them a negative, < 0, distance
+ // number.
+ distance = kPriorityClassA;
// For insiders we cannot meassure the distance from the outer box. Instead,
// we meassure distance _from_ the focused container's rect's "opposite
@@ -611,10 +634,11 @@ double ComputeDistanceDataForNode(SpatialNavigationDirection direction,
// "outsider".
} else if (!IsRectInDirection(direction, current_rect, node_rect)) {
return kMaxDistance;
- } else {
- PhysicalRect intersection_rect = Intersection(current_rect, node_rect);
- overlap =
- (intersection_rect.Width() * intersection_rect.Height()).ToDouble();
+ } else if (BothOnTopmostPaintLayerInStackingContext(current_interest,
+ candidate)) {
+ // Prioritize "popup candidates" over other candidates by giving them a
+ // negative, < 0, distance number.
+ distance = kPriorityClassB;
}
LayoutPoint exit_point;
@@ -664,10 +688,11 @@ double ComputeDistanceDataForNode(SpatialNavigationDirection direction,
return kMaxDistance;
}
- // Distance calculation is based on https://drafts.csswg.org/css-nav-1/.
- return distance + navigation_axis_distance -
- Alignment(direction, current_rect, node_rect) +
- weighted_orthogonal_axis_distance - sqrt(overlap);
+ // We try to formalize this distance calculation at
+ // https://drafts.csswg.org/css-nav-1/.
+ distance += weighted_orthogonal_axis_distance.ToDouble() +
+ navigation_axis_distance.ToDouble();
+ return distance - Alignment(direction, current_rect, node_rect);
}
// Returns a thin rectangle that represents one of |box|'s edges.
@@ -718,7 +743,7 @@ PhysicalRect StartEdgeForAreaElement(const HTMLAreaElement& area,
}
HTMLFrameOwnerElement* FrameOwnerElement(const FocusCandidate& candidate) {
- return DynamicTo<HTMLFrameOwnerElement>(candidate.visible_node.Get());
+ return DynamicTo<HTMLFrameOwnerElement>(candidate.visible_node);
}
// The visual viewport's rect (given in the root frame's coordinate space).