diff --git a/Userland/Libraries/LibWeb/Layout/BlockBox.cpp b/Userland/Libraries/LibWeb/Layout/BlockBox.cpp index c0a05cae33..a23d33d1e2 100644 --- a/Userland/Libraries/LibWeb/Layout/BlockBox.cpp +++ b/Userland/Libraries/LibWeb/Layout/BlockBox.cpp @@ -68,6 +68,7 @@ void BlockBox::paint(PaintContext& context, PaintPhase phase) context.painter().save(); // FIXME: Handle overflow-x and overflow-y being different values. context.painter().add_clip_rect(enclosing_int_rect(padded_rect())); + context.painter().translate(-m_scroll_offset.to_type()); } for (auto& line_box : m_line_boxes) { @@ -141,4 +142,19 @@ void BlockBox::split_into_lines(InlineFormattingContext& context, LayoutMode lay line_box->add_fragment(*this, 0, 0, border_box_width(), height()); } +void BlockBox::set_scroll_offset(const Gfx::FloatPoint& offset) +{ + if (m_scroll_offset == offset) + return; + m_scroll_offset = offset; + set_needs_display(); +} + +void BlockBox::handle_mousewheel(Badge, const Gfx::IntPoint&, unsigned int, unsigned int, int wheel_delta) +{ + auto new_offset = m_scroll_offset; + new_offset.move_by(0, wheel_delta); + set_scroll_offset(new_offset); +} + } diff --git a/Userland/Libraries/LibWeb/Layout/BlockBox.h b/Userland/Libraries/LibWeb/Layout/BlockBox.h index d2ffbb8a88..470b78ad64 100644 --- a/Userland/Libraries/LibWeb/Layout/BlockBox.h +++ b/Userland/Libraries/LibWeb/Layout/BlockBox.h @@ -53,10 +53,17 @@ public: virtual void split_into_lines(InlineFormattingContext&, LayoutMode) override; + const Gfx::FloatPoint& scroll_offset() const { return m_scroll_offset; } + void set_scroll_offset(const Gfx::FloatPoint&); + private: virtual bool is_block_box() const final { return true; } + virtual bool wants_mouse_events() const override { return true; } + virtual void handle_mousewheel(Badge, const Gfx::IntPoint&, unsigned buttons, unsigned modifiers, int wheel_delta) override; bool should_clip_overflow() const; + + Gfx::FloatPoint m_scroll_offset; }; template<> diff --git a/Userland/Libraries/LibWeb/Layout/Node.cpp b/Userland/Libraries/LibWeb/Layout/Node.cpp index e44cd2db74..0893fb3416 100644 --- a/Userland/Libraries/LibWeb/Layout/Node.cpp +++ b/Userland/Libraries/LibWeb/Layout/Node.cpp @@ -318,6 +318,15 @@ void Node::handle_mousemove(Badge, const Gfx::IntPoint&, unsigned, { } +void Node::handle_mousewheel(Badge, const Gfx::IntPoint&, unsigned, unsigned, int wheel_delta) +{ + if (auto* containing_block = this->containing_block()) { + auto new_offset = containing_block->scroll_offset(); + new_offset.move_by(0, wheel_delta); + containing_block->set_scroll_offset(new_offset); + } +} + bool Node::is_root_element() const { if (is_anonymous()) diff --git a/Userland/Libraries/LibWeb/Layout/Node.h b/Userland/Libraries/LibWeb/Layout/Node.h index 41397762b1..653baa5264 100644 --- a/Userland/Libraries/LibWeb/Layout/Node.h +++ b/Userland/Libraries/LibWeb/Layout/Node.h @@ -109,6 +109,7 @@ public: virtual void handle_mousedown(Badge, const Gfx::IntPoint&, unsigned button, unsigned modifiers); virtual void handle_mouseup(Badge, const Gfx::IntPoint&, unsigned button, unsigned modifiers); virtual void handle_mousemove(Badge, const Gfx::IntPoint&, unsigned buttons, unsigned modifiers); + virtual void handle_mousewheel(Badge, const Gfx::IntPoint&, unsigned buttons, unsigned modifiers, int wheel_delta); virtual void before_children_paint(PaintContext&, PaintPhase) {}; virtual void paint(PaintContext&, PaintPhase); diff --git a/Userland/Libraries/LibWeb/Page/EventHandler.cpp b/Userland/Libraries/LibWeb/Page/EventHandler.cpp index 54cd5c7d81..c9816975f7 100644 --- a/Userland/Libraries/LibWeb/Page/EventHandler.cpp +++ b/Userland/Libraries/LibWeb/Page/EventHandler.cpp @@ -75,6 +75,17 @@ Layout::InitialContainingBlockBox* EventHandler::layout_root() bool EventHandler::handle_mousewheel(const Gfx::IntPoint& position, unsigned int buttons, unsigned int modifiers, int wheel_delta) { + if (!layout_root()) + return false; + + // FIXME: Support wheel events in subframes. + + auto result = layout_root()->hit_test(position, Layout::HitTestType::Exact); + if (result.layout_node) { + result.layout_node->handle_mousewheel({}, position, buttons, modifiers, wheel_delta); + return true; + } + return false; }