diff --git a/servo/components/compositing/compositor.rs b/servo/components/compositing/compositor.rs index 55c183da777f..52c617fb0bd4 100644 --- a/servo/components/compositing/compositor.rs +++ b/servo/components/compositing/compositor.rs @@ -22,7 +22,7 @@ use net_traits::image::base::{Image, PixelFormat}; use profile_traits::time::{self, ProfilerCategory, profile}; use script_traits::{AnimationState, AnimationTickType, ConstellationControlMsg}; use script_traits::{ConstellationMsg, DevicePixel, LayoutControlMsg, LoadData, MouseButton}; -use script_traits::{MouseEventType, StackingContextScrollState}; +use script_traits::{MouseEventType, ScrollState}; use script_traits::{TouchpadPressurePhase, TouchEventType, TouchId, WindowSizeData, WindowSizeType}; use script_traits::CompositorEvent::{self, MouseMoveEvent, MouseButtonEvent, TouchEvent, TouchpadPressureEvent}; use servo_config::opts; @@ -1368,29 +1368,26 @@ impl IOCompositor { } fn send_viewport_rects(&self) { - let mut stacking_context_scroll_states_per_pipeline = HashMap::new(); + let mut scroll_states_per_pipeline = HashMap::new(); for scroll_layer_state in self.webrender_api.get_scroll_node_state() { if scroll_layer_state.id.external_id().is_none() && - scroll_layer_state.id.is_root_scroll_node() { + !scroll_layer_state.id.is_root_scroll_node() { continue; } - let stacking_context_scroll_state = StackingContextScrollState { + let scroll_state = ScrollState { scroll_root_id: scroll_layer_state.id, scroll_offset: scroll_layer_state.scroll_offset.to_untyped(), }; - stacking_context_scroll_states_per_pipeline - .entry(scroll_layer_state.id.pipeline_id()) - .or_insert(vec![]) - .push(stacking_context_scroll_state); + scroll_states_per_pipeline.entry(scroll_layer_state.id.pipeline_id()) + .or_insert(vec![]) + .push(scroll_state); } - for (pipeline_id, stacking_context_scroll_states) in - stacking_context_scroll_states_per_pipeline { + for (pipeline_id, scroll_states) in scroll_states_per_pipeline { if let Some(pipeline) = self.pipeline(pipeline_id.from_webrender()) { - let msg = LayoutControlMsg::SetStackingContextScrollStates( - stacking_context_scroll_states); + let msg = LayoutControlMsg::SetScrollStates(scroll_states); let _ = pipeline.layout_chan.send(msg); } } diff --git a/servo/components/gfx/display_list/mod.rs b/servo/components/gfx/display_list/mod.rs index ac1db774f10a..626c3f56b3dd 100644 --- a/servo/components/gfx/display_list/mod.rs +++ b/servo/components/gfx/display_list/mod.rs @@ -47,6 +47,74 @@ pub struct DisplayList { pub list: Vec, } +struct ScrollOffsetLookup<'a> { + parents: &'a mut HashMap, + calculated_total_offsets: ScrollOffsetMap, + raw_offsets: &'a ScrollOffsetMap, +} + +impl<'a> ScrollOffsetLookup<'a> { + fn new(parents: &'a mut HashMap, + raw_offsets: &'a ScrollOffsetMap) + -> ScrollOffsetLookup<'a> { + ScrollOffsetLookup { + parents: parents, + calculated_total_offsets: HashMap::new(), + raw_offsets: raw_offsets, + } + } + + fn new_for_reference_frame(&mut self, + clip_id: ClipId, + transform: &Matrix4D, + point: &mut Point2D) + -> Option { + // If a transform function causes the current transformation matrix of an object + // to be non-invertible, the object and its content do not get displayed. + let inv_transform = match transform.inverse() { + Some(transform) => transform, + None => return None, + }; + + let scroll_offset = self.full_offset_for_scroll_root(&clip_id); + *point = Point2D::new(point.x - Au::from_f32_px(scroll_offset.x), + point.y - Au::from_f32_px(scroll_offset.y)); + let frac_point = inv_transform.transform_point(&Point2D::new(point.x.to_f32_px(), + point.y.to_f32_px())); + *point = Point2D::new(Au::from_f32_px(frac_point.x), Au::from_f32_px(frac_point.y)); + + let mut sublookup = ScrollOffsetLookup { + parents: &mut self.parents, + calculated_total_offsets: HashMap::new(), + raw_offsets: self.raw_offsets, + }; + sublookup.calculated_total_offsets.insert(clip_id, Point2D::zero()); + Some(sublookup) + } + + fn add_scroll_root(&mut self, scroll_root: &ScrollRoot) { + self.parents.insert(scroll_root.id, scroll_root.parent_id); + } + + fn full_offset_for_scroll_root(&mut self, id: &ClipId) -> Point2D { + if let Some(offset) = self.calculated_total_offsets.get(id) { + return *offset; + } + + let parent_offset = if !id.is_root_scroll_node() { + let parent_id = *self.parents.get(id).unwrap(); + self.full_offset_for_scroll_root(&parent_id) + } else { + Point2D::zero() + }; + + let offset = parent_offset + + self.raw_offsets.get(id).cloned().unwrap_or_else(Point2D::zero); + self.calculated_total_offsets.insert(*id, offset); + offset + } +} + impl DisplayList { /// Return the bounds of this display list based on the dimensions of the root /// stacking context. @@ -69,51 +137,36 @@ impl DisplayList { self.text_index_contents(node, &mut traversal, client_point, - client_point, - scroll_offsets, + &mut ScrollOffsetLookup::new(&mut HashMap::new(), scroll_offsets), &mut result); result.pop() } - pub fn text_index_contents<'a>(&self, - node: OpaqueNode, - traversal: &mut DisplayListTraversal<'a>, - translated_point: &Point2D, - client_point: &Point2D, - scroll_offsets: &ScrollOffsetMap, - result: &mut Vec) { + fn text_index_contents<'a>(&self, + node: OpaqueNode, + traversal: &mut DisplayListTraversal<'a>, + point: &Point2D, + offset_lookup: &mut ScrollOffsetLookup, + result: &mut Vec) { while let Some(item) = traversal.next() { match item { - &DisplayItem::PushStackingContext(ref stacking_context_item) => { - let mut point = *translated_point; - DisplayList::translate_point(&stacking_context_item.stacking_context, - &mut point, - client_point); - self.text_index_contents(node, - traversal, - &point, - client_point, - scroll_offsets, - result); + &DisplayItem::PushStackingContext(ref context_item) => { + self.text_index_stacking_context(&context_item.stacking_context, + item.base().scroll_root_id, + node, + traversal, + point, + offset_lookup, + result); } &DisplayItem::DefineClip(ref item) => { - let mut point = *translated_point; - DisplayList::scroll_root(&item.scroll_root, - &mut point, - scroll_offsets); - self.text_index_contents(node, - traversal, - &point, - client_point, - scroll_offsets, - result); - - }, + offset_lookup.add_scroll_root(&item.scroll_root); + } &DisplayItem::PopStackingContext(_) => return, &DisplayItem::Text(ref text) => { let base = item.base(); if base.metadata.node == node { - let offset = *translated_point - text.baseline_origin; + let offset = *point - text.baseline_origin; let index = text.text_run.range_index_of_advance(&text.range, offset.x); result.push(index); } @@ -123,56 +176,71 @@ impl DisplayList { } } + fn text_index_stacking_context<'a>(&self, + stacking_context: &StackingContext, + clip_id: ClipId, + node: OpaqueNode, + traversal: &mut DisplayListTraversal<'a>, + point: &Point2D, + offset_lookup: &mut ScrollOffsetLookup, + result: &mut Vec) { + let mut point = *point - stacking_context.bounds.origin; + if stacking_context.scroll_policy == ScrollPolicy::Fixed { + let old_offset = offset_lookup.calculated_total_offsets.get(&clip_id).cloned(); + offset_lookup.calculated_total_offsets.insert(clip_id, Point2D::zero()); + + self.text_index_contents(node, traversal, &point, offset_lookup, result); + + match old_offset { + Some(offset) => offset_lookup.calculated_total_offsets.insert(clip_id, offset), + None => offset_lookup.calculated_total_offsets.remove(&clip_id), + }; + } else if let Some(transform) = stacking_context.transform { + if let Some(ref mut sublookup) = + offset_lookup.new_for_reference_frame(clip_id, &transform, &mut point) { + self.text_index_contents(node, traversal, &point, sublookup, result); + } + } else { + self.text_index_contents(node, traversal, &point, offset_lookup, result); + } + } + // Return all nodes containing the point of interest, bottommost first, and // respecting the `pointer-events` CSS property. pub fn hit_test(&self, - translated_point: &Point2D, - client_point: &Point2D, + point: &Point2D, scroll_offsets: &ScrollOffsetMap) -> Vec { let mut result = Vec::new(); let mut traversal = DisplayListTraversal::new(self); self.hit_test_contents(&mut traversal, - translated_point, - client_point, - scroll_offsets, + point, + &mut ScrollOffsetLookup::new(&mut HashMap::new(), scroll_offsets), &mut result); result } - pub fn hit_test_contents<'a>(&self, - traversal: &mut DisplayListTraversal<'a>, - translated_point: &Point2D, - client_point: &Point2D, - scroll_offsets: &ScrollOffsetMap, - result: &mut Vec) { + fn hit_test_contents<'a>(&self, + traversal: &mut DisplayListTraversal<'a>, + point: &Point2D, + offset_lookup: &mut ScrollOffsetLookup, + result: &mut Vec) { while let Some(item) = traversal.next() { match item { - &DisplayItem::PushStackingContext(ref stacking_context_item) => { - let mut point = *translated_point; - DisplayList::translate_point(&stacking_context_item.stacking_context, - &mut point, - client_point); - self.hit_test_contents(traversal, - &point, - client_point, - scroll_offsets, - result); - } - &DisplayItem::DefineClip(ref item) => { - let mut point = *translated_point; - DisplayList::scroll_root(&item.scroll_root, - &mut point, - scroll_offsets); - self.hit_test_contents(traversal, - &point, - client_point, - scroll_offsets, - result); + &DisplayItem::PushStackingContext(ref context_item) => { + self.hit_test_stacking_context(&context_item.stacking_context, + item.base().scroll_root_id, + traversal, + point, + offset_lookup, + result); } &DisplayItem::PopStackingContext(_) => return, + &DisplayItem::DefineClip(ref item) => { + offset_lookup.add_scroll_root(&item.scroll_root); + } _ => { - if let Some(meta) = item.hit_test(*translated_point) { + if let Some(meta) = item.hit_test(*point, offset_lookup) { result.push(meta); } } @@ -180,52 +248,33 @@ impl DisplayList { } } - #[inline] - fn translate_point<'a>(stacking_context: &StackingContext, - translated_point: &mut Point2D, - client_point: &Point2D) { - // Convert the parent translated point into stacking context local transform space if the - // stacking context isn't fixed. If it's fixed, we need to use the client point anyway. + fn hit_test_stacking_context<'a>(&self, + stacking_context: &StackingContext, + clip_id: ClipId, + traversal: &mut DisplayListTraversal<'a>, + point: &Point2D, + offset_lookup: &mut ScrollOffsetLookup, + result: &mut Vec) { debug_assert!(stacking_context.context_type == StackingContextType::Real); - let is_fixed = stacking_context.scroll_policy == ScrollPolicy::Fixed; - *translated_point = if is_fixed { - *client_point - } else { - let point = *translated_point - stacking_context.bounds.origin; - match stacking_context.transform { - Some(transform) => { - let inv_transform = match transform.inverse() { - Some(transform) => transform, - None => { - // If a transform function causes the current transformation matrix of an object - // to be non-invertible, the object and its content do not get displayed. - return; - } - }; - let frac_point = inv_transform.transform_point(&Point2D::new(point.x.to_f32_px(), - point.y.to_f32_px())); - Point2D::new(Au::from_f32_px(frac_point.x), Au::from_f32_px(frac_point.y)) - } - None => { - point - } + let mut point = *point - stacking_context.bounds.origin; + if stacking_context.scroll_policy == ScrollPolicy::Fixed { + let old_offset = offset_lookup.calculated_total_offsets.get(&clip_id).cloned(); + offset_lookup.calculated_total_offsets.insert(clip_id, Point2D::zero()); + + self.hit_test_contents(traversal, &point, offset_lookup, result); + + match old_offset { + Some(offset) => offset_lookup.calculated_total_offsets.insert(clip_id, offset), + None => offset_lookup.calculated_total_offsets.remove(&clip_id), + }; + } else if let Some(transform) = stacking_context.transform { + if let Some(ref mut sublookup) = + offset_lookup.new_for_reference_frame(clip_id, &transform, &mut point) { + self.hit_test_contents(traversal, &point, sublookup, result); } - }; - } - - #[inline] - fn scroll_root<'a>(scroll_root: &ScrollRoot, - translated_point: &mut Point2D, - scroll_offsets: &ScrollOffsetMap) { - // Adjust the translated point to account for the scroll offset if necessary. - // - // We don't perform this adjustment on the root stacking context because - // the DOM-side code has already translated the point for us (e.g. in - // `Window::hit_test_query()`) by now. - if let Some(scroll_offset) = scroll_offsets.get(&scroll_root.id) { - translated_point.x -= Au::from_f32_px(scroll_offset.x); - translated_point.y -= Au::from_f32_px(scroll_offset.y); + } else { + self.hit_test_contents(traversal, &point, offset_lookup, result); } } @@ -1207,11 +1256,18 @@ impl DisplayItem { println!("{}+ {:?}", indent, self); } - fn hit_test(&self, point: Point2D) -> Option { + fn hit_test(&self, + point: Point2D, + offset_lookup: &mut ScrollOffsetLookup) + -> Option { // TODO(pcwalton): Use a precise algorithm here. This will allow us to properly hit // test elements with `border-radius`, for example. let base_item = self.base(); + let scroll_offset = offset_lookup.full_offset_for_scroll_root(&base_item.scroll_root_id); + let point = Point2D::new(point.x - Au::from_f32_px(scroll_offset.x), + point.y - Au::from_f32_px(scroll_offset.y)); + if !base_item.clip.might_intersect_point(&point) { // Clipped out. return None; diff --git a/servo/components/layout/query.rs b/servo/components/layout/query.rs index 476a68afafe6..da10696ec297 100644 --- a/servo/components/layout/query.rs +++ b/servo/components/layout/query.rs @@ -81,8 +81,8 @@ pub struct LayoutThreadData { /// A queued response for the offset parent/rect of a node. pub margin_style_response: MarginStyleResponse, - /// Scroll offsets of stacking contexts. This will only be populated if WebRender is in use. - pub stacking_context_scroll_offsets: ScrollOffsetMap, + /// Scroll offsets of scrolling regions. + pub scroll_offsets: ScrollOffsetMap, /// Index in a text fragment. We need this do determine the insertion point. pub text_index_response: TextIndexResponse, diff --git a/servo/components/layout_thread/lib.rs b/servo/components/layout_thread/lib.rs index 7a3bf5cb9aba..eed95ecb9ea3 100644 --- a/servo/components/layout_thread/lib.rs +++ b/servo/components/layout_thread/lib.rs @@ -88,7 +88,7 @@ use script_layout_interface::rpc::{LayoutRPC, MarginStyleResponse, NodeOverflowR use script_layout_interface::rpc::TextIndexResponse; use script_layout_interface::wrapper_traits::LayoutNode; use script_traits::{ConstellationControlMsg, LayoutControlMsg, LayoutMsg as ConstellationMsg}; -use script_traits::{StackingContextScrollState, UntrustedNodeAddress}; +use script_traits::{ScrollState, UntrustedNodeAddress}; use selectors::Element; use servo_config::opts; use servo_config::prefs::PREFS; @@ -506,7 +506,7 @@ impl LayoutThread { resolved_style_response: String::new(), offset_parent_response: OffsetParentResponse::empty(), margin_style_response: MarginStyleResponse::empty(), - stacking_context_scroll_offsets: HashMap::new(), + scroll_offsets: HashMap::new(), text_index_response: TextIndexResponse(None), nodes_from_point_response: vec![], })), @@ -600,9 +600,8 @@ impl LayoutThread { }; match request { - Request::FromPipeline(LayoutControlMsg::SetStackingContextScrollStates( - new_scroll_states)) => { - self.handle_request_helper(Msg::SetStackingContextScrollStates(new_scroll_states), + Request::FromPipeline(LayoutControlMsg::SetScrollStates(new_scroll_states)) => { + self.handle_request_helper(Msg::SetScrollStates(new_scroll_states), possibly_locked_rw_data) }, Request::FromPipeline(LayoutControlMsg::TickAnimations) => { @@ -653,9 +652,12 @@ impl LayoutThread { || self.handle_reflow(&mut data, possibly_locked_rw_data)); }, Msg::TickAnimations => self.tick_all_animations(possibly_locked_rw_data), - Msg::SetStackingContextScrollStates(new_scroll_states) => { - self.set_stacking_context_scroll_states(new_scroll_states, - possibly_locked_rw_data); + Msg::SetScrollStates(new_scroll_states) => { + self.set_scroll_states(new_scroll_states, possibly_locked_rw_data); + } + Msg::UpdateScrollStateFromScript(state) => { + let mut rw_data = possibly_locked_rw_data.lock(); + rw_data.scroll_offsets.insert(state.scroll_root_id, state.scroll_offset); } Msg::ReapStyleAndLayoutData(dead_data) => { unsafe { @@ -1306,19 +1308,13 @@ impl LayoutThread { let node = unsafe { ServoLayoutNode::new(&node) }; rw_data.content_boxes_response = process_content_boxes_request(node, root_flow); }, - ReflowQueryType::HitTestQuery(translated_point, client_point, update_cursor) => { - let mut translated_point = Point2D::new(Au::from_f32_px(translated_point.x), - Au::from_f32_px(translated_point.y)); - - let client_point = Point2D::new(Au::from_f32_px(client_point.x), - Au::from_f32_px(client_point.y)); - + ReflowQueryType::HitTestQuery(client_point, update_cursor) => { + let point = Point2D::new(Au::from_f32_px(client_point.x), + Au::from_f32_px(client_point.y)); let result = rw_data.display_list .as_ref() .expect("Tried to hit test with no display list") - .hit_test(&mut translated_point, - &client_point, - &rw_data.stacking_context_scroll_offsets); + .hit_test(&point, &rw_data.scroll_offsets); rw_data.hit_test_response = (result.last().cloned(), update_cursor); }, ReflowQueryType::TextIndexQuery(node, mouse_x, mouse_y) => { @@ -1332,7 +1328,7 @@ impl LayoutThread { .expect("Tried to hit test with no display list") .text_index(opaque_node, &client_point, - &rw_data.stacking_context_scroll_offsets)); + &rw_data.scroll_offsets)); }, ReflowQueryType::NodeGeometryQuery(node) => { let node = unsafe { ServoLayoutNode::new(&node) }; @@ -1368,18 +1364,14 @@ impl LayoutThread { let node = unsafe { ServoLayoutNode::new(&node) }; rw_data.margin_style_response = process_margin_style_query(node); }, - ReflowQueryType::NodesFromPoint(page_point, client_point) => { - let page_point = Point2D::new(Au::from_f32_px(page_point.x), - Au::from_f32_px(page_point.y)); + ReflowQueryType::NodesFromPoint(client_point) => { let client_point = Point2D::new(Au::from_f32_px(client_point.x), Au::from_f32_px(client_point.y)); let nodes_from_point_list = { let result = match rw_data.display_list { None => panic!("Tried to hit test without a DisplayList"), Some(ref display_list) => { - display_list.hit_test(&page_point, - &client_point, - &rw_data.stacking_context_scroll_offsets) + display_list.hit_test(&client_point, &rw_data.scroll_offsets) } }; @@ -1395,10 +1387,9 @@ impl LayoutThread { } } - fn set_stacking_context_scroll_states<'a, 'b>( - &mut self, - new_scroll_states: Vec, - possibly_locked_rw_data: &mut RwData<'a, 'b>) { + fn set_scroll_states<'a, 'b>(&mut self, + new_scroll_states: Vec, + possibly_locked_rw_data: &mut RwData<'a, 'b>) { let mut rw_data = possibly_locked_rw_data.lock(); let mut script_scroll_states = vec![]; let mut layout_scroll_states = HashMap::new(); @@ -1416,7 +1407,7 @@ impl LayoutThread { } let _ = self.script_chan .send(ConstellationControlMsg::SetScrollState(self.id, script_scroll_states)); - rw_data.stacking_context_scroll_offsets = layout_scroll_states + rw_data.scroll_offsets = layout_scroll_states } fn tick_all_animations<'a, 'b>(&mut self, possibly_locked_rw_data: &mut RwData<'a, 'b>) { diff --git a/servo/components/script/dom/document.rs b/servo/components/script/dom/document.rs index bce898e6347b..e44de8be727c 100644 --- a/servo/components/script/dom/document.rs +++ b/servo/components/script/dom/document.rs @@ -1955,12 +1955,8 @@ impl Document { } pub fn nodes_from_point(&self, client_point: &Point2D) -> Vec { - let page_point = - Point2D::new(client_point.x + self.window.PageXOffset() as f32, - client_point.y + self.window.PageYOffset() as f32); - if !self.window.reflow(ReflowGoal::ForScriptQuery, - ReflowQueryType::NodesFromPoint(page_point, *client_point), + ReflowQueryType::NodesFromPoint(*client_point), ReflowReason::Query) { return vec!(); }; diff --git a/servo/components/script/dom/window.rs b/servo/components/script/dom/window.rs index 4317d2890b76..65d1a591adc5 100644 --- a/servo/components/script/dom/window.rs +++ b/servo/components/script/dom/window.rs @@ -75,11 +75,11 @@ use script_layout_interface::rpc::{ContentBoxResponse, ContentBoxesResponse, Lay use script_layout_interface::rpc::{MarginStyleResponse, NodeScrollRootIdResponse}; use script_layout_interface::rpc::{ResolvedStyleResponse, TextIndexResponse}; use script_runtime::{CommonScriptMsg, ScriptChan, ScriptPort, ScriptThreadEventCategory}; -use script_thread::{MainThreadScriptChan, MainThreadScriptMsg, Runnable, RunnableWrapper}; -use script_thread::{SendableMainThreadScriptChan, ImageCacheMsg, ScriptThread}; -use script_traits::{ConstellationControlMsg, LoadData, MozBrowserEvent, UntrustedNodeAddress}; -use script_traits::{DocumentState, TimerEvent, TimerEventId}; -use script_traits::{ScriptMsg as ConstellationMsg, TimerSchedulerMsg, WindowSizeData, WindowSizeType}; +use script_thread::{ImageCacheMsg, MainThreadScriptChan, MainThreadScriptMsg, Runnable}; +use script_thread::{RunnableWrapper, ScriptThread, SendableMainThreadScriptChan}; +use script_traits::{ConstellationControlMsg, DocumentState, LoadData, MozBrowserEvent}; +use script_traits::{ScriptMsg as ConstellationMsg, ScrollState, TimerEvent, TimerEventId}; +use script_traits::{TimerSchedulerMsg, UntrustedNodeAddress, WindowSizeData, WindowSizeType}; use script_traits::webdriver_msg::{WebDriverJSError, WebDriverJSResult}; use servo_atoms::Atom; use servo_config::opts; @@ -1111,6 +1111,11 @@ impl Window { ScrollBehavior::Smooth => true }; + self.layout_chan.send(Msg::UpdateScrollStateFromScript(ScrollState { + scroll_root_id: scroll_root_id, + scroll_offset: Point2D::new(-x, -y), + })).unwrap(); + // TODO (farodin91): Raise an event to stop the current_viewport self.update_viewport_for_scroll(x, y); @@ -1372,14 +1377,8 @@ impl Window { client_point: Point2D, update_cursor: bool) -> Option { - let translated_point = - Point2D::new(client_point.x + self.PageXOffset() as f32, - client_point.y + self.PageYOffset() as f32); - if !self.reflow(ReflowGoal::ForScriptQuery, - ReflowQueryType::HitTestQuery(translated_point, - client_point, - update_cursor), + ReflowQueryType::HitTestQuery(client_point, update_cursor), ReflowReason::Query) { return None } diff --git a/servo/components/script_layout_interface/message.rs b/servo/components/script_layout_interface/message.rs index 9c2f94b0dc04..038967fdd04a 100644 --- a/servo/components/script_layout_interface/message.rs +++ b/servo/components/script_layout_interface/message.rs @@ -12,8 +12,8 @@ use msg::constellation_msg::PipelineId; use net_traits::image_cache::ImageCache; use profile_traits::mem::ReportsChan; use rpc::LayoutRPC; -use script_traits::{ConstellationControlMsg, LayoutControlMsg, UntrustedNodeAddress}; -use script_traits::{LayoutMsg as ConstellationMsg, StackingContextScrollState, WindowSizeData}; +use script_traits::{ConstellationControlMsg, LayoutControlMsg, LayoutMsg as ConstellationMsg}; +use script_traits::{ScrollState, UntrustedNodeAddress, WindowSizeData}; use servo_url::ServoUrl; use std::sync::Arc; use std::sync::mpsc::{Receiver, Sender}; @@ -79,7 +79,11 @@ pub enum Msg { SetFinalUrl(ServoUrl), /// Tells layout about the new scrolling offsets of each scrollable stacking context. - SetStackingContextScrollStates(Vec), + SetScrollStates(Vec), + + /// Tells layout about a single new scrolling offset from the script. The rest will + /// remain untouched and layout won't forward this back to script. + UpdateScrollStateFromScript(ScrollState), } @@ -90,7 +94,7 @@ pub enum ReflowQueryType { ContentBoxQuery(TrustedNodeAddress), ContentBoxesQuery(TrustedNodeAddress), NodeOverflowQuery(TrustedNodeAddress), - HitTestQuery(Point2D, Point2D, bool), + HitTestQuery(Point2D, bool), NodeScrollRootIdQuery(TrustedNodeAddress), NodeGeometryQuery(TrustedNodeAddress), NodeScrollGeometryQuery(TrustedNodeAddress), @@ -98,7 +102,7 @@ pub enum ReflowQueryType { OffsetParentQuery(TrustedNodeAddress), MarginStyleQuery(TrustedNodeAddress), TextIndexQuery(TrustedNodeAddress, i32, i32), - NodesFromPoint(Point2D, Point2D), + NodesFromPoint(Point2D), } /// Information needed for a reflow. diff --git a/servo/components/script_traits/lib.rs b/servo/components/script_traits/lib.rs index 4f3cfca76a5c..bfc1e63fcc89 100644 --- a/servo/components/script_traits/lib.rs +++ b/servo/components/script_traits/lib.rs @@ -122,7 +122,7 @@ pub enum LayoutControlMsg { /// Asks layout to run another step in its animation. TickAnimations, /// Tells layout about the new scrolling offsets of each scrollable stacking context. - SetStackingContextScrollStates(Vec), + SetScrollStates(Vec), /// Requests the current load state of Web fonts. `true` is returned if fonts are still loading /// and `false` is returned if all fonts have loaded. GetWebFontLoadState(IpcSender), @@ -673,7 +673,7 @@ pub enum AnimationTickType { /// The scroll state of a stacking context. #[derive(Copy, Clone, Debug, Deserialize, Serialize)] -pub struct StackingContextScrollState { +pub struct ScrollState { /// The ID of the scroll root. pub scroll_root_id: ClipId, /// The scrolling offset of this stacking context.