From 5f54b8dd6ca114e9b867958f0a64b7b190d47a74 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Thu, 17 Feb 2022 12:59:32 +0100 Subject: [PATCH] LibWeb: Fire "input" and "change" events when editing a text This isn't entirely on-spec, but will hopefully allow us to make progress in other areas. --- Userland/Libraries/LibWeb/DOM/Text.cpp | 8 +++++++- Userland/Libraries/LibWeb/DOM/Text.h | 5 +++++ .../Libraries/LibWeb/HTML/BrowsingContext.cpp | 7 +++++++ .../Libraries/LibWeb/HTML/HTMLInputElement.cpp | 18 ++++++++++++++++++ .../Libraries/LibWeb/HTML/HTMLInputElement.h | 2 ++ 5 files changed, 39 insertions(+), 1 deletion(-) diff --git a/Userland/Libraries/LibWeb/DOM/Text.cpp b/Userland/Libraries/LibWeb/DOM/Text.cpp index 47754603d49..9f50e29fd85 100644 --- a/Userland/Libraries/LibWeb/DOM/Text.cpp +++ b/Userland/Libraries/LibWeb/DOM/Text.cpp @@ -1,11 +1,12 @@ /* - * Copyright (c) 2018-2020, Andreas Kling + * Copyright (c) 2018-2022, Andreas Kling * * SPDX-License-Identifier: BSD-2-Clause */ #include #include +#include #include namespace Web::DOM { @@ -25,4 +26,9 @@ NonnullRefPtr Text::create_with_global_object(Bindings::WindowObject& wind return make_ref_counted(window.impl().associated_document(), data); } +void Text::set_owner_input_element(Badge, HTML::HTMLInputElement& input_element) +{ + m_owner_input_element = input_element; +} + } diff --git a/Userland/Libraries/LibWeb/DOM/Text.h b/Userland/Libraries/LibWeb/DOM/Text.h index 1c298cc3718..e6bf9808755 100644 --- a/Userland/Libraries/LibWeb/DOM/Text.h +++ b/Userland/Libraries/LibWeb/DOM/Text.h @@ -27,7 +27,12 @@ public: void set_always_editable(bool b) { m_always_editable = b; } + void set_owner_input_element(Badge, HTML::HTMLInputElement&); + HTML::HTMLInputElement* owner_input_element() { return m_owner_input_element; } + private: + WeakPtr m_owner_input_element; + bool m_always_editable { false }; }; diff --git a/Userland/Libraries/LibWeb/HTML/BrowsingContext.cpp b/Userland/Libraries/LibWeb/HTML/BrowsingContext.cpp index d21a107ff13..668a0b1868c 100644 --- a/Userland/Libraries/LibWeb/HTML/BrowsingContext.cpp +++ b/Userland/Libraries/LibWeb/HTML/BrowsingContext.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -41,6 +42,12 @@ BrowsingContext::~BrowsingContext() void BrowsingContext::did_edit(Badge) { reset_cursor_blink_cycle(); + + if (m_cursor_position.node() && is(*m_cursor_position.node())) { + auto& text_node = static_cast(*m_cursor_position.node()); + if (auto* input_element = text_node.owner_input_element()) + input_element->did_edit_text_node({}); + } } void BrowsingContext::reset_cursor_blink_cycle() diff --git a/Userland/Libraries/LibWeb/HTML/HTMLInputElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLInputElement.cpp index da928de42df..4935f8d3d35 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLInputElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLInputElement.cpp @@ -112,6 +112,23 @@ void HTMLInputElement::run_input_activation_behavior() } } +void HTMLInputElement::did_edit_text_node(Badge) +{ + // NOTE: This is a bit ad-hoc, but basically implements part of "4.10.5.5 Common event behaviors" + // https://html.spec.whatwg.org/multipage/input.html#common-input-element-events + queue_an_element_task(HTML::Task::Source::UserInteraction, [this] { + auto input_event = DOM::Event::create(HTML::EventNames::input); + input_event->set_bubbles(true); + input_event->set_composed(true); + dispatch_event(move(input_event)); + + // FIXME: This should only fire when the input is "committed", whatever that means. + auto change_event = DOM::Event::create(HTML::EventNames::change); + change_event->set_bubbles(true); + dispatch_event(move(change_event)); + }); +} + bool HTMLInputElement::enabled() const { return !has_attribute(HTML::AttributeNames::disabled); @@ -147,6 +164,7 @@ void HTMLInputElement::create_shadow_tree_if_needed() element->set_attribute(HTML::AttributeNames::style, "white-space: pre"); m_text_node = adopt_ref(*new DOM::Text(document(), initial_value)); m_text_node->set_always_editable(true); + m_text_node->set_owner_input_element({}, *this); element->append_child(*m_text_node); shadow_root->append_child(move(element)); set_shadow_root(move(shadow_root)); diff --git a/Userland/Libraries/LibWeb/HTML/HTMLInputElement.h b/Userland/Libraries/LibWeb/HTML/HTMLInputElement.h index 248c968061f..7a5265ac054 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLInputElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLInputElement.h @@ -42,6 +42,8 @@ public: void did_click_button(Badge); + void did_edit_text_node(Badge); + virtual bool is_focusable() const override; virtual void parse_attribute(FlyString const&, String const&) override;