summaryrefslogtreecommitdiff
path: root/chromium/third_party/blink/renderer/core/scroll/smooth_scroll_sequencer.cc
blob: 707905fc1466afb36c008dd573b148ab9b493453 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
// Copyright (c) 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "third_party/blink/renderer/core/scroll/smooth_scroll_sequencer.h"

#include "third_party/blink/renderer/core/scroll/programmatic_scroll_animator.h"
#include "third_party/blink/renderer/core/scroll/scrollable_area.h"

namespace blink {

void SequencedScroll::Trace(Visitor* visitor) {
  visitor->Trace(scrollable_area);
}

void SmoothScrollSequencer::QueueAnimation(
    ScrollableArea* scrollable,
    ScrollOffset offset,
    mojom::blink::ScrollBehavior behavior) {
  if (scrollable->ClampScrollOffset(offset) != scrollable->GetScrollOffset()) {
    queue_.push_back(
        MakeGarbageCollected<SequencedScroll>(scrollable, offset, behavior));
  }
}

void SmoothScrollSequencer::RunQueuedAnimations() {
  if (queue_.IsEmpty()) {
    current_scrollable_ = nullptr;
    scroll_type_ = mojom::blink::ScrollType::kProgrammatic;
    return;
  }
  SequencedScroll* sequenced_scroll = queue_.back();
  queue_.pop_back();
  current_scrollable_ = sequenced_scroll->scrollable_area;
  current_scrollable_->SetScrollOffset(sequenced_scroll->scroll_offset,
                                       mojom::blink::ScrollType::kSequenced,
                                       sequenced_scroll->scroll_behavior);
}

void SmoothScrollSequencer::AbortAnimations() {
  if (current_scrollable_) {
    current_scrollable_->CancelProgrammaticScrollAnimation();
    current_scrollable_ = nullptr;
  }
  queue_.clear();
  scroll_type_ = mojom::blink::ScrollType::kProgrammatic;
}

bool SmoothScrollSequencer::FilterNewScrollOrAbortCurrent(
    mojom::blink::ScrollType incoming_type) {
  // Allow the incoming scroll to co-exist if its scroll type is
  // kSequenced, kClamping, or kAnchoring
  if (incoming_type == mojom::blink::ScrollType::kSequenced ||
      incoming_type == mojom::blink::ScrollType::kClamping ||
      incoming_type == mojom::blink::ScrollType::kAnchoring)
    return false;

  // If the current sequenced scroll is UserScroll, but the incoming scroll is
  // not, filter the incoming scroll. See crbug.com/913009 for more details.
  if (scroll_type_ == mojom::blink::ScrollType::kUser &&
      incoming_type != mojom::blink::ScrollType::kUser)
    return true;

  // Otherwise, abort the current sequenced scroll.
  AbortAnimations();
  return false;
}

void SmoothScrollSequencer::DidDisposeScrollableArea(
    const ScrollableArea& area) {
  for (Member<SequencedScroll>& sequenced_scroll : queue_) {
    if (sequenced_scroll->scrollable_area.Get() == &area) {
      AbortAnimations();
      break;
    }
  }
}

void SmoothScrollSequencer::Trace(Visitor* visitor) {
  visitor->Trace(queue_);
  visitor->Trace(current_scrollable_);
}

}  // namespace blink