LibWeb: Skip out-of-flow boxes when wrapping inlines in anonymous block
Out-of-flow boxes (floating and absolutely-positioned elements) were previously collected and put in the anonymous block wrapper as well, but this actually made hit testing not able to find them, since they were breaking expectations about tree structure that hit testing relies on. After this change, we simply let out-of-flow boxes stay in their original parent, preserving the author's intended box tree structure.
This commit is contained in:
parent
11354dbf9e
commit
6994ea5885
Notes:
sideshowbarker
2024-07-17 08:34:29 +09:00
Author: https://github.com/awesomekling Commit: https://github.com/SerenityOS/serenity/commit/6994ea5885 Pull-request: https://github.com/SerenityOS/serenity/pull/22250
10 changed files with 86 additions and 40 deletions
|
@ -3,17 +3,17 @@ Viewport <#document> at (0,0) content-size 800x600 children: not-inline
|
|||
BlockContainer <(anonymous)> at (0,0) content-size 800x0 children: inline
|
||||
TextNode <#text>
|
||||
BlockContainer <body> at (8,8) content-size 784x34.9375 children: not-inline
|
||||
BlockContainer <div.big-float> at (8,8) content-size 100x100 floating [BFC] children: not-inline
|
||||
BlockContainer <div.xxx> at (108,8) content-size 29.109375x17.46875 floating [BFC] children: inline
|
||||
line 0 width: 29.109375, height: 17.46875, bottom: 17.46875, baseline: 13.53125
|
||||
frag 0 from TextNode start: 0, length: 3, rect: [108,8 29.109375x17.46875]
|
||||
"xxx"
|
||||
TextNode <#text>
|
||||
BlockContainer <(anonymous)> at (8,8) content-size 784x17.46875 children: inline
|
||||
line 0 width: 27.640625, height: 17.46875, bottom: 17.46875, baseline: 13.53125
|
||||
frag 0 from TextNode start: 1, length: 3, rect: [137,8 27.640625x17.46875]
|
||||
"bar"
|
||||
BlockContainer <div.big-float> at (8,8) content-size 100x100 floating [BFC] children: not-inline
|
||||
TextNode <#text>
|
||||
BlockContainer <div.xxx> at (108,8) content-size 29.109375x17.46875 floating [BFC] children: inline
|
||||
line 0 width: 29.109375, height: 17.46875, bottom: 17.46875, baseline: 13.53125
|
||||
frag 0 from TextNode start: 0, length: 3, rect: [108,8 29.109375x17.46875]
|
||||
"xxx"
|
||||
TextNode <#text>
|
||||
TextNode <#text>
|
||||
BlockContainer <div> at (8,25.46875) content-size 784x17.46875 children: inline
|
||||
line 0 width: 27.203125, height: 17.46875, bottom: 17.46875, baseline: 13.53125
|
||||
|
@ -32,11 +32,11 @@ Viewport <#document> at (0,0) content-size 800x600 children: not-inline
|
|||
ViewportPaintable (Viewport<#document>) [0,0 800x600]
|
||||
PaintableWithLines (BlockContainer<HTML>) [0,0 800x108]
|
||||
PaintableWithLines (BlockContainer(anonymous)) [0,0 800x0]
|
||||
PaintableWithLines (BlockContainer<BODY>) [8,8 784x34.9375]
|
||||
PaintableWithLines (BlockContainer<BODY>) [8,8 784x34.9375] overflow: [8,8 784x100]
|
||||
PaintableWithLines (BlockContainer<DIV>.big-float) [8,8 100x100]
|
||||
PaintableWithLines (BlockContainer<DIV>.xxx) [108,8 29.109375x17.46875]
|
||||
TextPaintable (TextNode<#text>)
|
||||
PaintableWithLines (BlockContainer(anonymous)) [8,8 784x17.46875]
|
||||
PaintableWithLines (BlockContainer<DIV>.big-float) [8,8 100x100]
|
||||
PaintableWithLines (BlockContainer<DIV>.xxx) [108,8 29.109375x17.46875]
|
||||
TextPaintable (TextNode<#text>)
|
||||
TextPaintable (TextNode<#text>)
|
||||
PaintableWithLines (BlockContainer<DIV>) [8,25.46875 784x17.46875]
|
||||
PaintableWithLines (BlockContainer<DIV>.yyy) [108,25.46875 21.515625x17.46875]
|
||||
|
|
|
@ -2,9 +2,9 @@ Viewport <#document> at (0,0) content-size 800x600 children: not-inline
|
|||
BlockContainer <html> at (0,0) content-size 800x600 [BFC] children: not-inline
|
||||
BlockContainer <body> at (8,8) content-size 784x100 children: not-inline
|
||||
BlockContainer <div> at (8,8) content-size 784x100 children: not-inline
|
||||
BlockContainer <div.square.white> at (8,8) content-size 100x100 floating [BFC] children: not-inline
|
||||
BlockContainer <(anonymous)> at (8,8) content-size 784x0 children: inline
|
||||
TextNode <#text>
|
||||
BlockContainer <div.square.white> at (8,8) content-size 100x100 floating [BFC] children: not-inline
|
||||
TextNode <#text>
|
||||
BlockContainer <div.clearfix> at (8,108) content-size 784x0 children: not-inline
|
||||
BlockContainer <(anonymous)> at (8,108) content-size 784x0 children: inline
|
||||
|
@ -18,8 +18,8 @@ ViewportPaintable (Viewport<#document>) [0,0 800x600]
|
|||
PaintableWithLines (BlockContainer<HTML>) [0,0 800x600]
|
||||
PaintableWithLines (BlockContainer<BODY>) [8,8 784x100]
|
||||
PaintableWithLines (BlockContainer<DIV>) [8,8 784x100]
|
||||
PaintableWithLines (BlockContainer<DIV>.square.white) [8,8 100x100]
|
||||
PaintableWithLines (BlockContainer(anonymous)) [8,8 784x0]
|
||||
PaintableWithLines (BlockContainer<DIV>.square.white) [8,8 100x100]
|
||||
PaintableWithLines (BlockContainer<DIV>.clearfix) [8,108 784x0]
|
||||
PaintableWithLines (BlockContainer(anonymous)) [8,108 784x0]
|
||||
PaintableWithLines (BlockContainer<DIV>.square.black) [8,108 49x49]
|
||||
|
|
|
@ -3,9 +3,9 @@ Viewport <#document> at (0,0) content-size 800x600 children: not-inline
|
|||
BlockContainer <(anonymous)> at (0,0) content-size 800x0 children: inline
|
||||
TextNode <#text>
|
||||
BlockContainer <body> at (8,8) content-size 784x17.46875 children: not-inline
|
||||
BlockContainer <div#b> at (9,9) content-size 50x50 floating [BFC] children: not-inline
|
||||
BlockContainer <(anonymous)> at (8,8) content-size 784x0 children: inline
|
||||
TextNode <#text>
|
||||
BlockContainer <div#b> at (9,9) content-size 50x50 floating [BFC] children: not-inline
|
||||
TextNode <#text>
|
||||
BlockContainer <div#a> at (8,8) content-size 784x17.46875 children: inline
|
||||
line 0 width: 37.578125, height: 17.46875, bottom: 17.46875, baseline: 13.53125
|
||||
|
@ -18,9 +18,9 @@ Viewport <#document> at (0,0) content-size 800x600 children: not-inline
|
|||
ViewportPaintable (Viewport<#document>) [0,0 800x600]
|
||||
PaintableWithLines (BlockContainer<HTML>) [0,0 800x60]
|
||||
PaintableWithLines (BlockContainer(anonymous)) [0,0 800x0]
|
||||
PaintableWithLines (BlockContainer<BODY>) [8,8 784x17.46875]
|
||||
PaintableWithLines (BlockContainer<BODY>) [8,8 784x17.46875] overflow: [8,8 784x52]
|
||||
PaintableWithLines (BlockContainer<DIV>#b) [8,8 52x52]
|
||||
PaintableWithLines (BlockContainer(anonymous)) [8,8 784x0]
|
||||
PaintableWithLines (BlockContainer<DIV>#b) [8,8 52x52]
|
||||
PaintableWithLines (BlockContainer<DIV>#a) [8,8 784x17.46875]
|
||||
TextPaintable (TextNode<#text>)
|
||||
PaintableWithLines (BlockContainer(anonymous)) [8,25.46875 784x0]
|
||||
|
|
|
@ -3,19 +3,19 @@ Viewport <#document> at (0,0) content-size 800x600 children: not-inline
|
|||
BlockContainer <(anonymous)> at (0,0) content-size 800x0 children: inline
|
||||
TextNode <#text>
|
||||
BlockContainer <body> at (8,8) content-size 784x600 children: not-inline
|
||||
BlockContainer <div.blue.absolute> at (208,208) content-size 200x200 positioned [BFC] children: inline
|
||||
TextNode <#text>
|
||||
BlockContainer <div.red.absolute> at (308,308) content-size 100x100 positioned [BFC] children: not-inline
|
||||
TextNode <#text>
|
||||
BlockContainer <div.yellow.absolute> at (258,258) content-size 100x100 positioned [BFC] children: inline
|
||||
TextNode <#text>
|
||||
BlockContainer <div.black.absolute> at (308,308) content-size 50x50 positioned [BFC] children: not-inline
|
||||
TextNode <#text>
|
||||
TextNode <#text>
|
||||
BlockContainer <div.green.absolute> at (508,508) content-size 100x100 positioned [BFC] children: not-inline
|
||||
TextNode <#text>
|
||||
BlockContainer <(anonymous)> at (8,8) content-size 784x0 children: inline
|
||||
TextNode <#text>
|
||||
BlockContainer <div.blue.absolute> at (208,208) content-size 200x200 positioned [BFC] children: inline
|
||||
TextNode <#text>
|
||||
BlockContainer <div.red.absolute> at (308,308) content-size 100x100 positioned [BFC] children: not-inline
|
||||
TextNode <#text>
|
||||
BlockContainer <div.yellow.absolute> at (258,258) content-size 100x100 positioned [BFC] children: inline
|
||||
TextNode <#text>
|
||||
BlockContainer <div.black.absolute> at (308,308) content-size 50x50 positioned [BFC] children: not-inline
|
||||
TextNode <#text>
|
||||
TextNode <#text>
|
||||
BlockContainer <div.green.absolute> at (508,508) content-size 100x100 positioned [BFC] children: not-inline
|
||||
TextNode <#text>
|
||||
TextNode <#text>
|
||||
BlockContainer <div.blue> at (8,8) content-size 200x200 children: not-inline
|
||||
BlockContainer <(anonymous)> at (8,8) content-size 200x0 children: inline
|
||||
|
@ -39,12 +39,12 @@ ViewportPaintable (Viewport<#document>) [0,0 800x600] overflow: [0,0 800x616]
|
|||
PaintableWithLines (BlockContainer<HTML>) [0,0 800x616]
|
||||
PaintableWithLines (BlockContainer(anonymous)) [0,0 800x0]
|
||||
PaintableWithLines (BlockContainer<BODY>) [8,8 784x600]
|
||||
PaintableWithLines (BlockContainer<DIV>.blue.absolute) [208,208 200x200]
|
||||
PaintableWithLines (BlockContainer<DIV>.red.absolute) [308,308 100x100]
|
||||
PaintableWithLines (BlockContainer<DIV>.yellow.absolute) [258,258 100x100]
|
||||
PaintableWithLines (BlockContainer<DIV>.black.absolute) [308,308 50x50]
|
||||
PaintableWithLines (BlockContainer<DIV>.green.absolute) [508,508 100x100]
|
||||
PaintableWithLines (BlockContainer(anonymous)) [8,8 784x0]
|
||||
PaintableWithLines (BlockContainer<DIV>.blue.absolute) [208,208 200x200]
|
||||
PaintableWithLines (BlockContainer<DIV>.red.absolute) [308,308 100x100]
|
||||
PaintableWithLines (BlockContainer<DIV>.yellow.absolute) [258,258 100x100]
|
||||
PaintableWithLines (BlockContainer<DIV>.black.absolute) [308,308 50x50]
|
||||
PaintableWithLines (BlockContainer<DIV>.green.absolute) [508,508 100x100]
|
||||
PaintableWithLines (BlockContainer<DIV>.blue) [8,8 200x200] overflow: [8,8 200x300]
|
||||
PaintableWithLines (BlockContainer(anonymous)) [8,8 200x0]
|
||||
PaintableWithLines (BlockContainer<DIV>.red) [8,8 100x100]
|
||||
|
|
|
@ -9,9 +9,9 @@ Viewport <#document> at (0,0) content-size 800x600 children: not-inline
|
|||
BlockContainer <(anonymous)> at (8,16) content-size 1280x0 children: inline
|
||||
TextNode <#text>
|
||||
BlockContainer <div> at (8,16) content-size 1280x400 children: not-inline
|
||||
ImageBox <img> at (488,16) content-size 800x400 floating children: not-inline
|
||||
BlockContainer <(anonymous)> at (8,16) content-size 1280x0 children: inline
|
||||
TextNode <#text>
|
||||
ImageBox <img> at (488,16) content-size 800x400 floating children: not-inline
|
||||
TextNode <#text>
|
||||
BlockContainer <p> at (8,16) content-size 1280x17.46875 children: inline
|
||||
line 0 width: 37.21875, height: 17.46875, bottom: 17.46875, baseline: 13.53125
|
||||
|
@ -33,8 +33,8 @@ ViewportPaintable (Viewport<#document>) [0,0 800x600] overflow: [0,0 1288x824]
|
|||
PaintableWithLines (BlockContainer<DIV>.foo) [8,16 1280x800]
|
||||
PaintableWithLines (BlockContainer(anonymous)) [8,16 1280x0]
|
||||
PaintableWithLines (BlockContainer<DIV>) [8,16 1280x400]
|
||||
ImagePaintable (ImageBox<IMG>) [488,16 800x400]
|
||||
PaintableWithLines (BlockContainer(anonymous)) [8,16 1280x0]
|
||||
ImagePaintable (ImageBox<IMG>) [488,16 800x400]
|
||||
PaintableWithLines (BlockContainer<P>) [8,16 1280x17.46875]
|
||||
TextPaintable (TextNode<#text>)
|
||||
PaintableWithLines (BlockContainer(anonymous)) [8,49.46875 1280x0]
|
||||
|
|
|
@ -3,9 +3,9 @@ Viewport <#document> at (0,0) content-size 800x600 children: not-inline
|
|||
BlockContainer <(anonymous)> at (0,0) content-size 800x0 children: inline
|
||||
TextNode <#text>
|
||||
BlockContainer <body> at (8,16) content-size 784x17.46875 children: not-inline
|
||||
ImageBox <img> at (8,16) content-size 200x100 floating children: not-inline
|
||||
BlockContainer <(anonymous)> at (8,16) content-size 784x0 children: inline
|
||||
TextNode <#text>
|
||||
ImageBox <img> at (8,16) content-size 200x100 floating children: not-inline
|
||||
TextNode <#text>
|
||||
BlockContainer <p> at (8,16) content-size 784x17.46875 children: inline
|
||||
line 0 width: 37.21875, height: 17.46875, bottom: 17.46875, baseline: 13.53125
|
||||
|
@ -18,9 +18,9 @@ Viewport <#document> at (0,0) content-size 800x600 children: not-inline
|
|||
ViewportPaintable (Viewport<#document>) [0,0 800x600]
|
||||
PaintableWithLines (BlockContainer<HTML>) [0,0 800x116]
|
||||
PaintableWithLines (BlockContainer(anonymous)) [0,0 800x0]
|
||||
PaintableWithLines (BlockContainer<BODY>) [8,16 784x17.46875] overflow: [8,16 784x33.46875]
|
||||
PaintableWithLines (BlockContainer<BODY>) [8,16 784x17.46875] overflow: [8,16 784x100]
|
||||
ImagePaintable (ImageBox<IMG>) [8,16 200x100]
|
||||
PaintableWithLines (BlockContainer(anonymous)) [8,16 784x0]
|
||||
ImagePaintable (ImageBox<IMG>) [8,16 200x100]
|
||||
PaintableWithLines (BlockContainer<P>) [8,16 784x17.46875]
|
||||
TextPaintable (TextNode<#text>)
|
||||
PaintableWithLines (BlockContainer(anonymous)) [8,49.46875 784x0]
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
true
|
|
@ -0,0 +1,38 @@
|
|||
<!DOCTYPE html><style>
|
||||
* {
|
||||
outline: 1px solid black;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
body {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#d_header {
|
||||
background: pink;
|
||||
width: 400px;
|
||||
height: 30px;
|
||||
}
|
||||
|
||||
#d_scene_btns {
|
||||
float: left;
|
||||
}
|
||||
|
||||
#button {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
background: orange;
|
||||
}
|
||||
|
||||
#button:hover {
|
||||
background: red;
|
||||
}
|
||||
</style><body><div id="d_header"><div id="d_scene_btns"><div id="button"></div></div> <div class="clear"></div>
|
||||
<div id="box"></div>
|
||||
<script src="../include.js"></script>
|
||||
<script>
|
||||
test(() => {
|
||||
println(internals.hitTest(5, 5).node === document.getElementById("button"));
|
||||
});
|
||||
</script>
|
|
@ -121,9 +121,16 @@ static Layout::Node& insertion_parent_for_block_node(Layout::NodeWithStyle& layo
|
|||
// Parent block has inline-level children (our siblings).
|
||||
// First move these siblings into an anonymous wrapper block.
|
||||
Vector<JS::Handle<Layout::Node>> children;
|
||||
while (JS::GCPtr<Layout::Node> child = layout_parent.first_child()) {
|
||||
layout_parent.remove_child(*child);
|
||||
children.append(*child);
|
||||
{
|
||||
JS::GCPtr<Layout::Node> next;
|
||||
for (JS::GCPtr<Layout::Node> child = layout_parent.first_child(); child; child = next) {
|
||||
next = child->next_sibling();
|
||||
// NOTE: We let out-of-flow children stay in the parent, to preserve tree structure.
|
||||
if (child->is_floating() || child->is_absolutely_positioned())
|
||||
continue;
|
||||
layout_parent.remove_child(*child);
|
||||
children.append(*child);
|
||||
}
|
||||
}
|
||||
layout_parent.append_child(layout_parent.create_anonymous_wrapper());
|
||||
layout_parent.set_children_are_inline(false);
|
||||
|
|
|
@ -805,7 +805,7 @@ Optional<HitTestResult> PaintableBox::hit_test(CSSPixelPoint position, HitTestTy
|
|||
|
||||
Optional<HitTestResult> PaintableWithLines::hit_test(CSSPixelPoint position, HitTestType type) const
|
||||
{
|
||||
if (!layout_box().children_are_inline())
|
||||
if (!layout_box().children_are_inline() || m_line_boxes.is_empty())
|
||||
return PaintableBox::hit_test(position, type);
|
||||
|
||||
Optional<HitTestResult> last_good_candidate;
|
||||
|
|
Loading…
Add table
Reference in a new issue