diff --git a/Userland/Libraries/LibWeb/Layout/ImageBox.cpp b/Userland/Libraries/LibWeb/Layout/ImageBox.cpp index aefd465eda..92b5986cae 100644 --- a/Userland/Libraries/LibWeb/Layout/ImageBox.cpp +++ b/Userland/Libraries/LibWeb/Layout/ImageBox.cpp @@ -30,6 +30,7 @@ #include #include #include +#include namespace Web::Layout { @@ -37,10 +38,12 @@ ImageBox::ImageBox(DOM::Document& document, DOM::Element& element, NonnullRefPtr : ReplacedBox(document, element, move(style)) , m_image_loader(image_loader) { + frame().register_viewport_client(*this); } ImageBox::~ImageBox() { + frame().unregister_viewport_client(*this); } int ImageBox::preferred_width() const @@ -127,9 +130,9 @@ bool ImageBox::renders_as_alt_text() const return false; } -void ImageBox::set_visible_in_viewport(Badge, bool visible_in_viewport) +void ImageBox::frame_did_set_viewport_rect(const Gfx::IntRect& viewport_rect) { - m_image_loader.set_visible_in_viewport(visible_in_viewport); + m_image_loader.set_visible_in_viewport(viewport_rect.to().intersects(absolute_rect())); } } diff --git a/Userland/Libraries/LibWeb/Layout/ImageBox.h b/Userland/Libraries/LibWeb/Layout/ImageBox.h index a404ca1ca0..d96db80ec5 100644 --- a/Userland/Libraries/LibWeb/Layout/ImageBox.h +++ b/Userland/Libraries/LibWeb/Layout/ImageBox.h @@ -28,10 +28,13 @@ #include #include +#include namespace Web::Layout { -class ImageBox : public ReplacedBox { +class ImageBox + : public ReplacedBox + , public Frame::ViewportClient { public: ImageBox(DOM::Document&, DOM::Element&, NonnullRefPtr, const ImageLoader&); virtual ~ImageBox() override; @@ -43,9 +46,9 @@ public: bool renders_as_alt_text() const; - void set_visible_in_viewport(Badge, bool); - private: + virtual void frame_did_set_viewport_rect(const Gfx::IntRect&) final; + int preferred_width() const; int preferred_height() const; diff --git a/Userland/Libraries/LibWeb/Layout/InitialContainingBlockBox.cpp b/Userland/Libraries/LibWeb/Layout/InitialContainingBlockBox.cpp index 320f0f770c..3a71495d8d 100644 --- a/Userland/Libraries/LibWeb/Layout/InitialContainingBlockBox.cpp +++ b/Userland/Libraries/LibWeb/Layout/InitialContainingBlockBox.cpp @@ -63,15 +63,6 @@ void InitialContainingBlockBox::build_stacking_context_tree() }); } -void InitialContainingBlockBox::did_set_viewport_rect(Badge, const Gfx::IntRect& a_viewport_rect) -{ - Gfx::FloatRect viewport_rect(a_viewport_rect.x(), a_viewport_rect.y(), a_viewport_rect.width(), a_viewport_rect.height()); - for_each_in_subtree_of_type([&](auto& layout_image) { - const_cast(layout_image).set_visible_in_viewport({}, viewport_rect.intersects(layout_image.absolute_rect())); - return IterationDecision::Continue; - }); -} - void InitialContainingBlockBox::paint_all_phases(PaintContext& context) { paint(context, PaintPhase::Background); diff --git a/Userland/Libraries/LibWeb/Layout/InitialContainingBlockBox.h b/Userland/Libraries/LibWeb/Layout/InitialContainingBlockBox.h index b7b4810364..92d2746ef4 100644 --- a/Userland/Libraries/LibWeb/Layout/InitialContainingBlockBox.h +++ b/Userland/Libraries/LibWeb/Layout/InitialContainingBlockBox.h @@ -47,8 +47,6 @@ public: void set_selection(const LayoutRange&); void set_selection_end(const LayoutPosition&); - void did_set_viewport_rect(Badge, const Gfx::IntRect&); - void build_stacking_context_tree(); void recompute_selection_states(); diff --git a/Userland/Libraries/LibWeb/Page/Frame.cpp b/Userland/Libraries/LibWeb/Page/Frame.cpp index 2b8d5ddb63..bea214f768 100644 --- a/Userland/Libraries/LibWeb/Page/Frame.cpp +++ b/Userland/Libraries/LibWeb/Page/Frame.cpp @@ -110,11 +110,11 @@ void Frame::set_size(const Gfx::IntSize& size) if (m_size == size) return; m_size = size; - if (m_document) { + if (m_document) m_document->update_layout(); - if (m_document->layout_node()) - m_document->layout_node()->did_set_viewport_rect({}, viewport_rect()); - } + + for (auto* client : m_viewport_clients) + client->frame_did_set_viewport_rect(viewport_rect()); } void Frame::set_viewport_scroll_offset(const Gfx::IntPoint& offset) @@ -123,8 +123,8 @@ void Frame::set_viewport_scroll_offset(const Gfx::IntPoint& offset) return; m_viewport_scroll_offset = offset; - if (m_document && m_document->layout_node()) - m_document->layout_node()->did_set_viewport_rect({}, viewport_rect()); + for (auto* client : m_viewport_clients) + client->frame_did_set_viewport_rect(viewport_rect()); } void Frame::set_needs_display(const Gfx::IntRect& rect) @@ -274,4 +274,16 @@ String Frame::selected_text() const return builder.to_string(); } +void Frame::register_viewport_client(ViewportClient& client) +{ + auto result = m_viewport_clients.set(&client); + ASSERT(result == AK::HashSetResult::InsertedNewEntry); +} + +void Frame::unregister_viewport_client(ViewportClient& client) +{ + bool was_removed = m_viewport_clients.remove(&client); + ASSERT(was_removed); +} + } diff --git a/Userland/Libraries/LibWeb/Page/Frame.h b/Userland/Libraries/LibWeb/Page/Frame.h index d6ba5eea8d..c98554b4aa 100644 --- a/Userland/Libraries/LibWeb/Page/Frame.h +++ b/Userland/Libraries/LibWeb/Page/Frame.h @@ -47,6 +47,14 @@ public: static NonnullRefPtr create(Page& page) { return adopt(*new Frame(page)); } ~Frame(); + class ViewportClient { + public: + virtual ~ViewportClient() { } + virtual void frame_did_set_viewport_rect(const Gfx::IntRect&) = 0; + }; + void register_viewport_client(ViewportClient&); + void unregister_viewport_client(ViewportClient&); + bool is_main_frame() const { return this == &m_main_frame; } bool is_focused_frame() const; @@ -116,6 +124,8 @@ private: DOM::Position m_cursor_position; RefPtr m_cursor_blink_timer; bool m_cursor_blink_state { false }; + + HashTable m_viewport_clients; }; }