Commit Graph

63 Commits

Author SHA1 Message Date
Oriol Brufau
d5c82150e0 layout: Add testing API for counting restyled and rebuilt fragments (#42817)
Now `ServoTestUtils.forceLayout()` will provide the number of fragments
that have been restyled and rebuilt. This will be useful to test that
incremental layout works well.

Testing: Adds a test using this new API

---------

Signed-off-by: Oriol Brufau <obrufau@igalia.com>
Signed-off-by: Martin Robinson <mrobinson@igalia.com>
Co-authored-by: Luke Warlow <lwarlow@igalia.com>
Co-authored-by: Martin Robinson <mrobinson@igalia.com>
2026-02-25 21:25:32 +00:00
shuppy
c07682f222 libservo: Allow the embedder to activate accessibility (#42336)
this patch adds a Servo::set_accessibility_active() method that
embedders can use to tell Servo to start building and sending
accessibility trees to the platform, as long as the pref is enabled
(#42333). doing so sets a global flag in the constellation, which is
then propagated to the layout of all existing and future pipelines.

Testing: none yet, no functional change
Fixes: part of #4344

---------

Signed-off-by: delan azabani <dazabani@igalia.com>
Signed-off-by: Alice Boxhall <alice@igalia.com>
Co-authored-by: Alice Boxhall <alice@igalia.com>
2026-02-20 05:56:15 +00:00
webbeef
86403fa4e5 layout: get rid of some collect() calls (#42327)
Profiling a speedometer run showed significant time spent in some layout
function in vector allocations. The main change is to switch the result
of `query_box_areas()` from a Vec<T> to and iterator.

Testing: refactoring with no expected test changes

Signed-off-by: webbeef <me@webbeef.org>
2026-02-06 09:38:49 +00:00
Mukilan Thiyagarajan
79ed814ec1 libservo: Expand the UserContentManager API. (#42288)
The patch adds the following functionality to the per-WebView
`UserContentManager` API.
- Removing a `UserScript` at that was previously added.
- Adding a new `UserStyleSheet` representing a user-origin style sheet.
allow removing user script
- Removing a previously added `UserStyleSheet`.

There might be scope for some improvements in the API:
- `UserScript` and `UserStyleSheet` have different ways of representing
the source location - a `PathBuf` and `Url` respectively. This is due to
how those values are used by the underlying evaluation APIs in script
and stylo. More investigation is needed here and could be addressed in
future patches.

Testing: New unit tests are added for the user stylesheet APIs. Existing
tests have been updated to test the removal of user scripts.
2026-02-05 13:26:54 +00:00
Martin Robinson
2a7d2780b3 fonts: Store shaping output per-character rather than per-code point (#42105)
This change is a reworking of the shaping code and simplification of the
`GlyphRun` data structure.

The shaper was written between 2012 and 2014 against an early version of
Rust. It was originally written to have a single glyph entry per UTF-8
code point. This is useful when you always need to iterate through
glyphs based on UTF-8 code points. Unfortunately, this required a
tri-level data structure to hold detailed glyphs and meant that CJK
characters took over 3x the memory usage of ASCII characters. In
addition, iterating through glyphs (the most common and basic operation
on shaped text) required doing a lookup involving a binary search for
detailed glyphs (ones that had large advances or mapped to more or less
than a single UTF-8 code point).

The new design of the `GlyphStore` is instead based on `chars` in the
input string. These are tracked during layout so that the resulting
glyph output can be interpreted relatively to its original character
offset in the containing IFC. We are already dealing with IFC text on a
per-character basis for a variety of reasons (such as text
transformation and whitespace collapse). In addition, we will now able
to
implement mapping between the character offsets before and after layout
transformations of the original DOM string.

Now the penalty of more complex glyph iteration is only paid when
transforming glyph offsets to character offsets. Currently this is only
done for selections and clicking in text boxes, both of which are much
less common than layout.

This change does not properly handle selections in RTL text, though
rendering and basic selection and visual movement works (though buggy).

It does not seem like this affects the performance of shaping based on
measurement using the text shaping performance counters. This likely
means that the performance of shaping is dominated on our machines by
HarfBuzz. We noticed no performance degradation in Speedometer when run
on a M3 Mac.

Followup work:
 - Properly handle selection in RTL text.
 - Support mapping from original DOM character offsets to offsets in
   layout after text transformation and whitespace collapse. This is now
   possible.

Testing: This causes some tests to pass and a few to fail. This is
likely
due to the fact that we are handling glyphs more consistently while
shaping. Of the new failures:
- `letter-spacing-bengali-yaphala-001.html`,
`letter-spacing-cursive-001.html`, `font-feature-settings-tibetan.html`
where passing before probably because we were not applying letter
spacing to detailed glyphs. These scripts should not have letter spacing
applied to them, because they are cursive -- which we never implemented
properly. It will be handled in a a followup.
- `shaping-arabic-diacritics-001.html`: This was a false pass. The tests
verifies that Arabic diacritics are applied to NBSP. This wasn't
happening before nor after this change, but the results matched anyway.
Now they don't, but before and after are equally broken.
 - 
Fixes: #216
Part of #35540.

---------

Signed-off-by: Martin Robinson <mrobinson@igalia.com>
Co-authored-by: Oriol Brufau <obrufau@igalia.com>
2026-01-26 12:38:04 +00:00
Thomas Cummings
ffb91ac4b1 script: Evict stale SVGs from image cache (#41675)
Parsed and vectorized representations of SVGs in the image cache are
never evicted when SVGs are updated, leading to stale SVGs staying in
the image cache alongside updated ones. This PR:
- adds a stringified uuid field to SVGSVGElement
- adds a map of `SVGSVGElement` uuid to `PendingImageId` in
`ImageCacheImpl`
- adds an optional argument for the uuid to
`ImageCacheImpl::rasterize_vector_image`, which, if provided, removes
any existing parsed svgs associated with the uuid and stores a new entry
of uuid -> `PendingImageId`
- implements `unbind_from_tree` on SVGSVGElement, which clears the
associated images/representations from the image_cache (from
`vector_images`, `rasterized_vector_images`, and `completed_loads`) as
well as from the layout image resolver image cache.

Testing: Each of the following documents should display their (very
flashy) content correctly and memory usage should stay constant
<details>
<summary>Changing SVGSVGElement</summary>

```

<svg height="100" width="100" xmlns="http://www.w3.org/2000/svg">
  <circle id="c" r="1" cx="50" cy="50" fill="red" />
</svg>
<script>
let c = document.querySelector("#c");
let r = 1;
setInterval(() => {
  r += 1;
  c.setAttribute("r", r.toString());
  let tmp = document.createTextNode("ignored");
  c.parentNode.appendChild(tmp);
  tmp.remove();
}, 100);
</script>

```

</details>
<details>
<summary>Unbinding SVGSVGElements</summary>

```

<div id="parent_div">
  <svg id="test" height="100" width="100" xmlns="http://www.w3.org/2000/svg">
    <circle id="c" r="10" cx="50" cy="50" fill="red" />
  </svg>
</div>
<script>
  let div = document.querySelector("#parent_div");
  let svg_html_string = div.innerHTML;
  let svg = document.querySelector("#test");
  let r = 10;
  setInterval(() => {
    svg.remove();
    div.innerHTML = svg_html_string;
    svg = document.querySelector("#test");
    let circle = document.querySelector("#c");
    r += 1;
    circle.setAttribute("r", r.toString());
  }, 100);
</script>

```

</details>
<details>
<summary>Unbinding SVGSVGElements (and rebinding the same SVG)</summary>

This didn't work until I also evicted the associated image from the
layout image resolver image cache and the image cache's
`completed_loads` on SVGSVGElement unbind, so it seems like a useful, if
a bit redundant, test.

```

<div id="parent_div">
  <svg id="test" height="100" width="100" xmlns="http://www.w3.org/2000/svg">
    <circle id="c" r="10" cx="50" cy="50" fill="red" />
  </svg>
</div>
<script>
  let div = document.querySelector("#parent_div");
  let svg_html_string = div.innerHTML;
  let svg = document.querySelector("#test");
  let r = 10;
  setInterval(() => {
    svg.remove();
    div.innerHTML = svg_html_string;
    svg = document.querySelector("#test");
  }, 100);
</script>

```

</details>

Fixes: #41070

---------

Signed-off-by: Tom Cummings <cummings.t287@gmail.com>
2026-01-26 06:02:50 +00:00
Martin Robinson
9c9d9c863f Rename compositing and compositing_traits to paint and paint_api (#42066)
This change finishes the big rename associated with the old
`compositing` crates. Long ago, these crates managed a compositor, like
you might find in a traditional web engine. These days, compositing is
done in WebRender so the name has stopped making much sense. Various
structs inside the crates have already been renamed and this is the
final big change necessary for the rename

Testing: This is just a rename so existing tests should cover it.

Signed-off-by: Martin Robinson <mrobinson@igalia.com>
2026-01-24 09:17:35 +00:00
Martin Robinson
5d0db1fa6a layout: Add unit types to most layout queries (#42002)
This change makes it so that the euclid types returned from layout
queries use the `CSSPixel` unit type when appropriate. The minimal set
of changes are also made to avoid having to convert these types to the
`UnknownUnit` in other places. There is still some casting that has to
happen to deal with the difference between Stylo's `CSSPixel` and
WebRender's `LayoutPixel`, but a followup changes will try to switch to
using one or the other.

Testing: This should not change behavior, so is covered by existing
tests.

Signed-off-by: Martin Robinson <mrobinson@igalia.com>
2026-01-23 15:38:57 +00:00
Rod Borovyk
eacdbd9a34 layout: Accept lengths in arbitrary units for SVG width and height (#40761)
Previously it was only possible to set width and height of SVG elements
in pixels. These changes allow parsing other units like em using a CSS
parser in SVGSVGElement and resolving them to computed values in the
layout code.

Testing: Tested manually
Fixes: -

---------

Signed-off-by: Rodion Borovyk <rodion.borovyk@gmail.com>
2026-01-19 13:31:27 +00:00
Martin Robinson
d5dcdd6e06 script: Add support for setting the edit point with the mouse in <input> and <textarea> (#41906)
This change updates and implements the old `query_text_index` layout
query to properly look for the glyph index of a point within a node's
`Fragment`s. This should work properly with the shadow DOM of both
`<input>` and `<textarea>` elements. In particular, multiple lines are
supported.

Caveats:
 - `<input>` and `<textarea>` that are transformed are currently not
   supported. This will happen in a followup.
 - For multi-line inputs, we should be finding the text offset of the
   nearest line that is within the block range of the click. This will
   happen in a followup.

Testing: This change adds two Servo-specific WPT-style tests. These are
Servo-specific because the behavior of clicking in text fields isn't
fully specified.

Fixes: #35432
Fixes: #10083

Signed-off-by: Martin Robinson <mrobinson@igalia.com>
Co-authored-by: Josh Matthews <josh@joshmatthews.net>
Co-authored-by: Oriol Brufau <obrufau@igalia.com>
2026-01-14 13:23:43 +00:00
Martin Robinson
824f551f03 Rename IOCompositor to Paint (#41176)
For a long time, the "Compositor" hasn't done any compositing. This is
handled by WebRender. In addition the "Compositor" does many other
tasks. This change renames `IOCompositor` to `Paint`.

`Paint` is Servo's paint subsystem and contains multiple `Painter`s.
This change does not rename the crate; that will be done in a
followup change.

Testing: This just renames types and updates comments, so no new tests
are necessary.

---------

Signed-off-by: Martin Robinson <mrobinson@igalia.com>
2025-12-10 15:09:49 +00:00
Martin Robinson
2503684d84 constellation: Break the EventLoop dependency on the initial Pipeline (#40944)
Currently starting a script `EventLoop` depends on sending data about
the initial `Pipeline`. This change breaks this dependency. The goal
here is to:

1. Allow `ScriptThread`s to be shared between `WebView`s. This will
   allow more flexiblity with the way that `ScriptThread`s are created,
   which should allow us to perserve system resources by allowing them
   to be shared between `WebView`s. With this change, we can do away
   with the `InitialPipelineState` entirely, which was gather
   information necessary for both a new `EventLoop` and a new
   `Pipeline`. We no longer have to do many clones when reusing an
   existing even loop.
1. Simplify the way that `EventLoop`s and `Pipeline`s are spawned. Now
   `Pipeline`s are spawned in the same way no matter what.

Now the general order of operations when starting a pipeline is:

1. Get or create an event loop for the pipeline:
    - If the event loop needs to be spawn, spawned it in a new thread or
      process.
2. Send the spawn pipeline message to the event loop (kept alive via an
   `Rc`.

Testing: This should not change behavior in a way that is observable, so
should
be covered by existing tests.

Signed-off-by: Martin Robinson <mrobinson@igalia.com>
2025-11-29 23:30:17 +00:00
Josh Matthews
bbbfe6d299 fonts: Add WebFontDocumentContext for CSS Fonts 4 font fetching (#40301)
Rebase of #37021 with review comments applied. These changes bundle up
the required information from the relevant global when a stylesheet is
added so that any requests for web fonts match the specification.

Testing: Newly passing tests.
Fixes: #36590

---------

Signed-off-by: Uthman Yahaya Baba <uthmanyahayababa@gmail.com>
Signed-off-by: Josh Matthews <josh@joshmatthews.net>
Co-authored-by: Uthman Yahaya Baba <uthmanyahayababa@gmail.com>
2025-11-23 07:45:24 +00:00
Martin Robinson
65deada7ef script: Return only a JoinHandle from ScriptThread constructor (#40571)
The `JoinHandle` was added as a newer return value from this
constructor. Both return values accomplish more or less the same thing.
The difference is that the `Sender` return value is triggered right
before the thread ends while the `JoinHandle` is triggered after thread
completion. One was used in multiprocess mode and one in single process
mode. In any case, the `JoinHandle` works fine for both cases.

Testing: Multiprocess isn't tested currently, but I confirmed that the
ScripThread shut down properly in multiprocess mode with this change.

Signed-off-by: Martin Robinson <mrobinson@igalia.com>
2025-11-12 05:40:28 +00:00
Martin Robinson
b334c9470b constellation: Reuse InitialScriptState and InitialPipelineState in UnprivilegedPipelineContent (#40529)
`UnprivilegedPipelineContent` contains all of the data necessary to
create a new `ScriptThread` with an initial `Pipeline` in a new
process. This change reuses the `InitialScriptState` and
`InitialPipelineState` structs inside `UnprivilegedPipelineContent` and
renames it to `NewScriptEventLoopProcessInfo` to clarify what it does.

In addition, `InitialScriptState` also repeated much of the data of
`NewPipelineInfo`, which is now deduplicated and passed separately to
the `ScriptThreadFactory`.

The overall goal here is to make `ScriptThread` and `Pipeline` creation
separate. A `ScriptThread` contains many `Pipeline`s which come and go,
so it should not depend on a single creation `Pipeline`. This is the
first step toward doing that.

Some inputs to `ScriptThreadFactory` differ based on whether the new
`ScriptThread` is created in a new process or not. This change makes it
so that these input are passed as extra arguments.

Finally these changes have revealed a couple members of data structures
that aren't used. These have been removed.

Testing: This is just a refactor and shouldn't change behavior so is
covered by existing tests.

Signed-off-by: Martin Robinson <mrobinson@igalia.com>
2025-11-10 11:41:59 +00:00
Narfinger
3bfd107686 net: Do not implement Serialize/Deserialize for RasterImage and introduce`SharedRasterImage (#40459)
RasterImage is now not seralizeable and backed by Vec<u8> storage. Add a
new struct `SharedRasterImage` that allows serializeing. This can be
constructed from RasterImage. This introduces some more copying but I
think the tradeoff is ok. Newly introduced copies are for favicon
response to the embedder and EmbedderNotifications.

Testing: Should not change functionality, so covered by existing tests.
Fixes: https://github.com/servo/servo/issues/39626 and related issues.

---------

Signed-off-by: Narfinger <Narfinger@users.noreply.github.com>
2025-11-07 16:49:32 +00:00
WaterWhisperer
241bff962d Change some #[allow]s to #[expect]s (#40458)
Removes some unneeded lints.

Testing: Refactor
Part of: #40383

Signed-off-by: WaterWhisperer <waterwhisperer24@qq.com>
2025-11-06 12:31:48 +00:00
Martin Robinson
fd54ce9059 script: Eagerly update the Device in Layout when it changes (#40432)
Instead of waiting for a reflow to update the `Device` in layout, update
it eagerly. This ensures that media queries can be answered correctly in
script before the next reflow. Also, it ensure that a new reflow is
triggered and reflects the change to the theme or viewport.

In addition, an unused viewport-related message from the Constellation
is removed. This would have needed to be updated by change, but since
it's unused I've just removed it.

This depends on https://github.com/servo/stylo/pull/260.

Testing: This fixes a WebView API test and improves

`/html/semantics/embedded-content/the-img-element/environment-changes/viewport-change.html`.

Fixes: #40395.
Fixes: #40129.

Signed-off-by: Martin Robinson <mrobinson@igalia.com>
2025-11-05 21:17:23 +00:00
WaterWhisperer
a90dff6919 script/layout: Implement Element.currentCSSZoom attribute (#40304)
Implements the `currentCSSZoom` readonly attribute on the Element
interface as
[spec](https://drafts.csswg.org/cssom-view/#dom-element-currentcsszoom).
- Adds a new layout query (`CurrentCSSZoomQuery`) that traverses from
the target element up through its ancestors
- Accumulates the product of all `zoom` CSS property values to compute
the effective zoom
- Returns 1.0 for elements that are not being rendered (display: none or
no layout data)

Testing: Updated WPT (removed 4 FAIL expectations from
`idlharness.html.ini`). Behavior tests in Element-currentCSSZoom.html
remain as expected FAIL because the underlying CSS `zoom` property
implementation in Servo does not yet apply zoom values to layout (the
zoom property is parsed but computed values remain 1.0).
Fixes: #40256

Signed-off-by: WaterWhisperer <waterwhisperer24@qq.com>
2025-11-05 14:25:53 +00:00
Martin Robinson
9fa6303d26 script: Let HTMLCanvasElement manage the ImageKey for canvases (#40375)
This change makes it so that the `HTMLCanvasElement` is responsible for
managing the `ImageKey` for associated `RenderingContext`s. Only
canvases display their contents into WebRender directly, so this makes
it so that keys are not generated for `OffscreenCanvas`.

The main goal here is that `ImageKey`s are always associated with a
particular `WebView`, which isn't possible in the various canvas
backends yet. This is important because each `WebView` may soon have a
different WebRender instance entirely with its own set of `ImageKey`s.

This also allows for clearing `ImageKey`s when canvases are disconnected
from the DOM in a future change. One tricky thing here is placeholder
canvases, which are meant to be driven from workers.

It seems that the implementation isn't correct for these at the moment
as they need to be updated to the specification. Instead, what is
happening is that any existing context / image is completely lost when
converting to an `OffscreenCanvas`.

Testing: This shouldn't change observable behavior, so is covered by
existing tests.
Fixes: This is part of #40261.

---------

Signed-off-by: Martin Robinson <mrobinson@igalia.com>
Signed-off-by: Mukilan Thiyagarajan <mukilan@igalia.com>
Co-authored-by: Mukilan Thiyagarajan <mukilan@igalia.com>
2025-11-04 12:18:30 +00:00
Josh Matthews
61f98c510f script: Do not include transforms and inline boxes in ResizeObserver box area queries (#40323)
These changes implement the restrictions for content rects required by
the ResizeObserver specification: inline boxes must return empty rects,
and any transforms must be ignored.

Testing: Newly passing tests.
Fixes: #40259
Fixes: #40258

---------

Signed-off-by: Josh Matthews <josh@joshmatthews.net>
2025-11-03 15:19:34 +00:00
Josh Matthews
b3868c28e9 script: Report target padding and desired sizes for ResizeObserver notifications (#40254)
We were not following the specification for computing the values of the
content rect. Additionally, any non-content-box observer would get
confused because we never stored the correct size, leading to infinite
notifications when the latest size didn't match the last observed size.

Testing: Various tests now pass.
Fixes: #32549
Fixes: #40107

---------

Signed-off-by: Josh Matthews <josh@joshmatthews.net>
2025-10-31 18:11:34 +00:00
Martin Robinson
ea5929e2a4 pixels: Store decoded images as RGBA premultiplied data (#40158)
Canvas expects input data to be in RGBA premultiplied format and
WebRender already supports RGBA and BGRA data as long as they are
premultiplied. Pre-multiplying up front allows:

- Avoiding many conversions when painting images to canvas.
- Passing the `RasterImage` IpcSharedMemory of the image instead of
creating
  a new one with the premultiplied data every time we upload to
  WebRender. This is a big deal for animated gifs, because before every
  frame was creating a new shared memory segment.

It seems that for rasterized SVGs were were already putting
premultplied data into the `RasterImage` so it's quite likely SVGs were
being composited incorrectly.

Testing: This causes 8 tests to start passing and 2 tests to fail in the
WebGL conformance suite.
The failures are due to the fact that premultiplying alpha is lossy when
alpha is 0. In that case,
the resulting color of a blend operation might be wrong. This is
typically only a problem if you
use RGBA data as RGB data, which is pretty unusual. In the case that you
are blending with
RGBA the final color values will be 0 or close to 0 anyway. Gecko solves
this issue by having a
cacheable surface generation API that can fetch both premulitplied and
unpremulitplied data
from things like image elements. We do not have that yet, but I argue
that this change
is important anyway due to the amount that it reduces memory and file
descriptor usage
as well as the cost of copying image data so much in memory.

Signed-off-by: Martin Robinson <mrobinson@igalia.com>
2025-10-31 10:07:38 +00:00
Martin Robinson
8be7ec73fd pixels: Split Snapshot into SharedSnapshot and Snapshot (#40136)
This splits `Snapshot` into two structs:

- `Snapshot`: A non-serializable owned image buffer that might contain
  either shared memory or a `Vec<u8>`. When mutated the shared memory
  version is converted into a `Vec<u8>` avoiding a copy of the data
  until absolutely necessary.
- `SharedSnapshot`: A serialzable version of `Snapshot` that contains
  only shared memory and is suitable for sending across IPC channels.
  This version is cheaply convertible from and to owned `Snapshot`s as
  long as the source is also a shared memory `Snapshot`.

In addition, it does copyless conversions of `RasterImage` into
`Snapshot`s (including for frame offsets in animated images). Finally,
there are a few minor changes to try harder not to have to do a
`transform()` operation.

Testing: This should not change observable behavior, so is covered by
existing
tests. It should come with a mild performance improvement and open up
the
opportunity for others.
Fixes: #36594.

Signed-off-by: Martin Robinson <mrobinson@igalia.com>
2025-10-26 15:03:30 +00:00
Oriol Brufau
7b60bd7f51 script: Refactor imported stylesheets (#39719)
We were previously using the unsound `StylesheetContents::from_data()`
to create a dummy stylesheet, which we were later replacing with the
actual imported stylesheet once it loaded.

This patch changes that to use `ImportSheet::Pending` instead. But then:
- We need to store the `MediaList` in `StylesheetContextSource`.
Previosuly we stored it in the dummy stylesheet.
- We also need to store an Arc pointer to the `ImportRule`, in order to
update its stylesheet to `ImportSheet::Sheet(stylesheet)` later on.

Testing: Unnecessary, there should be no behavior change
Fixes: #39710

Stylo PR: https://github.com/servo/stylo/pull/250

Signed-off-by: Oriol Brufau <obrufau@igalia.com>
2025-10-09 09:38:33 +00:00
Martin Robinson
9808973467 script: Do not root nodes with animating images (#38996)
Now that we do not need to call `Node::dirty` when an image frame
changes, we no longer have to keep a map of rooted nodes. Instead,
expose a new `AnimatingImages` type that also tracks when the set of
animating images is diryt and new image animation update should maybe be
scheduled.

In addition, cancel any ongoing image animations eagerly when they are
removed from the DOM like we do for CSS animations.

Testing: This should not change behavior and thus is covered by existing
WPT tests.

Signed-off-by: Martin Robinson <mrobinson@igalia.com>
Co-authored-by: Mukilan Thiyagarajan <mukilan@igalia.com>
2025-10-09 07:28:38 +00:00
Tim van der Lippe
6a0f9d1bcb Define conditional_malloc_size_of for all Rc (#39660)
This updates all Rc that were ignored for malloc_size_of to use
conditional_malloc_size_of, unless the type in the Rc itself doesn't
support malloc_size.

Regular expressions used to search for all occurrences:

```
ignore_malloc_size_of = "Rc.*"
ignore_malloc_size_of = "Arc.*"
```

There are a couple left since they have nested Rc, which I don't know
how to fix.

To be able to define these, several new implementations were added to
`malloc_size_of/lib.rs` as well as
`HashMapTracedValues`.

Testing: if it compiles, it's safe

Signed-off-by: Tim van der Lippe <tvanderlippe@gmail.com>
2025-10-05 15:12:16 +00:00
Martin Robinson
cf5b8592bf script: Skip running layout when only updating images or canvas (#38991)
Add a new super-lightweight layout mode that avoids any layout when
canvas is updated or animated images progress to the next frame. In the
future this can also be used for video elements.

Testing: This is a performance optimization, so shouldn't change any
WPT test results.

Signed-off-by: Martin Robinson <mrobinson@igalia.com>
Co-authored-by: Mukilan Thiyagarajan <mukilan@igalia.com>
2025-10-03 13:46:03 +00:00
Martin Robinson
949981163a script: Share Epoch between canvas and layout and update the renderer separately (#39627)
Before both canvas updates and layout had their own `Epoch`. This change
makes it so the `Epoch` is shared. This means that display lists might
have non-consecutive `Epoch`s, but will also allow for the `Epoch` in
the renderer to update even when no new display list is produced. This
is important for #38991. In that PR the display list step can be skipped
for canvas-only updates, but the `Epoch` in the renderer must still
advance.

Testing: This shouldn't change the user-observable behavior and is thus
covered
by existing tests. It should prevent flakiness once #38991 lands.

Signed-off-by: Martin Robinson <mrobinson@igalia.com>
2025-10-03 07:22:48 +00:00
Martin Robinson
ffdb7d3663 script: Chain up keyboard scrolling to parent <iframe>s (#39469)
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>
2025-09-25 11:16:41 +00:00
shuppy
ac8895c3ae script: Move keyboard scrolling to script (#39371)
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>
2025-09-23 20:35:08 +00:00
Narfinger
84465e7768 Removed FnvHash and transformed the rest to FxHashmap (#39233)
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>
2025-09-10 13:34:54 +00:00
Sam
228b240635 layout: Convert animated image delays < 10ms into 100 ms delays (#39189)
Some animated images in the wild have delays <10ms and browsers usually
change them into 100ms as such small timings are unusual.

Relevant code in FF:
https://searchfox.org/firefox-main/source/image/FrameTimeout.h#35

Testing: Manually tested
Fixes: #39187

Signed-off-by: sagudev <16504129+sagudev@users.noreply.github.com>
2025-09-08 14:16:21 +00:00
JoeDow
30d3706a2b layout: allow only repaint when css background and border image loaded (#39201)
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>
2025-09-08 13:23:11 +00:00
Martin Robinson
9f4f598f44 script: Use HTMLElement.scrollParent to implement Element.scrollIntoView (#39144)
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>
2025-09-07 21:44:11 +00:00
Narfinger
e64c53972a Switch the majority of fxhash uses to rustc_hash which is maintained (#39168)
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>
2025-09-06 05:19:47 +00:00
Martin Robinson
2c7866eb24 script/layout: Implement HTMLElement.scrollParent (#39110)
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>
2025-09-03 18:52:15 +00:00
Narfinger
5c7ea4bdee constellation: Use FnvHashMap for hashmaps that use ids as keys (#39106)
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>
2025-09-03 18:15:19 +00:00
Jo Steven Novaryo
10ca3b6fde layout: Parameterize content box query (#38935)
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>
2025-08-27 02:27:53 +00:00
Martin Robinson
87fe202ded script: Integrate animated image updates into ScriptThread event loop (#38941)
Instead of manually triggering `ScriptThread::update_the_rendering`,
have animated images trigger rendering updates via the `ScriptThread`
event loop. This should result in fewer calls to
`ScriptThread::update_the_rendering`.

Testing: This should not change behavior and is thus covered by existing
tests.

Signed-off-by: Martin Robinson <mrobinson@igalia.com>
Co-authored-by: Mukilan Thiyagarajan <mukilan@igalia.com>
2025-08-26 17:24:12 +00:00
Martin Robinson
e7a963cca0 script: Generate only a single frame during "update the rendering" (#38858)
Instead of generating a frame for every display list, which might be one
rendered frame per `<iframe>`, generate only a single frame per call to
"update the rendering." This should make rendering more efficient when
there are `<iframe>`s present and also open up optimizations for
non-display list frames.

Testing: This could potentially reduce flashing of content during
rendering
updates, but that is very difficult to test.

Signed-off-by: Martin Robinson <mrobinson@igalia.com>
2025-08-26 16:09:10 +00:00
Josh Matthews
636e7211e0 script: Measure heap usage of various ignored fields (#38791)
These changes allow using MallocSizeOf/`#[conditional_malloc_size_of]`
on WebIDL callback values, and then fix a grab bag of places in the
script crate that previously ignored those values. There are also some
commits removing ignored fields that involved Arc/Rc that are not WebIDL
callbacks, since they are now easier to support with the
`#[conditional_malloc_size_of]` attribute.

Testing: Manual testing on about:memory for servo.org.

---------

Signed-off-by: Josh Matthews <josh@joshmatthews.net>
2025-08-20 08:43:58 +00:00
Jonathan Schwender
8587536755 Use GenericChannel for script_chan (#38645)
Motivation: 
Using our GenericChannel abstraction allows us to optimize IPC in
single-process mode to just use cross-beam channel.
To keep the diff low, and get early feedback, this PR only tackles a
single channel, but the intention is to port all ipc channels to the
generic channel, which allows us to skip serializing and deserializing
messages in single process mode.

Based on: 
- https://github.com/servo/servo/pull/38638
- https://github.com/servo/servo/pull/38636

Testing: Covered by existing tests

---------

Signed-off-by: Jonathan Schwender <schwenderjonathan@gmail.com>
2025-08-19 09:59:20 +00:00
Simon Wülker
43da933247 script: Implement CSS.registerProperty (#38682)
The implementation is mostly equivalent to
https://searchfox.org/mozilla-central/source/servo/ports/geckolib/glue.rs#9480.

Testing: New web platform tests start to pass

---------

Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>
2025-08-14 13:34:02 +00:00
Oriol Brufau
141413d52e layout: Improve sizing for inline SVG (#38603)
The metadata provided by usvg has unreliable sizes. Ignore it, and rely
on the `width`, `height` and `viewBox` attributes instead.

Note that inline SVG with a natural aspect ratio but no natural sizes
should stretch to the containing block. This is left for a follow-up.

Bumps Stylo to https://github.com/servo/stylo/pull/229

Testing: Improves several WPT.

---------

Signed-off-by: Oriol Brufau <obrufau@igalia.com>
Signed-off-by: Mukilan Thiyagarajan <mukilan@igalia.com>
Co-authored-by: Mukilan Thiyagarajan <mukilan@igalia.com>
2025-08-12 12:45:15 +00:00
Mukilan Thiyagarajan
4c05758ded script: support inline SVG by serializing the subtree (#38188)
This patch adds support for rendering static inline SVG documents in the
DOM tree by serializing the SVGElement's subtree and leveraging the
existing resvg based SVG stack for rendering. Serialiing the subtree is
necessary as resvg's tree representation (roxmltree) is immutable, so we
can't construct the tree incrementally.

Few other design choices here:
1. The `SVGSVGElement` is now treated as a replaced element and the
   layout code is responsible for plumbing the serialized SVG source
   (encoded as a base64 data: url) into the image cache, much like how
   background images are handled.
2. The serialization is done on the script thread after an initial
   layout pass. This is necessary because the serialization code asserts
that it is invoked from script thread i.e we can't call it from layout
   workers.
3. The serialized SVG data: url is cached to avoid recomputing it on
   subsequent layouts. The cache is invalidated when the SVGSVGElement's
   subtree is mutated.

The original SVGSVGElement code was behind the `dom_svg_enabled` pref.
This patch also removes the preference and make SVG support using resvg
available unconditionally.

Below is the analysis of the new test failures:

These tests use inline SVG but used to pass by accident.
They now fail because they contain SVG with no intrinsic
sizing which is not handled by resvg in a way that would
allows us to distinguish it from the sized case. The same
limitation applies to non-inline SVG.

 - /css/CSS2/positioning/absolute-replaced-width-003a.xht
 - /css/CSS2/positioning/absolute-replaced-width-003b.xht
 - /css/CSS2/positioning/absolute-replaced-width-003c.xht

These tests employ CSS styles in the HTML that
target the elements in inline SVG, which is not currently
supported.

-
/css/compositing/mix-blend-mode/mix-blend-mode-plus-lighter-svg-basic.html
 - /css/compositing/mix-blend-mode/mix-blend-mode-plus-lighter-svg.html

This is a tentative test that uses the unsupported 'border-shape' CSS
property. The ref uses SVG, so it used to pass accidentally. The ref
still doesn't render correctly since it also relies on styling SVG
elements using CSS classes in the HTML (instead of inline in SVG).

 - /css/css-borders/tentative/border-shape/border-shape-stroke.html

These tests use the attribute 'clip-path=circle(...)' in the
test, but this doesn't seem to work in resvg.

 - /css/css-masking/clip-path/clip-path-borderBox-1b.html
 - /css/css-masking/clip-path/clip-path-contentBox-1b.html
 - /css/css-masking/clip-path/clip-path-contentBox-1c.html
 - /css/css-masking/clip-path/clip-path-fillBox-1b.html
 - /css/css-masking/clip-path/clip-path-marginBox-1a.html
 - /css/css-masking/clip-path/clip-path-paddingBox-1b.html
 - /css/css-masking/clip-path/clip-path-strokeBox-1b.html
 - /css/css-masking/clip-path/clip-path-strokeBox-1c.html
 - /css/css-masking/clip-path/clip-path-viewBox-1a.html
 - /css/css-masking/clip-path/clip-path-viewBox-1b.html
 - /css/css-masking/clip-path/clip-path-viewBox-1d.html
 - /css/css-masking/clip-path/svg-clip-path-circle-offset.html
 - /css/css-masking/clip-path/svg-clip-path-ellipse-offset.html

Additionally, the below two tests use a `foreignObject` SVG element
which
embeds a html div fragment. This is also not supported by resvg.

 - /css/css-masking/clip-path/clip-path-viewBox-1d.html
 - /css/css-masking/clip-path/clip-path-fillBox-1b.html

The following test fails because of apparent pixel differences
between a circle rendered purely using CSS clip-path vs a circle
rendered in SVG using resvg.

 - /css/css-masking/clip-path/clip-path-contentBox-1c.html

These tests style the inline SVG elements using CSS in the HTML or
separate stylesheet. This is not supported by this implementation.

 - /css-transforms/document-styles/svg-document-styles-{001..004}.html
 - /css-transforms/document-styles/svg-document-styles-012.html
 - /css-transforms/external-styles/svg-external-styles-{001..004}.html
 - /css-transforms/external-styles/svg-external-styles-014.html

These tests seem like they should pass, but they fail because of what
seems like an anti-aliasing issue in the rendering engine. The
transformed element has a thin outline which is causing pixel difference
with the ref:

 - /css/css-transforms/group/svg-transform-group-008.html
 - /css/css-transforms/group/svg-transform-group-009.html
 - /css/css-transforms/group/svg-transform-nested-009.html
 - /css/css-transforms/group/svg-transform-nested-013.html
 - /css/css-transforms/group/svg-transform-nested-014.html
 - /css/css-transforms/group/svg-transform-nested-018.html
 - /css/css-transforms/group/svg-transform-nested-019.html
 - /css/css-transforms/group/svg-transform-nested-008.html

The below tests fail because resvg is calculating the wrong size for the
'rect' inside the SVG. The dimensions of the SVG are established via the
CSS in the HTML, so it seems resvg is using incorrect coordinates for
the children of the svg when explict width/height are not specified in
the root svg element.

 - /css/css-transforms/group/svg-transform-group-011.html
 - /css/css-transforms/group/svg-transform-nested-021.html
 - /css/css-transforms/group/svg-transform-nested-029.html

All these tests use an SVG that doesn't have width nor height attributes
and this causes resvg to use incorrect coordinates for the SVG's
children. In addition, the following tests use the CSS syntax for
transforms inside the SVG (using style attribute) which is not supported
by resvg (it only supports the SVG 1.1 transform syntax).

 - /css/css-transforms/inline-styles/svg-inline-styles-{001..004}.html
 - /css/css-transforms/inline-styles/svg-inline-styles-012.html

In the case of these four tests, the `style` attribute specifies an
invalid transform, but resvg doesn't fallback to the transform specified
via the `transform`  attribute on the same element.

 - /css/css-transforms/inline-styles/svg-inline-styles-005.html
 - /css/css-transforms/inline-styles/svg-inline-styles-006.html
 - /css/css-transforms/inline-styles/svg-inline-styles-010.html
 - /css/css-transforms/inline-styles/svg-inline-styles-013.html

The following test fails because of the lack of width/height in SVG as
described above but it also exposes gaps in our CSS tranform
implementation.

 - /css/css-transforms/preserve3d-and-filter-with-perspective.html

These tests failure because resvg doesn't handle the SVG without
explicit width and height, but specified via CSS in the HTML. In
addition, there are pixel differences between the ref due to
antialiasing issues.

 - /css/css-transforms/matrix/svg-matrix-{005...008}.html
 - /css/css-transforms/matrix/svg-matrix-010.html
 - /css/css-transforms/matrix/svg-matrix-012.html
 - /css/css-transforms/matrix/svg-matrix-{015..069}.html
 - /css/css-transforms/rotate/svg-rotate-angle-45-001.html
 - /css/css-transforms/rotate/svg-rotate-angle-45-011.html
 - /css/css-transforms/rotate/svg-rotate-angle-45-022.html
 - /css/css-transforms/scale/svg-scale-006.html
 - /css/css-transforms/scale/svg-scale-007.html

These tests seem to be failing due to some sort of antialiasing issue,
where a transformed SVG element has a thin border that causes pixel
differences compared to the solid colored reference.

 - /css/css-transforms/skewX/svg-skewx-001.html
 - /css/css-transforms/skewX/svg-skewx-006.html
 - /css/css-transforms/skewX/svg-skewx-011.html
 - /css/css-transforms/skewX/svg-skewx-016.html
 - /css/css-transforms/skewX/svg-skewx-021.html
 - /css/css-transforms/skewX/svg-skewxy-001.html
 - /css/css-transforms/skewY/svg-skewy-001.html
 - /css/css-transforms/skewY/svg-skewy-006.html
 - /css/css-transforms/skewY/svg-skewy-011.html
 - /css/css-transforms/skewY/svg-skewy-016.html
 - /css/css-transforms/skewY/svg-skewy-021.html

These tests specify several SVG attributes such as transform,
vector-effect etc via CSS in the HTML (rather than inline in SVG). The
current implementation doesn't support this.

 - /css/css-transforms/transform-box/stroke-box-mutation-001.html
 - /css/css-transforms/transform-box/stroke-box-mutation-002.html
 - /css/css-transforms/transform-box/stroke-box-mutation-003.html
 - /css/css-transforms/transform-box/stroke-box-mutation-004.html
 - /css/css-transforms/transform-box/svgbox-stroke-box-002.html
 - /css/css-transforms/transform-box/svgbox-stroke-box-003.html
 - /css/css-transforms/transform-box/svgbox-stroke-box-004.html
 - /css/css-transforms/transform-box/svgbox-stroke-box-005.html

These tests depend on 'transform-origin' specified on an element inside
an SVG, but this transform is influenced by the 'tranform-box' set via
CSS in the HTML itself (not the SVG). The current implementation doesn't
support styling the SVG using document styles, so these tests just fail.

- /css/css-transforms/transform-origin/svg-origin-relative-length-*.html

These tests check the fallback behaviour when invalid syntax is
encountered in the 'transform-origin' value. resvg doesn't correctly
fallback to 0,0 causing the tests to fail.

-
/css/css-transforms/transform-origin/svg-origin-relative-length-invalid-001.html
-
/css/css-transforms/transform-origin/svg-origin-relative-length-invalid-002.html
-
/css/css-transforms/transform-origin/svg-origin-relative-length-invalid-003.html
-
/css/css-transforms/transform-origin/svg-origin-relative-length-invalid-004.html

These tests use unimplemented Canvas APIs like 'beginLayer' and
the 'CanvasFilter' constructor and hence fail at runtime.

-
/html/canvas/element/filters/2d.filter.canvasFilterObject.gaussianBlur.tentative.html
-
/html/canvas/element/filters/2d.filter.layers.gaussianBlur.tentative.html
-
/html/canvas/element/layers/2d.layer.anisotropic-blur.isotropic.tentative.html
-
/html/canvas/element/layers/2d.layer.anisotropic-blur.mostly-x.tentative.html
-
/html/canvas/element/layers/2d.layer.anisotropic-blur.mostly-y.tentative.html
-
/html/canvas/element/layers/2d.layer.anisotropic-blur.x-only.tentative.html
-
/html/canvas/element/layers/2d.layer.anisotropic-blur.y-only.tentative.html
-
/html/canvas/element/layers/2d.layer.css-filters.blur-and-shadow.tentative.html
 - /html/canvas/element/layers/2d.layer.css-filters.blur.tentative.html
- /html/canvas/element/layers/2d.layer.css-filters.shadow.tentative.html
 - /html/canvas/element/layers/2d.layer.ctm.layer-filter.tentative.html
-
/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.dropShadow.tentative.html
-
/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.tentative.html
-
/html/canvas/offscreen/filters/2d.filter.layers.dropShadow.tentative.html
-
/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.tentative.html
-
/html/canvas/offscreen/layers/2d.layer.anisotropic-blur.isotropic.tentative.html
-
/html/canvas/offscreen/layers/2d.layer.anisotropic-blur.mostly-x.tentative.html
-
/html/canvas/offscreen/layers/2d.layer.anisotropic-blur.mostly-y.tentative.html
-
/html/canvas/offscreen/layers/2d.layer.anisotropic-blur.x-only.tentative.html
-
/html/canvas/offscreen/layers/2d.layer.anisotropic-blur.y-only.tentative.html
-
/html/canvas/offscreen/layers/2d.layer.css-filters.blur-and-shadow.tentative.html
- /html/canvas/offscreen/layers/2d.layer.css-filters.blur.tentative.html
-
/html/canvas/offscreen/layers/2d.layer.css-filters.shadow.tentative.html
- /html/canvas/offscreen/layers/2d.layer.ctm.layer-filter.tentative.html

These tests fail because resvg doesn't seem to honour the 'translate'
CSS property specified on an SVG element using an inline 'style'
attribute.

 - /css/css-transforms/translate/svg-translate-with-units.html
-
/css/css-transforms/translate/translate-and-transform-attribute-in-svg.html
-
/css/css-transforms/translate/translate-and-transform-css-property-in-svg.html
 - /css/css-transforms/translate/translate-in-svg.html

These tests seem to fail due to the filter effect implementation in
resvg either not being complete or spec compliant.

 - /css/filter-effects/feconvolve-divisor.html
 - /css/filter-effects/feconvolve-region-001.html
 - /css/filter-effects/feconvolve-region-002.html
 - /css/filter-effects/filter-subregion-01.html
 - /css/filter-effects/svg-feimage-002.html
 - /css/filter-effects/svg-feimage-003.html
 - /css/filter-effects/svg-feimage-004.html
 - /css/filter-effects/svg-feoffset-001.html

The test /css/filter-effects/svg-feimage-004.html should ideally PASS
but currently fails because we don't propagate height/width set using
CSS in HTML element to the root SVG, so resvg uses the wrong dimensions
when rendering the children of the SVG.

These failures are due to deficienies in our current implementation
i.e we don't support styling SVG elements using CSS in HTML.

-
/css/css-transforms/gradientTransform/svg-gradientTransform-combination-001.html
 - /css/selectors/sharing-in-svg-use.html

The below test fails as our current implementation relies on resvg to
tell us the intrinsic ratio of the SVG, but this doesn't always work
correctly.

 - /css/css-sizing/svg-intrinsic-size-005.html

This failure is due to lack of proper fallback to no-op transform in
resvg when the `rotate()` syntax is specified with an invalid list e.g
`rotate(90,)`.

 - /css/css-transforms/rotate/svg-rotate-3args-invalid-002.html

This test only passes in CI and based on the raw log output, it seems
that no text inside the SVG is rendered in the CI. This could be an font
stack related issue.

 - /css/css-display/display-contents-svg-elements.html

This test asserts that the CSP blocks loads triggered using `use`
elements in SVG. It used to TIMEOUT as without inline SVG support, no
CSP violation event was triggered. It fails now since the event is now
triggered for the load of the SVG itself (our current implementation
loads inline SVGs as serialized base64 data: urls). This doesn't match
the blocked URL in the use element though.

 - /content-security-policy/img-src/svg-use-blocked.tentative.html

Signed-off-by: Mukilan Thiyagarajan <mukilan@igalia.com>

Signed-off-by: Mukilan Thiyagarajan <mukilan@igalia.com>
2025-08-11 11:07:59 +00:00
Martin Robinson
6651f37c05 script/compositor: Handle cursor updates from script (#38518)
Instead of using WebRender hit testing to update the cursor, base it on
layout hit tests. This allows removing the majority of WebRender hit
test items and finally opens up the possibility of adding support for
custom cursors. In addition, this change fixes an issue where cursors
were not set properly on areas of the viewport that extended past the
page content.

Testing: This is difficult to test as verifying that the cursor changed
properly is beyond the capabilities of Servo's test harnesses.

Signed-off-by: Martin Robinson <mrobinson@igalia.com>
Co-authored-by: Oriol Brufau <obrufau@igalia.com>
2025-08-07 18:49:38 +00:00
Martin Robinson
ad805e3110 compositor/layout: Rely on layout for fine-grained input event hit testing (#38480)
Before, the compositor was responsible for doing the hit testing during
input events within a page. This change moves that hit testing to
layout.  With this change, epoch mismatches are no longer a bit deal and
we can simply ignore them, as the Constellation and Script will take
care of ignoring hit tests against scroll nodes and browsing contexts
that no longer exist. This means that hit testing retry support can be
removed.

Add the concept of a Script `HitTest` that transforms the coarse-grained
renderer hit test into one that hit tests against the actual layout
items.

Testing: Currently we do not have good tests for verifying the behavior
of
input events, but WebDriver tests should cover this.
Fixes: This is part of #37932.
Fixes: #26608.
Fixes: #25282.
Fixes: #38090.

Signed-off-by: Martin Robinson <mrobinson@igalia.com>
Co-authored-by: Oriol Brufau <obrufau@igalia.com>
Co-authored-by: kongbai1996 <1782765876@qq.com>
2025-08-07 08:38:43 +00:00
Gregory Terzian
a99ad240a0 constellation: join on script-threads (#38424)
We currently send exit signals to script-threads, and we also join on
the BHM worker. This ensure the constellation shuts-down only after
script has dropped it's sender to the BHM worker. By joining on the
script-threads, we have a guarantee that they have exited(which is
stronger than having dropped their senders) by the time the
constellation exits.

Testing: Manually opened many tabs and closed the window, both in
single- and multi-process modes.
Fixes: Part of - https://github.com/servo/servo/issues/30849

---------

Signed-off-by: gterzian <2792687+gterzian@users.noreply.github.com>
2025-08-06 18:05:18 +00:00
Martin Robinson
44a11a7c6c script/layout: Ensure a StackingContextTree before IntersectionObserver geometry queries (#38473)
IntersectionObserver needs to be able to query node geometry without
forcing a layout. A previous layout could have run without needing a
`StackingContextTree`. In that case the layout-less query should finish
building the `StackingContextTree` before doing the query.  Add a new
type of layout API which requests that layout finishes building the
StackingContextTree.

This change also slightly simplifies and corrects the naming of
`Element` APIs around client box queries.

Testing: This should fix intermittent failures in WPT tests.
Fixes: #38380.
Fixes: #38390.
Closes: #38400.

Signed-off-by: Martin Robinson <mrobinson@igalia.com>
2025-08-06 13:46:43 +00:00