aboutsummaryrefslogtreecommitdiffstats
path: root/components/layout
diff options
context:
space:
mode:
authorMartin Robinson <mrobinson@igalia.com>2017-08-24 09:37:49 +0200
committerMartin Robinson <mrobinson@igalia.com>2017-09-05 09:10:55 +0200
commitbc455c8a1f5f355323c63e5d1639df2fcaaba5df (patch)
tree8cbe1bfbe8145242736759ed39c1cdd8b42eb683 /components/layout
parent4725a05bfba0b588d19af8bc5cfe960bda1ea880 (diff)
downloadservo-bc455c8a1f5f355323c63e5d1639df2fcaaba5df.tar.gz
servo-bc455c8a1f5f355323c63e5d1639df2fcaaba5df.zip
Add support for position:sticky
This leverages the position:sticky support in WebRender to bring basic support for position:sticky in Servo. There are still some issues with nested sticky flows as well as a few other corner cases. Tests are imported from WPT and can be removed once we update to the latest version.
Diffstat (limited to 'components/layout')
-rw-r--r--components/layout/block.rs26
-rw-r--r--components/layout/display_list_builder.rs151
-rw-r--r--components/layout/fragment.rs5
-rw-r--r--components/layout/query.rs3
-rw-r--r--components/layout/sequential.rs2
-rw-r--r--components/layout/table.rs5
-rw-r--r--components/layout/table_caption.rs5
-rw-r--r--components/layout/table_cell.rs5
-rw-r--r--components/layout/table_row.rs5
-rw-r--r--components/layout/table_rowgroup.rs5
-rw-r--r--components/layout/table_wrapper.rs5
-rw-r--r--components/layout/webrender_helpers.rs6
12 files changed, 176 insertions, 47 deletions
diff --git a/components/layout/block.rs b/components/layout/block.rs
index b22519ee71a..b0bb0c9b671 100644
--- a/components/layout/block.rs
+++ b/components/layout/block.rs
@@ -29,9 +29,9 @@
use app_units::{Au, MAX_AU};
use context::LayoutContext;
-use display_list_builder::{BorderPaintingMode, DisplayListBuildState};
-use display_list_builder::BlockFlowDisplayListBuilding;
-use euclid::{Point2D, Size2D, Rect};
+use display_list_builder::{BlockFlowDisplayListBuilding, BorderPaintingMode};
+use display_list_builder::{DisplayListBuildState, EstablishContainingBlock};
+use euclid::{Point2D, Rect, SideOffsets2D, Size2D};
use floats::{ClearType, FloatKind, Floats, PlacementInfo};
use flow::{self, BaseFlow, EarlyAbsolutePositionInfo, Flow, FlowClass, ForceNonfloatedFlag};
use flow::{BLOCK_POSITION_IS_STATIC, CLEARS_LEFT, CLEARS_RIGHT};
@@ -54,7 +54,7 @@ use std::sync::Arc;
use style::computed_values::{border_collapse, box_sizing, display, float, overflow_x};
use style::computed_values::{position, text_align};
use style::context::SharedStyleContext;
-use style::logical_geometry::{LogicalPoint, LogicalRect, LogicalSize, WritingMode};
+use style::logical_geometry::{LogicalMargin, LogicalPoint, LogicalRect, LogicalSize, WritingMode};
use style::properties::ComputedValues;
use style::servo::restyle_damage::{BUBBLE_ISIZES, REFLOW, REFLOW_OUT_OF_FLOW};
use style::values::computed::{LengthOrPercentageOrNone, LengthOrPercentage};
@@ -643,7 +643,7 @@ impl BlockFlow {
&mut self.fragment
}
- pub fn stacking_relative_position(&self, coor: CoordinateSystem) -> Rect<Au> {
+ pub fn stacking_relative_border_box(&self, coor: CoordinateSystem) -> Rect<Au> {
return self.fragment.stacking_relative_border_box(
&self.base.stacking_relative_position,
&self.base.early_absolute_position_info.relative_containing_block_size,
@@ -1787,6 +1787,20 @@ impl BlockFlow {
self.flags.contains(HAS_SCROLLING_OVERFLOW)
}
+ // Return offset from original position because of `position: sticky`.
+ pub fn sticky_position(&self) -> SideOffsets2D<MaybeAuto> {
+ let containing_block_size = &self.base.early_absolute_position_info
+ .relative_containing_block_size;
+ let writing_mode = self.base.early_absolute_position_info.relative_containing_block_mode;
+ let offsets = self.fragment.style().logical_position();
+ let as_margins = LogicalMargin::new(writing_mode,
+ MaybeAuto::from_style(offsets.block_start, containing_block_size.inline),
+ MaybeAuto::from_style(offsets.inline_end, containing_block_size.inline),
+ MaybeAuto::from_style(offsets.block_end, containing_block_size.inline),
+ MaybeAuto::from_style(offsets.inline_start, containing_block_size.inline));
+ as_margins.to_physical(writing_mode)
+ }
+
}
impl Flow for BlockFlow {
@@ -2134,7 +2148,7 @@ impl Flow for BlockFlow {
}
fn collect_stacking_contexts(&mut self, state: &mut DisplayListBuildState) {
- self.collect_stacking_contexts_for_block(state);
+ self.collect_stacking_contexts_for_block(state, EstablishContainingBlock::Yes);
}
fn build_display_list(&mut self, state: &mut DisplayListBuildState) {
diff --git a/components/layout/display_list_builder.rs b/components/layout/display_list_builder.rs
index e7f4474e8f6..6387c72ce3d 100644
--- a/components/layout/display_list_builder.rs
+++ b/components/layout/display_list_builder.rs
@@ -14,7 +14,8 @@ use app_units::{AU_PER_PX, Au};
use block::{BlockFlow, BlockStackingContextType};
use canvas_traits::canvas::{CanvasMsg, FromLayoutMsg};
use context::LayoutContext;
-use euclid::{Transform3D, Point2D, Vector2D, Rect, SideOffsets2D, Size2D, TypedSize2D};
+use euclid::{Point2D, Rect, SideOffsets2D, Size2D, Transform3D, TypedSize2D};
+use euclid::Vector2D;
use flex::FlexFlow;
use flow::{BaseFlow, Flow, IS_ABSOLUTELY_POSITIONED};
use flow_ref::FlowRef;
@@ -72,7 +73,8 @@ use style_traits::ToCss;
use style_traits::cursor::Cursor;
use table_cell::CollapsedBordersForCell;
use webrender_api::{ClipAndScrollInfo, ClipId, ColorF, ComplexClipRegion, GradientStop, LineStyle};
-use webrender_api::{LocalClip, RepeatMode, ScrollPolicy, ScrollSensitivity};
+use webrender_api::{LocalClip, RepeatMode, ScrollPolicy, ScrollSensitivity, StickyFrameInfo};
+use webrender_api::StickySideConstraint;
use webrender_helpers::{ToBorderRadius, ToMixBlendMode, ToRectF, ToTransformStyle};
trait ResolvePercentage {
@@ -101,11 +103,11 @@ fn convert_repeat_mode(from: RepeatKeyword) -> RepeatMode {
}
}
-fn establishes_containing_block_for_absolute(positioning: position::T) -> bool {
- match positioning {
- position::T::absolute | position::T::relative | position::T::fixed => true,
- _ => false,
- }
+fn establishes_containing_block_for_absolute(can_establish_containing_block: EstablishContainingBlock,
+ positioning: position::T)
+ -> bool {
+ can_establish_containing_block == EstablishContainingBlock::Yes &&
+ position::T::static_ != positioning
}
trait RgbColor {
@@ -192,6 +194,9 @@ pub struct DisplayListBuildState<'a> {
/// A stack of clips used to cull display list entries that are outside the
/// rendered region, but only collected at containing block boundaries.
pub containing_block_clip_stack: Vec<Rect<Au>>,
+
+ /// The flow parent's content box, used to calculate sticky constraints.
+ parent_stacking_relative_content_box: Rect<Au>,
}
impl<'a> DisplayListBuildState<'a> {
@@ -211,6 +216,7 @@ impl<'a> DisplayListBuildState<'a> {
iframe_sizes: Vec::new(),
clip_stack: Vec::new(),
containing_block_clip_stack: Vec::new(),
+ parent_stacking_relative_content_box: Rect::zero(),
}
}
@@ -2254,8 +2260,16 @@ impl FragmentDisplayListBuilding for Fragment {
}
}
+#[derive(Clone, Copy, PartialEq)]
+pub enum EstablishContainingBlock {
+ Yes,
+ No,
+}
+
pub trait BlockFlowDisplayListBuilding {
- fn collect_stacking_contexts_for_block(&mut self, state: &mut DisplayListBuildState);
+ fn collect_stacking_contexts_for_block(&mut self,
+ state: &mut DisplayListBuildState,
+ can_establish_containing_block: EstablishContainingBlock);
fn transform_clip_to_coordinate_space(&mut self,
state: &mut DisplayListBuildState,
@@ -2263,8 +2277,12 @@ pub trait BlockFlowDisplayListBuilding {
fn setup_clipping_for_block(&mut self,
state: &mut DisplayListBuildState,
preserved_state: &mut PreservedDisplayListState,
- stacking_context_type: BlockStackingContextType)
+ stacking_context_type: BlockStackingContextType,
+ can_establish_containing_block: EstablishContainingBlock)
-> ClipAndScrollInfo;
+ fn setup_scroll_root_for_position(&mut self,
+ state: &mut DisplayListBuildState,
+ border_box: &Rect<Au>);
fn setup_scroll_root_for_overflow(&mut self,
state: &mut DisplayListBuildState,
border_box: &Rect<Au>);
@@ -2297,6 +2315,7 @@ pub struct PreservedDisplayListState {
containing_block_clip_and_scroll_info: ClipAndScrollInfo,
clips_pushed: usize,
containing_block_clips_pushed: usize,
+ stacking_relative_content_box: Rect<Au>,
}
impl PreservedDisplayListState {
@@ -2308,6 +2327,7 @@ impl PreservedDisplayListState {
containing_block_clip_and_scroll_info: state.containing_block_clip_and_scroll_info,
clips_pushed: 0,
containing_block_clips_pushed: 0,
+ stacking_relative_content_box: state.parent_stacking_relative_content_box,
}
}
@@ -2322,6 +2342,7 @@ impl PreservedDisplayListState {
state.current_real_stacking_context_id = self.real_stacking_context_id;
state.current_clip_and_scroll_info = self.clip_and_scroll_info;
state.containing_block_clip_and_scroll_info = self.containing_block_clip_and_scroll_info;
+ state.parent_stacking_relative_content_box = self.stacking_relative_content_box;
let truncate_length = state.clip_stack.len() - self.clips_pushed;
state.clip_stack.truncate(truncate_length);
@@ -2359,7 +2380,7 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
if state.clip_stack.is_empty() {
return;
}
- let border_box = self.stacking_relative_position(CoordinateSystem::Parent);
+ let border_box = self.stacking_relative_border_box(CoordinateSystem::Parent);
let transform = match self.fragment.transform_matrix(&border_box) {
Some(transform) => transform,
None => return,
@@ -2412,7 +2433,9 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
}
}
- fn collect_stacking_contexts_for_block(&mut self, state: &mut DisplayListBuildState) {
+ fn collect_stacking_contexts_for_block(&mut self,
+ state: &mut DisplayListBuildState,
+ can_establish_containing_block: EstablishContainingBlock) {
let mut preserved_state = PreservedDisplayListState::new(state);
let block_stacking_context_type = self.block_stacking_context_type();
@@ -2432,8 +2455,13 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
// stored in state.current_clip_and_scroll_info. If we create a stacking context,
// we don't want it to be contained by its own scroll root.
let containing_clip_and_scroll_info =
- self.setup_clipping_for_block(state, &mut preserved_state, block_stacking_context_type);
- if establishes_containing_block_for_absolute(self.positioning()) {
+ self.setup_clipping_for_block(state,
+ &mut preserved_state,
+ block_stacking_context_type,
+ can_establish_containing_block);
+
+ if establishes_containing_block_for_absolute(can_establish_containing_block,
+ self.positioning()) {
state.containing_block_clip_and_scroll_info = state.current_clip_and_scroll_info;
}
@@ -2459,7 +2487,8 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
fn setup_clipping_for_block(&mut self,
state: &mut DisplayListBuildState,
preserved_state: &mut PreservedDisplayListState,
- stacking_context_type: BlockStackingContextType)
+ stacking_context_type: BlockStackingContextType,
+ can_establish_containing_block: EstablishContainingBlock)
-> ClipAndScrollInfo {
// If this block is absolutely positioned, we should be clipped and positioned by
// the scroll root of our nearest ancestor that establishes a containing block.
@@ -2477,26 +2506,33 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
};
self.base.clip_and_scroll_info = Some(containing_clip_and_scroll_info);
- let coordinate_system = if self.fragment.establishes_stacking_context() {
- CoordinateSystem::Own
+ let stacking_relative_border_box = if self.fragment.establishes_stacking_context() {
+ self.stacking_relative_border_box(CoordinateSystem::Own)
} else {
- CoordinateSystem::Parent
+ self.stacking_relative_border_box(CoordinateSystem::Parent)
};
- let stacking_relative_border_box = self.fragment.stacking_relative_border_box(
- &self.base.stacking_relative_position,
- &self.base.early_absolute_position_info.relative_containing_block_size,
- self.base.early_absolute_position_info.relative_containing_block_mode,
- coordinate_system);
-
if stacking_context_type == BlockStackingContextType::StackingContext {
self.transform_clip_to_coordinate_space(state, preserved_state);
}
+ self.setup_scroll_root_for_position(state, &stacking_relative_border_box);
self.setup_scroll_root_for_overflow(state, &stacking_relative_border_box);
self.setup_scroll_root_for_css_clip(state, preserved_state, &stacking_relative_border_box);
self.base.clip = state.clip_stack.last().cloned().unwrap_or_else(max_rect);
+ // We keep track of our position so that any stickily positioned elements can
+ // properly determine the extent of their movement relative to scrolling containers.
+ if can_establish_containing_block == EstablishContainingBlock::Yes {
+ let border_box = if self.fragment.establishes_stacking_context() {
+ stacking_relative_border_box
+ } else {
+ self.stacking_relative_border_box(CoordinateSystem::Own)
+ };
+ state.parent_stacking_relative_content_box =
+ self.fragment.stacking_relative_content_box(&border_box)
+ }
+
match self.positioning() {
position::T::absolute | position::T::relative | position::T::fixed =>
state.containing_block_clip_and_scroll_info = state.current_clip_and_scroll_info,
@@ -2506,6 +2542,72 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
containing_clip_and_scroll_info
}
+ fn setup_scroll_root_for_position(&mut self,
+ state: &mut DisplayListBuildState,
+ border_box: &Rect<Au>) {
+ if self.positioning() != position::T::sticky {
+ return;
+ }
+
+ let sticky_position = self.sticky_position();
+ if sticky_position.left == MaybeAuto::Auto && sticky_position.right == MaybeAuto::Auto &&
+ sticky_position.top == MaybeAuto::Auto && sticky_position.bottom == MaybeAuto::Auto {
+ return;
+ }
+
+ // Since position: sticky elements always establish a stacking context, we will
+ // have previously calculated our border box in our own coordinate system. In
+ // order to properly calculate max offsets we need to compare our size and
+ // position in our parent's coordinate system.
+ let border_box_in_parent = self.stacking_relative_border_box(CoordinateSystem::Parent);
+ let margins = self.fragment.margin.to_physical(
+ self.base.early_absolute_position_info.relative_containing_block_mode);
+
+ // Position:sticky elements are always restricted based on the size and position of
+ // their containing block, which for sticky items is like relative and statically
+ // positioned items: just the parent block.
+ let constraint_rect = state.parent_stacking_relative_content_box;
+
+ let to_max_offset = |constraint_edge: Au, moving_edge: Au| -> f32 {
+ (constraint_edge - moving_edge).to_f32_px()
+ };
+
+ let to_sticky_info = |margin: MaybeAuto, max_offset: f32| -> Option<StickySideConstraint> {
+ match margin {
+ MaybeAuto::Auto => None,
+ MaybeAuto::Specified(value) =>
+ Some(StickySideConstraint { margin: value.to_f32_px(), max_offset }),
+ }
+ };
+
+ let sticky_frame_info = StickyFrameInfo::new(
+ to_sticky_info(sticky_position.top,
+ to_max_offset(constraint_rect.max_y(), border_box_in_parent.max_y())),
+ to_sticky_info(sticky_position.right,
+ to_max_offset(constraint_rect.min_x(), border_box_in_parent.min_x() - margins.left)),
+ to_sticky_info(sticky_position.bottom,
+ to_max_offset(constraint_rect.min_y(), border_box_in_parent.min_y() - margins.top)),
+ to_sticky_info(sticky_position.left,
+ to_max_offset(constraint_rect.max_x(), border_box_in_parent.max_x())));
+
+ let new_scroll_root_id = ClipId::new(self.fragment.unique_id(IdType::OverflowClip),
+ state.layout_context.id.to_webrender());
+ let parent_id = self.clip_and_scroll_info(state.layout_context.id).scroll_node_id;
+ state.add_scroll_root(
+ ScrollRoot {
+ id: new_scroll_root_id,
+ parent_id: parent_id,
+ clip: ClippingRegion::from_rect(border_box),
+ content_rect: Rect::zero(),
+ root_type: ScrollRootType::StickyFrame(sticky_frame_info),
+ },
+ );
+
+ let new_clip_and_scroll_info = ClipAndScrollInfo::simple(new_scroll_root_id);
+ self.base.clip_and_scroll_info = Some(new_clip_and_scroll_info);
+ state.current_clip_and_scroll_info = new_clip_and_scroll_info;
+ }
+
fn setup_scroll_root_for_overflow(&mut self,
state: &mut DisplayListBuildState,
border_box: &Rect<Au>) {
@@ -2737,7 +2839,8 @@ impl InlineFlowDisplayListBuilding for InlineFlow {
for fragment in self.fragments.fragments.iter_mut() {
let previous_cb_clip_scroll_info = state.containing_block_clip_and_scroll_info;
- if establishes_containing_block_for_absolute(fragment.style.get_box().position) {
+ if establishes_containing_block_for_absolute(EstablishContainingBlock::Yes,
+ fragment.style.get_box().position) {
state.containing_block_clip_and_scroll_info = state.current_clip_and_scroll_info;
}
diff --git a/components/layout/fragment.rs b/components/layout/fragment.rs
index 4e0763612ad..8cd37f314ed 100644
--- a/components/layout/fragment.rs
+++ b/components/layout/fragment.rs
@@ -2521,8 +2521,9 @@ impl Fragment {
return true
}
- // Fixed position blocks always create stacking contexts.
- if self.style.get_box().position == position::T::fixed {
+ // Fixed position and sticky position always create stacking contexts.
+ if self.style().get_box().position == position::T::fixed ||
+ self.style().get_box().position == position::T::sticky {
return true
}
diff --git a/components/layout/query.rs b/components/layout/query.rs
index 5803a247e19..f3040376f60 100644
--- a/components/layout/query.rs
+++ b/components/layout/query.rs
@@ -598,6 +598,7 @@ impl FragmentBorderBoxIterator for ParentOffsetBorderBoxIterator {
(true, _, _) |
(false, computed_values::position::T::static_, &SpecificFragmentInfo::Table) |
(false, computed_values::position::T::static_, &SpecificFragmentInfo::TableCell) |
+ (false, computed_values::position::T::sticky, _) |
(false, computed_values::position::T::absolute, _) |
(false, computed_values::position::T::relative, _) |
(false, computed_values::position::T::fixed, _) => true,
@@ -766,7 +767,7 @@ where
let positioned = match style.get_box().position {
position::computed_value::T::relative |
- /*position::computed_value::T::sticky |*/
+ position::computed_value::T::sticky |
position::computed_value::T::fixed |
position::computed_value::T::absolute => true,
_ => false
diff --git a/components/layout/sequential.rs b/components/layout/sequential.rs
index 3c95b75fbb6..1121ace2d89 100644
--- a/components/layout/sequential.rs
+++ b/components/layout/sequential.rs
@@ -95,7 +95,7 @@ pub fn iterate_through_flow_tree_fragment_border_boxes(root: &mut Flow, iterator
flow::base(kid).stacking_relative_position +
stacking_context_position.to_vector();
let relative_position = kid.as_block()
- .stacking_relative_position(CoordinateSystem::Own);
+ .stacking_relative_border_box(CoordinateSystem::Own);
if let Some(matrix) = kid.as_block()
.fragment
.transform_matrix(&relative_position) {
diff --git a/components/layout/table.rs b/components/layout/table.rs
index b56ac7c4d09..974a497bb94 100644
--- a/components/layout/table.rs
+++ b/components/layout/table.rs
@@ -10,7 +10,8 @@ use app_units::Au;
use block::{BlockFlow, CandidateBSizeIterator, ISizeAndMarginsComputer};
use block::{ISizeConstraintInput, ISizeConstraintSolution};
use context::LayoutContext;
-use display_list_builder::{BlockFlowDisplayListBuilding, BorderPaintingMode, DisplayListBuildState};
+use display_list_builder::{BlockFlowDisplayListBuilding, BorderPaintingMode};
+use display_list_builder::{DisplayListBuildState, EstablishContainingBlock};
use euclid::Point2D;
use flow;
use flow::{BaseFlow, EarlyAbsolutePositionInfo, Flow, FlowClass, ImmutableFlowUtils, OpaqueFlow};
@@ -503,7 +504,7 @@ impl Flow for TableFlow {
}
fn collect_stacking_contexts(&mut self, state: &mut DisplayListBuildState) {
- self.block_flow.collect_stacking_contexts(state);
+ self.block_flow.collect_stacking_contexts_for_block(state, EstablishContainingBlock::Yes);
}
fn repair_style(&mut self, new_style: &::ServoArc<ComputedValues>) {
diff --git a/components/layout/table_caption.rs b/components/layout/table_caption.rs
index 8e5fa302028..39e20d95bbf 100644
--- a/components/layout/table_caption.rs
+++ b/components/layout/table_caption.rs
@@ -9,7 +9,8 @@
use app_units::Au;
use block::BlockFlow;
use context::LayoutContext;
-use display_list_builder::DisplayListBuildState;
+use display_list_builder::{BlockFlowDisplayListBuilding, DisplayListBuildState};
+use display_list_builder::EstablishContainingBlock;
use euclid::Point2D;
use flow::{Flow, FlowClass, OpaqueFlow};
use fragment::{Fragment, FragmentBorderBoxIterator, Overflow};
@@ -80,7 +81,7 @@ impl Flow for TableCaptionFlow {
}
fn collect_stacking_contexts(&mut self, state: &mut DisplayListBuildState) {
- self.block_flow.collect_stacking_contexts(state);
+ self.block_flow.collect_stacking_contexts_for_block(state, EstablishContainingBlock::No);
}
fn repair_style(&mut self, new_style: &::ServoArc<ComputedValues>) {
diff --git a/components/layout/table_cell.rs b/components/layout/table_cell.rs
index 370937bc73d..389232345f6 100644
--- a/components/layout/table_cell.rs
+++ b/components/layout/table_cell.rs
@@ -9,7 +9,8 @@
use app_units::Au;
use block::{BlockFlow, ISizeAndMarginsComputer, MarginsMayCollapseFlag};
use context::LayoutContext;
-use display_list_builder::{BlockFlowDisplayListBuilding, BorderPaintingMode, DisplayListBuildState};
+use display_list_builder::{BlockFlowDisplayListBuilding, BorderPaintingMode};
+use display_list_builder::{DisplayListBuildState, EstablishContainingBlock};
use euclid::{Point2D, Rect, SideOffsets2D, Size2D};
use flow::{self, Flow, FlowClass, IS_ABSOLUTELY_POSITIONED, OpaqueFlow};
use fragment::{Fragment, FragmentBorderBoxIterator, Overflow};
@@ -260,7 +261,7 @@ impl Flow for TableCellFlow {
}
fn collect_stacking_contexts(&mut self, state: &mut DisplayListBuildState) {
- self.block_flow.collect_stacking_contexts(state);
+ self.block_flow.collect_stacking_contexts_for_block(state, EstablishContainingBlock::No);
}
fn repair_style(&mut self, new_style: &::ServoArc<ComputedValues>) {
diff --git a/components/layout/table_row.rs b/components/layout/table_row.rs
index 3e6365d8c77..070e7da9229 100644
--- a/components/layout/table_row.rs
+++ b/components/layout/table_row.rs
@@ -9,7 +9,8 @@
use app_units::Au;
use block::{BlockFlow, ISizeAndMarginsComputer};
use context::LayoutContext;
-use display_list_builder::{BlockFlowDisplayListBuilding, BorderPaintingMode, DisplayListBuildState};
+use display_list_builder::{BlockFlowDisplayListBuilding, BorderPaintingMode};
+use display_list_builder::{DisplayListBuildState, EstablishContainingBlock};
use euclid::Point2D;
use flow::{self, EarlyAbsolutePositionInfo, Flow, FlowClass, ImmutableFlowUtils, OpaqueFlow};
use flow_list::MutFlowListIterator;
@@ -478,7 +479,7 @@ impl Flow for TableRowFlow {
}
fn collect_stacking_contexts(&mut self, state: &mut DisplayListBuildState) {
- self.block_flow.collect_stacking_contexts(state);
+ self.block_flow.collect_stacking_contexts_for_block(state, EstablishContainingBlock::No);
}
fn repair_style(&mut self, new_style: &::ServoArc<ComputedValues>) {
diff --git a/components/layout/table_rowgroup.rs b/components/layout/table_rowgroup.rs
index 760a20a72fc..c3cb764686b 100644
--- a/components/layout/table_rowgroup.rs
+++ b/components/layout/table_rowgroup.rs
@@ -9,7 +9,8 @@
use app_units::Au;
use block::{BlockFlow, ISizeAndMarginsComputer};
use context::LayoutContext;
-use display_list_builder::DisplayListBuildState;
+use display_list_builder::{BlockFlowDisplayListBuilding, DisplayListBuildState};
+use display_list_builder::EstablishContainingBlock;
use euclid::Point2D;
use flow::{Flow, FlowClass, OpaqueFlow};
use fragment::{Fragment, FragmentBorderBoxIterator, Overflow};
@@ -183,7 +184,7 @@ impl Flow for TableRowGroupFlow {
}
fn collect_stacking_contexts(&mut self, state: &mut DisplayListBuildState) {
- self.block_flow.collect_stacking_contexts(state);
+ self.block_flow.collect_stacking_contexts_for_block(state, EstablishContainingBlock::No);
}
fn repair_style(&mut self, new_style: &::ServoArc<ComputedValues>) {
diff --git a/components/layout/table_wrapper.rs b/components/layout/table_wrapper.rs
index 531176d52d3..5619a487ea7 100644
--- a/components/layout/table_wrapper.rs
+++ b/components/layout/table_wrapper.rs
@@ -17,7 +17,8 @@ use app_units::Au;
use block::{AbsoluteNonReplaced, BlockFlow, FloatNonReplaced, ISizeAndMarginsComputer, ISizeConstraintInput};
use block::{ISizeConstraintSolution, MarginsMayCollapseFlag};
use context::LayoutContext;
-use display_list_builder::DisplayListBuildState;
+use display_list_builder::{BlockFlowDisplayListBuilding, DisplayListBuildState};
+use display_list_builder::EstablishContainingBlock;
use euclid::Point2D;
use floats::FloatKind;
use flow::{Flow, FlowClass, ImmutableFlowUtils, INLINE_POSITION_IS_STATIC, OpaqueFlow};
@@ -463,7 +464,7 @@ impl Flow for TableWrapperFlow {
}
fn collect_stacking_contexts(&mut self, state: &mut DisplayListBuildState) {
- self.block_flow.collect_stacking_contexts(state);
+ self.block_flow.collect_stacking_contexts_for_block(state, EstablishContainingBlock::No);
}
fn repair_style(&mut self, new_style: &::ServoArc<ComputedValues>) {
diff --git a/components/layout/webrender_helpers.rs b/components/layout/webrender_helpers.rs
index 6e5a774e283..6370043542f 100644
--- a/components/layout/webrender_helpers.rs
+++ b/components/layout/webrender_helpers.rs
@@ -493,10 +493,11 @@ impl WebRenderDisplayItemConverter for DisplayItem {
builder.push_clip_id(item.scroll_root.parent_id);
let our_id = item.scroll_root.id;
+ let item_rect = item.scroll_root.clip.main.to_rectf();
let webrender_id = match item.scroll_root.root_type {
ScrollRootType::Clip => {
builder.define_clip(Some(our_id),
- item.scroll_root.clip.main.to_rectf(),
+ item_rect,
item.scroll_root.clip.get_complex_clips(),
None)
}
@@ -508,6 +509,9 @@ impl WebRenderDisplayItemConverter for DisplayItem {
None,
scroll_sensitivity)
}
+ ScrollRootType::StickyFrame(sticky_frame_info) => {
+ builder.define_sticky_frame(Some(our_id), item_rect, sticky_frame_info)
+ }
};
debug_assert!(our_id == webrender_id);