diff options
Diffstat (limited to 'chromium/third_party/blink/renderer/core/page/autoscroll_controller.cc')
-rw-r--r-- | chromium/third_party/blink/renderer/core/page/autoscroll_controller.cc | 104 |
1 files changed, 91 insertions, 13 deletions
diff --git a/chromium/third_party/blink/renderer/core/page/autoscroll_controller.cc b/chromium/third_party/blink/renderer/core/page/autoscroll_controller.cc index 84e4f01a35c..cc558625673 100644 --- a/chromium/third_party/blink/renderer/core/page/autoscroll_controller.cc +++ b/chromium/third_party/blink/renderer/core/page/autoscroll_controller.cc @@ -29,11 +29,13 @@ #include "third_party/blink/renderer/core/page/autoscroll_controller.h" +#include "third_party/blink/renderer/core/dom/node_computed_style.h" #include "third_party/blink/renderer/core/frame/local_frame.h" #include "third_party/blink/renderer/core/frame/local_frame_view.h" #include "third_party/blink/renderer/core/frame/visual_viewport.h" #include "third_party/blink/renderer/core/html/html_frame_owner_element.h" #include "third_party/blink/renderer/core/input/event_handler.h" +#include "third_party/blink/renderer/core/input/scroll_manager.h" #include "third_party/blink/renderer/core/layout/hit_test_result.h" #include "third_party/blink/renderer/core/layout/layout_box.h" #include "third_party/blink/renderer/core/page/chrome_client.h" @@ -143,6 +145,18 @@ void AutoscrollController::StopAutoscrollIfNeeded(LayoutObject* layout_object) { if (pressed_layout_object_ == layout_object) pressed_layout_object_ = nullptr; + if (horizontal_autoscroll_layout_box_ == layout_object) + horizontal_autoscroll_layout_box_ = nullptr; + + if (vertical_autoscroll_layout_box_ == layout_object) + vertical_autoscroll_layout_box_ = nullptr; + + if (MiddleClickAutoscrollInProgress() && !horizontal_autoscroll_layout_box_ && + !vertical_autoscroll_layout_box_) { + page_->GetChromeClient().AutoscrollEnd(layout_object->GetFrame()); + autoscroll_type_ = kNoAutoscroll; + } + if (autoscroll_layout_object_ != layout_object) return; autoscroll_layout_object_ = nullptr; @@ -250,7 +264,16 @@ void AutoscrollController::HandleMouseMoveForMiddleClickAutoscroll( if (!MiddleClickAutoscrollInProgress()) return; - if (!autoscroll_layout_object_->CanBeScrolledAndHasScrollableArea()) { + bool horizontal_autoscroll_possible = + horizontal_autoscroll_layout_box_ && + horizontal_autoscroll_layout_box_->GetNode(); + bool vertical_autoscroll_possible = + vertical_autoscroll_layout_box_ && + vertical_autoscroll_layout_box_->GetNode(); + if (horizontal_autoscroll_possible && + !horizontal_autoscroll_layout_box_->CanBeScrolledAndHasScrollableArea() && + vertical_autoscroll_possible && + !vertical_autoscroll_layout_box_->CanBeScrolledAndHasScrollableArea()) { StopMiddleClickAutoscroll(frame); return; } @@ -277,11 +300,17 @@ void AutoscrollController::HandleMouseMoveForMiddleClickAutoscroll( pow(fabs(distance.Height()), kExponent) * kMultiplier * y_signum); bool can_scroll_vertically = - CanScrollDirection(autoscroll_layout_object_, frame->GetPage(), - ScrollOrientation::kVerticalScroll); + vertical_autoscroll_possible + ? CanScrollDirection(vertical_autoscroll_layout_box_, + frame->GetPage(), + ScrollOrientation::kVerticalScroll) + : false; bool can_scroll_horizontally = - CanScrollDirection(autoscroll_layout_object_, frame->GetPage(), - ScrollOrientation::kHorizontalScroll); + horizontal_autoscroll_possible + ? CanScrollDirection(horizontal_autoscroll_layout_box_, + frame->GetPage(), + ScrollOrientation::kHorizontalScroll) + : false; if (velocity != last_velocity_) { last_velocity_ = velocity; @@ -319,7 +348,8 @@ void AutoscrollController::StopMiddleClickAutoscroll(LocalFrame* frame) { autoscroll_type_ = kNoAutoscroll; page_->GetChromeClient().SetCursorOverridden(false); frame->LocalFrameRoot().GetEventHandler().UpdateCursor(); - autoscroll_layout_object_ = nullptr; + horizontal_autoscroll_layout_box_ = nullptr; + vertical_autoscroll_layout_box_ = nullptr; } bool AutoscrollController::MiddleClickAutoscrollInProgress() const { @@ -338,17 +368,65 @@ void AutoscrollController::StartMiddleClickAutoscroll( if (autoscroll_type_ != kNoAutoscroll) return; - autoscroll_layout_object_ = scrollable; autoscroll_type_ = kAutoscrollForMiddleClick; middle_click_mode_ = kMiddleClickInitial; middle_click_autoscroll_start_pos_global_ = position_global; - bool can_scroll_vertically = - CanScrollDirection(autoscroll_layout_object_, frame->GetPage(), - ScrollOrientation::kVerticalScroll); - bool can_scroll_horizontally = - CanScrollDirection(autoscroll_layout_object_, frame->GetPage(), - ScrollOrientation::kHorizontalScroll); + bool can_scroll_vertically = false; + bool can_scroll_horizontally = false; + + // Scroll propagation can be prevented in either direction independently. + // We check whether autoscroll can be prevented in either direction after + // checking whether the layout box can be scrolled. If propagation is not + // allowed, we do not perform further checks for whether parents can be + // scrolled in that direction. + bool can_propagate_vertically = true; + bool can_propagate_horizontally = true; + + LayoutObject* layout_object = scrollable->GetNode()->GetLayoutObject(); + + while (layout_object && !(can_scroll_horizontally && can_scroll_vertically)) { + if (LayoutBox* layout_box = DynamicTo<LayoutBox>(layout_object)) { + // Check whether the layout box can be scrolled and has horizontal + // scrollable area. + if (can_propagate_vertically && + CanScrollDirection(layout_box, frame->GetPage(), + ScrollOrientation::kVerticalScroll) && + !vertical_autoscroll_layout_box_) { + vertical_autoscroll_layout_box_ = layout_box; + can_scroll_vertically = true; + } + // Check whether the layout box can be scrolled and has vertical + // scrollable area. + if (can_propagate_horizontally && + CanScrollDirection(layout_box, frame->GetPage(), + ScrollOrientation::kHorizontalScroll) && + !horizontal_autoscroll_layout_box_) { + horizontal_autoscroll_layout_box_ = layout_box; + can_scroll_horizontally = true; + } + + can_propagate_vertically = ScrollManager::CanPropagate( + layout_box, ScrollPropagationDirection::kVertical); + can_propagate_horizontally = ScrollManager::CanPropagate( + layout_box, ScrollPropagationDirection::kHorizontal); + } + + // Exit loop if we can't propagate to the parent in any direction or if + // layout boxes have been found for both directions. + if ((!can_propagate_vertically && !can_propagate_horizontally) || + (can_scroll_horizontally && can_scroll_vertically)) + break; + + if (!layout_object->Parent() && + layout_object->GetNode() == layout_object->GetDocument() && + layout_object->GetDocument().LocalOwner()) { + layout_object = + layout_object->GetDocument().LocalOwner()->GetLayoutObject(); + } else { + layout_object = layout_object->Parent(); + } + } UseCounter::Count(frame->GetDocument(), WebFeature::kMiddleClickAutoscrollStart); |