Explorar o código

LibWeb: Defer mouse events from TextNode to Label

A label's format is: <label>Label text</label>

So, a TextNode is created as a child of the Label node, and EventHandler
will send events to the TextNode. This changes TextNode to accept mouse
events if its parent is a Label, and to forward those events upward.
Timothy Flynn %!s(int64=4) %!d(string=hai) anos
pai
achega
e1b5613142

+ 1 - 0
Userland/Libraries/LibWeb/Forward.h

@@ -182,6 +182,7 @@ class Node;
 class NodeWithStyle;
 class RadioButton;
 class ReplacedBox;
+class TextNode;
 }
 
 namespace Web {

+ 3 - 3
Userland/Libraries/LibWeb/Layout/Label.cpp

@@ -45,7 +45,7 @@ Label::~Label()
 {
 }
 
-void Label::handle_mousedown(Badge<EventHandler>, const Gfx::IntPoint&, unsigned button, unsigned)
+void Label::handle_mousedown_on_label(Badge<TextNode>, const Gfx::IntPoint&, unsigned button)
 {
     if (button != GUI::MouseButton::Left)
         return;
@@ -56,7 +56,7 @@ void Label::handle_mousedown(Badge<EventHandler>, const Gfx::IntPoint&, unsigned
     m_tracking_mouse = true;
 }
 
-void Label::handle_mouseup(Badge<EventHandler>, const Gfx::IntPoint& position, unsigned button, unsigned)
+void Label::handle_mouseup_on_label(Badge<TextNode>, const Gfx::IntPoint& position, unsigned button)
 {
     if (!m_tracking_mouse || button != GUI::MouseButton::Left)
         return;
@@ -75,7 +75,7 @@ void Label::handle_mouseup(Badge<EventHandler>, const Gfx::IntPoint& position, u
     m_tracking_mouse = false;
 }
 
-void Label::handle_mousemove(Badge<EventHandler>, const Gfx::IntPoint& position, unsigned, unsigned)
+void Label::handle_mousemove_on_label(Badge<TextNode>, const Gfx::IntPoint& position, unsigned)
 {
     if (!m_tracking_mouse)
         return;

+ 4 - 5
Userland/Libraries/LibWeb/Layout/Label.h

@@ -41,12 +41,11 @@ public:
     const HTML::HTMLLabelElement& dom_node() const { return static_cast<const HTML::HTMLLabelElement&>(*BlockBox::dom_node()); }
     HTML::HTMLLabelElement& dom_node() { return static_cast<HTML::HTMLLabelElement&>(*BlockBox::dom_node()); }
 
-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 button, unsigned modifiers) override;
+    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);
 
+private:
     static Label* label_for_control_node(LabelableNode&);
     LabelableNode* control_node();
 

+ 29 - 0
Userland/Libraries/LibWeb/Layout/TextNode.cpp

@@ -30,6 +30,7 @@
 #include <LibWeb/DOM/Document.h>
 #include <LibWeb/Layout/BlockBox.h>
 #include <LibWeb/Layout/InlineFormattingContext.h>
+#include <LibWeb/Layout/Label.h>
 #include <LibWeb/Layout/TextNode.h>
 #include <LibWeb/Page/Frame.h>
 #include <ctype.h>
@@ -306,4 +307,32 @@ void TextNode::split_into_lines(InlineFormattingContext& context, LayoutMode lay
     split_into_lines_by_rules(context, layout_mode, do_collapse, do_wrap_lines, do_wrap_breaks);
 }
 
+bool TextNode::wants_mouse_events() const
+{
+    return parent() && is<Label>(parent());
+}
+
+void TextNode::handle_mousedown(Badge<EventHandler>, const Gfx::IntPoint& position, unsigned button, unsigned)
+{
+    if (!parent() || !is<Label>(*parent()))
+        return;
+    downcast<Label>(*parent()).handle_mousedown_on_label({}, position, button);
+    frame().event_handler().set_mouse_event_tracking_layout_node(this);
+}
+
+void TextNode::handle_mouseup(Badge<EventHandler>, const Gfx::IntPoint& position, unsigned button, unsigned)
+{
+    if (!parent() || !is<Label>(*parent()))
+        return;
+    downcast<Label>(*parent()).handle_mouseup_on_label({}, position, button);
+    frame().event_handler().set_mouse_event_tracking_layout_node(nullptr);
+}
+
+void TextNode::handle_mousemove(Badge<EventHandler>, const Gfx::IntPoint& position, unsigned button, unsigned)
+{
+    if (!parent() || !is<Label>(*parent()))
+        return;
+    downcast<Label>(*parent()).handle_mousemove_on_label({}, position, button);
+}
+
 }

+ 4 - 0
Userland/Libraries/LibWeb/Layout/TextNode.h

@@ -48,6 +48,10 @@ 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 split_into_lines_by_rules(InlineFormattingContext&, LayoutMode, bool do_collapse, bool do_wrap_lines, bool do_wrap_breaks);
     void paint_cursor_if_needed(PaintContext&, const LineBoxFragment&) const;