Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(36)

Unified Diff: cc/layers/layer_impl.cc

Issue 23983047: Pinch/Zoom Infrastructure & Plumbing CL (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebase to r248052. Created 6 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « cc/layers/layer_impl.h ('k') | cc/layers/layer_impl_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: cc/layers/layer_impl.cc
diff --git a/cc/layers/layer_impl.cc b/cc/layers/layer_impl.cc
index 42338e0b8197fb17f8b9b242d9243a16c534f7e0..e21cc13e29422256bdb597a456ea2cae5b08dbf1 100644
--- a/cc/layers/layer_impl.cc
+++ b/cc/layers/layer_impl.cc
@@ -27,6 +27,7 @@
#include "cc/trees/layer_tree_settings.h"
#include "cc/trees/proxy.h"
#include "ui/gfx/box_f.h"
+#include "ui/gfx/geometry/vector2d_conversions.h"
#include "ui/gfx/point_conversions.h"
#include "ui/gfx/quad_f.h"
#include "ui/gfx/rect_conversions.h"
@@ -43,7 +44,7 @@ LayerImpl::LayerImpl(LayerTreeImpl* tree_impl, int id)
anchor_point_(0.5f, 0.5f),
anchor_point_z_(0.f),
scroll_offset_delegate_(NULL),
- scrollable_(false),
+ scroll_clip_layer_(NULL),
should_scroll_on_main_thread_(false),
have_wheel_event_handlers_(false),
user_scrollable_horizontal_(true),
@@ -67,9 +68,7 @@ LayerImpl::LayerImpl(LayerTreeImpl* tree_impl, int id)
draw_depth_(0.f),
needs_push_properties_(false),
num_dependents_need_push_properties_(0),
- current_draw_mode_(DRAW_MODE_NONE),
- horizontal_scrollbar_layer_(NULL),
- vertical_scrollbar_layer_(NULL) {
+ current_draw_mode_(DRAW_MODE_NONE) {
DCHECK_GT(layer_id_, 0);
DCHECK(layer_tree_impl_);
layer_tree_impl_->RegisterLayer(this);
@@ -381,7 +380,7 @@ void LayerImpl::SetSentScrollDelta(gfx::Vector2d sent_scroll_delta) {
gfx::Vector2dF LayerImpl::ScrollBy(const gfx::Vector2dF& scroll) {
DCHECK(scrollable());
gfx::Vector2dF min_delta = -scroll_offset_;
- gfx::Vector2dF max_delta = max_scroll_offset_ - scroll_offset_;
+ gfx::Vector2dF max_delta = MaxScrollOffset() - scroll_offset_;
// Clamp new_delta so that position + delta stays within scroll bounds.
gfx::Vector2dF new_delta = (ScrollDelta() + scroll);
new_delta.SetToMax(min_delta);
@@ -389,9 +388,14 @@ gfx::Vector2dF LayerImpl::ScrollBy(const gfx::Vector2dF& scroll) {
gfx::Vector2dF unscrolled =
ScrollDelta() + scroll - new_delta;
SetScrollDelta(new_delta);
+
return unscrolled;
}
+void LayerImpl::SetScrollClipLayer(int scroll_clip_layer_id) {
+ scroll_clip_layer_ = layer_tree_impl()->LayerById(scroll_clip_layer_id);
+}
+
void LayerImpl::ApplySentScrollDeltasFromAbortedCommit() {
// Pending tree never has sent scroll deltas
DCHECK(layer_tree_impl()->IsActiveTree());
@@ -481,7 +485,8 @@ InputHandler::ScrollStatus LayerImpl::TryScroll(
return InputHandler::ScrollIgnored;
}
- if (max_scroll_offset_.x() <= 0 && max_scroll_offset_.y() <= 0) {
+ gfx::Vector2d max_scroll_offset = MaxScrollOffset();
+ if (max_scroll_offset.x() <= 0 && max_scroll_offset.y() <= 0) {
TRACE_EVENT0("cc",
"LayerImpl::tryScroll: Ignored. Technically scrollable,"
" but has no affordance in either direction.");
@@ -552,15 +557,14 @@ void LayerImpl::PushPropertiesTo(LayerImpl* layer) {
layer->SetSublayerTransform(sublayer_transform_);
layer->SetTransform(transform_);
- layer->SetScrollable(scrollable_);
+ layer->SetScrollClipLayer(scroll_clip_layer_ ? scroll_clip_layer_->id()
+ : Layer::INVALID_ID);
layer->set_user_scrollable_horizontal(user_scrollable_horizontal_);
layer->set_user_scrollable_vertical(user_scrollable_vertical_);
layer->SetScrollOffsetAndDelta(
scroll_offset_, layer->ScrollDelta() - layer->sent_scroll_delta());
layer->SetSentScrollDelta(gfx::Vector2d());
- layer->SetMaxScrollOffset(max_scroll_offset_);
-
LayerImpl* scroll_parent = NULL;
if (scroll_parent_)
scroll_parent = layer->layer_tree_impl()->LayerById(scroll_parent_->id());
@@ -634,8 +638,8 @@ base::DictionaryValue* LayerImpl::LayerTreeAsJson() const {
result->SetDouble("Opacity", opacity());
result->SetBoolean("ContentsOpaque", contents_opaque_);
- if (scrollable_)
- result->SetBoolean("Scrollable", scrollable_);
+ if (scrollable())
+ result->SetBoolean("Scrollable", true);
if (have_wheel_event_handlers_)
result->SetBoolean("WheelHandler", have_wheel_event_handlers_);
@@ -757,6 +761,7 @@ void LayerImpl::SetBounds(const gfx::Size& bounds) {
bounds_ = bounds;
+ ScrollbarParametersDidChange();
if (masks_to_bounds())
NoteLayerPropertyChangedForSubtree();
else
@@ -1030,44 +1035,6 @@ void LayerImpl::CalculateContentsScale(
*content_bounds = this->content_bounds();
}
-void LayerImpl::UpdateScrollbarPositions() {
- gfx::Vector2dF current_offset = scroll_offset_ + ScrollDelta();
-
- gfx::RectF viewport(PointAtOffsetFromOrigin(current_offset), bounds_);
- gfx::SizeF scrollable_size(max_scroll_offset_.x() + bounds_.width(),
- max_scroll_offset_.y() + bounds_.height());
- if (horizontal_scrollbar_layer_) {
- horizontal_scrollbar_layer_->SetCurrentPos(current_offset.x());
- horizontal_scrollbar_layer_->SetMaximum(max_scroll_offset_.x());
- horizontal_scrollbar_layer_->SetVisibleToTotalLengthRatio(
- viewport.width() / scrollable_size.width());
- }
- if (vertical_scrollbar_layer_) {
- vertical_scrollbar_layer_->SetCurrentPos(current_offset.y());
- vertical_scrollbar_layer_->SetMaximum(max_scroll_offset_.y());
- vertical_scrollbar_layer_->SetVisibleToTotalLengthRatio(
- viewport.height() / scrollable_size.height());
- }
-
- if (current_offset == last_scroll_offset_)
- return;
- last_scroll_offset_ = current_offset;
-
- if (scrollbar_animation_controller_) {
- bool should_animate = scrollbar_animation_controller_->DidScrollUpdate(
- layer_tree_impl_->CurrentPhysicalTimeTicks());
- if (should_animate)
- layer_tree_impl_->StartScrollbarAnimation();
- }
-
- // Get the current_offset_.y() value for a sanity-check on scrolling
- // benchmark metrics. Specifically, we want to make sure
- // BasicMouseWheelSmoothScrollGesture has proper scroll curves.
- if (layer_tree_impl()->IsActiveTree()) {
- TRACE_COUNTER_ID1("gpu", "scroll_offset_y", this->id(), current_offset.y());
- }
-}
-
void LayerImpl::SetScrollOffsetDelegate(
LayerScrollOffsetDelegate* scroll_offset_delegate) {
// Having both a scroll parent and a scroll offset delegate is unsupported.
@@ -1078,10 +1045,8 @@ void LayerImpl::SetScrollOffsetDelegate(
}
gfx::Vector2dF total_offset = TotalScrollOffset();
scroll_offset_delegate_ = scroll_offset_delegate;
- if (scroll_offset_delegate_) {
- scroll_offset_delegate_->SetMaxScrollOffset(max_scroll_offset_);
+ if (scroll_offset_delegate_)
scroll_offset_delegate_->SetTotalScrollOffset(total_offset);
- }
}
bool LayerImpl::IsExternalFlingActive() const {
@@ -1097,6 +1062,8 @@ void LayerImpl::SetScrollOffsetAndDelta(gfx::Vector2d scroll_offset,
const gfx::Vector2dF& scroll_delta) {
bool changed = false;
+ last_scroll_offset_ = scroll_offset;
+
if (scroll_offset_ != scroll_offset) {
changed = true;
scroll_offset_ = scroll_offset;
@@ -1131,7 +1098,7 @@ void LayerImpl::SetScrollOffsetAndDelta(gfx::Vector2d scroll_offset,
if (changed) {
NoteLayerPropertyChangedForSubtree();
- UpdateScrollbarPositions();
+ ScrollbarParametersDidChange();
}
}
@@ -1167,17 +1134,150 @@ void LayerImpl::DidBeginTracing() {}
void LayerImpl::ReleaseResources() {}
-void LayerImpl::SetMaxScrollOffset(gfx::Vector2d max_scroll_offset) {
- if (max_scroll_offset_ == max_scroll_offset)
+gfx::Vector2d LayerImpl::MaxScrollOffset() const {
+ if (!scroll_clip_layer_ || bounds().IsEmpty())
+ return gfx::Vector2d();
+
+ LayerImpl const* page_scale_layer = layer_tree_impl()->page_scale_layer();
+ DCHECK(this != page_scale_layer);
+ DCHECK(scroll_clip_layer_);
+ DCHECK(this != layer_tree_impl()->InnerViewportScrollLayer() ||
+ IsContainerForFixedPositionLayers());
+
+ gfx::Size scaled_scroll_bounds(bounds());
+
+ float scale_factor = 1.f;
+ for (LayerImpl const* current_layer = this;
+ current_layer != scroll_clip_layer_;
+ current_layer = current_layer->parent()) {
+ DCHECK(current_layer);
+ float current_layer_scale = 1.f;
+
+ const gfx::Transform& layer_transform = current_layer->transform();
+ if (current_layer == page_scale_layer) {
+ DCHECK(layer_transform.IsIdentity());
+ current_layer_scale = layer_tree_impl()->total_page_scale_factor();
+ } else {
+ // TODO(wjmaclean) Should we allow for translation too?
+ DCHECK(layer_transform.IsScale2d());
+ gfx::Vector2dF layer_scale = layer_transform.Scale2d();
+ // TODO(wjmaclean) Allow for non-isotropic scales.
+ DCHECK(layer_scale.x() == layer_scale.y());
+ current_layer_scale = layer_scale.x();
+ }
+
+ scale_factor *= current_layer_scale;
+ }
+ // TODO(wjmaclean) Once we move to a model where the two-viewport model is
+ // turned on in all builds, remove the next two lines. For now however, the
+ // page scale layer may coincide with the clip layer, and so this is
+ // necessary.
+ if (page_scale_layer == scroll_clip_layer_)
+ scale_factor *= layer_tree_impl()->total_page_scale_factor();
+
+ scaled_scroll_bounds.SetSize(scale_factor * scaled_scroll_bounds.width(),
+ scale_factor * scaled_scroll_bounds.height());
+
+ gfx::RectF clip_rect(gfx::PointF(), scroll_clip_layer_->bounds());
+ if (this == layer_tree_impl()->InnerViewportScrollLayer())
+ clip_rect =
+ gfx::RectF(gfx::PointF(), layer_tree_impl()->ScrollableViewportSize());
+ gfx::Vector2dF max_offset(
+ scaled_scroll_bounds.width() - scroll_clip_layer_->bounds().width(),
+ scaled_scroll_bounds.height() - scroll_clip_layer_->bounds().height());
+ // We need the final scroll offset to be in CSS coords.
+ max_offset.Scale(1 / scale_factor);
+ max_offset.SetToMax(gfx::Vector2dF());
+ return gfx::ToFlooredVector2d(max_offset);
+}
+
+gfx::Vector2dF LayerImpl::ClampScrollToMaxScrollOffset() {
+ gfx::Vector2dF max_offset = MaxScrollOffset();
+ gfx::Vector2dF old_offset = TotalScrollOffset();
+ gfx::Vector2dF clamped_offset = old_offset;
+
+ clamped_offset.SetToMin(max_offset);
+ clamped_offset.SetToMax(gfx::Vector2d());
+ gfx::Vector2dF delta = clamped_offset - old_offset;
+ if (!delta.IsZero())
+ ScrollBy(delta);
+
+ return delta;
+}
+
+void LayerImpl::SetScrollbarPosition(ScrollbarLayerImplBase* scrollbar_layer,
+ LayerImpl* scrollbar_clip_layer) const {
+ DCHECK(scrollbar_layer);
+ LayerImpl* page_scale_layer = layer_tree_impl()->page_scale_layer();
+
+ DCHECK(this != page_scale_layer);
+ DCHECK(scrollbar_clip_layer);
+ DCHECK(this != layer_tree_impl()->InnerViewportScrollLayer() ||
+ IsContainerForFixedPositionLayers());
+ gfx::RectF clip_rect(gfx::PointF(), scrollbar_clip_layer->bounds());
+
+ // See comment in MaxScrollOffset() regarding the use of the content layer
+ // bounds here.
+ gfx::RectF scroll_rect(gfx::PointF(), bounds());
+
+ if (scroll_rect.size().IsEmpty())
return;
- max_scroll_offset_ = max_scroll_offset;
- if (scroll_offset_delegate_)
- scroll_offset_delegate_->SetMaxScrollOffset(max_scroll_offset_);
+ // TODO(wjmaclean) This computation is nearly identical to the one in
+ // MaxScrollOffset. Find some way to combine these.
+ gfx::Vector2dF current_offset;
+ for (LayerImpl const* current_layer = this;
+ current_layer != scrollbar_clip_layer;
+ current_layer = current_layer->parent()) {
+ DCHECK(current_layer);
+ const gfx::Transform& layer_transform = current_layer->transform();
+ if (current_layer == page_scale_layer) {
+ DCHECK(layer_transform.IsIdentity());
+ float scale_factor = layer_tree_impl()->total_page_scale_factor();
+ current_offset.Scale(scale_factor);
+ scroll_rect.Scale(scale_factor);
+ } else {
+ DCHECK(layer_transform.IsScale2d());
+ gfx::Vector2dF layer_scale = layer_transform.Scale2d();
+ DCHECK(layer_scale.x() == layer_scale.y());
+ gfx::Vector2dF new_offset =
+ current_layer->scroll_offset() + current_layer->ScrollDelta();
+ new_offset.Scale(layer_scale.x(), layer_scale.y());
+ current_offset += new_offset;
+ }
+ }
+ // TODO(wjmaclean) Once we move to a model where the two-viewport model is
+ // turned on in all builds, remove the next two lines. For now however, the
+ // page scale layer may coincide with the clip layer, and so this is
+ // necessary.
+ if (page_scale_layer == scrollbar_clip_layer)
+ scroll_rect.Scale(layer_tree_impl()->total_page_scale_factor());
+
+ scrollbar_layer->SetVerticalAdjust(layer_tree_impl()->VerticalAdjust(this));
+ if (scrollbar_layer->orientation() == HORIZONTAL) {
+ float visible_ratio = clip_rect.width() / scroll_rect.width();
+ scrollbar_layer->SetCurrentPos(current_offset.x());
+ scrollbar_layer->SetMaximum(scroll_rect.width() - clip_rect.width());
+ scrollbar_layer->SetVisibleToTotalLengthRatio(visible_ratio);
+ } else {
+ float visible_ratio = clip_rect.height() / scroll_rect.height();
+ scrollbar_layer->SetCurrentPos(current_offset.y());
+ scrollbar_layer->SetMaximum(scroll_rect.height() - clip_rect.height());
+ scrollbar_layer->SetVisibleToTotalLengthRatio(visible_ratio);
+ }
layer_tree_impl()->set_needs_update_draw_properties();
- UpdateScrollbarPositions();
- SetNeedsPushProperties();
+ // TODO(wjmaclean) Should the rest of this function be deleted?
+ // TODO(wjmaclean) The scrollbar animator for the pinch-zoom scrollbars should
+ // activate for every scroll on the main frame, not just the scrolls that move
+ // the pinch virtual viewport (i.e. trigger from either inner or outer
+ // viewport).
+ if (scrollbar_animation_controller_) {
+ bool should_animate = scrollbar_animation_controller_->DidScrollUpdate(
+ layer_tree_impl_->CurrentPhysicalTimeTicks());
+ if (should_animate)
+ layer_tree_impl_->StartScrollbarAnimation();
+ }
}
void LayerImpl::DidBecomeActive() {
@@ -1186,8 +1286,7 @@ void LayerImpl::DidBecomeActive() {
return;
}
- bool need_scrollbar_animation_controller = horizontal_scrollbar_layer_ ||
- vertical_scrollbar_layer_;
+ bool need_scrollbar_animation_controller = scrollable() && scrollbars_;
if (!need_scrollbar_animation_controller) {
scrollbar_animation_controller_.reset();
return;
@@ -1221,18 +1320,53 @@ void LayerImpl::DidBecomeActive() {
}
}
-void LayerImpl::SetHorizontalScrollbarLayer(
- ScrollbarLayerImplBase* scrollbar_layer) {
- horizontal_scrollbar_layer_ = scrollbar_layer;
- if (horizontal_scrollbar_layer_)
- horizontal_scrollbar_layer_->set_scroll_layer_id(id());
+void LayerImpl::ClearScrollbars() {
+ if (!scrollbars_)
+ return;
+
+ scrollbars_.reset(NULL);
+}
+
+void LayerImpl::AddScrollbar(ScrollbarLayerImplBase* layer) {
+ DCHECK(layer);
+ DCHECK(!scrollbars_ || scrollbars_->find(layer) == scrollbars_->end());
+ if (!scrollbars_)
+ scrollbars_.reset(new ScrollbarSet());
+
+ scrollbars_->insert(layer);
+}
+
+void LayerImpl::RemoveScrollbar(ScrollbarLayerImplBase* layer) {
+ DCHECK(scrollbars_);
+ DCHECK(layer);
+ DCHECK(scrollbars_->find(layer) != scrollbars_->end());
+
+ scrollbars_->erase(layer);
+ if (scrollbars_->empty())
+ scrollbars_.reset();
+}
+
+bool LayerImpl::HasScrollbar(ScrollbarOrientation orientation) const {
+ if (!scrollbars_)
+ return false;
+
+ for (ScrollbarSet::iterator it = scrollbars_->begin();
+ it != scrollbars_->end();
+ ++it)
+ if ((*it)->orientation() == orientation)
+ return true;
+
+ return false;
}
-void LayerImpl::SetVerticalScrollbarLayer(
- ScrollbarLayerImplBase* scrollbar_layer) {
- vertical_scrollbar_layer_ = scrollbar_layer;
- if (vertical_scrollbar_layer_)
- vertical_scrollbar_layer_->set_scroll_layer_id(id());
+void LayerImpl::ScrollbarParametersDidChange() {
+ if (!scrollbars_)
+ return;
+
+ for (ScrollbarSet::iterator it = scrollbars_->begin();
+ it != scrollbars_->end();
+ ++it)
+ (*it)->ScrollbarParametersDidChange();
}
void LayerImpl::SetNeedsPushProperties() {
« no previous file with comments | « cc/layers/layer_impl.h ('k') | cc/layers/layer_impl_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698