summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authortony@chromium.org <tony@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-10-01 21:38:24 +0000
committertony@chromium.org <tony@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-10-01 21:38:24 +0000
commitf620b0e71676e17d1d5289fa0f44693f0d9e2f83 (patch)
treeddb3d2616b9d8c5d0b35063bf1ca8d4558d70bde
parentac19cac3c85e67c0c185ec187945896f8ef60055 (diff)
downloadchromium_src-f620b0e71676e17d1d5289fa0f44693f0d9e2f83.zip
chromium_src-f620b0e71676e17d1d5289fa0f44693f0d9e2f83.tar.gz
chromium_src-f620b0e71676e17d1d5289fa0f44693f0d9e2f83.tar.bz2
Grow scrollbars while the mouse is over the track or thumb.
For overlay scrollbars, when the mouse is over the scrollbar, prevent the animation from making the scrollbar smaller. BUG=274010 R=enne@chromium.org Review URL: https://codereview.chromium.org/24782002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@226308 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--cc/animation/scrollbar_animation_controller.h1
-rw-r--r--cc/animation/scrollbar_animation_controller_linear_fade.cc5
-rw-r--r--cc/animation/scrollbar_animation_controller_linear_fade.h1
-rw-r--r--cc/animation/scrollbar_animation_controller_thinning.cc16
-rw-r--r--cc/animation/scrollbar_animation_controller_thinning.h2
-rw-r--r--cc/animation/scrollbar_animation_controller_thinning_unittest.cc41
-rw-r--r--cc/trees/layer_tree_host_impl.cc74
-rw-r--r--cc/trees/layer_tree_host_impl.h13
-rw-r--r--cc/trees/layer_tree_host_impl_unittest.cc11
9 files changed, 144 insertions, 20 deletions
diff --git a/cc/animation/scrollbar_animation_controller.h b/cc/animation/scrollbar_animation_controller.h
index d0794a2..ecef4fb 100644
--- a/cc/animation/scrollbar_animation_controller.h
+++ b/cc/animation/scrollbar_animation_controller.h
@@ -24,6 +24,7 @@ class CC_EXPORT ScrollbarAnimationController {
virtual bool Animate(base::TimeTicks now) = 0;
virtual void DidScrollGestureBegin() = 0;
virtual void DidScrollGestureEnd(base::TimeTicks now) = 0;
+ virtual void DidMouseMoveOffScrollbar(base::TimeTicks now) = 0;
// Returns true if we should start an animation.
virtual bool DidScrollUpdate(base::TimeTicks now) = 0;
diff --git a/cc/animation/scrollbar_animation_controller_linear_fade.cc b/cc/animation/scrollbar_animation_controller_linear_fade.cc
index 451c45d..0690498 100644
--- a/cc/animation/scrollbar_animation_controller_linear_fade.cc
+++ b/cc/animation/scrollbar_animation_controller_linear_fade.cc
@@ -65,6 +65,11 @@ void ScrollbarAnimationControllerLinearFade::DidScrollGestureEnd(
scroll_gesture_in_progress_ = false;
}
+void ScrollbarAnimationControllerLinearFade::DidMouseMoveOffScrollbar(
+ base::TimeTicks now) {
+ // Ignore mouse move events.
+}
+
bool ScrollbarAnimationControllerLinearFade::DidScrollUpdate(
base::TimeTicks now) {
ApplyOpacityToScrollbars(1.0f);
diff --git a/cc/animation/scrollbar_animation_controller_linear_fade.h b/cc/animation/scrollbar_animation_controller_linear_fade.h
index b490f2e..85cdada 100644
--- a/cc/animation/scrollbar_animation_controller_linear_fade.h
+++ b/cc/animation/scrollbar_animation_controller_linear_fade.h
@@ -29,6 +29,7 @@ class CC_EXPORT ScrollbarAnimationControllerLinearFade
virtual bool Animate(base::TimeTicks now) OVERRIDE;
virtual void DidScrollGestureBegin() OVERRIDE;
virtual void DidScrollGestureEnd(base::TimeTicks now) OVERRIDE;
+ virtual void DidMouseMoveOffScrollbar(base::TimeTicks now) OVERRIDE;
virtual bool DidScrollUpdate(base::TimeTicks now) OVERRIDE;
virtual bool DidMouseMoveNear(base::TimeTicks now, float distance) OVERRIDE;
diff --git a/cc/animation/scrollbar_animation_controller_thinning.cc b/cc/animation/scrollbar_animation_controller_thinning.cc
index e439daf..ce196fb 100644
--- a/cc/animation/scrollbar_animation_controller_thinning.cc
+++ b/cc/animation/scrollbar_animation_controller_thinning.cc
@@ -34,6 +34,7 @@ ScrollbarAnimationControllerThinning::ScrollbarAnimationControllerThinning(
: ScrollbarAnimationController(),
scroll_layer_(scroll_layer),
scroll_gesture_in_progress_(false),
+ mouse_is_over_scrollbar_(false),
animation_delay_(animation_delay),
animation_duration_(animation_duration),
mouse_move_distance_to_trigger_animation_(100.f) {}
@@ -53,6 +54,10 @@ base::TimeDelta ScrollbarAnimationControllerThinning::DelayBeforeStart(
}
bool ScrollbarAnimationControllerThinning::Animate(base::TimeTicks now) {
+ if (mouse_is_over_scrollbar_) {
+ ApplyOpacityAndThumbThicknessScale(1, 1);
+ return false;
+ }
float progress = AnimationProgressAtTime(now);
float opacity = OpacityAtAnimationProgress(progress);
float thumb_thickness_scale = ThumbThicknessScaleAtAnimationProgress(
@@ -75,6 +80,12 @@ void ScrollbarAnimationControllerThinning::DidScrollGestureEnd(
scroll_gesture_in_progress_ = false;
}
+void ScrollbarAnimationControllerThinning::DidMouseMoveOffScrollbar(
+ base::TimeTicks now) {
+ mouse_is_over_scrollbar_ = false;
+ DidScrollUpdate(now);
+}
+
bool ScrollbarAnimationControllerThinning::DidScrollUpdate(
base::TimeTicks now) {
ApplyOpacityAndThumbThicknessScale(1, 1);
@@ -85,6 +96,11 @@ bool ScrollbarAnimationControllerThinning::DidScrollUpdate(
bool ScrollbarAnimationControllerThinning::DidMouseMoveNear(
base::TimeTicks now, float distance) {
+ if (distance == 0.0) {
+ mouse_is_over_scrollbar_ = true;
+ return false;
+ }
+
if (distance < mouse_move_distance_to_trigger_animation_)
return DidScrollUpdate(now);
diff --git a/cc/animation/scrollbar_animation_controller_thinning.h b/cc/animation/scrollbar_animation_controller_thinning.h
index 1f0d41d..8038745 100644
--- a/cc/animation/scrollbar_animation_controller_thinning.h
+++ b/cc/animation/scrollbar_animation_controller_thinning.h
@@ -37,6 +37,7 @@ class CC_EXPORT ScrollbarAnimationControllerThinning
virtual bool Animate(base::TimeTicks now) OVERRIDE;
virtual void DidScrollGestureBegin() OVERRIDE;
virtual void DidScrollGestureEnd(base::TimeTicks now) OVERRIDE;
+ virtual void DidMouseMoveOffScrollbar(base::TimeTicks now) OVERRIDE;
virtual bool DidScrollUpdate(base::TimeTicks now) OVERRIDE;
virtual bool DidMouseMoveNear(base::TimeTicks now, float distance) OVERRIDE;
@@ -58,6 +59,7 @@ class CC_EXPORT ScrollbarAnimationControllerThinning
base::TimeTicks last_awaken_time_;
bool scroll_gesture_in_progress_;
+ bool mouse_is_over_scrollbar_;
base::TimeDelta animation_delay_;
base::TimeDelta animation_duration_;
diff --git a/cc/animation/scrollbar_animation_controller_thinning_unittest.cc b/cc/animation/scrollbar_animation_controller_thinning_unittest.cc
index c83bdc8..7bb5076 100644
--- a/cc/animation/scrollbar_animation_controller_thinning_unittest.cc
+++ b/cc/animation/scrollbar_animation_controller_thinning_unittest.cc
@@ -181,5 +181,46 @@ TEST_F(ScrollbarAnimationControllerThinningTest, AwakenByProgrammaticScroll) {
EXPECT_FLOAT_EQ(0.4f, scrollbar_layer_->thumb_thickness_scale_factor());
}
+TEST_F(ScrollbarAnimationControllerThinningTest, MouseOverAndOut) {
+ base::TimeTicks time;
+ time += base::TimeDelta::FromSeconds(1);
+ EXPECT_TRUE(scrollbar_controller_->DidScrollUpdate(time));
+ EXPECT_TRUE(scrollbar_controller_->IsAnimating());
+ EXPECT_EQ(2, scrollbar_controller_->DelayBeforeStart(time).InSeconds());
+ scrollbar_controller_->Animate(time);
+ EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->opacity());
+ EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor());
+
+ time += base::TimeDelta::FromSeconds(4);
+ scrollbar_controller_->Animate(time);
+ EXPECT_FLOAT_EQ(0.8f, scrollbar_layer_->opacity());
+ EXPECT_FLOAT_EQ(0.6f, scrollbar_layer_->thumb_thickness_scale_factor());
+
+ scrollbar_controller_->DidMouseMoveNear(time, 0);
+ scrollbar_controller_->Animate(time);
+ EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->opacity());
+ EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor());
+
+ time += base::TimeDelta::FromSeconds(4);
+ scrollbar_controller_->Animate(time);
+ EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->opacity());
+ EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor());
+
+ scrollbar_controller_->DidMouseMoveOffScrollbar(time);
+ scrollbar_controller_->Animate(time);
+ EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->opacity());
+ EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor());
+
+ time += base::TimeDelta::FromSeconds(4);
+ scrollbar_controller_->Animate(time);
+ EXPECT_FLOAT_EQ(0.8f, scrollbar_layer_->opacity());
+ EXPECT_FLOAT_EQ(0.6f, scrollbar_layer_->thumb_thickness_scale_factor());
+
+ time += base::TimeDelta::FromSeconds(1);
+ scrollbar_controller_->Animate(time);
+ EXPECT_FLOAT_EQ(0.7f, scrollbar_layer_->opacity());
+ EXPECT_FLOAT_EQ(0.4f, scrollbar_layer_->thumb_thickness_scale_factor());
+}
+
} // namespace
} // namespace cc
diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc
index a764372..281fa5b 100644
--- a/cc/trees/layer_tree_host_impl.cc
+++ b/cc/trees/layer_tree_host_impl.cc
@@ -198,6 +198,7 @@ LayerTreeHostImpl::LayerTreeHostImpl(
did_lock_scrolling_layer_(false),
should_bubble_scrolls_(false),
wheel_scrolling_(false),
+ scroll_layer_id_when_mouse_over_scrollbar_(0),
tile_priorities_dirty_(false),
root_layer_scroll_offset_delegate_(NULL),
settings_(settings),
@@ -1904,19 +1905,11 @@ static LayerImpl* NextScrollLayer(LayerImpl* layer) {
return layer->parent();
}
-LayerImpl* LayerTreeHostImpl::FindScrollLayerForViewportPoint(
- gfx::Point viewport_point, InputHandler::ScrollInputType type,
- bool* scroll_on_main_thread) {
+LayerImpl* LayerTreeHostImpl::FindScrollLayerForDeviceViewportPoint(
+ gfx::PointF device_viewport_point, InputHandler::ScrollInputType type,
+ LayerImpl* layer_impl, bool* scroll_on_main_thread) {
DCHECK(scroll_on_main_thread);
- gfx::PointF device_viewport_point = gfx::ScalePoint(viewport_point,
- device_scale_factor_);
-
- // First find out which layer was hit from the saved list of visible layers
- // in the most recent frame.
- LayerImpl* layer_impl = LayerTreeHostCommon::FindLayerThatIsHitByPoint(
- device_viewport_point, active_tree_->RenderSurfaceLayerList());
-
// Walk up the hierarchy and look for a scrollable layer.
LayerImpl* potentially_scrolling_layer_impl = 0;
for (; layer_impl; layer_impl = NextScrollLayer(layer_impl)) {
@@ -1968,9 +1961,15 @@ InputHandler::ScrollStatus LayerTreeHostImpl::ScrollBegin(
if (!EnsureRenderSurfaceLayerList())
return ScrollIgnored;
+ gfx::PointF device_viewport_point = gfx::ScalePoint(viewport_point,
+ device_scale_factor_);
+ LayerImpl* layer_impl = LayerTreeHostCommon::FindLayerThatIsHitByPoint(
+ device_viewport_point,
+ active_tree_->RenderSurfaceLayerList());
bool scroll_on_main_thread = false;
- LayerImpl* potentially_scrolling_layer_impl = FindScrollLayerForViewportPoint(
- viewport_point, type, &scroll_on_main_thread);
+ LayerImpl* potentially_scrolling_layer_impl =
+ FindScrollLayerForDeviceViewportPoint(device_viewport_point, type,
+ layer_impl, &scroll_on_main_thread);
if (scroll_on_main_thread) {
rendering_stats_instrumentation_->IncrementMainThreadScrolls();
@@ -2296,10 +2295,32 @@ void LayerTreeHostImpl::MouseMoveAt(gfx::Point viewport_point) {
if (!EnsureRenderSurfaceLayerList())
return;
- // TODO(tony): What should happen if the mouse cursor is over the scrollbar?
+ gfx::PointF device_viewport_point = gfx::ScalePoint(viewport_point,
+ device_scale_factor_);
+
+ LayerImpl* layer_impl = LayerTreeHostCommon::FindLayerThatIsHitByPoint(
+ device_viewport_point,
+ active_tree_->RenderSurfaceLayerList());
+ if (HandleMouseOverScrollbar(layer_impl, device_viewport_point))
+ return;
+
+ if (scroll_layer_id_when_mouse_over_scrollbar_) {
+ LayerImpl* scroll_layer_impl = active_tree_->LayerById(
+ scroll_layer_id_when_mouse_over_scrollbar_);
+
+ ScrollbarAnimationController* animation_controller =
+ scroll_layer_impl->scrollbar_animation_controller();
+ if (animation_controller) {
+ animation_controller->DidMouseMoveOffScrollbar(
+ CurrentPhysicalTimeTicks());
+ StartScrollbarAnimation();
+ }
+ scroll_layer_id_when_mouse_over_scrollbar_ = 0;
+ }
+
bool scroll_on_main_thread = false;
- LayerImpl* scroll_layer_impl = FindScrollLayerForViewportPoint(
- viewport_point, InputHandler::Gesture,
+ LayerImpl* scroll_layer_impl = FindScrollLayerForDeviceViewportPoint(
+ device_viewport_point, InputHandler::Gesture, layer_impl,
&scroll_on_main_thread);
if (scroll_on_main_thread || !scroll_layer_impl)
return;
@@ -2309,8 +2330,6 @@ void LayerTreeHostImpl::MouseMoveAt(gfx::Point viewport_point) {
if (!animation_controller)
return;
- gfx::PointF device_viewport_point = gfx::ScalePoint(viewport_point,
- device_scale_factor_);
float distance_to_scrollbar = std::min(
DeviceSpaceDistanceToLayer(device_viewport_point,
scroll_layer_impl->horizontal_scrollbar_layer()),
@@ -2325,6 +2344,25 @@ void LayerTreeHostImpl::MouseMoveAt(gfx::Point viewport_point) {
}
}
+bool LayerTreeHostImpl::HandleMouseOverScrollbar(LayerImpl* layer_impl,
+ gfx::PointF device_viewport_point) {
+ if (layer_impl && layer_impl->ToScrollbarLayer()) {
+ int scroll_layer_id = layer_impl->ToScrollbarLayer()->ScrollLayerId();
+ layer_impl = active_tree_->LayerById(scroll_layer_id);
+ if (layer_impl && layer_impl->scrollbar_animation_controller()) {
+ scroll_layer_id_when_mouse_over_scrollbar_ = scroll_layer_id;
+ layer_impl->scrollbar_animation_controller()->DidMouseMoveNear(
+ CurrentPhysicalTimeTicks(), 0);
+ } else {
+ scroll_layer_id_when_mouse_over_scrollbar_ = 0;
+ }
+
+ return true;
+ }
+
+ return false;
+}
+
void LayerTreeHostImpl::PinchGestureBegin() {
pinch_gesture_active_ = true;
previous_pinch_anchor_ = gfx::Point();
diff --git a/cc/trees/layer_tree_host_impl.h b/cc/trees/layer_tree_host_impl.h
index d71a0aa..aabd0b5 100644
--- a/cc/trees/layer_tree_host_impl.h
+++ b/cc/trees/layer_tree_host_impl.h
@@ -278,6 +278,10 @@ class CC_EXPORT LayerTreeHostImpl
LayerImpl* RootScrollLayer() const;
LayerImpl* CurrentlyScrollingLayer() const;
+ int scroll_layer_id_when_mouse_over_scrollbar() {
+ return scroll_layer_id_when_mouse_over_scrollbar_;
+ }
+
virtual void SetVisible(bool visible);
bool visible() const { return visible_; }
@@ -456,14 +460,18 @@ class CC_EXPORT LayerTreeHostImpl
bool EnsureRenderSurfaceLayerList();
void ClearCurrentlyScrollingLayer();
+ bool HandleMouseOverScrollbar(LayerImpl* layer_impl,
+ gfx::PointF device_viewport_point);
+
void AnimateScrollbarsRecursive(LayerImpl* layer,
base::TimeTicks time);
void UpdateCurrentFrameTime(base::TimeTicks* ticks, base::Time* now) const;
- LayerImpl* FindScrollLayerForViewportPoint(
- gfx::Point viewport_point,
+ LayerImpl* FindScrollLayerForDeviceViewportPoint(
+ gfx::PointF device_viewport_point,
InputHandler::ScrollInputType type,
+ LayerImpl* layer_hit_by_point,
bool* scroll_on_main_thread);
float DeviceSpaceDistanceToLayer(gfx::PointF device_viewport_point,
LayerImpl* layer_impl);
@@ -511,6 +519,7 @@ class CC_EXPORT LayerTreeHostImpl
bool did_lock_scrolling_layer_;
bool should_bubble_scrolls_;
bool wheel_scrolling_;
+ int scroll_layer_id_when_mouse_over_scrollbar_;
bool tile_priorities_dirty_;
diff --git a/cc/trees/layer_tree_host_impl_unittest.cc b/cc/trees/layer_tree_host_impl_unittest.cc
index 5f2eaf7..2ddd544 100644
--- a/cc/trees/layer_tree_host_impl_unittest.cc
+++ b/cc/trees/layer_tree_host_impl_unittest.cc
@@ -1259,6 +1259,8 @@ void LayerTreeHostImplTest::SetupMouseMoveAtWithDeviceScale(
// The scrollbar is on the right side.
scoped_ptr<PaintedScrollbarLayerImpl> scrollbar =
PaintedScrollbarLayerImpl::Create(host_impl_->active_tree(), 5, VERTICAL);
+ scrollbar->SetDrawsContent(true);
+ scrollbar->SetBounds(gfx::Size(15, viewport_size.height()));
scrollbar->SetContentBounds(gfx::Size(15, viewport_size.height()));
scrollbar->SetPosition(gfx::Point(285, 0));
scroll->SetVerticalScrollbarLayer(scrollbar.get());
@@ -1293,6 +1295,15 @@ void LayerTreeHostImplTest::SetupMouseMoveAtWithDeviceScale(
did_request_redraw_ = false;
host_impl_->MouseMoveAt(gfx::Point(184, 100));
EXPECT_TRUE(did_request_redraw_);
+
+ did_request_redraw_ = false;
+ EXPECT_EQ(0, host_impl_->scroll_layer_id_when_mouse_over_scrollbar());
+ host_impl_->MouseMoveAt(gfx::Point(290, 100));
+ EXPECT_EQ(2, host_impl_->scroll_layer_id_when_mouse_over_scrollbar());
+ host_impl_->MouseMoveAt(gfx::Point(290, 120));
+ EXPECT_EQ(2, host_impl_->scroll_layer_id_when_mouse_over_scrollbar());
+ host_impl_->MouseMoveAt(gfx::Point(150, 120));
+ EXPECT_EQ(0, host_impl_->scroll_layer_id_when_mouse_over_scrollbar());
}
TEST_F(LayerTreeHostImplTest, MouseMoveAtWithDeviceScaleOf1) {