From cb0c5390ff9a0189ae79cfd690f6c089ba73c4a7 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Thu, 10 Mar 2022 22:46:35 +0100 Subject: [PATCH] LibWeb: Move mouse event and label logic from layout to painting tree Input events have nothing to do with layout, so let's not send them to layout nodes. The job of Paintable starts to become clear. It represents a paintable item that can be rendered into the viewport, which means it can also be targeted by the mouse cursor. --- Userland/Libraries/LibWeb/CMakeLists.txt | 2 + Userland/Libraries/LibWeb/DOM/Node.cpp | 7 ++ Userland/Libraries/LibWeb/DOM/Node.h | 1 + Userland/Libraries/LibWeb/Forward.h | 4 + .../LibWeb/HTML/HTMLInputElement.cpp | 4 +- .../Libraries/LibWeb/HTML/HTMLInputElement.h | 4 +- .../LibWeb/Layout/BlockContainer.cpp | 11 -- .../Libraries/LibWeb/Layout/BlockContainer.h | 2 - .../Libraries/LibWeb/Layout/ButtonBox.cpp | 75 ------------- Userland/Libraries/LibWeb/Layout/ButtonBox.h | 16 +-- Userland/Libraries/LibWeb/Layout/CheckBox.cpp | 84 --------------- Userland/Libraries/LibWeb/Layout/CheckBox.h | 16 +-- Userland/Libraries/LibWeb/Layout/Label.cpp | 24 ++--- Userland/Libraries/LibWeb/Layout/Label.h | 12 +-- .../Libraries/LibWeb/Layout/LabelableNode.cpp | 22 ++++ .../Libraries/LibWeb/Layout/LabelableNode.h | 5 +- Userland/Libraries/LibWeb/Layout/Node.cpp | 26 ----- Userland/Libraries/LibWeb/Layout/Node.h | 7 -- .../Libraries/LibWeb/Layout/RadioButton.cpp | 87 --------------- .../Libraries/LibWeb/Layout/RadioButton.h | 18 +--- Userland/Libraries/LibWeb/Layout/TextNode.cpp | 35 ------ Userland/Libraries/LibWeb/Layout/TextNode.h | 4 - .../Libraries/LibWeb/Page/EventHandler.cpp | 27 ++--- .../LibWeb/Painting/ButtonPaintable.cpp | 87 ++++++++++++++- .../LibWeb/Painting/ButtonPaintable.h | 17 ++- .../LibWeb/Painting/CheckBoxPaintable.cpp | 93 +++++++++++++++- .../LibWeb/Painting/CheckBoxPaintable.h | 17 ++- .../LibWeb/Painting/LabelablePaintable.cpp | 26 +++++ .../LibWeb/Painting/LabelablePaintable.h | 27 +++++ .../Libraries/LibWeb/Painting/Paintable.cpp | 48 +++++++++ .../Libraries/LibWeb/Painting/Paintable.h | 22 ++++ .../LibWeb/Painting/RadioButtonPaintable.cpp | 100 +++++++++++++++++- .../LibWeb/Painting/RadioButtonPaintable.h | 19 +++- .../LibWeb/Painting/TextPaintable.cpp | 35 ++++++ .../Libraries/LibWeb/Painting/TextPaintable.h | 5 + 35 files changed, 560 insertions(+), 429 deletions(-) create mode 100644 Userland/Libraries/LibWeb/Layout/LabelableNode.cpp create mode 100644 Userland/Libraries/LibWeb/Painting/LabelablePaintable.cpp create mode 100644 Userland/Libraries/LibWeb/Painting/LabelablePaintable.h diff --git a/Userland/Libraries/LibWeb/CMakeLists.txt b/Userland/Libraries/LibWeb/CMakeLists.txt index da7b9397b8..1635d1e59b 100644 --- a/Userland/Libraries/LibWeb/CMakeLists.txt +++ b/Userland/Libraries/LibWeb/CMakeLists.txt @@ -246,6 +246,7 @@ set(SOURCES Layout/InlineLevelIterator.cpp Layout/InlineNode.cpp Layout/Label.cpp + Layout/LabelableNode.cpp Layout/LayoutPosition.cpp Layout/LineBox.cpp Layout/LineBoxFragment.cpp @@ -289,6 +290,7 @@ set(SOURCES Painting/CheckBoxPaintable.cpp Painting/ImagePaintable.cpp Painting/InlinePaintable.cpp + Painting/LabelablePaintable.cpp Painting/MarkerPaintable.cpp Painting/NestedBrowsingContextPaintable.cpp Painting/PaintContext.cpp diff --git a/Userland/Libraries/LibWeb/DOM/Node.cpp b/Userland/Libraries/LibWeb/DOM/Node.cpp index 5241cb9f1d..b1eb86a63d 100644 --- a/Userland/Libraries/LibWeb/DOM/Node.cpp +++ b/Userland/Libraries/LibWeb/DOM/Node.cpp @@ -1010,6 +1010,13 @@ size_t Node::length() const return child_count(); } +Painting::Paintable const* Node::paintable() const +{ + if (!layout_node()) + return nullptr; + return layout_node()->paintable(); +} + Painting::PaintableBox const* Node::paint_box() const { if (!layout_node()) diff --git a/Userland/Libraries/LibWeb/DOM/Node.h b/Userland/Libraries/LibWeb/DOM/Node.h index 8b9b641de2..536738c9f0 100644 --- a/Userland/Libraries/LibWeb/DOM/Node.h +++ b/Userland/Libraries/LibWeb/DOM/Node.h @@ -159,6 +159,7 @@ public: Layout::Node* layout_node() { return m_layout_node; } Painting::PaintableBox const* paint_box() const; + Painting::Paintable const* paintable() const; void set_layout_node(Badge, Layout::Node*) const; diff --git a/Userland/Libraries/LibWeb/Forward.h b/Userland/Libraries/LibWeb/Forward.h index f088b61bbe..730437e732 100644 --- a/Userland/Libraries/LibWeb/Forward.h +++ b/Userland/Libraries/LibWeb/Forward.h @@ -265,9 +265,13 @@ class PerformanceTiming; namespace Web::Painting { enum class PaintPhase; +class ButtonPaintable; +class CheckBoxPaintable; +class LabelablePaintable; class Paintable; class PaintableBox; class PaintableWithLines; +class TextPaintable; } namespace Web::RequestIdleCallback { diff --git a/Userland/Libraries/LibWeb/HTML/HTMLInputElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLInputElement.cpp index 535c405ed5..f71f8b1259 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLInputElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLInputElement.cpp @@ -29,7 +29,7 @@ HTMLInputElement::~HTMLInputElement() { } -void HTMLInputElement::did_click_button(Badge) +void HTMLInputElement::did_click_button(Badge) { // FIXME: This should be a PointerEvent. dispatch_event(DOM::Event::create(EventNames::click)); @@ -42,7 +42,7 @@ void HTMLInputElement::did_click_button(Badge) } } -void HTMLInputElement::did_click_checkbox(Badge) +void HTMLInputElement::did_click_checkbox(Badge) { // FIXME: This should be a PointerEvent. auto click_event = DOM::Event::create(EventNames::click); diff --git a/Userland/Libraries/LibWeb/HTML/HTMLInputElement.h b/Userland/Libraries/LibWeb/HTML/HTMLInputElement.h index 5027ea12a4..7d5e6b2ec1 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLInputElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLInputElement.h @@ -73,8 +73,8 @@ public: }; void set_checked(bool, ChangeSource = ChangeSource::Programmatic, ShouldRunActivationBehavior = ShouldRunActivationBehavior::Yes); - void did_click_button(Badge); - void did_click_checkbox(Badge); + void did_click_button(Badge); + void did_click_checkbox(Badge); void did_edit_text_node(Badge); diff --git a/Userland/Libraries/LibWeb/Layout/BlockContainer.cpp b/Userland/Libraries/LibWeb/Layout/BlockContainer.cpp index 5b320da24c..dcfa305ae5 100644 --- a/Userland/Libraries/LibWeb/Layout/BlockContainer.cpp +++ b/Userland/Libraries/LibWeb/Layout/BlockContainer.cpp @@ -69,17 +69,6 @@ void BlockContainer::set_scroll_offset(const Gfx::FloatPoint& offset) set_needs_display(); } -bool BlockContainer::handle_mousewheel(Badge, const Gfx::IntPoint&, unsigned int, unsigned int, int wheel_delta_x, int wheel_delta_y) -{ - if (!is_scrollable()) - return false; - auto new_offset = m_scroll_offset; - new_offset.translate_by(wheel_delta_x, wheel_delta_y); - set_scroll_offset(new_offset); - - return true; -} - Painting::PaintableWithLines const* BlockContainer::paint_box() const { return static_cast(Box::paint_box()); diff --git a/Userland/Libraries/LibWeb/Layout/BlockContainer.h b/Userland/Libraries/LibWeb/Layout/BlockContainer.h index 5cf325d7a3..162f40f12e 100644 --- a/Userland/Libraries/LibWeb/Layout/BlockContainer.h +++ b/Userland/Libraries/LibWeb/Layout/BlockContainer.h @@ -35,8 +35,6 @@ public: private: virtual bool is_block_container() const final { return true; } - virtual bool wants_mouse_events() const override { return false; } - virtual bool handle_mousewheel(Badge, const Gfx::IntPoint&, unsigned buttons, unsigned modifiers, int wheel_delta_x, int wheel_delta_y) override; Gfx::FloatPoint m_scroll_offset; }; diff --git a/Userland/Libraries/LibWeb/Layout/ButtonBox.cpp b/Userland/Libraries/LibWeb/Layout/ButtonBox.cpp index 5ed1ba9a2d..c0db4bafd3 100644 --- a/Userland/Libraries/LibWeb/Layout/ButtonBox.cpp +++ b/Userland/Libraries/LibWeb/Layout/ButtonBox.cpp @@ -31,81 +31,6 @@ void ButtonBox::prepare_for_replaced_layout() set_intrinsic_height(font().glyph_height()); } -void ButtonBox::handle_mousedown(Badge, const Gfx::IntPoint&, unsigned button, unsigned) -{ - if (button != GUI::MouseButton::Primary || !dom_node().enabled()) - return; - - m_being_pressed = true; - set_needs_display(); - - m_tracking_mouse = true; - browsing_context().event_handler().set_mouse_event_tracking_layout_node(this); -} - -void ButtonBox::handle_mouseup(Badge, const Gfx::IntPoint& position, unsigned button, unsigned) -{ - if (!m_tracking_mouse || button != GUI::MouseButton::Primary || !dom_node().enabled()) - return; - - // NOTE: Handling the click may run arbitrary JS, which could disappear this node. - NonnullRefPtr protected_this = *this; - NonnullRefPtr protected_browsing_context = browsing_context(); - - bool is_inside_node_or_label = enclosing_int_rect(paint_box()->absolute_rect()).contains(position); - if (!is_inside_node_or_label) - is_inside_node_or_label = Label::is_inside_associated_label(*this, position); - - if (is_inside_node_or_label) - dom_node().did_click_button({}); - - m_being_pressed = false; - m_tracking_mouse = false; - - protected_browsing_context->event_handler().set_mouse_event_tracking_layout_node(nullptr); -} - -void ButtonBox::handle_mousemove(Badge, const Gfx::IntPoint& position, unsigned, unsigned) -{ - if (!m_tracking_mouse || !dom_node().enabled()) - return; - - bool is_inside_node_or_label = enclosing_int_rect(paint_box()->absolute_rect()).contains(position); - if (!is_inside_node_or_label) - is_inside_node_or_label = Label::is_inside_associated_label(*this, position); - - if (m_being_pressed == is_inside_node_or_label) - return; - - m_being_pressed = is_inside_node_or_label; - set_needs_display(); -} - -void ButtonBox::handle_associated_label_mousedown(Badge