diff options
-rw-r--r-- | components/compositing/compositor.rs | 20 | ||||
-rw-r--r-- | components/compositing/compositor_layer.rs | 8 | ||||
-rw-r--r-- | components/gfx/display_list/mod.rs | 212 | ||||
-rw-r--r-- | components/gfx/paint_task.rs | 17 | ||||
-rw-r--r-- | components/layout/display_list_builder.rs | 52 | ||||
-rw-r--r-- | components/layout/fragment.rs | 6 | ||||
-rw-r--r-- | components/layout/inline.rs | 2 | ||||
-rw-r--r-- | components/msg/compositor_msg.rs | 13 | ||||
-rw-r--r-- | components/servo/Cargo.lock | 2 | ||||
-rw-r--r-- | ports/cef/Cargo.lock | 2 | ||||
-rw-r--r-- | ports/gonk/Cargo.lock | 2 | ||||
-rw-r--r-- | tests/wpt/mozilla/tests/css/stacked_layers.html | 16 | ||||
-rw-r--r-- | tests/wpt/mozilla/tests/css/stacked_layers_ref.html | 10 |
13 files changed, 271 insertions, 91 deletions
diff --git a/components/compositing/compositor.rs b/components/compositing/compositor.rs index dc7d54cfa5e..739cc1ddb44 100644 --- a/components/compositing/compositor.rs +++ b/components/compositing/compositor.rs @@ -670,7 +670,7 @@ impl<Window: WindowMethods> IOCompositor<Window> { scroll_policy: ScrollPolicy::Scrollable, transform: Matrix4::identity(), perspective: Matrix4::identity(), - subpage_layer_info: None, + subpage_pipeline_id: None, establishes_3d_context: true, scrolls_overflow_area: false, }; @@ -819,18 +819,16 @@ impl<Window: WindowMethods> IOCompositor<Window> { } // If this layer contains a subpage, then create the root layer for that subpage now. - if let Some(ref subpage_layer_info) = layer_properties.subpage_layer_info { + if let Some(ref subpage_pipeline_id) = layer_properties.subpage_pipeline_id { let subpage_layer_properties = LayerProperties { id: LayerId::null(), parent_id: None, - rect: Rect::new(Point2D::new(subpage_layer_info.origin.x.to_f32_px(), - subpage_layer_info.origin.y.to_f32_px()), - layer_properties.rect.size), + rect: Rect::new(Point2D::zero(), layer_properties.rect.size), background_color: layer_properties.background_color, scroll_policy: ScrollPolicy::Scrollable, transform: Matrix4::identity(), perspective: Matrix4::identity(), - subpage_layer_info: layer_properties.subpage_layer_info, + subpage_pipeline_id: layer_properties.subpage_pipeline_id, establishes_3d_context: true, scrolls_overflow_area: true, }; @@ -840,13 +838,13 @@ impl<Window: WindowMethods> IOCompositor<Window> { } else { WantsScrollEventsFlag::DoesntWantScrollEvents }; - let subpage_layer = CompositorData::new_layer(subpage_layer_info.pipeline_id, + let subpage_layer = CompositorData::new_layer(*subpage_pipeline_id, subpage_layer_properties, wants_scroll_events, new_layer.tile_size); *subpage_layer.masks_to_bounds.borrow_mut() = true; new_layer.add_child(subpage_layer); - self.pending_subpages.insert(subpage_layer_info.pipeline_id); + self.pending_subpages.insert(*subpage_pipeline_id); } parent_layer.add_child(new_layer.clone()); @@ -871,13 +869,13 @@ impl<Window: WindowMethods> IOCompositor<Window> { /// Sends the size of the given subpage up to the constellation. This will often trigger a /// reflow of that subpage. fn update_subpage_size_if_necessary(&self, layer_properties: &LayerProperties) { - let subpage_layer_info = match layer_properties.subpage_layer_info { - Some(ref subpage_layer_info) => *subpage_layer_info, + let subpage_pipeline_id = match layer_properties.subpage_pipeline_id { + Some(ref subpage_pipeline_id) => subpage_pipeline_id, None => return, }; let ConstellationChan(ref chan) = self.constellation_chan; - chan.send(ConstellationMsg::FrameSize(subpage_layer_info.pipeline_id, + chan.send(ConstellationMsg::FrameSize(*subpage_pipeline_id, layer_properties.rect.size)).unwrap(); } diff --git a/components/compositing/compositor_layer.rs b/components/compositing/compositor_layer.rs index 525135fd208..e3661987a78 100644 --- a/components/compositing/compositor_layer.rs +++ b/components/compositing/compositor_layer.rs @@ -61,9 +61,7 @@ impl CompositorData { requested_epoch: Epoch(0), painted_epoch: Epoch(0), scroll_offset: Point2D::typed(0., 0.), - subpage_info: layer_properties.subpage_layer_info.map(|subpage_layer_info| { - subpage_layer_info.pipeline_id - }), + subpage_info: layer_properties.subpage_pipeline_id, }; Rc::new(Layer::new(Rect::from_untyped(&layer_properties.rect), @@ -485,8 +483,8 @@ impl RcCompositorLayer for Rc<Layer<CompositorData>> { if let Some(layer_pipeline_id) = layer_pipeline_id { for layer_properties in new_layers.iter() { // Keep this layer if a reference to it exists. - if let Some(ref subpage_layer_info) = layer_properties.subpage_layer_info { - if subpage_layer_info.pipeline_id == layer_pipeline_id { + if let Some(ref subpage_pipeline_id) = layer_properties.subpage_pipeline_id { + if *subpage_pipeline_id == layer_pipeline_id { return true } } diff --git a/components/gfx/display_list/mod.rs b/components/gfx/display_list/mod.rs index 07f32519ab9..5fb8b99d990 100644 --- a/components/gfx/display_list/mod.rs +++ b/components/gfx/display_list/mod.rs @@ -23,7 +23,8 @@ use euclid::num::Zero; use euclid::{Matrix2D, Matrix4, Point2D, Rect, SideOffsets2D, Size2D}; use gfx_traits::color; use libc::uintptr_t; -use msg::compositor_msg::{LayerId, LayerKind, ScrollPolicy, SubpageLayerInfo}; +use msg::compositor_msg::{LayerId, LayerKind, ScrollPolicy}; +use msg::constellation_msg::PipelineId; use net_traits::image::base::Image; use paint_context::PaintContext; use paint_task::{PaintLayerContents, PaintLayer}; @@ -88,7 +89,7 @@ pub struct LayerInfo { pub scroll_policy: ScrollPolicy, /// The subpage that this layer represents, if there is one. - pub subpage_layer_info: Option<SubpageLayerInfo>, + pub subpage_pipeline_id: Option<PipelineId>, /// The id for the next layer in the sequence. This is used for synthesizing /// layers for content that needs to be displayed on top of this layer. @@ -98,12 +99,12 @@ pub struct LayerInfo { impl LayerInfo { pub fn new(id: LayerId, scroll_policy: ScrollPolicy, - subpage_layer_info: Option<SubpageLayerInfo>) + subpage_pipeline_id: Option<PipelineId>) -> LayerInfo { LayerInfo { layer_id: id, scroll_policy: scroll_policy, - subpage_layer_info: subpage_layer_info, + subpage_pipeline_id: subpage_pipeline_id, next_layer_id: id.companion_layer_id(), } } @@ -144,6 +145,8 @@ pub struct DisplayList { pub children: LinkedList<Arc<StackingContext>>, /// Child PaintLayers that will be rendered on top of everything else. pub layered_children: LinkedList<Arc<PaintLayer>>, + /// Information about child layers. + pub layer_info: LinkedList<LayerInfo>, } impl DisplayList { @@ -159,6 +162,7 @@ impl DisplayList { outlines: LinkedList::new(), children: LinkedList::new(), layered_children: LinkedList::new(), + layer_info: LinkedList::new(), } } @@ -174,6 +178,7 @@ impl DisplayList { self.outlines.append(&mut other.outlines); self.children.append(&mut other.children); self.layered_children.append(&mut other.layered_children); + self.layer_info.append(&mut other.layer_info); } /// Merges all display items from all non-float stacking levels to the `float` stacking level. @@ -554,6 +559,29 @@ impl DisplayList { bounds } + + #[inline] + fn get_section_mut(&mut self, section: DisplayListSection) -> &mut LinkedList<DisplayItem> { + match section { + DisplayListSection::BackgroundAndBorders => &mut self.background_and_borders, + DisplayListSection::BlockBackgroundsAndBorders => + &mut self.block_backgrounds_and_borders, + DisplayListSection::Floats => &mut self.floats, + DisplayListSection::Content => &mut self.content, + DisplayListSection::PositionedContent => &mut self.positioned_content, + DisplayListSection::Outlines => &mut self.outlines, + } + } +} + +#[derive(Clone, Copy, Debug)] +enum DisplayListSection { + BackgroundAndBorders, + BlockBackgroundsAndBorders, + Floats, + Content, + PositionedContent, + Outlines, } #[derive(HeapSizeOf, Deserialize, Serialize)] @@ -591,6 +619,9 @@ pub struct StackingContext { /// The layer info for this stacking context, if there is any. pub layer_info: Option<LayerInfo>, + + /// The LayerId of the last child layer of this stacking context. + pub last_child_layer_info: Option<LayerInfo>, } impl StackingContext { @@ -620,29 +651,12 @@ impl StackingContext { establishes_3d_context: establishes_3d_context, scrolls_overflow_area: scrolls_overflow_area, layer_info: layer_info, + last_child_layer_info: None, }; StackingContextLayerCreator::add_layers_to_preserve_drawing_order(&mut stacking_context); stacking_context } - pub fn create_layered_child(&self, - layer_info: LayerInfo, - display_list: Box<DisplayList>) -> StackingContext { - StackingContext { - display_list: display_list, - bounds: self.bounds.clone(), - overflow: self.overflow.clone(), - z_index: self.z_index, - filters: self.filters.clone(), - blend_mode: self.blend_mode, - transform: Matrix4::identity(), - perspective: Matrix4::identity(), - establishes_3d_context: false, - scrolls_overflow_area: self.scrolls_overflow_area, - layer_info: Some(layer_info), - } - } - /// Draws the stacking context in the proper order according to the steps in CSS 2.1 § E.2. pub fn draw_into_context(&self, display_list: &DisplayList, @@ -752,11 +766,22 @@ impl StackingContext { None => ScrollPolicy::Scrollable, } } + + fn get_layer_info(&mut self, layer_id: LayerId) -> &mut LayerInfo { + for layer_info in self.display_list.layer_info.iter_mut() { + if layer_info.layer_id == layer_id { + return layer_info; + } + } + + panic!("Could not find LayerInfo with id: {:?}", layer_id); + } } struct StackingContextLayerCreator { display_list_for_next_layer: Option<DisplayList>, next_layer_info: Option<LayerInfo>, + building_ordering_layer: bool, } impl StackingContextLayerCreator { @@ -764,6 +789,7 @@ impl StackingContextLayerCreator { StackingContextLayerCreator { display_list_for_next_layer: None, next_layer_info: None, + building_ordering_layer: false, } } @@ -771,6 +797,15 @@ impl StackingContextLayerCreator { fn add_layers_to_preserve_drawing_order(stacking_context: &mut StackingContext) { let mut state = StackingContextLayerCreator::new(); + state.layerize_display_list_section(DisplayListSection::BackgroundAndBorders, + stacking_context); + state.layerize_display_list_section(DisplayListSection::BlockBackgroundsAndBorders, + stacking_context); + state.layerize_display_list_section(DisplayListSection::Floats, stacking_context); + state.layerize_display_list_section(DisplayListSection::Content, stacking_context); + state.layerize_display_list_section(DisplayListSection::PositionedContent, stacking_context); + state.layerize_display_list_section(DisplayListSection::Outlines, stacking_context); + // First we need to sort child stacking contexts by z-index, so we can detect // situations where unlayered ones should be on top of layered ones. let existing_children = mem::replace(&mut stacking_context.display_list.children, @@ -779,12 +814,12 @@ impl StackingContextLayerCreator { sorted_children.extend(existing_children.into_iter()); sorted_children.sort_by(|this, other| this.z_index.cmp(&other.z_index)); - // FIXME(#7566, mrobinson): This should properly handle unlayered children that are on - // top of unlayered children which have child stacking contexts with layers. for child_stacking_context in sorted_children.into_iter() { state.add_stacking_context(child_stacking_context, stacking_context); } state.finish_building_current_layer(stacking_context); + stacking_context.last_child_layer_info = + StackingContextLayerCreator::find_last_child_layer_info(stacking_context); } #[inline] @@ -793,6 +828,97 @@ impl StackingContextLayerCreator { } #[inline] + fn layerize_display_list_section(&mut self, + section: DisplayListSection, + stacking_context: &mut StackingContext) { + let section_list = stacking_context.display_list.get_section_mut(section).split_off(0); + for item in section_list.into_iter() { + self.add_display_item(item, section, stacking_context); + } + } + + #[inline] + fn display_item_needs_layer(&mut self, item: &DisplayItem) -> bool { + match *item { + LayeredItemClass(_) => true, + _ => self.all_following_children_need_layers(), + } + } + + #[inline] + fn prepare_ordering_layer(&mut self, + stacking_context: &mut StackingContext) { + if self.building_ordering_layer { + assert!(self.next_layer_info.is_some()); + return; + } + + let next_layer_info = Some(stacking_context + .get_layer_info(self.next_layer_info.unwrap().layer_id) + .next_with_scroll_policy(ScrollPolicy::Scrollable)); + self.finish_building_current_layer(stacking_context); + self.next_layer_info = next_layer_info; + + self.building_ordering_layer = true; + } + + fn add_display_item(&mut self, + item: DisplayItem, + section: DisplayListSection, + stacking_context: &mut StackingContext) { + if !self.display_item_needs_layer(&item) { + stacking_context.display_list.get_section_mut(section).push_back(item); + return; + } + + if let LayeredItemClass(ref item) = item { + if let Some(ref next_layer_info) = self.next_layer_info { + if item.layer_id == next_layer_info.layer_id && !self.building_ordering_layer { + return; + } + } + + self.finish_building_current_layer(stacking_context); + self.building_ordering_layer = false; + self.next_layer_info = Some(stacking_context.get_layer_info(item.layer_id).clone()); + } else { + self.prepare_ordering_layer(stacking_context); + } + + match item { + LayeredItemClass(layered_item) => + self.add_display_item_to_display_list(layered_item.item, section), + _ => self.add_display_item_to_display_list(item, section), + } + } + + fn add_display_item_to_display_list(&mut self, + item: DisplayItem, + section: DisplayListSection) { + if self.display_list_for_next_layer.is_none() { + self.display_list_for_next_layer = Some(DisplayList::new()); + } + + if let Some(ref mut display_list) = self.display_list_for_next_layer { + display_list.get_section_mut(section).push_back(item); + } + } + + fn find_last_child_layer_info(stacking_context: &mut StackingContext) -> Option<LayerInfo> { + if let Some(layer) = stacking_context.display_list.layered_children.back() { + return Some(LayerInfo::new(layer.id, ScrollPolicy::Scrollable, None)); + } + + // We only care about the last child, because a layer in a child's hierarchy + // automatically gives following children a layer, so they will be in the + // 'layered_children' list instead of 'children'. + match stacking_context.display_list.children.back() { + Some(child) => child.last_child_layer_info, + None => None, + } + } + + #[inline] fn finish_building_current_layer(&mut self, stacking_context: &mut StackingContext) { if let Some(display_list) = self.display_list_for_next_layer.take() { let layer_info = self.next_layer_info.take().unwrap(); @@ -810,6 +936,15 @@ impl StackingContextLayerCreator { return; } + // This StackingContext has a layered child somewhere in its children. + // We need to give all new StackingContexts their own layer, so that they + // draw on top of this layered child. + if let Some(layer_info) = stacking_context.last_child_layer_info { + self.building_ordering_layer = true; + self.next_layer_info = + Some(layer_info.clone().next_with_scroll_policy(ScrollPolicy::Scrollable)); + } + parent_stacking_context.display_list.children.push_back(stacking_context); } @@ -822,8 +957,10 @@ impl StackingContextLayerCreator { // We have started processing layered stacking contexts, so any stacking context that // we process from now on needs its own layer to ensure proper rendering order. + self.building_ordering_layer = true; self.next_layer_info = Some(layer_info.next_with_scroll_policy(parent_stacking_context.scroll_policy())); + parent_stacking_context.display_list.layered_children.push_back( Arc::new(PaintLayer::new_with_stacking_context(layer_info, stacking_context, @@ -831,6 +968,8 @@ impl StackingContextLayerCreator { return; } + self.prepare_ordering_layer(parent_stacking_context); + if self.display_list_for_next_layer.is_none() { self.display_list_for_next_layer = Some(DisplayList::new()); } @@ -850,6 +989,8 @@ pub enum DisplayItem { GradientClass(Box<GradientDisplayItem>), LineClass(Box<LineDisplayItem>), BoxShadowClass(Box<BoxShadowDisplayItem>), + LayeredItemClass(Box<LayeredItem>), + NoopClass(Box<BaseDisplayItem>), } /// Information common to all display items. @@ -1254,6 +1395,16 @@ pub struct BoxShadowDisplayItem { pub clip_mode: BoxShadowClipMode, } +/// Contains an item that should get its own layer during layer creation. +#[derive(Clone, HeapSizeOf, Deserialize, Serialize)] +pub struct LayeredItem { + /// Fields common to all display items. + pub item: DisplayItem, + + /// The id of the layer this item belongs to. + pub layer_id: LayerId, +} + /// How a box shadow should be clipped. #[derive(Clone, Copy, Debug, PartialEq, HeapSizeOf, Deserialize, Serialize)] pub enum BoxShadowClipMode { @@ -1337,8 +1488,12 @@ impl DisplayItem { box_shadow.color, box_shadow.blur_radius, box_shadow.spread_radius, - box_shadow.clip_mode) + box_shadow.clip_mode); } + + DisplayItem::LayeredItemClass(_) => panic!("Found layered item during drawing."), + + DisplayItem::NoopClass(_) => { } } } @@ -1351,6 +1506,8 @@ impl DisplayItem { DisplayItem::GradientClass(ref gradient) => &gradient.base, DisplayItem::LineClass(ref line) => &line.base, DisplayItem::BoxShadowClass(ref box_shadow) => &box_shadow.base, + DisplayItem::LayeredItemClass(ref layered_item) => layered_item.item.base(), + DisplayItem::NoopClass(ref base_item) => base_item, } } @@ -1363,6 +1520,8 @@ impl DisplayItem { DisplayItem::GradientClass(ref mut gradient) => &mut gradient.base, DisplayItem::LineClass(ref mut line) => &mut line.base, DisplayItem::BoxShadowClass(ref mut box_shadow) => &mut box_shadow.base, + DisplayItem::LayeredItemClass(ref mut layered_item) => layered_item.item.mut_base(), + DisplayItem::NoopClass(ref mut base_item) => base_item, } } @@ -1395,6 +1554,9 @@ impl fmt::Debug for DisplayItem { DisplayItem::GradientClass(_) => "Gradient".to_owned(), DisplayItem::LineClass(_) => "Line".to_owned(), DisplayItem::BoxShadowClass(_) => "BoxShadow".to_owned(), + DisplayItem::LayeredItemClass(ref layered_item) => + format!("LayeredItem({:?})", layered_item.item), + DisplayItem::NoopClass(_) => "Noop".to_owned(), }, self.base().bounds, self.base().metadata.node.id() diff --git a/components/gfx/paint_task.rs b/components/gfx/paint_task.rs index 0c58155ab2d..e33432caf57 100644 --- a/components/gfx/paint_task.rs +++ b/components/gfx/paint_task.rs @@ -19,11 +19,10 @@ use gfx_traits::color; use ipc_channel::ipc::IpcSender; use layers::layers::{BufferRequest, LayerBuffer, LayerBufferSet}; use layers::platform::surface::{NativeDisplay, NativeSurface}; -use msg::compositor_msg::{Epoch, FrameTreeId, LayerId, LayerKind, LayerProperties, PaintListener}; -use msg::compositor_msg::{ScrollPolicy, SubpageLayerInfo}; +use msg::compositor_msg::{Epoch, FrameTreeId, LayerId, LayerKind, LayerProperties}; +use msg::compositor_msg::{PaintListener, ScrollPolicy}; use msg::constellation_msg::Msg as ConstellationMsg; -use msg::constellation_msg::PipelineExitType; -use msg::constellation_msg::{ConstellationChan, Failure, PipelineId}; +use msg::constellation_msg::{ConstellationChan, Failure, PipelineExitType, PipelineId}; use paint_context::PaintContext; use profile_traits::mem::{self, ReportsChan}; use profile_traits::time::{self, profile}; @@ -60,8 +59,8 @@ pub struct PaintLayer { pub bounds: Rect<Au>, /// The scrolling policy of this layer. pub scroll_policy: ScrollPolicy, - /// The subpage that this layer represents, if there is one. - pub subpage_layer_info: Option<SubpageLayerInfo>, + /// The pipeline of the subpage that this layer represents, if there is one. + pub subpage_pipeline_id: Option<PipelineId>, } impl PaintLayer { @@ -78,7 +77,7 @@ impl PaintLayer { contents: PaintLayerContents::StackingContext(stacking_context), bounds: bounds, scroll_policy: layer_info.scroll_policy, - subpage_layer_info: layer_info.subpage_layer_info, + subpage_pipeline_id: layer_info.subpage_pipeline_id, } } @@ -93,7 +92,7 @@ impl PaintLayer { contents: PaintLayerContents::DisplayList(Arc::new(display_list)), bounds: bounds, scroll_policy: layer_info.scroll_policy, - subpage_layer_info: layer_info.subpage_layer_info, + subpage_pipeline_id: layer_info.subpage_pipeline_id, } } @@ -149,7 +148,7 @@ impl PaintLayer { perspective: perspective, establishes_3d_context: establishes_3d_context, scrolls_overflow_area: scrolls_overflow_area, - subpage_layer_info: self.subpage_layer_info, + subpage_pipeline_id: self.subpage_pipeline_id, } } diff --git a/components/layout/display_list_builder.rs b/components/layout/display_list_builder.rs index 299f0155e4d..37a3a543794 100644 --- a/components/layout/display_list_builder.rs +++ b/components/layout/display_list_builder.rs @@ -15,6 +15,7 @@ use azure::azure_hl::Color; use block::BlockFlow; use canvas_traits::{CanvasMsg, FromLayoutMsg}; use context::LayoutContext; +use euclid::num::Zero; use euclid::{Matrix4, Point2D, Point3D, Rect, SideOffsets2D, Size2D}; use flex::FlexFlow; use flow::{self, BaseFlow, Flow, IS_ABSOLUTELY_POSITIONED}; @@ -25,8 +26,8 @@ use gfx::display_list::{BLUR_INFLATION_FACTOR, BaseDisplayItem, BorderDisplayIte use gfx::display_list::{BorderRadii, BoxShadowClipMode, BoxShadowDisplayItem, ClippingRegion}; use gfx::display_list::{DisplayItem, DisplayItemMetadata, DisplayList}; use gfx::display_list::{GradientDisplayItem}; -use gfx::display_list::{GradientStop, ImageDisplayItem, LayerInfo, LineDisplayItem}; -use gfx::display_list::{OpaqueNode, SolidColorDisplayItem}; +use gfx::display_list::{GradientStop, ImageDisplayItem, LayeredItem, LayerInfo}; +use gfx::display_list::{LineDisplayItem, OpaqueNode, SolidColorDisplayItem}; use gfx::display_list::{StackingContext, TextDisplayItem, TextOrientation}; use gfx::paint_task::THREAD_TINT_COLORS; use gfx::text::glyph::CharIndex; @@ -35,7 +36,7 @@ use inline::{FIRST_FRAGMENT_OF_ELEMENT, InlineFlow, LAST_FRAGMENT_OF_ELEMENT}; use ipc_channel::ipc::{self, IpcSharedMemory}; use list_item::ListItemFlow; use model::{self, MaybeAuto, ToGfxMatrix}; -use msg::compositor_msg::{ScrollPolicy, SubpageLayerInfo}; +use msg::compositor_msg::ScrollPolicy; use net_traits::image::base::{Image, PixelFormat}; use net_traits::image_cache_task::UsePlaceholder; use std::default::Default; @@ -1098,7 +1099,6 @@ impl FragmentDisplayListBuilding for Fragment { } SpecificFragmentInfo::Generic | SpecificFragmentInfo::GeneratedContent(..) | - SpecificFragmentInfo::Iframe(..) | SpecificFragmentInfo::Table | SpecificFragmentInfo::TableCell | SpecificFragmentInfo::TableRow | @@ -1112,6 +1112,27 @@ impl FragmentDisplayListBuilding for Fragment { clip); } } + SpecificFragmentInfo::Iframe(ref fragment_info) => { + // TODO(mrobinson): When https://github.com/servo/euclid/issues/109 is fixed this + // check can just become stacking_relative_content_box.is_empty(). + if stacking_relative_content_box.size.width != Zero::zero() && + stacking_relative_content_box.size.height != Zero::zero() { + let layer_id = self.layer_id(); + display_list.content.push_back(DisplayItem::LayeredItemClass(box LayeredItem { + item: DisplayItem::NoopClass( + box BaseDisplayItem::new(stacking_relative_content_box, + DisplayItemMetadata::new(self.node, + &*self.style, + Cursor::DefaultCursor), + (*clip).clone())), + layer_id: layer_id + })); + + display_list.layer_info.push_back(LayerInfo::new(layer_id, + ScrollPolicy::Scrollable, + Some(fragment_info.pipeline_id))); + } + } SpecificFragmentInfo::Image(ref mut image_fragment) => { // Place the image into the display list. if let Some(ref image) = image_fragment.image { @@ -1284,19 +1305,8 @@ impl FragmentDisplayListBuilding for Fragment { filters.push(Filter::Opacity(effects.opacity)) } - let subpage_layer_info = match self.specific { - SpecificFragmentInfo::Iframe(ref iframe_fragment_info) => { - let border_padding = self.border_padding.to_physical(self.style().writing_mode); - Some(SubpageLayerInfo { - pipeline_id: iframe_fragment_info.pipeline_id, - origin: Point2D::new(border_padding.left, border_padding.top), - }) - } - _ => None, - }; - - let canvas_or_iframe = match self.specific { - SpecificFragmentInfo::Canvas(_) | SpecificFragmentInfo::Iframe(_) => true, + let canvas = match self.specific { + SpecificFragmentInfo::Canvas(_) => true, _ => false }; @@ -1304,11 +1314,9 @@ impl FragmentDisplayListBuilding for Fragment { // flag, when this is a canvas or iframe fragment, 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, - subpage_layer_info)) - } else if self.flags.contains(HAS_LAYER) || canvas_or_iframe { - Some(LayerInfo::new(self.layer_id(), scroll_policy, subpage_layer_info)) + Some(LayerInfo::new(self.layer_id_for_overflow_scroll(), scroll_policy, None)) + } else if self.flags.contains(HAS_LAYER) || canvas { + Some(LayerInfo::new(self.layer_id(), scroll_policy, None)) } else { None }; diff --git a/components/layout/fragment.rs b/components/layout/fragment.rs index 308532d9768..3623e1c5d76 100644 --- a/components/layout/fragment.rs +++ b/components/layout/fragment.rs @@ -2107,11 +2107,11 @@ impl Fragment { } /// Returns true if this fragment unconditionally layerizes. - pub fn needs_layer(&self) -> bool { + pub fn needs_layered_stacking_context(&self) -> bool { // Canvas and iframes always layerize, as an special case // FIXME(pcwalton): Don't unconditionally form stacking contexts for each canvas. match self.specific { - SpecificFragmentInfo::Canvas(_) | SpecificFragmentInfo::Iframe(_) => true, + SpecificFragmentInfo::Canvas(_) => true, _ => false, } } @@ -2140,7 +2140,7 @@ impl Fragment { transform_style::T::auto => {} } - if self.needs_layer() { + if self.needs_layered_stacking_context() { return true } diff --git a/components/layout/inline.rs b/components/layout/inline.rs index d6704405e1b..dbe61662b12 100644 --- a/components/layout/inline.rs +++ b/components/layout/inline.rs @@ -1496,7 +1496,7 @@ impl Flow for InlineFlow { for fragment_index in line.range.each_index() { let fragment = &mut self.fragments.fragments[fragment_index.to_usize()]; - if fragment.needs_layer() && !fragment.is_positioned() { + if fragment.needs_layered_stacking_context() && !fragment.is_positioned() { layers_needed_for_descendants = true } diff --git a/components/msg/compositor_msg.rs b/components/msg/compositor_msg.rs index 8c411148c9a..e7612351724 100644 --- a/components/msg/compositor_msg.rs +++ b/components/msg/compositor_msg.rs @@ -2,7 +2,6 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -use app_units::Au; use azure::azure_hl::Color; use constellation_msg::{Key, KeyModifiers, KeyState, PipelineId}; use euclid::{Matrix4, Point2D, Rect, Size2D}; @@ -120,7 +119,7 @@ pub struct LayerProperties { pub perspective: Matrix4, /// The subpage that this layer represents. If this is `Some`, this layer represents an /// iframe. - pub subpage_layer_info: Option<SubpageLayerInfo>, + pub subpage_pipeline_id: Option<PipelineId>, /// Whether this layer establishes a new 3d rendering context. pub establishes_3d_context: bool, /// Whether this layer scrolls its overflow area. @@ -163,13 +162,3 @@ pub enum ScriptToCompositorMsg { ResizeTo(Size2D<u32>), Exit, } - -/// Subpage (i.e. iframe)-specific information about each layer. -#[derive(Clone, Copy, Debug, Deserialize, Serialize, HeapSizeOf)] -pub struct SubpageLayerInfo { - /// The ID of the pipeline. - pub pipeline_id: PipelineId, - /// The offset of the subpage within this layer (to account for borders). - pub origin: Point2D<Au>, -} - diff --git a/components/servo/Cargo.lock b/components/servo/Cargo.lock index 20c56d42776..81b62bf7a1f 100644 --- a/components/servo/Cargo.lock +++ b/components/servo/Cargo.lock @@ -978,7 +978,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "layers" version = "0.1.0" -source = "git+https://github.com/servo/rust-layers#497a54e403ff737c35e47b29c664ed8ae8ee26cf" +source = "git+https://github.com/servo/rust-layers#5af8c6bb9801e4f8d337c6a74a0bb2641ab48e0e" dependencies = [ "azure 0.1.0 (git+https://github.com/servo/rust-azure)", "cgl 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/ports/cef/Cargo.lock b/ports/cef/Cargo.lock index b92931c5a7c..04a658e73fe 100644 --- a/ports/cef/Cargo.lock +++ b/ports/cef/Cargo.lock @@ -928,7 +928,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "layers" version = "0.1.0" -source = "git+https://github.com/servo/rust-layers#497a54e403ff737c35e47b29c664ed8ae8ee26cf" +source = "git+https://github.com/servo/rust-layers#5af8c6bb9801e4f8d337c6a74a0bb2641ab48e0e" dependencies = [ "azure 0.1.0 (git+https://github.com/servo/rust-azure)", "cgl 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/ports/gonk/Cargo.lock b/ports/gonk/Cargo.lock index c5b2291d0d8..ef5b60b87ad 100644 --- a/ports/gonk/Cargo.lock +++ b/ports/gonk/Cargo.lock @@ -808,7 +808,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "layers" version = "0.1.0" -source = "git+https://github.com/servo/rust-layers#497a54e403ff737c35e47b29c664ed8ae8ee26cf" +source = "git+https://github.com/servo/rust-layers#5af8c6bb9801e4f8d337c6a74a0bb2641ab48e0e" dependencies = [ "azure 0.1.0 (git+https://github.com/servo/rust-azure)", "cgl 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/tests/wpt/mozilla/tests/css/stacked_layers.html b/tests/wpt/mozilla/tests/css/stacked_layers.html index a0edbaf667c..d135ab144cd 100644 --- a/tests/wpt/mozilla/tests/css/stacked_layers.html +++ b/tests/wpt/mozilla/tests/css/stacked_layers.html @@ -8,6 +8,7 @@ .gray { background: rgb(200, 200, 200); } .grayer { background: rgb(80, 80, 80); } .grayest { background: rgb(0, 0, 0); } + iframe { display: block; border: 0; } </style> </head> <body> @@ -27,5 +28,20 @@ <div class="grayer box" style="margin-left: 10px; margin-top: 10px; opacity: 0.999; z-index: -1;"></div> <div class="gray box" style="margin-left: 20px; margin-top: -40px; opacity: 0.999;"> </div> </div> + + <!-- The iframe should be painted in tree order since it is not positioned and + the following div is. --> + <div class="test grayest box"> + <iframe class="box" style="margin-left: 10px; margin-top: 10px;" src="data:text/html;charset=utf-8;base64,PGh0bWw+PGJvZHkgc3R5bGU9ImJhY2tncm91bmQ6IHJnYig4MCwgODAsIDgwKTsiPjwvYm9keT48L2Rpdj4="></iframe> + <div class="gray box" style="position: relative; left: 20px; top: -40px;"> </div> + </div> + + <!-- The iframe should be painted in tree order since both it and the inner div are + not positioned elements. --> + <div class="test grayest box"> + <iframe class="box" style="position: relative; left: 10px; top: 10px;" src="data:text/html;charset=utf-8;base64,PGh0bWw+PGJvZHkgc3R5bGU9ImJhY2tncm91bmQ6IHJnYig4MCwgODAsIDgwKTsiPjwvYm9keT48L2Rpdj4="></iframe> + <div class="gray box" style="position: relative; left: 20px; top: -30px;"> </div> + </div> + </body> </html> diff --git a/tests/wpt/mozilla/tests/css/stacked_layers_ref.html b/tests/wpt/mozilla/tests/css/stacked_layers_ref.html index fbec3c30c7d..a166e23cae7 100644 --- a/tests/wpt/mozilla/tests/css/stacked_layers_ref.html +++ b/tests/wpt/mozilla/tests/css/stacked_layers_ref.html @@ -24,5 +24,15 @@ <div class="grayer box" style="margin-left: 10px; margin-top: 10px; position: absolute; opacity: 0.999;"></div> <div class="gray box" style="margin-left: 20px; margin-top: 20px; position: relative; opacity: 0.999;"></div> </div> + + <div class="test grayest box"> + <div class="grayer box" style="margin-left: 10px; margin-top: 10px;"></div> + <div class="gray box" style="margin-left: 20px; margin-top: -40px;"></div> + </div> + + <div class="test grayest box"> + <div class="grayer box" style="margin-left: 10px; margin-top: 10px;"></div> + <div class="gray box" style="margin-left: 20px; margin-top: -40px;"></div> + </div> </body> </html> |