| OLD | NEW |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "core/input/ScrollManager.h" | 5 #include "core/input/ScrollManager.h" |
| 6 | 6 |
| 7 #include <memory> | 7 #include <memory> |
| 8 #include "core/dom/DOMNodeIds.h" | 8 #include "core/dom/DOMNodeIds.h" |
| 9 #include "core/events/GestureEvent.h" | 9 #include "core/events/GestureEvent.h" |
| 10 #include "core/frame/BrowserControls.h" | 10 #include "core/frame/BrowserControls.h" |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 78 GetAutoscrollController()->MiddleClickAutoscrollInProgress(); | 78 GetAutoscrollController()->MiddleClickAutoscrollInProgress(); |
| 79 } | 79 } |
| 80 | 80 |
| 81 AutoscrollController* ScrollManager::GetAutoscrollController() const { | 81 AutoscrollController* ScrollManager::GetAutoscrollController() const { |
| 82 if (Page* page = frame_->GetPage()) | 82 if (Page* page = frame_->GetPage()) |
| 83 return &page->GetAutoscrollController(); | 83 return &page->GetAutoscrollController(); |
| 84 return nullptr; | 84 return nullptr; |
| 85 } | 85 } |
| 86 | 86 |
| 87 void ScrollManager::RecomputeScrollChain(const Node& start_node, | 87 void ScrollManager::RecomputeScrollChain(const Node& start_node, |
| 88 const ScrollState& scroll_state, |
| 88 std::deque<int>& scroll_chain) { | 89 std::deque<int>& scroll_chain) { |
| 90 DCHECK(!scroll_chain.size()); |
| 89 scroll_chain.clear(); | 91 scroll_chain.clear(); |
| 90 | 92 |
| 91 DCHECK(start_node.GetLayoutObject()); | 93 DCHECK(start_node.GetLayoutObject()); |
| 92 LayoutBox* cur_box = start_node.GetLayoutObject()->EnclosingBox(); | 94 LayoutBox* cur_box = start_node.GetLayoutObject()->EnclosingBox(); |
| 93 Element* document_element = frame_->GetDocument()->documentElement(); | 95 Element* document_element = frame_->GetDocument()->documentElement(); |
| 94 | 96 |
| 95 // Scrolling propagates along the containing block chain and ends at the | 97 // Scrolling propagates along the containing block chain and ends at the |
| 96 // RootScroller element. The RootScroller element will have a custom | 98 // RootScroller element. The RootScroller element will have a custom |
| 97 // applyScroll callback that scrolls the frame or element. | 99 // applyScroll callback that scrolls the frame or element. |
| 98 while (cur_box) { | 100 while (cur_box) { |
| 99 Node* cur_node = cur_box->GetNode(); | 101 Node* cur_node = cur_box->GetNode(); |
| 100 Element* cur_element = nullptr; | 102 Element* cur_element = nullptr; |
| 101 | 103 |
| 102 // FIXME: this should reject more elements, as part of crbug.com/410974. | 104 // FIXME: this should reject more elements, as part of crbug.com/410974. |
| 103 if (cur_node && cur_node->IsElementNode()) { | 105 if (cur_node && cur_node->IsElementNode()) { |
| 104 cur_element = ToElement(cur_node); | 106 cur_element = ToElement(cur_node); |
| 105 } else if (cur_node && cur_node->IsDocumentNode()) { | 107 } else if (cur_node && cur_node->IsDocumentNode()) { |
| 106 // In normal circumastances, the documentElement will be the root | 108 // In normal circumastances, the documentElement will be the root |
| 107 // scroller but the documentElement itself isn't a containing block, | 109 // scroller but the documentElement itself isn't a containing block, |
| 108 // that'll be the document node rather than the element. | 110 // that'll be the document node rather than the element. |
| 109 cur_element = document_element; | 111 cur_element = document_element; |
| 110 } | 112 } |
| 111 | 113 |
| 112 if (cur_element) { | 114 if (cur_element) { |
| 113 scroll_chain.push_front(DOMNodeIds::IdForNode(cur_element)); | 115 if (CanScroll(scroll_state, *cur_element)) |
| 116 scroll_chain.push_front(DOMNodeIds::IdForNode(cur_element)); |
| 114 if (IsViewportScrollingElement(*cur_element) || | 117 if (IsViewportScrollingElement(*cur_element) || |
| 115 cur_element == document_element) | 118 cur_element == document_element) |
| 116 break; | 119 break; |
| 117 } | 120 } |
| 118 | 121 |
| 119 cur_box = cur_box->ContainingBlock(); | 122 cur_box = cur_box->ContainingBlock(); |
| 120 } | 123 } |
| 121 } | 124 } |
| 122 | 125 |
| 126 bool ScrollManager::CanScroll(const ScrollState& scroll_state, |
| 127 const Element& current_element) { |
| 128 const double delta_x = scroll_state.isBeginning() ? scroll_state.deltaXHint() |
| 129 : scroll_state.deltaX(); |
| 130 const double delta_y = scroll_state.isBeginning() ? scroll_state.deltaYHint() |
| 131 : scroll_state.deltaY(); |
| 132 if (!delta_x && !delta_y) |
| 133 return true; |
| 134 |
| 135 if (scroll_state.ignoreDeltaHints()) { |
| 136 DCHECK(scroll_state.isBeginning()); |
| 137 return true; |
| 138 } |
| 139 |
| 140 if (IsViewportScrollingElement(current_element)) |
| 141 return true; |
| 142 |
| 143 if (current_element == *(frame_->GetDocument()->documentElement())) |
| 144 return true; |
| 145 |
| 146 ScrollableArea* scrollable_area = |
| 147 current_element.GetLayoutBox() |
| 148 ? current_element.GetLayoutBox()->GetScrollableArea() |
| 149 : nullptr; |
| 150 if (!scrollable_area) |
| 151 return false; |
| 152 |
| 153 ScrollOffset current_offset = scrollable_area->GetScrollOffset(); |
| 154 ScrollOffset target_offset = current_offset + ScrollOffset(delta_x, delta_y); |
| 155 ScrollOffset clamped_offset = |
| 156 scrollable_area->ClampScrollOffset(target_offset); |
| 157 return clamped_offset != current_offset; |
| 158 } |
| 159 |
| 123 bool ScrollManager::LogicalScroll(ScrollDirection direction, | 160 bool ScrollManager::LogicalScroll(ScrollDirection direction, |
| 124 ScrollGranularity granularity, | 161 ScrollGranularity granularity, |
| 125 Node* start_node, | 162 Node* start_node, |
| 126 Node* mouse_press_node) { | 163 Node* mouse_press_node) { |
| 127 Node* node = start_node; | 164 Node* node = start_node; |
| 128 | 165 |
| 129 if (!node) | 166 if (!node) |
| 130 node = frame_->GetDocument()->FocusedElement(); | 167 node = frame_->GetDocument()->FocusedElement(); |
| 131 | 168 |
| 132 if (!node) | 169 if (!node) |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 182 return ToLocalFrame(parent_frame) | 219 return ToLocalFrame(parent_frame) |
| 183 ->GetEventHandler() | 220 ->GetEventHandler() |
| 184 .BubblingScroll(direction, granularity, frame_->DeprecatedLocalOwner()); | 221 .BubblingScroll(direction, granularity, frame_->DeprecatedLocalOwner()); |
| 185 } | 222 } |
| 186 | 223 |
| 187 void ScrollManager::SetFrameWasScrolledByUser() { | 224 void ScrollManager::SetFrameWasScrolledByUser() { |
| 188 if (DocumentLoader* document_loader = frame_->Loader().GetDocumentLoader()) | 225 if (DocumentLoader* document_loader = frame_->Loader().GetDocumentLoader()) |
| 189 document_loader->GetInitialScrollState().was_scrolled_by_user = true; | 226 document_loader->GetInitialScrollState().was_scrolled_by_user = true; |
| 190 } | 227 } |
| 191 | 228 |
| 192 void ScrollManager::CustomizedScroll(const Node& start_node, | 229 void ScrollManager::CustomizedScroll(ScrollState& scroll_state) { |
| 193 ScrollState& scroll_state) { | |
| 194 if (scroll_state.FullyConsumed()) | 230 if (scroll_state.FullyConsumed()) |
| 195 return; | 231 return; |
| 196 | 232 |
| 197 if (scroll_state.deltaX() || scroll_state.deltaY()) | 233 if (scroll_state.deltaX() || scroll_state.deltaY()) |
| 198 frame_->GetDocument()->UpdateStyleAndLayoutIgnorePendingStylesheets(); | 234 frame_->GetDocument()->UpdateStyleAndLayoutIgnorePendingStylesheets(); |
| 199 | 235 |
| 200 if (current_scroll_chain_.empty()) | 236 DCHECK(!current_scroll_chain_.empty()); |
| 201 RecomputeScrollChain(start_node, current_scroll_chain_); | |
| 202 scroll_state.SetScrollChain(current_scroll_chain_); | 237 scroll_state.SetScrollChain(current_scroll_chain_); |
| 203 | 238 |
| 204 scroll_state.distributeToScrollChainDescendant(); | 239 scroll_state.distributeToScrollChainDescendant(); |
| 205 } | 240 } |
| 206 | 241 |
| 207 void ScrollManager::ComputeScrollRelatedMetrics( | 242 void ScrollManager::ComputeScrollRelatedMetrics( |
| 208 uint32_t* non_composited_main_thread_scrolling_reasons, | 243 uint32_t* non_composited_main_thread_scrolling_reasons, |
| 209 int* scroller_size, | 244 int* scroller_size, |
| 210 bool* scroller_size_updated) { | 245 bool* scroller_size_updated) { |
| 211 // When scrolling on the main thread, the scrollableArea may or may not be | 246 // When scrolling on the main thread, the scrollableArea may or may not be |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 316 scroll_gesture_handling_node_->GetLayoutObject()); | 351 scroll_gesture_handling_node_->GetLayoutObject()); |
| 317 | 352 |
| 318 RecordScrollRelatedMetrics(gesture_event.source_device); | 353 RecordScrollRelatedMetrics(gesture_event.source_device); |
| 319 | 354 |
| 320 current_scroll_chain_.clear(); | 355 current_scroll_chain_.clear(); |
| 321 std::unique_ptr<ScrollStateData> scroll_state_data = | 356 std::unique_ptr<ScrollStateData> scroll_state_data = |
| 322 WTF::MakeUnique<ScrollStateData>(); | 357 WTF::MakeUnique<ScrollStateData>(); |
| 323 IntPoint position = FlooredIntPoint(gesture_event.PositionInRootFrame()); | 358 IntPoint position = FlooredIntPoint(gesture_event.PositionInRootFrame()); |
| 324 scroll_state_data->position_x = position.X(); | 359 scroll_state_data->position_x = position.X(); |
| 325 scroll_state_data->position_y = position.Y(); | 360 scroll_state_data->position_y = position.Y(); |
| 361 scroll_state_data->delta_x_hint = -gesture_event.DeltaXInRootFrame(); |
| 362 scroll_state_data->delta_y_hint = -gesture_event.DeltaYInRootFrame(); |
| 363 scroll_state_data->ignore_delta_hints = |
| 364 gesture_event.data.scroll_begin.ignore_delta_hints; |
| 326 scroll_state_data->is_beginning = true; | 365 scroll_state_data->is_beginning = true; |
| 327 scroll_state_data->from_user_input = true; | 366 scroll_state_data->from_user_input = true; |
| 328 scroll_state_data->is_direct_manipulation = | 367 scroll_state_data->is_direct_manipulation = |
| 329 gesture_event.source_device == kWebGestureDeviceTouchscreen; | 368 gesture_event.source_device == kWebGestureDeviceTouchscreen; |
| 330 scroll_state_data->delta_consumed_for_scroll_sequence = | 369 scroll_state_data->delta_consumed_for_scroll_sequence = |
| 331 delta_consumed_for_scroll_sequence_; | 370 delta_consumed_for_scroll_sequence_; |
| 332 ScrollState* scroll_state = ScrollState::Create(std::move(scroll_state_data)); | 371 ScrollState* scroll_state = ScrollState::Create(std::move(scroll_state_data)); |
| 333 CustomizedScroll(*scroll_gesture_handling_node_.Get(), *scroll_state); | 372 RecomputeScrollChain(*scroll_gesture_handling_node_.Get(), *scroll_state, |
| 373 current_scroll_chain_); |
| 374 if (current_scroll_chain_.empty()) |
| 375 return WebInputEventResult::kNotHandled; |
| 376 |
| 377 CustomizedScroll(*scroll_state); |
| 334 | 378 |
| 335 if (gesture_event.source_device == kWebGestureDeviceTouchscreen) | 379 if (gesture_event.source_device == kWebGestureDeviceTouchscreen) |
| 336 UseCounter::Count(frame_->GetDocument(), WebFeature::kScrollByTouch); | 380 UseCounter::Count(frame_->GetDocument(), WebFeature::kScrollByTouch); |
| 337 else | 381 else |
| 338 UseCounter::Count(frame_->GetDocument(), WebFeature::kScrollByWheel); | 382 UseCounter::Count(frame_->GetDocument(), WebFeature::kScrollByWheel); |
| 339 | 383 |
| 340 return WebInputEventResult::kHandledSystem; | 384 return WebInputEventResult::kHandledSystem; |
| 341 } | 385 } |
| 342 | 386 |
| 343 WebInputEventResult ScrollManager::HandleGestureScrollUpdate( | 387 WebInputEventResult ScrollManager::HandleGestureScrollUpdate( |
| (...skipping 21 matching lines...) Expand all Loading... |
| 365 // Try to send the event to the correct view. | 409 // Try to send the event to the correct view. |
| 366 WebInputEventResult result = | 410 WebInputEventResult result = |
| 367 PassScrollGestureEvent(gesture_event, layout_object); | 411 PassScrollGestureEvent(gesture_event, layout_object); |
| 368 if (result != WebInputEventResult::kNotHandled) { | 412 if (result != WebInputEventResult::kNotHandled) { |
| 369 // FIXME: we should allow simultaneous scrolling of nested | 413 // FIXME: we should allow simultaneous scrolling of nested |
| 370 // iframes along perpendicular axes. See crbug.com/466991. | 414 // iframes along perpendicular axes. See crbug.com/466991. |
| 371 delta_consumed_for_scroll_sequence_ = true; | 415 delta_consumed_for_scroll_sequence_ = true; |
| 372 return result; | 416 return result; |
| 373 } | 417 } |
| 374 | 418 |
| 419 if (current_scroll_chain_.empty()) |
| 420 return WebInputEventResult::kNotHandled; |
| 421 |
| 375 std::unique_ptr<ScrollStateData> scroll_state_data = | 422 std::unique_ptr<ScrollStateData> scroll_state_data = |
| 376 WTF::MakeUnique<ScrollStateData>(); | 423 WTF::MakeUnique<ScrollStateData>(); |
| 377 scroll_state_data->delta_x = delta.Width(); | 424 scroll_state_data->delta_x = delta.Width(); |
| 378 scroll_state_data->delta_y = delta.Height(); | 425 scroll_state_data->delta_y = delta.Height(); |
| 379 scroll_state_data->delta_granularity = static_cast<double>( | 426 scroll_state_data->delta_granularity = static_cast<double>( |
| 380 ToPlatformScrollGranularity(gesture_event.DeltaUnits())); | 427 ToPlatformScrollGranularity(gesture_event.DeltaUnits())); |
| 381 scroll_state_data->velocity_x = velocity.Width(); | 428 scroll_state_data->velocity_x = velocity.Width(); |
| 382 scroll_state_data->velocity_y = velocity.Height(); | 429 scroll_state_data->velocity_y = velocity.Height(); |
| 383 scroll_state_data->position_x = position.X(); | 430 scroll_state_data->position_x = position.X(); |
| 384 scroll_state_data->position_y = position.Y(); | 431 scroll_state_data->position_y = position.Y(); |
| 385 scroll_state_data->should_propagate = !gesture_event.PreventPropagation(); | 432 scroll_state_data->should_propagate = !gesture_event.PreventPropagation(); |
| 386 scroll_state_data->is_in_inertial_phase = | 433 scroll_state_data->is_in_inertial_phase = |
| 387 gesture_event.InertialPhase() == WebGestureEvent::kMomentumPhase; | 434 gesture_event.InertialPhase() == WebGestureEvent::kMomentumPhase; |
| 388 scroll_state_data->is_direct_manipulation = | 435 scroll_state_data->is_direct_manipulation = |
| 389 gesture_event.source_device == kWebGestureDeviceTouchscreen; | 436 gesture_event.source_device == kWebGestureDeviceTouchscreen; |
| 390 scroll_state_data->from_user_input = true; | 437 scroll_state_data->from_user_input = true; |
| 391 scroll_state_data->delta_consumed_for_scroll_sequence = | 438 scroll_state_data->delta_consumed_for_scroll_sequence = |
| 392 delta_consumed_for_scroll_sequence_; | 439 delta_consumed_for_scroll_sequence_; |
| 393 ScrollState* scroll_state = ScrollState::Create(std::move(scroll_state_data)); | 440 ScrollState* scroll_state = ScrollState::Create(std::move(scroll_state_data)); |
| 394 if (previous_gesture_scrolled_element_) { | 441 if (previous_gesture_scrolled_element_) { |
| 395 // The ScrollState needs to know what the current | 442 // The ScrollState needs to know what the current |
| 396 // native scrolling element is, so that for an | 443 // native scrolling element is, so that for an |
| 397 // inertial scroll that shouldn't propagate, only the | 444 // inertial scroll that shouldn't propagate, only the |
| 398 // currently scrolling element responds. | 445 // currently scrolling element responds. |
| 399 scroll_state->SetCurrentNativeScrollingElement( | 446 scroll_state->SetCurrentNativeScrollingElement( |
| 400 previous_gesture_scrolled_element_); | 447 previous_gesture_scrolled_element_); |
| 401 } | 448 } |
| 402 CustomizedScroll(*node, *scroll_state); | 449 |
| 450 CustomizedScroll(*scroll_state); |
| 403 previous_gesture_scrolled_element_ = | 451 previous_gesture_scrolled_element_ = |
| 404 scroll_state->CurrentNativeScrollingElement(); | 452 scroll_state->CurrentNativeScrollingElement(); |
| 405 delta_consumed_for_scroll_sequence_ = | 453 delta_consumed_for_scroll_sequence_ = |
| 406 scroll_state->DeltaConsumedForScrollSequence(); | 454 scroll_state->DeltaConsumedForScrollSequence(); |
| 407 | 455 |
| 408 bool did_scroll_x = scroll_state->deltaX() != delta.Width(); | 456 bool did_scroll_x = scroll_state->deltaX() != delta.Width(); |
| 409 bool did_scroll_y = scroll_state->deltaY() != delta.Height(); | 457 bool did_scroll_y = scroll_state->deltaY() != delta.Height(); |
| 410 | 458 |
| 411 if ((!previous_gesture_scrolled_element_ || | 459 if ((!previous_gesture_scrolled_element_ || |
| 412 !IsViewportScrollingElement(*previous_gesture_scrolled_element_)) && | 460 !IsViewportScrollingElement(*previous_gesture_scrolled_element_)) && |
| 413 GetPage()) | 461 GetPage()) |
| 414 GetPage()->GetOverscrollController().ResetAccumulated(did_scroll_x, | 462 GetPage()->GetOverscrollController().ResetAccumulated(did_scroll_x, |
| 415 did_scroll_y); | 463 did_scroll_y); |
| 416 | 464 |
| 417 if (did_scroll_x || did_scroll_y) { | 465 if (did_scroll_x || did_scroll_y) { |
| 418 SetFrameWasScrolledByUser(); | 466 SetFrameWasScrolledByUser(); |
| 419 return WebInputEventResult::kHandledSystem; | 467 return WebInputEventResult::kHandledSystem; |
| 420 } | 468 } |
| 421 | 469 |
| 422 return WebInputEventResult::kNotHandled; | 470 return WebInputEventResult::kNotHandled; |
| 423 } | 471 } |
| 424 | 472 |
| 425 WebInputEventResult ScrollManager::HandleGestureScrollEnd( | 473 WebInputEventResult ScrollManager::HandleGestureScrollEnd( |
| 426 const WebGestureEvent& gesture_event) { | 474 const WebGestureEvent& gesture_event) { |
| 427 Node* node = scroll_gesture_handling_node_; | 475 Node* node = scroll_gesture_handling_node_; |
| 428 | 476 |
| 429 if (node && node->GetLayoutObject()) { | 477 if (node && node->GetLayoutObject()) { |
| 430 PassScrollGestureEvent(gesture_event, node->GetLayoutObject()); | 478 PassScrollGestureEvent(gesture_event, node->GetLayoutObject()); |
| 479 if (current_scroll_chain_.empty()) { |
| 480 ClearGestureScrollState(); |
| 481 return WebInputEventResult::kNotHandled; |
| 482 } |
| 431 std::unique_ptr<ScrollStateData> scroll_state_data = | 483 std::unique_ptr<ScrollStateData> scroll_state_data = |
| 432 WTF::MakeUnique<ScrollStateData>(); | 484 WTF::MakeUnique<ScrollStateData>(); |
| 433 scroll_state_data->is_ending = true; | 485 scroll_state_data->is_ending = true; |
| 434 scroll_state_data->is_in_inertial_phase = | 486 scroll_state_data->is_in_inertial_phase = |
| 435 gesture_event.InertialPhase() == WebGestureEvent::kMomentumPhase; | 487 gesture_event.InertialPhase() == WebGestureEvent::kMomentumPhase; |
| 436 scroll_state_data->from_user_input = true; | 488 scroll_state_data->from_user_input = true; |
| 437 scroll_state_data->is_direct_manipulation = | 489 scroll_state_data->is_direct_manipulation = |
| 438 gesture_event.source_device == kWebGestureDeviceTouchscreen; | 490 gesture_event.source_device == kWebGestureDeviceTouchscreen; |
| 439 scroll_state_data->delta_consumed_for_scroll_sequence = | 491 scroll_state_data->delta_consumed_for_scroll_sequence = |
| 440 delta_consumed_for_scroll_sequence_; | 492 delta_consumed_for_scroll_sequence_; |
| 441 ScrollState* scroll_state = | 493 ScrollState* scroll_state = |
| 442 ScrollState::Create(std::move(scroll_state_data)); | 494 ScrollState::Create(std::move(scroll_state_data)); |
| 443 CustomizedScroll(*node, *scroll_state); | 495 CustomizedScroll(*scroll_state); |
| 444 } | 496 } |
| 445 | 497 |
| 446 ClearGestureScrollState(); | 498 ClearGestureScrollState(); |
| 447 return WebInputEventResult::kNotHandled; | 499 return WebInputEventResult::kNotHandled; |
| 448 } | 500 } |
| 449 | 501 |
| 450 Page* ScrollManager::GetPage() const { | 502 Page* ScrollManager::GetPage() const { |
| 451 return frame_->GetPage(); | 503 return frame_->GetPage(); |
| 452 } | 504 } |
| 453 | 505 |
| (...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 661 &should_update_capture)) { | 713 &should_update_capture)) { |
| 662 if (should_update_capture) | 714 if (should_update_capture) |
| 663 scrollbar_handling_scroll_gesture_ = scrollbar; | 715 scrollbar_handling_scroll_gesture_ = scrollbar; |
| 664 return true; | 716 return true; |
| 665 } | 717 } |
| 666 } | 718 } |
| 667 return false; | 719 return false; |
| 668 } | 720 } |
| 669 | 721 |
| 670 } // namespace blink | 722 } // namespace blink |
| OLD | NEW |