mirror of
https://github.com/RGBCube/serenity
synced 2025-07-27 01:57:45 +00:00
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.
This commit is contained in:
parent
ed84fbce47
commit
cb0c5390ff
35 changed files with 560 additions and 429 deletions
|
@ -69,17 +69,6 @@ void BlockContainer::set_scroll_offset(const Gfx::FloatPoint& offset)
|
|||
set_needs_display();
|
||||
}
|
||||
|
||||
bool BlockContainer::handle_mousewheel(Badge<EventHandler>, 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<Painting::PaintableWithLines const*>(Box::paint_box());
|
||||
|
|
|
@ -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<EventHandler>, const Gfx::IntPoint&, unsigned buttons, unsigned modifiers, int wheel_delta_x, int wheel_delta_y) override;
|
||||
|
||||
Gfx::FloatPoint m_scroll_offset;
|
||||
};
|
||||
|
|
|
@ -31,81 +31,6 @@ void ButtonBox::prepare_for_replaced_layout()
|
|||
set_intrinsic_height(font().glyph_height());
|
||||
}
|
||||
|
||||
void ButtonBox::handle_mousedown(Badge<EventHandler>, 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<EventHandler>, 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<EventHandler>, 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<Label>)
|
||||
{
|
||||
m_being_pressed = true;
|
||||
set_needs_display();
|
||||
}
|
||||
|
||||
void ButtonBox::handle_associated_label_mouseup(Badge<Label>)
|
||||
{
|
||||
// NOTE: Handling the click may run arbitrary JS, which could disappear this node.
|
||||
NonnullRefPtr protected_this = *this;
|
||||
NonnullRefPtr protected_browsing_context = browsing_context();
|
||||
|
||||
dom_node().did_click_button({});
|
||||
m_being_pressed = false;
|
||||
}
|
||||
|
||||
void ButtonBox::handle_associated_label_mousemove(Badge<Label>, bool is_inside_node_or_label)
|
||||
{
|
||||
if (m_being_pressed == is_inside_node_or_label)
|
||||
return;
|
||||
|
||||
m_being_pressed = is_inside_node_or_label;
|
||||
set_needs_display();
|
||||
}
|
||||
|
||||
RefPtr<Painting::Paintable> ButtonBox::create_paintable() const
|
||||
{
|
||||
return Painting::ButtonPaintable::create(*this);
|
||||
|
|
|
@ -21,22 +21,8 @@ public:
|
|||
const HTML::HTMLInputElement& dom_node() const { return static_cast<const HTML::HTMLInputElement&>(LabelableNode::dom_node()); }
|
||||
HTML::HTMLInputElement& dom_node() { return static_cast<HTML::HTMLInputElement&>(LabelableNode::dom_node()); }
|
||||
|
||||
bool being_pressed() const { return m_being_pressed; }
|
||||
|
||||
virtual RefPtr<Painting::Paintable> create_paintable() const override;
|
||||
|
||||
private:
|
||||
virtual bool wants_mouse_events() const override { return true; }
|
||||
virtual void handle_mousedown(Badge<EventHandler>, const Gfx::IntPoint&, unsigned button, unsigned modifiers) override;
|
||||
virtual void handle_mouseup(Badge<EventHandler>, const Gfx::IntPoint&, unsigned button, unsigned modifiers) override;
|
||||
virtual void handle_mousemove(Badge<EventHandler>, const Gfx::IntPoint&, unsigned buttons, unsigned modifiers) override;
|
||||
|
||||
virtual void handle_associated_label_mousedown(Badge<Label>) override;
|
||||
virtual void handle_associated_label_mouseup(Badge<Label>) override;
|
||||
virtual void handle_associated_label_mousemove(Badge<Label>, bool is_inside_node_or_label) override;
|
||||
|
||||
bool m_being_pressed { false };
|
||||
bool m_tracking_mouse { false };
|
||||
virtual RefPtr<Painting::Paintable> create_paintable() const override;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -4,10 +4,7 @@
|
|||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <LibGUI/Event.h>
|
||||
#include <LibGfx/Font.h>
|
||||
#include <LibGfx/Painter.h>
|
||||
#include <LibGfx/StylePainter.h>
|
||||
#include <LibWeb/HTML/BrowsingContext.h>
|
||||
#include <LibWeb/HTML/HTMLInputElement.h>
|
||||
#include <LibWeb/Layout/CheckBox.h>
|
||||
|
@ -27,87 +24,6 @@ CheckBox::~CheckBox()
|
|||
{
|
||||
}
|
||||
|
||||
void CheckBox::handle_mousedown(Badge<EventHandler>, 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 CheckBox::handle_mouseup(Badge<EventHandler>, const Gfx::IntPoint& position, unsigned button, unsigned)
|
||||
{
|
||||
if (!m_tracking_mouse || button != GUI::MouseButton::Primary || !dom_node().enabled())
|
||||
return;
|
||||
|
||||
// NOTE: Changing the checked state of the DOM node may run arbitrary JS, which could disappear this node.
|
||||
NonnullRefPtr protect = *this;
|
||||
|
||||
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_checkbox({});
|
||||
dom_node().set_checked(!dom_node().checked(), HTML::HTMLInputElement::ChangeSource::User);
|
||||
}
|
||||
|
||||
m_being_pressed = false;
|
||||
m_tracking_mouse = false;
|
||||
browsing_context().event_handler().set_mouse_event_tracking_layout_node(nullptr);
|
||||
}
|
||||
|
||||
void CheckBox::handle_mousemove(Badge<EventHandler>, 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 CheckBox::handle_associated_label_mousedown(Badge<Label>)
|
||||
{
|
||||
if (!dom_node().enabled())
|
||||
return;
|
||||
|
||||
m_being_pressed = true;
|
||||
set_needs_display();
|
||||
}
|
||||
|
||||
void CheckBox::handle_associated_label_mouseup(Badge<Label>)
|
||||
{
|
||||
if (!dom_node().enabled())
|
||||
return;
|
||||
|
||||
// NOTE: Changing the checked state of the DOM node may run arbitrary JS, which could disappear this node.
|
||||
NonnullRefPtr protect = *this;
|
||||
|
||||
dom_node().did_click_checkbox({});
|
||||
dom_node().set_checked(!dom_node().checked(), HTML::HTMLInputElement::ChangeSource::User);
|
||||
m_being_pressed = false;
|
||||
}
|
||||
|
||||
void CheckBox::handle_associated_label_mousemove(Badge<Label>, bool is_inside_node_or_label)
|
||||
{
|
||||
if (m_being_pressed == is_inside_node_or_label || !dom_node().enabled())
|
||||
return;
|
||||
|
||||
m_being_pressed = is_inside_node_or_label;
|
||||
set_needs_display();
|
||||
}
|
||||
|
||||
RefPtr<Painting::Paintable> CheckBox::create_paintable() const
|
||||
{
|
||||
return Painting::CheckBoxPaintable::create(*this);
|
||||
|
|
|
@ -19,22 +19,8 @@ public:
|
|||
const HTML::HTMLInputElement& dom_node() const { return static_cast<const HTML::HTMLInputElement&>(LabelableNode::dom_node()); }
|
||||
HTML::HTMLInputElement& dom_node() { return static_cast<HTML::HTMLInputElement&>(LabelableNode::dom_node()); }
|
||||
|
||||
bool being_pressed() const { return m_being_pressed; }
|
||||
|
||||
virtual RefPtr<Painting::Paintable> create_paintable() const override;
|
||||
|
||||
private:
|
||||
virtual bool wants_mouse_events() const override { return true; }
|
||||
virtual void handle_mousedown(Badge<EventHandler>, const Gfx::IntPoint&, unsigned button, unsigned modifiers) override;
|
||||
virtual void handle_mouseup(Badge<EventHandler>, const Gfx::IntPoint&, unsigned button, unsigned modifiers) override;
|
||||
virtual void handle_mousemove(Badge<EventHandler>, const Gfx::IntPoint&, unsigned buttons, unsigned modifiers) override;
|
||||
|
||||
virtual void handle_associated_label_mousedown(Badge<Label>) override;
|
||||
virtual void handle_associated_label_mouseup(Badge<Label>) override;
|
||||
virtual void handle_associated_label_mousemove(Badge<Label>, bool is_inside_node_or_label) override;
|
||||
|
||||
bool m_being_pressed { false };
|
||||
bool m_tracking_mouse { false };
|
||||
virtual RefPtr<Painting::Paintable> create_paintable() const override;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -5,16 +5,14 @@
|
|||
*/
|
||||
|
||||
#include <LibGUI/Event.h>
|
||||
#include <LibGfx/Painter.h>
|
||||
#include <LibGfx/StylePainter.h>
|
||||
#include <LibWeb/DOM/Document.h>
|
||||
#include <LibWeb/DOM/Element.h>
|
||||
#include <LibWeb/HTML/BrowsingContext.h>
|
||||
#include <LibWeb/Layout/InitialContainingBlock.h>
|
||||
#include <LibWeb/Layout/Label.h>
|
||||
#include <LibWeb/Layout/LabelableNode.h>
|
||||
#include <LibWeb/Layout/TextNode.h>
|
||||
#include <LibWeb/Painting/Paintable.h>
|
||||
#include <LibWeb/Painting/LabelablePaintable.h>
|
||||
|
||||
namespace Web::Layout {
|
||||
|
||||
|
@ -27,18 +25,18 @@ Label::~Label()
|
|||
{
|
||||
}
|
||||
|
||||
void Label::handle_mousedown_on_label(Badge<TextNode>, const Gfx::IntPoint&, unsigned button)
|
||||
void Label::handle_mousedown_on_label(Badge<Painting::TextPaintable>, Gfx::IntPoint const&, unsigned button)
|
||||
{
|
||||
if (button != GUI::MouseButton::Primary)
|
||||
return;
|
||||
|
||||
if (auto* control = labeled_control(); control)
|
||||
control->handle_associated_label_mousedown({});
|
||||
control->paintable()->handle_associated_label_mousedown({});
|
||||
|
||||
m_tracking_mouse = true;
|
||||
}
|
||||
|
||||
void Label::handle_mouseup_on_label(Badge<TextNode>, const Gfx::IntPoint& position, unsigned button)
|
||||
void Label::handle_mouseup_on_label(Badge<Painting::TextPaintable>, Gfx::IntPoint const& position, unsigned button)
|
||||
{
|
||||
if (!m_tracking_mouse || button != GUI::MouseButton::Primary)
|
||||
return;
|
||||
|
@ -51,13 +49,13 @@ void Label::handle_mouseup_on_label(Badge<TextNode>, const Gfx::IntPoint& positi
|
|||
bool is_inside_label = enclosing_int_rect(paint_box()->absolute_rect()).contains(position);
|
||||
|
||||
if (is_inside_control || is_inside_label)
|
||||
control->handle_associated_label_mouseup({});
|
||||
control->paintable()->handle_associated_label_mouseup({});
|
||||
}
|
||||
|
||||
m_tracking_mouse = false;
|
||||
}
|
||||
|
||||
void Label::handle_mousemove_on_label(Badge<TextNode>, const Gfx::IntPoint& position, unsigned)
|
||||
void Label::handle_mousemove_on_label(Badge<Painting::TextPaintable>, Gfx::IntPoint const& position, unsigned)
|
||||
{
|
||||
if (!m_tracking_mouse)
|
||||
return;
|
||||
|
@ -66,18 +64,18 @@ void Label::handle_mousemove_on_label(Badge<TextNode>, const Gfx::IntPoint& posi
|
|||
bool is_inside_control = enclosing_int_rect(control->paint_box()->absolute_rect()).contains(position);
|
||||
bool is_inside_label = enclosing_int_rect(paint_box()->absolute_rect()).contains(position);
|
||||
|
||||
control->handle_associated_label_mousemove({}, is_inside_control || is_inside_label);
|
||||
control->paintable()->handle_associated_label_mousemove({}, is_inside_control || is_inside_label);
|
||||
}
|
||||
}
|
||||
|
||||
bool Label::is_inside_associated_label(LabelableNode& control, const Gfx::IntPoint& position)
|
||||
bool Label::is_inside_associated_label(LabelableNode const& control, const Gfx::IntPoint& position)
|
||||
{
|
||||
if (auto* label = label_for_control_node(control); label)
|
||||
return enclosing_int_rect(label->paint_box()->absolute_rect()).contains(position);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Label::is_associated_label_hovered(LabelableNode& control)
|
||||
bool Label::is_associated_label_hovered(LabelableNode const& control)
|
||||
{
|
||||
if (auto* label = label_for_control_node(control); label) {
|
||||
if (label->document().hovered_node() == &label->dom_node())
|
||||
|
@ -91,7 +89,7 @@ bool Label::is_associated_label_hovered(LabelableNode& control)
|
|||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/forms.html#labeled-control
|
||||
Label* Label::label_for_control_node(LabelableNode& control)
|
||||
Label const* Label::label_for_control_node(LabelableNode const& control)
|
||||
{
|
||||
if (!control.document().layout_node())
|
||||
return nullptr;
|
||||
|
@ -102,7 +100,7 @@ Label* Label::label_for_control_node(LabelableNode& control)
|
|||
// whose ID is equal to the value of the for attribute, and the first such element in tree order is
|
||||
// a labelable element, then that element is the label element's labeled control.
|
||||
if (auto id = control.dom_node().attribute(HTML::AttributeNames::id); !id.is_empty()) {
|
||||
Label* label = nullptr;
|
||||
Label const* label = nullptr;
|
||||
|
||||
control.document().layout_node()->for_each_in_inclusive_subtree_of_type<Label>([&](auto& node) {
|
||||
if (node.dom_node().for_() == id) {
|
||||
|
|
|
@ -16,20 +16,20 @@ public:
|
|||
Label(DOM::Document&, HTML::HTMLLabelElement*, NonnullRefPtr<CSS::StyleProperties>);
|
||||
virtual ~Label() override;
|
||||
|
||||
static bool is_inside_associated_label(LabelableNode&, const Gfx::IntPoint&);
|
||||
static bool is_associated_label_hovered(LabelableNode&);
|
||||
static bool is_inside_associated_label(LabelableNode const&, Gfx::IntPoint const&);
|
||||
static bool is_associated_label_hovered(LabelableNode const&);
|
||||
|
||||
const HTML::HTMLLabelElement& dom_node() const { return static_cast<const HTML::HTMLLabelElement&>(*BlockContainer::dom_node()); }
|
||||
HTML::HTMLLabelElement& dom_node() { return static_cast<HTML::HTMLLabelElement&>(*BlockContainer::dom_node()); }
|
||||
|
||||
void handle_mousedown_on_label(Badge<TextNode>, const Gfx::IntPoint&, unsigned button);
|
||||
void handle_mouseup_on_label(Badge<TextNode>, const Gfx::IntPoint&, unsigned button);
|
||||
void handle_mousemove_on_label(Badge<TextNode>, const Gfx::IntPoint&, unsigned button);
|
||||
void handle_mousedown_on_label(Badge<Painting::TextPaintable>, const Gfx::IntPoint&, unsigned button);
|
||||
void handle_mouseup_on_label(Badge<Painting::TextPaintable>, const Gfx::IntPoint&, unsigned button);
|
||||
void handle_mousemove_on_label(Badge<Painting::TextPaintable>, const Gfx::IntPoint&, unsigned button);
|
||||
|
||||
private:
|
||||
virtual bool is_label() const override { return true; }
|
||||
|
||||
static Label* label_for_control_node(LabelableNode&);
|
||||
static Label const* label_for_control_node(LabelableNode const&);
|
||||
LabelableNode* labeled_control();
|
||||
|
||||
bool m_tracking_mouse { false };
|
||||
|
|
22
Userland/Libraries/LibWeb/Layout/LabelableNode.cpp
Normal file
22
Userland/Libraries/LibWeb/Layout/LabelableNode.cpp
Normal file
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
* Copyright (c) 2022, Andreas Kling <kling@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <LibWeb/Layout/LabelableNode.h>
|
||||
#include <LibWeb/Painting/LabelablePaintable.h>
|
||||
|
||||
namespace Web::Layout {
|
||||
|
||||
Painting::LabelablePaintable* LabelableNode::paintable()
|
||||
{
|
||||
return static_cast<Painting::LabelablePaintable*>(ReplacedBox::paintable());
|
||||
}
|
||||
|
||||
Painting::LabelablePaintable const* LabelableNode::paintable() const
|
||||
{
|
||||
return static_cast<Painting::LabelablePaintable const*>(ReplacedBox::paintable());
|
||||
}
|
||||
|
||||
}
|
|
@ -13,9 +13,8 @@ namespace Web::Layout {
|
|||
|
||||
class LabelableNode : public ReplacedBox {
|
||||
public:
|
||||
virtual void handle_associated_label_mousedown(Badge<Label>) { }
|
||||
virtual void handle_associated_label_mouseup(Badge<Label>) { }
|
||||
virtual void handle_associated_label_mousemove(Badge<Label>, [[maybe_unused]] bool is_inside_node_or_label) { }
|
||||
Painting::LabelablePaintable* paintable();
|
||||
Painting::LabelablePaintable const* paintable() const;
|
||||
|
||||
protected:
|
||||
LabelableNode(DOM::Document& document, DOM::Element& element, NonnullRefPtr<CSS::StyleProperties> style)
|
||||
|
|
|
@ -514,32 +514,6 @@ void NodeWithStyle::apply_style(const CSS::StyleProperties& specified_style)
|
|||
}
|
||||
}
|
||||
|
||||
void Node::handle_mousedown(Badge<EventHandler>, const Gfx::IntPoint&, unsigned, unsigned)
|
||||
{
|
||||
}
|
||||
|
||||
void Node::handle_mouseup(Badge<EventHandler>, const Gfx::IntPoint&, unsigned, unsigned)
|
||||
{
|
||||
}
|
||||
|
||||
void Node::handle_mousemove(Badge<EventHandler>, const Gfx::IntPoint&, unsigned, unsigned)
|
||||
{
|
||||
}
|
||||
|
||||
bool Node::handle_mousewheel(Badge<EventHandler>, const Gfx::IntPoint&, unsigned, unsigned, int wheel_delta_x, int wheel_delta_y)
|
||||
{
|
||||
if (auto* containing_block = this->containing_block()) {
|
||||
if (!containing_block->is_scrollable())
|
||||
return false;
|
||||
auto new_offset = containing_block->scroll_offset();
|
||||
new_offset.translate_by(wheel_delta_x, wheel_delta_y);
|
||||
containing_block->set_scroll_offset(new_offset);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Node::is_root_element() const
|
||||
{
|
||||
if (is_anonymous())
|
||||
|
|
|
@ -83,13 +83,6 @@ public:
|
|||
|
||||
bool is_inline_block() const;
|
||||
|
||||
virtual bool wants_mouse_events() const { return false; }
|
||||
|
||||
virtual void handle_mousedown(Badge<EventHandler>, const Gfx::IntPoint&, unsigned button, unsigned modifiers);
|
||||
virtual void handle_mouseup(Badge<EventHandler>, const Gfx::IntPoint&, unsigned button, unsigned modifiers);
|
||||
virtual void handle_mousemove(Badge<EventHandler>, const Gfx::IntPoint&, unsigned buttons, unsigned modifiers);
|
||||
virtual bool handle_mousewheel(Badge<EventHandler>, const Gfx::IntPoint&, unsigned buttons, unsigned modifiers, int wheel_delta_x, int wheel_delta_y);
|
||||
|
||||
virtual void paint_fragment(PaintContext&, const LineBoxFragment&, Painting::PaintPhase) const { }
|
||||
|
||||
// These are used to optimize hot is<T> variants for some classes where dynamic_cast is too slow.
|
||||
|
|
|
@ -27,93 +27,6 @@ RadioButton::~RadioButton()
|
|||
{
|
||||
}
|
||||
|
||||
void RadioButton::handle_mousedown(Badge<EventHandler>, 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 RadioButton::handle_mouseup(Badge<EventHandler>, const Gfx::IntPoint& position, unsigned button, unsigned)
|
||||
{
|
||||
if (!m_tracking_mouse || button != GUI::MouseButton::Primary || !dom_node().enabled())
|
||||
return;
|
||||
|
||||
// NOTE: Changing the checked state of the DOM node may run arbitrary JS, which could disappear this node.
|
||||
NonnullRefPtr protect = *this;
|
||||
|
||||
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)
|
||||
set_checked_within_group();
|
||||
|
||||
m_being_pressed = false;
|
||||
m_tracking_mouse = false;
|
||||
browsing_context().event_handler().set_mouse_event_tracking_layout_node(nullptr);
|
||||
}
|
||||
|
||||
void RadioButton::handle_mousemove(Badge<EventHandler>, 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 RadioButton::handle_associated_label_mousedown(Badge<Label>)
|
||||
{
|
||||
m_being_pressed = true;
|
||||
set_needs_display();
|
||||
}
|
||||
|
||||
void RadioButton::handle_associated_label_mouseup(Badge<Label>)
|
||||
{
|
||||
// NOTE: Changing the checked state of the DOM node may run arbitrary JS, which could disappear this node.
|
||||
NonnullRefPtr protect = *this;
|
||||
|
||||
set_checked_within_group();
|
||||
m_being_pressed = false;
|
||||
}
|
||||
|
||||
void RadioButton::handle_associated_label_mousemove(Badge<Label>, bool is_inside_node_or_label)
|
||||
{
|
||||
if (m_being_pressed == is_inside_node_or_label)
|
||||
return;
|
||||
|
||||
m_being_pressed = is_inside_node_or_label;
|
||||
set_needs_display();
|
||||
}
|
||||
|
||||
void RadioButton::set_checked_within_group()
|
||||
{
|
||||
if (dom_node().checked())
|
||||
return;
|
||||
|
||||
dom_node().set_checked(true, HTML::HTMLInputElement::ChangeSource::User);
|
||||
String name = dom_node().name();
|
||||
|
||||
document().for_each_in_inclusive_subtree_of_type<HTML::HTMLInputElement>([&](auto& element) {
|
||||
if (element.checked() && (element.layout_node() != this) && (element.name() == name))
|
||||
element.set_checked(false, HTML::HTMLInputElement::ChangeSource::User);
|
||||
return IterationDecision::Continue;
|
||||
});
|
||||
}
|
||||
|
||||
RefPtr<Painting::Paintable> RadioButton::create_paintable() const
|
||||
{
|
||||
return Painting::RadioButtonPaintable::create(*this);
|
||||
|
|
|
@ -19,24 +19,8 @@ public:
|
|||
const HTML::HTMLInputElement& dom_node() const { return static_cast<const HTML::HTMLInputElement&>(LabelableNode::dom_node()); }
|
||||
HTML::HTMLInputElement& dom_node() { return static_cast<HTML::HTMLInputElement&>(LabelableNode::dom_node()); }
|
||||
|
||||
virtual RefPtr<Painting::Paintable> create_paintable() const override;
|
||||
|
||||
bool being_pressed() const { return m_being_pressed; }
|
||||
|
||||
private:
|
||||
virtual bool wants_mouse_events() const override { return true; }
|
||||
virtual void handle_mousedown(Badge<EventHandler>, const Gfx::IntPoint&, unsigned button, unsigned modifiers) override;
|
||||
virtual void handle_mouseup(Badge<EventHandler>, const Gfx::IntPoint&, unsigned button, unsigned modifiers) override;
|
||||
virtual void handle_mousemove(Badge<EventHandler>, const Gfx::IntPoint&, unsigned buttons, unsigned modifiers) override;
|
||||
|
||||
virtual void handle_associated_label_mousedown(Badge<Label>) override;
|
||||
virtual void handle_associated_label_mouseup(Badge<Label>) override;
|
||||
virtual void handle_associated_label_mousemove(Badge<Label>, bool is_inside_node_or_label) override;
|
||||
|
||||
void set_checked_within_group();
|
||||
|
||||
bool m_being_pressed { false };
|
||||
bool m_tracking_mouse { false };
|
||||
virtual RefPtr<Painting::Paintable> create_paintable() const override;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -241,41 +241,6 @@ void TextNode::compute_text_for_rendering(bool collapse, bool previous_is_empty_
|
|||
m_text_for_rendering = builder.to_string();
|
||||
}
|
||||
|
||||
bool TextNode::wants_mouse_events() const
|
||||
{
|
||||
return first_ancestor_of_type<Label>();
|
||||
}
|
||||
|
||||
void TextNode::handle_mousedown(Badge<EventHandler>, const Gfx::IntPoint& position, unsigned button, unsigned)
|
||||
{
|
||||
auto* label = first_ancestor_of_type<Label>();
|
||||
if (!label)
|
||||
return;
|
||||
label->handle_mousedown_on_label({}, position, button);
|
||||
browsing_context().event_handler().set_mouse_event_tracking_layout_node(this);
|
||||
}
|
||||
|
||||
void TextNode::handle_mouseup(Badge<EventHandler>, const Gfx::IntPoint& position, unsigned button, unsigned)
|
||||
{
|
||||
auto* label = first_ancestor_of_type<Label>();
|
||||
if (!label)
|
||||
return;
|
||||
|
||||
// NOTE: Changing the state of the DOM node may run arbitrary JS, which could disappear this node.
|
||||
NonnullRefPtr protect = *this;
|
||||
|
||||
label->handle_mouseup_on_label({}, position, button);
|
||||
browsing_context().event_handler().set_mouse_event_tracking_layout_node(nullptr);
|
||||
}
|
||||
|
||||
void TextNode::handle_mousemove(Badge<EventHandler>, const Gfx::IntPoint& position, unsigned button, unsigned)
|
||||
{
|
||||
auto* label = first_ancestor_of_type<Label>();
|
||||
if (!label)
|
||||
return;
|
||||
label->handle_mousemove_on_label({}, position, button);
|
||||
}
|
||||
|
||||
TextNode::ChunkIterator::ChunkIterator(StringView text, LayoutMode layout_mode, bool wrap_lines, bool respect_linebreaks)
|
||||
: m_layout_mode(layout_mode)
|
||||
, m_wrap_lines(wrap_lines)
|
||||
|
|
|
@ -56,10 +56,6 @@ public:
|
|||
|
||||
private:
|
||||
virtual bool is_text_node() const final { return true; }
|
||||
virtual bool wants_mouse_events() const override;
|
||||
virtual void handle_mousedown(Badge<EventHandler>, const Gfx::IntPoint&, unsigned button, unsigned modifiers) override;
|
||||
virtual void handle_mouseup(Badge<EventHandler>, const Gfx::IntPoint&, unsigned button, unsigned modifiers) override;
|
||||
virtual void handle_mousemove(Badge<EventHandler>, const Gfx::IntPoint&, unsigned button, unsigned modifiers) override;
|
||||
void paint_cursor_if_needed(PaintContext&, const LineBoxFragment&) const;
|
||||
void paint_text_decoration(Gfx::Painter&, LineBoxFragment const&) const;
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue