Skip to content

Commit

Permalink
LibWeb: Move page scrollbar painting into WebContent
Browse files Browse the repository at this point in the history
  • Loading branch information
kalenikaliaksandr committed Jun 1, 2024
1 parent 29bc40b commit 55e68d4
Show file tree
Hide file tree
Showing 14 changed files with 118 additions and 81 deletions.
43 changes: 15 additions & 28 deletions Ladybird/Qt/WebContentView.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ WebContentView::WebContentView(QWidget* window, WebContentOptions const& web_con
, m_web_content_options(web_content_options)
, m_webdriver_content_ipc_path(webdriver_content_ipc_path)
{
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);

m_client_state.client = parent_client;
m_client_state.page_index = page_index;

Expand All @@ -67,13 +70,6 @@ WebContentView::WebContentView(QWidget* window, WebContentOptions const& web_con
verticalScrollBar()->setSingleStep(24);
horizontalScrollBar()->setSingleStep(24);

QObject::connect(verticalScrollBar(), &QScrollBar::valueChanged, [this](int) {
update_viewport_rect();
});
QObject::connect(horizontalScrollBar(), &QScrollBar::valueChanged, [this](int) {
update_viewport_rect();
});

QObject::connect(qGuiApp, &QGuiApplication::screenRemoved, [this](QScreen*) {
update_screen_rects();
});
Expand All @@ -84,15 +80,6 @@ WebContentView::WebContentView(QWidget* window, WebContentOptions const& web_con

initialize_client((parent_client == nullptr) ? CreateNewClient::Yes : CreateNewClient::No);

on_did_layout = [this](auto content_size) {
verticalScrollBar()->setMinimum(0);
verticalScrollBar()->setMaximum(content_size.height() - m_viewport_rect.height());
verticalScrollBar()->setPageStep(m_viewport_rect.height());
horizontalScrollBar()->setMinimum(0);
horizontalScrollBar()->setMaximum(content_size.width() - m_viewport_rect.width());
horizontalScrollBar()->setPageStep(m_viewport_rect.width());
};

on_ready_to_paint = [this]() {
viewport()->update();
};
Expand Down Expand Up @@ -444,13 +431,13 @@ void WebContentView::paintEvent(QPaintEvent*)
void WebContentView::resizeEvent(QResizeEvent* event)
{
QAbstractScrollArea::resizeEvent(event);
update_viewport_rect();
update_viewport_size();
handle_resize();
}

void WebContentView::set_viewport_rect(Gfx::IntRect rect)
{
m_viewport_rect = rect;
m_viewport_size = rect.size();
client().async_set_viewport_rect(m_client_state.page_index, rect.to_type<Web::DevicePixels>());
}

Expand All @@ -468,23 +455,23 @@ void WebContentView::set_device_pixel_ratio(double device_pixel_ratio)
{
m_device_pixel_ratio = device_pixel_ratio;
client().async_set_device_pixels_per_css_pixel(m_client_state.page_index, m_device_pixel_ratio * m_zoom_level);
update_viewport_rect();
update_viewport_size();
handle_resize();
}

void WebContentView::update_viewport_rect()
void WebContentView::update_viewport_size()
{
auto scaled_width = int(viewport()->width() * m_device_pixel_ratio);
auto scaled_height = int(viewport()->height() * m_device_pixel_ratio);
Gfx::IntRect rect(max(0, horizontalScrollBar()->value()), max(0, verticalScrollBar()->value()), scaled_width, scaled_height);
Gfx::IntRect rect(0, 0, scaled_width, scaled_height);

set_viewport_rect(rect);
}

void WebContentView::update_zoom()
{
client().async_set_device_pixels_per_css_pixel(m_client_state.page_index, m_device_pixel_ratio * m_zoom_level);
update_viewport_rect();
update_viewport_size();
}

void WebContentView::showEvent(QShowEvent* event)
Expand Down Expand Up @@ -661,9 +648,9 @@ void WebContentView::update_cursor(Gfx::StandardCursor cursor)
}
}

Web::DevicePixelRect WebContentView::viewport_rect() const
Web::DevicePixelSize WebContentView::viewport_size() const
{
return m_viewport_rect.to_type<Web::DevicePixels>();
return m_viewport_size.to_type<Web::DevicePixels>();
}

QPoint WebContentView::map_point_to_global_position(Gfx::IntPoint position) const
Expand All @@ -673,12 +660,12 @@ QPoint WebContentView::map_point_to_global_position(Gfx::IntPoint position) cons

Gfx::IntPoint WebContentView::to_content_position(Gfx::IntPoint widget_position) const
{
return widget_position.translated(max(0, horizontalScrollBar()->value()), max(0, verticalScrollBar()->value()));
return widget_position;
}

Gfx::IntPoint WebContentView::to_widget_position(Gfx::IntPoint content_position) const
{
return content_position.translated(-(max(0, horizontalScrollBar()->value())), -(max(0, verticalScrollBar()->value())));
return content_position;
}

bool WebContentView::event(QEvent* event)
Expand Down Expand Up @@ -715,7 +702,7 @@ ErrorOr<String> WebContentView::dump_layout_tree()

void WebContentView::enqueue_native_event(Web::MouseEvent::Type type, QSinglePointEvent const& event)
{
auto position = to_content_position({ event.position().x() * m_device_pixel_ratio, event.position().y() * m_device_pixel_ratio });
Web::DevicePixelPoint position = { event.position().x() * m_device_pixel_ratio, event.position().y() * m_device_pixel_ratio };
auto screen_position = Gfx::IntPoint { event.globalPosition().x() * m_device_pixel_ratio, event.globalPosition().y() * m_device_pixel_ratio };

auto button = get_button_from_qt_event(event);
Expand Down Expand Up @@ -751,7 +738,7 @@ void WebContentView::enqueue_native_event(Web::MouseEvent::Type type, QSinglePoi
}
}

enqueue_input_event(Web::MouseEvent { type, position.to_type<Web::DevicePixels>(), screen_position.to_type<Web::DevicePixels>(), button, buttons, modifiers, wheel_delta_x, wheel_delta_y, nullptr });
enqueue_input_event(Web::MouseEvent { type, position, screen_position.to_type<Web::DevicePixels>(), button, buttons, modifiers, wheel_delta_x, wheel_delta_y, nullptr });
}

struct KeyData : Web::ChromeInputData {
Expand Down
6 changes: 3 additions & 3 deletions Ladybird/Qt/WebContentView.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,11 +90,11 @@ class WebContentView final
// ^WebView::ViewImplementation
virtual void initialize_client(CreateNewClient) override;
virtual void update_zoom() override;
virtual Web::DevicePixelRect viewport_rect() const override;
virtual Web::DevicePixelSize viewport_size() const override;
virtual Gfx::IntPoint to_content_position(Gfx::IntPoint widget_position) const override;
virtual Gfx::IntPoint to_widget_position(Gfx::IntPoint content_position) const override;

void update_viewport_rect();
void update_viewport_size();
void update_cursor(Gfx::StandardCursor cursor);

void enqueue_native_event(Web::MouseEvent::Type, QSinglePointEvent const& event);
Expand All @@ -104,7 +104,7 @@ class WebContentView final

bool m_should_show_line_box_borders { false };

Gfx::IntRect m_viewport_rect;
Gfx::IntSize m_viewport_size;

WebContentOptions m_web_content_options;
StringView m_webdriver_content_ipc_path;
Expand Down
4 changes: 4 additions & 0 deletions Tests/LibWeb/Ref/css-background-clip-text.html
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@
<title>Document</title>

<style>
html {
scrollbar-width: none;
}

p, .container {
border: 0.8em darkviolet;
border-style: dotted double;
Expand Down
3 changes: 3 additions & 0 deletions Tests/LibWeb/Ref/reference/css-background-clip-text-ref.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
body {
background-color: white;
}
html {
scrollbar-width: none;
}
</style>
<!-- To rebase:
1. Open background-clip-text.html in Ladybird
Expand Down
5 changes: 4 additions & 1 deletion Tests/LibWeb/Ref/scroll-iframe.html
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,10 @@
<script>
const iframe = document.createElement("iframe");
iframe.srcdoc = `
<style>body { margin: 0 }</style>
<style>
body { margin: 0 }
html { scrollbar-width: none; }
</style>
<div style="width: 200px; height: 200px; background-color: darkblue"></div>
<div style="width: 200px; height: 200px; background-color: blue"></div>
<div style="width: 200px; height: 200px; background-color: magenta"></div>
Expand Down
2 changes: 1 addition & 1 deletion Userland/Libraries/LibWeb/DOM/Element.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -890,7 +890,7 @@ JS::NonnullGCPtr<Geometry::DOMRectList> Element::get_client_rects() const

if (auto const* paintable_box = this->paintable_box()) {
transform = Gfx::extract_2d_affine_transform(paintable_box->transform());
for (auto const* containing_block = paintable->containing_block(); containing_block; containing_block = containing_block->containing_block()) {
for (auto const* containing_block = paintable->containing_block(); !containing_block->layout_node().is_viewport(); containing_block = containing_block->containing_block()) {
transform = Gfx::extract_2d_affine_transform(containing_block->transform()).multiply(transform);
scroll_offset.translate_by(containing_block->scroll_offset());
}
Expand Down
37 changes: 28 additions & 9 deletions Userland/Libraries/LibWeb/HTML/Navigable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2012,8 +2012,19 @@ void Navigable::set_viewport_rect(CSSPixelRect const& rect)
m_needs_repaint = true;
}

if (m_viewport_scroll_offset != rect.location()) {
m_viewport_scroll_offset = rect.location();
auto new_scroll_offset = m_viewport_scroll_offset;
auto document = active_document();
if (document) {
auto x = new_scroll_offset.x();
auto y = new_scroll_offset.y();
auto scrolling_area = document->paintable_box()->scrollable_overflow_rect().value();
x = max(CSSPixels(0), min(x, scrolling_area.width() - m_size.width()));
y = max(CSSPixels(0), min(y, scrolling_area.height() - m_size.height()));
new_scroll_offset = { x, y };
}

if (m_viewport_scroll_offset != new_scroll_offset) {
m_viewport_scroll_offset = new_scroll_offset;
scroll_offset_did_change();
did_change = true;
m_needs_repaint = true;
Expand All @@ -2027,15 +2038,23 @@ void Navigable::set_viewport_rect(CSSPixelRect const& rect)
HTML::main_thread_event_loop().schedule();
}

void Navigable::perform_scroll_of_viewport(CSSPixelPoint position)
void Navigable::perform_scroll_of_viewport(CSSPixelPoint new_position)
{
auto viewport_rect = this->viewport_rect();
viewport_rect.set_location(position);
set_viewport_rect(viewport_rect);
set_needs_display();
bool did_change = false;

if (is_traversable() && active_browsing_context())
active_browsing_context()->page().client().page_did_request_scroll_to(position);
if (m_viewport_scroll_offset != new_position) {
m_viewport_scroll_offset = new_position;
scroll_offset_did_change();
did_change = true;
m_needs_repaint = true;
}

if (did_change && active_document()) {
active_document()->inform_all_viewport_clients_about_the_current_viewport_rect();
}

// Schedule the HTML event loop to ensure that a `resize` event gets fired.
HTML::main_thread_event_loop().schedule();
}

void Navigable::set_size(CSSPixelSize size)
Expand Down
37 changes: 29 additions & 8 deletions Userland/Libraries/LibWeb/Page/EventHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -151,13 +151,16 @@ Painting::PaintableBox const* EventHandler::paint_root() const
return m_navigable->active_document()->paintable_box();
}

bool EventHandler::handle_mousewheel(CSSPixelPoint position, CSSPixelPoint screen_position, u32 button, u32 buttons, u32 modifiers, int wheel_delta_x, int wheel_delta_y)
bool EventHandler::handle_mousewheel(CSSPixelPoint viewport_position, CSSPixelPoint screen_position, u32 button, u32 buttons, u32 modifiers, int wheel_delta_x, int wheel_delta_y)
{
if (!m_navigable->active_document())
return false;
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);

m_navigable->active_document()->update_layout();

if (!paint_root())
Expand Down Expand Up @@ -214,13 +217,16 @@ bool EventHandler::handle_mousewheel(CSSPixelPoint position, CSSPixelPoint scree
return handled_event;
}

bool EventHandler::handle_mouseup(CSSPixelPoint position, CSSPixelPoint screen_position, u32 button, u32 buttons, u32 modifiers)
bool EventHandler::handle_mouseup(CSSPixelPoint viewport_position, CSSPixelPoint screen_position, u32 button, u32 buttons, u32 modifiers)
{
if (!m_navigable->active_document())
return false;
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);

m_navigable->active_document()->update_layout();

if (!paint_root())
Expand Down Expand Up @@ -336,13 +342,16 @@ bool EventHandler::handle_mouseup(CSSPixelPoint position, CSSPixelPoint screen_p
return handled_event;
}

bool EventHandler::handle_mousedown(CSSPixelPoint position, CSSPixelPoint screen_position, u32 button, u32 buttons, u32 modifiers)
bool EventHandler::handle_mousedown(CSSPixelPoint viewport_position, CSSPixelPoint screen_position, u32 button, u32 buttons, u32 modifiers)
{
if (!m_navigable->active_document())
return false;
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);

m_navigable->active_document()->update_layout();

if (!paint_root())
Expand Down Expand Up @@ -409,6 +418,7 @@ bool EventHandler::handle_mousedown(CSSPixelPoint position, CSSPixelPoint screen
if (candidate->is_focusable()) {
// When a user activates a click focusable focusable area, the user agent must run the focusing steps on the focusable area with focus trigger set to "click".
// Spec Note: Note that focusing is not an activation behavior, i.e. calling the click() method on an element or dispatching a synthetic click event on it won't cause the element to get focused.
dbgln(">before run_focusing_steps");
HTML::run_focusing_steps(candidate.ptr(), nullptr, "click"sv);
did_focus_something = true;
break;
Expand Down Expand Up @@ -436,13 +446,16 @@ bool EventHandler::handle_mousedown(CSSPixelPoint position, CSSPixelPoint screen
return true;
}

bool EventHandler::handle_mousemove(CSSPixelPoint position, CSSPixelPoint screen_position, u32 buttons, u32 modifiers)
bool EventHandler::handle_mousemove(CSSPixelPoint viewport_position, CSSPixelPoint screen_position, u32 buttons, u32 modifiers)
{
if (!m_navigable->active_document())
return false;
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);

m_navigable->active_document()->update_layout();

if (!paint_root())
Expand Down Expand Up @@ -562,13 +575,16 @@ bool EventHandler::handle_mousemove(CSSPixelPoint position, CSSPixelPoint screen
return true;
}

bool EventHandler::handle_doubleclick(CSSPixelPoint position, CSSPixelPoint screen_position, u32 button, u32 buttons, u32 modifiers)
bool EventHandler::handle_doubleclick(CSSPixelPoint viewport_position, CSSPixelPoint screen_position, u32 button, u32 buttons, u32 modifiers)
{
if (!m_navigable->active_document())
return false;
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);

m_navigable->active_document()->update_layout();

if (!paint_root())
Expand Down Expand Up @@ -898,8 +914,10 @@ CSSPixelPoint EventHandler::compute_mouse_event_client_offset(CSSPixelPoint even
// https://w3c.github.io/csswg-drafts/cssom-view/#dom-mouseevent-clientx
// The clientX attribute must return the x-coordinate of the position where the event occurred relative to the origin of the viewport.

auto scroll_offset = m_navigable->active_document()->navigable()->viewport_scroll_offset();
return event_page_position.translated(-scroll_offset);
// auto scroll_offset = m_navigable->active_document()->navigable()->viewport_scroll_offset();
// return event_page_position.translated(scroll_offset);

return event_page_position;
}

CSSPixelPoint EventHandler::compute_mouse_event_page_offset(CSSPixelPoint event_client_offset) const
Expand All @@ -909,9 +927,12 @@ CSSPixelPoint EventHandler::compute_mouse_event_page_offset(CSSPixelPoint event_

// 2. Let offset be the value of the scrollX attribute of the event’s associated Window object, if there is one, or zero otherwise.
auto scroll_offset = m_navigable->active_document()->navigable()->viewport_scroll_offset();
(void)scroll_offset;

// 3. Return the sum of offset and the value of the event’s clientX attribute.
return event_client_offset.translated(scroll_offset);
auto result = event_client_offset.translated(scroll_offset);

return result;
}

CSSPixelPoint EventHandler::compute_mouse_event_movement(CSSPixelPoint screen_position) const
Expand Down
2 changes: 1 addition & 1 deletion Userland/Libraries/LibWeb/Painting/BackgroundPainting.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@ void paint_background(PaintContext& context, Layout::NodeWithStyleAndBoxModelMet
background_positioning_area = get_box(layer.origin).rect;
if (is<Layout::Box>(layout_node)) {
auto* paintable_box = static_cast<Layout::Box const&>(layout_node).paintable_box();
if (paintable_box) {
if (paintable_box && !paintable_box->layout_node().is_viewport()) {
auto scroll_offset = paintable_box->scroll_offset();
background_positioning_area.translate_by(-scroll_offset.x(), -scroll_offset.y());
}
Expand Down
Loading

0 comments on commit 55e68d4

Please sign in to comment.