1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-26 04:37:44 +00:00

LibWeb: Apply scroll boxes offsets after painting commands recording

With this change, instead of applying scroll offsets during the
recording of the painting command list, we do the following:
1. Collect all boxes with scrollable overflow into a PaintContext,
   each with an id and the total amount of scrolling offset accumulated
   from ancestor scrollable boxes.
2. During the recording phase assign a corresponding scroll_frame_id to
   each command that paints content within a scrollable box.
3. Before executing the recorded commands, translate each command that
   has a scroll_frame_id by the accumulated scroll offset.

This approach has following advantages:
- Implementing nested scrollables becomes much simpler, as the
  recording phase only requires the correct assignment of the nearest
  scrollable's scroll_frame_id, while the accumulated offset from
  ancestors is applied subsequently.
- The recording of painting commands is not tied to a specific offset
  within scrollable boxes, which means in the future, it will be
  possible to update the scrolling offset and repaint without the need
  to re-record painting commands.
This commit is contained in:
Aliaksandr Kalenik 2023-12-29 06:10:32 +01:00 committed by Andreas Kling
parent d3025668a4
commit ac6b3c989d
12 changed files with 307 additions and 24 deletions

View file

@ -57,4 +57,22 @@ void ViewportPaintable::paint_all_phases(PaintContext& context)
stacking_context()->paint(context);
}
void ViewportPaintable::collect_scroll_frames(PaintContext& context) const
{
i32 next_id = 0;
for_each_in_subtree_of_type<PaintableBox>([&](auto const& paintable_box) {
if (paintable_box.has_scrollable_overflow()) {
auto offset = paintable_box.scroll_offset();
auto ancestor = paintable_box.parent();
while (ancestor) {
if (ancestor->is_paintable_box() && static_cast<PaintableBox const*>(ancestor)->has_scrollable_overflow())
offset.translate_by(static_cast<PaintableBox const*>(ancestor)->scroll_offset());
ancestor = ancestor->parent();
}
context.scroll_frames().set(&paintable_box, { .id = next_id++, .offset = -offset });
}
return TraversalDecision::Continue;
});
}
}