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