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

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: Draft for review. Created 7 years, 1 month 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
Index: cc/layers/layer_impl.cc
diff --git a/cc/layers/layer_impl.cc b/cc/layers/layer_impl.cc
index 894daf1a27f04cd2b40dfc70436b806af3e59d65..9c2e487fe83c282012537f9093c366fe5037b7cc 100644
--- a/cc/layers/layer_impl.cc
+++ b/cc/layers/layer_impl.cc
@@ -39,7 +39,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),
+ clip_layer_(NULL),
should_scroll_on_main_thread_(false),
have_wheel_event_handlers_(false),
user_scrollable_horizontal_(true),
@@ -60,9 +60,7 @@ LayerImpl::LayerImpl(LayerTreeImpl* tree_impl, int id)
is_container_for_fixed_position_layers_(false),
draw_depth_(0.f),
compositing_reasons_(kCompositingReasonUnknown),
- 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);
@@ -354,7 +352,7 @@ gfx::Vector2dF LayerImpl::ScrollBy(gfx::Vector2dF scroll) {
}
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);
@@ -362,9 +360,14 @@ gfx::Vector2dF LayerImpl::ScrollBy(gfx::Vector2dF scroll) {
gfx::Vector2dF unscrolled =
ScrollDelta() + scroll + scroll_hidden - new_delta;
SetScrollDelta(new_delta);
+
return unscrolled;
}
+void LayerImpl::SetScrollable(int clip_layer_id) {
enne (OOO) 2013/11/14 22:59:01 As I said on the other patch, I think this is a so
wjmaclean 2013/12/24 21:03:49 Let's try "SetScrollClipLayer", sound ok? Fixed i
+ clip_layer_ = layer_tree_impl()->LayerById(clip_layer_id);
+}
+
void LayerImpl::ApplySentScrollDeltasFromAbortedCommit() {
// Pending tree never has sent scroll deltas
DCHECK(layer_tree_impl()->IsActiveTree());
@@ -454,7 +457,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.");
@@ -532,15 +536,13 @@ void LayerImpl::PushPropertiesTo(LayerImpl* layer) {
layer->SetSublayerTransform(sublayer_transform_);
layer->SetTransform(transform_);
- layer->SetScrollable(scrollable_);
+ layer->SetScrollable(clip_layer_ ? 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());
@@ -611,8 +613,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_);
@@ -702,6 +704,7 @@ void LayerImpl::SetBounds(gfx::Size bounds) {
bounds_ = bounds;
+ NotifyScrollbars();
if (masks_to_bounds())
NoteLayerPropertyChangedForSubtree();
else
@@ -954,44 +957,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.
@@ -1002,10 +967,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 {
@@ -1021,6 +984,8 @@ void LayerImpl::SetScrollOffsetAndDelta(gfx::Vector2d scroll_offset,
gfx::Vector2dF scroll_delta) {
bool changed = false;
+ last_scroll_offset_ = scroll_offset;
enne (OOO) 2013/11/14 22:59:01 What is last_scroll_offset_ used for?
wjmaclean 2013/12/24 21:03:49 Ooops, remnant of diagnostic code :-) Removed.
+
if (scroll_offset_ != scroll_offset) {
changed = true;
scroll_offset_ = scroll_offset;
@@ -1055,7 +1020,7 @@ void LayerImpl::SetScrollOffsetAndDelta(gfx::Vector2d scroll_offset,
if (changed) {
NoteLayerPropertyChangedForSubtree();
- UpdateScrollbarPositions();
+ NotifyScrollbars();
}
}
@@ -1091,16 +1056,99 @@ void LayerImpl::DidBeginTracing() {}
void LayerImpl::DidLoseOutputSurface() {}
-void LayerImpl::SetMaxScrollOffset(gfx::Vector2d max_scroll_offset) {
- if (max_scroll_offset_ == max_scroll_offset)
- return;
- max_scroll_offset_ = max_scroll_offset;
-
- if (scroll_offset_delegate_)
- scroll_offset_delegate_->SetMaxScrollOffset(max_scroll_offset_);
+gfx::Vector2d LayerImpl::MaxScrollOffset() const {
+ if (!clip_layer_)
+ return gfx::Vector2d();
+
+ gfx::Size scaled_scroll_bounds(bounds());
+ LayerImpl const* current_layer = this;
+ LayerImpl const* page_scale_layer = layer_tree_impl()->page_scale_layer();
+ float scale_factor = 1.f;
+ do {
enne (OOO) 2013/11/14 22:59:01 This loop assumes there are no other scale transfo
wjmaclean 2013/12/24 21:03:49 I've made this more general, allow scale (but not
+ if (current_layer == page_scale_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());
+ }
+ current_layer = current_layer->parent();
+ } while (current_layer && current_layer != clip_layer_);
+ DCHECK(current_layer == clip_layer_);
+
+ gfx::Vector2dF max_offset(
+ scaled_scroll_bounds.width() - clip_layer_->bounds().width(),
aelias_OOO_until_Jul13 2013/11/14 01:25:35 Using clip_layer_->bounds() is incorrect on Androi
+ scaled_scroll_bounds.height() - clip_layer_->bounds().height());
+ // We need the final scroll offset to be in CSS coords.
+ max_offset.Scale(1 / scale_factor);
+ return gfx::Vector2d(max_offset.x(), max_offset.y());
+}
+
+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(scrollbar_clip_layer);
+ gfx::RectF clip_rect(gfx::PointF(), scrollbar_clip_layer->bounds());
+ gfx::RectF scroll_rect(gfx::PointF(), bounds());
+
+ gfx::Vector2dF current_offset;
+
+ // TODO(wjmaclean): How do I account for vertical adjust, or do I need to?
aelias_OOO_until_Jul13 2013/11/14 01:25:35 "Vertical adjust" is used to keep the horizontal s
wjmaclean 2013/12/24 21:03:49 Done.
+ // Also, I can probably improve some of the variable names.
+ LayerImpl const* current_layer = this;
+ float scale_factor = 1.f;
+ do {
+ if (current_layer == page_scale_layer) {
+ scale_factor = layer_tree_impl()->total_page_scale_factor();
+ current_offset.Scale(scale_factor);
+ scroll_rect.Scale(scale_factor);
+ current_offset.Scale(scale_factor);
+ } else {
+ gfx::Vector2dF new_offset =
+ current_layer->scroll_offset() + current_layer->ScrollDelta();
+ current_offset += new_offset;
+ }
+ current_layer = current_layer->parent();
+ } while (current_layer && current_layer != scrollbar_clip_layer);
+ DCHECK(current_layer == scrollbar_clip_layer);
+ current_offset.Scale(1 / scale_factor);
+
+ 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();
+ // 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.
+ 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() {
@@ -1109,8 +1157,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;
@@ -1143,18 +1190,50 @@ void LayerImpl::DidBecomeActive() {
break;
}
}
-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::SetVerticalScrollbarLayer(
- ScrollbarLayerImplBase* scrollbar_layer) {
- vertical_scrollbar_layer_ = scrollbar_layer;
- if (vertical_scrollbar_layer_)
- vertical_scrollbar_layer_->set_scroll_layer_id(id());
+void LayerImpl::AddScrollbar(ScrollbarLayerImplBase* layer) {
+ DCHECK(layer);
+ if (!scrollbars_)
+ scrollbars_.reset(new ScrollbarSet());
+
+ scrollbars_->insert(layer);
+}
+
+void LayerImpl::RemoveScrollbar(ScrollbarLayerImplBase* layer) {
+ DCHECK(scrollbars_);
+ DCHECK(layer);
+
+ 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::NotifyScrollbars() {
+ if (!scrollbars_)
+ return;
+
+ for (ScrollbarSet::iterator it = scrollbars_->begin();
+ it != scrollbars_->end(); ++it)
+ (*it)->ScrollbarParametersDidChange();
}
static scoped_ptr<base::Value>

Powered by Google App Engine
This is Rietveld 408576698