mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-21 23:20:20 +00:00
LibWeb: Add parent-child relationship between scroll frames
This allows the calculation of the cumulative scroll offset for a scroll frame by adding its scroll offset to the parent’s scroll offset, rather than traversing the containing block chain. While it doesn't greatly simplify calculations for typical scroll frames, it serves as a preparation for supporting "position: sticky".
This commit is contained in:
parent
2565757c7a
commit
866608532a
Notes:
github-actions[bot]
2024-08-30 17:04:01 +00:00
Author: https://github.com/kalenikaliaksandr Commit: https://github.com/LadybirdBrowser/ladybird/commit/866608532a7 Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/1229
8 changed files with 30 additions and 16 deletions
|
@ -24,12 +24,12 @@ CSSPixelRect ClipFrame::clip_rect_for_hit_testing() const
|
|||
VERIFY(!m_clip_rects.is_empty());
|
||||
auto rect = m_clip_rects[0].rect;
|
||||
if (m_clip_rects[0].enclosing_scroll_frame) {
|
||||
rect.translate_by(m_clip_rects[0].enclosing_scroll_frame->cumulative_offset);
|
||||
rect.translate_by(m_clip_rects[0].enclosing_scroll_frame->cumulative_offset());
|
||||
}
|
||||
for (size_t i = 1; i < m_clip_rects.size(); ++i) {
|
||||
auto clip_rect = m_clip_rects[i].rect;
|
||||
if (m_clip_rects[i].enclosing_scroll_frame) {
|
||||
clip_rect.translate_by(m_clip_rects[i].enclosing_scroll_frame->cumulative_offset);
|
||||
clip_rect.translate_by(m_clip_rects[i].enclosing_scroll_frame->cumulative_offset());
|
||||
}
|
||||
rect.intersect(clip_rect);
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@ Optional<int> ClippableAndScrollable::scroll_frame_id() const
|
|||
CSSPixelPoint ClippableAndScrollable::cumulative_offset_of_enclosing_scroll_frame() const
|
||||
{
|
||||
if (m_enclosing_scroll_frame)
|
||||
return m_enclosing_scroll_frame->cumulative_offset;
|
||||
return m_enclosing_scroll_frame->cumulative_offset();
|
||||
return {};
|
||||
}
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@ public:
|
|||
[[nodiscard]] CSSPixelPoint cumulative_offset_of_enclosing_scroll_frame() const;
|
||||
[[nodiscard]] Optional<CSSPixelRect> clip_rect_for_hit_testing() const;
|
||||
|
||||
[[nodiscard]] RefPtr<ScrollFrame const> own_scroll_frame() const { return m_own_scroll_frame; }
|
||||
[[nodiscard]] Optional<int> own_scroll_frame_id() const;
|
||||
[[nodiscard]] CSSPixelPoint own_scroll_frame_offset() const
|
||||
{
|
||||
|
|
|
@ -48,7 +48,7 @@ void DisplayListPlayer::execute(DisplayList& display_list)
|
|||
}
|
||||
|
||||
if (scroll_frame_id.has_value()) {
|
||||
auto const& scroll_offset = scroll_state[scroll_frame_id.value()]->cumulative_offset.to_type<double>().scaled(device_pixels_per_css_pixel).to_type<int>();
|
||||
auto const& scroll_offset = scroll_state[scroll_frame_id.value()]->cumulative_offset().to_type<double>().scaled(device_pixels_per_css_pixel).to_type<int>();
|
||||
command.visit(
|
||||
[&](auto& command) {
|
||||
if constexpr (requires { command.translate_by(scroll_offset); }) {
|
||||
|
|
|
@ -1100,4 +1100,15 @@ void PaintableWithLines::resolve_paint_properties()
|
|||
}
|
||||
}
|
||||
|
||||
RefPtr<ScrollFrame const> PaintableBox::nearest_scroll_frame() const
|
||||
{
|
||||
auto const* paintable = this->containing_block();
|
||||
while (paintable) {
|
||||
if (paintable->own_scroll_frame())
|
||||
return paintable->own_scroll_frame();
|
||||
paintable = paintable->containing_block();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -210,6 +210,8 @@ public:
|
|||
|
||||
virtual void resolve_paint_properties() override;
|
||||
|
||||
RefPtr<ScrollFrame const> nearest_scroll_frame() const;
|
||||
|
||||
protected:
|
||||
explicit PaintableBox(Layout::Box const&);
|
||||
|
||||
|
|
|
@ -12,8 +12,15 @@ namespace Web::Painting {
|
|||
|
||||
struct ScrollFrame : public RefCounted<ScrollFrame> {
|
||||
i32 id { -1 };
|
||||
CSSPixelPoint cumulative_offset;
|
||||
CSSPixelPoint own_offset;
|
||||
RefPtr<ScrollFrame const> parent;
|
||||
|
||||
CSSPixelPoint cumulative_offset() const
|
||||
{
|
||||
if (parent)
|
||||
return parent->cumulative_offset() + own_offset;
|
||||
return own_offset;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -71,6 +71,7 @@ void ViewportPaintable::assign_scroll_frames()
|
|||
if (paintable_box.has_scrollable_overflow() || is<ViewportPaintable>(paintable_box)) {
|
||||
auto scroll_frame = adopt_ref(*new ScrollFrame());
|
||||
scroll_frame->id = next_id++;
|
||||
scroll_frame->parent = paintable_box.nearest_scroll_frame();
|
||||
paintable_box.set_own_scroll_frame(scroll_frame);
|
||||
scroll_state.set(paintable_box, move(scroll_frame));
|
||||
}
|
||||
|
@ -82,13 +83,13 @@ void ViewportPaintable::assign_scroll_frames()
|
|||
return TraversalDecision::Continue;
|
||||
}
|
||||
for (auto block = paintable.containing_block(); block; block = block->containing_block()) {
|
||||
if (auto scroll_frame = scroll_state.get(block); scroll_frame.has_value()) {
|
||||
if (auto scroll_frame = block->own_scroll_frame(); scroll_frame) {
|
||||
if (paintable.is_paintable_box()) {
|
||||
auto const& paintable_box = static_cast<PaintableBox const&>(paintable);
|
||||
const_cast<PaintableBox&>(paintable_box).set_enclosing_scroll_frame(scroll_frame.value());
|
||||
const_cast<PaintableBox&>(paintable_box).set_enclosing_scroll_frame(*scroll_frame);
|
||||
} else if (paintable.is_inline_paintable()) {
|
||||
auto const& inline_paintable = static_cast<InlinePaintable const&>(paintable);
|
||||
const_cast<InlinePaintable&>(inline_paintable).set_enclosing_scroll_frame(scroll_frame.value());
|
||||
const_cast<InlinePaintable&>(inline_paintable).set_enclosing_scroll_frame(*scroll_frame);
|
||||
}
|
||||
return TraversalDecision::Continue;
|
||||
}
|
||||
|
@ -162,14 +163,6 @@ void ViewportPaintable::refresh_scroll_state()
|
|||
for (auto& it : scroll_state) {
|
||||
auto const& paintable_box = *it.key;
|
||||
auto& scroll_frame = *it.value;
|
||||
CSSPixelPoint cumulative_offset;
|
||||
for (auto const* block = &paintable_box.layout_box(); block; block = block->containing_block()) {
|
||||
auto const& block_paintable_box = *block->paintable_box();
|
||||
cumulative_offset.translate_by(block_paintable_box.scroll_offset());
|
||||
if (block->is_fixed_position())
|
||||
break;
|
||||
}
|
||||
scroll_frame.cumulative_offset = -cumulative_offset;
|
||||
scroll_frame.own_offset = -paintable_box.scroll_offset();
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue