mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-22 23:50:19 +00:00
LibWeb: Unify scroll handling between viewport and scrollable boxes
This change causes the viewport to be treated as a "scroll frame," similar to how it already works for boxes with "overflow: scroll." This means that, instead of encoding the viewport translation into a display list, the items will be assigned the scroll frame id of the viewport and then shifted by the scroll offset before execution. In the future it will allow us to reuse a display list for repainting if only scroll offset has changed. As a side effect, it also removes the need for special handling of "position: fixed" because compensating for the viewport offset while painting or hit-testing is no longer necessary. Instead, anything contained within a "position: fixed" element is simply not assigned a scroll frame id, which means it is not shifted by the scroll offset.
This commit is contained in:
parent
00eca78d28
commit
dd8c693725
Notes:
github-actions[bot]
2024-08-11 19:07:23 +00:00
Author: https://github.com/kalenikaliaksandr Commit: https://github.com/LadybirdBrowser/ladybird/commit/dd8c6937254 Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/1026
5 changed files with 25 additions and 30 deletions
|
@ -2012,8 +2012,11 @@ void Navigable::perform_scroll_of_viewport(CSSPixelPoint new_position)
|
|||
scroll_offset_did_change();
|
||||
set_needs_display();
|
||||
|
||||
if (auto document = active_document())
|
||||
if (auto document = active_document()) {
|
||||
document->set_needs_to_refresh_scroll_state(true);
|
||||
document->set_needs_to_refresh_clip_state(true);
|
||||
document->inform_all_viewport_clients_about_the_current_viewport_rect();
|
||||
}
|
||||
}
|
||||
|
||||
// Schedule the HTML event loop to ensure that a `resize` event gets fired.
|
||||
|
|
|
@ -166,8 +166,7 @@ bool EventHandler::handle_mousewheel(CSSPixelPoint viewport_position, CSSPixelPo
|
|||
if (!m_navigable->active_document()->is_fully_active())
|
||||
return false;
|
||||
|
||||
auto scroll_offset = m_navigable->active_document()->navigable()->viewport_scroll_offset();
|
||||
auto position = viewport_position.translated(scroll_offset);
|
||||
auto position = viewport_position;
|
||||
|
||||
m_navigable->active_document()->update_layout();
|
||||
|
||||
|
@ -232,8 +231,7 @@ bool EventHandler::handle_mouseup(CSSPixelPoint viewport_position, CSSPixelPoint
|
|||
if (!m_navigable->active_document()->is_fully_active())
|
||||
return false;
|
||||
|
||||
auto scroll_offset = m_navigable->active_document()->navigable()->viewport_scroll_offset();
|
||||
auto position = viewport_position.translated(scroll_offset);
|
||||
auto position = viewport_position;
|
||||
|
||||
m_navigable->active_document()->update_layout();
|
||||
|
||||
|
@ -359,8 +357,7 @@ bool EventHandler::handle_mousedown(CSSPixelPoint viewport_position, CSSPixelPoi
|
|||
if (!m_navigable->active_document()->is_fully_active())
|
||||
return false;
|
||||
|
||||
auto scroll_offset = m_navigable->active_document()->navigable()->viewport_scroll_offset();
|
||||
auto position = viewport_position.translated(scroll_offset);
|
||||
auto position = viewport_position;
|
||||
|
||||
m_navigable->active_document()->update_layout();
|
||||
|
||||
|
@ -467,8 +464,7 @@ bool EventHandler::handle_mousemove(CSSPixelPoint viewport_position, CSSPixelPoi
|
|||
if (!m_navigable->active_document()->is_fully_active())
|
||||
return false;
|
||||
|
||||
auto scroll_offset = m_navigable->active_document()->navigable()->viewport_scroll_offset();
|
||||
auto position = viewport_position.translated(scroll_offset);
|
||||
auto position = viewport_position;
|
||||
|
||||
m_navigable->active_document()->update_layout();
|
||||
|
||||
|
|
|
@ -294,9 +294,6 @@ Optional<CSSPixelRect> PaintableBox::scroll_thumb_rect(ScrollDirection direction
|
|||
};
|
||||
}
|
||||
|
||||
if (is_viewport())
|
||||
thumb_rect.translate_by(this->scroll_offset());
|
||||
|
||||
return thumb_rect;
|
||||
}
|
||||
|
||||
|
@ -751,14 +748,10 @@ Paintable::DispatchEventOfSameName PaintableBox::handle_mousedown(Badge<EventHan
|
|||
auto vertical_scroll_thumb_rect = scroll_thumb_rect(ScrollDirection::Vertical);
|
||||
auto horizontal_scroll_thumb_rect = scroll_thumb_rect(ScrollDirection::Horizontal);
|
||||
if (vertical_scroll_thumb_rect.has_value() && vertical_scroll_thumb_rect.value().contains(position)) {
|
||||
if (is_viewport())
|
||||
position.translate_by(-scroll_offset());
|
||||
m_last_mouse_tracking_position = position;
|
||||
m_scroll_thumb_dragging_direction = ScrollDirection::Vertical;
|
||||
const_cast<HTML::Navigable&>(*navigable()).event_handler().set_mouse_event_tracking_paintable(this);
|
||||
} else if (horizontal_scroll_thumb_rect.has_value() && horizontal_scroll_thumb_rect.value().contains(position)) {
|
||||
if (is_viewport())
|
||||
position.translate_by(-scroll_offset());
|
||||
m_last_mouse_tracking_position = position;
|
||||
m_scroll_thumb_dragging_direction = ScrollDirection::Horizontal;
|
||||
const_cast<HTML::Navigable&>(*navigable()).event_handler().set_mouse_event_tracking_paintable(this);
|
||||
|
@ -779,9 +772,6 @@ Paintable::DispatchEventOfSameName PaintableBox::handle_mouseup(Badge<EventHandl
|
|||
Paintable::DispatchEventOfSameName PaintableBox::handle_mousemove(Badge<EventHandler>, CSSPixelPoint position, unsigned, unsigned)
|
||||
{
|
||||
if (m_last_mouse_tracking_position.has_value()) {
|
||||
if (is_viewport())
|
||||
position.translate_by(-scroll_offset());
|
||||
|
||||
Gfx::Point<double> scroll_delta;
|
||||
if (m_scroll_thumb_dragging_direction == ScrollDirection::Horizontal)
|
||||
scroll_delta.set_x((position.x() - m_last_mouse_tracking_position->x()).to_double());
|
||||
|
|
|
@ -345,11 +345,6 @@ TraversalDecision StackingContext::hit_test(CSSPixelPoint position, HitTestType
|
|||
};
|
||||
auto transformed_position = affine_transform_matrix().inverse().value_or({}).map(offset_position).to_type<CSSPixels>() + transform_origin;
|
||||
|
||||
if (paintable().is_fixed_position()) {
|
||||
auto scroll_offset = paintable().document().navigable()->viewport_scroll_offset();
|
||||
transformed_position.translate_by(-scroll_offset);
|
||||
}
|
||||
|
||||
// NOTE: Hit testing basically happens in reverse painting order.
|
||||
// https://www.w3.org/TR/CSS22/visuren.html#z-index
|
||||
|
||||
|
|
|
@ -61,13 +61,16 @@ void ViewportPaintable::build_stacking_context_tree()
|
|||
void ViewportPaintable::paint_all_phases(PaintContext& context)
|
||||
{
|
||||
build_stacking_context_tree_if_needed();
|
||||
context.display_list_recorder().translate(-context.device_viewport_rect().location().to_type<int>());
|
||||
stacking_context()->paint(context);
|
||||
}
|
||||
|
||||
void ViewportPaintable::assign_scroll_frames()
|
||||
{
|
||||
int next_id = 0;
|
||||
auto viewport_scroll_frame = adopt_ref(*new ScrollFrame());
|
||||
viewport_scroll_frame->id = 0;
|
||||
scroll_state.set(this, move(viewport_scroll_frame));
|
||||
|
||||
int next_id = 1;
|
||||
for_each_in_subtree_of_type<PaintableBox>([&](auto const& paintable_box) {
|
||||
if (paintable_box.has_scrollable_overflow()) {
|
||||
auto scroll_frame = adopt_ref(*new ScrollFrame());
|
||||
|
@ -78,7 +81,10 @@ void ViewportPaintable::assign_scroll_frames()
|
|||
});
|
||||
|
||||
for_each_in_subtree([&](auto const& paintable) {
|
||||
for (auto block = paintable.containing_block(); !block->is_viewport(); block = block->containing_block()) {
|
||||
if (paintable.is_fixed_position()) {
|
||||
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 (paintable.is_paintable_box()) {
|
||||
auto const& paintable_box = static_cast<PaintableBox const&>(paintable);
|
||||
|
@ -87,10 +93,13 @@ void ViewportPaintable::assign_scroll_frames()
|
|||
auto const& inline_paintable = static_cast<InlinePaintable const&>(paintable);
|
||||
const_cast<InlinePaintable&>(inline_paintable).set_enclosing_scroll_frame(scroll_frame.value());
|
||||
}
|
||||
break;
|
||||
return TraversalDecision::Continue;
|
||||
}
|
||||
if (block->is_fixed_position()) {
|
||||
return TraversalDecision::Continue;
|
||||
}
|
||||
}
|
||||
return TraversalDecision::Continue;
|
||||
VERIFY_NOT_REACHED();
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -137,9 +146,11 @@ void ViewportPaintable::refresh_scroll_state()
|
|||
auto const& paintable_box = *it.key;
|
||||
auto& scroll_frame = *it.value;
|
||||
CSSPixelPoint offset;
|
||||
for (auto const* block = &paintable_box.layout_box(); !block->is_viewport(); block = block->containing_block()) {
|
||||
for (auto const* block = &paintable_box.layout_box(); block; block = block->containing_block()) {
|
||||
auto const& block_paintable_box = *block->paintable_box();
|
||||
offset.translate_by(block_paintable_box.scroll_offset());
|
||||
if (block->is_fixed_position())
|
||||
break;
|
||||
}
|
||||
scroll_frame.offset = -offset;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue