Hoisted absolutes that are cached in IndependentFormattingContexts may
have their HoistedSharedFragment reused between layouts. This means
that the original value of the adjusted static positioning rectangles
need to be preserved in cache. This change makes it so that these values
are cloned when being retrieved from the cache. Further adjustments up
the tree will now no longer affected the version in teh cache.
Testing: This should cause `/_mozilla/css/stacked_layers.html` to no
longer
be flaky.
Fixes: #39548.
Fixes: #39439.
Signed-off-by: Martin Robinson <mrobinson@igalia.com>
Co-authored-by: Oriol Brufau <obrufau@igalia.com>
When `block-size` was intrinsic and there was no block-end padding or
margin, we were allowing the block-end margin of the box to collapse
with the block-end margin of its contents.
However, due to `min-block-size` or `max-block-size`, the final size can
be different than the intrinsic size of the contents. In that case it
didn't make any sense to collapse end margins, only WebKit does it too.
This patch takes the final size into account, like Gecko and Blink. This
is under discussion in https://github.com/w3c/csswg-drafts/issues/12218,
but for now we will match Blink.
Testing: 2 tests are now passing. There is also 1 new failure, but that
test only passes in WebKit and I don't agree with it.
Fixes: #36321
Signed-off-by: Oriol Brufau <obrufau@igalia.com>
The `border-radius` property provides the radii for the border box. For
the curvature of the padding and content boxes, we then subtract the
border and padding sizes. However, we weren't flooring the result by
zero, which could make the background completely disappear when using
`background-clip: padding-box` or `background-clip: content-box`.
Testing: Adding 4 new tests, but 2 of them fail in both Servo and
Firefox.
Fixes: #39540
Signed-off-by: Oriol Brufau <obrufau@igalia.com>
The first epoch is 0 as that is the one used in the initial transaction,
but the code was setting the first `Epoch` to `Epoch(1)`. This means
that
when layout advanced the epoch, the `Epoch` of the first produced
display list was `Epoch(2)`.
This change makes the value reflected in `current_epoch` actually match
the index of the display list produced. In addition, we always store
this epoch in `PipelineDetails` in the renderer. This will be important
when adding the `WebView::take_screenshot` API.
Testing: This should not change behavior, so is covered by existing
tests which
rely on proper `Epoch` advancement.
Signed-off-by: Martin Robinson <mrobinson@igalia.com>
Motivation: The font cache currently has to store a cache of Keys which
need to be given by the webrender instance.
Having a cache for every WebViewId in the future when we have every
webview have the different webrender::DocumentId might be too wasteful
to store this key cache per DocumentId. This proposes to include in the
WebViewId another id, the RenderingGroupId. This id can be easily
changed
to be equivalent to the DocumentId when we support multiple DocumentIds
for a unique Webrender instance.
Additionally this will keep it easier to integrate the currently out of
tree patches for multiple rendering contexts with different webrenders.
Change:
We introduce the RenderingGroupId in the WebViewId and allow a method to
extract it. The font key cache uses this cache
and forwards it to the Compositor when requesting new changes. The
compositor currently ignores this id.
Additionally, the WebView can return the RenderingGroupId. The WebViewId
also has an appropiate constructor for specifying a RenderingGroupId.
Because there currently will be only one RenderingGroupId the
performance will be minimal.
Signed-off-by: Narfinger <Narfinger@users.noreply.github.com>
Testing: This should be covered by WPT tests and normal browsing
behavior works fine.
---------
Signed-off-by: Narfinger <Narfinger@users.noreply.github.com>
This keyword is de-facto required for web compatibility, Firefox is also
enabling it (https://bugzil.la/1988938).
This patch just aliases it to `stretch`.
Stylo PR: https://github.com/servo/stylo/pull/243
Testing: Various tests pass
Signed-off-by: Oriol Brufau <obrufau@igalia.com>
As resolved in https://github.com/w3c/csswg-drafts/issues/12220, when
resolving `align-content: normal` on a table cell, we will now use safe
alignment.
The difference only matters when the contents of the cell are taller
than the cell, which doesn't typically happen. But in Servo it's
observable when there are collapsed rows.
Testing: Adding new tests. Some fail because we don't support
`align-content` yet.
Signed-off-by: Oriol Brufau <obrufau@igalia.com>
This fixes the logic that computes sticky offset bounds in order to
correctly take margins into account.
Testing: One test passes
Fixes: #39389
Signed-off-by: Oriol Brufau <obrufau@igalia.com>
When an `<iframe>` cannot scroll because the size of the frame is
greater than or
equal to the size of page contents, chain up the keyboard scroll
operation to the parent frame.
Testing: A new Servo-only WPT tests is added, though needs to be
manually
run with `--product servodriver`.
Signed-off-by: Martin Robinson <mrobinson@igalia.com>
Co-authored-by: Delan Azabani <dazabani@igalia.com>
This undoes #35882 according to the last CSSWG resolution, since this is
required by web compat.
Testing: Modifying the relevant test
Signed-off-by: Oriol Brufau <obrufau@igalia.com>
Instead of having every single embedder implement keyboard scrolling,
handle it in script in the default key event handler. This allows
properly targeting the scroll events to their scroll containers as well
as appropriately sizing "page up" and "page down" scroll deltas.
This change means that when you use the keyboard to scroll, the focused
or most recently clicked `<iframe>` or overflow scroll container is
scrolled, rather than the main frame.
In addition, when a particular scroll frame is larger than its content
in the axis of the scroll, the scrolling operation is chained to
the parent (as in other browsers). One exception is for `<iframe>`s,
which will be implemented in a followup change.
Testing: automated tests runnable locally with `mach test-wpt --product
servodriver`
Signed-off-by: Martin Robinson <mrobinson@igalia.com>
Co-authored-by: Martin Robinson <mrobinson@igalia.com>
Sticky positioning tries to keep an element visible within the nearest
scrollport. However, the element can't be offset to go beyond its
containing block. We implement this as offset bounds.
The problem was that, if the element would already be overflowing its
containing block before applying the sticky positioning, then we were
forcing it to move inside the containing block. That was wrong, and is
solved by flooring or ceiling the offset bounds by zero.
Testing: Adding new tests
Signed-off-by: Oriol Brufau <obrufau@igalia.com>
Co-authored-by: Martin Robinson <mrobinson@igalia.com>
Taffy treats static and sticky positionings as relative. So the inset
properties shifted the element in the relpos way, which was no good.
It's better to just treat them as `auto` instead.
Testing: 3 existing tests pass, and adding a new one.
Fixes: #39399
Signed-off-by: Oriol Brufau <obrufau@igalia.com>
`offsetLeft` and `offsetTop` were ignoring that sticky positioned boxes
can be shifted out of their normal position.
Testing: Various test improvements.
Signed-off-by: Oriol Brufau <obrufau@igalia.com>
Co-authored-by: Martin Robinson <mrobinson@igalia.com>
#33426 only added support for relative positioning on captions with
`caption-side: top`, but forgot about `caption-side: bottom`. This
unifies the logic for both kinds of captions to avoid divergences.
Testing: Modifying an existing test to also cover this case.
Fixes: #39386
Signed-off-by: Oriol Brufau <obrufau@igalia.com>
Changes function signatures to accept `ClipId`, `ExternalScrollId` and
`ScrollTreeNodeId` instead of `&ClipId`, `&ExternalScrollId` and
`&ScrollTreeNodeId`. This avoids several `&` and `*`.
Testing: not needed, no behavior change.
Signed-off-by: Oriol Brufau <obrufau@igalia.com>
Co-authored-by: Martin Robinson <mrobinson@igalia.com>
Laying out a block-level box that establishes an independent formatting
context may require multiple attempts because it needs to avoid floats.
We were previously recomputing the automatic inline size every time,
even if it was always the same. Now we will only compute it once.
Testing: Not needed, no behavior change
Signed-off-by: Oriol Brufau <obrufau@igalia.com>
According to https://drafts.csswg.org/css-inline/#invisible-line-boxes,
if a line box contains non-zero inline-axis margins, padding or borders,
then it can't be phantom.
Therefore, this patch makes adds a `has_inline_pbm` flag to the line.
Note that we can't use the `has_content` flag, because that would add a
soft wrap opportunity between the padding/border/margin and the first
content of the line.
The patch also renames `InlineFormattingContext::had_inflow_content` to
`has_line_boxes`, which is what we care about for collapsing margins
through.
Testing: Adding new tests
Fixes: #39057
Signed-off-by: Oriol Brufau <obrufau@igalia.com>
This patch refactors the logic for propagating overflow to the viewport,
fixing various issues:
- Now we won't propagate from the root element if it has no box. Note
the fix isn't observable in Servo because we lack scrollbars.
- If the first `<body>` element has no box, we won't keep searching for
other `<body>` elements. This deviates from the spec, but aligns us with
other browsers.
- We won't propagate from the `<body>` if it has no box. We were already
handling `display: none` but not `display: contents`. This deviates from
the spec, but aligns us with other browsers.
Also, when we flag the root or `<body>` as having propagated `overflow`
to the viewport, we retrieve the `LayoutBoxBase`. Therefore, now we get
the computed style from the `LayoutBoxBase` in a single operation,
instead of first retrieving the style from the DOM element and then
getting the `LayoutBoxBase` from the box.
Testing: Adding more tests. We were only failing one of them, but it's
hard to test the fixes given that we don't show scrollbars. The tests
that were already passing are useful too, e.g. Firefox fails one of
them.
Signed-off-by: Oriol Brufau <obrufau@igalia.com>
The min-content and max-content inline sizes of an inline formatting
contentext need to take `text-indent` into account. Note it can be set
to a negative amount, so the `ContentSizesComputation` logic needs some
tweaks to handle it well.
Testing: Fixes various WPT tests
Signed-off-by: Oriol Brufau <obrufau@igalia.com>
They only had the writing mode, now they will have the entire computed
style.
This is needed for #39230.
Testing: Not needed, no behavior change
Signed-off-by: Oriol Brufau <obrufau@igalia.com>
This should be the final PR for the Hash Function series that is
trivial.
Of note: I decided to transform `HashMapTracedValues<Atom,..>` to use
FxBuildHasher. This is likely not going to improve performance as Atom's
already have a unique u32 that is used as the Hash but it safes a few
bytes for the RandomState that is normally in the HashMap.
Signed-off-by: Narfinger <Narfinger@users.noreply.github.com>
Testing: Hash function changes should not change functionality, we
slightly decrease the size and unit tests still work.
Signed-off-by: Narfinger <Narfinger@users.noreply.github.com>
`InlineFormattingContextLayout::finish_current_line_and_reset()` has an
early return in case the line has no fragment. However, if the line only
has a forced line break, then we still need to set the baseline.
Testing: Adding new test.
Signed-off-by: Oriol Brufau <obrufau@igalia.com>
Reincorporate the styles to help with the vertical alignment of textual
`<input>` element that was removed by #38775. Followed by adding Servo
specific WPTs to help with these kinds of problem.
Testing: New WPT
Signed-off-by: Jo Steven Novaryo <jo.steven.novaryo@huawei.com>
This change allows that only new display list is built when css
background and border image loaded.
Testing: This change should not change any behaviors so covered by
existing WPT tests.
Signed-off-by: sharpshooter_pt <ibluegalaxy_taoj@163.com>
To find scrolling ancestors, we need to walk up the flat tree and only
consider the elements that are in the chain of containing block
ancestors of an element. `scrollParent` now does this so we can use it
to properly implement `scrollIntoView`.
Testing: There are WPT tests for this change.
---------
Signed-off-by: Martin Robinson <mrobinson@igalia.com>
Co-authored-by: Oriol Brufau <obrufau@igalia.com>
This implements the Default trait for `AxesOverflow`, to avoid having to
manually set both axes to `Overflow::Visible`.
Also implements the conversion from `&ComputedValues` to `AxesOverflow`,
which is the also used for overflow viewport propagation.
And moves the `is_inline_box()` checkinto the `ignores_overflow` logic.
Testing: Not needed, no change in behavior
Signed-off-by: Oriol Brufau <obrufau@igalia.com>
fxhash seems to be unmaintained (see
https://github.com/rustsec/advisory-db/issues/2185) so we should move
away from it.
Additionally, the new crate might be slightly faster.
There is still some cases depending on stylo that have the old fxhash
crate.
Signed-off-by: Narfinger <Narfinger@users.noreply.github.com>
Testing: Changes in Hash should really not show any bugs. And
performance should be comparable.
Signed-off-by: Narfinger <Narfinger@users.noreply.github.com>
A LayoutBox typically has one LayoutBoxBase, or none in the case of
`LayoutBox::DisplayContents`. However, `LayoutBox::InlineLevel` can
contain multiple inline items, each one with its base. But since things
like the style or the fragment flags should be the same for all of them,
getting the first base is sometimes enough.
Testing: not needed, no change in behavior.
Signed-off-by: Oriol Brufau <obrufau@igalia.com>
When encountering such an ancestor, we were returning null instead of
skipping it.
Testing: Adding new subtest for this. And while I'm at it, another one
for the root element, unrelated to this fix.
Signed-off-by: Oriol Brufau <obrufau@igalia.com>
This new API allows getting the element which establishes an element's
scroll container. This will be used to properly implement
`scrollIntoView`. There is still work to do for this API and
`offsetParent` to properly handle ancestors which are
closed-shadow-hidden from the original query element.
In addition, fix an issue where inline boxes were establishing scrolling
containers (they shouldn't do that).
Testing: There are tests for this change.
Fixes: #39096.
Signed-off-by: Martin Robinson <mrobinson@igalia.com>
Co-authored-by: Oriol Brufau <obrufau@igalia.com>
FNV is faster for hashing less than 16 bytes of data and the
cryptographic properties of the default HashMap are not needed for the
various ids.
Testing: This does not change functionality.
Signed-off-by: Narfinger <Narfinger@users.noreply.github.com>
Instead of panicking when doing a geometry script query on a node with
an uninvertible transform, return a zero-sized rectangle at the
untransformed position. This is similar to what Gecko and Blink do
(though it seems there are some differences in positioning this
zero-sized rectangle). Mostly importantly, do not panic.
Testing: This change adds a new WPT crash test.
Fixes: #38848.
Signed-off-by: Martin Robinson <mrobinson@igalia.com>
Move the construction of hit test items for scroll nodes to the display
list construction stage. This way they respect the `z-index` of their
originating fragments and stacking context ordering in general.
Testing: We currently do not have great testing for this as this tests
the combination of hit testing of input events and scrolling at that
point. The completion of WebDriver support should make this easier to
test.
Fixes: #38967
Signed-off-by: coding-joedow <ibluegalaxy_taoj@163.com>
Co-authored-by: kongbai1996 <1782765876@qq.com>
Absolutely positioned elements get blockified, but their static position
still depends on the original display. Therefore, if we encounter an
abspos with an inline-level original display, we will now ensure that
it's handled in an inline formatting context. This way its static
position will correctly take into account things like `text-align`.
Testing: Several WPT tests are now passing.
Fixes: #39017
Signed-off-by: Oriol Brufau <obrufau@igalia.com>
It's expected that script queries be able to interact with collapsed
table rows and columns, so this change starts laying them out. They
still do not affect table dimensions, nor are they painted.
This does not fix all interaction with collapsed rows and columns. For
instance, setting scroll offsets of contained scrolling nodes does not
work properly. It does fix the panic though, which is the most important
thing.
Testing: this change includes a new WPT crash test.
Fixes: #37421.
Signed-off-by: Martin Robinson <mrobinson@igalia.com>
Phantom line boxes should be treated as non-existing for most purposes,
so don't let them affect the baseline of their block container.
Testing: An existing test passes, and also adding a new one which
doesn't rely on `<button>`
Signed-off-by: Oriol Brufau <obrufau@igalia.com>
This method could iterate all the items in the inline formatting context
that was being created. This patch turns it into a field, replacing
`has_uncollapsible_text_content` (so this doesn't increase memory).
Testing: Not needed, no behavior change
Signed-off-by: Oriol Brufau <obrufau@igalia.com>
Parameterize and rename both `Layout::content_box_query` and
`Layout::content_boxes_query` to support the query of rendered padding
area and content area that accounts for transform and scroll. Both of
these query have been misleading for a time since they are using border
box, instead of content box of a Node.
This PR adds a new type `layout_api::BoxAreaType` to be passed from
`ScriptThread` to `LayoutThread` to query the respective area. It is
then used for the query within `IntersectionObserver` to pass several
WPTs.
Testing: Existing WPT Coverage.
---------
Signed-off-by: Jo Steven Novaryo <jo.steven.novaryo@huawei.com>
While building the stacking context tree we were assuming that `<body>`
would have propagated its `overflow` value to the viewport, and thus its
used `overflow` would be `visible`.
However, the element that propagates `overflow` can be the root element
instead. Since #38598 we are correctly taking this into account in
`effective_overflow()`, so we no longer need to do anything special in
the stacking context logic.
Testing: `css/css-overflow/overflow-body-propagation-012.html`
Fixes: #38799
Signed-off-by: Shubham Gupta <shubham13297@gmail.com>
The `<input>` element inner container should be stretch to its
containing block. This would allow the alignment of the text. This is
done by adding `min-width: 100%`. It is required because we are not
using a custom layout contrary to Firefox and Chrome.
Testing: New Servo specific WPT.
---------
Signed-off-by: Jo Steven Novaryo <jo.steven.novaryo@huawei.com>
Measures the memory usage of the stacking context tree in the memory
report of the layout thread by adding `MallocSizeOf` to
`StackingContextTree` and all the types required for that. Also requires
adding `MallocSizeOf` to some webrender types.
Testing: Manually looked at about:memory
<img width="636" height="241" alt="image"
src="https://github.com/user-attachments/assets/6bf9d65a-0bf0-4a99-99b5-ddedba3269c1"
/>
Fixes: https://github.com/servo/servo/issues/38725
---------
Signed-off-by: Rahul Menon <menonrahul02@gmail.com>
The `overflow-*` values of either the root element or the `<body>` get
propagated to the viewport. However, we were missing this part:
> The element from which the value is propagated must then have a used
`overflow` value of `visible`.
See https://drafts.csswg.org/css-overflow/#overflow-propagation
Testing:
- `css/cssom-view/scrolling-quirks-vs-nonquirks.html`
- `css/css-overflow/overflow-body-propagation-007.html`
- `css/css-overflow/overflow-body-propagation-008.html`
- `css/css-overflow/overflow-body-propagation-009.html`
- `css/css-overflow/scrollable-overflow-with-nested-elements-001.html`
- `css/css-overflow/scrollable-overflow-with-nested-elements-002.html`
- `css/css-overflow/scrollable-overflow-with-nested-elements-003.html`
- `css/css-overflow/scrollable-overflow-with-nested-elements-004.html`
- `css/css-overflow/scrollbar-gutter-scroll-into-view.html`
Failures:
- `css/css-overflow/overflow-body-propagation-010.html`
Failing because of missing support for `contain: paint`.
- `css/css-overflow/scrollable-overflow-with-nested-elements-005.html`
Failing because of wrong `data-expected-height`, but correct
`data-expected-scroll-height` which is core of this PR.
`data-expected-height` can be dealt separately.
Fixes: #38248
---------
Signed-off-by: Shubham Gupta <shubham13297@gmail.com>
Signed-off-by: Oriol Brufau <obrufau@igalia.com>
Co-authored-by: Oriol Brufau <obrufau@igalia.com>
`ComputedValuesExt::preferred_aspect_ratio()` was getting the natural
aspect ratio expressed logically as inline over block, but then it was
mixing it with the value of the `aspect-ratio` CSS property, which is
expressed physically as width over height.
Therefore, this changes `ComputedValuesExt::preferred_aspect_ratio()` to
expect the physical natural ratio, and then it takes care to convert the
resulting ratio logically.
Testing: Unneeded. This has no effect in practice because we don't
support `writing-mode` yet.
Signed-off-by: Oriol Brufau <obrufau@igalia.com>
This is simpler, and has been successfully shipped in Blink.
See https://github.com/w3c/csswg-drafts/issues/12053 for more
information.
Testing: Improves WPT tests.
Signed-off-by: Oriol Brufau <obrufau@igalia.com>