diff --git a/Cargo.lock b/Cargo.lock index 418864bc117..654f6bf2b08 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2721,6 +2721,7 @@ dependencies = [ "app_units", "atomic_refcell", "cssparser", + "embedder_traits", "euclid", "gfx", "gfx_traits", diff --git a/components/layout_2020/Cargo.toml b/components/layout_2020/Cargo.toml index 1d76d00af79..4fd783a66bc 100644 --- a/components/layout_2020/Cargo.toml +++ b/components/layout_2020/Cargo.toml @@ -16,6 +16,7 @@ doctest = false app_units = "0.7" atomic_refcell = "0.1" cssparser = "0.27" +embedder_traits = {path = "../embedder_traits"} euclid = "0.20" gfx = {path = "../gfx"} gfx_traits = {path = "../gfx_traits"} diff --git a/components/layout_2020/display_list.rs b/components/layout_2020/display_list.rs index dabdb32b88b..f39a2f23b18 100644 --- a/components/layout_2020/display_list.rs +++ b/components/layout_2020/display_list.rs @@ -4,9 +4,11 @@ use crate::fragments::{BoxFragment, Fragment}; use crate::geom::physical::{Rect, Vec2}; +use embedder_traits::Cursor; use euclid::{Point2D, SideOffsets2D}; use gfx::text::glyph::GlyphStore; use std::sync::Arc; +use style::properties::ComputedValues; use style::values::computed::{BorderStyle, Length}; use webrender_api::{self as wr, units, CommonItemProperties, PrimitiveFlags}; @@ -58,11 +60,12 @@ impl Fragment { .translate(&containing_block.top_left); let mut baseline_origin = rect.top_left.clone(); baseline_origin.y += t.ascent; + let cursor = cursor(&t.parent_style, Cursor::Text); let common = CommonItemProperties { clip_rect: rect.clone().into(), clip_id: wr::ClipId::root(builder.pipeline_id), spatial_id: wr::SpatialId::root_scroll_node(builder.pipeline_id), - hit_info: None, + hit_info: cursor.map(|cursor| (t.tag.0 as u64, cursor as u16)), // TODO(gw): Make use of the WR backface visibility functionality. flags: PrimitiveFlags::default(), }; @@ -119,11 +122,12 @@ impl BoxFragment { .to_physical(self.style.writing_mode, containing_block) .translate(&containing_block.top_left) .into(); + let cursor = cursor(&self.style, Cursor::Default); let common = CommonItemProperties { clip_rect: border_rect, clip_id: wr::ClipId::root(builder.pipeline_id), spatial_id: wr::SpatialId::root_scroll_node(builder.pipeline_id), - hit_info: None, + hit_info: cursor.map(|cursor| (self.tag.0 as u64, cursor as u16)), // TODO(gw): Make use of the WR backface visibility functionality. flags: PrimitiveFlags::default(), }; @@ -147,7 +151,7 @@ impl BoxFragment { let background_color = self .style .resolve_color(self.style.clone_background_color()); - if background_color.alpha > 0 { + if background_color.alpha > 0 || common.hit_info.is_some() { builder.wr.push_rect(common, rgba(background_color)) } } @@ -228,3 +232,51 @@ fn glyphs(glyph_runs: &[Arc], mut origin: Vec2) -> Vec Option { + use style::computed_values::pointer_events::T as PointerEvents; + use style::values::specified::ui::CursorKind; + + let inherited_ui = values.get_inherited_ui(); + if inherited_ui.pointer_events == PointerEvents::None { + return None; + } + Some(match inherited_ui.cursor.keyword { + CursorKind::Auto => default, + CursorKind::None => Cursor::None, + CursorKind::Default => Cursor::Default, + CursorKind::Pointer => Cursor::Pointer, + CursorKind::ContextMenu => Cursor::ContextMenu, + CursorKind::Help => Cursor::Help, + CursorKind::Progress => Cursor::Progress, + CursorKind::Wait => Cursor::Wait, + CursorKind::Cell => Cursor::Cell, + CursorKind::Crosshair => Cursor::Crosshair, + CursorKind::Text => Cursor::Text, + CursorKind::VerticalText => Cursor::VerticalText, + CursorKind::Alias => Cursor::Alias, + CursorKind::Copy => Cursor::Copy, + CursorKind::Move => Cursor::Move, + CursorKind::NoDrop => Cursor::NoDrop, + CursorKind::NotAllowed => Cursor::NotAllowed, + CursorKind::Grab => Cursor::Grab, + CursorKind::Grabbing => Cursor::Grabbing, + CursorKind::EResize => Cursor::EResize, + CursorKind::NResize => Cursor::NResize, + CursorKind::NeResize => Cursor::NeResize, + CursorKind::NwResize => Cursor::NwResize, + CursorKind::SResize => Cursor::SResize, + CursorKind::SeResize => Cursor::SeResize, + CursorKind::SwResize => Cursor::SwResize, + CursorKind::WResize => Cursor::WResize, + CursorKind::EwResize => Cursor::EwResize, + CursorKind::NsResize => Cursor::NsResize, + CursorKind::NeswResize => Cursor::NeswResize, + CursorKind::NwseResize => Cursor::NwseResize, + CursorKind::ColResize => Cursor::ColResize, + CursorKind::RowResize => Cursor::RowResize, + CursorKind::AllScroll => Cursor::AllScroll, + CursorKind::ZoomIn => Cursor::ZoomIn, + CursorKind::ZoomOut => Cursor::ZoomOut, + }) +} diff --git a/components/layout_2020/dom_traversal.rs b/components/layout_2020/dom_traversal.rs index 56ee72d67ca..5ccf8310d53 100644 --- a/components/layout_2020/dom_traversal.rs +++ b/components/layout_2020/dom_traversal.rs @@ -14,7 +14,7 @@ use script_layout_interface::wrapper_traits::{LayoutNode, ThreadSafeLayoutNode}; use servo_arc::Arc as ServoArc; use std::marker::PhantomData as marker; use std::sync::Arc; -use style::dom::TNode; +use style::dom::{OpaqueNode, TNode}; use style::properties::ComputedValues; use style::selector_parser::PseudoElement; @@ -24,9 +24,9 @@ pub enum WhichPseudoElement { After, } -pub(super) enum Contents { +pub(super) enum Contents { /// Refers to a DOM subtree, plus `::before` and `::after` pseudo-elements. - OfElement(Node), + OfElement, /// Example: an `` element. /// @@ -37,8 +37,8 @@ pub(super) enum Contents { OfPseudoElement(Vec), } -pub(super) enum NonReplacedContents { - OfElement(Node), +pub(super) enum NonReplacedContents { + OfElement, OfPseudoElement(Vec), } @@ -51,14 +51,15 @@ pub(super) trait TraversalHandler<'dom, Node> where Node: 'dom, { - fn handle_text(&mut self, text: String, parent_style: &ServoArc); + fn handle_text(&mut self, node: Node, text: String, parent_style: &ServoArc); /// Or pseudo-element fn handle_element( &mut self, + node: Node, style: &ServoArc, display: DisplayGeneratingBox, - contents: Contents, + contents: Contents, box_slot: BoxSlot<'dom>, ); } @@ -75,7 +76,7 @@ fn traverse_children_of<'dom, Node>( let mut next = parent_element.first_child(); while let Some(child) = next { if let Some(contents) = child.as_text() { - handler.handle_text(contents, &child.style(context)); + handler.handle_text(child, contents, &child.style(context)); } else if child.is_element() { traverse_element(child, context, handler); } @@ -108,9 +109,10 @@ fn traverse_element<'dom, Node>( }, Display::GeneratingBox(display) => { handler.handle_element( + element, &style, display, - replaced.map_or(Contents::OfElement(element), Contents::Replaced), + replaced.map_or(Contents::OfElement, Contents::Replaced), element.element_box_slot(), ); }, @@ -131,19 +133,20 @@ fn traverse_pseudo_element<'dom, Node>( Display::Contents => { element.unset_pseudo_element_box(which); let items = generate_pseudo_element_content(&style, element, context); - traverse_pseudo_element_contents(&style, context, handler, items); + traverse_pseudo_element_contents(element, &style, context, handler, items); }, Display::GeneratingBox(display) => { let items = generate_pseudo_element_content(&style, element, context); let contents = Contents::OfPseudoElement(items); let box_slot = element.pseudo_element_box_slot(which); - handler.handle_element(&style, display, contents, box_slot); + handler.handle_element(element, &style, display, contents, box_slot); }, } } } fn traverse_pseudo_element_contents<'dom, Node>( + node: Node, pseudo_element_style: &ServoArc, context: &LayoutContext, handler: &mut impl TraversalHandler<'dom, Node>, @@ -154,7 +157,9 @@ fn traverse_pseudo_element_contents<'dom, Node>( let mut anonymous_style = None; for item in items { match item { - PseudoElementContentItem::Text(text) => handler.handle_text(text, pseudo_element_style), + PseudoElementContentItem::Text(text) => { + handler.handle_text(node, text, pseudo_element_style) + }, PseudoElementContentItem::Replaced(contents) => { let item_style = anonymous_style.get_or_insert_with(|| { context @@ -176,6 +181,7 @@ fn traverse_pseudo_element_contents<'dom, Node>( Display::GeneratingBox(display_inline) ); handler.handle_element( + node, item_style, display_inline, Contents::Replaced(contents), @@ -187,51 +193,51 @@ fn traverse_pseudo_element_contents<'dom, Node>( } } -impl Contents { +impl Contents { /// Returns true iff the `try_from` impl below would return `Err(_)` pub fn is_replaced(&self) -> bool { match self { - Contents::OfElement(_) | Contents::OfPseudoElement(_) => false, + Contents::OfElement | Contents::OfPseudoElement(_) => false, Contents::Replaced(_) => true, } } } -impl std::convert::TryFrom> for NonReplacedContents { +impl std::convert::TryFrom for NonReplacedContents { type Error = ReplacedContent; - fn try_from(contents: Contents) -> Result { + fn try_from(contents: Contents) -> Result { match contents { - Contents::OfElement(node) => Ok(NonReplacedContents::OfElement(node)), + Contents::OfElement => Ok(NonReplacedContents::OfElement), Contents::OfPseudoElement(items) => Ok(NonReplacedContents::OfPseudoElement(items)), Contents::Replaced(replaced) => Err(replaced), } } } -impl std::convert::From> for Contents { - fn from(contents: NonReplacedContents) -> Self { +impl From for Contents { + fn from(contents: NonReplacedContents) -> Self { match contents { - NonReplacedContents::OfElement(node) => Contents::OfElement(node), + NonReplacedContents::OfElement => Contents::OfElement, NonReplacedContents::OfPseudoElement(items) => Contents::OfPseudoElement(items), } } } -impl<'dom, Node> NonReplacedContents -where - Node: NodeExt<'dom>, -{ - pub(crate) fn traverse( +impl NonReplacedContents { + pub(crate) fn traverse<'dom, Node>( self, - inherited_style: &ServoArc, context: &LayoutContext, + node: Node, + inherited_style: &ServoArc, handler: &mut impl TraversalHandler<'dom, Node>, - ) { + ) where + Node: NodeExt<'dom>, + { match self { - NonReplacedContents::OfElement(node) => traverse_children_of(node, context, handler), + NonReplacedContents::OfElement => traverse_children_of(node, context, handler), NonReplacedContents::OfPseudoElement(items) => { - traverse_pseudo_element_contents(inherited_style, context, handler, items) + traverse_pseudo_element_contents(node, inherited_style, context, handler, items) }, } } @@ -307,6 +313,7 @@ pub(crate) trait NodeExt<'dom>: 'dom + Copy + LayoutNode + Send + Sync { fn parent_node(self) -> Option; fn style(self, context: &LayoutContext) -> ServoArc; + fn as_opaque(self) -> OpaqueNode; fn layout_data_mut(&self) -> AtomicRefMut; fn element_box_slot(&self) -> BoxSlot<'dom>; fn pseudo_element_box_slot(&self, which: WhichPseudoElement) -> BoxSlot<'dom>; @@ -366,6 +373,10 @@ where self.to_threadsafe().style(context.shared_context()) } + fn as_opaque(self) -> OpaqueNode { + self.opaque() + } + fn layout_data_mut(&self) -> AtomicRefMut { self.get_raw_data() .map(|d| d.layout_data.borrow_mut()) diff --git a/components/layout_2020/flow/construct.rs b/components/layout_2020/flow/construct.rs index 25b401e5592..cff3fa281a6 100644 --- a/components/layout_2020/flow/construct.rs +++ b/components/layout_2020/flow/construct.rs @@ -22,12 +22,13 @@ use style::selector_parser::PseudoElement; impl BlockFormattingContext { pub fn construct<'dom>( context: &LayoutContext, + node: impl NodeExt<'dom>, style: &Arc, - contents: NonReplacedContents>, + contents: NonReplacedContents, content_sizes: ContentSizesRequest, ) -> (Self, BoxContentSizes) { let (contents, contains_floats, inline_content_sizes) = - BlockContainer::construct(context, style, contents, content_sizes); + BlockContainer::construct(context, node, style, contents, content_sizes); // FIXME: add contribution to `inline_content_sizes` of floats in this formatting context // https://dbaron.org/css/intrinsic/#intrinsic let bfc = Self { @@ -38,25 +39,26 @@ impl BlockFormattingContext { } } -enum IntermediateBlockLevelBox { - SameFormattingContextBlock { - style: Arc, - contents: IntermediateBlockContainer, - }, +struct BlockLevelJob<'dom, Node> { + node: Node, + box_slot: BoxSlot<'dom>, + style: Arc, + kind: BlockLevelCreator, +} + +enum BlockLevelCreator { + SameFormattingContextBlock(IntermediateBlockContainer), Independent { - style: Arc, display_inside: DisplayInside, - contents: Contents, + contents: Contents, }, OutOfFlowAbsolutelyPositionedBox { - style: Arc, display_inside: DisplayInside, - contents: Contents, + contents: Contents, }, OutOfFlowFloatBox { - style: Arc, display_inside: DisplayInside, - contents: Contents, + contents: Contents, }, } @@ -67,9 +69,9 @@ enum IntermediateBlockLevelBox { /// of a given element. /// /// Deferring allows using rayon’s `into_par_iter`. -enum IntermediateBlockContainer { +enum IntermediateBlockContainer { InlineFormattingContext(InlineFormattingContext), - Deferred { contents: NonReplacedContents }, + Deferred(NonReplacedContents), } /// A builder for a block container. @@ -79,11 +81,13 @@ enum IntermediateBlockContainer { struct BlockContainerBuilder<'dom, 'style, Node> { context: &'style LayoutContext<'style>, + root: Node, + block_container_style: &'style Arc, - /// The list of block-level boxes of the final block container. + /// The list of block-level boxes to be built for the final block container. /// - /// Contains all the complete block level boxes we found traversing the tree + /// Contains all the block-level jobs we found traversing the tree /// so far, if this is empty at the end of the traversal and the ongoing /// inline formatting context is not empty, the block container establishes /// an inline formatting context (see end of `build`). @@ -94,7 +98,7 @@ struct BlockContainerBuilder<'dom, 'style, Node> { /// doesn't have a next sibling, we either reached the end of the container /// root or there are ongoing inline-level boxes /// (see `handle_block_level_element`). - block_level_boxes: Vec<(IntermediateBlockLevelBox, BoxSlot<'dom>)>, + block_level_boxes: Vec>, /// The ongoing inline formatting context of the builder. /// @@ -131,12 +135,14 @@ struct BlockContainerBuilder<'dom, 'style, Node> { impl BlockContainer { pub fn construct<'dom>( context: &LayoutContext, + root: impl NodeExt<'dom>, block_container_style: &Arc, - contents: NonReplacedContents>, + contents: NonReplacedContents, content_sizes: ContentSizesRequest, ) -> (BlockContainer, ContainsFloats, BoxContentSizes) { let mut builder = BlockContainerBuilder { context, + root, block_container_style, block_level_boxes: Vec::new(), ongoing_inline_formatting_context: InlineFormattingContext::default(), @@ -145,7 +151,7 @@ impl BlockContainer { contains_floats: ContainsFloats::No, }; - contents.traverse(block_container_style, context, &mut builder); + contents.traverse(context, root, block_container_style, &mut builder); debug_assert!(builder.ongoing_inline_boxes_stack.is_empty()); @@ -176,17 +182,14 @@ impl BlockContainer { contains_floats: builder.contains_floats, outer_content_sizes_of_children: ContentSizes::zero(), }; - let mapfold = - |acc: &mut Accumulator, - (intermediate, box_slot): (IntermediateBlockLevelBox<_>, BoxSlot<'_>)| { - let (block_level_box, box_contains_floats) = intermediate.finish( - context, - content_sizes.if_requests_inline(|| &mut acc.outer_content_sizes_of_children), - ); - acc.contains_floats |= box_contains_floats; - box_slot.set(LayoutBox::BlockLevel(block_level_box.clone())); - block_level_box - }; + let mapfold = |acc: &mut Accumulator, creator: BlockLevelJob<'dom, _>| { + let (block_level_box, box_contains_floats) = creator.finish( + context, + content_sizes.if_requests_inline(|| &mut acc.outer_content_sizes_of_children), + ); + acc.contains_floats |= box_contains_floats; + block_level_box + }; let block_level_boxes = if context.use_rayon { builder .block_level_boxes @@ -231,15 +234,16 @@ where { fn handle_element( &mut self, + node: Node, style: &Arc, display: DisplayGeneratingBox, - contents: Contents, + contents: Contents, box_slot: BoxSlot<'dom>, ) { match display { DisplayGeneratingBox::OutsideInside { outside, inside } => match outside { DisplayOutside::Inline => box_slot.set(LayoutBox::InlineLevel( - self.handle_inline_level_element(style, inside, contents), + self.handle_inline_level_element(node, style, inside, contents), )), DisplayOutside::Block => { let box_style = style.get_box(); @@ -247,22 +251,29 @@ where // https://drafts.csswg.org/css2/visuren.html#dis-pos-flo if box_style.position.is_absolutely_positioned() { self.handle_absolutely_positioned_element( + node, style.clone(), inside, contents, box_slot, ) } else if box_style.float.is_floating() { - self.handle_float_element(style.clone(), inside, contents, box_slot) + self.handle_float_element(node, style.clone(), inside, contents, box_slot) } else { - self.handle_block_level_element(style.clone(), inside, contents, box_slot) + self.handle_block_level_element( + node, + style.clone(), + inside, + contents, + box_slot, + ) } }, }, } } - fn handle_text(&mut self, input: String, parent_style: &Arc) { + fn handle_text(&mut self, node: Node, input: String, parent_style: &Arc) { let (leading_whitespace, mut input) = self.handle_leading_whitespace(&input); if leading_whitespace || !input.is_empty() { // This text node should be pushed either to the next ongoing @@ -319,6 +330,7 @@ where if let Some(text) = new_text_run_contents { let parent_style = parent_style.clone(); inlines.push(Arc::new(InlineLevelBox::TextRun(TextRun { + tag: node.as_opaque(), parent_style, text, }))) @@ -368,15 +380,17 @@ where fn handle_inline_level_element( &mut self, + node: Node, style: &Arc, display_inside: DisplayInside, - contents: Contents, + contents: Contents, ) -> Arc { let box_ = if display_inside == DisplayInside::Flow && !contents.is_replaced() { // We found un inline box. // Whatever happened before, all we need to do before recurring // is to remember this ongoing inline level box. self.ongoing_inline_boxes_stack.push(InlineBox { + tag: node.as_opaque(), style: style.clone(), first_fragment: true, last_fragment: false, @@ -384,9 +398,12 @@ where }); // `unwrap` doesn’t panic here because `is_replaced` returned `false`. - NonReplacedContents::try_from(contents) - .unwrap() - .traverse(&style, self.context, self); + NonReplacedContents::try_from(contents).unwrap().traverse( + self.context, + node, + &style, + self, + ); let mut inline_box = self .ongoing_inline_boxes_stack @@ -398,6 +415,7 @@ where Arc::new(InlineLevelBox::Atomic( IndependentFormattingContext::construct( self.context, + node, style.clone(), display_inside, contents, @@ -411,9 +429,10 @@ where fn handle_block_level_element( &mut self, + node: Node, style: Arc, display_inside: DisplayInside, - contents: Contents, + contents: Contents, box_slot: BoxSlot<'dom>, ) { // We just found a block level element, all ongoing inline level boxes @@ -427,6 +446,7 @@ where .rev() .map(|ongoing| { let fragmented = InlineBox { + tag: ongoing.tag, style: ongoing.style.clone(), first_fragment: ongoing.first_fragment, // The fragmented boxes before the block level element @@ -459,47 +479,60 @@ where // context needs to be ended. self.end_ongoing_inline_formatting_context(); - let intermediate_box = match contents.try_into() { + let kind = match contents.try_into() { Ok(contents) => match display_inside { - DisplayInside::Flow => IntermediateBlockLevelBox::SameFormattingContextBlock { - style, - contents: IntermediateBlockContainer::Deferred { contents }, - }, - _ => IntermediateBlockLevelBox::Independent { - style, + DisplayInside::Flow => BlockLevelCreator::SameFormattingContextBlock( + IntermediateBlockContainer::Deferred(contents), + ), + _ => BlockLevelCreator::Independent { display_inside, contents: contents.into(), }, }, Err(contents) => { let contents = Contents::Replaced(contents); - IntermediateBlockLevelBox::Independent { - style, + BlockLevelCreator::Independent { display_inside, contents, } }, }; - self.block_level_boxes.push((intermediate_box, box_slot)) + self.block_level_boxes.push(BlockLevelJob { + node, + box_slot, + style, + kind, + }); } fn handle_absolutely_positioned_element( &mut self, + node: Node, style: Arc, display_inside: DisplayInside, - contents: Contents, + contents: Contents, box_slot: BoxSlot<'dom>, ) { if !self.has_ongoing_inline_formatting_context() { - let box_ = IntermediateBlockLevelBox::OutOfFlowAbsolutelyPositionedBox { - style, + let kind = BlockLevelCreator::OutOfFlowAbsolutelyPositionedBox { contents, display_inside, }; - self.block_level_boxes.push((box_, box_slot)); + self.block_level_boxes.push(BlockLevelJob { + node, + box_slot, + style, + kind, + }); } else { let box_ = Arc::new(InlineLevelBox::OutOfFlowAbsolutelyPositionedBox( - AbsolutelyPositionedBox::construct(self.context, style, display_inside, contents), + AbsolutelyPositionedBox::construct( + self.context, + node, + style, + display_inside, + contents, + ), )); self.current_inline_level_boxes().push(box_.clone()); box_slot.set(LayoutBox::InlineLevel(box_)) @@ -508,23 +541,29 @@ where fn handle_float_element( &mut self, + node: Node, style: Arc, display_inside: DisplayInside, - contents: Contents, + contents: Contents, box_slot: BoxSlot<'dom>, ) { self.contains_floats = ContainsFloats::Yes; if !self.has_ongoing_inline_formatting_context() { - let box_ = IntermediateBlockLevelBox::OutOfFlowFloatBox { - style, + let kind = BlockLevelCreator::OutOfFlowFloatBox { contents, display_inside, }; - self.block_level_boxes.push((box_, box_slot)); + self.block_level_boxes.push(BlockLevelJob { + node, + box_slot, + style, + kind, + }); } else { let box_ = Arc::new(InlineLevelBox::OutOfFlowFloatBox(FloatBox::construct( self.context, + node, style, display_inside, contents, @@ -557,13 +596,18 @@ where ) }); - let box_ = IntermediateBlockLevelBox::SameFormattingContextBlock { - style: anonymous_style.clone(), - contents: IntermediateBlockContainer::InlineFormattingContext(std::mem::take( + let kind = BlockLevelCreator::SameFormattingContextBlock( + IntermediateBlockContainer::InlineFormattingContext(std::mem::take( &mut self.ongoing_inline_formatting_context, )), - }; - self.block_level_boxes.push((box_, BoxSlot::dummy())) + ); + self.block_level_boxes.push(BlockLevelJob { + node: self.root, + // FIXME(nox): We should be storing this somewhere. + box_slot: BoxSlot::dummy(), + style: anonymous_style.clone(), + kind, + }); } fn current_inline_level_boxes(&mut self) -> &mut Vec> { @@ -582,7 +626,7 @@ where } } -impl<'dom, Node> IntermediateBlockLevelBox +impl<'dom, Node> BlockLevelJob<'dom, Node> where Node: NodeExt<'dom>, { @@ -591,10 +635,13 @@ where context: &LayoutContext, max_assign_in_flow_outer_content_sizes_to: Option<&mut ContentSizes>, ) -> (Arc, ContainsFloats) { - match self { - IntermediateBlockLevelBox::SameFormattingContextBlock { style, contents } => { + let node = self.node; + let style = self.style; + let (block_level_box, contains_floats) = match self.kind { + BlockLevelCreator::SameFormattingContextBlock(contents) => { let (contents, contains_floats, box_content_sizes) = contents.finish( context, + node, &style, ContentSizesRequest::inline_if( max_assign_in_flow_outer_content_sizes_to.is_some() && @@ -604,12 +651,14 @@ where if let Some(to) = max_assign_in_flow_outer_content_sizes_to { to.max_assign(&box_content_sizes.outer_inline(&style)) } - let block_level_box = - Arc::new(BlockLevelBox::SameFormattingContextBlock { contents, style }); + let block_level_box = Arc::new(BlockLevelBox::SameFormattingContextBlock { + tag: node.as_opaque(), + contents, + style, + }); (block_level_box, contains_floats) }, - IntermediateBlockLevelBox::Independent { - style, + BlockLevelCreator::Independent { display_inside, contents, } => { @@ -619,6 +668,7 @@ where ); let contents = IndependentFormattingContext::construct( context, + node, style, display_inside, contents, @@ -632,43 +682,48 @@ where ContainsFloats::No, ) }, - IntermediateBlockLevelBox::OutOfFlowAbsolutelyPositionedBox { - style, + BlockLevelCreator::OutOfFlowAbsolutelyPositionedBox { display_inside, contents, } => { let block_level_box = Arc::new(BlockLevelBox::OutOfFlowAbsolutelyPositionedBox( - AbsolutelyPositionedBox::construct(context, style, display_inside, contents), + AbsolutelyPositionedBox::construct( + context, + node, + style, + display_inside, + contents, + ), )); (block_level_box, ContainsFloats::No) }, - IntermediateBlockLevelBox::OutOfFlowFloatBox { - style, + BlockLevelCreator::OutOfFlowFloatBox { display_inside, contents, } => { let block_level_box = Arc::new(BlockLevelBox::OutOfFlowFloatBox( - FloatBox::construct(context, style, display_inside, contents), + FloatBox::construct(context, node, style, display_inside, contents), )); (block_level_box, ContainsFloats::Yes) }, - } + }; + self.box_slot + .set(LayoutBox::BlockLevel(block_level_box.clone())); + (block_level_box, contains_floats) } } -impl<'dom, Node> IntermediateBlockContainer -where - Node: NodeExt<'dom>, -{ - fn finish( +impl IntermediateBlockContainer { + fn finish<'dom>( self, context: &LayoutContext, + node: impl NodeExt<'dom>, style: &Arc, content_sizes: ContentSizesRequest, ) -> (BlockContainer, ContainsFloats, BoxContentSizes) { match self { - IntermediateBlockContainer::Deferred { contents } => { - BlockContainer::construct(context, style, contents, content_sizes) + IntermediateBlockContainer::Deferred(contents) => { + BlockContainer::construct(context, node, style, contents, content_sizes) }, IntermediateBlockContainer::InlineFormattingContext(ifc) => { let content_sizes = content_sizes.compute(|| ifc.inline_content_sizes(context)); diff --git a/components/layout_2020/flow/float.rs b/components/layout_2020/flow/float.rs index df9cbbaf514..7c7a2ab5a31 100644 --- a/components/layout_2020/flow/float.rs +++ b/components/layout_2020/flow/float.rs @@ -29,14 +29,16 @@ impl FloatContext { impl FloatBox { pub fn construct<'dom>( context: &LayoutContext, + node: impl NodeExt<'dom>, style: Arc, display_inside: DisplayInside, - contents: Contents>, + contents: Contents, ) -> Self { let content_sizes = ContentSizesRequest::inline_if(!style.inline_size_is_length()); Self { contents: IndependentFormattingContext::construct( context, + node, style, display_inside, contents, diff --git a/components/layout_2020/flow/inline.rs b/components/layout_2020/flow/inline.rs index 93d7d6f8bdc..7c3fd9a29e3 100644 --- a/components/layout_2020/flow/inline.rs +++ b/components/layout_2020/flow/inline.rs @@ -16,6 +16,7 @@ use crate::ContainingBlock; use app_units::Au; use gfx::text::text_run::GlyphRun; use servo_arc::Arc; +use style::dom::OpaqueNode; use style::properties::ComputedValues; use style::values::computed::{Length, LengthPercentage, Percentage}; use style::values::specified::text::TextAlignKeyword; @@ -38,6 +39,7 @@ pub(crate) enum InlineLevelBox { #[derive(Debug)] pub(crate) struct InlineBox { + pub tag: OpaqueNode, pub style: Arc, pub first_fragment: bool, pub last_fragment: bool, @@ -47,6 +49,7 @@ pub(crate) struct InlineBox { /// https://www.w3.org/TR/css-display-3/#css-text-run #[derive(Debug)] pub(crate) struct TextRun { + pub tag: OpaqueNode, pub parent_style: Arc, pub text: String, } @@ -59,6 +62,7 @@ struct InlineNestingLevelState<'box_tree> { } struct PartialInlineBoxFragment<'box_tree> { + tag: OpaqueNode, style: Arc, start_corner: Vec2, padding: Sides, @@ -371,6 +375,7 @@ impl InlineBox { start_corner += &relative_adjustement(&style, ifc.containing_block) } PartialInlineBoxFragment { + tag: self.tag, style, start_corner, padding, @@ -398,6 +403,7 @@ impl<'box_tree> PartialInlineBoxFragment<'box_tree> { at_line_break: bool, ) { let mut fragment = BoxFragment { + tag: self.tag, style: self.style.clone(), children: std::mem::take(&mut nesting_level.fragments_so_far), content_rect: Rect { @@ -465,6 +471,7 @@ fn layout_atomic<'box_tree>( let fragments = replaced.make_fragments(&atomic.style, size.clone()); let content_rect = Rect { start_corner, size }; BoxFragment { + tag: atomic.tag, style: atomic.style.clone(), children: fragments, content_rect, @@ -539,6 +546,7 @@ fn layout_atomic<'box_tree>( }, }; BoxFragment { + tag: atomic.tag, style: atomic.style.clone(), children: independent_layout.fragments, content_rect, @@ -685,6 +693,7 @@ impl TextRun { ifc.current_nesting_level .fragments_so_far .push(Fragment::Text(TextFragment { + tag: self.tag, parent_style: self.parent_style.clone(), rect, ascent: font_ascent.into(), diff --git a/components/layout_2020/flow/mod.rs b/components/layout_2020/flow/mod.rs index 64f87ea09d0..b7373baf55a 100644 --- a/components/layout_2020/flow/mod.rs +++ b/components/layout_2020/flow/mod.rs @@ -18,6 +18,7 @@ use crate::ContainingBlock; use rayon::iter::{IndexedParallelIterator, IntoParallelRefIterator, ParallelIterator}; use rayon_croissant::ParallelIteratorExt; use servo_arc::Arc; +use style::dom::OpaqueNode; use style::properties::ComputedValues; use style::values::computed::{Length, LengthOrAuto}; use style::Zero; @@ -44,6 +45,7 @@ pub(crate) enum BlockContainer { #[derive(Debug)] pub(crate) enum BlockLevelBox { SameFormattingContextBlock { + tag: OpaqueNode, style: Arc, contents: BlockContainer, }, @@ -268,24 +270,27 @@ impl BlockLevelBox { float_context: Option<&mut FloatContext>, ) -> Fragment { match self { - BlockLevelBox::SameFormattingContextBlock { style, contents } => { - Fragment::Box(positioning_context.for_maybe_position_relative( - layout_context, - containing_block, - style, - |positioning_context| { - layout_in_flow_non_replaced_block_level( - layout_context, - positioning_context, - containing_block, - style, - NonReplacedContents::SameFormattingContextBlock(contents), - tree_rank, - float_context, - ) - }, - )) - }, + BlockLevelBox::SameFormattingContextBlock { + tag, + style, + contents, + } => Fragment::Box(positioning_context.for_maybe_position_relative( + layout_context, + containing_block, + style, + |positioning_context| { + layout_in_flow_non_replaced_block_level( + layout_context, + positioning_context, + containing_block, + *tag, + style, + NonReplacedContents::SameFormattingContextBlock(contents), + tree_rank, + float_context, + ) + }, + )), BlockLevelBox::Independent(contents) => { Fragment::Box(positioning_context.for_maybe_position_relative( layout_context, @@ -294,6 +299,7 @@ impl BlockLevelBox { |positioning_context| match contents.as_replaced() { Ok(replaced) => layout_in_flow_replaced_block_level( containing_block, + contents.tag, &contents.style, replaced, ), @@ -301,6 +307,7 @@ impl BlockLevelBox { layout_context, positioning_context, containing_block, + contents.tag, &contents.style, NonReplacedContents::EstablishesAnIndependentFormattingContext( non_replaced, @@ -339,6 +346,7 @@ fn layout_in_flow_non_replaced_block_level<'a>( layout_context: &LayoutContext, positioning_context: &mut PositioningContext<'a>, containing_block: &ContainingBlock, + tag: OpaqueNode, style: &Arc, block_level_kind: NonReplacedContents<'a>, tree_rank: usize, @@ -488,6 +496,7 @@ fn layout_in_flow_non_replaced_block_level<'a>( }, }; BoxFragment { + tag, style: style.clone(), children: fragments, content_rect, @@ -503,6 +512,7 @@ fn layout_in_flow_non_replaced_block_level<'a>( /// https://drafts.csswg.org/css2/visudet.html#inline-replaced-height fn layout_in_flow_replaced_block_level<'a>( containing_block: &ContainingBlock, + tag: OpaqueNode, style: &Arc, replaced: &ReplacedContent, ) -> BoxFragment { @@ -536,6 +546,7 @@ fn layout_in_flow_replaced_block_level<'a>( size, }; BoxFragment { + tag, style: style.clone(), children: fragments, content_rect, diff --git a/components/layout_2020/flow/root.rs b/components/layout_2020/flow/root.rs index 24dea984e62..fda5eff5116 100644 --- a/components/layout_2020/flow/root.rs +++ b/components/layout_2020/flow/root.rs @@ -61,19 +61,25 @@ fn construct_for_root_element<'dom>( Display::GeneratingBox(DisplayGeneratingBox::OutsideInside { inside, .. }) => inside, }; - let contents = replaced.map_or(Contents::OfElement(root_element), Contents::Replaced); + let contents = replaced.map_or(Contents::OfElement, Contents::Replaced); if box_style.position.is_absolutely_positioned() { ( ContainsFloats::No, vec![Arc::new(BlockLevelBox::OutOfFlowAbsolutelyPositionedBox( - AbsolutelyPositionedBox::construct(context, style, display_inside, contents), + AbsolutelyPositionedBox::construct( + context, + root_element, + style, + display_inside, + contents, + ), ))], ) } else if box_style.float.is_floating() { ( ContainsFloats::Yes, vec![Arc::new(BlockLevelBox::OutOfFlowFloatBox( - FloatBox::construct(context, style, display_inside, contents), + FloatBox::construct(context, root_element, style, display_inside, contents), ))], ) } else { @@ -82,6 +88,7 @@ fn construct_for_root_element<'dom>( vec![Arc::new(BlockLevelBox::Independent( IndependentFormattingContext::construct( context, + root_element, style, display_inside, contents, diff --git a/components/layout_2020/formatting_contexts.rs b/components/layout_2020/formatting_contexts.rs index dcbbfa370a6..b8fc029c887 100644 --- a/components/layout_2020/formatting_contexts.rs +++ b/components/layout_2020/formatting_contexts.rs @@ -13,12 +13,14 @@ use crate::style_ext::DisplayInside; use crate::ContainingBlock; use servo_arc::Arc; use std::convert::TryInto; +use style::dom::OpaqueNode; use style::properties::ComputedValues; use style::values::computed::Length; /// https://drafts.csswg.org/css-display/#independent-formatting-context #[derive(Debug)] pub(crate) struct IndependentFormattingContext { + pub tag: OpaqueNode, pub style: Arc, /// If it was requested during construction @@ -54,9 +56,10 @@ enum NonReplacedIFCKind<'a> { impl IndependentFormattingContext { pub fn construct<'dom>( context: &LayoutContext, + node: impl NodeExt<'dom>, style: Arc, display_inside: DisplayInside, - contents: Contents>, + contents: Contents, content_sizes: ContentSizesRequest, ) -> Self { match contents.try_into() { @@ -64,11 +67,13 @@ impl IndependentFormattingContext { DisplayInside::Flow | DisplayInside::FlowRoot => { let (bfc, content_sizes) = BlockFormattingContext::construct( context, + node, &style, non_replaced, content_sizes, ); Self { + tag: node.as_opaque(), style, content_sizes, contents: IndependentFormattingContextContents::Flow(bfc), @@ -78,6 +83,7 @@ impl IndependentFormattingContext { Err(replaced) => { let content_sizes = content_sizes.compute(|| replaced.inline_content_sizes(&style)); Self { + tag: node.as_opaque(), style, content_sizes, contents: IndependentFormattingContextContents::Replaced(replaced), diff --git a/components/layout_2020/fragments.rs b/components/layout_2020/fragments.rs index 29f9db8e0b3..730037a984b 100644 --- a/components/layout_2020/fragments.rs +++ b/components/layout_2020/fragments.rs @@ -6,6 +6,7 @@ use crate::geom::flow_relative::{Rect, Sides, Vec2}; use gfx::text::glyph::GlyphStore; use servo_arc::Arc as ServoArc; use std::sync::Arc; +use style::dom::OpaqueNode; use style::logical_geometry::WritingMode; use style::properties::ComputedValues; use style::values::computed::Length; @@ -20,6 +21,7 @@ pub(crate) enum Fragment { } pub(crate) struct BoxFragment { + pub tag: OpaqueNode, pub style: ServoArc, pub children: Vec, @@ -55,6 +57,7 @@ pub(crate) struct AnonymousFragment { } pub(crate) struct TextFragment { + pub tag: OpaqueNode, pub parent_style: ServoArc, pub rect: Rect, pub ascent: Length, diff --git a/components/layout_2020/positioned.rs b/components/layout_2020/positioned.rs index cfe615ae27d..c9ad2dd97c4 100644 --- a/components/layout_2020/positioned.rs +++ b/components/layout_2020/positioned.rs @@ -60,9 +60,10 @@ pub(crate) enum AbsoluteBoxOffsets { impl AbsolutelyPositionedBox { pub fn construct<'dom>( context: &LayoutContext, + node: impl NodeExt<'dom>, style: Arc, display_inside: DisplayInside, - contents: Contents>, + contents: Contents, ) -> Self { // "Shrink-to-fit" in https://drafts.csswg.org/css2/visudet.html#abs-non-replaced-width let content_sizes = ContentSizesRequest::inline_if( @@ -76,6 +77,7 @@ impl AbsolutelyPositionedBox { Self { contents: IndependentFormattingContext::construct( context, + node, style, display_inside, contents, @@ -469,6 +471,7 @@ impl<'box_tree> HoistedAbsolutelyPositionedBox<'box_tree> { }; BoxFragment { + tag: self.absolutely_positioned_box.contents.tag, style: style.clone(), children: fragments, content_rect, diff --git a/components/style/properties/longhands/inherited_ui.mako.rs b/components/style/properties/longhands/inherited_ui.mako.rs index d854d4a499c..a7b83f0ea99 100644 --- a/components/style/properties/longhands/inherited_ui.mako.rs +++ b/components/style/properties/longhands/inherited_ui.mako.rs @@ -10,7 +10,7 @@ ${helpers.predefined_type( "cursor", "Cursor", "computed::Cursor::auto()", - engines="gecko servo-2013", + engines="gecko servo-2013 servo-2020", initial_specified_value="specified::Cursor::auto()", animation_value_type="discrete", spec="https://drafts.csswg.org/css-ui/#cursor", @@ -22,7 +22,7 @@ ${helpers.predefined_type( ${helpers.single_keyword( "pointer-events", "auto none", - engines="gecko servo-2013", + engines="gecko servo-2013 servo-2020", animation_value_type="discrete", extra_gecko_values="visiblepainted visiblefill visiblestroke visible painted fill stroke all", spec="https://www.w3.org/TR/SVG11/interact.html#PointerEventsProperty",