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 (IsViewportScrollingElement(current_element)) |
| 136 return true; |
| 137 |
| 138 if (current_element == *(frame_->GetDocument()->documentElement())) |
| 139 return true; |
| 140 |
| 141 ScrollableArea* scrollable_area = |
| 142 current_element.GetLayoutBox() |
| 143 ? current_element.GetLayoutBox()->GetScrollableArea() |
| 144 : nullptr; |
| 145 if (!scrollable_area) |
| 146 return false; |
| 147 |
| 148 ScrollOffset current_offset = scrollable_area->GetScrollOffset(); |
| 149 ScrollOffset target_offset = current_offset + ScrollOffset(delta_x, delta_y); |
| 150 ScrollOffset clamped_offset = |
| 151 scrollable_area->ClampScrollOffset(target_offset); |
| 152 return clamped_offset != current_offset; |
| 153 } |
| 154 |
123 bool ScrollManager::LogicalScroll(ScrollDirection direction, | 155 bool ScrollManager::LogicalScroll(ScrollDirection direction, |
124 ScrollGranularity granularity, | 156 ScrollGranularity granularity, |
125 Node* start_node, | 157 Node* start_node, |
126 Node* mouse_press_node) { | 158 Node* mouse_press_node) { |
127 Node* node = start_node; | 159 Node* node = start_node; |
128 | 160 |
129 if (!node) | 161 if (!node) |
130 node = frame_->GetDocument()->FocusedElement(); | 162 node = frame_->GetDocument()->FocusedElement(); |
131 | 163 |
132 if (!node) | 164 if (!node) |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
182 return ToLocalFrame(parent_frame) | 214 return ToLocalFrame(parent_frame) |
183 ->GetEventHandler() | 215 ->GetEventHandler() |
184 .BubblingScroll(direction, granularity, frame_->DeprecatedLocalOwner()); | 216 .BubblingScroll(direction, granularity, frame_->DeprecatedLocalOwner()); |
185 } | 217 } |
186 | 218 |
187 void ScrollManager::SetFrameWasScrolledByUser() { | 219 void ScrollManager::SetFrameWasScrolledByUser() { |
188 if (DocumentLoader* document_loader = frame_->Loader().GetDocumentLoader()) | 220 if (DocumentLoader* document_loader = frame_->Loader().GetDocumentLoader()) |
189 document_loader->GetInitialScrollState().was_scrolled_by_user = true; | 221 document_loader->GetInitialScrollState().was_scrolled_by_user = true; |
190 } | 222 } |
191 | 223 |
192 void ScrollManager::CustomizedScroll(const Node& start_node, | 224 void ScrollManager::CustomizedScroll(ScrollState& scroll_state) { |
193 ScrollState& scroll_state) { | |
194 if (scroll_state.FullyConsumed()) | 225 if (scroll_state.FullyConsumed()) |
195 return; | 226 return; |
196 | 227 |
197 if (scroll_state.deltaX() || scroll_state.deltaY()) | 228 if (scroll_state.deltaX() || scroll_state.deltaY()) |
198 frame_->GetDocument()->UpdateStyleAndLayoutIgnorePendingStylesheets(); | 229 frame_->GetDocument()->UpdateStyleAndLayoutIgnorePendingStylesheets(); |
199 | 230 |
200 if (current_scroll_chain_.empty()) | 231 DCHECK(!current_scroll_chain_.empty()); |
201 RecomputeScrollChain(start_node, current_scroll_chain_); | |
202 scroll_state.SetScrollChain(current_scroll_chain_); | 232 scroll_state.SetScrollChain(current_scroll_chain_); |
203 | 233 |
204 scroll_state.distributeToScrollChainDescendant(); | 234 scroll_state.distributeToScrollChainDescendant(); |
205 } | 235 } |
206 | 236 |
207 void ScrollManager::ComputeScrollRelatedMetrics( | 237 void ScrollManager::ComputeScrollRelatedMetrics( |
208 uint32_t* non_composited_main_thread_scrolling_reasons, | 238 uint32_t* non_composited_main_thread_scrolling_reasons, |
209 int* scroller_size, | 239 int* scroller_size, |
210 bool* scroller_size_updated) { | 240 bool* scroller_size_updated) { |
211 // When scrolling on the main thread, the scrollableArea may or may not be | 241 // 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()); | 346 scroll_gesture_handling_node_->GetLayoutObject()); |
317 | 347 |
318 RecordScrollRelatedMetrics(gesture_event.source_device); | 348 RecordScrollRelatedMetrics(gesture_event.source_device); |
319 | 349 |
320 current_scroll_chain_.clear(); | 350 current_scroll_chain_.clear(); |
321 std::unique_ptr<ScrollStateData> scroll_state_data = | 351 std::unique_ptr<ScrollStateData> scroll_state_data = |
322 WTF::MakeUnique<ScrollStateData>(); | 352 WTF::MakeUnique<ScrollStateData>(); |
323 IntPoint position = FlooredIntPoint(gesture_event.PositionInRootFrame()); | 353 IntPoint position = FlooredIntPoint(gesture_event.PositionInRootFrame()); |
324 scroll_state_data->position_x = position.X(); | 354 scroll_state_data->position_x = position.X(); |
325 scroll_state_data->position_y = position.Y(); | 355 scroll_state_data->position_y = position.Y(); |
| 356 scroll_state_data->delta_x_hint = -gesture_event.DeltaXInRootFrame(); |
| 357 scroll_state_data->delta_y_hint = -gesture_event.DeltaYInRootFrame(); |
326 scroll_state_data->is_beginning = true; | 358 scroll_state_data->is_beginning = true; |
327 scroll_state_data->from_user_input = true; | 359 scroll_state_data->from_user_input = true; |
328 scroll_state_data->is_direct_manipulation = | 360 scroll_state_data->is_direct_manipulation = |
329 gesture_event.source_device == kWebGestureDeviceTouchscreen; | 361 gesture_event.source_device == kWebGestureDeviceTouchscreen; |
330 scroll_state_data->delta_consumed_for_scroll_sequence = | 362 scroll_state_data->delta_consumed_for_scroll_sequence = |
331 delta_consumed_for_scroll_sequence_; | 363 delta_consumed_for_scroll_sequence_; |
332 ScrollState* scroll_state = ScrollState::Create(std::move(scroll_state_data)); | 364 ScrollState* scroll_state = ScrollState::Create(std::move(scroll_state_data)); |
333 CustomizedScroll(*scroll_gesture_handling_node_.Get(), *scroll_state); | 365 RecomputeScrollChain(*scroll_gesture_handling_node_.Get(), *scroll_state, |
| 366 current_scroll_chain_); |
| 367 if (current_scroll_chain_.empty()) |
| 368 return WebInputEventResult::kNotHandled; |
| 369 |
| 370 CustomizedScroll(*scroll_state); |
334 | 371 |
335 if (gesture_event.source_device == kWebGestureDeviceTouchscreen) | 372 if (gesture_event.source_device == kWebGestureDeviceTouchscreen) |
336 UseCounter::Count(frame_->GetDocument(), WebFeature::kScrollByTouch); | 373 UseCounter::Count(frame_->GetDocument(), WebFeature::kScrollByTouch); |
337 else | 374 else |
338 UseCounter::Count(frame_->GetDocument(), WebFeature::kScrollByWheel); | 375 UseCounter::Count(frame_->GetDocument(), WebFeature::kScrollByWheel); |
339 | 376 |
340 return WebInputEventResult::kHandledSystem; | 377 return WebInputEventResult::kHandledSystem; |
341 } | 378 } |
342 | 379 |
343 WebInputEventResult ScrollManager::HandleGestureScrollUpdate( | 380 WebInputEventResult ScrollManager::HandleGestureScrollUpdate( |
(...skipping 21 matching lines...) Expand all Loading... |
365 // Try to send the event to the correct view. | 402 // Try to send the event to the correct view. |
366 WebInputEventResult result = | 403 WebInputEventResult result = |
367 PassScrollGestureEvent(gesture_event, layout_object); | 404 PassScrollGestureEvent(gesture_event, layout_object); |
368 if (result != WebInputEventResult::kNotHandled) { | 405 if (result != WebInputEventResult::kNotHandled) { |
369 // FIXME: we should allow simultaneous scrolling of nested | 406 // FIXME: we should allow simultaneous scrolling of nested |
370 // iframes along perpendicular axes. See crbug.com/466991. | 407 // iframes along perpendicular axes. See crbug.com/466991. |
371 delta_consumed_for_scroll_sequence_ = true; | 408 delta_consumed_for_scroll_sequence_ = true; |
372 return result; | 409 return result; |
373 } | 410 } |
374 | 411 |
| 412 if (current_scroll_chain_.empty()) |
| 413 return WebInputEventResult::kNotHandled; |
| 414 |
375 std::unique_ptr<ScrollStateData> scroll_state_data = | 415 std::unique_ptr<ScrollStateData> scroll_state_data = |
376 WTF::MakeUnique<ScrollStateData>(); | 416 WTF::MakeUnique<ScrollStateData>(); |
377 scroll_state_data->delta_x = delta.Width(); | 417 scroll_state_data->delta_x = delta.Width(); |
378 scroll_state_data->delta_y = delta.Height(); | 418 scroll_state_data->delta_y = delta.Height(); |
379 scroll_state_data->delta_granularity = static_cast<double>( | 419 scroll_state_data->delta_granularity = static_cast<double>( |
380 ToPlatformScrollGranularity(gesture_event.DeltaUnits())); | 420 ToPlatformScrollGranularity(gesture_event.DeltaUnits())); |
381 scroll_state_data->velocity_x = velocity.Width(); | 421 scroll_state_data->velocity_x = velocity.Width(); |
382 scroll_state_data->velocity_y = velocity.Height(); | 422 scroll_state_data->velocity_y = velocity.Height(); |
383 scroll_state_data->position_x = position.X(); | 423 scroll_state_data->position_x = position.X(); |
384 scroll_state_data->position_y = position.Y(); | 424 scroll_state_data->position_y = position.Y(); |
385 scroll_state_data->should_propagate = !gesture_event.PreventPropagation(); | 425 scroll_state_data->should_propagate = !gesture_event.PreventPropagation(); |
386 scroll_state_data->is_in_inertial_phase = | 426 scroll_state_data->is_in_inertial_phase = |
387 gesture_event.InertialPhase() == WebGestureEvent::kMomentumPhase; | 427 gesture_event.InertialPhase() == WebGestureEvent::kMomentumPhase; |
388 scroll_state_data->is_direct_manipulation = | 428 scroll_state_data->is_direct_manipulation = |
389 gesture_event.source_device == kWebGestureDeviceTouchscreen; | 429 gesture_event.source_device == kWebGestureDeviceTouchscreen; |
390 scroll_state_data->from_user_input = true; | 430 scroll_state_data->from_user_input = true; |
391 scroll_state_data->delta_consumed_for_scroll_sequence = | 431 scroll_state_data->delta_consumed_for_scroll_sequence = |
392 delta_consumed_for_scroll_sequence_; | 432 delta_consumed_for_scroll_sequence_; |
393 ScrollState* scroll_state = ScrollState::Create(std::move(scroll_state_data)); | 433 ScrollState* scroll_state = ScrollState::Create(std::move(scroll_state_data)); |
394 if (previous_gesture_scrolled_element_) { | 434 if (previous_gesture_scrolled_element_) { |
395 // The ScrollState needs to know what the current | 435 // The ScrollState needs to know what the current |
396 // native scrolling element is, so that for an | 436 // native scrolling element is, so that for an |
397 // inertial scroll that shouldn't propagate, only the | 437 // inertial scroll that shouldn't propagate, only the |
398 // currently scrolling element responds. | 438 // currently scrolling element responds. |
399 scroll_state->SetCurrentNativeScrollingElement( | 439 scroll_state->SetCurrentNativeScrollingElement( |
400 previous_gesture_scrolled_element_); | 440 previous_gesture_scrolled_element_); |
401 } | 441 } |
402 CustomizedScroll(*node, *scroll_state); | 442 |
| 443 CustomizedScroll(*scroll_state); |
403 previous_gesture_scrolled_element_ = | 444 previous_gesture_scrolled_element_ = |
404 scroll_state->CurrentNativeScrollingElement(); | 445 scroll_state->CurrentNativeScrollingElement(); |
405 delta_consumed_for_scroll_sequence_ = | 446 delta_consumed_for_scroll_sequence_ = |
406 scroll_state->DeltaConsumedForScrollSequence(); | 447 scroll_state->DeltaConsumedForScrollSequence(); |
407 | 448 |
408 bool did_scroll_x = scroll_state->deltaX() != delta.Width(); | 449 bool did_scroll_x = scroll_state->deltaX() != delta.Width(); |
409 bool did_scroll_y = scroll_state->deltaY() != delta.Height(); | 450 bool did_scroll_y = scroll_state->deltaY() != delta.Height(); |
410 | 451 |
411 if ((!previous_gesture_scrolled_element_ || | 452 if ((!previous_gesture_scrolled_element_ || |
412 !IsViewportScrollingElement(*previous_gesture_scrolled_element_)) && | 453 !IsViewportScrollingElement(*previous_gesture_scrolled_element_)) && |
413 GetPage()) | 454 GetPage()) |
414 GetPage()->GetOverscrollController().ResetAccumulated(did_scroll_x, | 455 GetPage()->GetOverscrollController().ResetAccumulated(did_scroll_x, |
415 did_scroll_y); | 456 did_scroll_y); |
416 | 457 |
417 if (did_scroll_x || did_scroll_y) { | 458 if (did_scroll_x || did_scroll_y) { |
418 SetFrameWasScrolledByUser(); | 459 SetFrameWasScrolledByUser(); |
419 return WebInputEventResult::kHandledSystem; | 460 return WebInputEventResult::kHandledSystem; |
420 } | 461 } |
421 | 462 |
422 return WebInputEventResult::kNotHandled; | 463 return WebInputEventResult::kNotHandled; |
423 } | 464 } |
424 | 465 |
425 WebInputEventResult ScrollManager::HandleGestureScrollEnd( | 466 WebInputEventResult ScrollManager::HandleGestureScrollEnd( |
426 const WebGestureEvent& gesture_event) { | 467 const WebGestureEvent& gesture_event) { |
427 Node* node = scroll_gesture_handling_node_; | 468 Node* node = scroll_gesture_handling_node_; |
428 | 469 |
429 if (node && node->GetLayoutObject()) { | 470 if (node && node->GetLayoutObject()) { |
430 PassScrollGestureEvent(gesture_event, node->GetLayoutObject()); | 471 PassScrollGestureEvent(gesture_event, node->GetLayoutObject()); |
| 472 if (current_scroll_chain_.empty()) { |
| 473 ClearGestureScrollState(); |
| 474 return WebInputEventResult::kNotHandled; |
| 475 } |
431 std::unique_ptr<ScrollStateData> scroll_state_data = | 476 std::unique_ptr<ScrollStateData> scroll_state_data = |
432 WTF::MakeUnique<ScrollStateData>(); | 477 WTF::MakeUnique<ScrollStateData>(); |
433 scroll_state_data->is_ending = true; | 478 scroll_state_data->is_ending = true; |
434 scroll_state_data->is_in_inertial_phase = | 479 scroll_state_data->is_in_inertial_phase = |
435 gesture_event.InertialPhase() == WebGestureEvent::kMomentumPhase; | 480 gesture_event.InertialPhase() == WebGestureEvent::kMomentumPhase; |
436 scroll_state_data->from_user_input = true; | 481 scroll_state_data->from_user_input = true; |
437 scroll_state_data->is_direct_manipulation = | 482 scroll_state_data->is_direct_manipulation = |
438 gesture_event.source_device == kWebGestureDeviceTouchscreen; | 483 gesture_event.source_device == kWebGestureDeviceTouchscreen; |
439 scroll_state_data->delta_consumed_for_scroll_sequence = | 484 scroll_state_data->delta_consumed_for_scroll_sequence = |
440 delta_consumed_for_scroll_sequence_; | 485 delta_consumed_for_scroll_sequence_; |
441 ScrollState* scroll_state = | 486 ScrollState* scroll_state = |
442 ScrollState::Create(std::move(scroll_state_data)); | 487 ScrollState::Create(std::move(scroll_state_data)); |
443 CustomizedScroll(*node, *scroll_state); | 488 CustomizedScroll(*scroll_state); |
444 } | 489 } |
445 | 490 |
446 ClearGestureScrollState(); | 491 ClearGestureScrollState(); |
447 return WebInputEventResult::kNotHandled; | 492 return WebInputEventResult::kNotHandled; |
448 } | 493 } |
449 | 494 |
450 Page* ScrollManager::GetPage() const { | 495 Page* ScrollManager::GetPage() const { |
451 return frame_->GetPage(); | 496 return frame_->GetPage(); |
452 } | 497 } |
453 | 498 |
(...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
661 &should_update_capture)) { | 706 &should_update_capture)) { |
662 if (should_update_capture) | 707 if (should_update_capture) |
663 scrollbar_handling_scroll_gesture_ = scrollbar; | 708 scrollbar_handling_scroll_gesture_ = scrollbar; |
664 return true; | 709 return true; |
665 } | 710 } |
666 } | 711 } |
667 return false; | 712 return false; |
668 } | 713 } |
669 | 714 |
670 } // namespace blink | 715 } // namespace blink |
OLD | NEW |