Age | Commit message (Collapse) | Author |
|
It's not enough to only relayout here, since the API can substantially
change the DOM. We have to rebuild the layout tree.
|
|
https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#cother-other-default-operation-rules
"The compiler is more likely to get the default semantics right and
you cannot implement these functions better than the compiler."
|
|
This was causing us to miss layout invalidations. With this fixed, we
can remove the invalidation from Element::recompute_style() along with
the associated FIXME.
Thanks to Idan for spotting this! :^)
|
|
Use the new CSS::property_affects_layout() helper to figure out if we
actually need to perform a full relayout after recomputing style.
There are three tiers of required invalidation after an element receives
new style: none, repaint only, or full relayout.
This avoids the need to rebuild the layout tree (and perform layout on
it) when trivial properties like "color" etc are changed.
|
|
|
|
|
|
Let's make it very clear that these are *computed* values, and not at
all the specified values. The specified values are currently discarded
by the CSS cascade algorithm.
|
|
This more accurately reflects what's actually being returned.
|
|
This way we can traverse from inside a shadow root across the boundary
to the outside. :^)
|
|
It's not enough to compare StyleProperties pointers to see if something
changed, we have to do a deep compare.
|
|
|
|
|
|
Calling this "Box" made it very confusing to look at code that used both
Layout::Box and Painting::Box. Let's try calling it Paintable instead.
|
|
The "paintable" state in Layout::Box was actually not safe to access
until after layout had been performed.
As a first step towards making this harder to mess up accidentally,
this patch moves painting information from Layout::Box to a new class:
Painting::Box. Every layout can have a corresponding paint box, and
it holds the final used metrics determined by layout.
The paint box is created and populated by FormattingState::commit().
I've also added DOM::Node::paint_box() as a convenient way to access
the paint box (if available) of a given DOM node.
Going forward, I believe this will allow us to better separate data
that belongs to layout vs painting, and also open up opportunities
for naturally invalidating caches in the paint box (since it's
reconstituted by every layout.)
|
|
This patch only makes them appear in the tree - they are not yet
inspectable themselves.
|
|
Let's get this right before trying to make it fast. This patch removes
the code that tried to do less work when an element's style changes,
and instead simply invalidates the entire document.
Note that invalidations are still coalesced, and will not be
synchronized until update_style() and/or update_layout() is used.
|
|
As step "2. Validate qualifiedName" got implemented in
bfa7aad0f6443249ae1a8f577b3150ac32add7a3, parts is known to have a
length of 2.
|
|
When recomputing the style for an element that previously didn't have
a corresponding layout node, it may become necessary to create a layout
node for it.
However, we should not do this if it's within a subtree that can't have
layout children. Nor should we do it for elements who have an ancestor
with display:none.
|
|
1% progression on ACID3. :^)
|
|
We were returning a QualifiedName with the localName and namespace
fields swapped.
|
|
1% progression on ACID3. :^)
|
|
We need to run the same logic for creating the ::before and ::after
pseudo-elements, so this saves us from duplicating the code.
|
|
This means we can instantiate them for pseudo-elements, which don't have
an associated Element. They all pass it to their parent as a
`Layout::Node*` and handle a lack of `layout_node()` already so this
won't affect any functionality.
|
|
|
|
|
|
This allows subclasses to react to DOM attributes being removed.
|
|
This patch also adds CSS::Display::to_string() so we can log the
unimplemented CSS display value (if you have LIBWEB_CSS_DEBUG enabled).
|
|
getClientRects supposed to return a list of bounding DOMRect
for each box fragment of Element's layout, but most elements have
only one box fragment, so implementing it with getBoundingClientRect
is useful.
|
|
This implementation does some of the required validation and then passes
through the localName and value to Element.setAttribute().
|
|
Style updates are lazy since late last year, so the StyleInvalidator is
actually hurting us more than it's helping by running the entire CSS
selector machine on the whole DOM for every attribute change.
Instead, simply mark the entire DOM dirty and let the lazy style update
mechanism run *once* on next event loop iteration.
|
|
Instead of making each Layout::Node compute style for itself, we now
compute it in TreeBuilder before even calling create_layout_node().
For non-element DOM nodes, we create the style and layout tree node
in TreeBuilder. This allows us to move create_layout_node() from
DOM::Node to DOM::Element.
|
|
|
|
|
|
Browsing contexts are defined by the HTML specification, so let's move
them into the HTML directory. :^)
|
|
|
|
Rather than following the spec exactly and creating lowercase strings,
we can simply do a case-insensitive string comparison. The caveat is
that creating attributes must follow the spec by creating the attribute
name with a lowercase string.
|
|
And ensure it is updated (if it exists) when the 'class' attribute is
changed.
|
|
|
|
|
|
Note our Attribute class is what the spec refers to as just "Attr". The
main differences between the existing implementation and the spec are
just that the spec defines more fields.
Attributes can contain namespace URIs and prefixes. However, note that
these are not parsed in HTML documents unless the document content-type
is XML. So for now, these are initialized to null. Web pages are able to
set the namespace via JavaScript (setAttributeNS), so these fields may
be filled in when the corresponding APIs are implemented.
The main change to be aware of is that an attribute is a node. This has
implications on how attributes are stored in the Element class. Nodes
are non-copyable and non-movable because these constructors are deleted
by the EventTarget base class. This means attributes cannot be stored in
a Vector or HashMap as these containers assume copyability / movability.
So for now, the Vector holding attributes is changed to hold RefPtrs to
attributes instead. This might change when attribute storage is
implemented according to the spec (by way of NamedNodeMap).
|
|
|
|
'static' for a function means that the symbol shall not be made public
for the result of the current compilation unit. This does not make sense
in a header, especially not if it's a large function that is used in
more than one place and not that performance-sensitive.
|
|
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.
|
|
Until now, we've internally thought of the CSS "display" property as a
single-value property. In practice, "display" is a much more complex
property that comes in a number of configurations.
The most interesting one is the two-part format that describes the
outside and inside behavior of a box. Switching our own internal
representation towards this model will allow for much cleaner
abstractions around layout and the various formatting contexts.
Note that we don't *parse* two-part "display" yet, this is only about
changing the internal representation of the property.
Spec: https://drafts.csswg.org/css-display
|
|
Instead of doing layout synchronously whenever something changes,
we now use a basic event loop timer to defer and coalesce relayouts.
If you did something that requires a relayout of the page, make sure
to call Document::set_needs_layout() and it will get coalesced with all
the other layout updates.
There's lots of room for improvement here, but this already makes many
web pages significantly snappier. :^)
Also, note that this exposes a number of layout bugs where we have been
relying on multiple relayouts to calculate the correct dimensions for
things. Now that we only do a single layout in many cases, these kind of
problems are much more noticeable. That should also make them easier to
figure out and fix. :^)
|
|
|
|
This returns whether an element matches any of a set of selectors.
|
|
This marks our entry into the Web::Geometry namespace, based on the
"Geometry" spec at https://drafts.fxtf.org/geometry/
|
|
|
|
Resolved style is a spec concept that refers to the weird mix of
computed style and used style reflected by getComputedStyle().
The purpose of this class is to produce the *computed* style for a given
element, so let's call it StyleComputer.
|