cc: Avoid prefer smoothness mode when scrolling with scroll handler
    
Avoid going into prefer smoothness mode when the scrolled layer has a
scroll handler. The presence of a scroll handler suggests that the main
thread wants to animate in response to scrolling. Avoiding smoothness
mode gives it a chance to do that while still having our deadline as a
fallback.
    
BUG=347366

Review URL: https://codereview.chromium.org/206523003

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@260859 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc
index 072e8e7..5d40bb7f 100644
--- a/cc/trees/layer_tree_host_impl.cc
+++ b/cc/trees/layer_tree_host_impl.cc
@@ -221,6 +221,7 @@
       did_lock_scrolling_layer_(false),
       should_bubble_scrolls_(false),
       wheel_scrolling_(false),
+      scroll_affects_scroll_handler_(false),
       scroll_layer_id_when_mouse_over_scrollbar_(0),
       tile_priorities_dirty_(false),
       root_layer_scroll_offset_delegate_(NULL),
@@ -2030,7 +2031,9 @@
 LayerImpl* LayerTreeHostImpl::FindScrollLayerForDeviceViewportPoint(
     const gfx::PointF& device_viewport_point,
     InputHandler::ScrollInputType type,
-    LayerImpl* layer_impl, bool* scroll_on_main_thread) const {
+    LayerImpl* layer_impl,
+    bool* scroll_on_main_thread,
+    bool* has_ancestor_scroll_handler) const {
   DCHECK(scroll_on_main_thread);
 
   // Walk up the hierarchy and look for a scrollable layer.
@@ -2055,6 +2058,10 @@
       return NULL;
     }
 
+    if (has_ancestor_scroll_handler &&
+        scroll_layer_impl->have_scroll_event_handlers())
+      *has_ancestor_scroll_handler = true;
+
     if (status == ScrollStarted && !potentially_scrolling_layer_impl)
       potentially_scrolling_layer_impl = scroll_layer_impl;
   }
@@ -2083,8 +2090,11 @@
       active_tree_->RenderSurfaceLayerList());
   bool scroll_on_main_thread = false;
   LayerImpl* potentially_scrolling_layer_impl =
-      FindScrollLayerForDeviceViewportPoint(device_viewport_point, type,
-          layer_impl, &scroll_on_main_thread);
+      FindScrollLayerForDeviceViewportPoint(device_viewport_point,
+                                            type,
+                                            layer_impl,
+                                            &scroll_on_main_thread,
+                                            &scroll_affects_scroll_handler_);
 
   if (scroll_on_main_thread) {
     UMA_HISTOGRAM_BOOLEAN("TryScroll.SlowScroll", true);
@@ -2383,6 +2393,7 @@
 void LayerTreeHostImpl::ClearCurrentlyScrollingLayer() {
   active_tree_->ClearCurrentlyScrollingLayer();
   did_lock_scrolling_layer_ = false;
+  scroll_affects_scroll_handler_ = false;
   accumulated_root_overscroll_ = gfx::Vector2dF();
   current_fling_velocity_ = gfx::Vector2dF();
 }
@@ -2468,9 +2479,12 @@
   }
 
   bool scroll_on_main_thread = false;
-  LayerImpl* scroll_layer_impl = FindScrollLayerForDeviceViewportPoint(
-      device_viewport_point, InputHandler::Gesture, layer_impl,
-      &scroll_on_main_thread);
+  LayerImpl* scroll_layer_impl =
+      FindScrollLayerForDeviceViewportPoint(device_viewport_point,
+                                            InputHandler::Gesture,
+                                            layer_impl,
+                                            &scroll_on_main_thread,
+                                            NULL);
   if (scroll_on_main_thread || !scroll_layer_impl)
     return;
 
diff --git a/cc/trees/layer_tree_host_impl.h b/cc/trees/layer_tree_host_impl.h
index 10477dc2..2d64a3b 100644
--- a/cc/trees/layer_tree_host_impl.h
+++ b/cc/trees/layer_tree_host_impl.h
@@ -284,9 +284,12 @@
   LayerImpl* OuterViewportScrollLayer() const;
   LayerImpl* CurrentlyScrollingLayer() const;
 
-  int scroll_layer_id_when_mouse_over_scrollbar() {
+  int scroll_layer_id_when_mouse_over_scrollbar() const {
     return scroll_layer_id_when_mouse_over_scrollbar_;
   }
+  bool scroll_affects_scroll_handler() const {
+    return scroll_affects_scroll_handler_;
+  }
 
   bool IsCurrentlyScrolling() const;
 
@@ -508,7 +511,8 @@
       const gfx::PointF& device_viewport_point,
       InputHandler::ScrollInputType type,
       LayerImpl* layer_hit_by_point,
-      bool* scroll_on_main_thread) const;
+      bool* scroll_on_main_thread,
+      bool* has_ancestor_scroll_handler) const;
   float DeviceSpaceDistanceToLayer(const gfx::PointF& device_viewport_point,
                                    LayerImpl* layer_impl);
   void StartScrollbarAnimationRecursive(LayerImpl* layer, base::TimeTicks time);
@@ -557,6 +561,7 @@
   bool did_lock_scrolling_layer_;
   bool should_bubble_scrolls_;
   bool wheel_scrolling_;
+  bool scroll_affects_scroll_handler_;
   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 351ec356..c20d08f 100644
--- a/cc/trees/layer_tree_host_impl_unittest.cc
+++ b/cc/trees/layer_tree_host_impl_unittest.cc
@@ -701,6 +701,32 @@
                                     InputHandler::Wheel));
 }
 
+TEST_F(LayerTreeHostImplTest, ScrollHandlerNotPresent) {
+  LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(200, 200));
+  EXPECT_FALSE(scroll_layer->have_scroll_event_handlers());
+  host_impl_->SetViewportSize(gfx::Size(50, 50));
+  DrawFrame();
+
+  EXPECT_FALSE(host_impl_->scroll_affects_scroll_handler());
+  host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture);
+  EXPECT_FALSE(host_impl_->scroll_affects_scroll_handler());
+  host_impl_->ScrollEnd();
+  EXPECT_FALSE(host_impl_->scroll_affects_scroll_handler());
+}
+
+TEST_F(LayerTreeHostImplTest, ScrollHandlerPresent) {
+  LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(200, 200));
+  scroll_layer->SetHaveScrollEventHandlers(true);
+  host_impl_->SetViewportSize(gfx::Size(50, 50));
+  DrawFrame();
+
+  EXPECT_FALSE(host_impl_->scroll_affects_scroll_handler());
+  host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture);
+  EXPECT_TRUE(host_impl_->scroll_affects_scroll_handler());
+  host_impl_->ScrollEnd();
+  EXPECT_FALSE(host_impl_->scroll_affects_scroll_handler());
+}
+
 TEST_F(LayerTreeHostImplTest, ScrollByReturnsCorrectValue) {
   SetupScrollAndContentsLayers(gfx::Size(200, 200));
   host_impl_->SetViewportSize(gfx::Size(100, 100));
diff --git a/cc/trees/thread_proxy.cc b/cc/trees/thread_proxy.cc
index 8a1547c3..0c0ff9a 100644
--- a/cc/trees/thread_proxy.cc
+++ b/cc/trees/thread_proxy.cc
@@ -1626,8 +1626,9 @@
   DCHECK(IsImplThread());
   bool smoothness_takes_priority =
       impl().layer_tree_host_impl->pinch_gesture_active() ||
-      impl().layer_tree_host_impl->IsCurrentlyScrolling() ||
-      impl().layer_tree_host_impl->page_scale_animation_active();
+      impl().layer_tree_host_impl->page_scale_animation_active() ||
+      (impl().layer_tree_host_impl->IsCurrentlyScrolling() &&
+       !impl().layer_tree_host_impl->scroll_affects_scroll_handler());
 
   base::TimeTicks now = impl().layer_tree_host_impl->CurrentFrameTimeTicks();