diff --git a/components/gfx/display_list/mod.rs b/components/gfx/display_list/mod.rs index 6c10e56031f5..663db59def2b 100644 --- a/components/gfx/display_list/mod.rs +++ b/components/gfx/display_list/mod.rs @@ -589,14 +589,14 @@ pub struct StackingContext { /// Whether this stacking context creates a new 3d rendering context. pub establishes_3d_context: bool, - /// Whether this stacking context scrolls its overflow area. - pub scrolls_overflow_area: bool, - /// The layer info for this stacking context, if there is any. pub layer_info: Option, /// Children of this StackingContext. pub children: Vec, + + /// If this StackingContext scrolls its overflow area, this will contain the id. + pub overflow_scroll_id: Option, } impl StackingContext { @@ -612,8 +612,8 @@ impl StackingContext { transform: Matrix4D, perspective: Matrix4D, establishes_3d_context: bool, - scrolls_overflow_area: bool, - layer_info: Option) + layer_info: Option, + scroll_id: Option) -> StackingContext { StackingContext { id: id, @@ -626,9 +626,9 @@ impl StackingContext { transform: transform, perspective: perspective, establishes_3d_context: establishes_3d_context, - scrolls_overflow_area: scrolls_overflow_area, layer_info: layer_info, children: Vec::new(), + overflow_scroll_id: scroll_id, } } @@ -648,13 +648,10 @@ impl StackingContext { fn update_overflow_for_all_children(&mut self) { for child in self.children.iter() { if self.context_type == StackingContextType::Real && - child.context_type == StackingContextType::Real && - !self.scrolls_overflow_area { + child.context_type == StackingContextType::Real { // This child might be transformed, so we need to take into account // its transformed overflow rect too, but at the correct position. - let overflow = - child.overflow_rect_in_parent_space(); - + let overflow = child.overflow_rect_in_parent_space(); self.overflow = self.overflow.union(&overflow); } } @@ -740,7 +737,7 @@ impl fmt::Debug for StackingContext { "Pseudo-StackingContext" }; - let scrollable_string = if self.scrolls_overflow_area { + let scrollable_string = if self.overflow_scroll_id.is_some() { " (scrolls overflow area)" } else { "" diff --git a/components/layout/display_list_builder.rs b/components/layout/display_list_builder.rs index 3dcbee9de3c8..2574d3454661 100644 --- a/components/layout/display_list_builder.rs +++ b/components/layout/display_list_builder.rs @@ -298,7 +298,8 @@ pub trait FragmentDisplayListBuilding { id: StackingContextId, base_flow: &BaseFlow, scroll_policy: ScrollPolicy, - mode: StackingContextCreationMode) + mode: StackingContextCreationMode, + scroll_id: Option) -> StackingContext; /// Returns the 4D matrix representing this fragment's transform. @@ -1354,36 +1355,26 @@ impl FragmentDisplayListBuilding for Fragment { id: StackingContextId, base_flow: &BaseFlow, scroll_policy: ScrollPolicy, - mode: StackingContextCreationMode) + mode: StackingContextCreationMode, + scroll_id: Option) -> StackingContext { - let border_box = match mode { - StackingContextCreationMode::InnerScrollWrapper => { - Rect::new(Point2D::zero(), base_flow.overflow.scroll.size) - } - _ => { - self.stacking_relative_border_box(&base_flow.stacking_relative_position, - &base_flow.early_absolute_position_info - .relative_containing_block_size, - base_flow.early_absolute_position_info - .relative_containing_block_mode, - CoordinateSystem::Parent) - } - }; - let overflow = match mode { - StackingContextCreationMode::InnerScrollWrapper => { - Rect::new(Point2D::zero(), base_flow.overflow.scroll.size) - } - StackingContextCreationMode::OuterScrollWrapper => { - Rect::new(Point2D::zero(), border_box.size) - } - _ => { - // First, compute the offset of our border box (including relative positioning) - // from our flow origin, since that is what `BaseFlow::overflow` is relative to. - let border_box_offset = - border_box.translate(&-base_flow.stacking_relative_position).origin; - // Then, using that, compute our overflow region relative to our border box. - base_flow.overflow.paint.translate(&-border_box_offset) - } + let scrolls_overflow_area = mode == StackingContextCreationMode::ScrollWrapper; + let border_box = + self.stacking_relative_border_box(&base_flow.stacking_relative_position, + &base_flow.early_absolute_position_info + .relative_containing_block_size, + base_flow.early_absolute_position_info + .relative_containing_block_mode, + CoordinateSystem::Parent); + let overflow = if scrolls_overflow_area { + Rect::new(Point2D::zero(), base_flow.overflow.scroll.size) + } else { + // First, compute the offset of our border box (including relative positioning) + // from our flow origin, since that is what `BaseFlow::overflow` is relative to. + let border_box_offset = + border_box.translate(&-base_flow.stacking_relative_position).origin; + // Then, using that, compute our overflow region relative to our border box. + base_flow.overflow.paint.translate(&-border_box_offset) }; let transform = self.transform_matrix(&border_box); @@ -1419,20 +1410,12 @@ impl FragmentDisplayListBuilding for Fragment { filters.push(Filter::Opacity(effects.opacity)) } - // There are two situations that need layers: when the fragment has the HAS_LAYER - // flag and when we are building a layer tree for overflow scrolling. - let layer_info = if mode == StackingContextCreationMode::InnerScrollWrapper { - Some(LayerInfo::new(self.layer_id_for_overflow_scroll(), - scroll_policy, - None, - color::transparent())) - } else if self.flags.contains(HAS_LAYER) { + let layer_info = if self.flags.contains(HAS_LAYER) { Some(LayerInfo::new(self.layer_id(), scroll_policy, None, color::transparent())) } else { None }; - let scrolls_overflow_area = mode == StackingContextCreationMode::OuterScrollWrapper; let transform_style = self.style().get_used_transform_style(); let establishes_3d_context = scrolls_overflow_area || transform_style == transform_style::T::flat; @@ -1453,8 +1436,8 @@ impl FragmentDisplayListBuilding for Fragment { transform, perspective, establishes_3d_context, - scrolls_overflow_area, - layer_info) + layer_info, + scroll_id) } fn adjust_clipping_region_for_children(&self, @@ -1736,22 +1719,10 @@ impl BlockFlowDisplayListBuilding for BlockFlow { } let has_scrolling_overflow = self.has_scrolling_overflow(); - let stacking_context_id = if has_scrolling_overflow { - StackingContextId::new_outer(self.fragment.fragment_type()) - } else { - StackingContextId::new_of_type(self.fragment.node.id() as usize, - self.fragment.fragment_type()) - }; + let stacking_context_id = StackingContextId::new_of_type(self.fragment.node.id() as usize, + self.fragment.fragment_type()); self.base.stacking_context_id = stacking_context_id; - let inner_stacking_context_id = if has_scrolling_overflow { - StackingContextId::new_of_type(self.fragment.node.id() as usize, - self.fragment.fragment_type()) - } else { - stacking_context_id - }; - - if block_stacking_context_type == BlockStackingContextType::PseudoStackingContext { let creation_mode = if self.base.flags.contains(IS_ABSOLUTELY_POSITIONED) || self.fragment.style.get_box().position != position::T::static_ { @@ -1764,7 +1735,8 @@ impl BlockFlowDisplayListBuilding for BlockFlow { let mut new_context = self.fragment.create_stacking_context(stacking_context_id, &self.base, ScrollPolicy::Scrollable, - creation_mode); + creation_mode, + None); self.base.collect_stacking_contexts_for_children(&mut new_context); let new_children: Vec = new_context.children.drain(..).collect(); @@ -1788,32 +1760,23 @@ impl BlockFlowDisplayListBuilding for BlockFlow { ScrollPolicy::Scrollable }; - let stacking_context = if self.has_scrolling_overflow() { - let mut inner_stacking_context = self.fragment.create_stacking_context( - inner_stacking_context_id, - &self.base, - scroll_policy, - StackingContextCreationMode::InnerScrollWrapper); - - self.base.collect_stacking_contexts_for_children(&mut inner_stacking_context); - - let mut outer_stacking_context = self.fragment.create_stacking_context( - stacking_context_id, - &self.base, - scroll_policy, - StackingContextCreationMode::OuterScrollWrapper); - outer_stacking_context.add_child(inner_stacking_context); - outer_stacking_context + let (creation_mode, internal_id) = if has_scrolling_overflow { + (StackingContextCreationMode::ScrollWrapper, + Some(StackingContextId::new_of_type(self.fragment.node.id() as usize, + self.fragment.fragment_type()))) + } else { - let mut stacking_context = self.fragment.create_stacking_context( - stacking_context_id, - &self.base, - scroll_policy, - StackingContextCreationMode::Normal); - self.base.collect_stacking_contexts_for_children(&mut stacking_context); - stacking_context + (StackingContextCreationMode::Normal, None) }; + let mut stacking_context = self.fragment.create_stacking_context( + stacking_context_id, + &self.base, + scroll_policy, + creation_mode, + internal_id); + self.base.collect_stacking_contexts_for_children(&mut stacking_context); + parent.add_child(stacking_context); } @@ -1931,7 +1894,8 @@ impl InlineFlowDisplayListBuilding for InlineFlow { fragment.stacking_context_id, &self.base, ScrollPolicy::Scrollable, - StackingContextCreationMode::Normal)); + StackingContextCreationMode::Normal, + None)); } _ => fragment.stacking_context_id = parent.id, } @@ -2135,8 +2099,7 @@ pub enum BorderPaintingMode<'a> { #[derive(Copy, Clone, PartialEq)] pub enum StackingContextCreationMode { Normal, - OuterScrollWrapper, - InnerScrollWrapper, + ScrollWrapper, PseudoPositioned, PseudoFloat, } diff --git a/components/layout/webrender_helpers.rs b/components/layout/webrender_helpers.rs index 85c5dff58582..632d7b6f592a 100644 --- a/components/layout/webrender_helpers.rs +++ b/components/layout/webrender_helpers.rs @@ -9,7 +9,7 @@ use app_units::Au; use azure::azure_hl::Color; -use euclid::{Point2D, Rect, Size2D}; +use euclid::{Matrix4D, Point2D, Rect, Size2D}; use gfx::display_list::{BorderRadii, BoxShadowClipMode, ClippingRegion}; use gfx::display_list::{DisplayItem, DisplayList, DisplayListTraversal}; use gfx::display_list::{GradientStop, StackingContext, StackingContextType}; @@ -266,7 +266,7 @@ impl WebRenderStackingContextConverter for StackingContext { let stacking_context = &stacking_context_item.stacking_context; debug_assert!(stacking_context.context_type == StackingContextType::Real); - let scroll_layer_id_for_children = if self.scrolls_overflow_area { + let scroll_layer_id_for_children = if self.overflow_scroll_id.is_some() { scroll_layer_id } else { None @@ -294,7 +294,7 @@ impl WebRenderStackingContextConverter for StackingContext { api: &mut webrender_traits::RenderApi, pipeline_id: webrender_traits::PipelineId, epoch: webrender_traits::Epoch, - mut scroll_layer_id: Option, + scroll_layer_id: Option, mut scroll_policy: ScrollPolicy, frame_builder: &mut WebRenderFrameBuilder) -> webrender_traits::StackingContextId { @@ -309,12 +309,18 @@ impl WebRenderStackingContextConverter for StackingContext { let webrender_stacking_context_id = self.id.convert_to_webrender(); + let outer_overflow = if self.overflow_scroll_id.is_none() { + self.overflow.to_rectf() + } else { + Rect::new(Point2D::zero(), self.bounds.size).to_rectf() + }; + let mut sc = webrender_traits::StackingContext::new(webrender_stacking_context_id, scroll_layer_id, webrender_scroll_policy, self.bounds.to_rectf(), - self.overflow.to_rectf(), + outer_overflow, self.z_index, &self.transform, &self.perspective, @@ -325,19 +331,49 @@ impl WebRenderStackingContextConverter for StackingContext { let mut builder = webrender_traits::DisplayListBuilder::new(); - if self.scrolls_overflow_area { - scroll_layer_id = Some(frame_builder.next_scroll_layer_id()); + if let Some(inner_stacking_context_id) = self.overflow_scroll_id { + let inner_webrender_stacking_context_id = + inner_stacking_context_id.convert_to_webrender(); + let mut inner_sc = + webrender_traits::StackingContext::new(inner_webrender_stacking_context_id, + Some(frame_builder.next_scroll_layer_id()), + webrender_scroll_policy, + self.overflow.to_rectf(), + self.overflow.to_rectf(), + self.z_index, + &Matrix4D::identity(), + &Matrix4D::identity(), + false, + webrender_traits::MixBlendMode::Normal, + Vec::new(), + &mut frame_builder.auxiliary_lists_builder); + let mut inner_builder = webrender_traits::DisplayListBuilder::new(); + self.convert_children_to_webrender(traversal, + api, + pipeline_id, + epoch, + None, + scroll_policy, + &mut inner_builder, + frame_builder, + false); + + frame_builder.add_display_list(api, inner_builder.finalize(), &mut inner_sc); + let new_id = frame_builder.add_stacking_context(api, pipeline_id, inner_sc); + builder.push_stacking_context(new_id); + } else { + self.convert_children_to_webrender(traversal, + api, + pipeline_id, + epoch, + scroll_layer_id, + scroll_policy, + &mut builder, + frame_builder, + false); } - self.convert_children_to_webrender(traversal, - api, - pipeline_id, - epoch, - scroll_layer_id, - scroll_policy, - &mut builder, - frame_builder, - false); + frame_builder.add_display_list(api, builder.finalize(), &mut sc); frame_builder.add_stacking_context(api, pipeline_id, sc) } diff --git a/components/layout_thread/lib.rs b/components/layout_thread/lib.rs index f7d4bd05fdeb..23da2de84ae7 100644 --- a/components/layout_thread/lib.rs +++ b/components/layout_thread/lib.rs @@ -935,7 +935,7 @@ impl LayoutThread { Matrix4D::identity(), Matrix4D::identity(), true, - false, + None, None); let display_list_entries =