mirror of
https://github.com/servo/servo.git
synced 2025-07-24 15:50:21 +01:00
Auto merge of #20767 - mrobinson:use-reference-frame-for-fixed-position, r=gw3583
Use reference frames explicitly for fixed positioning <!-- Please describe your changes on the following line: --> --- <!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `__` with appropriate data: --> - [x] `./mach build -d` does not report any errors - [x] `./mach test-tidy` does not report any errors - [ ] These changes fix #__ (github issue number if applicable). <!-- Either: --> - [x] There are tests for these changes because they should not change behavior. - [ ] These changes do not require tests because _____ <!-- Also, please make sure that "Allow edits from maintainers" checkbox is checked, so that we can help you if you get stuck somewhere along the way.--> <!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. --> <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/20767) <!-- Reviewable:end -->
This commit is contained in:
commit
a07c718895
4 changed files with 160 additions and 50 deletions
|
@ -192,12 +192,16 @@ pub struct StackingContextCollectionState {
|
|||
/// recursively building and processing the display list.
|
||||
pub current_stacking_context_id: StackingContextId,
|
||||
|
||||
/// The current stacking real context id, which doesn't include pseudo-stacking contexts.
|
||||
/// The current reference frame ClipScrollNodeIndex.
|
||||
pub current_real_stacking_context_id: StackingContextId,
|
||||
|
||||
/// The next stacking context id that we will assign to a stacking context.
|
||||
pub next_stacking_context_id: StackingContextId,
|
||||
|
||||
/// The current reference frame id. This is used to assign items to the parent
|
||||
/// reference frame when we encounter a fixed position stacking context.
|
||||
pub current_parent_reference_frame_id: ClipScrollNodeIndex,
|
||||
|
||||
/// The current clip and scroll info, used to keep track of state when
|
||||
/// recursively building and processing the display list.
|
||||
pub current_clipping_and_scrolling: ClippingAndScrolling,
|
||||
|
@ -221,19 +225,8 @@ pub struct StackingContextCollectionState {
|
|||
|
||||
impl StackingContextCollectionState {
|
||||
pub fn new(pipeline_id: PipelineId) -> StackingContextCollectionState {
|
||||
let root_clip_indices = ClippingAndScrolling::simple(ClipScrollNodeIndex(0));
|
||||
|
||||
// This is just a dummy node to take up a slot in the array. WebRender
|
||||
// takes care of adding this root node and it can be ignored during DL conversion.
|
||||
let root_node = ClipScrollNode {
|
||||
parent_index: ClipScrollNodeIndex(0),
|
||||
clip: ClippingRegion::from_rect(LayoutRect::zero()),
|
||||
content_rect: LayoutRect::zero(),
|
||||
node_type: ClipScrollNodeType::ScrollFrame(
|
||||
ScrollSensitivity::ScriptAndInputEvents,
|
||||
pipeline_id.root_scroll_id(),
|
||||
),
|
||||
};
|
||||
let root_clip_indices =
|
||||
ClippingAndScrolling::simple(ClipScrollNodeIndex::root_scroll_node());
|
||||
|
||||
let mut stacking_context_info = FnvHashMap::default();
|
||||
stacking_context_info.insert(
|
||||
|
@ -241,14 +234,22 @@ impl StackingContextCollectionState {
|
|||
StackingContextInfo::new(StackingContextId::root()),
|
||||
);
|
||||
|
||||
// We add two empty nodes to represent the WebRender root reference frame and
|
||||
// root scroll nodes. WebRender adds these automatically and we add them here
|
||||
// so that the ids in the array match up with the ones we assign during display
|
||||
// list building. We ignore these two nodes during conversion to WebRender
|
||||
// display lists.
|
||||
let clip_scroll_nodes = vec![ClipScrollNode::placeholder(), ClipScrollNode::placeholder()];
|
||||
|
||||
StackingContextCollectionState {
|
||||
pipeline_id: pipeline_id,
|
||||
root_stacking_context: StackingContext::root(),
|
||||
stacking_context_info,
|
||||
clip_scroll_nodes: vec![root_node],
|
||||
clip_scroll_nodes,
|
||||
current_stacking_context_id: StackingContextId::root(),
|
||||
current_real_stacking_context_id: StackingContextId::root(),
|
||||
next_stacking_context_id: StackingContextId::root().next(),
|
||||
current_parent_reference_frame_id: ClipScrollNodeIndex::root_reference_frame(),
|
||||
current_clipping_and_scrolling: root_clip_indices,
|
||||
containing_block_clipping_and_scrolling: root_clip_indices,
|
||||
clip_stack: Vec::new(),
|
||||
|
@ -291,17 +292,27 @@ impl StackingContextCollectionState {
|
|||
}
|
||||
|
||||
fn add_clip_scroll_node(&mut self, clip_scroll_node: ClipScrollNode) -> ClipScrollNodeIndex {
|
||||
// We want the scroll root to be defined before any possible item that could use it,
|
||||
// so we make sure that it is added to the beginning of the parent "real" (non-pseudo)
|
||||
// stacking context. This ensures that item reordering will not result in an item using
|
||||
// the scroll root before it is defined.
|
||||
let is_placeholder = clip_scroll_node.is_placeholder();
|
||||
|
||||
self.clip_scroll_nodes.push(clip_scroll_node);
|
||||
let index = ClipScrollNodeIndex(self.clip_scroll_nodes.len() - 1);
|
||||
self.stacking_context_info
|
||||
.get_mut(&self.current_real_stacking_context_id)
|
||||
.unwrap()
|
||||
.clip_scroll_nodes
|
||||
.push(index);
|
||||
let index = ClipScrollNodeIndex::new(self.clip_scroll_nodes.len() - 1);
|
||||
|
||||
// If this node is a placeholder node (currently just reference frames), then don't add
|
||||
// it to the stacking context list. Placeholder nodes are created automatically by
|
||||
// WebRender and we don't want to explicitly create them in the display list. The node
|
||||
// is just there to take up a spot in the global list of ClipScrollNodes.
|
||||
if !is_placeholder {
|
||||
// We want the scroll root to be defined before any possible item that could use it,
|
||||
// so we make sure that it is added to the beginning of the parent "real" (non-pseudo)
|
||||
// stacking context. This ensures that item reordering will not result in an item using
|
||||
// the scroll root before it is defined.
|
||||
self.stacking_context_info
|
||||
.get_mut(&self.current_real_stacking_context_id)
|
||||
.unwrap()
|
||||
.clip_scroll_nodes
|
||||
.push(index);
|
||||
}
|
||||
|
||||
index
|
||||
}
|
||||
}
|
||||
|
@ -347,7 +358,6 @@ impl<'a> DisplayListBuildState<'a> {
|
|||
layout_context: &'a LayoutContext,
|
||||
state: StackingContextCollectionState,
|
||||
) -> DisplayListBuildState<'a> {
|
||||
let root_clip_indices = ClippingAndScrolling::simple(ClipScrollNodeIndex(0));
|
||||
DisplayListBuildState {
|
||||
layout_context: layout_context,
|
||||
root_stacking_context: state.root_stacking_context,
|
||||
|
@ -356,7 +366,8 @@ impl<'a> DisplayListBuildState<'a> {
|
|||
clip_scroll_nodes: state.clip_scroll_nodes,
|
||||
processing_scrolling_overflow_element: false,
|
||||
current_stacking_context_id: StackingContextId::root(),
|
||||
current_clipping_and_scrolling: root_clip_indices,
|
||||
current_clipping_and_scrolling:
|
||||
ClippingAndScrolling::simple(ClipScrollNodeIndex::root_scroll_node()),
|
||||
iframe_sizes: Vec::new(),
|
||||
indexable_text: IndexableText::default(),
|
||||
}
|
||||
|
@ -374,7 +385,7 @@ impl<'a> DisplayListBuildState<'a> {
|
|||
return index;
|
||||
}
|
||||
|
||||
self.clip_scroll_nodes[index.0].parent_index
|
||||
self.clip_scroll_nodes[index.to_index()].parent_index
|
||||
}
|
||||
|
||||
fn is_background_or_border_of_clip_scroll_node(&self, section: DisplayListSection) -> bool {
|
||||
|
@ -429,7 +440,7 @@ impl<'a> DisplayListBuildState<'a> {
|
|||
// stacking context. This ensures that item reordering will not result in an item using
|
||||
// the scroll root before it is defined.
|
||||
self.clip_scroll_nodes.push(node);
|
||||
let index = ClipScrollNodeIndex(self.clip_scroll_nodes.len() - 1);
|
||||
let index = ClipScrollNodeIndex::new(self.clip_scroll_nodes.len() - 1);
|
||||
let real_stacking_context_id =
|
||||
self.stacking_context_info[&self.current_stacking_context_id].real_stacking_context_id;
|
||||
self.stacking_context_info
|
||||
|
@ -751,6 +762,7 @@ pub trait FragmentDisplayListBuilding {
|
|||
base_flow: &BaseFlow,
|
||||
scroll_policy: ScrollPolicy,
|
||||
context_type: StackingContextType,
|
||||
established_reference_frame: Option<ClipScrollNodeIndex>,
|
||||
parent_clipping_and_scrolling: ClippingAndScrolling,
|
||||
) -> StackingContext;
|
||||
|
||||
|
@ -1873,6 +1885,7 @@ impl FragmentDisplayListBuilding for Fragment {
|
|||
base_flow: &BaseFlow,
|
||||
scroll_policy: ScrollPolicy,
|
||||
context_type: StackingContextType,
|
||||
established_reference_frame: Option<ClipScrollNodeIndex>,
|
||||
parent_clipping_and_scrolling: ClippingAndScrolling,
|
||||
) -> StackingContext {
|
||||
let border_box = self.stacking_relative_border_box(
|
||||
|
@ -1916,6 +1929,7 @@ impl FragmentDisplayListBuilding for Fragment {
|
|||
self.perspective_matrix(&border_box),
|
||||
scroll_policy,
|
||||
parent_clipping_and_scrolling,
|
||||
established_reference_frame,
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -2135,6 +2149,7 @@ pub trait BlockFlowDisplayListBuilding {
|
|||
state: &mut StackingContextCollectionState,
|
||||
preserved_state: &mut SavedStackingContextCollectionState,
|
||||
stacking_context_type: Option<StackingContextType>,
|
||||
established_reference_frame: Option<ClipScrollNodeIndex>,
|
||||
flags: StackingContextCollectionFlags,
|
||||
) -> ClippingAndScrolling;
|
||||
fn setup_clip_scroll_node_for_position(
|
||||
|
@ -2164,6 +2179,7 @@ pub trait BlockFlowDisplayListBuilding {
|
|||
&mut self,
|
||||
parent_stacking_context_id: StackingContextId,
|
||||
parent_clipping_and_scrolling: ClippingAndScrolling,
|
||||
established_reference_frame: Option<ClipScrollNodeIndex>,
|
||||
state: &mut StackingContextCollectionState,
|
||||
);
|
||||
fn build_display_list_for_block(
|
||||
|
@ -2187,6 +2203,8 @@ pub trait BlockFlowDisplayListBuilding {
|
|||
&self,
|
||||
flags: StackingContextCollectionFlags,
|
||||
) -> Option<StackingContextType>;
|
||||
|
||||
fn is_reference_frame(&self, context_type: Option<StackingContextType>) -> bool;
|
||||
}
|
||||
|
||||
/// This structure manages ensuring that modification to StackingContextCollectionState is
|
||||
|
@ -2197,6 +2215,7 @@ pub trait BlockFlowDisplayListBuilding {
|
|||
pub struct SavedStackingContextCollectionState {
|
||||
stacking_context_id: StackingContextId,
|
||||
real_stacking_context_id: StackingContextId,
|
||||
parent_reference_frame_id: ClipScrollNodeIndex,
|
||||
clipping_and_scrolling: ClippingAndScrolling,
|
||||
containing_block_clipping_and_scrolling: ClippingAndScrolling,
|
||||
clips_pushed: usize,
|
||||
|
@ -2209,6 +2228,7 @@ impl SavedStackingContextCollectionState {
|
|||
SavedStackingContextCollectionState {
|
||||
stacking_context_id: state.current_stacking_context_id,
|
||||
real_stacking_context_id: state.current_real_stacking_context_id,
|
||||
parent_reference_frame_id: state.current_parent_reference_frame_id,
|
||||
clipping_and_scrolling: state.current_clipping_and_scrolling,
|
||||
containing_block_clipping_and_scrolling: state.containing_block_clipping_and_scrolling,
|
||||
clips_pushed: 0,
|
||||
|
@ -2230,6 +2250,7 @@ impl SavedStackingContextCollectionState {
|
|||
fn restore(self, state: &mut StackingContextCollectionState) {
|
||||
state.current_stacking_context_id = self.stacking_context_id;
|
||||
state.current_real_stacking_context_id = self.real_stacking_context_id;
|
||||
state.current_parent_reference_frame_id = self.parent_reference_frame_id;
|
||||
state.current_clipping_and_scrolling = self.clipping_and_scrolling;
|
||||
state.containing_block_clipping_and_scrolling =
|
||||
self.containing_block_clipping_and_scrolling;
|
||||
|
@ -2332,6 +2353,16 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
|
|||
}
|
||||
}
|
||||
|
||||
/// Returns true if this fragment may establish a reference frame and this block
|
||||
/// creates a stacking context. Both are necessary in order to establish a reference
|
||||
/// frame.
|
||||
fn is_reference_frame(&self, context_type: Option<StackingContextType>) -> bool {
|
||||
match context_type {
|
||||
Some(StackingContextType::Real) => self.fragment.can_establish_reference_frame(),
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
fn collect_stacking_contexts_for_block(
|
||||
&mut self,
|
||||
state: &mut StackingContextCollectionState,
|
||||
|
@ -2348,8 +2379,17 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
|
|||
|
||||
if stacking_context_type == Some(StackingContextType::Real) {
|
||||
state.current_real_stacking_context_id = self.base.stacking_context_id;
|
||||
|
||||
}
|
||||
|
||||
let established_reference_frame = if self.is_reference_frame(stacking_context_type) {
|
||||
// WebRender currently creates reference frames automatically, so just add
|
||||
// a placeholder node to allocate a ClipScrollNodeIndex for this reference frame.
|
||||
Some(state.add_clip_scroll_node(ClipScrollNode::placeholder()))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
// We are getting the id of the scroll root that contains us here, not the id of
|
||||
// any scroll root that we create. If we create a scroll root, its index will be
|
||||
// stored in state.current_clipping_and_scrolling. If we create a stacking context,
|
||||
|
@ -2358,6 +2398,7 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
|
|||
state,
|
||||
&mut preserved_state,
|
||||
stacking_context_type,
|
||||
established_reference_frame,
|
||||
flags,
|
||||
);
|
||||
|
||||
|
@ -2371,6 +2412,7 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
|
|||
self.create_real_stacking_context_for_block(
|
||||
preserved_state.stacking_context_id,
|
||||
containing_clipping_and_scrolling,
|
||||
established_reference_frame,
|
||||
state,
|
||||
);
|
||||
},
|
||||
|
@ -2392,6 +2434,7 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
|
|||
state: &mut StackingContextCollectionState,
|
||||
preserved_state: &mut SavedStackingContextCollectionState,
|
||||
stacking_context_type: Option<StackingContextType>,
|
||||
established_reference_frame: Option<ClipScrollNodeIndex>,
|
||||
flags: StackingContextCollectionFlags,
|
||||
) -> ClippingAndScrolling {
|
||||
// If this block is absolutely positioned, we should be clipped and positioned by
|
||||
|
@ -2404,13 +2447,23 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
|
|||
state.containing_block_clipping_and_scrolling
|
||||
},
|
||||
StylePosition::Fixed => {
|
||||
// If we are a fixed positioned stacking context, we want to be scrolled by
|
||||
// our reference frame instead of the clip scroll node that we are inside.
|
||||
preserved_state.push_clip(state, Rect::max_rect(), StylePosition::Fixed);
|
||||
state.current_clipping_and_scrolling.scrolling =
|
||||
state.current_parent_reference_frame_id;
|
||||
state.current_clipping_and_scrolling
|
||||
},
|
||||
_ => state.current_clipping_and_scrolling,
|
||||
};
|
||||
self.base.clipping_and_scrolling = Some(containing_clipping_and_scrolling);
|
||||
|
||||
if let Some(reference_frame_index) = established_reference_frame {
|
||||
let clipping_and_scrolling = ClippingAndScrolling::simple(reference_frame_index);
|
||||
state.current_clipping_and_scrolling = clipping_and_scrolling;
|
||||
self.base.clipping_and_scrolling = Some(clipping_and_scrolling);
|
||||
}
|
||||
|
||||
let stacking_relative_border_box = if self.fragment.establishes_stacking_context() {
|
||||
self.stacking_relative_border_box(CoordinateSystem::Own)
|
||||
} else {
|
||||
|
@ -2658,6 +2711,7 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
|
|||
&self.base,
|
||||
ScrollPolicy::Scrollable,
|
||||
stacking_context_type,
|
||||
None,
|
||||
parent_clipping_and_scrolling,
|
||||
);
|
||||
state.add_stacking_context(parent_stacking_context_id, new_context);
|
||||
|
@ -2683,19 +2737,15 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
|
|||
&mut self,
|
||||
parent_stacking_context_id: StackingContextId,
|
||||
parent_clipping_and_scrolling: ClippingAndScrolling,
|
||||
established_reference_frame: Option<ClipScrollNodeIndex>,
|
||||
state: &mut StackingContextCollectionState,
|
||||
) {
|
||||
let scroll_policy = if self.is_fixed() {
|
||||
ScrollPolicy::Fixed
|
||||
} else {
|
||||
ScrollPolicy::Scrollable
|
||||
};
|
||||
|
||||
let stacking_context = self.fragment.create_stacking_context(
|
||||
self.base.stacking_context_id,
|
||||
&self.base,
|
||||
scroll_policy,
|
||||
ScrollPolicy::Scrollable,
|
||||
StackingContextType::Real,
|
||||
established_reference_frame,
|
||||
parent_clipping_and_scrolling,
|
||||
);
|
||||
|
||||
|
@ -2833,6 +2883,7 @@ impl InlineFlowDisplayListBuilding for InlineFlow {
|
|||
&self.base,
|
||||
ScrollPolicy::Scrollable,
|
||||
StackingContextType::Real,
|
||||
None,
|
||||
state.current_clipping_and_scrolling,
|
||||
);
|
||||
|
||||
|
|
|
@ -38,14 +38,25 @@ pub static BLUR_INFLATION_FACTOR: i32 = 3;
|
|||
/// An index into the vector of ClipScrollNodes. During WebRender conversion these nodes
|
||||
/// are given ClipIds.
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Serialize)]
|
||||
pub struct ClipScrollNodeIndex(pub usize);
|
||||
pub struct ClipScrollNodeIndex(usize);
|
||||
|
||||
impl ClipScrollNodeIndex {
|
||||
pub fn root_scroll_node() -> ClipScrollNodeIndex {
|
||||
ClipScrollNodeIndex(1)
|
||||
}
|
||||
|
||||
pub fn root_reference_frame() -> ClipScrollNodeIndex {
|
||||
ClipScrollNodeIndex(0)
|
||||
}
|
||||
|
||||
pub fn new(index: usize) -> ClipScrollNodeIndex {
|
||||
assert_ne!(index, 0, "Use the root_reference_frame constructor");
|
||||
assert_ne!(index, 1, "Use the root_scroll_node constructor");
|
||||
ClipScrollNodeIndex(index)
|
||||
}
|
||||
|
||||
pub fn is_root_scroll_node(&self) -> bool {
|
||||
match *self {
|
||||
ClipScrollNodeIndex(0) => true,
|
||||
_ => false,
|
||||
}
|
||||
*self == Self::root_scroll_node()
|
||||
}
|
||||
|
||||
pub fn to_define_item(&self) -> DisplayItem {
|
||||
|
@ -54,6 +65,10 @@ impl ClipScrollNodeIndex {
|
|||
node_index: *self,
|
||||
}))
|
||||
}
|
||||
|
||||
pub fn to_index(self) -> usize {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
/// A set of indices into the clip scroll node vector for a given item.
|
||||
|
@ -193,6 +208,9 @@ pub struct StackingContext {
|
|||
|
||||
/// The clip and scroll info for this StackingContext.
|
||||
pub parent_clipping_and_scrolling: ClippingAndScrolling,
|
||||
|
||||
/// The index of the reference frame that this stacking context estalishes.
|
||||
pub established_reference_frame: Option<ClipScrollNodeIndex>,
|
||||
}
|
||||
|
||||
impl StackingContext {
|
||||
|
@ -211,6 +229,7 @@ impl StackingContext {
|
|||
perspective: Option<LayoutTransform>,
|
||||
scroll_policy: ScrollPolicy,
|
||||
parent_clipping_and_scrolling: ClippingAndScrolling,
|
||||
established_reference_frame: Option<ClipScrollNodeIndex>,
|
||||
) -> StackingContext {
|
||||
StackingContext {
|
||||
id,
|
||||
|
@ -225,6 +244,7 @@ impl StackingContext {
|
|||
perspective,
|
||||
scroll_policy,
|
||||
parent_clipping_and_scrolling,
|
||||
established_reference_frame,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -242,7 +262,8 @@ impl StackingContext {
|
|||
TransformStyle::Flat,
|
||||
None,
|
||||
ScrollPolicy::Scrollable,
|
||||
ClippingAndScrolling::simple(ClipScrollNodeIndex(0)),
|
||||
ClippingAndScrolling::simple(ClipScrollNodeIndex::root_scroll_node()),
|
||||
None,
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -309,15 +330,16 @@ impl fmt::Debug for StackingContext {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize)]
|
||||
#[derive(Clone, Debug, PartialEq, Serialize)]
|
||||
pub struct StickyFrameData {
|
||||
pub margins: SideOffsets2D<Option<f32>>,
|
||||
pub vertical_offset_bounds: StickyOffsetBounds,
|
||||
pub horizontal_offset_bounds: StickyOffsetBounds,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize)]
|
||||
#[derive(Clone, Debug, PartialEq, Serialize)]
|
||||
pub enum ClipScrollNodeType {
|
||||
Placeholder,
|
||||
ScrollFrame(ScrollSensitivity, ExternalScrollId),
|
||||
StickyFrame(StickyFrameData),
|
||||
Clip,
|
||||
|
@ -339,6 +361,21 @@ pub struct ClipScrollNode {
|
|||
pub node_type: ClipScrollNodeType,
|
||||
}
|
||||
|
||||
impl ClipScrollNode {
|
||||
pub fn placeholder() -> ClipScrollNode {
|
||||
ClipScrollNode {
|
||||
parent_index: ClipScrollNodeIndex(0),
|
||||
clip: ClippingRegion::from_rect(LayoutRect::zero()),
|
||||
content_rect: LayoutRect::zero(),
|
||||
node_type: ClipScrollNodeType::Placeholder,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_placeholder(&self) -> bool {
|
||||
self.node_type == ClipScrollNodeType::Placeholder
|
||||
}
|
||||
}
|
||||
|
||||
/// One drawing command in the list.
|
||||
#[derive(Clone, Serialize)]
|
||||
pub enum DisplayItem {
|
||||
|
@ -412,7 +449,8 @@ impl BaseDisplayItem {
|
|||
clip_rect: LayoutRect::max_rect(),
|
||||
section: DisplayListSection::Content,
|
||||
stacking_context_id: StackingContextId::root(),
|
||||
clipping_and_scrolling: ClippingAndScrolling::simple(ClipScrollNodeIndex(0)),
|
||||
clipping_and_scrolling:
|
||||
ClippingAndScrolling::simple(ClipScrollNodeIndex::root_scroll_node()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,7 +41,12 @@ impl WebRenderDisplayListConverter for DisplayList {
|
|||
|
||||
let mut clip_ids = Vec::with_capacity(self.clip_scroll_nodes.len());
|
||||
clip_ids.resize(self.clip_scroll_nodes.len(), None);
|
||||
clip_ids[0] = Some(ClipId::root_scroll_node(pipeline_id.to_webrender()));
|
||||
|
||||
// We need to add the WebRender root reference frame and root scroll node ids
|
||||
// here manually, because WebRender creates these automatically.
|
||||
let webrender_pipeline = pipeline_id.to_webrender();
|
||||
clip_ids[0] = Some(ClipId::root_reference_frame(webrender_pipeline));
|
||||
clip_ids[1] = Some(ClipId::root_scroll_node(webrender_pipeline));
|
||||
|
||||
for item in &self.list {
|
||||
item.convert_to_webrender(
|
||||
|
@ -78,7 +83,7 @@ impl WebRenderDisplayItemConverter for DisplayItem {
|
|||
current_clip_and_scroll_info: &mut ClipAndScrollInfo,
|
||||
) {
|
||||
let get_id = |clip_ids: &[Option<ClipId>], index: ClipScrollNodeIndex| -> ClipId {
|
||||
match clip_ids[index.0] {
|
||||
match clip_ids[index.to_index()] {
|
||||
Some(id) => id,
|
||||
None => unreachable!("Tried to use WebRender ClipId before it was defined."),
|
||||
}
|
||||
|
@ -214,7 +219,7 @@ impl WebRenderDisplayItemConverter for DisplayItem {
|
|||
let stacking_context = &item.stacking_context;
|
||||
debug_assert_eq!(stacking_context.context_type, StackingContextType::Real);
|
||||
|
||||
builder.push_stacking_context(
|
||||
let reference_frame_clip_id = builder.push_stacking_context(
|
||||
&webrender_api::LayoutPrimitiveInfo::new(stacking_context.bounds),
|
||||
None,
|
||||
stacking_context.scroll_policy,
|
||||
|
@ -225,10 +230,17 @@ impl WebRenderDisplayItemConverter for DisplayItem {
|
|||
stacking_context.filters.clone(),
|
||||
GlyphRasterSpace::Screen,
|
||||
);
|
||||
|
||||
match (reference_frame_clip_id, stacking_context.established_reference_frame) {
|
||||
(Some(webrender_id), Some(frame_index)) =>
|
||||
clip_ids[frame_index.to_index()] = Some(webrender_id),
|
||||
(None, None) => {},
|
||||
_ => warn!("Mismatch between reference frame establishment!"),
|
||||
}
|
||||
},
|
||||
DisplayItem::PopStackingContext(_) => builder.pop_stacking_context(),
|
||||
DisplayItem::DefineClipScrollNode(ref item) => {
|
||||
let node = &clip_scroll_nodes[item.node_index.0];
|
||||
let node = &clip_scroll_nodes[item.node_index.to_index()];
|
||||
let parent_id = get_id(clip_ids, node.parent_index);
|
||||
let item_rect = node.clip.main;
|
||||
|
||||
|
@ -262,9 +274,12 @@ impl WebRenderDisplayItemConverter for DisplayItem {
|
|||
builder.pop_clip_id();
|
||||
id
|
||||
},
|
||||
ClipScrollNodeType::Placeholder => {
|
||||
unreachable!("Found DefineClipScrollNode for Placeholder type node.");
|
||||
}
|
||||
};
|
||||
|
||||
clip_ids[item.node_index.0] = Some(webrender_id);
|
||||
clip_ids[item.node_index.to_index()] = Some(webrender_id);
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2474,6 +2474,12 @@ impl Fragment {
|
|||
stacking_relative_border_box.size.height - border_padding.vertical()))
|
||||
}
|
||||
|
||||
/// Returns true if this fragment may establish a reference frame.
|
||||
pub fn can_establish_reference_frame(&self) -> bool {
|
||||
!self.style().get_box().transform.0.is_empty() ||
|
||||
self.style().get_box().perspective != Perspective::None
|
||||
}
|
||||
|
||||
/// Returns true if this fragment has a filter, transform, or perspective property set.
|
||||
pub fn has_filter_transform_or_perspective(&self) -> bool {
|
||||
!self.style().get_box().transform.0.is_empty() ||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue