summaryrefslogtreecommitdiff
path: root/Userland/Libraries/LibWeb/Painting/ButtonPaintable.cpp
diff options
context:
space:
mode:
authorAndreas Kling <kling@serenityos.org>2022-03-10 22:46:35 +0100
committerAndreas Kling <kling@serenityos.org>2022-03-11 00:21:49 +0100
commitcb0c5390ff9a0189ae79cfd690f6c089ba73c4a7 (patch)
treef6b3f94c65f92cb195e67eb75add5eb9815e8cc2 /Userland/Libraries/LibWeb/Painting/ButtonPaintable.cpp
parented84fbce474a86721ff85aa9559213e12bd556ba (diff)
downloadserenity-cb0c5390ff9a0189ae79cfd690f6c089ba73c4a7.zip
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.
Diffstat (limited to 'Userland/Libraries/LibWeb/Painting/ButtonPaintable.cpp')
-rw-r--r--Userland/Libraries/LibWeb/Painting/ButtonPaintable.cpp87
1 files changed, 85 insertions, 2 deletions
diff --git a/Userland/Libraries/LibWeb/Painting/ButtonPaintable.cpp b/Userland/Libraries/LibWeb/Painting/ButtonPaintable.cpp
index 87c343ca83..dd406293bb 100644
--- a/Userland/Libraries/LibWeb/Painting/ButtonPaintable.cpp
+++ b/Userland/Libraries/LibWeb/Painting/ButtonPaintable.cpp
@@ -4,8 +4,11 @@
* SPDX-License-Identifier: BSD-2-Clause
*/
+#include <LibGUI/Event.h>
+#include <LibWeb/HTML/BrowsingContext.h>
#include <LibWeb/HTML/HTMLImageElement.h>
#include <LibWeb/Layout/ButtonBox.h>
+#include <LibWeb/Layout/Label.h>
#include <LibWeb/Painting/ButtonPaintable.h>
namespace Web::Painting {
@@ -16,7 +19,7 @@ NonnullRefPtr<ButtonPaintable> ButtonPaintable::create(Layout::ButtonBox const&
}
ButtonPaintable::ButtonPaintable(Layout::ButtonBox const& layout_box)
- : PaintableBox(layout_box)
+ : LabelablePaintable(layout_box)
{
}
@@ -25,6 +28,11 @@ Layout::ButtonBox const& ButtonPaintable::layout_box() const
return static_cast<Layout::ButtonBox const&>(layout_node());
}
+Layout::ButtonBox& ButtonPaintable::layout_box()
+{
+ return static_cast<Layout::ButtonBox&>(layout_node());
+}
+
void ButtonPaintable::paint(PaintContext& context, PaintPhase phase) const
{
if (!is_visible())
@@ -34,10 +42,85 @@ void ButtonPaintable::paint(PaintContext& context, PaintPhase phase) const
if (phase == PaintPhase::Foreground) {
auto text_rect = enclosing_int_rect(absolute_rect());
- if (layout_box().being_pressed())
+ if (m_being_pressed)
text_rect.translate_by(1, 1);
context.painter().draw_text(text_rect, layout_box().dom_node().value(), layout_box().font(), Gfx::TextAlignment::Center, computed_values().color());
}
}
+void ButtonPaintable::handle_mousedown(Badge<EventHandler>, const Gfx::IntPoint&, unsigned button, unsigned)
+{
+ if (button != GUI::MouseButton::Primary || !layout_box().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(&layout_box());
+}
+
+void ButtonPaintable::handle_mouseup(Badge<EventHandler>, const Gfx::IntPoint& position, unsigned button, unsigned)
+{
+ if (!m_tracking_mouse || button != GUI::MouseButton::Primary || !layout_box().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(absolute_rect()).contains(position);
+ if (!is_inside_node_or_label)
+ is_inside_node_or_label = Layout::Label::is_inside_associated_label(layout_box(), position);
+
+ if (is_inside_node_or_label)
+ const_cast<Layout::ButtonBox&>(layout_box()).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 ButtonPaintable::handle_mousemove(Badge<EventHandler>, const Gfx::IntPoint& position, unsigned, unsigned)
+{
+ if (!m_tracking_mouse || !layout_box().dom_node().enabled())
+ return;
+
+ bool is_inside_node_or_label = enclosing_int_rect(absolute_rect()).contains(position);
+ if (!is_inside_node_or_label)
+ is_inside_node_or_label = Layout::Label::is_inside_associated_label(layout_box(), position);
+
+ if (m_being_pressed == is_inside_node_or_label)
+ return;
+
+ m_being_pressed = is_inside_node_or_label;
+ set_needs_display();
+}
+
+void ButtonPaintable::handle_associated_label_mousedown(Badge<Layout::Label>)
+{
+ m_being_pressed = true;
+ set_needs_display();
+}
+
+void ButtonPaintable::handle_associated_label_mouseup(Badge<Layout::Label>)
+{
+ // NOTE: Handling the click may run arbitrary JS, which could disappear this node.
+ NonnullRefPtr protected_this = *this;
+ NonnullRefPtr protected_browsing_context = browsing_context();
+
+ layout_box().dom_node().did_click_button({});
+ m_being_pressed = false;
+}
+
+void ButtonPaintable::handle_associated_label_mousemove(Badge<Layout::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();
+}
+
}