LibWeb+WebContent: Move scrollbar painting into WebContent

The main intention of this change is to have a consistent look and
behavior across all scrollbars, including elements with
`overflow: scroll` and `overflow: auto`, iframes, and a page.

Before:
- Page's scrollbar is painted by Browser (Qt/AppKit) using the
  corresponding UI framework style,
- Both WebContent and Browser know the scroll position offset.
- WebContent uses did_request_scroll_to() IPC call to send updates.
- Browser uses set_viewport_rect() to send updates.

After:
- Page's scrollbar is painted on WebContent side using the same style as
  currently used for elements with `overflow: scroll` and
  `overflow: auto`. A nice side effects: scrollbars are now painted for
  iframes, and page's scrollbar respects scrollbar-width CSS property.
- Only WebContent knows scroll position offset.
- did_request_scroll_to() is no longer used.
- set_viewport_rect() is changed to set_viewport_size().
This commit is contained in:
Aliaksandr Kalenik 2024-06-03 17:53:55 +03:00 committed by Andreas Kling
parent eb909118bf
commit 5285e22f2a
Notes: sideshowbarker 2024-07-17 01:28:15 +09:00
30 changed files with 147 additions and 186 deletions

View file

@ -351,22 +351,6 @@ static void copy_data_to_clipboard(StringView data, NSPasteboardType pasteboard_
self.event_being_redispatched = nil; self.event_being_redispatched = nil;
}; };
m_web_view_bridge->on_scroll = [self](auto position) {
auto content_rect = [self frame];
auto document_rect = [[self documentView] frame];
auto ns_position = Ladybird::gfx_point_to_ns_point(position);
ns_position.x = max(ns_position.x, document_rect.origin.x);
ns_position.x = min(ns_position.x, document_rect.size.width - content_rect.size.width);
ns_position.y = max(ns_position.y, document_rect.origin.y);
ns_position.y = min(ns_position.y, document_rect.size.height - content_rect.size.height);
[self scrollToPoint:ns_position];
[[self scrollView] reflectScrolledClipView:self];
[self updateViewportRect:Ladybird::WebViewBridge::ForResize::No];
};
m_web_view_bridge->on_cursor_change = [self](auto cursor) { m_web_view_bridge->on_cursor_change = [self](auto cursor) {
if (cursor == Gfx::StandardCursor::Hidden) { if (cursor == Gfx::StandardCursor::Hidden) {
if (!m_hidden_cursor.has_value()) { if (!m_hidden_cursor.has_value()) {

View file

@ -35,20 +35,6 @@ WebViewBridge::WebViewBridge(Vector<Web::DevicePixelRect> screen_rects, float de
, m_preferred_color_scheme(preferred_color_scheme) , m_preferred_color_scheme(preferred_color_scheme)
{ {
m_device_pixel_ratio = device_pixel_ratio; m_device_pixel_ratio = device_pixel_ratio;
on_scroll_by_delta = [this](auto x_delta, auto y_delta) {
auto position = m_viewport_rect.location();
position.set_x(position.x() + x_delta);
position.set_y(position.y() + y_delta);
if (on_scroll_to_point)
on_scroll_to_point(position);
};
on_scroll_to_point = [this](auto position) {
if (on_scroll)
on_scroll(to_widget_position(position));
};
} }
WebViewBridge::~WebViewBridge() = default; WebViewBridge::~WebViewBridge() = default;
@ -67,9 +53,9 @@ void WebViewBridge::set_system_visibility_state(bool is_visible)
void WebViewBridge::set_viewport_rect(Gfx::IntRect viewport_rect, ForResize for_resize) void WebViewBridge::set_viewport_rect(Gfx::IntRect viewport_rect, ForResize for_resize)
{ {
viewport_rect.set_size(scale_for_device(viewport_rect.size(), m_device_pixel_ratio)); viewport_rect.set_size(scale_for_device(viewport_rect.size(), m_device_pixel_ratio));
m_viewport_rect = viewport_rect; m_viewport_size = viewport_rect.size();
client().async_set_viewport_rect(m_client_state.page_index, m_viewport_rect.to_type<Web::DevicePixels>()); client().async_set_viewport_size(m_client_state.page_index, m_viewport_size.to_type<Web::DevicePixels>());
if (for_resize == ForResize::Yes) { if (for_resize == ForResize::Yes) {
handle_resize(); handle_resize();
@ -126,9 +112,9 @@ void WebViewBridge::update_zoom()
on_zoom_level_changed(); on_zoom_level_changed();
} }
Web::DevicePixelRect WebViewBridge::viewport_rect() const Web::DevicePixelSize WebViewBridge::viewport_size() const
{ {
return m_viewport_rect.to_type<Web::DevicePixels>(); return m_viewport_size.to_type<Web::DevicePixels>();
} }
Gfx::IntPoint WebViewBridge::to_content_position(Gfx::IntPoint widget_position) const Gfx::IntPoint WebViewBridge::to_content_position(Gfx::IntPoint widget_position) const

View file

@ -53,18 +53,17 @@ public:
Function<NonnullRefPtr<WebView::WebContentClient>()> on_request_web_content; Function<NonnullRefPtr<WebView::WebContentClient>()> on_request_web_content;
Function<void()> on_zoom_level_changed; Function<void()> on_zoom_level_changed;
Function<void(Gfx::IntPoint)> on_scroll;
private: private:
WebViewBridge(Vector<Web::DevicePixelRect> screen_rects, float device_pixel_ratio, WebContentOptions const&, Optional<StringView> webdriver_content_ipc_path, Web::CSS::PreferredColorScheme); WebViewBridge(Vector<Web::DevicePixelRect> screen_rects, float device_pixel_ratio, WebContentOptions const&, Optional<StringView> webdriver_content_ipc_path, Web::CSS::PreferredColorScheme);
virtual void update_zoom() 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_content_position(Gfx::IntPoint widget_position) const override;
virtual Gfx::IntPoint to_widget_position(Gfx::IntPoint content_position) const override; virtual Gfx::IntPoint to_widget_position(Gfx::IntPoint content_position) const override;
Vector<Web::DevicePixelRect> m_screen_rects; Vector<Web::DevicePixelRect> m_screen_rects;
Gfx::IntRect m_viewport_rect; Gfx::IntSize m_viewport_size;
WebContentOptions m_web_content_options; WebContentOptions m_web_content_options;
Optional<StringView> m_webdriver_content_ipc_path; Optional<StringView> m_webdriver_content_ipc_path;

View file

@ -91,8 +91,8 @@ static constexpr CGFloat const WINDOW_HEIGHT = 800;
[self.search_panel setHidden:YES]; [self.search_panel setHidden:YES];
auto* scroll_view = [[NSScrollView alloc] init]; auto* scroll_view = [[NSScrollView alloc] init];
[scroll_view setHasVerticalScroller:YES]; [scroll_view setHasVerticalScroller:NO];
[scroll_view setHasHorizontalScroller:YES]; [scroll_view setHasHorizontalScroller:NO];
[scroll_view setLineScroll:24]; [scroll_view setLineScroll:24];
[scroll_view setContentView:self.web_view]; [scroll_view setContentView:self.web_view];

View file

@ -55,6 +55,9 @@ WebContentView::WebContentView(QWidget* window, WebContentOptions const& web_con
, m_web_content_options(web_content_options) , m_web_content_options(web_content_options)
, m_webdriver_content_ipc_path(webdriver_content_ipc_path) , m_webdriver_content_ipc_path(webdriver_content_ipc_path)
{ {
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
m_client_state.client = parent_client; m_client_state.client = parent_client;
m_client_state.page_index = page_index; m_client_state.page_index = page_index;
@ -68,13 +71,6 @@ WebContentView::WebContentView(QWidget* window, WebContentOptions const& web_con
verticalScrollBar()->setSingleStep(24); verticalScrollBar()->setSingleStep(24);
horizontalScrollBar()->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*) { QObject::connect(qGuiApp, &QGuiApplication::screenRemoved, [this](QScreen*) {
update_screen_rects(); update_screen_rects();
}); });
@ -85,29 +81,10 @@ WebContentView::WebContentView(QWidget* window, WebContentOptions const& web_con
initialize_client((parent_client == nullptr) ? CreateNewClient::Yes : CreateNewClient::No); 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]() { on_ready_to_paint = [this]() {
viewport()->update(); viewport()->update();
}; };
on_scroll_by_delta = [this](auto x_delta, auto y_delta) {
horizontalScrollBar()->setValue(max(0, horizontalScrollBar()->value() + x_delta));
verticalScrollBar()->setValue(max(0, verticalScrollBar()->value() + y_delta));
};
on_scroll_to_point = [this](auto position) {
horizontalScrollBar()->setValue(position.x());
verticalScrollBar()->setValue(position.y());
};
on_cursor_change = [this](auto cursor) { on_cursor_change = [this](auto cursor) {
update_cursor(cursor); update_cursor(cursor);
}; };
@ -445,14 +422,14 @@ void WebContentView::paintEvent(QPaintEvent*)
void WebContentView::resizeEvent(QResizeEvent* event) void WebContentView::resizeEvent(QResizeEvent* event)
{ {
QAbstractScrollArea::resizeEvent(event); QAbstractScrollArea::resizeEvent(event);
update_viewport_rect(); update_viewport_size();
handle_resize(); handle_resize();
} }
void WebContentView::set_viewport_rect(Gfx::IntRect rect) 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>()); client().async_set_viewport_size(m_client_state.page_index, rect.size().to_type<Web::DevicePixels>());
} }
void WebContentView::set_window_size(Gfx::IntSize size) void WebContentView::set_window_size(Gfx::IntSize size)
@ -469,15 +446,15 @@ void WebContentView::set_device_pixel_ratio(double device_pixel_ratio)
{ {
m_device_pixel_ratio = 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); 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(); handle_resize();
} }
void WebContentView::update_viewport_rect() void WebContentView::update_viewport_size()
{ {
auto scaled_width = int(viewport()->width() * m_device_pixel_ratio); auto scaled_width = int(viewport()->width() * m_device_pixel_ratio);
auto scaled_height = int(viewport()->height() * 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); set_viewport_rect(rect);
} }
@ -485,7 +462,7 @@ void WebContentView::update_viewport_rect()
void WebContentView::update_zoom() void WebContentView::update_zoom()
{ {
client().async_set_device_pixels_per_css_pixel(m_client_state.page_index, m_device_pixel_ratio * m_zoom_level); 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) void WebContentView::showEvent(QShowEvent* event)
@ -661,9 +638,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 QPoint WebContentView::map_point_to_global_position(Gfx::IntPoint position) const
@ -673,12 +650,12 @@ QPoint WebContentView::map_point_to_global_position(Gfx::IntPoint position) cons
Gfx::IntPoint WebContentView::to_content_position(Gfx::IntPoint widget_position) const 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 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) bool WebContentView::event(QEvent* event)
@ -715,7 +692,7 @@ ErrorOr<String> WebContentView::dump_layout_tree()
void WebContentView::enqueue_native_event(Web::MouseEvent::Type type, QSinglePointEvent const& event) 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 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); auto button = get_button_from_qt_event(event);
@ -751,7 +728,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 { struct KeyData : Web::ChromeInputData {

View file

@ -90,11 +90,11 @@ private:
// ^WebView::ViewImplementation // ^WebView::ViewImplementation
virtual void initialize_client(CreateNewClient) override; virtual void initialize_client(CreateNewClient) override;
virtual void update_zoom() 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_content_position(Gfx::IntPoint widget_position) const override;
virtual Gfx::IntPoint to_widget_position(Gfx::IntPoint content_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 update_cursor(Gfx::StandardCursor cursor);
void enqueue_native_event(Web::MouseEvent::Type, QSinglePointEvent const& event); void enqueue_native_event(Web::MouseEvent::Type, QSinglePointEvent const& event);
@ -104,7 +104,7 @@ private:
bool m_should_show_line_box_borders { false }; bool m_should_show_line_box_borders { false };
Gfx::IntRect m_viewport_rect; Gfx::IntSize m_viewport_size;
WebContentOptions m_web_content_options; WebContentOptions m_web_content_options;
StringView m_webdriver_content_ipc_path; StringView m_webdriver_content_ipc_path;

View file

@ -7,6 +7,10 @@
<title>Document</title> <title>Document</title>
<style> <style>
html {
scrollbar-width: none;
}
p, .container { p, .container {
border: 0.8em darkviolet; border: 0.8em darkviolet;
border-style: dotted double; border-style: dotted double;

View file

@ -5,6 +5,9 @@
body { body {
background-color: white; background-color: white;
} }
html {
scrollbar-width: none;
}
</style> </style>
<!-- To rebase: <!-- To rebase:
1. Open background-clip-text.html in Ladybird 1. Open background-clip-text.html in Ladybird

View file

@ -11,7 +11,10 @@
<script> <script>
const iframe = document.createElement("iframe"); const iframe = document.createElement("iframe");
iframe.srcdoc = ` 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: darkblue"></div>
<div style="width: 200px; height: 200px; background-color: blue"></div> <div style="width: 200px; height: 200px; background-color: blue"></div>
<div style="width: 200px; height: 200px; background-color: magenta"></div> <div style="width: 200px; height: 200px; background-color: magenta"></div>

View file

@ -1146,6 +1146,11 @@ void Document::update_layout()
paintable()->recompute_selection_states(); paintable()->recompute_selection_states();
m_needs_layout = false; m_needs_layout = false;
// Scrolling by zero offset will clamp scroll offset back to valid range if it was out of bounds
// after the viewport size change.
if (auto window = this->window())
window->scroll_by(0, 0);
} }
[[nodiscard]] static CSS::RequiredInvalidationAfterStyleChange update_style_recursively(Node& node, CSS::StyleComputer& style_computer) [[nodiscard]] static CSS::RequiredInvalidationAfterStyleChange update_style_recursively(Node& node, CSS::StyleComputer& style_computer)

View file

@ -890,7 +890,7 @@ JS::NonnullGCPtr<Geometry::DOMRectList> Element::get_client_rects() const
if (auto const* paintable_box = this->paintable_box()) { if (auto const* paintable_box = this->paintable_box()) {
transform = Gfx::extract_2d_affine_transform(paintable_box->transform()); 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->is_viewport(); containing_block = containing_block->containing_block()) {
transform = Gfx::extract_2d_affine_transform(containing_block->transform()).multiply(transform); transform = Gfx::extract_2d_affine_transform(containing_block->transform()).multiply(transform);
scroll_offset.translate_by(containing_block->scroll_offset()); scroll_offset.translate_by(containing_block->scroll_offset());
} }

View file

@ -1993,60 +1993,36 @@ CSSPixelPoint Navigable::to_top_level_position(CSSPixelPoint a_position)
return position; return position;
} }
void Navigable::set_viewport_rect(CSSPixelRect const& rect) void Navigable::set_viewport_size(CSSPixelSize size)
{
bool did_change = false;
if (m_size != rect.size()) {
m_size = rect.size();
if (auto document = active_document()) {
// NOTE: Resizing the viewport changes the reference value for viewport-relative CSS lengths.
document->invalidate_style();
document->set_needs_layout();
}
did_change = true;
m_needs_repaint = true;
}
if (m_viewport_scroll_offset != rect.location()) {
m_viewport_scroll_offset = rect.location();
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::perform_scroll_of_viewport(CSSPixelPoint position)
{
auto viewport_rect = this->viewport_rect();
viewport_rect.set_location(position);
set_viewport_rect(viewport_rect);
set_needs_display();
if (is_traversable() && active_browsing_context())
active_browsing_context()->page().client().page_did_request_scroll_to(position);
}
void Navigable::set_size(CSSPixelSize size)
{ {
if (m_size == size) if (m_size == size)
return; return;
m_size = size;
m_size = size;
if (auto document = active_document()) { if (auto document = active_document()) {
// NOTE: Resizing the viewport changes the reference value for viewport-relative CSS lengths.
document->invalidate_style(); document->invalidate_style();
document->set_needs_layout(); document->set_needs_layout();
} }
m_needs_repaint = true;
if (auto document = active_document()) { if (auto document = active_document()) {
document->inform_all_viewport_clients_about_the_current_viewport_rect(); 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::perform_scroll_of_viewport(CSSPixelPoint new_position)
{
if (m_viewport_scroll_offset != new_position) {
m_viewport_scroll_offset = new_position;
scroll_offset_did_change();
m_needs_repaint = true;
if (auto document = active_document())
document->inform_all_viewport_clients_about_the_current_viewport_rect();
} }
// Schedule the HTML event loop to ensure that a `resize` event gets fired. // Schedule the HTML event loop to ensure that a `resize` event gets fired.

View file

@ -160,11 +160,10 @@ public:
CSSPixelRect to_top_level_rect(CSSPixelRect const&); CSSPixelRect to_top_level_rect(CSSPixelRect const&);
CSSPixelSize size() const { return m_size; } CSSPixelSize size() const { return m_size; }
void set_size(CSSPixelSize);
CSSPixelPoint viewport_scroll_offset() const { return m_viewport_scroll_offset; } CSSPixelPoint viewport_scroll_offset() const { return m_viewport_scroll_offset; }
CSSPixelRect viewport_rect() const { return { m_viewport_scroll_offset, m_size }; } CSSPixelRect viewport_rect() const { return { m_viewport_scroll_offset, m_size }; }
void set_viewport_rect(CSSPixelRect const&); void set_viewport_size(CSSPixelSize);
void perform_scroll_of_viewport(CSSPixelPoint position); void perform_scroll_of_viewport(CSSPixelPoint position);
void set_needs_display(); void set_needs_display();

View file

@ -32,7 +32,7 @@ void FrameBox::did_set_content_size()
ReplacedBox::did_set_content_size(); ReplacedBox::did_set_content_size();
if (dom_node().content_navigable()) if (dom_node().content_navigable())
dom_node().content_navigable()->set_size(paintable_box()->content_size()); dom_node().content_navigable()->set_viewport_size(paintable_box()->content_size());
} }
JS::GCPtr<Painting::Paintable> FrameBox::create_paintable() const JS::GCPtr<Painting::Paintable> FrameBox::create_paintable() const

View file

@ -151,13 +151,16 @@ Painting::PaintableBox const* EventHandler::paint_root() const
return m_navigable->active_document()->paintable_box(); 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()) if (!m_navigable->active_document())
return false; return false;
if (!m_navigable->active_document()->is_fully_active()) if (!m_navigable->active_document()->is_fully_active())
return false; 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(); m_navigable->active_document()->update_layout();
if (!paint_root()) if (!paint_root())
@ -214,13 +217,16 @@ bool EventHandler::handle_mousewheel(CSSPixelPoint position, CSSPixelPoint scree
return handled_event; 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()) if (!m_navigable->active_document())
return false; return false;
if (!m_navigable->active_document()->is_fully_active()) if (!m_navigable->active_document()->is_fully_active())
return false; 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(); m_navigable->active_document()->update_layout();
if (!paint_root()) if (!paint_root())
@ -292,8 +298,6 @@ bool EventHandler::handle_mouseup(CSSPixelPoint position, CSSPixelPoint screen_p
// //
// https://html.spec.whatwg.org/multipage/document-sequences.html#the-rules-for-choosing-a-navigable // https://html.spec.whatwg.org/multipage/document-sequences.html#the-rules-for-choosing-a-navigable
auto top_level_position = m_navigable->active_document()->navigable()->to_top_level_position(position);
if (JS::GCPtr<HTML::HTMLAnchorElement const> link = node->enclosing_link_element()) { if (JS::GCPtr<HTML::HTMLAnchorElement const> link = node->enclosing_link_element()) {
JS::NonnullGCPtr<DOM::Document> document = *m_navigable->active_document(); JS::NonnullGCPtr<DOM::Document> document = *m_navigable->active_document();
auto href = link->href(); auto href = link->href();
@ -302,13 +306,13 @@ bool EventHandler::handle_mouseup(CSSPixelPoint position, CSSPixelPoint screen_p
if (button == UIEvents::MouseButton::Middle) { if (button == UIEvents::MouseButton::Middle) {
m_navigable->page().client().page_did_middle_click_link(url, link->target().to_byte_string(), modifiers); m_navigable->page().client().page_did_middle_click_link(url, link->target().to_byte_string(), modifiers);
} else if (button == UIEvents::MouseButton::Secondary) { } else if (button == UIEvents::MouseButton::Secondary) {
m_navigable->page().client().page_did_request_link_context_menu(top_level_position, url, link->target().to_byte_string(), modifiers); m_navigable->page().client().page_did_request_link_context_menu(viewport_position, url, link->target().to_byte_string(), modifiers);
} }
} else if (button == UIEvents::MouseButton::Secondary) { } else if (button == UIEvents::MouseButton::Secondary) {
if (is<HTML::HTMLImageElement>(*node)) { if (is<HTML::HTMLImageElement>(*node)) {
auto& image_element = verify_cast<HTML::HTMLImageElement>(*node); auto& image_element = verify_cast<HTML::HTMLImageElement>(*node);
auto image_url = image_element.document().parse_url(image_element.src()); auto image_url = image_element.document().parse_url(image_element.src());
m_navigable->page().client().page_did_request_image_context_menu(top_level_position, image_url, "", modifiers, image_element.bitmap()); m_navigable->page().client().page_did_request_image_context_menu(viewport_position, image_url, "", modifiers, image_element.bitmap());
} else if (is<HTML::HTMLMediaElement>(*node)) { } else if (is<HTML::HTMLMediaElement>(*node)) {
auto& media_element = verify_cast<HTML::HTMLMediaElement>(*node); auto& media_element = verify_cast<HTML::HTMLMediaElement>(*node);
@ -321,9 +325,9 @@ bool EventHandler::handle_mouseup(CSSPixelPoint position, CSSPixelPoint screen_p
.is_looping = media_element.has_attribute(HTML::AttributeNames::loop), .is_looping = media_element.has_attribute(HTML::AttributeNames::loop),
}; };
m_navigable->page().did_request_media_context_menu(media_element.unique_id(), top_level_position, "", modifiers, move(menu)); m_navigable->page().did_request_media_context_menu(media_element.unique_id(), viewport_position, "", modifiers, move(menu));
} else { } else {
m_navigable->page().client().page_did_request_context_menu(top_level_position); m_navigable->page().client().page_did_request_context_menu(viewport_position);
} }
} }
} }
@ -336,13 +340,16 @@ after_node_use:
return handled_event; 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()) if (!m_navigable->active_document())
return false; return false;
if (!m_navigable->active_document()->is_fully_active()) if (!m_navigable->active_document()->is_fully_active())
return false; 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(); m_navigable->active_document()->update_layout();
if (!paint_root()) if (!paint_root())
@ -436,13 +443,16 @@ bool EventHandler::handle_mousedown(CSSPixelPoint position, CSSPixelPoint screen
return true; 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()) if (!m_navigable->active_document())
return false; return false;
if (!m_navigable->active_document()->is_fully_active()) if (!m_navigable->active_document()->is_fully_active())
return false; 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(); m_navigable->active_document()->update_layout();
if (!paint_root()) if (!paint_root())
@ -562,13 +572,16 @@ bool EventHandler::handle_mousemove(CSSPixelPoint position, CSSPixelPoint screen
return true; 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()) if (!m_navigable->active_document())
return false; return false;
if (!m_navigable->active_document()->is_fully_active()) if (!m_navigable->active_document()->is_fully_active())
return false; 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(); m_navigable->active_document()->update_layout();
if (!paint_root()) if (!paint_root())

View file

@ -147,6 +147,15 @@ CSSPixelRect Page::device_to_css_rect(DevicePixelRect rect) const
}; };
} }
CSSPixelSize Page::device_to_css_size(DevicePixelSize size) const
{
auto scale = client().device_pixels_per_css_pixel();
return {
CSSPixels::floored_value_for(size.width().value() / scale),
CSSPixels::floored_value_for(size.height().value() / scale),
};
}
DevicePixelRect Page::enclosing_device_rect(CSSPixelRect rect) const DevicePixelRect Page::enclosing_device_rect(CSSPixelRect rect) const
{ {
auto scale = client().device_pixels_per_css_pixel(); auto scale = client().device_pixels_per_css_pixel();

View file

@ -82,6 +82,7 @@ public:
DevicePixelPoint css_to_device_point(CSSPixelPoint) const; DevicePixelPoint css_to_device_point(CSSPixelPoint) const;
DevicePixelRect css_to_device_rect(CSSPixelRect) const; DevicePixelRect css_to_device_rect(CSSPixelRect) const;
CSSPixelRect device_to_css_rect(DevicePixelRect) const; CSSPixelRect device_to_css_rect(DevicePixelRect) const;
CSSPixelSize device_to_css_size(DevicePixelSize) const;
DevicePixelRect enclosing_device_rect(CSSPixelRect) const; DevicePixelRect enclosing_device_rect(CSSPixelRect) const;
DevicePixelRect rounded_device_rect(CSSPixelRect) const; DevicePixelRect rounded_device_rect(CSSPixelRect) const;

View file

@ -245,7 +245,7 @@ void paint_background(PaintContext& context, Layout::NodeWithStyleAndBoxModelMet
background_positioning_area = get_box(layer.origin).rect; background_positioning_area = get_box(layer.origin).rect;
if (is<Layout::Box>(layout_node)) { if (is<Layout::Box>(layout_node)) {
auto* paintable_box = static_cast<Layout::Box const&>(layout_node).paintable_box(); auto* paintable_box = static_cast<Layout::Box const&>(layout_node).paintable_box();
if (paintable_box) { if (paintable_box && !paintable_box->is_viewport()) {
auto scroll_offset = paintable_box->scroll_offset(); auto scroll_offset = paintable_box->scroll_offset();
background_positioning_area.translate_by(-scroll_offset.x(), -scroll_offset.y()); background_positioning_area.translate_by(-scroll_offset.x(), -scroll_offset.y());
} }

View file

@ -53,6 +53,12 @@ PaintableWithLines::~PaintableWithLines()
CSSPixelPoint PaintableBox::scroll_offset() const CSSPixelPoint PaintableBox::scroll_offset() const
{ {
if (is_viewport()) {
auto navigable = document().navigable();
VERIFY(navigable);
return navigable->viewport_scroll_offset();
}
auto const& node = layout_node(); auto const& node = layout_node();
if (node.is_generated_for_before_pseudo_element()) if (node.is_generated_for_before_pseudo_element())
return node.pseudo_element_generator()->scroll_offset(DOM::Element::ScrollOffsetFor::PseudoBefore); return node.pseudo_element_generator()->scroll_offset(DOM::Element::ScrollOffsetFor::PseudoBefore);
@ -230,7 +236,7 @@ bool PaintableBox::is_scrollable(ScrollDirection direction) const
auto overflow = direction == ScrollDirection::Horizontal ? computed_values().overflow_x() : computed_values().overflow_y(); auto overflow = direction == ScrollDirection::Horizontal ? computed_values().overflow_x() : computed_values().overflow_y();
auto scrollable_overflow_size = direction == ScrollDirection::Horizontal ? scrollable_overflow_rect()->width() : scrollable_overflow_rect()->height(); auto scrollable_overflow_size = direction == ScrollDirection::Horizontal ? scrollable_overflow_rect()->width() : scrollable_overflow_rect()->height();
auto scrollport_size = direction == ScrollDirection::Horizontal ? absolute_padding_box_rect().width() : absolute_padding_box_rect().height(); auto scrollport_size = direction == ScrollDirection::Horizontal ? absolute_padding_box_rect().width() : absolute_padding_box_rect().height();
if (overflow == CSS::Overflow::Auto) if (is_viewport() || overflow == CSS::Overflow::Auto)
return scrollable_overflow_size > scrollport_size; return scrollable_overflow_size > scrollport_size;
return overflow == CSS::Overflow::Scroll; return overflow == CSS::Overflow::Scroll;
} }
@ -255,20 +261,27 @@ Optional<CSSPixelRect> PaintableBox::scroll_thumb_rect(ScrollDirection direction
if (scroll_overflow_size > scrollport_size) if (scroll_overflow_size > scrollport_size)
thumb_position = scroll_offset * (scrollport_size - thumb_size) / (scroll_overflow_size - scrollport_size); thumb_position = scroll_offset * (scrollport_size - thumb_size) / (scroll_overflow_size - scrollport_size);
CSSPixelRect thumb_rect;
if (direction == ScrollDirection::Horizontal) { if (direction == ScrollDirection::Horizontal) {
return CSSPixelRect { thumb_rect = {
padding_rect.left() + thumb_position, padding_rect.left() + thumb_position,
padding_rect.bottom() - scrollbar_thumb_thickness, padding_rect.bottom() - scrollbar_thumb_thickness,
thumb_size, thumb_size,
scrollbar_thumb_thickness scrollbar_thumb_thickness
}; };
} else {
thumb_rect = {
padding_rect.right() - scrollbar_thumb_thickness,
padding_rect.top() + thumb_position,
scrollbar_thumb_thickness,
thumb_size
};
} }
return CSSPixelRect {
padding_rect.right() - scrollbar_thumb_thickness, if (is_viewport())
padding_rect.top() + thumb_position, thumb_rect.translate_by(this->scroll_offset());
scrollbar_thumb_thickness,
thumb_size return thumb_rect;
};
} }
void PaintableBox::paint(PaintContext& context, PaintPhase phase) const void PaintableBox::paint(PaintContext& context, PaintPhase phase) const
@ -314,7 +327,7 @@ void PaintableBox::paint(PaintContext& context, PaintPhase phase) const
} }
auto scrollbar_width = computed_values().scrollbar_width(); auto scrollbar_width = computed_values().scrollbar_width();
if (!layout_box().is_viewport() && phase == PaintPhase::Overlay && scrollbar_width != CSS::ScrollbarWidth::None) { if (phase == PaintPhase::Overlay && scrollbar_width != CSS::ScrollbarWidth::None) {
auto color = Color(Color::NamedColor::DarkGray).with_alpha(128); auto color = Color(Color::NamedColor::DarkGray).with_alpha(128);
int thumb_corner_radius = static_cast<int>(context.rounded_device_pixels(scrollbar_thumb_thickness / 2)); int thumb_corner_radius = static_cast<int>(context.rounded_device_pixels(scrollbar_thumb_thickness / 2));
if (auto thumb_rect = scroll_thumb_rect(ScrollDirection::Horizontal); thumb_rect.has_value()) { if (auto thumb_rect = scroll_thumb_rect(ScrollDirection::Horizontal); thumb_rect.has_value()) {

View file

@ -203,6 +203,8 @@ public:
Optional<CSSPixelRect> get_clip_rect() const; Optional<CSSPixelRect> get_clip_rect() const;
bool is_viewport() const { return layout_box().is_viewport(); }
protected: protected:
explicit PaintableBox(Layout::Box const&); explicit PaintableBox(Layout::Box const&);

View file

@ -80,7 +80,7 @@ void ViewportPaintable::assign_scroll_frames()
}); });
for_each_in_subtree([&](auto const& paintable) { for_each_in_subtree([&](auto const& paintable) {
for (auto block = paintable.containing_block(); block; block = block->containing_block()) { for (auto block = paintable.containing_block(); !block->is_viewport(); block = block->containing_block()) {
if (auto scroll_frame = scroll_state.get(block); scroll_frame.has_value()) { if (auto scroll_frame = scroll_state.get(block); scroll_frame.has_value()) {
if (paintable.is_paintable_box()) { if (paintable.is_paintable_box()) {
auto const& paintable_box = static_cast<PaintableBox const&>(paintable); auto const& paintable_box = static_cast<PaintableBox const&>(paintable);
@ -110,7 +110,7 @@ void ViewportPaintable::assign_clip_frames()
}); });
for_each_in_subtree([&](auto const& paintable) { for_each_in_subtree([&](auto const& paintable) {
for (auto block = paintable.containing_block(); block; block = block->containing_block()) { for (auto block = paintable.containing_block(); !block->is_viewport(); block = block->containing_block()) {
if (auto clip_frame = clip_state.get(block); clip_frame.has_value()) { if (auto clip_frame = clip_state.get(block); clip_frame.has_value()) {
if (paintable.is_paintable_box()) { if (paintable.is_paintable_box()) {
auto const& paintable_box = static_cast<PaintableBox const&>(paintable); auto const& paintable_box = static_cast<PaintableBox const&>(paintable);
@ -136,7 +136,7 @@ void ViewportPaintable::refresh_scroll_state()
auto const& paintable_box = *it.key; auto const& paintable_box = *it.key;
auto& scroll_frame = *it.value; auto& scroll_frame = *it.value;
CSSPixelPoint offset; CSSPixelPoint offset;
for (auto const* block = &paintable_box.layout_box(); block; block = block->containing_block()) { for (auto const* block = &paintable_box.layout_box(); !block->is_viewport(); block = block->containing_block()) {
auto const& block_paintable_box = *block->paintable_box(); auto const& block_paintable_box = *block->paintable_box();
offset.translate_by(block_paintable_box.scroll_offset()); offset.translate_by(block_paintable_box.scroll_offset());
} }

View file

@ -89,7 +89,7 @@ RefPtr<Gfx::Bitmap> SVGDecodedImageData::render(Gfx::IntSize size) const
{ {
auto bitmap = Gfx::Bitmap::create(Gfx::BitmapFormat::BGRA8888, size).release_value_but_fixme_should_propagate_errors(); auto bitmap = Gfx::Bitmap::create(Gfx::BitmapFormat::BGRA8888, size).release_value_but_fixme_should_propagate_errors();
VERIFY(m_document->navigable()); VERIFY(m_document->navigable());
m_document->navigable()->set_viewport_rect({ 0, 0, size.width(), size.height() }); m_document->navigable()->set_viewport_size(size.to_type<CSSPixels>());
m_document->update_layout(); m_document->update_layout();
Painting::CommandList painting_commands; Painting::CommandList painting_commands;

View file

@ -392,18 +392,18 @@ void ViewImplementation::resize_backing_stores_if_needed(WindowResizeInProgress
m_client_state.has_usable_bitmap = false; m_client_state.has_usable_bitmap = false;
auto viewport_rect = this->viewport_rect(); auto viewport_size = this->viewport_size();
if (viewport_rect.is_empty()) if (viewport_size.is_empty())
return; return;
Web::DevicePixelSize minimum_needed_size; Web::DevicePixelSize minimum_needed_size;
if (window_resize_in_progress == WindowResizeInProgress::Yes) { if (window_resize_in_progress == WindowResizeInProgress::Yes) {
// Pad the minimum needed size so that we don't have to keep reallocating backing stores while the window is being resized. // Pad the minimum needed size so that we don't have to keep reallocating backing stores while the window is being resized.
minimum_needed_size = { viewport_rect.width() + 256, viewport_rect.height() + 256 }; minimum_needed_size = { viewport_size.width() + 256, viewport_size.height() + 256 };
} else { } else {
// If we're not in the middle of a resize, we can shrink the backing store size to match the viewport size. // If we're not in the middle of a resize, we can shrink the backing store size to match the viewport size.
minimum_needed_size = viewport_rect.size(); minimum_needed_size = viewport_size;
m_client_state.front_bitmap = {}; m_client_state.front_bitmap = {};
m_client_state.back_bitmap = {}; m_client_state.back_bitmap = {};
} }
@ -417,7 +417,7 @@ void ViewImplementation::resize_backing_stores_if_needed(WindowResizeInProgress
backing_store.bitmap = new_bitmap_or_error.release_value(); backing_store.bitmap = new_bitmap_or_error.release_value();
backing_store.id = m_client_state.next_bitmap_id++; backing_store.id = m_client_state.next_bitmap_id++;
} }
backing_store.last_painted_size = viewport_rect.size(); backing_store.last_painted_size = viewport_size;
} }
}; };
@ -430,7 +430,7 @@ void ViewImplementation::resize_backing_stores_if_needed(WindowResizeInProgress
if (front_bitmap.id != old_front_bitmap_id || back_bitmap.id != old_back_bitmap_id) { if (front_bitmap.id != old_front_bitmap_id || back_bitmap.id != old_back_bitmap_id) {
client().async_add_backing_store(page_id(), front_bitmap.id, front_bitmap.bitmap->to_shareable_bitmap(), back_bitmap.id, client().async_add_backing_store(page_id(), front_bitmap.id, front_bitmap.bitmap->to_shareable_bitmap(), back_bitmap.id,
back_bitmap.bitmap->to_shareable_bitmap()); back_bitmap.bitmap->to_shareable_bitmap());
client().async_set_viewport_rect(page_id(), viewport_rect); client().async_set_viewport_size(page_id(), viewport_size);
} }
} }

View file

@ -205,7 +205,7 @@ public:
Function<void(String const&)> on_inspector_executed_console_script; Function<void(String const&)> on_inspector_executed_console_script;
Function<IPC::File()> on_request_worker_agent; Function<IPC::File()> on_request_worker_agent;
virtual Web::DevicePixelRect viewport_rect() const = 0; virtual Web::DevicePixelSize viewport_size() const = 0;
virtual Gfx::IntPoint to_content_position(Gfx::IntPoint widget_position) const = 0; virtual Gfx::IntPoint to_content_position(Gfx::IntPoint widget_position) const = 0;
virtual Gfx::IntPoint to_widget_position(Gfx::IntPoint content_position) const = 0; virtual Gfx::IntPoint to_widget_position(Gfx::IntPoint content_position) const = 0;

View file

@ -161,10 +161,10 @@ void ConnectionFromClient::traverse_the_history_by_delta(u64 page_id, i32 delta)
page->page().traverse_the_history_by_delta(delta); page->page().traverse_the_history_by_delta(delta);
} }
void ConnectionFromClient::set_viewport_rect(u64 page_id, Web::DevicePixelRect const& rect) void ConnectionFromClient::set_viewport_size(u64 page_id, Web::DevicePixelSize const size)
{ {
if (auto page = this->page(page_id); page.has_value()) if (auto page = this->page(page_id); page.has_value())
page->set_viewport_rect(rect); page->set_viewport_size(size);
} }
void ConnectionFromClient::add_backing_store(u64 page_id, i32 front_bitmap_id, Gfx::ShareableBitmap const& front_bitmap, i32 back_bitmap_id, Gfx::ShareableBitmap const& back_bitmap) void ConnectionFromClient::add_backing_store(u64 page_id, i32 front_bitmap_id, Gfx::ShareableBitmap const& front_bitmap, i32 back_bitmap_id, Gfx::ShareableBitmap const& back_bitmap)

View file

@ -58,7 +58,7 @@ private:
virtual void load_html(u64 page_id, ByteString const&) override; virtual void load_html(u64 page_id, ByteString const&) override;
virtual void reload(u64 page_id) override; virtual void reload(u64 page_id) override;
virtual void traverse_the_history_by_delta(u64 page_id, i32 delta) override; virtual void traverse_the_history_by_delta(u64 page_id, i32 delta) override;
virtual void set_viewport_rect(u64 page_id, Web::DevicePixelRect const&) override; virtual void set_viewport_size(u64 page_id, Web::DevicePixelSize const) override;
virtual void key_event(u64 page_id, Web::KeyEvent const&) override; virtual void key_event(u64 page_id, Web::KeyEvent const&) override;
virtual void mouse_event(u64 page_id, Web::MouseEvent const&) override; virtual void mouse_event(u64 page_id, Web::MouseEvent const&) override;
virtual void add_backing_store(u64 page_id, i32 front_bitmap_id, Gfx::ShareableBitmap const& front_bitmap, i32 back_bitmap_id, Gfx::ShareableBitmap const& back_bitmap) override; virtual void add_backing_store(u64 page_id, i32 front_bitmap_id, Gfx::ShareableBitmap const& front_bitmap, i32 back_bitmap_id, Gfx::ShareableBitmap const& back_bitmap) override;

View file

@ -233,9 +233,9 @@ void PageClient::paint(Web::DevicePixelRect const& content_rect, Gfx::Bitmap& ta
} }
} }
void PageClient::set_viewport_rect(Web::DevicePixelRect const& rect) void PageClient::set_viewport_size(Web::DevicePixelSize const& size)
{ {
page().top_level_traversable()->set_viewport_rect(page().device_to_css_rect(rect)); page().top_level_traversable()->set_viewport_size(page().device_to_css_size(size));
} }
void PageClient::page_did_request_cursor_change(Gfx::StandardCursor cursor) void PageClient::page_did_request_cursor_change(Gfx::StandardCursor cursor)
@ -321,7 +321,7 @@ void PageClient::page_did_request_scroll_to(Web::CSSPixelPoint scroll_position)
// scroll on browser side happens. // scroll on browser side happens.
auto viewport = page().top_level_traversable()->viewport_rect(); auto viewport = page().top_level_traversable()->viewport_rect();
viewport.set_location(scroll_position); viewport.set_location(scroll_position);
page().top_level_traversable()->set_viewport_rect(viewport); page().top_level_traversable()->set_viewport_size(viewport.size());
auto device_scroll_position = page().css_to_device_point(scroll_position); auto device_scroll_position = page().css_to_device_point(scroll_position);
client().async_did_request_scroll_to(m_id, device_scroll_position.to_type<int>()); client().async_did_request_scroll_to(m_id, device_scroll_position.to_type<int>());

View file

@ -44,7 +44,7 @@ public:
virtual void paint(Web::DevicePixelRect const& content_rect, Gfx::Bitmap&, Web::PaintOptions = {}) override; virtual void paint(Web::DevicePixelRect const& content_rect, Gfx::Bitmap&, Web::PaintOptions = {}) override;
void set_palette_impl(Gfx::PaletteImpl&); void set_palette_impl(Gfx::PaletteImpl&);
void set_viewport_rect(Web::DevicePixelRect const&); void set_viewport_size(Web::DevicePixelSize const&);
void set_screen_rects(Vector<Web::DevicePixelRect, 4> const& rects, size_t main_screen_index) { m_screen_rect = rects[main_screen_index]; } void set_screen_rects(Vector<Web::DevicePixelRect, 4> const& rects, size_t main_screen_index) { m_screen_rect = rects[main_screen_index]; }
void set_device_pixels_per_css_pixel(float device_pixels_per_css_pixel) { m_device_pixels_per_css_pixel = device_pixels_per_css_pixel; } void set_device_pixels_per_css_pixel(float device_pixels_per_css_pixel) { m_device_pixels_per_css_pixel = device_pixels_per_css_pixel; }
void set_preferred_color_scheme(Web::CSS::PreferredColorScheme); void set_preferred_color_scheme(Web::CSS::PreferredColorScheme);

View file

@ -29,7 +29,7 @@ endpoint WebContentServer
add_backing_store(u64 page_id, i32 front_bitmap_id, Gfx::ShareableBitmap front_bitmap, i32 back_bitmap_id, Gfx::ShareableBitmap back_bitmap) =| add_backing_store(u64 page_id, i32 front_bitmap_id, Gfx::ShareableBitmap front_bitmap, i32 back_bitmap_id, Gfx::ShareableBitmap back_bitmap) =|
ready_to_paint(u64 page_id) =| ready_to_paint(u64 page_id) =|
set_viewport_rect(u64 page_id, Web::DevicePixelRect rect) =| set_viewport_size(u64 page_id, Web::DevicePixelSize size) =|
key_event(u64 page_id, Web::KeyEvent event) =| key_event(u64 page_id, Web::KeyEvent event) =|
mouse_event(u64 page_id, Web::MouseEvent event) =| mouse_event(u64 page_id, Web::MouseEvent event) =|

View file

@ -105,8 +105,8 @@ public:
view->client().async_update_system_theme(0, move(theme)); view->client().async_update_system_theme(0, move(theme));
view->m_viewport_rect = { { 0, 0 }, window_size }; view->m_viewport_size = window_size;
view->client().async_set_viewport_rect(0, view->m_viewport_rect.to_type<Web::DevicePixels>()); view->client().async_set_viewport_size(0, view->m_viewport_size.to_type<Web::DevicePixels>());
view->client().async_set_window_size(0, window_size.to_type<Web::DevicePixels>()); view->client().async_set_window_size(0, window_size.to_type<Web::DevicePixels>());
if (!web_driver_ipc_path.is_empty()) if (!web_driver_ipc_path.is_empty())
@ -168,19 +168,6 @@ private:
, m_cookie_jar(move(cookie_jar)) , m_cookie_jar(move(cookie_jar))
, m_request_client(move(request_client)) , m_request_client(move(request_client))
{ {
on_scroll_to_point = [this](auto position) {
m_viewport_rect.set_location(position);
client().async_set_viewport_rect(0, m_viewport_rect.to_type<Web::DevicePixels>());
};
on_scroll_by_delta = [this](auto x_delta, auto y_delta) {
auto position = m_viewport_rect.location();
position.set_x(position.x() + x_delta);
position.set_y(position.y() + y_delta);
if (on_scroll_to_point)
on_scroll_to_point(position);
};
on_get_cookie = [this](auto const& url, auto source) { on_get_cookie = [this](auto const& url, auto source) {
return m_cookie_jar->get_cookie(url, source); return m_cookie_jar->get_cookie(url, source);
}; };
@ -203,12 +190,12 @@ private:
void update_zoom() override { } void update_zoom() override { }
void initialize_client(CreateNewClient) override { } void initialize_client(CreateNewClient) override { }
virtual Web::DevicePixelRect viewport_rect() const override { return m_viewport_rect.to_type<Web::DevicePixels>(); } virtual Web::DevicePixelSize viewport_size() const override { return m_viewport_size.to_type<Web::DevicePixels>(); }
virtual Gfx::IntPoint to_content_position(Gfx::IntPoint widget_position) const override { return widget_position; } virtual Gfx::IntPoint to_content_position(Gfx::IntPoint widget_position) const override { return widget_position; }
virtual Gfx::IntPoint to_widget_position(Gfx::IntPoint content_position) const override { return content_position; } virtual Gfx::IntPoint to_widget_position(Gfx::IntPoint content_position) const override { return content_position; }
private: private:
Gfx::IntRect m_viewport_rect; Gfx::IntSize m_viewport_size;
RefPtr<Core::Promise<RefPtr<Gfx::Bitmap>>> m_pending_screenshot; RefPtr<Core::Promise<RefPtr<Gfx::Bitmap>>> m_pending_screenshot;
NonnullRefPtr<WebView::Database> m_database; NonnullRefPtr<WebView::Database> m_database;