1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "cc/layers/viewport.h"
7 #include "base/logging.h"
8 #include "cc/input/top_controls_manager.h"
9 #include "cc/trees/layer_tree_host_impl.h"
10 #include "cc/trees/layer_tree_impl.h"
11 #include "ui/gfx/geometry/vector2d_conversions.h"
12 #include "ui/gfx/geometry/vector2d_f.h"
17 scoped_ptr
<Viewport
> Viewport::Create(
18 LayerTreeHostImpl
* host_impl
) {
19 return make_scoped_ptr(new Viewport(host_impl
));
22 Viewport::Viewport(LayerTreeHostImpl
* host_impl
)
23 : host_impl_(host_impl
) {
27 Viewport::ScrollResult
Viewport::ScrollBy(const gfx::Vector2dF
& delta
,
28 const gfx::Point
& viewport_point
,
29 bool is_wheel_scroll
) {
30 gfx::Vector2dF content_delta
= delta
;
33 if (ShouldTopControlsConsumeScroll(delta
)) {
34 result
.top_controls_applied_delta
= ScrollTopControls(delta
);
35 content_delta
-= result
.top_controls_applied_delta
;
38 gfx::Vector2dF pending_content_delta
= content_delta
;
40 if (OuterScrollLayer()) {
41 pending_content_delta
-= host_impl_
->ScrollLayer(OuterScrollLayer(),
42 pending_content_delta
,
47 // TODO(bokan): This shouldn't be needed but removing it causes subtle
48 // viewport movement during top controls manipulation.
49 if (!gfx::ToRoundedVector2d(pending_content_delta
).IsZero()) {
50 pending_content_delta
-= host_impl_
->ScrollLayer(InnerScrollLayer(),
51 pending_content_delta
,
54 result
.unused_scroll_delta
= AdjustOverscroll(pending_content_delta
);
58 result
.applied_delta
= content_delta
- pending_content_delta
;
62 gfx::Vector2dF
Viewport::ScrollTopControls(const gfx::Vector2dF
& delta
) {
63 gfx::Vector2dF excess_delta
=
64 host_impl_
->top_controls_manager()->ScrollBy(delta
);
66 return delta
- excess_delta
;
69 bool Viewport::ShouldTopControlsConsumeScroll(
70 const gfx::Vector2dF
& scroll_delta
) const {
71 // Always consume if it's in the direction to show the top controls.
72 if (scroll_delta
.y() < 0)
75 if (TotalScrollOffset().y() < MaxTotalScrollOffset().y())
81 gfx::Vector2dF
Viewport::AdjustOverscroll(const gfx::Vector2dF
& delta
) const {
82 const float kEpsilon
= 0.1f
;
83 gfx::Vector2dF adjusted
= delta
;
85 if (std::abs(adjusted
.x()) < kEpsilon
)
87 if (std::abs(adjusted
.y()) < kEpsilon
)
90 // Disable overscroll on axes which are impossible to scroll.
91 if (host_impl_
->settings().report_overscroll_only_for_scrollable_axes
) {
92 if (std::abs(MaxTotalScrollOffset().x()) <= kEpsilon
||
93 !InnerScrollLayer()->user_scrollable_horizontal())
95 if (std::abs(MaxTotalScrollOffset().y()) <= kEpsilon
||
96 !InnerScrollLayer()->user_scrollable_vertical())
103 gfx::ScrollOffset
Viewport::MaxTotalScrollOffset() const {
104 gfx::ScrollOffset offset
;
106 offset
+= InnerScrollLayer()->MaxScrollOffset();
108 if (OuterScrollLayer())
109 offset
+= OuterScrollLayer()->MaxScrollOffset();
114 gfx::ScrollOffset
Viewport::TotalScrollOffset() const {
115 gfx::ScrollOffset offset
;
117 offset
+= InnerScrollLayer()->CurrentScrollOffset();
119 if (OuterScrollLayer())
120 offset
+= OuterScrollLayer()->CurrentScrollOffset();
125 LayerImpl
* Viewport::InnerScrollLayer() const {
126 return host_impl_
->InnerViewportScrollLayer();
129 LayerImpl
* Viewport::OuterScrollLayer() const {
130 return host_impl_
->OuterViewportScrollLayer();