mirror of
https://github.com/RGBCube/serenity
synced 2025-07-03 05:32:13 +00:00
LibWeb: Add Page abstraction between PageView and main Frame
* A PageView is a view onto a Page object. * A Page always has a main Frame (root of Frame tree.) * Page has a PageClient. PageView is a PageClient. The goal here is to allow building another kind of view onto a Page while keeping the rest of LibWeb intact.
This commit is contained in:
parent
5072d4e02d
commit
92392398a2
16 changed files with 351 additions and 179 deletions
|
@ -55,24 +55,8 @@
|
|||
namespace Web {
|
||||
|
||||
PageView::PageView()
|
||||
: m_main_frame(Web::Frame::create(*this))
|
||||
: m_page(make<Page>(*this))
|
||||
{
|
||||
main_frame().on_set_document = [this](auto* document) {
|
||||
if (on_set_document)
|
||||
on_set_document(document);
|
||||
layout_and_sync_size();
|
||||
scroll_to_top();
|
||||
update();
|
||||
};
|
||||
main_frame().on_title_change = [this](auto& title) {
|
||||
if (on_title_change)
|
||||
on_title_change(title);
|
||||
};
|
||||
main_frame().on_load_start = [this](auto& url) {
|
||||
if (on_load_start)
|
||||
on_load_start(url);
|
||||
};
|
||||
|
||||
set_should_hide_unnecessary_scrollbars(true);
|
||||
set_background_role(ColorRole::Base);
|
||||
}
|
||||
|
@ -81,6 +65,86 @@ PageView::~PageView()
|
|||
{
|
||||
}
|
||||
|
||||
void PageView::page_did_change_title(const String& title)
|
||||
{
|
||||
if (on_title_change)
|
||||
on_title_change(title);
|
||||
}
|
||||
|
||||
void PageView::page_did_set_document_in_main_frame(Document* document)
|
||||
{
|
||||
if (on_set_document)
|
||||
on_set_document(document);
|
||||
layout_and_sync_size();
|
||||
scroll_to_top();
|
||||
update();
|
||||
}
|
||||
|
||||
void PageView::page_did_start_loading(const URL& url)
|
||||
{
|
||||
if (on_load_start)
|
||||
on_load_start(url);
|
||||
}
|
||||
|
||||
void PageView::page_did_change_selection()
|
||||
{
|
||||
update();
|
||||
}
|
||||
|
||||
void PageView::page_did_request_cursor_change(GUI::StandardCursor cursor)
|
||||
{
|
||||
if (window())
|
||||
window()->set_override_cursor(cursor);
|
||||
}
|
||||
|
||||
void PageView::page_did_request_link_context_menu(const Gfx::Point& content_position, const String& href, [[maybe_unused]] const String& target, [[maybe_unused]] unsigned modifiers)
|
||||
{
|
||||
if (on_link_context_menu_request)
|
||||
on_link_context_menu_request(href, screen_relative_rect().location().translated(to_widget_position(content_position)));
|
||||
}
|
||||
|
||||
void PageView::page_did_click_link(const String& href, const String& target, unsigned modifiers)
|
||||
{
|
||||
if (on_link_click)
|
||||
on_link_click(href, target, modifiers);
|
||||
}
|
||||
|
||||
void PageView::page_did_middle_click_link(const String& href, [[maybe_unused]] const String& target, [[maybe_unused]] unsigned modifiers)
|
||||
{
|
||||
if (on_link_middle_click)
|
||||
on_link_middle_click(href);
|
||||
}
|
||||
|
||||
void PageView::page_did_enter_tooltip_area(const Gfx::Point& content_position, const String& title)
|
||||
{
|
||||
GUI::Application::the().show_tooltip(title, screen_relative_rect().location().translated(to_widget_position(content_position)));
|
||||
}
|
||||
|
||||
void PageView::page_did_leave_tooltip_area()
|
||||
{
|
||||
GUI::Application::the().hide_tooltip();
|
||||
}
|
||||
|
||||
void PageView::page_did_hover_link(const URL& url)
|
||||
{
|
||||
if (on_link_hover)
|
||||
on_link_hover(url.to_string());
|
||||
}
|
||||
|
||||
void PageView::page_did_unhover_link()
|
||||
{
|
||||
}
|
||||
|
||||
void PageView::page_did_request_scroll_to_anchor(const String& fragment)
|
||||
{
|
||||
scroll_to_anchor(fragment);
|
||||
}
|
||||
|
||||
void PageView::page_did_invalidate(const Gfx::Rect&)
|
||||
{
|
||||
update();
|
||||
}
|
||||
|
||||
void PageView::layout_and_sync_size()
|
||||
{
|
||||
if (!document())
|
||||
|
@ -89,19 +153,19 @@ void PageView::layout_and_sync_size()
|
|||
bool had_vertical_scrollbar = vertical_scrollbar().is_visible();
|
||||
bool had_horizontal_scrollbar = horizontal_scrollbar().is_visible();
|
||||
|
||||
main_frame().set_size(available_size());
|
||||
page().main_frame().set_size(available_size());
|
||||
document()->layout();
|
||||
set_content_size(enclosing_int_rect(layout_root()->rect()).size());
|
||||
|
||||
// NOTE: If layout caused us to gain or lose scrollbars, we have to lay out again
|
||||
// since the scrollbars now take up some of the available space.
|
||||
if (had_vertical_scrollbar != vertical_scrollbar().is_visible() || had_horizontal_scrollbar != horizontal_scrollbar().is_visible()) {
|
||||
main_frame().set_size(available_size());
|
||||
page().main_frame().set_size(available_size());
|
||||
document()->layout();
|
||||
set_content_size(enclosing_int_rect(layout_root()->rect()).size());
|
||||
}
|
||||
|
||||
main_frame().set_viewport_rect(viewport_rect_in_content_coordinates());
|
||||
page().main_frame().set_viewport_rect(viewport_rect_in_content_coordinates());
|
||||
|
||||
#ifdef HTML_DEBUG
|
||||
dbgprintf("\033[33;1mLayout tree after layout:\033[0m\n");
|
||||
|
@ -145,28 +209,19 @@ void PageView::paint_event(GUI::PaintEvent& event)
|
|||
|
||||
void PageView::mousemove_event(GUI::MouseEvent& event)
|
||||
{
|
||||
if (main_frame().event_handler().handle_mousemove(to_content_position(event.position()), event.buttons(), event.modifiers())) {
|
||||
event.accept();
|
||||
return;
|
||||
}
|
||||
page().handle_mousemove(to_content_position(event.position()), event.buttons(), event.modifiers());
|
||||
GUI::ScrollableWidget::mousemove_event(event);
|
||||
}
|
||||
|
||||
void PageView::mousedown_event(GUI::MouseEvent& event)
|
||||
{
|
||||
if (main_frame().event_handler().handle_mousedown(to_content_position(event.position()), event.button(), event.modifiers())) {
|
||||
event.accept();
|
||||
return;
|
||||
}
|
||||
page().handle_mousedown(to_content_position(event.position()), event.button(), event.modifiers());
|
||||
GUI::ScrollableWidget::mousedown_event(event);
|
||||
}
|
||||
|
||||
void PageView::mouseup_event(GUI::MouseEvent& event)
|
||||
{
|
||||
if (main_frame().event_handler().handle_mouseup(to_content_position(event.position()), event.button(), event.modifiers())) {
|
||||
event.accept();
|
||||
return;
|
||||
}
|
||||
page().handle_mouseup(to_content_position(event.position()), event.button(), event.modifiers());
|
||||
GUI::ScrollableWidget::mouseup_event(event);
|
||||
}
|
||||
|
||||
|
@ -208,7 +263,7 @@ void PageView::keydown_event(GUI::KeyEvent& event)
|
|||
|
||||
void PageView::reload()
|
||||
{
|
||||
load(main_frame().document()->url());
|
||||
load(page().main_frame().document()->url());
|
||||
}
|
||||
|
||||
bool PageView::load(const URL& url)
|
||||
|
@ -216,7 +271,7 @@ bool PageView::load(const URL& url)
|
|||
if (window())
|
||||
window()->set_override_cursor(GUI::StandardCursor::None);
|
||||
|
||||
return main_frame().loader().load(url);
|
||||
return page().main_frame().loader().load(url);
|
||||
}
|
||||
|
||||
const LayoutDocument* PageView::layout_root() const
|
||||
|
@ -263,33 +318,33 @@ void PageView::scroll_to_anchor(const StringView& name)
|
|||
|
||||
void PageView::set_use_old_parser(bool use_old_parser)
|
||||
{
|
||||
main_frame().loader().set_use_old_parser(use_old_parser);
|
||||
page().main_frame().loader().set_use_old_parser(use_old_parser);
|
||||
}
|
||||
|
||||
void PageView::load_empty_document()
|
||||
{
|
||||
main_frame().set_document(nullptr);
|
||||
page().main_frame().set_document(nullptr);
|
||||
}
|
||||
|
||||
Document* PageView::document()
|
||||
{
|
||||
return main_frame().document();
|
||||
return page().main_frame().document();
|
||||
}
|
||||
|
||||
const Document* PageView::document() const
|
||||
{
|
||||
return main_frame().document();
|
||||
return page().main_frame().document();
|
||||
}
|
||||
|
||||
void PageView::set_document(Document* document)
|
||||
{
|
||||
main_frame().set_document(document);
|
||||
page().main_frame().set_document(document);
|
||||
}
|
||||
|
||||
void PageView::did_scroll()
|
||||
{
|
||||
main_frame().set_viewport_rect(viewport_rect_in_content_coordinates());
|
||||
main_frame().did_scroll({});
|
||||
page().main_frame().set_viewport_rect(viewport_rect_in_content_coordinates());
|
||||
page().main_frame().did_scroll({});
|
||||
}
|
||||
|
||||
void PageView::drop_event(GUI::DropEvent& event)
|
||||
|
@ -303,77 +358,4 @@ void PageView::drop_event(GUI::DropEvent& event)
|
|||
ScrollableWidget::drop_event(event);
|
||||
}
|
||||
|
||||
void PageView::notify_link_click(Badge<EventHandler>, Web::Frame&, const String& href, const String& target, unsigned modifiers)
|
||||
{
|
||||
if (on_link_click)
|
||||
on_link_click(href, target, modifiers);
|
||||
}
|
||||
|
||||
void PageView::notify_link_middle_click(Badge<EventHandler>, Web::Frame&, const String& href, const String&, unsigned)
|
||||
{
|
||||
if (on_link_middle_click)
|
||||
on_link_middle_click(href);
|
||||
}
|
||||
|
||||
Gfx::Point PageView::to_screen_position(const Web::Frame& frame, const Gfx::Point& frame_position) const
|
||||
{
|
||||
Gfx::Point offset;
|
||||
for (auto* f = &frame; f; f = f->parent()) {
|
||||
if (f->is_main_frame())
|
||||
break;
|
||||
auto f_position = f->host_element()->layout_node()->box_type_agnostic_position().to_int_point();
|
||||
offset.move_by(f_position);
|
||||
}
|
||||
return screen_relative_rect().location().translated(offset).translated(frame_position);
|
||||
}
|
||||
|
||||
Gfx::Rect PageView::to_widget_rect(const Web::Frame& frame, const Gfx::Rect& frame_rect) const
|
||||
{
|
||||
Gfx::Point offset;
|
||||
for (auto* f = &frame; f; f = f->parent()) {
|
||||
if (f->is_main_frame())
|
||||
break;
|
||||
if (!f->host_element())
|
||||
return {};
|
||||
if (!f->host_element()->layout_node())
|
||||
return {};
|
||||
auto f_position = f->host_element()->layout_node()->box_type_agnostic_position().to_int_point();
|
||||
offset.move_by(f_position);
|
||||
}
|
||||
|
||||
auto content_position = frame_rect.location().translated(offset);
|
||||
return { to_widget_position(content_position), frame_rect.size() };
|
||||
}
|
||||
|
||||
void PageView::notify_link_context_menu_request(Badge<EventHandler>, Web::Frame& frame, const Gfx::Point& content_position, const String& href, const String&, unsigned)
|
||||
{
|
||||
if (on_link_context_menu_request)
|
||||
on_link_context_menu_request(href, to_screen_position(frame, content_position));
|
||||
}
|
||||
|
||||
void PageView::notify_link_hover(Badge<EventHandler>, Web::Frame&, const String& href)
|
||||
{
|
||||
if (on_link_hover)
|
||||
on_link_hover(href);
|
||||
}
|
||||
|
||||
void PageView::notify_tooltip_area_enter(Badge<EventHandler>, Web::Frame& frame, const Gfx::Point& content_position, const String& title)
|
||||
{
|
||||
GUI::Application::the().show_tooltip(title, to_screen_position(frame, content_position));
|
||||
}
|
||||
|
||||
void PageView::notify_tooltip_area_leave(Badge<EventHandler>, Web::Frame&)
|
||||
{
|
||||
GUI::Application::the().hide_tooltip();
|
||||
}
|
||||
|
||||
void PageView::notify_needs_display(Badge<Web::Frame>, Web::Frame& frame, const Gfx::Rect& rect)
|
||||
{
|
||||
update(to_widget_rect(frame, rect));
|
||||
|
||||
// FIXME: This is a total hack that forces a full repaint every time.
|
||||
// We shouldn't have to do this, but until the ICB is actually viewport-sized, we have no choice.
|
||||
update();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue