mirror of
https://github.com/servo/servo.git
synced 2025-08-03 04:30:10 +01:00
Stop splitting scroll roots
Now that WebRender can handle splitting scrolling layers on its own, we don't need to do any work to split up scroll roots. This should also make it possible to handle overflow:scroll and containing block scroll roots in the future.
This commit is contained in:
parent
2f6cf2e9c8
commit
9d72e89ce3
5 changed files with 173 additions and 163 deletions
|
@ -40,7 +40,7 @@ use style_traits::viewport::ViewportConstraints;
|
|||
use time::{precise_time_ns, precise_time_s};
|
||||
use touch::{TouchHandler, TouchAction};
|
||||
use webrender;
|
||||
use webrender_traits::{self, ScrollEventPhase, ServoScrollRootId, LayoutPoint, ScrollLocation};
|
||||
use webrender_traits::{self, LayoutPoint, ScrollEventPhase, ScrollLayerId, ScrollLocation};
|
||||
use windowing::{self, MouseWindowEvent, WindowEvent, WindowMethods, WindowNavigateMsg};
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
|
@ -77,9 +77,9 @@ trait ConvertScrollRootIdFromWebRender {
|
|||
fn from_webrender(&self) -> ScrollRootId;
|
||||
}
|
||||
|
||||
impl ConvertScrollRootIdFromWebRender for webrender_traits::ServoScrollRootId {
|
||||
impl ConvertScrollRootIdFromWebRender for usize {
|
||||
fn from_webrender(&self) -> ScrollRootId {
|
||||
ScrollRootId(self.0)
|
||||
ScrollRootId(*self)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -791,10 +791,8 @@ impl<Window: WindowMethods> IOCompositor<Window> {
|
|||
pipeline_id: PipelineId,
|
||||
scroll_root_id: ScrollRootId,
|
||||
point: Point2D<f32>) {
|
||||
self.webrender_api.scroll_layers_with_scroll_root_id(
|
||||
LayoutPoint::from_untyped(&point),
|
||||
pipeline_id.to_webrender(),
|
||||
ServoScrollRootId(scroll_root_id.0));
|
||||
let id = ScrollLayerId::new(scroll_root_id.0, pipeline_id.to_webrender());
|
||||
self.webrender_api.scroll_layer_with_id(LayoutPoint::from_untyped(&point), id);
|
||||
}
|
||||
|
||||
fn handle_window_message(&mut self, event: WindowEvent) {
|
||||
|
@ -1386,13 +1384,18 @@ impl<Window: WindowMethods> IOCompositor<Window> {
|
|||
fn send_viewport_rects(&self) {
|
||||
let mut stacking_context_scroll_states_per_pipeline = HashMap::new();
|
||||
for scroll_layer_state in self.webrender_api.get_scroll_layer_state() {
|
||||
let external_id = match scroll_layer_state.id.external_id() {
|
||||
Some(id) => id,
|
||||
None => continue,
|
||||
};
|
||||
|
||||
let stacking_context_scroll_state = StackingContextScrollState {
|
||||
scroll_root_id: scroll_layer_state.scroll_root_id.from_webrender(),
|
||||
scroll_root_id: external_id.from_webrender(),
|
||||
scroll_offset: scroll_layer_state.scroll_offset.to_untyped(),
|
||||
};
|
||||
let pipeline_id = scroll_layer_state.pipeline_id;
|
||||
|
||||
stacking_context_scroll_states_per_pipeline
|
||||
.entry(pipeline_id)
|
||||
.entry(scroll_layer_state.id.pipeline_id())
|
||||
.or_insert(vec![])
|
||||
.push(stacking_context_scroll_state);
|
||||
}
|
||||
|
|
|
@ -434,6 +434,7 @@ impl StackingContext {
|
|||
pub fn to_display_list_items(self) -> (DisplayItem, DisplayItem) {
|
||||
let mut base_item = BaseDisplayItem::empty();
|
||||
base_item.stacking_context_id = self.id;
|
||||
base_item.scroll_root_id = self.parent_scroll_id;
|
||||
|
||||
let pop_item = DisplayItem::PopStackingContext(Box::new(
|
||||
PopStackingContextItem {
|
||||
|
|
|
@ -2233,10 +2233,11 @@ impl Flow for BlockFlow {
|
|||
|
||||
fn compute_overflow(&self) -> Overflow {
|
||||
let flow_size = self.base.position.size.to_physical(self.base.writing_mode);
|
||||
self.fragment.compute_overflow(&flow_size,
|
||||
let overflow = self.fragment.compute_overflow(&flow_size,
|
||||
&self.base
|
||||
.early_absolute_position_info
|
||||
.relative_containing_block_size)
|
||||
.relative_containing_block_size);
|
||||
overflow
|
||||
}
|
||||
|
||||
fn iterate_through_fragment_border_boxes(&self,
|
||||
|
|
|
@ -120,12 +120,31 @@ fn get_cyclic<T>(arr: &[T], index: usize) -> &T {
|
|||
&arr[index % arr.len()]
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct StackingContextInfo {
|
||||
children: Vec<StackingContext>,
|
||||
scroll_roots: Vec<ScrollRoot>,
|
||||
}
|
||||
|
||||
impl StackingContextInfo {
|
||||
fn new() -> StackingContextInfo {
|
||||
StackingContextInfo {
|
||||
children: Vec::new(),
|
||||
scroll_roots: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
fn take_children(&mut self) -> Vec<StackingContext> {
|
||||
mem::replace(&mut self.children, Vec::new())
|
||||
}
|
||||
}
|
||||
|
||||
pub struct DisplayListBuildState<'a> {
|
||||
pub layout_context: &'a LayoutContext<'a>,
|
||||
pub root_stacking_context: StackingContext,
|
||||
pub items: HashMap<StackingContextId, Vec<DisplayItem>>,
|
||||
pub stacking_context_children: HashMap<StackingContextId, Vec<StackingContext>>,
|
||||
pub scroll_roots: HashMap<ScrollRootId, ScrollRoot>,
|
||||
stacking_context_info: HashMap<StackingContextId, StackingContextInfo>,
|
||||
pub scroll_root_parents: HashMap<ScrollRootId, ScrollRootId>,
|
||||
pub processing_scroll_root_element: bool,
|
||||
|
||||
/// The current stacking context id, used to keep track of state when building.
|
||||
|
@ -147,8 +166,8 @@ impl<'a> DisplayListBuildState<'a> {
|
|||
layout_context: layout_context,
|
||||
root_stacking_context: StackingContext::root(),
|
||||
items: HashMap::new(),
|
||||
stacking_context_children: HashMap::new(),
|
||||
scroll_roots: HashMap::new(),
|
||||
stacking_context_info: HashMap::new(),
|
||||
scroll_root_parents: HashMap::new(),
|
||||
processing_scroll_root_element: false,
|
||||
current_stacking_context_id: StackingContextId::root(),
|
||||
current_scroll_root_id: ScrollRootId::root(),
|
||||
|
@ -164,13 +183,18 @@ impl<'a> DisplayListBuildState<'a> {
|
|||
fn add_stacking_context(&mut self,
|
||||
parent_id: StackingContextId,
|
||||
stacking_context: StackingContext) {
|
||||
let contexts = self.stacking_context_children.entry(parent_id).or_insert(Vec::new());
|
||||
contexts.push(stacking_context);
|
||||
let info = self.stacking_context_info
|
||||
.entry(parent_id)
|
||||
.or_insert(StackingContextInfo::new());
|
||||
info.children.push(stacking_context);
|
||||
}
|
||||
|
||||
fn add_scroll_root(&mut self, scroll_root: ScrollRoot) {
|
||||
debug_assert!(!self.scroll_roots.contains_key(&scroll_root.id));
|
||||
self.scroll_roots.insert(scroll_root.id, scroll_root);
|
||||
fn add_scroll_root(&mut self, scroll_root: ScrollRoot, stacking_context_id: StackingContextId) {
|
||||
self.scroll_root_parents.insert(scroll_root.id, scroll_root.parent_id);
|
||||
let info = self.stacking_context_info
|
||||
.entry(stacking_context_id)
|
||||
.or_insert(StackingContextInfo::new());
|
||||
info.scroll_roots.push(scroll_root);
|
||||
}
|
||||
|
||||
fn parent_scroll_root_id(&self, scroll_root_id: ScrollRootId) -> ScrollRootId {
|
||||
|
@ -178,8 +202,8 @@ impl<'a> DisplayListBuildState<'a> {
|
|||
return ScrollRootId::root()
|
||||
}
|
||||
|
||||
debug_assert!(self.scroll_roots.contains_key(&scroll_root_id));
|
||||
self.scroll_roots.get(&scroll_root_id).unwrap().parent_id
|
||||
debug_assert!(self.scroll_root_parents.contains_key(&scroll_root_id));
|
||||
*self.scroll_root_parents.get(&scroll_root_id).unwrap()
|
||||
}
|
||||
|
||||
fn create_base_display_item(&self,
|
||||
|
@ -209,13 +233,10 @@ impl<'a> DisplayListBuildState<'a> {
|
|||
}
|
||||
|
||||
pub fn to_display_list(mut self) -> DisplayList {
|
||||
let mut scroll_root_stack = Vec::new();
|
||||
scroll_root_stack.push(ScrollRootId::root());
|
||||
|
||||
let mut list = Vec::new();
|
||||
let root_context = mem::replace(&mut self.root_stacking_context, StackingContext::root());
|
||||
|
||||
self.to_display_list_for_stacking_context(&mut list, root_context, &mut scroll_root_stack);
|
||||
self.to_display_list_for_stacking_context(&mut list, root_context);
|
||||
|
||||
DisplayList {
|
||||
list: list,
|
||||
|
@ -224,128 +245,75 @@ impl<'a> DisplayListBuildState<'a> {
|
|||
|
||||
fn to_display_list_for_stacking_context(&mut self,
|
||||
list: &mut Vec<DisplayItem>,
|
||||
stacking_context: StackingContext,
|
||||
scroll_root_stack: &mut Vec<ScrollRootId>) {
|
||||
stacking_context: StackingContext) {
|
||||
let mut child_items = self.items.remove(&stacking_context.id).unwrap_or(Vec::new());
|
||||
child_items.sort_by(|a, b| a.base().section.cmp(&b.base().section));
|
||||
child_items.reverse();
|
||||
|
||||
let mut child_stacking_contexts =
|
||||
self.stacking_context_children.remove(&stacking_context.id).unwrap_or_else(Vec::new);
|
||||
child_stacking_contexts.sort();
|
||||
let mut info = self.stacking_context_info.remove(&stacking_context.id)
|
||||
.unwrap_or_else(StackingContextInfo::new);
|
||||
|
||||
let real_stacking_context = stacking_context.context_type == StackingContextType::Real;
|
||||
if !real_stacking_context {
|
||||
self.to_display_list_for_items(list,
|
||||
child_items,
|
||||
child_stacking_contexts,
|
||||
scroll_root_stack);
|
||||
return;
|
||||
info.children.sort();
|
||||
|
||||
if stacking_context.context_type != StackingContextType::Real {
|
||||
list.extend(info.scroll_roots.into_iter().map(|root| root.to_push()));
|
||||
self.to_display_list_for_items(list, child_items, info.children);
|
||||
} else {
|
||||
let (push_item, pop_item) = stacking_context.to_display_list_items();
|
||||
list.push(push_item);
|
||||
list.extend(info.scroll_roots.into_iter().map(|root| root.to_push()));
|
||||
self.to_display_list_for_items(list, child_items, info.children);
|
||||
list.push(pop_item);
|
||||
}
|
||||
|
||||
let mut scroll_root_stack = Vec::new();
|
||||
scroll_root_stack.push(stacking_context.parent_scroll_id);
|
||||
|
||||
let (push_item, pop_item) = stacking_context.to_display_list_items();
|
||||
list.push(push_item);
|
||||
self.to_display_list_for_items(list,
|
||||
child_items,
|
||||
child_stacking_contexts,
|
||||
&mut scroll_root_stack);
|
||||
list.push(pop_item);
|
||||
}
|
||||
|
||||
fn to_display_list_for_items(&mut self,
|
||||
list: &mut Vec<DisplayItem>,
|
||||
mut child_items: Vec<DisplayItem>,
|
||||
child_stacking_contexts: Vec<StackingContext>,
|
||||
scroll_root_stack: &mut Vec<ScrollRootId>) {
|
||||
child_stacking_contexts: Vec<StackingContext>) {
|
||||
// Properly order display items that make up a stacking context. "Steps" here
|
||||
// refer to the steps in CSS 2.1 Appendix E.
|
||||
// Steps 1 and 2: Borders and background for the root.
|
||||
while child_items.last().map_or(false,
|
||||
|child| child.section() == DisplayListSection::BackgroundAndBorders) {
|
||||
let item = child_items.pop().unwrap();
|
||||
self.switch_scroll_roots(list, item.scroll_root_id(), scroll_root_stack);
|
||||
list.push(item);
|
||||
list.push(child_items.pop().unwrap());
|
||||
}
|
||||
|
||||
// Step 3: Positioned descendants with negative z-indices.
|
||||
let mut child_stacking_contexts = child_stacking_contexts.into_iter().peekable();
|
||||
while child_stacking_contexts.peek().map_or(false, |child| child.z_index < 0) {
|
||||
let context = child_stacking_contexts.next().unwrap();
|
||||
self.switch_scroll_roots(list, context.parent_scroll_id, scroll_root_stack);
|
||||
self.to_display_list_for_stacking_context(list, context, scroll_root_stack);
|
||||
self.to_display_list_for_stacking_context(list, context);
|
||||
}
|
||||
|
||||
// Step 4: Block backgrounds and borders.
|
||||
while child_items.last().map_or(false,
|
||||
|child| child.section() == DisplayListSection::BlockBackgroundsAndBorders) {
|
||||
let item = child_items.pop().unwrap();
|
||||
self.switch_scroll_roots(list, item.scroll_root_id(), scroll_root_stack);
|
||||
list.push(item);
|
||||
list.push(child_items.pop().unwrap());
|
||||
}
|
||||
|
||||
// Step 5: Floats.
|
||||
while child_stacking_contexts.peek().map_or(false,
|
||||
|child| child.context_type == StackingContextType::PseudoFloat) {
|
||||
let context = child_stacking_contexts.next().unwrap();
|
||||
self.switch_scroll_roots(list, context.parent_scroll_id, scroll_root_stack);
|
||||
self.to_display_list_for_stacking_context(list, context, scroll_root_stack);
|
||||
self.to_display_list_for_stacking_context(list, context);
|
||||
}
|
||||
|
||||
// Step 6 & 7: Content and inlines that generate stacking contexts.
|
||||
while child_items.last().map_or(false,
|
||||
|child| child.section() == DisplayListSection::Content) {
|
||||
let item = child_items.pop().unwrap();
|
||||
self.switch_scroll_roots(list, item.scroll_root_id(), scroll_root_stack);
|
||||
list.push(item);
|
||||
list.push(child_items.pop().unwrap());
|
||||
}
|
||||
|
||||
// Step 8 & 9: Positioned descendants with nonnegative, numeric z-indices.
|
||||
for child in child_stacking_contexts {
|
||||
self.switch_scroll_roots(list, child.parent_scroll_id, scroll_root_stack);
|
||||
self.to_display_list_for_stacking_context(list, child, scroll_root_stack);
|
||||
self.to_display_list_for_stacking_context(list, child);
|
||||
}
|
||||
|
||||
// Step 10: Outlines.
|
||||
for item in child_items.drain(..) {
|
||||
self.switch_scroll_roots(list, item.scroll_root_id(), scroll_root_stack);
|
||||
list.push(item);
|
||||
}
|
||||
|
||||
for _ in scroll_root_stack.drain(1..) {
|
||||
list.push(DisplayItem::PopScrollRoot(Box::new(BaseDisplayItem::empty())));
|
||||
}
|
||||
}
|
||||
|
||||
fn switch_scroll_roots(&self,
|
||||
list: &mut Vec<DisplayItem>,
|
||||
new_id: ScrollRootId,
|
||||
scroll_root_stack: &mut Vec<ScrollRootId>) {
|
||||
if new_id == *scroll_root_stack.last().unwrap() {
|
||||
return;
|
||||
}
|
||||
|
||||
if new_id == *scroll_root_stack.first().unwrap() {
|
||||
for _ in scroll_root_stack.drain(1..) {
|
||||
list.push(DisplayItem::PopScrollRoot(Box::new(BaseDisplayItem::empty())));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// We never want to reach the root of the ScrollRoot tree without encountering the
|
||||
// containing scroll root of this StackingContext. If this does happen we've tried to
|
||||
// switch to a ScrollRoot that does not contain our current stacking context or isn't
|
||||
// itself a direct child of our current stacking context. This should never happen
|
||||
// due to CSS stacking rules.
|
||||
debug_assert!(new_id != ScrollRootId::root());
|
||||
|
||||
let scroll_root = self.scroll_roots.get(&new_id).unwrap();
|
||||
self.switch_scroll_roots(list, scroll_root.parent_id, scroll_root_stack);
|
||||
|
||||
scroll_root_stack.push(new_id);
|
||||
list.push(scroll_root.to_push());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -507,6 +475,10 @@ pub trait FragmentDisplayListBuilding {
|
|||
mode: StackingContextCreationMode,
|
||||
parent_scroll_id: ScrollRootId)
|
||||
-> StackingContext;
|
||||
|
||||
|
||||
/// The id of stacking context this fragment would create.
|
||||
fn stacking_context_id(&self) -> StackingContextId;
|
||||
}
|
||||
|
||||
fn handle_overlapping_radii(size: &Size2D<Au>, radii: &BorderRadii<Au>) -> BorderRadii<Au> {
|
||||
|
@ -1612,6 +1584,10 @@ impl FragmentDisplayListBuilding for Fragment {
|
|||
}
|
||||
}
|
||||
|
||||
fn stacking_context_id(&self) -> StackingContextId {
|
||||
StackingContextId::new_of_type(self.node.id() as usize, self.fragment_type())
|
||||
}
|
||||
|
||||
fn create_stacking_context(&self,
|
||||
id: StackingContextId,
|
||||
base_flow: &BaseFlow,
|
||||
|
@ -1858,14 +1834,12 @@ impl FragmentDisplayListBuilding for Fragment {
|
|||
|
||||
pub trait BlockFlowDisplayListBuilding {
|
||||
fn collect_stacking_contexts_for_block(&mut self, state: &mut DisplayListBuildState);
|
||||
fn collect_scroll_root_for_block(&mut self, state: &mut DisplayListBuildState) -> ScrollRootId;
|
||||
fn setup_scroll_root_for_block(&mut self, state: &mut DisplayListBuildState) -> ScrollRootId;
|
||||
fn create_pseudo_stacking_context_for_block(&mut self,
|
||||
stacking_context_id: StackingContextId,
|
||||
parent_stacking_context_id: StackingContextId,
|
||||
parent_scroll_root_id: ScrollRootId,
|
||||
state: &mut DisplayListBuildState);
|
||||
fn create_real_stacking_context_for_block(&mut self,
|
||||
stacking_context_id: StackingContextId,
|
||||
parent_stacking_context_id: StackingContextId,
|
||||
parent_scroll_root_id: ScrollRootId,
|
||||
state: &mut DisplayListBuildState);
|
||||
|
@ -1876,43 +1850,49 @@ pub trait BlockFlowDisplayListBuilding {
|
|||
|
||||
impl BlockFlowDisplayListBuilding for BlockFlow {
|
||||
fn collect_stacking_contexts_for_block(&mut self, state: &mut DisplayListBuildState) {
|
||||
let parent_scroll_root_id = state.current_scroll_root_id;
|
||||
self.base.scroll_root_id = self.collect_scroll_root_for_block(state);
|
||||
state.current_scroll_root_id = self.base.scroll_root_id;
|
||||
|
||||
let parent_stacking_context_id = state.current_stacking_context_id;
|
||||
let block_stacking_context_type = self.block_stacking_context_type();
|
||||
if block_stacking_context_type == BlockStackingContextType::NonstackingContext {
|
||||
self.base.stacking_context_id = state.current_stacking_context_id;
|
||||
self.base.collect_stacking_contexts_for_children(state);
|
||||
} else {
|
||||
let parent_stacking_context_id = state.current_stacking_context_id;
|
||||
let stacking_context_id =
|
||||
StackingContextId::new_of_type(self.fragment.node.id() as usize,
|
||||
self.fragment.fragment_type());
|
||||
state.current_stacking_context_id = stacking_context_id;
|
||||
self.base.stacking_context_id = stacking_context_id;
|
||||
self.base.stacking_context_id = match block_stacking_context_type {
|
||||
BlockStackingContextType::NonstackingContext => state.current_stacking_context_id,
|
||||
BlockStackingContextType::PseudoStackingContext |
|
||||
BlockStackingContextType::StackingContext => self.fragment.stacking_context_id(),
|
||||
};
|
||||
state.current_stacking_context_id = self.base.stacking_context_id;
|
||||
|
||||
if block_stacking_context_type == BlockStackingContextType::PseudoStackingContext {
|
||||
self.create_pseudo_stacking_context_for_block(stacking_context_id,
|
||||
parent_stacking_context_id,
|
||||
parent_scroll_root_id,
|
||||
let original_scroll_root_id = state.current_scroll_root_id;
|
||||
|
||||
// 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 id will be
|
||||
// stored in state.current_scroll_root_id. If we should create a stacking context,
|
||||
// we don't want it to be clipped by its own scroll root.
|
||||
let containing_scroll_root_id = self.setup_scroll_root_for_block(state);
|
||||
|
||||
match block_stacking_context_type {
|
||||
BlockStackingContextType::NonstackingContext => {
|
||||
self.base.collect_stacking_contexts_for_children(state);
|
||||
}
|
||||
BlockStackingContextType::PseudoStackingContext => {
|
||||
self.create_pseudo_stacking_context_for_block(parent_stacking_context_id,
|
||||
containing_scroll_root_id,
|
||||
state);
|
||||
} else {
|
||||
self.create_real_stacking_context_for_block(stacking_context_id,
|
||||
parent_stacking_context_id,
|
||||
parent_scroll_root_id,
|
||||
}
|
||||
BlockStackingContextType::StackingContext => {
|
||||
self.create_real_stacking_context_for_block(parent_stacking_context_id,
|
||||
containing_scroll_root_id,
|
||||
state);
|
||||
}
|
||||
|
||||
state.current_stacking_context_id = parent_stacking_context_id;
|
||||
}
|
||||
|
||||
state.current_scroll_root_id = parent_scroll_root_id;
|
||||
state.current_scroll_root_id = original_scroll_root_id;
|
||||
state.current_stacking_context_id = parent_stacking_context_id;
|
||||
}
|
||||
|
||||
fn collect_scroll_root_for_block(&mut self, state: &mut DisplayListBuildState) -> ScrollRootId {
|
||||
fn setup_scroll_root_for_block(&mut self, state: &mut DisplayListBuildState) -> ScrollRootId {
|
||||
let containing_scroll_root_id = state.current_scroll_root_id;
|
||||
self.base.scroll_root_id = containing_scroll_root_id;
|
||||
|
||||
if !self.style_permits_scrolling_overflow() {
|
||||
return state.current_scroll_root_id;
|
||||
return containing_scroll_root_id;
|
||||
}
|
||||
|
||||
let coordinate_system = if self.fragment.establishes_stacking_context() {
|
||||
|
@ -1933,25 +1913,27 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
|
|||
self.base.overflow.scroll.size.height > clip.size.height;
|
||||
self.mark_scrolling_overflow(has_scrolling_overflow);
|
||||
if !has_scrolling_overflow {
|
||||
return state.current_scroll_root_id;
|
||||
return containing_scroll_root_id;
|
||||
}
|
||||
|
||||
let scroll_root_id = ScrollRootId::new_of_type(self.fragment.node.id() as usize,
|
||||
self.fragment.fragment_type());
|
||||
let parent_scroll_root_id = state.current_scroll_root_id;
|
||||
let new_scroll_root_id = ScrollRootId::new_of_type(self.fragment.node.id() as usize,
|
||||
self.fragment.fragment_type());
|
||||
state.add_scroll_root(
|
||||
ScrollRoot {
|
||||
id: scroll_root_id,
|
||||
parent_id: parent_scroll_root_id,
|
||||
id: new_scroll_root_id,
|
||||
parent_id: containing_scroll_root_id,
|
||||
clip: clip,
|
||||
size: self.base.overflow.scroll.size,
|
||||
}
|
||||
},
|
||||
self.base.stacking_context_id
|
||||
);
|
||||
scroll_root_id
|
||||
|
||||
self.base.scroll_root_id = new_scroll_root_id;
|
||||
state.current_scroll_root_id = new_scroll_root_id;
|
||||
containing_scroll_root_id
|
||||
}
|
||||
|
||||
fn create_pseudo_stacking_context_for_block(&mut self,
|
||||
stacking_context_id: StackingContextId,
|
||||
parent_stacking_context_id: StackingContextId,
|
||||
parent_scroll_root_id: ScrollRootId,
|
||||
state: &mut DisplayListBuildState) {
|
||||
|
@ -1963,7 +1945,7 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
|
|||
StackingContextCreationMode::PseudoFloat
|
||||
};
|
||||
|
||||
let new_context = self.fragment.create_stacking_context(stacking_context_id,
|
||||
let new_context = self.fragment.create_stacking_context(self.base.stacking_context_id,
|
||||
&self.base,
|
||||
ScrollPolicy::Scrollable,
|
||||
creation_mode,
|
||||
|
@ -1972,19 +1954,20 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
|
|||
|
||||
self.base.collect_stacking_contexts_for_children(state);
|
||||
|
||||
let new_children =
|
||||
state.stacking_context_children.remove(&stacking_context_id).unwrap_or_else(Vec::new);
|
||||
for child in new_children {
|
||||
if child.context_type == StackingContextType::PseudoFloat {
|
||||
state.add_stacking_context(stacking_context_id, child);
|
||||
} else {
|
||||
state.add_stacking_context(parent_stacking_context_id, child);
|
||||
let children = state.stacking_context_info.get_mut(&self.base.stacking_context_id)
|
||||
.map(|info| info.take_children());
|
||||
if let Some(children) = children {
|
||||
for child in children {
|
||||
if child.context_type == StackingContextType::PseudoFloat {
|
||||
state.add_stacking_context(self.base.stacking_context_id, child);
|
||||
} else {
|
||||
state.add_stacking_context(parent_stacking_context_id, child);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn create_real_stacking_context_for_block(&mut self,
|
||||
stacking_context_id: StackingContextId,
|
||||
parent_stacking_context_id: StackingContextId,
|
||||
parent_scroll_root_id: ScrollRootId,
|
||||
state: &mut DisplayListBuildState) {
|
||||
|
@ -1995,7 +1978,7 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
|
|||
};
|
||||
|
||||
let stacking_context = self.fragment.create_stacking_context(
|
||||
stacking_context_id,
|
||||
self.base.stacking_context_id,
|
||||
&self.base,
|
||||
scroll_policy,
|
||||
StackingContextCreationMode::Normal,
|
||||
|
|
|
@ -16,14 +16,16 @@ use msg::constellation_msg::PipelineId;
|
|||
use style::computed_values::{image_rendering, mix_blend_mode};
|
||||
use style::computed_values::filter::{self, Filter};
|
||||
use style::values::computed::BorderStyle;
|
||||
use webrender_traits::{self, DisplayListBuilder, ExtendMode, LayoutTransform};
|
||||
use webrender_traits::{self, DisplayListBuilder, ExtendMode, LayoutTransform, ScrollLayerId};
|
||||
|
||||
pub trait WebRenderDisplayListConverter {
|
||||
fn convert_to_webrender(&self, pipeline_id: PipelineId) -> DisplayListBuilder;
|
||||
}
|
||||
|
||||
trait WebRenderDisplayItemConverter {
|
||||
fn convert_to_webrender(&self, builder: &mut DisplayListBuilder);
|
||||
fn convert_to_webrender(&self,
|
||||
builder: &mut DisplayListBuilder,
|
||||
current_scroll_root_id: &mut ScrollRootId);
|
||||
}
|
||||
|
||||
trait ToBorderStyle {
|
||||
|
@ -212,16 +214,31 @@ impl ToFilterOps for filter::T {
|
|||
impl WebRenderDisplayListConverter for DisplayList {
|
||||
fn convert_to_webrender(&self, pipeline_id: PipelineId) -> DisplayListBuilder {
|
||||
let traversal = DisplayListTraversal::new(self);
|
||||
let mut builder = DisplayListBuilder::new(pipeline_id.to_webrender());
|
||||
let webrender_pipeline_id = pipeline_id.to_webrender();
|
||||
let mut builder = DisplayListBuilder::new(webrender_pipeline_id);
|
||||
|
||||
let mut current_scroll_root_id = ScrollRootId::root();
|
||||
builder.push_clip_id(current_scroll_root_id.convert_to_webrender(webrender_pipeline_id));
|
||||
|
||||
for item in traversal {
|
||||
item.convert_to_webrender(&mut builder);
|
||||
item.convert_to_webrender(&mut builder, &mut current_scroll_root_id);
|
||||
}
|
||||
builder
|
||||
}
|
||||
}
|
||||
|
||||
impl WebRenderDisplayItemConverter for DisplayItem {
|
||||
fn convert_to_webrender(&self, builder: &mut DisplayListBuilder) {
|
||||
fn convert_to_webrender(&self,
|
||||
builder: &mut DisplayListBuilder,
|
||||
current_scroll_root_id: &mut ScrollRootId) {
|
||||
let scroll_root_id = self.base().scroll_root_id;
|
||||
if scroll_root_id != *current_scroll_root_id {
|
||||
let pipeline_id = builder.pipeline_id;
|
||||
builder.pop_clip_id();
|
||||
builder.push_clip_id(scroll_root_id.convert_to_webrender(pipeline_id));
|
||||
*current_scroll_root_id = scroll_root_id;
|
||||
}
|
||||
|
||||
match *self {
|
||||
DisplayItem::SolidColor(ref item) => {
|
||||
let color = item.color;
|
||||
|
@ -403,21 +420,26 @@ impl WebRenderDisplayItemConverter for DisplayItem {
|
|||
vec![],
|
||||
None);
|
||||
|
||||
builder.push_scroll_layer(clip,
|
||||
item.scroll_root.size.to_sizef(),
|
||||
Some(item.scroll_root.id.convert_to_webrender()));
|
||||
let provided_id = ScrollLayerId::new(item.scroll_root.id.0, builder.pipeline_id);
|
||||
let id = builder.define_clip(clip,
|
||||
item.scroll_root.size.to_sizef(),
|
||||
Some(provided_id));
|
||||
debug_assert!(provided_id == id);
|
||||
}
|
||||
DisplayItem::PopScrollRoot(_) => builder.pop_scroll_layer(),
|
||||
DisplayItem::PopScrollRoot(_) => {} //builder.pop_scroll_layer(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
trait WebRenderScrollRootIdConverter {
|
||||
fn convert_to_webrender(&self) -> webrender_traits::ServoScrollRootId;
|
||||
fn convert_to_webrender(&self, pipeline_id: webrender_traits::PipelineId) -> ScrollLayerId;
|
||||
}
|
||||
|
||||
impl WebRenderScrollRootIdConverter for ScrollRootId {
|
||||
fn convert_to_webrender(&self) -> webrender_traits::ServoScrollRootId {
|
||||
webrender_traits::ServoScrollRootId(self.0)
|
||||
fn convert_to_webrender(&self, pipeline_id: webrender_traits::PipelineId) -> ScrollLayerId {
|
||||
if *self == ScrollRootId::root() {
|
||||
ScrollLayerId::root_scroll_layer(pipeline_id)
|
||||
} else {
|
||||
ScrollLayerId::new(self.0, pipeline_id)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue