The old mode names, while mechanically accurate, didn't really reflect
their relationship to the CSS specifications.
This patch renames them as follows:
Default => Normal
AllPossibleLineBreaks => MinContent
OnlyRequiredLineBreaks => MaxContent
There's also now an explainer comment with the LayoutMode enum about the
specific implications of layout in each mode.
1. Make this decision *after* we've inserted the layout node into the
layout tree. Otherwise, we can't reach its containing block!
2. Per css-sizing-3, consider auto-sized blocks whose sizes resolve
solely against other definite sizes as definite themselves.
In particular, (2) makes us consider width:auto block children of a
definite-size containing block as having definite size. This becomes
very important in flex layout.
Everything related to hit testing is better off using the painting tree.
The thing being mousemoved over is a paintable, so let's hand that out
directly instead of the corresponding layout node.
Input events have nothing to do with layout, so let's not send them to
layout nodes.
The job of Paintable starts to become clear. It represents a paintable
item that can be rendered into the viewport, which means it can also
be targeted by the mouse cursor.
This patch adds a bunch of Paintable subclasses, each corresponding to
the Layout::Node subclasses that had a paint() override. All painting
logic is moved from layout nodes into their corresponding paintables.
Paintables are now created by asking a Layout::Box to produce one:
static NonnullOwnPtr<Paintable> Layout::Box::create_paintable()
Note that inline nodes still have their painting logic. Since they
are not boxes, and all paintables have a corresponding box, we'll need
to come up with some other solution for them.
This patch adds a map of Layout::Node to FormattingState::NodeState.
Instead of updating layout nodes incrementally as layout progresses
through the formatting contexts, all updates are now written to the
corresponding NodeState instead.
At the end of layout, FormattingState::commit() is called, which
transfers all the values from the NodeState objects to the Node.
This will soon allow us to perform completely non-destructive layouts
which don't affect the tree.
Note that there are many imperfections here, and still many places
where we assign to the NodeState, but later read directly from the Node
instead. I'm just committing at this stage to make subsequent diffs
easier to understand.
This returns a String with this format:
- LayoutNodeClassName<TAG_NAME>#id.class1.class2.class3
I've rewritten this function 10+ times at this point, so I'm just gonna
add it to the repository for future debugging needs. :^)
The existing implementation, which is used by Node::hit_test() and
sub-classes, does not include stacking contexts which prevents hit
testing from returning elements contained by those stacking contexts
in some situations.
This is quite rough and definitely not optimal. The stacking contexts
are not retrieved in the correct order. They should be sorted by
z-index then tree order.
This change makes DuckDuckGo technically usable with all the absolute
and relative positioning they use.
Now that we build lines incrementally, we no longer need the atomic line
splitting API.
The new InlineLevelIterator and LineBuilder setup does have some
regressions from the old behavior, but we can deal with them as we go.
Instead of storing these as individual `background-foo` properties, we
combine them together into layers, since that is how they will be
painted. It also makes it more convenient to pass them around.
In #10434 an issue with leading whitespace in new lines after
a <br> element was fixed by checking whether the last fragment
of LineBox is empty.
However, this introduced a regression by which whitespace following
inline elements was swallowed, so `<b>Test</b> 123` would appear
like `Test123`.
By asking specifically if we are handling a forced linebreak
instead of implicity asking for a property that may be shared by
other Node types, we can maintain the correct behavior in regards
to leading whitespace on new lines, as well as trailing whitespace
of inline elements.
There's a subtle difference here. A "block box" in the spec is a
block-level box, while a "block container" is a box whose children are
either all inline-level boxes in an IFC, or all block-level boxes
participating in a BFC.
Notably, an "inline-block" box is a "block container" but not a "block
box" since it is itself inline-level.
In the past, the base class implementation of this was used to descend
into subtrees and paint children. That is now taken care of by
StackingContext::paint_descendants() instead, and nothing used this.
Our "frame" concept very closely matches what the web specs call a
"browsing context", so let's rename it to that. :^)
The "main frame" becomes the "top-level browsing context",
and "sub-frames" are now "nested browsing contexts".
SPDX License Identifiers are a more compact / standardized
way of representing file license information.
See: https://spdx.dev/resources/use/#identifiers
This was done with the `ambr` search and replace tool.
ambr --no-parent-ignore --key-from-file --rep-from-file key.txt rep.txt *
We try scrolling a Node with the handle_mousewheel event, but if it
isn't scrollable, the event should be passed back up to the page
host. This is the first step in that process.
This is rather crude, but you can now use the mouse wheel to scroll up
and down in block-level boxes with clipped overflowing content.
There's no limit to how far you can scroll in either direction, since
we don't yet track how much overflow there is. But it's a start. :^)
The generic is<T>() uses dynamic_cast which is fine in the majority
of cases, but when one of them shows up in profiles, we can make it
faster by answering the is-a question manually.