mirror of
https://github.com/servo/servo.git
synced 2025-08-04 13:10:20 +01:00
offsetParent queries now basically work on inline nodes.
This commit is contained in:
parent
0a5218dc75
commit
66235837e7
1 changed files with 52 additions and 13 deletions
|
@ -440,6 +440,11 @@ impl UnioningFragmentScrollAreaIterator {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct NodeOffsetBoxInfo {
|
||||||
|
offset: Point2D<Au>,
|
||||||
|
rectangle: Rect<Au>,
|
||||||
|
}
|
||||||
|
|
||||||
struct ParentBorderBoxInfo {
|
struct ParentBorderBoxInfo {
|
||||||
node_address: OpaqueNode,
|
node_address: OpaqueNode,
|
||||||
border_box: Rect<Au>,
|
border_box: Rect<Au>,
|
||||||
|
@ -447,8 +452,8 @@ struct ParentBorderBoxInfo {
|
||||||
|
|
||||||
struct ParentOffsetBorderBoxIterator {
|
struct ParentOffsetBorderBoxIterator {
|
||||||
node_address: OpaqueNode,
|
node_address: OpaqueNode,
|
||||||
has_found_node: bool,
|
has_processed_node: bool,
|
||||||
node_border_box: Rect<Au>,
|
node_offset_box: Option<NodeOffsetBoxInfo>,
|
||||||
parent_nodes: Vec<Option<ParentBorderBoxInfo>>,
|
parent_nodes: Vec<Option<ParentBorderBoxInfo>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -456,8 +461,8 @@ impl ParentOffsetBorderBoxIterator {
|
||||||
fn new(node_address: OpaqueNode) -> ParentOffsetBorderBoxIterator {
|
fn new(node_address: OpaqueNode) -> ParentOffsetBorderBoxIterator {
|
||||||
ParentOffsetBorderBoxIterator {
|
ParentOffsetBorderBoxIterator {
|
||||||
node_address: node_address,
|
node_address: node_address,
|
||||||
has_found_node: false,
|
has_processed_node: false,
|
||||||
node_border_box: Rect::zero(),
|
node_offset_box: None,
|
||||||
parent_nodes: Vec::new(),
|
parent_nodes: Vec::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -534,20 +539,53 @@ impl FragmentBorderBoxIterator for UnioningFragmentScrollAreaIterator {
|
||||||
// https://drafts.csswg.org/cssom-view/#extensions-to-the-htmlelement-interface
|
// https://drafts.csswg.org/cssom-view/#extensions-to-the-htmlelement-interface
|
||||||
impl FragmentBorderBoxIterator for ParentOffsetBorderBoxIterator {
|
impl FragmentBorderBoxIterator for ParentOffsetBorderBoxIterator {
|
||||||
fn process(&mut self, fragment: &Fragment, level: i32, border_box: &Rect<Au>) {
|
fn process(&mut self, fragment: &Fragment, level: i32, border_box: &Rect<Au>) {
|
||||||
// Remove all nodes at this level or higher, as they can't be parents of this node.
|
match self.node_offset_box {
|
||||||
self.parent_nodes.truncate(level as usize);
|
Some(_) => { }, // We've already found the node, so we already have its parent.
|
||||||
assert!(self.parent_nodes.len() == level as usize);
|
None => {
|
||||||
|
// Remove all nodes at this level or higher, as they can't be parents of this node.
|
||||||
|
self.parent_nodes.truncate(level as usize);
|
||||||
|
assert!(self.parent_nodes.len() == level as usize);
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
if fragment.node == self.node_address {
|
if fragment.node == self.node_address {
|
||||||
// Found the fragment in the flow tree that matches the
|
// Found the fragment in the flow tree that matches the
|
||||||
// DOM node being looked for.
|
// DOM node being looked for.
|
||||||
self.has_found_node = true;
|
self.has_processed_node = true;
|
||||||
self.node_border_box = *border_box;
|
self.node_offset_box = Some(NodeOffsetBoxInfo {
|
||||||
|
offset: border_box.origin,
|
||||||
|
rectangle: *border_box,
|
||||||
|
});
|
||||||
|
|
||||||
// offsetParent returns null if the node is fixed.
|
// offsetParent returns null if the node is fixed.
|
||||||
if fragment.style.get_box().position == computed_values::position::T::fixed {
|
if fragment.style.get_box().position == computed_values::position::T::fixed {
|
||||||
self.parent_nodes.clear();
|
self.parent_nodes.clear();
|
||||||
}
|
}
|
||||||
|
} else if fragment.contains_node(self.node_address) {
|
||||||
|
// Found a fragment in the flow tree that matches a child
|
||||||
|
// of the DOM node being looked for.
|
||||||
|
// Since we haven't found an exact match, the node must be
|
||||||
|
// inline. Hopefully.
|
||||||
|
match self.node_offset_box {
|
||||||
|
Some(NodeOffsetBoxInfo { ref mut rectangle, .. }) => {
|
||||||
|
*rectangle = rectangle.union(border_box);
|
||||||
|
},
|
||||||
|
None => {
|
||||||
|
self.node_offset_box = Some(NodeOffsetBoxInfo {
|
||||||
|
offset: border_box.origin,
|
||||||
|
rectangle: *border_box,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: `position: fixed` on inline elements doesn't seem to work
|
||||||
|
// as of Sep 25, 2016, so I don't know how one will check if an
|
||||||
|
// inline element has it when it does.
|
||||||
|
} else if let Some(_) = self.node_offset_box {
|
||||||
|
// We've been processing fragments within the node, but now
|
||||||
|
// we've found one outside it. That means we're done.
|
||||||
|
// Hopefully.
|
||||||
|
self.has_processed_node = true;
|
||||||
} else {
|
} else {
|
||||||
// TODO(gw): Is there a less fragile way of checking whether this
|
// TODO(gw): Is there a less fragile way of checking whether this
|
||||||
// fragment is the body element, rather than just checking that
|
// fragment is the body element, rather than just checking that
|
||||||
|
@ -586,7 +624,7 @@ impl FragmentBorderBoxIterator for ParentOffsetBorderBoxIterator {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn should_process(&mut self, _: &Fragment) -> bool {
|
fn should_process(&mut self, _: &Fragment) -> bool {
|
||||||
!self.has_found_node
|
!self.has_processed_node
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -807,14 +845,15 @@ pub fn process_offset_parent_query<N: LayoutNode>(requested_node: N, layout_root
|
||||||
-> OffsetParentResponse {
|
-> OffsetParentResponse {
|
||||||
let mut iterator = ParentOffsetBorderBoxIterator::new(requested_node.opaque());
|
let mut iterator = ParentOffsetBorderBoxIterator::new(requested_node.opaque());
|
||||||
sequential::iterate_through_flow_tree_fragment_border_boxes(layout_root, &mut iterator);
|
sequential::iterate_through_flow_tree_fragment_border_boxes(layout_root, &mut iterator);
|
||||||
assert!(iterator.has_found_node);
|
// If we didn't find the node, something went wrong. Unwrap it.
|
||||||
|
let node_offset_box = iterator.node_offset_box.unwrap();
|
||||||
|
|
||||||
let parent_info_index = iterator.parent_nodes.iter().rposition(|info| info.is_some());
|
let parent_info_index = iterator.parent_nodes.iter().rposition(|info| info.is_some());
|
||||||
match parent_info_index {
|
match parent_info_index {
|
||||||
Some(parent_info_index) => {
|
Some(parent_info_index) => {
|
||||||
let parent = iterator.parent_nodes[parent_info_index].as_ref().unwrap();
|
let parent = iterator.parent_nodes[parent_info_index].as_ref().unwrap();
|
||||||
let origin = iterator.node_border_box.origin - parent.border_box.origin;
|
let origin = node_offset_box.offset - parent.border_box.origin;
|
||||||
let size = iterator.node_border_box.size;
|
let size = node_offset_box.rectangle.size;
|
||||||
OffsetParentResponse {
|
OffsetParentResponse {
|
||||||
node_address: Some(parent.node_address.to_untrusted_node_address()),
|
node_address: Some(parent.node_address.to_untrusted_node_address()),
|
||||||
rect: Rect::new(origin, size),
|
rect: Rect::new(origin, size),
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue