Fix fixed position items with parents with CSS clips

In order to properly handle CSS clipping, we need to keep track of what
the different kinds of clips that we have. On one hand, clipping due to
overflow rules should respect the containing block hierarchy, while CSS
clipping should respect the flow tree hierarchy. In order to represent
the complexity of items that are scrolled via one clip/scroll frame and
clipped by another we keep track of that status with a
ClipAndScrollInfo.
This commit is contained in:
Martin Robinson 2017-07-27 11:25:59 +02:00
parent 46f6e68bad
commit daf638bc3f
11 changed files with 214 additions and 106 deletions

View file

@ -33,8 +33,8 @@ use style::values::computed::Filter;
use style_traits::cursor::Cursor;
use text::TextRun;
use text::glyph::ByteIndex;
use webrender_api::{self, ClipId, ColorF, GradientStop, LocalClip, MixBlendMode, ScrollPolicy};
use webrender_api::{ScrollSensitivity, TransformStyle, WebGLContextId};
use webrender_api::{self, ClipAndScrollInfo, ClipId, ColorF, GradientStop, LocalClip};
use webrender_api::{MixBlendMode, ScrollPolicy, ScrollSensitivity, TransformStyle, WebGLContextId};
pub use style::dom::OpaqueNode;
@ -152,7 +152,7 @@ impl DisplayList {
match item {
&DisplayItem::PushStackingContext(ref context_item) => {
self.text_index_stacking_context(&context_item.stacking_context,
item.base().scroll_root_id,
item.scroll_node_id(),
node,
traversal,
point,
@ -229,7 +229,7 @@ impl DisplayList {
match item {
&DisplayItem::PushStackingContext(ref context_item) => {
self.hit_test_stacking_context(&context_item.stacking_context,
item.base().scroll_root_id,
item.scroll_node_id(),
traversal,
point,
offset_lookup,
@ -286,10 +286,10 @@ impl DisplayList {
pub fn print_with_tree(&self, print_tree: &mut PrintTree) {
print_tree.new_level("Items".to_owned());
for item in &self.list {
print_tree.add_item(format!("{:?} StackingContext: {:?} ScrollRoot: {:?}",
print_tree.add_item(format!("{:?} StackingContext: {:?} {:?}",
item,
item.base().stacking_context_id,
item.scroll_root_id()));
item.clip_and_scroll_info()));
}
print_tree.end_level();
}
@ -438,8 +438,8 @@ pub struct StackingContext {
/// The scroll policy of this layer.
pub scroll_policy: ScrollPolicy,
/// The id of the parent scrolling area that contains this StackingContext.
pub parent_scroll_id: ClipId,
/// The clip and scroll info for this StackingContext.
pub parent_clip_and_scroll_info: ClipAndScrollInfo,
}
impl StackingContext {
@ -456,7 +456,7 @@ impl StackingContext {
transform_style: TransformStyle,
perspective: Option<Transform3D<f32>>,
scroll_policy: ScrollPolicy,
parent_scroll_id: ClipId)
parent_clip_and_scroll_info: ClipAndScrollInfo)
-> StackingContext {
StackingContext {
id: id,
@ -470,7 +470,7 @@ impl StackingContext {
transform_style: transform_style,
perspective: perspective,
scroll_policy: scroll_policy,
parent_scroll_id: parent_scroll_id,
parent_clip_and_scroll_info: parent_clip_and_scroll_info,
}
}
@ -487,13 +487,13 @@ impl StackingContext {
TransformStyle::Flat,
None,
ScrollPolicy::Scrollable,
pipeline_id.root_scroll_node())
pipeline_id.root_clip_and_scroll_info())
}
pub fn to_display_list_items(self, pipeline_id: PipelineId) -> (DisplayItem, DisplayItem) {
let mut base_item = BaseDisplayItem::empty(pipeline_id);
base_item.stacking_context_id = self.id;
base_item.scroll_root_id = self.parent_scroll_id;
base_item.clip_and_scroll_info = self.parent_clip_and_scroll_info;
let pop_item = DisplayItem::PopStackingContext(Box::new(
PopStackingContextItem {
@ -631,8 +631,8 @@ pub struct BaseDisplayItem {
/// The id of the stacking context this item belongs to.
pub stacking_context_id: StackingContextId,
/// The id of the scroll root this item belongs to.
pub scroll_root_id: ClipId,
/// The clip and scroll info for this item.
pub clip_and_scroll_info: ClipAndScrollInfo,
}
impl BaseDisplayItem {
@ -642,7 +642,7 @@ impl BaseDisplayItem {
local_clip: LocalClip,
section: DisplayListSection,
stacking_context_id: StackingContextId,
scroll_root_id: ClipId)
clip_and_scroll_info: ClipAndScrollInfo)
-> BaseDisplayItem {
BaseDisplayItem {
bounds: *bounds,
@ -650,7 +650,7 @@ impl BaseDisplayItem {
local_clip: local_clip,
section: section,
stacking_context_id: stacking_context_id,
scroll_root_id: scroll_root_id,
clip_and_scroll_info: clip_and_scroll_info,
}
}
@ -665,7 +665,7 @@ impl BaseDisplayItem {
local_clip: LocalClip::from(max_rect().to_rectf()),
section: DisplayListSection::Content,
stacking_context_id: StackingContextId::root(),
scroll_root_id: pipeline_id.root_scroll_node(),
clip_and_scroll_info: pipeline_id.root_clip_and_scroll_info(),
}
}
}
@ -1265,8 +1265,12 @@ impl DisplayItem {
}
}
pub fn scroll_root_id(&self) -> ClipId {
self.base().scroll_root_id
pub fn scroll_node_id(&self) -> ClipId {
self.base().clip_and_scroll_info.scroll_node_id
}
pub fn clip_and_scroll_info(&self) -> ClipAndScrollInfo {
self.base().clip_and_scroll_info
}
pub fn stacking_context_id(&self) -> StackingContextId {
@ -1297,7 +1301,7 @@ impl DisplayItem {
// test elements with `border-radius`, for example.
let base_item = self.base();
let scroll_offset = offset_lookup.full_offset_for_scroll_root(&base_item.scroll_root_id);
let scroll_offset = offset_lookup.full_offset_for_scroll_root(&self.scroll_node_id());
let point = Point2D::new(point.x - Au::from_f32_px(scroll_offset.x),
point.y - Au::from_f32_px(scroll_offset.y));