Add initial CC support for scroll-blocks-on
When 'scroll-blocks-on: scroll-event' is applied anywhere in the scroll ancestor tree where is a scroll event handler, force the scroll to be executed on the main thread. Note that this is still experimental. We'll be at least adding a timeout mechanism to this to mitigate the risk of improper usage.
When 'scroll-blocks-on: wheel-event' is NOT applied (it's on by default), ignore the existence of wheel event handlers (allowing scrolling to run freely on impl).
When 'scroll-blocks-on: start-touch' is NOT applied (it's on by default), suppress sending touch events to blink. Eventually we'll make this smarter - sending async touch events that don't block scroll.
Depends on blink change https://src.chromium.org/viewvc/blink?view=rev&revision=188230
BUG=347272
Review URL: https://codereview.chromium.org/784463002
Cr-Commit-Position: refs/heads/master@{#314765}
diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc
index b5509a7..f51c61a 100644
--- a/cc/trees/layer_tree_host_impl.cc
+++ b/cc/trees/layer_tree_host_impl.cc
@@ -467,16 +467,39 @@
return layer_impl != NULL;
}
-bool LayerTreeHostImpl::HaveTouchEventHandlersAt(
- const gfx::Point& viewport_point) {
+static LayerImpl* NextScrollLayer(LayerImpl* layer) {
+ if (LayerImpl* scroll_parent = layer->scroll_parent())
+ return scroll_parent;
+ return layer->parent();
+}
+static ScrollBlocksOn EffectiveScrollBlocksOn(LayerImpl* layer) {
+ ScrollBlocksOn blocks = ScrollBlocksOnNone;
+ for (; layer; layer = NextScrollLayer(layer)) {
+ blocks |= layer->scroll_blocks_on();
+ }
+ return blocks;
+}
+
+bool LayerTreeHostImpl::DoTouchEventsBlockScrollAt(
+ const gfx::Point& viewport_point) {
gfx::PointF device_viewport_point =
gfx::ScalePoint(viewport_point, device_scale_factor_);
+ // First check if scrolling at this point is required to block on any
+ // touch event handlers. Note that we must start at the innermost layer
+ // (as opposed to only the layer found to contain a touch handler region
+ // below) to ensure all relevant scroll-blocks-on values are applied.
LayerImpl* layer_impl =
- active_tree_->FindLayerThatIsHitByPointInTouchHandlerRegion(
- device_viewport_point);
+ active_tree_->FindLayerThatIsHitByPoint(device_viewport_point);
+ ScrollBlocksOn blocking = EffectiveScrollBlocksOn(layer_impl);
+ if (!(blocking & ScrollBlocksOnStartTouch))
+ return false;
+ // Now determine if there are actually any handlers at that point.
+ // TODO(rbyers): Consider also honoring touch-action (crbug.com/347272).
+ layer_impl = active_tree_->FindLayerThatIsHitByPointInTouchHandlerRegion(
+ device_viewport_point);
return layer_impl != NULL;
}
@@ -2276,12 +2299,6 @@
input_handler_client_ = client;
}
-static LayerImpl* NextScrollLayer(LayerImpl* layer) {
- if (LayerImpl* scroll_parent = layer->scroll_parent())
- return scroll_parent;
- return layer->parent();
-}
-
LayerImpl* LayerTreeHostImpl::FindScrollLayerForDeviceViewportPoint(
const gfx::PointF& device_viewport_point,
InputHandler::ScrollInputType type,
@@ -2290,12 +2307,15 @@
bool* optional_has_ancestor_scroll_handler) const {
DCHECK(scroll_on_main_thread);
+ ScrollBlocksOn block_mode = EffectiveScrollBlocksOn(layer_impl);
+
// Walk up the hierarchy and look for a scrollable layer.
LayerImpl* potentially_scrolling_layer_impl = NULL;
for (; layer_impl; layer_impl = NextScrollLayer(layer_impl)) {
// The content layer can also block attempts to scroll outside the main
// thread.
- ScrollStatus status = layer_impl->TryScroll(device_viewport_point, type);
+ ScrollStatus status =
+ layer_impl->TryScroll(device_viewport_point, type, block_mode);
if (status == ScrollOnMainThread) {
*scroll_on_main_thread = true;
return NULL;
@@ -2305,7 +2325,8 @@
if (!scroll_layer_impl)
continue;
- status = scroll_layer_impl->TryScroll(device_viewport_point, type);
+ status =
+ scroll_layer_impl->TryScroll(device_viewport_point, type, block_mode);
// If any layer wants to divert the scroll event to the main thread, abort.
if (status == ScrollOnMainThread) {
*scroll_on_main_thread = true;