diff --git a/components/compositing/compositor_data.rs b/components/compositing/compositor_data.rs index bbb46603f6a..17ce34aab12 100644 --- a/components/compositing/compositor_data.rs +++ b/components/compositing/compositor_data.rs @@ -18,6 +18,7 @@ use layers::platform::surface::NativeSurfaceMethods; use servo_msg::compositor_msg::{Epoch, LayerId}; use servo_msg::compositor_msg::ScrollPolicy; use servo_msg::constellation_msg::PipelineId; +use servo_util::geometry::PagePx; use std::rc::Rc; pub struct CompositorData { @@ -39,6 +40,10 @@ pub struct CompositorData { /// A monotonically increasing counter that keeps track of the current epoch. /// add_buffer() calls that don't match the current epoch will be ignored. pub epoch: Epoch, + + /// The scroll offset originating from this scrolling root. This allows scrolling roots + /// to track their current scroll position even while their content_offset does not change. + pub scroll_offset: TypedPoint2D, } #[deriving(PartialEq, Clone)] @@ -60,6 +65,7 @@ impl CompositorData { scroll_policy: layer_properties.scroll_policy, background_color: layer_properties.background_color, epoch: layer_properties.epoch, + scroll_offset: TypedPoint2D(0., 0.), }; Rc::new(Layer::new(Rect::from_untyped(&layer_properties.rect), diff --git a/components/compositing/events.rs b/components/compositing/events.rs index c4e86cae26a..0c9136d9936 100644 --- a/components/compositing/events.rs +++ b/components/compositing/events.rs @@ -56,10 +56,9 @@ pub fn handle_scroll_event(layer: Rc>, } // Allow children to scroll. - let content_offset_in_page_pixels : TypedPoint2D = - Point2D::from_untyped(&*layer.content_offset.borrow()); - let content_offset : TypedPoint2D = content_offset_in_page_pixels * scale; - let new_cursor = cursor - content_offset; + let scroll_offset = layer.extra_data.borrow().scroll_offset; + let scroll_offset_in_device_pixels = scroll_offset * scale; + let new_cursor = cursor - scroll_offset_in_device_pixels; for child in layer.children().iter() { let child_bounds = child.bounds.borrow(); if child_bounds.contains(&new_cursor) && @@ -72,8 +71,10 @@ pub fn handle_scroll_event(layer: Rc>, } } - clamp_scroll_offset_and_scroll_layer(layer, content_offset + delta, window_size, scale) - + clamp_scroll_offset_and_scroll_layer(layer, + scroll_offset_in_device_pixels + delta, + window_size, + scale) } pub fn clamp_scroll_offset_and_scroll_layer(layer: Rc>, @@ -89,15 +90,19 @@ pub fn clamp_scroll_offset_and_scroll_layer(layer: Rc>, Length(new_offset.y.get().clamp(&min_y, &0.0))); let new_offset_in_page_px = new_offset / scale; - let untyped_new_offset = new_offset_in_page_px.to_untyped(); - if *layer.content_offset.borrow() == untyped_new_offset { + if layer.extra_data.borrow().scroll_offset == new_offset_in_page_px { return false } - // FIXME: This allows the base layer to record the current content offset without - // updating its transform. This should be replaced with something less strange. - *layer.content_offset.borrow_mut() = untyped_new_offset; - scroll_layer_and_all_child_layers(layer.clone(), new_offset_in_page_px) + // The scroll offset is just a record of the scroll position of this scrolling root, + // but scroll_layer_and_all_child_layers actually moves the child layers. + layer.extra_data.borrow_mut().scroll_offset = new_offset_in_page_px; + + let mut result = false; + for child in layer.children().iter() { + result |= scroll_layer_and_all_child_layers(child.clone(), new_offset_in_page_px); + } + return result; } fn scroll_layer_and_all_child_layers(layer: Rc>,