diff options
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.cc | 61 |
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). |