diff --git a/components/compositing/compositor.rs b/components/compositing/compositor.rs index ed2f0879afac..d25fdb4b7d2e 100644 --- a/components/compositing/compositor.rs +++ b/components/compositing/compositor.rs @@ -15,7 +15,8 @@ use euclid::scale_factor::ScaleFactor; use euclid::size::TypedSize2D; use euclid::{Matrix4D, Point2D, Rect, Size2D}; use gfx::paint_thread::{ChromeToPaintMsg, PaintRequest}; -use gfx_traits::{color, Epoch, FrameTreeId, LayerId, LayerKind, LayerProperties, ScrollPolicy}; +use gfx_traits::{ScrollPolicy, StackingContextId}; +use gfx_traits::{color, Epoch, FrameTreeId, FragmentType, LayerId, LayerKind, LayerProperties}; use gleam::gl; use gleam::gl::types::{GLint, GLsizei}; use image::{DynamicImage, ImageFormat, RgbImage}; @@ -35,8 +36,8 @@ use profile_traits::mem::{self, ReportKind, Reporter, ReporterRequest}; use profile_traits::time::{self, ProfilerCategory, profile}; use script_traits::CompositorEvent::{MouseMoveEvent, MouseButtonEvent, TouchEvent}; use script_traits::{AnimationState, AnimationTickType, ConstellationControlMsg}; -use script_traits::{ConstellationMsg, LayoutControlMsg, MouseButton}; -use script_traits::{MouseEventType, TouchpadPressurePhase, TouchEventType, TouchId}; +use script_traits::{ConstellationMsg, LayoutControlMsg, MouseButton, MouseEventType}; +use script_traits::{StackingContextScrollState, TouchpadPressurePhase, TouchEventType, TouchId}; use std::collections::hash_map::Entry::{Occupied, Vacant}; use std::collections::{HashMap, HashSet}; use std::fs::File; @@ -91,6 +92,32 @@ impl ConvertPipelineIdFromWebRender for webrender_traits::PipelineId { } } +trait ConvertStackingContextFromWebRender { + fn from_webrender(&self) -> StackingContextId; +} + +impl ConvertStackingContextFromWebRender for webrender_traits::ServoStackingContextId { + fn from_webrender(&self) -> StackingContextId { + StackingContextId::new_of_type(self.1, self.0.from_webrender()) + } +} + +trait ConvertFragmentTypeFromWebRender { + fn from_webrender(&self) -> FragmentType; +} + +impl ConvertFragmentTypeFromWebRender for webrender_traits::FragmentType { + fn from_webrender(&self) -> FragmentType { + match *self { + webrender_traits::FragmentType::FragmentBody => FragmentType::FragmentBody, + webrender_traits::FragmentType::BeforePseudoContent => { + FragmentType::BeforePseudoContent + } + webrender_traits::FragmentType::AfterPseudoContent => FragmentType::AfterPseudoContent, + } + } +} + /// Holds the state when running reftests that determines when it is /// safe to save the output image. #[derive(Copy, Clone, PartialEq)] @@ -1620,12 +1647,12 @@ impl IOCompositor { self.perform_updates_after_scroll(); } - - if had_events { - self.send_viewport_rects_for_all_layers(); - } } } + + if had_events { + self.send_viewport_rects_for_all_layers(); + } } /// Computes new display ports for each layer, taking the scroll position into account, and @@ -1887,9 +1914,40 @@ impl IOCompositor { } fn send_viewport_rects_for_all_layers(&self) { - match self.scene.root { - Some(ref root) => self.send_viewport_rect_for_layer(root.clone()), - None => {}, + if opts::get().use_webrender { + return self.send_webrender_viewport_rects() + } + + if let Some(ref root) = self.scene.root { + self.send_viewport_rect_for_layer(root.clone()) + } + } + + fn send_webrender_viewport_rects(&self) { + let mut stacking_context_scroll_states_per_pipeline = HashMap::new(); + if let Some(ref webrender_api) = self.webrender_api { + for scroll_layer_state in webrender_api.get_scroll_layer_state() { + let stacking_context_scroll_state = StackingContextScrollState { + stacking_context_id: scroll_layer_state.stacking_context_id.from_webrender(), + scroll_offset: scroll_layer_state.scroll_offset, + }; + let pipeline_id = scroll_layer_state.pipeline_id; + match stacking_context_scroll_states_per_pipeline.entry(pipeline_id) { + Vacant(mut entry) => { + entry.insert(vec![stacking_context_scroll_state]); + } + Occupied(mut entry) => entry.get_mut().push(stacking_context_scroll_state), + } + } + + for (pipeline_id, stacking_context_scroll_states) in + stacking_context_scroll_states_per_pipeline { + if let Some(pipeline) = self.pipeline(pipeline_id.from_webrender()) { + let msg = LayoutControlMsg::SetStackingContextScrollStates( + stacking_context_scroll_states); + let _ = pipeline.layout_chan.send(msg); + } + } } } diff --git a/components/gfx/display_list/mod.rs b/components/gfx/display_list/mod.rs index d7463c311243..f60a5245cb11 100644 --- a/components/gfx/display_list/mod.rs +++ b/components/gfx/display_list/mod.rs @@ -22,7 +22,7 @@ use euclid::num::Zero; use euclid::rect::TypedRect; use euclid::{Matrix2D, Matrix4D, Point2D, Rect, SideOffsets2D, Size2D}; use fnv::FnvHasher; -use gfx_traits::{LayerId, ScrollPolicy}; +use gfx_traits::{LayerId, ScrollPolicy, StackingContextId}; use ipc_channel::ipc::IpcSharedMemory; use msg::constellation_msg::PipelineId; use net_traits::image::base::{Image, PixelFormat}; @@ -1395,37 +1395,6 @@ impl fmt::Debug for DisplayItem { } } -#[derive(Clone, Debug, PartialEq, Eq, Copy, Hash, Deserialize, Serialize, HeapSizeOf, RustcEncodable)] -pub enum FragmentType { - /// A StackingContext for the fragment body itself. - FragmentBody, - /// A StackingContext created to contain ::before pseudo-element content. - BeforePseudoContent, - /// A StackingContext created to contain ::after pseudo-element content. - AfterPseudoContent, -} - -/// A unique ID for every stacking context. -#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, HeapSizeOf, PartialEq, RustcEncodable, Serialize)] -pub struct StackingContextId( - /// The identifier for this StackingContext, derived from the Flow's memory address - /// and fragment type. As a space optimization, these are combined into a single word. - usize -); - -impl StackingContextId { - #[inline(always)] - pub fn new(id: usize) -> StackingContextId { - StackingContextId::new_of_type(id, FragmentType::FragmentBody) - } - - #[inline(always)] - pub fn new_of_type(id: usize, fragment_type: FragmentType) -> StackingContextId { - debug_assert_eq!(id & fragment_type as usize, 0); - StackingContextId(id | fragment_type as usize) - } -} - #[derive(Copy, Clone, HeapSizeOf, Deserialize, Serialize)] pub struct WebRenderImageInfo { pub width: u32, diff --git a/components/gfx/paint_thread.rs b/components/gfx/paint_thread.rs index bafe17ce015b..3f86acfb4d61 100644 --- a/components/gfx/paint_thread.rs +++ b/components/gfx/paint_thread.rs @@ -8,13 +8,14 @@ use app_units::Au; use azure::AzFloat; use azure::azure_hl::{BackendType, Color, DrawTarget, SurfaceFormat}; use display_list::{DisplayItem, DisplayList, DisplayListTraversal}; -use display_list::{LayerInfo, StackingContext, StackingContextId, StackingContextType}; +use display_list::{LayerInfo, StackingContext, StackingContextType}; use euclid::Matrix4D; use euclid::point::Point2D; use euclid::rect::Rect; use euclid::size::Size2D; use font_cache_thread::FontCacheThread; use font_context::FontContext; +use gfx_traits::StackingContextId; use gfx_traits::{Epoch, FrameTreeId, LayerId, LayerKind, LayerProperties, PaintListener}; use ipc_channel::ipc::IpcSender; use layers::layers::{BufferRequest, LayerBuffer, LayerBufferSet}; diff --git a/components/gfx_traits/lib.rs b/components/gfx_traits/lib.rs index 6065704648da..c1a8155a7989 100644 --- a/components/gfx_traits/lib.rs +++ b/components/gfx_traits/lib.rs @@ -149,3 +149,58 @@ impl FrameTreeId { self.0 += 1; } } + +/// A unique ID for every stacking context. +#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, HeapSizeOf, PartialEq, Serialize)] +pub struct StackingContextId( + /// The identifier for this StackingContext, derived from the Flow's memory address + /// and fragment type. As a space optimization, these are combined into a single word. + usize +); + +impl StackingContextId { + #[inline(always)] + pub fn new(id: usize) -> StackingContextId { + StackingContextId::new_of_type(id, FragmentType::FragmentBody) + } + + #[inline(always)] + pub fn new_of_type(id: usize, fragment_type: FragmentType) -> StackingContextId { + debug_assert_eq!(id & fragment_type as usize, 0); + StackingContextId(id | fragment_type as usize) + } + + #[inline] + pub fn fragment_type(&self) -> FragmentType { + FragmentType::from_usize(self.0 & 3) + } + + #[inline] + pub fn id(&self) -> usize { + self.0 & !3 + } +} + + +#[derive(Clone, Debug, PartialEq, Eq, Copy, Hash, Deserialize, Serialize, HeapSizeOf)] +pub enum FragmentType { + /// A StackingContext for the fragment body itself. + FragmentBody, + /// A StackingContext created to contain ::before pseudo-element content. + BeforePseudoContent, + /// A StackingContext created to contain ::after pseudo-element content. + AfterPseudoContent, +} + +impl FragmentType { + #[inline] + pub fn from_usize(n: usize) -> FragmentType { + debug_assert!(n < 3); + match n { + 0 => FragmentType::FragmentBody, + 1 => FragmentType::BeforePseudoContent, + _ => FragmentType::AfterPseudoContent, + } + } +} + diff --git a/components/layout/block.rs b/components/layout/block.rs index d5decf50c8df..2e0794913d3f 100644 --- a/components/layout/block.rs +++ b/components/layout/block.rs @@ -43,8 +43,8 @@ use flow_list::FlowList; use flow_ref::FlowRef; use fragment::SpecificFragmentInfo; use fragment::{CoordinateSystem, Fragment, FragmentBorderBoxIterator, HAS_LAYER, Overflow}; -use gfx::display_list::{ClippingRegion, StackingContext, StackingContextId}; -use gfx_traits::LayerId; +use gfx::display_list::{ClippingRegion, StackingContext}; +use gfx_traits::{LayerId, StackingContextId}; use incremental::{BUBBLE_ISIZES, REFLOW, REFLOW_OUT_OF_FLOW, REPAINT}; use layout_debug; use layout_thread::DISPLAY_PORT_SIZE_FACTOR; diff --git a/components/layout/display_list_builder.rs b/components/layout/display_list_builder.rs index 8e1d10424db0..c5e32ab77827 100644 --- a/components/layout/display_list_builder.rs +++ b/components/layout/display_list_builder.rs @@ -21,17 +21,16 @@ use flow::{BaseFlow, Flow, IS_ABSOLUTELY_POSITIONED}; use flow_ref; use fragment::SpecificFragmentInfo; use fragment::{CoordinateSystem, Fragment, HAS_LAYER, ImageFragmentInfo, ScannedTextFragmentInfo}; -use gfx::display_list::GradientDisplayItem; use gfx::display_list::{BLUR_INFLATION_FACTOR, BaseDisplayItem, BorderDisplayItem}; use gfx::display_list::{BorderRadii, BoxShadowClipMode, BoxShadowDisplayItem, ClippingRegion}; -use gfx::display_list::{DisplayItem, DisplayItemMetadata, DisplayListSection}; -use gfx::display_list::{GradientStop, IframeDisplayItem, ImageDisplayItem, WebGLDisplayItem, LayeredItem, LayerInfo}; -use gfx::display_list::{LineDisplayItem, OpaqueNode, SolidColorDisplayItem}; -use gfx::display_list::{StackingContext, StackingContextId, StackingContextType}; +use gfx::display_list::{DisplayItem, DisplayItemMetadata, DisplayListSection, GradientDisplayItem}; +use gfx::display_list::{GradientStop, IframeDisplayItem, ImageDisplayItem, WebGLDisplayItem}; +use gfx::display_list::{LayeredItem, LayerInfo, LineDisplayItem, OpaqueNode}; +use gfx::display_list::{SolidColorDisplayItem, StackingContext, StackingContextType}; use gfx::display_list::{TextDisplayItem, TextOrientation, WebRenderImageInfo}; use gfx::paint_thread::THREAD_TINT_COLORS; use gfx::text::glyph::ByteIndex; -use gfx_traits::{color, ScrollPolicy}; +use gfx_traits::{color, ScrollPolicy, StackingContextId}; use inline::{FIRST_FRAGMENT_OF_ELEMENT, InlineFlow, LAST_FRAGMENT_OF_ELEMENT}; use ipc_channel::ipc; use list_item::ListItemFlow; diff --git a/components/layout/flex.rs b/components/layout/flex.rs index 6d2a12fec62f..5a89a627fbed 100644 --- a/components/layout/flex.rs +++ b/components/layout/flex.rs @@ -17,7 +17,8 @@ use flow::{Flow, FlowClass, ImmutableFlowUtils, OpaqueFlow}; use flow::{INLINE_POSITION_IS_STATIC, IS_ABSOLUTELY_POSITIONED}; use flow_ref::{self, FlowRef}; use fragment::{Fragment, FragmentBorderBoxIterator, Overflow}; -use gfx::display_list::{StackingContext, StackingContextId}; +use gfx::display_list::StackingContext; +use gfx_traits::StackingContextId; use incremental::{REFLOW, REFLOW_OUT_OF_FLOW}; use layout_debug; use model::{IntrinsicISizes, MaybeAuto, MinMaxConstraint}; diff --git a/components/layout/flow.rs b/components/layout/flow.rs index 05e5814d0e06..1267ed31cf15 100644 --- a/components/layout/flow.rs +++ b/components/layout/flow.rs @@ -34,8 +34,8 @@ use floats::{Floats, SpeculatedFloatPlacement}; use flow_list::{FlowList, FlowListIterator, MutFlowListIterator}; use flow_ref::{self, FlowRef, WeakFlowRef}; use fragment::{Fragment, FragmentBorderBoxIterator, Overflow, SpecificFragmentInfo}; -use gfx::display_list::{ClippingRegion, StackingContext, StackingContextId}; -use gfx_traits::{LayerId, LayerType}; +use gfx::display_list::{ClippingRegion, StackingContext}; +use gfx_traits::{LayerId, LayerType, StackingContextId}; use incremental::{RECONSTRUCT_FLOW, REFLOW, REFLOW_OUT_OF_FLOW, REPAINT, RestyleDamage}; use inline::InlineFlow; use model::{CollapsibleMargins, IntrinsicISizes, MarginCollapseInfo}; diff --git a/components/layout/fragment.rs b/components/layout/fragment.rs index 3a5d90201bde..9868e141df19 100644 --- a/components/layout/fragment.rs +++ b/components/layout/fragment.rs @@ -14,10 +14,10 @@ use floats::ClearType; use flow::{self, ImmutableFlowUtils}; use flow_ref::{self, FlowRef}; use gfx; -use gfx::display_list::{BLUR_INFLATION_FACTOR, FragmentType, OpaqueNode, StackingContextId}; +use gfx::display_list::{BLUR_INFLATION_FACTOR, OpaqueNode}; use gfx::text::glyph::ByteIndex; use gfx::text::text_run::{TextRun, TextRunSlice}; -use gfx_traits::{LayerId, LayerType}; +use gfx_traits::{FragmentType, LayerId, LayerType, StackingContextId}; use incremental::{RECONSTRUCT_FLOW, RestyleDamage}; use inline::{FIRST_FRAGMENT_OF_ELEMENT, InlineFragmentContext, InlineFragmentNodeInfo}; use inline::{InlineMetrics, LAST_FRAGMENT_OF_ELEMENT}; diff --git a/components/layout/inline.rs b/components/layout/inline.rs index 4615b728335a..5ad86e54e052 100644 --- a/components/layout/inline.rs +++ b/components/layout/inline.rs @@ -17,9 +17,10 @@ use flow::{self, BaseFlow, Flow, FlowClass, ForceNonfloatedFlag, IS_ABSOLUTELY_P use flow_ref; use fragment::SpecificFragmentInfo; use fragment::{CoordinateSystem, Fragment, FragmentBorderBoxIterator, Overflow}; -use gfx::display_list::{OpaqueNode, StackingContext, StackingContextId}; +use gfx::display_list::{OpaqueNode, StackingContext}; use gfx::font::FontMetrics; use gfx::font_context::FontContext; +use gfx_traits::StackingContextId; use incremental::{BUBBLE_ISIZES, REFLOW, REFLOW_OUT_OF_FLOW, REPAINT, RESOLVE_GENERATED_CONTENT}; use layout_debug; use model::IntrinsicISizesContribution; diff --git a/components/layout/layout_thread.rs b/components/layout/layout_thread.rs index 2509394db5a0..779a23fba826 100644 --- a/components/layout/layout_thread.rs +++ b/components/layout/layout_thread.rs @@ -21,14 +21,13 @@ use euclid::size::Size2D; use flow::{self, Flow, ImmutableFlowUtils, MutableOwnedFlowUtils}; use flow_ref::{self, FlowRef}; use fnv::FnvHasher; -use gfx::display_list::WebRenderImageInfo; use gfx::display_list::{ClippingRegion, DisplayItemMetadata, DisplayList, LayerInfo}; -use gfx::display_list::{OpaqueNode, StackingContext, StackingContextId, StackingContextType}; +use gfx::display_list::{OpaqueNode, StackingContext, StackingContextType, WebRenderImageInfo}; use gfx::font; use gfx::font_cache_thread::FontCacheThread; use gfx::font_context; use gfx::paint_thread::LayoutToPaintMsg; -use gfx_traits::{color, Epoch, LayerId, ScrollPolicy}; +use gfx_traits::{color, Epoch, LayerId, ScrollPolicy, StackingContextId}; use heapsize::HeapSizeOf; use incremental::LayoutDamageComputation; use incremental::{REPAINT, STORE_OVERFLOW, REFLOW_OUT_OF_FLOW, REFLOW, REFLOW_ENTIRE_DOCUMENT}; @@ -52,8 +51,8 @@ use script::dom::node::OpaqueStyleAndLayoutData; use script::layout_interface::{LayoutRPC, OffsetParentResponse, NodeOverflowResponse, MarginStyleResponse}; use script::layout_interface::{Msg, NewLayoutThreadInfo, Reflow, ReflowQueryType, ScriptReflow}; use script::reporter::CSSErrorReporter; -use script_traits::ConstellationControlMsg; -use script_traits::{LayoutControlMsg, LayoutMsg as ConstellationMsg}; +use script_traits::StackingContextScrollState; +use script_traits::{ConstellationControlMsg, LayoutControlMsg, LayoutMsg as ConstellationMsg}; use sequential; use serde_json; use std::borrow::ToOwned; @@ -559,6 +558,11 @@ impl LayoutThread { self.handle_request_helper(Msg::SetVisibleRects(new_visible_rects), possibly_locked_rw_data) }, + Request::FromPipeline(LayoutControlMsg::SetStackingContextScrollStates( + new_scroll_states)) => { + self.handle_request_helper(Msg::SetStackingContextScrollStates(new_scroll_states), + possibly_locked_rw_data) + }, Request::FromPipeline(LayoutControlMsg::TickAnimations) => { self.handle_request_helper(Msg::TickAnimations, possibly_locked_rw_data) }, @@ -644,6 +648,10 @@ impl LayoutThread { Msg::SetVisibleRects(new_visible_rects) => { self.set_visible_rects(new_visible_rects, possibly_locked_rw_data); } + Msg::SetStackingContextScrollStates(new_scroll_states) => { + self.set_stacking_context_scroll_states(new_scroll_states, + possibly_locked_rw_data); + } Msg::ReapStyleAndLayoutData(dead_data) => { unsafe { self.handle_reap_style_and_layout_data(dead_data) @@ -883,19 +891,18 @@ impl LayoutThread { if flow::base(&**layout_root).restyle_damage.contains(REPAINT) || rw_data.display_list.is_none() { - let mut root_stacking_context = - StackingContext::new(StackingContextId::new(0), - StackingContextType::Real, - &Rect::zero(), - &Rect::zero(), - 0, - filter::T::new(Vec::new()), - mix_blend_mode::T::normal, - Matrix4D::identity(), - Matrix4D::identity(), - true, - false, - None); + let mut root_stacking_context = StackingContext::new(StackingContextId::new(0), + StackingContextType::Real, + &Rect::zero(), + &Rect::zero(), + 0, + filter::T::new(Vec::new()), + mix_blend_mode::T::normal, + Matrix4D::identity(), + Matrix4D::identity(), + true, + false, + None); let display_list_entries = sequential::build_display_list_for_subtree(layout_root, @@ -1264,6 +1271,19 @@ impl LayoutThread { true } + fn set_stacking_context_scroll_states<'a, 'b>( + &mut self, + new_scroll_states: Vec, + _: &mut RwData<'a, 'b>) { + for new_scroll_state in &new_scroll_states { + if self.root_flow.is_some() && new_scroll_state.stacking_context_id.id() == 0 { + let _ = self.script_chan.send(ConstellationControlMsg::SetScrollState( + self.id, + new_scroll_state.scroll_offset)); + } + } + } + fn tick_all_animations<'a, 'b>(&mut self, possibly_locked_rw_data: &mut RwData<'a, 'b>) { let mut rw_data = possibly_locked_rw_data.lock(); self.tick_animations(&mut rw_data); diff --git a/components/layout/list_item.rs b/components/layout/list_item.rs index 9b44ed786404..d32c19d5c37d 100644 --- a/components/layout/list_item.rs +++ b/components/layout/list_item.rs @@ -17,7 +17,8 @@ use flow::{Flow, FlowClass, OpaqueFlow}; use fragment::Overflow; use fragment::{CoordinateSystem, Fragment, FragmentBorderBoxIterator, GeneratedContentInfo}; use generated_content; -use gfx::display_list::{StackingContext, StackingContextId}; +use gfx::display_list::StackingContext; +use gfx_traits::StackingContextId; use incremental::RESOLVE_GENERATED_CONTENT; use inline::InlineMetrics; use std::sync::Arc; diff --git a/components/layout/multicol.rs b/components/layout/multicol.rs index a4e532c3b0a3..09f0efd11303 100644 --- a/components/layout/multicol.rs +++ b/components/layout/multicol.rs @@ -15,7 +15,8 @@ use floats::FloatKind; use flow::{Flow, FlowClass, OpaqueFlow, mut_base, FragmentationContext}; use flow_ref::{self, FlowRef}; use fragment::{Fragment, FragmentBorderBoxIterator, Overflow}; -use gfx::display_list::{StackingContext, StackingContextId}; +use gfx::display_list::StackingContext; +use gfx_traits::StackingContextId; use std::cmp::{min, max}; use std::fmt; use std::sync::Arc; diff --git a/components/layout/table.rs b/components/layout/table.rs index 9ed0dfd02d75..5b7f26eb9d90 100644 --- a/components/layout/table.rs +++ b/components/layout/table.rs @@ -16,7 +16,8 @@ use flow; use flow::{BaseFlow, EarlyAbsolutePositionInfo, Flow, FlowClass, ImmutableFlowUtils, OpaqueFlow}; use flow_list::MutFlowListIterator; use fragment::{Fragment, FragmentBorderBoxIterator, Overflow}; -use gfx::display_list::{StackingContext, StackingContextId}; +use gfx::display_list::StackingContext; +use gfx_traits::StackingContextId; use incremental::{REFLOW, REFLOW_OUT_OF_FLOW}; use layout_debug; use model::{IntrinsicISizes, IntrinsicISizesContribution, MaybeAuto}; diff --git a/components/layout/table_caption.rs b/components/layout/table_caption.rs index 2f26e7ea2ae9..1c24491d06d6 100644 --- a/components/layout/table_caption.rs +++ b/components/layout/table_caption.rs @@ -13,7 +13,8 @@ use display_list_builder::DisplayListBuildState; use euclid::Point2D; use flow::{Flow, FlowClass, OpaqueFlow}; use fragment::{Fragment, FragmentBorderBoxIterator, Overflow}; -use gfx::display_list::{StackingContext, StackingContextId}; +use gfx::display_list::StackingContext; +use gfx_traits::StackingContextId; use std::fmt; use std::sync::Arc; use style::logical_geometry::LogicalSize; diff --git a/components/layout/table_cell.rs b/components/layout/table_cell.rs index 06cb1e31eccb..a579ecb6c126 100644 --- a/components/layout/table_cell.rs +++ b/components/layout/table_cell.rs @@ -14,7 +14,8 @@ use display_list_builder::{BlockFlowDisplayListBuilding, BorderPaintingMode, Dis use euclid::{Point2D, Rect, SideOffsets2D, Size2D}; use flow::{self, Flow, FlowClass, OpaqueFlow}; use fragment::{Fragment, FragmentBorderBoxIterator, Overflow}; -use gfx::display_list::{StackingContext, StackingContextId}; +use gfx::display_list::StackingContext; +use gfx_traits::StackingContextId; use incremental::REFLOW; use layout_debug; use model::MaybeAuto; diff --git a/components/layout/table_colgroup.rs b/components/layout/table_colgroup.rs index 86192f75c529..6dce7bd56d17 100644 --- a/components/layout/table_colgroup.rs +++ b/components/layout/table_colgroup.rs @@ -12,7 +12,8 @@ use display_list_builder::DisplayListBuildState; use euclid::Point2D; use flow::{BaseFlow, Flow, FlowClass, ForceNonfloatedFlag, OpaqueFlow}; use fragment::{Fragment, FragmentBorderBoxIterator, Overflow, SpecificFragmentInfo}; -use gfx::display_list::{StackingContext, StackingContextId}; +use gfx::display_list::StackingContext; +use gfx_traits::StackingContextId; use layout_debug; use std::cmp::max; use std::fmt; diff --git a/components/layout/table_row.rs b/components/layout/table_row.rs index ca5b51339849..42257ec5a76a 100644 --- a/components/layout/table_row.rs +++ b/components/layout/table_row.rs @@ -15,7 +15,8 @@ use euclid::Point2D; use flow::{self, EarlyAbsolutePositionInfo, Flow, FlowClass, ImmutableFlowUtils, OpaqueFlow}; use flow_list::MutFlowListIterator; use fragment::{Fragment, FragmentBorderBoxIterator, Overflow}; -use gfx::display_list::{StackingContext, StackingContextId}; +use gfx::display_list::StackingContext; +use gfx_traits::StackingContextId; use layout_debug; use model::MaybeAuto; use rustc_serialize::{Encodable, Encoder}; diff --git a/components/layout/table_rowgroup.rs b/components/layout/table_rowgroup.rs index 202d604a758a..e7e3e2fa9386 100644 --- a/components/layout/table_rowgroup.rs +++ b/components/layout/table_rowgroup.rs @@ -13,7 +13,8 @@ use display_list_builder::DisplayListBuildState; use euclid::Point2D; use flow::{Flow, FlowClass, OpaqueFlow}; use fragment::{Fragment, FragmentBorderBoxIterator, Overflow}; -use gfx::display_list::{StackingContext, StackingContextId}; +use gfx::display_list::StackingContext; +use gfx_traits::StackingContextId; use layout_debug; use rustc_serialize::{Encodable, Encoder}; use std::fmt; diff --git a/components/layout/table_wrapper.rs b/components/layout/table_wrapper.rs index 99bd3d29b64a..9b3b6f5c062e 100644 --- a/components/layout/table_wrapper.rs +++ b/components/layout/table_wrapper.rs @@ -22,7 +22,8 @@ use euclid::Point2D; use floats::FloatKind; use flow::{Flow, FlowClass, ImmutableFlowUtils, INLINE_POSITION_IS_STATIC, OpaqueFlow}; use fragment::{Fragment, FragmentBorderBoxIterator, Overflow}; -use gfx::display_list::{StackingContext, StackingContextId}; +use gfx::display_list::StackingContext; +use gfx_traits::StackingContextId; use model::MaybeAuto; use std::cmp::{max, min}; use std::fmt; diff --git a/components/layout/webrender_helpers.rs b/components/layout/webrender_helpers.rs index 59329147bcb3..d7fd26513e5d 100644 --- a/components/layout/webrender_helpers.rs +++ b/components/layout/webrender_helpers.rs @@ -11,13 +11,13 @@ use app_units::Au; use azure::azure_hl::Color; use euclid::{Point2D, Rect, Size2D}; use gfx::display_list::{BorderRadii, BoxShadowClipMode, ClippingRegion}; -use gfx::display_list::{DisplayItem, DisplayList}; -use gfx::display_list::{DisplayListTraversal, GradientStop, StackingContext, StackingContextType}; -use gfx_traits::ScrollPolicy; +use gfx::display_list::{DisplayItem, DisplayList, DisplayListTraversal}; +use gfx::display_list::{GradientStop, StackingContext, StackingContextType}; +use gfx_traits::{FragmentType, ScrollPolicy, StackingContextId}; use style::computed_values::filter::{self, Filter}; use style::computed_values::{image_rendering, mix_blend_mode}; use style::values::computed::BorderStyle; -use webrender_traits::{self, AuxiliaryListsBuilder, DisplayListId, PipelineId, StackingContextId}; +use webrender_traits::{self, AuxiliaryListsBuilder, DisplayListId, PipelineId}; trait WebRenderStackingContextConverter { fn convert_to_webrender<'a>(&self, @@ -315,8 +315,11 @@ impl WebRenderStackingContextConverter for StackingContext { ScrollPolicy::FixedPosition => webrender_traits::ScrollPolicy::Fixed, }; + let webrender_stacking_context_id = self.id.convert_to_webrender(); + let mut sc = - webrender_traits::StackingContext::new(scroll_layer_id, + webrender_traits::StackingContext::new(webrender_stacking_context_id, + scroll_layer_id, webrender_scroll_policy, self.bounds.to_rectf(), self.overflow.to_rectf(), @@ -514,7 +517,8 @@ impl WebRenderDisplayItemConverter for DisplayItem { } pub struct WebRenderFrameBuilder { - pub stacking_contexts: Vec<(StackingContextId, webrender_traits::StackingContext)>, + pub stacking_contexts: Vec<(webrender_traits::StackingContextId, + webrender_traits::StackingContext)>, pub display_lists: Vec<(DisplayListId, webrender_traits::BuiltDisplayList)>, pub auxiliary_lists_builder: AuxiliaryListsBuilder, pub root_pipeline_id: PipelineId, @@ -536,7 +540,7 @@ impl WebRenderFrameBuilder { api: &mut webrender_traits::RenderApi, pipeline_id: PipelineId, stacking_context: webrender_traits::StackingContext) - -> StackingContextId { + -> webrender_traits::StackingContextId { assert!(pipeline_id == self.root_pipeline_id); let id = api.next_stacking_context_id(); self.stacking_contexts.push((id, stacking_context)); @@ -561,5 +565,32 @@ impl WebRenderFrameBuilder { self.next_scroll_layer_id += 1; webrender_traits::ScrollLayerId::new(self.root_pipeline_id, scroll_layer_id) } +} + +trait WebRenderStackingContextIdConverter { + fn convert_to_webrender(&self) -> webrender_traits::ServoStackingContextId; +} + +impl WebRenderStackingContextIdConverter for StackingContextId { + fn convert_to_webrender(&self) -> webrender_traits::ServoStackingContextId { + webrender_traits::ServoStackingContextId(self.fragment_type().convert_to_webrender(), + self.id()) + } +} +trait WebRenderFragmentTypeConverter { + fn convert_to_webrender(&self) -> webrender_traits::FragmentType; } + +impl WebRenderFragmentTypeConverter for FragmentType { + fn convert_to_webrender(&self) -> webrender_traits::FragmentType { + match *self { + FragmentType::FragmentBody => webrender_traits::FragmentType::FragmentBody, + FragmentType::BeforePseudoContent => { + webrender_traits::FragmentType::BeforePseudoContent + } + FragmentType::AfterPseudoContent => webrender_traits::FragmentType::AfterPseudoContent, + } + } +} + diff --git a/components/profile/time.rs b/components/profile/time.rs index f45e7df8c71d..6271c8745e19 100644 --- a/components/profile/time.rs +++ b/components/profile/time.rs @@ -143,6 +143,7 @@ impl Formattable for ProfilerCategory { ProfilerCategory::ScriptResize => "Script Resize", ProfilerCategory::ScriptEvent => "Script Event", ProfilerCategory::ScriptUpdateReplacedElement => "Script Update Replaced Element", + ProfilerCategory::ScriptSetScrollState => "Script Set Scroll State", ProfilerCategory::ScriptSetViewport => "Script Set Viewport", ProfilerCategory::ScriptTimerEvent => "Script Timer Event", ProfilerCategory::ScriptStylesheetLoad => "Script Stylesheet Load", diff --git a/components/profile_traits/time.rs b/components/profile_traits/time.rs index 5d9a95ddd60f..4083f3f3c14d 100644 --- a/components/profile_traits/time.rs +++ b/components/profile_traits/time.rs @@ -73,6 +73,7 @@ pub enum ProfilerCategory { ScriptParseHTML, ScriptPlannedNavigation, ScriptResize, + ScriptSetScrollState, ScriptSetViewport, ScriptTimerEvent, ScriptStylesheetLoad, diff --git a/components/script/dom/window.rs b/components/script/dom/window.rs index 4862cb83c9e9..3d6695986aee 100644 --- a/components/script/dom/window.rs +++ b/components/script/dom/window.rs @@ -995,13 +995,18 @@ impl Window { }; // TODO (farodin91): Raise an event to stop the current_viewport - let size = self.current_viewport.get().size; - self.current_viewport.set(Rect::new(Point2D::new(Au::from_f32_px(x), Au::from_f32_px(y)), size)); + self.update_viewport_for_scroll(x, y); let message = ConstellationMsg::ScrollFragmentPoint(self.pipeline(), layer_id, point, smooth); self.constellation_chan.send(message).unwrap(); } + pub fn update_viewport_for_scroll(&self, x: f32, y: f32) { + let size = self.current_viewport.get().size; + let new_viewport = Rect::new(Point2D::new(Au::from_f32_px(x), Au::from_f32_px(y)), size); + self.current_viewport.set(new_viewport) + } + pub fn client_window(&self) -> (Size2D, Point2D) { let (send, recv) = ipc::channel::<(Size2D, Point2D)>().unwrap(); self.constellation_chan.send(ConstellationMsg::GetClientWindow(send)).unwrap(); diff --git a/components/script/layout_interface.rs b/components/script/layout_interface.rs index b03273056651..29dff1795252 100644 --- a/components/script/layout_interface.rs +++ b/components/script/layout_interface.rs @@ -15,8 +15,8 @@ use ipc_channel::ipc::{IpcReceiver, IpcSender}; use msg::constellation_msg::{PanicMsg, PipelineId, WindowSizeData}; use net_traits::image_cache_thread::ImageCacheThread; use profile_traits::mem::ReportsChan; -use script_traits::UntrustedNodeAddress; use script_traits::{ConstellationControlMsg, LayoutControlMsg, LayoutMsg as ConstellationMsg}; +use script_traits::{StackingContextScrollState, UntrustedNodeAddress}; use std::sync::Arc; use std::sync::mpsc::{Receiver, Sender}; use string_cache::Atom; @@ -85,6 +85,9 @@ pub enum Msg { /// Set the final Url. SetFinalUrl(Url), + + /// Tells layout about the new scrolling offsets of each scrollable stacking context. + SetStackingContextScrollStates(Vec), } /// Synchronous messages that script can send to layout. diff --git a/components/script/script_runtime.rs b/components/script/script_runtime.rs index 543574ccc625..061b80502b83 100644 --- a/components/script/script_runtime.rs +++ b/components/script/script_runtime.rs @@ -62,6 +62,7 @@ pub enum ScriptThreadEventCategory { NetworkEvent, Resize, ScriptEvent, + SetScrollState, SetViewport, StylesheetLoad, TimerEvent, diff --git a/components/script/script_thread.rs b/components/script/script_thread.rs index 20a8602a2498..b913c5bbae02 100644 --- a/components/script/script_thread.rs +++ b/components/script/script_thread.rs @@ -708,6 +708,11 @@ impl ScriptThread { self.handle_viewport(id, rect); }) } + FromConstellation(ConstellationControlMsg::SetScrollState(id, scroll_offset)) => { + self.profile_event(ScriptThreadEventCategory::SetScrollState, || { + self.handle_set_scroll_state(id, &scroll_offset); + }) + } FromConstellation(ConstellationControlMsg::TickAllAnimations( pipeline_id)) => { if !animation_ticks.contains(&pipeline_id) { @@ -850,6 +855,9 @@ impl ScriptThread { ScriptThreadEventCategory::NetworkEvent => ProfilerCategory::ScriptNetworkEvent, ScriptThreadEventCategory::Resize => ProfilerCategory::ScriptResize, ScriptThreadEventCategory::ScriptEvent => ProfilerCategory::ScriptEvent, + ScriptThreadEventCategory::SetScrollState => { + ProfilerCategory::ScriptSetScrollState + } ScriptThreadEventCategory::UpdateReplacedElement => { ProfilerCategory::ScriptUpdateReplacedElement } @@ -877,6 +885,8 @@ impl ScriptThread { self.handle_resize_inactive_msg(id, new_size), ConstellationControlMsg::Viewport(..) => panic!("should have handled Viewport already"), + ConstellationControlMsg::SetScrollState(..) => + panic!("should have handled SetScrollState already"), ConstellationControlMsg::Resize(..) => panic!("should have handled Resize already"), ConstellationControlMsg::ExitPipeline(..) => @@ -1077,6 +1087,19 @@ impl ScriptThread { panic!("Page rect message sent to nonexistent pipeline"); } + fn handle_set_scroll_state(&self, id: PipelineId, scroll_state: &Point2D) { + let context = self.browsing_context.get(); + if let Some(context) = context { + if let Some(inner_context) = context.find(id) { + let window = inner_context.active_window(); + window.update_viewport_for_scroll(-scroll_state.x, -scroll_state.y); + return + } + } + + panic!("Set scroll state message message sent to nonexistent pipeline: {:?}", id); + } + fn handle_new_layout(&self, new_layout_info: NewLayoutInfo) { let NewLayoutInfo { containing_pipeline_id, diff --git a/components/script_traits/lib.rs b/components/script_traits/lib.rs index 529fc6ad715c..da9c49f88342 100644 --- a/components/script_traits/lib.rs +++ b/components/script_traits/lib.rs @@ -39,6 +39,7 @@ use euclid::point::Point2D; use euclid::rect::Rect; use gfx_traits::Epoch; use gfx_traits::LayerId; +use gfx_traits::StackingContextId; use ipc_channel::ipc::{IpcReceiver, IpcSender}; use libc::c_void; use msg::constellation_msg::{FrameId, FrameType, Key, KeyModifiers, KeyState, LoadData}; @@ -76,6 +77,8 @@ pub enum LayoutControlMsg { TickAnimations, /// Informs layout as to which regions of the page are visible. SetVisibleRects(Vec<(LayerId, Rect)>), + /// Tells layout about the new scrolling offsets of each scrollable stacking context. + SetStackingContextScrollStates(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), @@ -122,6 +125,8 @@ pub enum ConstellationControlMsg { SendEvent(PipelineId, CompositorEvent), /// Notifies script of the viewport. Viewport(PipelineId, Rect), + /// Notifies script of a new scroll offset. + SetScrollState(PipelineId, Point2D), /// Requests that the script thread immediately send the constellation the title of a pipeline. GetTitle(PipelineId), /// Notifies script thread to suspend all its timers @@ -463,6 +468,15 @@ pub enum AnimationTickType { Layout, } +/// The scroll state of a stacking context. +#[derive(Copy, Clone, Debug, Deserialize, Serialize)] +pub struct StackingContextScrollState { + /// The ID of the stacking context. + pub stacking_context_id: StackingContextId, + /// The scrolling offset of this stacking context. + pub scroll_offset: Point2D, +} + /// Messages to the constellation. #[derive(Deserialize, Serialize)] pub enum ConstellationMsg { diff --git a/components/servo/Cargo.lock b/components/servo/Cargo.lock index 53875b3957ca..b2ebec2e9cc6 100644 --- a/components/servo/Cargo.lock +++ b/components/servo/Cargo.lock @@ -2517,7 +2517,7 @@ dependencies = [ [[package]] name = "webrender" version = "0.1.0" -source = "git+https://github.com/servo/webrender#02bfa59b3f15145cfc559684deba8153dc33a5af" +source = "git+https://github.com/servo/webrender#4ee826b19c23e63ecab7f5a8d0a68faa1f05b70c" dependencies = [ "app_units 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2540,7 +2540,7 @@ dependencies = [ [[package]] name = "webrender_traits" version = "0.1.0" -source = "git+https://github.com/servo/webrender_traits#f74a744614b4c0c2fc64d39916386848124f4d52" +source = "git+https://github.com/servo/webrender_traits#e4cbde9880d118e50de425d37bd93d4e7c866e44" dependencies = [ "app_units 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/ports/cef/Cargo.lock b/ports/cef/Cargo.lock index 9029fa2cbfdc..0925f658c70d 100644 --- a/ports/cef/Cargo.lock +++ b/ports/cef/Cargo.lock @@ -2378,7 +2378,7 @@ dependencies = [ [[package]] name = "webrender" version = "0.1.0" -source = "git+https://github.com/servo/webrender#02bfa59b3f15145cfc559684deba8153dc33a5af" +source = "git+https://github.com/servo/webrender#4ee826b19c23e63ecab7f5a8d0a68faa1f05b70c" dependencies = [ "app_units 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2401,7 +2401,7 @@ dependencies = [ [[package]] name = "webrender_traits" version = "0.1.0" -source = "git+https://github.com/servo/webrender_traits#f74a744614b4c0c2fc64d39916386848124f4d52" +source = "git+https://github.com/servo/webrender_traits#e4cbde9880d118e50de425d37bd93d4e7c866e44" dependencies = [ "app_units 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/tests/wpt/mozilla/meta/MANIFEST.json b/tests/wpt/mozilla/meta/MANIFEST.json index 05e8dc4ad7ed..7fabf3c762c1 100644 --- a/tests/wpt/mozilla/meta/MANIFEST.json +++ b/tests/wpt/mozilla/meta/MANIFEST.json @@ -6874,6 +6874,12 @@ "url": "/_mozilla/mozilla/script_type.html" } ], + "mozilla/scrollTo.html": [ + { + "path": "mozilla/scrollTo.html", + "url": "/_mozilla/mozilla/scrollTo.html" + } + ], "mozilla/send-arraybuffer.htm": [ { "path": "mozilla/send-arraybuffer.htm", diff --git a/tests/wpt/mozilla/tests/mozilla/scrollTo.html b/tests/wpt/mozilla/tests/mozilla/scrollTo.html new file mode 100644 index 000000000000..f1b4384e63bf --- /dev/null +++ b/tests/wpt/mozilla/tests/mozilla/scrollTo.html @@ -0,0 +1,21 @@ + + + + + + +