diff --git a/webrender/src/frame.rs b/webrender/src/frame.rs index 67e2abe192..2db9384895 100644 --- a/webrender/src/frame.rs +++ b/webrender/src/frame.rs @@ -352,9 +352,44 @@ impl Frame { (_, _, None) => return false, }; - let scroll_root_id = match scroll_layer_id.info { - ScrollLayerInfo::Scrollable(_, scroll_root_id) => scroll_root_id, - ScrollLayerInfo::Fixed => unreachable!("Tried to scroll a fixed position layer."), + let non_root_overscroll = if scroll_layer_id != root_scroll_layer_id { + // true if the current layer is overscrolling, + // and it is not the root scroll layer. + let child_layer = self.layers.get(&scroll_layer_id).unwrap(); + let overscroll_amount = child_layer.overscroll_amount(); + overscroll_amount.width != 0.0 || overscroll_amount.height != 0.0 + } else { + false + }; + + let switch_layer = match phase { + ScrollEventPhase::Start => { + // if this is a new gesture, we do not switch layer, + // however we do save the state of non_root_overscroll, + // for use in the subsequent Move phase. + let mut current_layer = self.layers.get_mut(&scroll_layer_id).unwrap(); + current_layer.scrolling.should_handoff_scroll = non_root_overscroll; + false + }, + ScrollEventPhase::Move(_) => { + // Switch layer if movement originated in a new gesture, + // from a non root layer in overscroll. + let current_layer = self.layers.get_mut(&scroll_layer_id).unwrap(); + current_layer.scrolling.should_handoff_scroll && non_root_overscroll + }, + ScrollEventPhase::End => { + // clean-up when gesture ends. + let mut current_layer = self.layers.get_mut(&scroll_layer_id).unwrap(); + current_layer.scrolling.should_handoff_scroll = false; + false + }, + }; + + let scroll_root_id = match (switch_layer, scroll_layer_id.info, root_scroll_layer_id.info) { + (true, _, ScrollLayerInfo::Scrollable(_, scroll_root_id)) | + (true, ScrollLayerInfo::Scrollable(_, scroll_root_id), ScrollLayerInfo::Fixed) | + (false, ScrollLayerInfo::Scrollable(_, scroll_root_id), _) => scroll_root_id, + (_, ScrollLayerInfo::Fixed, _) => unreachable!("Tried to scroll a fixed position layer."), }; let mut scrolled_a_layer = false; diff --git a/webrender/src/layer.rs b/webrender/src/layer.rs index f16509620e..985420ef59 100644 --- a/webrender/src/layer.rs +++ b/webrender/src/layer.rs @@ -128,6 +128,7 @@ pub struct ScrollingState { pub spring: Spring, pub started_bouncing_back: bool, pub bouncing_back: bool, + pub should_handoff_scroll: bool } impl ScrollingState { @@ -137,6 +138,7 @@ impl ScrollingState { spring: Spring::at(LayerPoint::zero(), STIFFNESS, DAMPING), started_bouncing_back: false, bouncing_back: false, + should_handoff_scroll: false } } }