Chromium Code Reviews| 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 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 73 GetAutoscrollController()->MiddleClickAutoscrollInProgress(); | 73 GetAutoscrollController()->MiddleClickAutoscrollInProgress(); |
| 74 } | 74 } |
| 75 | 75 |
| 76 AutoscrollController* ScrollManager::GetAutoscrollController() const { | 76 AutoscrollController* ScrollManager::GetAutoscrollController() const { |
| 77 if (Page* page = frame_->GetPage()) | 77 if (Page* page = frame_->GetPage()) |
| 78 return &page->GetAutoscrollController(); | 78 return &page->GetAutoscrollController(); |
| 79 return nullptr; | 79 return nullptr; |
| 80 } | 80 } |
| 81 | 81 |
| 82 void ScrollManager::RecomputeScrollChain(const Node& start_node, | 82 void ScrollManager::RecomputeScrollChain(const Node& start_node, |
| 83 const ScrollState& scroll_state, | |
| 83 std::deque<int>& scroll_chain) { | 84 std::deque<int>& scroll_chain) { |
| 85 DCHECK(!scroll_chain.size()); | |
| 84 scroll_chain.clear(); | 86 scroll_chain.clear(); |
| 85 | 87 |
| 86 DCHECK(start_node.GetLayoutObject()); | 88 DCHECK(start_node.GetLayoutObject()); |
| 87 LayoutBox* cur_box = start_node.GetLayoutObject()->EnclosingBox(); | 89 LayoutBox* cur_box = start_node.GetLayoutObject()->EnclosingBox(); |
| 88 Element* document_element = frame_->GetDocument()->documentElement(); | 90 Element* document_element = frame_->GetDocument()->documentElement(); |
| 89 | 91 |
| 90 // Scrolling propagates along the containing block chain and ends at the | 92 // Scrolling propagates along the containing block chain and ends at the |
| 91 // RootScroller element. The RootScroller element will have a custom | 93 // RootScroller element. The RootScroller element will have a custom |
| 92 // applyScroll callback that scrolls the frame or element. | 94 // applyScroll callback that scrolls the frame or element. |
| 93 while (cur_box) { | 95 while (cur_box) { |
| 94 Node* cur_node = cur_box->GetNode(); | 96 Node* cur_node = cur_box->GetNode(); |
| 95 Element* cur_element = nullptr; | 97 Element* cur_element = nullptr; |
| 96 | 98 |
| 97 // FIXME: this should reject more elements, as part of crbug.com/410974. | 99 // FIXME: this should reject more elements, as part of crbug.com/410974. |
| 98 if (cur_node && cur_node->IsElementNode()) { | 100 if (cur_node && cur_node->IsElementNode()) { |
| 99 cur_element = ToElement(cur_node); | 101 cur_element = ToElement(cur_node); |
| 100 } else if (cur_node && cur_node->IsDocumentNode()) { | 102 } else if (cur_node && cur_node->IsDocumentNode()) { |
| 101 // In normal circumastances, the documentElement will be the root | 103 // In normal circumastances, the documentElement will be the root |
| 102 // scroller but the documentElement itself isn't a containing block, | 104 // scroller but the documentElement itself isn't a containing block, |
| 103 // that'll be the document node rather than the element. | 105 // that'll be the document node rather than the element. |
| 104 cur_element = document_element; | 106 cur_element = document_element; |
| 105 } | 107 } |
| 106 | 108 |
| 107 if (cur_element) { | 109 if (cur_element) { |
| 108 scroll_chain.push_front(DOMNodeIds::IdForNode(cur_element)); | 110 if (CanScroll(scroll_state, cur_element)) |
|
bokan
2017/06/19 21:43:17
Do we have to do this after we've added our first
sahel
2017/06/22 16:34:20
Once scroll latching is enabled, we can get rid of
bokan
2017/06/22 21:44:37
Right, but I don't mean making the chain just one
sahel
2017/06/23 18:22:03
When scroll latching is off, there will be one GSB
bokan
2017/06/23 18:56:44
Right, thanks for the explanation.
| |
| 111 scroll_chain.push_front(DOMNodeIds::IdForNode(cur_element)); | |
| 109 if (IsViewportScrollingElement(*cur_element) || | 112 if (IsViewportScrollingElement(*cur_element) || |
| 110 cur_element == document_element) | 113 cur_element == document_element) |
| 111 break; | 114 break; |
| 112 } | 115 } |
| 113 | 116 |
| 114 cur_box = cur_box->ContainingBlock(); | 117 cur_box = cur_box->ContainingBlock(); |
| 115 } | 118 } |
| 116 } | 119 } |
| 117 | 120 |
| 121 bool ScrollManager::CanScroll(const ScrollState& scroll_state, | |
| 122 const Element* current_element) { | |
| 123 const double delta_x = scroll_state.isBeginning() ? scroll_state.deltaXHint() | |
| 124 : scroll_state.deltaX(); | |
| 125 const double delta_y = scroll_state.isBeginning() ? scroll_state.deltaYHint() | |
| 126 : scroll_state.deltaY(); | |
| 127 if (!delta_x && !delta_y) | |
| 128 return true; | |
| 129 | |
| 130 if (scroll_state.ignoreDeltaHints()) { | |
| 131 DCHECK(scroll_state.isBeginning()); | |
| 132 return true; | |
| 133 } | |
| 134 | |
| 135 DCHECK(current_element); | |
|
bokan
2017/06/19 21:43:17
Rather than DCHECK, just pass the Element by const
sahel
2017/06/22 16:34:18
Done.
| |
| 136 | |
| 137 if (IsViewportScrollingElement(*current_element)) | |
| 138 return true; | |
| 139 | |
| 140 if (current_element == frame_->GetDocument()->documentElement()) | |
| 141 return true; | |
| 142 | |
| 143 ScrollableArea* scrollable_area = | |
| 144 current_element->GetLayoutBox() | |
| 145 ? current_element->GetLayoutBox()->GetScrollableArea() | |
| 146 : nullptr; | |
| 147 if (!scrollable_area) | |
| 148 return false; | |
| 149 | |
| 150 ScrollOffset current_offset = scrollable_area->GetScrollOffset(); | |
| 151 ScrollOffset target_offset = current_offset + ScrollOffset(delta_x, delta_y); | |
| 152 ScrollOffset clamped_offset = | |
| 153 scrollable_area->ClampScrollOffset(target_offset); | |
| 154 return clamped_offset != current_offset; | |
| 155 } | |
| 156 | |
| 118 bool ScrollManager::LogicalScroll(ScrollDirection direction, | 157 bool ScrollManager::LogicalScroll(ScrollDirection direction, |
| 119 ScrollGranularity granularity, | 158 ScrollGranularity granularity, |
| 120 Node* start_node, | 159 Node* start_node, |
| 121 Node* mouse_press_node) { | 160 Node* mouse_press_node) { |
| 122 Node* node = start_node; | 161 Node* node = start_node; |
| 123 | 162 |
| 124 if (!node) | 163 if (!node) |
| 125 node = frame_->GetDocument()->FocusedElement(); | 164 node = frame_->GetDocument()->FocusedElement(); |
| 126 | 165 |
| 127 if (!node) | 166 if (!node) |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 177 return ToLocalFrame(parent_frame) | 216 return ToLocalFrame(parent_frame) |
| 178 ->GetEventHandler() | 217 ->GetEventHandler() |
| 179 .BubblingScroll(direction, granularity, frame_->DeprecatedLocalOwner()); | 218 .BubblingScroll(direction, granularity, frame_->DeprecatedLocalOwner()); |
| 180 } | 219 } |
| 181 | 220 |
| 182 void ScrollManager::SetFrameWasScrolledByUser() { | 221 void ScrollManager::SetFrameWasScrolledByUser() { |
| 183 if (DocumentLoader* document_loader = frame_->Loader().GetDocumentLoader()) | 222 if (DocumentLoader* document_loader = frame_->Loader().GetDocumentLoader()) |
| 184 document_loader->GetInitialScrollState().was_scrolled_by_user = true; | 223 document_loader->GetInitialScrollState().was_scrolled_by_user = true; |
| 185 } | 224 } |
| 186 | 225 |
| 187 void ScrollManager::CustomizedScroll(const Node& start_node, | 226 void ScrollManager::CustomizedScroll(ScrollState& scroll_state) { |
| 188 ScrollState& scroll_state) { | |
| 189 if (scroll_state.FullyConsumed()) | 227 if (scroll_state.FullyConsumed()) |
| 190 return; | 228 return; |
| 191 | 229 |
| 192 if (scroll_state.deltaX() || scroll_state.deltaY()) | 230 if (scroll_state.deltaX() || scroll_state.deltaY()) |
| 193 frame_->GetDocument()->UpdateStyleAndLayoutIgnorePendingStylesheets(); | 231 frame_->GetDocument()->UpdateStyleAndLayoutIgnorePendingStylesheets(); |
| 194 | 232 |
| 195 if (current_scroll_chain_.empty()) | 233 DCHECK(!current_scroll_chain_.empty()); |
| 196 RecomputeScrollChain(start_node, current_scroll_chain_); | |
| 197 scroll_state.SetScrollChain(current_scroll_chain_); | 234 scroll_state.SetScrollChain(current_scroll_chain_); |
| 198 | 235 |
| 199 scroll_state.distributeToScrollChainDescendant(); | 236 scroll_state.distributeToScrollChainDescendant(); |
| 200 } | 237 } |
| 201 | 238 |
| 202 void ScrollManager::ComputeScrollRelatedMetrics( | 239 void ScrollManager::ComputeScrollRelatedMetrics( |
| 203 uint32_t* non_composited_main_thread_scrolling_reasons, | 240 uint32_t* non_composited_main_thread_scrolling_reasons, |
| 204 int* scroller_size, | 241 int* scroller_size, |
| 205 bool* scroller_size_updated) { | 242 bool* scroller_size_updated) { |
| 206 // When scrolling on the main thread, the scrollableArea may or may not be | 243 // 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... | |
| 311 scroll_gesture_handling_node_->GetLayoutObject()); | 348 scroll_gesture_handling_node_->GetLayoutObject()); |
| 312 | 349 |
| 313 RecordScrollRelatedMetrics(gesture_event.source_device); | 350 RecordScrollRelatedMetrics(gesture_event.source_device); |
| 314 | 351 |
| 315 current_scroll_chain_.clear(); | 352 current_scroll_chain_.clear(); |
| 316 std::unique_ptr<ScrollStateData> scroll_state_data = | 353 std::unique_ptr<ScrollStateData> scroll_state_data = |
| 317 WTF::MakeUnique<ScrollStateData>(); | 354 WTF::MakeUnique<ScrollStateData>(); |
| 318 IntPoint position = FlooredIntPoint(gesture_event.PositionInRootFrame()); | 355 IntPoint position = FlooredIntPoint(gesture_event.PositionInRootFrame()); |
| 319 scroll_state_data->position_x = position.X(); | 356 scroll_state_data->position_x = position.X(); |
| 320 scroll_state_data->position_y = position.Y(); | 357 scroll_state_data->position_y = position.Y(); |
| 358 scroll_state_data->delta_x_hint = -gesture_event.DeltaXInRootFrame(); | |
| 359 scroll_state_data->delta_y_hint = -gesture_event.DeltaYInRootFrame(); | |
| 360 scroll_state_data->ignore_delta_hints = | |
| 361 gesture_event.data.scroll_begin.ignore_delta_hints; | |
| 321 scroll_state_data->is_beginning = true; | 362 scroll_state_data->is_beginning = true; |
| 322 scroll_state_data->from_user_input = true; | 363 scroll_state_data->from_user_input = true; |
| 323 scroll_state_data->is_direct_manipulation = | 364 scroll_state_data->is_direct_manipulation = |
| 324 gesture_event.source_device == kWebGestureDeviceTouchscreen; | 365 gesture_event.source_device == kWebGestureDeviceTouchscreen; |
| 325 scroll_state_data->delta_consumed_for_scroll_sequence = | 366 scroll_state_data->delta_consumed_for_scroll_sequence = |
| 326 delta_consumed_for_scroll_sequence_; | 367 delta_consumed_for_scroll_sequence_; |
| 327 ScrollState* scroll_state = ScrollState::Create(std::move(scroll_state_data)); | 368 ScrollState* scroll_state = ScrollState::Create(std::move(scroll_state_data)); |
| 328 CustomizedScroll(*scroll_gesture_handling_node_.Get(), *scroll_state); | 369 RecomputeScrollChain(*scroll_gesture_handling_node_.Get(), *scroll_state, |
| 370 current_scroll_chain_); | |
| 371 if (current_scroll_chain_.empty()) { | |
|
bokan
2017/06/19 21:43:17
Nit: no {}
sahel
2017/06/22 16:34:18
Done.
| |
| 372 return WebInputEventResult::kNotHandled; | |
| 373 } | |
| 374 CustomizedScroll(*scroll_state); | |
| 329 | 375 |
| 330 if (gesture_event.source_device == kWebGestureDeviceTouchscreen) | 376 if (gesture_event.source_device == kWebGestureDeviceTouchscreen) |
| 331 UseCounter::Count(frame_->GetDocument(), WebFeature::kScrollByTouch); | 377 UseCounter::Count(frame_->GetDocument(), WebFeature::kScrollByTouch); |
| 332 else | 378 else |
| 333 UseCounter::Count(frame_->GetDocument(), WebFeature::kScrollByWheel); | 379 UseCounter::Count(frame_->GetDocument(), WebFeature::kScrollByWheel); |
| 334 | 380 |
| 335 return WebInputEventResult::kHandledSystem; | 381 return WebInputEventResult::kHandledSystem; |
| 336 } | 382 } |
| 337 | 383 |
| 338 WebInputEventResult ScrollManager::HandleGestureScrollUpdate( | 384 WebInputEventResult ScrollManager::HandleGestureScrollUpdate( |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 387 delta_consumed_for_scroll_sequence_; | 433 delta_consumed_for_scroll_sequence_; |
| 388 ScrollState* scroll_state = ScrollState::Create(std::move(scroll_state_data)); | 434 ScrollState* scroll_state = ScrollState::Create(std::move(scroll_state_data)); |
| 389 if (previous_gesture_scrolled_element_) { | 435 if (previous_gesture_scrolled_element_) { |
| 390 // The ScrollState needs to know what the current | 436 // The ScrollState needs to know what the current |
| 391 // native scrolling element is, so that for an | 437 // native scrolling element is, so that for an |
| 392 // inertial scroll that shouldn't propagate, only the | 438 // inertial scroll that shouldn't propagate, only the |
| 393 // currently scrolling element responds. | 439 // currently scrolling element responds. |
| 394 scroll_state->SetCurrentNativeScrollingElement( | 440 scroll_state->SetCurrentNativeScrollingElement( |
| 395 previous_gesture_scrolled_element_); | 441 previous_gesture_scrolled_element_); |
| 396 } | 442 } |
| 397 CustomizedScroll(*node, *scroll_state); | 443 |
| 444 if (current_scroll_chain_.empty()) | |
|
bokan
2017/06/19 21:43:17
We can early out before creating and initializing
sahel
2017/06/22 16:34:19
Done.
| |
| 445 return WebInputEventResult::kNotHandled; | |
| 446 | |
| 447 CustomizedScroll(*scroll_state); | |
| 398 previous_gesture_scrolled_element_ = | 448 previous_gesture_scrolled_element_ = |
| 399 scroll_state->CurrentNativeScrollingElement(); | 449 scroll_state->CurrentNativeScrollingElement(); |
| 400 delta_consumed_for_scroll_sequence_ = | 450 delta_consumed_for_scroll_sequence_ = |
| 401 scroll_state->DeltaConsumedForScrollSequence(); | 451 scroll_state->DeltaConsumedForScrollSequence(); |
| 402 | 452 |
| 403 bool did_scroll_x = scroll_state->deltaX() != delta.Width(); | 453 bool did_scroll_x = scroll_state->deltaX() != delta.Width(); |
| 404 bool did_scroll_y = scroll_state->deltaY() != delta.Height(); | 454 bool did_scroll_y = scroll_state->deltaY() != delta.Height(); |
| 405 | 455 |
| 406 if ((!previous_gesture_scrolled_element_ || | 456 if ((!previous_gesture_scrolled_element_ || |
| 407 !IsViewportScrollingElement(*previous_gesture_scrolled_element_)) && | 457 !IsViewportScrollingElement(*previous_gesture_scrolled_element_)) && |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 428 scroll_state_data->is_ending = true; | 478 scroll_state_data->is_ending = true; |
| 429 scroll_state_data->is_in_inertial_phase = | 479 scroll_state_data->is_in_inertial_phase = |
| 430 gesture_event.InertialPhase() == WebGestureEvent::kMomentumPhase; | 480 gesture_event.InertialPhase() == WebGestureEvent::kMomentumPhase; |
| 431 scroll_state_data->from_user_input = true; | 481 scroll_state_data->from_user_input = true; |
| 432 scroll_state_data->is_direct_manipulation = | 482 scroll_state_data->is_direct_manipulation = |
| 433 gesture_event.source_device == kWebGestureDeviceTouchscreen; | 483 gesture_event.source_device == kWebGestureDeviceTouchscreen; |
| 434 scroll_state_data->delta_consumed_for_scroll_sequence = | 484 scroll_state_data->delta_consumed_for_scroll_sequence = |
| 435 delta_consumed_for_scroll_sequence_; | 485 delta_consumed_for_scroll_sequence_; |
| 436 ScrollState* scroll_state = | 486 ScrollState* scroll_state = |
| 437 ScrollState::Create(std::move(scroll_state_data)); | 487 ScrollState::Create(std::move(scroll_state_data)); |
| 438 CustomizedScroll(*node, *scroll_state); | 488 if (!current_scroll_chain_.empty()) |
|
bokan
2017/06/19 21:43:17
We should skip the scroll_state_data initializatio
sahel
2017/06/22 16:34:18
Done.
| |
| 489 CustomizedScroll(*scroll_state); | |
| 439 } | 490 } |
| 440 | 491 |
| 441 ClearGestureScrollState(); | 492 ClearGestureScrollState(); |
| 442 return WebInputEventResult::kNotHandled; | 493 return WebInputEventResult::kNotHandled; |
| 443 } | 494 } |
| 444 | 495 |
| 445 Page* ScrollManager::GetPage() const { | 496 Page* ScrollManager::GetPage() const { |
| 446 return frame_->GetPage(); | 497 return frame_->GetPage(); |
| 447 } | 498 } |
| 448 | 499 |
| (...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 656 &should_update_capture)) { | 707 &should_update_capture)) { |
| 657 if (should_update_capture) | 708 if (should_update_capture) |
| 658 scrollbar_handling_scroll_gesture_ = scrollbar; | 709 scrollbar_handling_scroll_gesture_ = scrollbar; |
| 659 return true; | 710 return true; |
| 660 } | 711 } |
| 661 } | 712 } |
| 662 return false; | 713 return false; |
| 663 } | 714 } |
| 664 | 715 |
| 665 } // namespace blink | 716 } // namespace blink |
| OLD | NEW |