diff options
-rw-r--r-- | cc/animation/scrollbar_animation_controller.h | 1 | ||||
-rw-r--r-- | cc/animation/scrollbar_animation_controller_linear_fade.cc | 5 | ||||
-rw-r--r-- | cc/animation/scrollbar_animation_controller_linear_fade.h | 1 | ||||
-rw-r--r-- | cc/animation/scrollbar_animation_controller_thinning.cc | 16 | ||||
-rw-r--r-- | cc/animation/scrollbar_animation_controller_thinning.h | 2 | ||||
-rw-r--r-- | cc/animation/scrollbar_animation_controller_thinning_unittest.cc | 41 | ||||
-rw-r--r-- | cc/trees/layer_tree_host_impl.cc | 74 | ||||
-rw-r--r-- | cc/trees/layer_tree_host_impl.h | 13 | ||||
-rw-r--r-- | cc/trees/layer_tree_host_impl_unittest.cc | 11 |
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) { |