diff options
Diffstat (limited to 'chromium/third_party/blink/renderer/core/input/scroll_manager.cc')
-rw-r--r-- | chromium/third_party/blink/renderer/core/input/scroll_manager.cc | 184 |
1 files changed, 85 insertions, 99 deletions
diff --git a/chromium/third_party/blink/renderer/core/input/scroll_manager.cc b/chromium/third_party/blink/renderer/core/input/scroll_manager.cc index 8b8d2a7faf1..68e636a737a 100644 --- a/chromium/third_party/blink/renderer/core/input/scroll_manager.cc +++ b/chromium/third_party/blink/renderer/core/input/scroll_manager.cc @@ -70,8 +70,7 @@ ScrollableArea* ScrollableAreaForSnapping(LayoutBox* layout_box) { } // namespace ScrollManager::ScrollManager(LocalFrame& frame) : frame_(frame) { - if (RuntimeEnabledFeatures::CSSScrollSnapPointsEnabled()) - snap_fling_controller_ = std::make_unique<cc::SnapFlingController>(this); + snap_fling_controller_ = std::make_unique<cc::SnapFlingController>(this); Clear(); } @@ -87,14 +86,14 @@ void ScrollManager::Clear() { void ScrollManager::Trace(blink::Visitor* visitor) { visitor->Trace(frame_); visitor->Trace(scroll_gesture_handling_node_); - visitor->Trace(previous_gesture_scrolled_element_); + visitor->Trace(previous_gesture_scrolled_node_); visitor->Trace(scrollbar_handling_scroll_gesture_); visitor->Trace(resize_scrollable_area_); } void ScrollManager::ClearGestureScrollState() { scroll_gesture_handling_node_ = nullptr; - previous_gesture_scrolled_element_ = nullptr; + previous_gesture_scrolled_node_ = nullptr; delta_consumed_for_scroll_sequence_ = false; did_scroll_x_for_scroll_gesture_ = false; did_scroll_y_for_scroll_gesture_ = false; @@ -128,9 +127,8 @@ AutoscrollController* ScrollManager::GetAutoscrollController() const { return nullptr; } -static bool CanPropagate(const ScrollState& scroll_state, - const Element& element) { - ScrollableArea* scrollable_area = element.GetLayoutBox()->GetScrollableArea(); +static bool CanPropagate(const ScrollState& scroll_state, const Node& node) { + ScrollableArea* scrollable_area = node.GetLayoutBox()->GetScrollableArea(); if (!scrollable_area) return true; @@ -139,10 +137,10 @@ static bool CanPropagate(const ScrollState& scroll_state, return true; return (scroll_state.deltaXHint() == 0 || - element.GetComputedStyle()->OverscrollBehaviorX() == + node.GetComputedStyle()->OverscrollBehaviorX() == EOverscrollBehavior::kAuto) && (scroll_state.deltaYHint() == 0 || - element.GetComputedStyle()->OverscrollBehaviorY() == + node.GetComputedStyle()->OverscrollBehaviorY() == EOverscrollBehavior::kAuto); } @@ -154,38 +152,27 @@ void ScrollManager::RecomputeScrollChain(const Node& start_node, DCHECK(start_node.GetLayoutObject()); LayoutBox* cur_box = start_node.GetLayoutObject()->EnclosingBox(); - Element* document_element = frame_->GetDocument()->documentElement(); // Scrolling propagates along the containing block chain and ends at the - // RootScroller element. The RootScroller element will have a custom - // applyScroll callback that scrolls the frame or element. + // RootScroller node. The RootScroller node will have a custom applyScroll + // callback that performs scrolling as well as associated "root" actions like + // browser control movement and overscroll glow. while (cur_box) { Node* cur_node = cur_box->GetNode(); - Element* cur_element = nullptr; - - // FIXME: this should reject more elements, as part of crbug.com/410974. - if (cur_node && cur_node->IsElementNode()) { - cur_element = ToElement(cur_node); - } else if (cur_node && cur_node->IsDocumentNode()) { - // In normal circumastances, the documentElement will be the root - // scroller but the documentElement itself isn't a containing block, - // that'll be the document node rather than the element. - cur_element = document_element; - } - if (cur_element) { - if (CanScroll(scroll_state, *cur_element)) - scroll_chain.push_front(DOMNodeIds::IdForNode(cur_element)); - if (IsViewportScrollingElement(*cur_element) || - cur_element == document_element) + if (cur_node) { + if (CanScroll(scroll_state, *cur_node)) + scroll_chain.push_front(DOMNodeIds::IdForNode(cur_node)); + + if (cur_node->IsEffectiveRootScroller()) break; - if (!CanPropagate(scroll_state, *cur_element)) { + if (!CanPropagate(scroll_state, *cur_node)) { // We should add the first node with non-auto overscroll-behavior to // the scroll chain regardlessly, as it's the only node we can latch to. if (scroll_chain.empty() || - scroll_chain.front() != DOMNodeIds::IdForNode(cur_element)) { - scroll_chain.push_front(DOMNodeIds::IdForNode(cur_element)); + scroll_chain.front() != DOMNodeIds::IdForNode(cur_node)) { + scroll_chain.push_front(DOMNodeIds::IdForNode(cur_node)); } break; } @@ -196,25 +183,18 @@ void ScrollManager::RecomputeScrollChain(const Node& start_node, } bool ScrollManager::CanScroll(const ScrollState& scroll_state, - const Element& current_element) { - ScrollableArea* scrollable_area = nullptr; - if (IsViewportScrollingElement(current_element) || - current_element == *(frame_->GetDocument()->documentElement())) { - if (!current_element.GetLayoutObject()) - return false; - - if (frame_->IsMainFrame()) - return true; + const Node& current_node) { + if (!current_node.GetLayoutBox()) + return false; - // For subframes, the viewport is added to the scroll chain only if it can - // actually consume some delta hints. The main frame always gets added - // since it produces overscroll effects. - scrollable_area = - frame_->View() ? frame_->View()->GetScrollableArea() : nullptr; - } + // We need to always add the global root scroller even if it isn't scrollable + // since we can always pinch-zoom and scroll as well as for overscroll + // effects. + if (current_node.GetLayoutBox()->IsGlobalRootScroller()) + return true; - if (!scrollable_area && current_element.GetLayoutBox()) - scrollable_area = current_element.GetLayoutBox()->GetScrollableArea(); + ScrollableArea* scrollable_area = + current_node.GetLayoutBox()->GetScrollableArea(); if (!scrollable_area) return false; @@ -282,20 +262,27 @@ bool ScrollManager::LogicalScroll(ScrollDirection direction, ScrollableArea* scrollable_area = nullptr; // The global root scroller must be scrolled by the RootFrameViewport. - if (RootScrollerUtil::IsGlobal(*box)) { + if (box->IsGlobalRootScroller()) { LocalFrame& main_frame = frame_->LocalFrameRoot(); // The local root must be the main frame if we have the global root // scroller since it can't yet be set on OOPIFs. DCHECK(main_frame.IsMainFrame()); scrollable_area = main_frame.View()->GetScrollableArea(); - } else if (node == document.documentElement()) { - scrollable_area = document.GetLayoutView()->GetScrollableArea(); } else { scrollable_area = box->GetScrollableArea(); } DCHECK(scrollable_area); + + SnapCoordinator* snap_coordinator = + frame_->GetDocument()->GetSnapCoordinator(); + ScrollOffset delta = ToScrollDelta(physical_direction, 1); + delta.Scale(scrollable_area->ScrollStep(granularity, kHorizontalScrollbar), + scrollable_area->ScrollStep(granularity, kVerticalScrollbar)); + if (snap_coordinator->SnapForDirection(*box, delta)) + return true; + ScrollResult result = scrollable_area->UserScroll( granularity, ToScrollDelta(physical_direction, 1)); @@ -419,7 +406,7 @@ WebInputEventResult ScrollManager::HandleGestureScrollBegin( scroll_gesture_handling_node_->ParentOrShadowHostNode(); if (!scroll_gesture_handling_node_) - scroll_gesture_handling_node_ = frame_->GetDocument()->documentElement(); + scroll_gesture_handling_node_ = frame_->GetDocument(); if (!scroll_gesture_handling_node_ || !scroll_gesture_handling_node_->GetLayoutObject()) { @@ -482,7 +469,7 @@ WebInputEventResult ScrollManager::HandleGestureScrollUpdate( if (!node || !node->GetLayoutObject()) { TRACE_EVENT_INSTANT0("input", "Lost scroll_gesture_handling_node", TRACE_EVENT_SCOPE_THREAD); - if (previous_gesture_scrolled_element_) { + if (previous_gesture_scrolled_node_) { // When the scroll_gesture_handling_node_ gets deleted in the middle of // scrolling call HandleGestureScrollEvent to start scrolling a new node // if possible. @@ -557,18 +544,17 @@ WebInputEventResult ScrollManager::HandleGestureScrollUpdate( scroll_state_data->delta_consumed_for_scroll_sequence = delta_consumed_for_scroll_sequence_; ScrollState* scroll_state = ScrollState::Create(std::move(scroll_state_data)); - if (previous_gesture_scrolled_element_) { + if (previous_gesture_scrolled_node_) { // The ScrollState needs to know what the current // native scrolling element is, so that for an // inertial scroll that shouldn't propagate, only the // currently scrolling element responds. - scroll_state->SetCurrentNativeScrollingElement( - previous_gesture_scrolled_element_); + scroll_state->SetCurrentNativeScrollingNode( + previous_gesture_scrolled_node_); } CustomizedScroll(*scroll_state); - previous_gesture_scrolled_element_ = - scroll_state->CurrentNativeScrollingElement(); + previous_gesture_scrolled_node_ = scroll_state->CurrentNativeScrollingNode(); delta_consumed_for_scroll_sequence_ = scroll_state->DeltaConsumedForScrollSequence(); @@ -578,9 +564,11 @@ WebInputEventResult ScrollManager::HandleGestureScrollUpdate( did_scroll_x_for_scroll_gesture_ |= did_scroll_x; did_scroll_y_for_scroll_gesture_ |= did_scroll_y; - if ((!previous_gesture_scrolled_element_ || - !IsViewportScrollingElement(*previous_gesture_scrolled_element_)) && - GetPage()) + // TODO(bokan): This looks like it resets overscroll if any *effective* root + // scroller is scrolled. This should probably be if the *global* root + // scroller is scrolled. + if (!previous_gesture_scrolled_node_ || + !previous_gesture_scrolled_node_->IsEffectiveRootScroller()) GetPage()->GetOverscrollController().ResetAccumulated(did_scroll_x, did_scroll_y); @@ -619,20 +607,19 @@ WebInputEventResult ScrollManager::HandleGestureScrollEnd( } ClearGestureScrollState(); + if (RuntimeEnabledFeatures::NoHoverDuringScrollEnabled()) + frame_->GetEventHandler().RecomputeMouseHoverState(); return WebInputEventResult::kNotHandled; } LayoutBox* ScrollManager::LayoutBoxForSnapping() const { - if (!previous_gesture_scrolled_element_) + if (!previous_gesture_scrolled_node_) return nullptr; - Element* document_element = frame_->GetDocument()->documentElement(); - return previous_gesture_scrolled_element_ == document_element - ? frame_->GetDocument()->GetLayoutView() - : previous_gesture_scrolled_element_->GetLayoutBox(); + return previous_gesture_scrolled_node_->GetLayoutBox(); } void ScrollManager::SnapAtGestureScrollEnd() { - if (!previous_gesture_scrolled_element_ || + if (!previous_gesture_scrolled_node_ || (!did_scroll_x_for_scroll_gesture_ && !did_scroll_y_for_scroll_gesture_)) return; SnapCoordinator* snap_coordinator = @@ -641,24 +628,34 @@ void ScrollManager::SnapAtGestureScrollEnd() { if (!snap_coordinator || !layout_box) return; - snap_coordinator->PerformSnapping(*layout_box, - did_scroll_x_for_scroll_gesture_, - did_scroll_y_for_scroll_gesture_); + snap_coordinator->SnapForEndPosition(*layout_box, + did_scroll_x_for_scroll_gesture_, + did_scroll_y_for_scroll_gesture_); } -bool ScrollManager::GetSnapFlingInfo(const gfx::Vector2dF& natural_displacement, - gfx::Vector2dF* out_initial_offset, - gfx::Vector2dF* out_target_offset) const { - if (!previous_gesture_scrolled_element_) - return false; - +bool ScrollManager::GetSnapFlingInfo( + const gfx::Vector2dF& natural_displacement, + gfx::Vector2dF* out_initial_position, + gfx::Vector2dF* out_target_position) const { SnapCoordinator* snap_coordinator = frame_->GetDocument()->GetSnapCoordinator(); LayoutBox* layout_box = LayoutBoxForSnapping(); - if (!snap_coordinator || !layout_box || !layout_box->GetScrollableArea()) + ScrollableArea* scrollable_area = ScrollableAreaForSnapping(layout_box); + if (!snap_coordinator || !layout_box || !scrollable_area) + return false; + + FloatPoint current_position = scrollable_area->ScrollPosition(); + *out_initial_position = gfx::Vector2dF(current_position); + std::unique_ptr<SnapSelectionStrategy> strategy = + SnapSelectionStrategy::CreateForEndAndDirection( + gfx::ScrollOffset(*out_initial_position), + gfx::ScrollOffset(natural_displacement)); + base::Optional<FloatPoint> snap_end = + snap_coordinator->GetSnapPosition(*layout_box, *strategy); + if (!snap_end.has_value()) return false; - return snap_coordinator->GetSnapFlingInfo( - *layout_box, natural_displacement, out_initial_offset, out_target_offset); + *out_target_position = gfx::Vector2dF(snap_end.value()); + return true; } gfx::Vector2dF ScrollManager::ScrollByForSnapFling( @@ -681,8 +678,7 @@ gfx::Vector2dF ScrollManager::ScrollByForSnapFling( scroll_state_data->delta_consumed_for_scroll_sequence = delta_consumed_for_scroll_sequence_; ScrollState* scroll_state = ScrollState::Create(std::move(scroll_state_data)); - scroll_state->SetCurrentNativeScrollingElement( - previous_gesture_scrolled_element_); + scroll_state->SetCurrentNativeScrollingNode(previous_gesture_scrolled_node_); CustomizedScroll(*scroll_state); FloatPoint end_position = scrollable_area->ScrollPosition(); @@ -743,16 +739,6 @@ WebInputEventResult ScrollManager::PassScrollGestureEvent( .HandleGestureScrollEvent(gesture_event); } -bool ScrollManager::IsViewportScrollingElement(const Element& element) const { - // The root scroller is the one Element on the page designated to perform - // "viewport actions" like browser controls movement and overscroll glow. - if (!frame_->GetDocument()) - return false; - - return frame_->GetDocument()->GetRootScrollerController().ScrollsViewport( - element); -} - WebInputEventResult ScrollManager::HandleGestureScrollEvent( const WebGestureEvent& gesture_event) { if (!frame_->View()) @@ -788,7 +774,7 @@ WebInputEventResult ScrollManager::HandleGestureScrollEvent( last_gesture_scroll_over_embedded_content_view_ = result.IsOverEmbeddedContentView(); scroll_gesture_handling_node_ = event_target; - previous_gesture_scrolled_element_ = nullptr; + previous_gesture_scrolled_node_ = nullptr; delta_consumed_for_scroll_sequence_ = false; did_scroll_x_for_scroll_gesture_ = false; did_scroll_y_for_scroll_gesture_ = false; @@ -820,7 +806,7 @@ WebInputEventResult ScrollManager::HandleGestureScrollEvent( if (gesture_dom_event_result != DispatchEventResult::kNotCanceled) { DCHECK(gesture_dom_event_result != DispatchEventResult::kCanceledByEventHandler); - return EventHandlingUtil::ToWebInputEventResult( + return event_handling_util::ToWebInputEventResult( gesture_dom_event_result); } } @@ -954,21 +940,21 @@ WebGestureEvent ScrollManager::SynthesizeGestureScrollBegin( void ScrollManager::NotifyScrollPhaseBeginForCustomizedScroll( const ScrollState& scroll_state) { - ScrollCustomization::ScrollDirection direction = - ScrollCustomization::GetScrollDirectionFromDeltas( + scroll_customization::ScrollDirection direction = + scroll_customization::GetScrollDirectionFromDeltas( scroll_state.deltaXHint(), scroll_state.deltaYHint()); for (auto id : current_scroll_chain_) { Node* node = DOMNodeIds::NodeForId(id); - if (node && node->IsElementNode()) - ToElement(node)->WillBeginCustomizedScrollPhase(direction); + if (node) + node->WillBeginCustomizedScrollPhase(direction); } } void ScrollManager::NotifyScrollPhaseEndForCustomizedScroll() { for (auto id : current_scroll_chain_) { Node* node = DOMNodeIds::NodeForId(id); - if (node && node->IsElementNode()) - ToElement(node)->DidEndCustomizedScrollPhase(); + if (node) + node->DidEndCustomizedScrollPhase(); } } |