From dd06a3e69c02646f050961a4551c9ee063d9baff Mon Sep 17 00:00:00 2001 From: Luke Warlow Date: Thu, 5 Dec 2024 22:53:51 +0000 Subject: [PATCH] LibWeb: Implement dialog closedby attribute closedby=any should add light-dismiss behavior to dialog, this isn't implemented in this patch. --- Libraries/LibWeb/HTML/AttributeNames.h | 3 ++- Libraries/LibWeb/HTML/HTMLDialogElement.cpp | 30 ++++++++++++++++++--- Libraries/LibWeb/HTML/HTMLDialogElement.h | 6 +++++ Libraries/LibWeb/HTML/HTMLDialogElement.idl | 2 +- 4 files changed, 35 insertions(+), 6 deletions(-) diff --git a/Libraries/LibWeb/HTML/AttributeNames.h b/Libraries/LibWeb/HTML/AttributeNames.h index 945f72b63cbf..ecdfa638ca7f 100644 --- a/Libraries/LibWeb/HTML/AttributeNames.h +++ b/Libraries/LibWeb/HTML/AttributeNames.h @@ -43,7 +43,8 @@ namespace AttributeNames { __ENUMERATE_HTML_ATTRIBUTE(cite, "cite") \ __ENUMERATE_HTML_ATTRIBUTE(class_, "class") \ __ENUMERATE_HTML_ATTRIBUTE(classid, "classid") \ - __ENUMERATE_HTML_ATTRIBUTE(clear, "clear") \ + __ENUMERATE_HTML_ATTRIBUTE(clear, "clear") \ + __ENUMERATE_HTML_ATTRIBUTE(closedby, "closedby") \ __ENUMERATE_HTML_ATTRIBUTE(code, "code") \ __ENUMERATE_HTML_ATTRIBUTE(codebase, "codebase") \ __ENUMERATE_HTML_ATTRIBUTE(codetype, "codetype") \ diff --git a/Libraries/LibWeb/HTML/HTMLDialogElement.cpp b/Libraries/LibWeb/HTML/HTMLDialogElement.cpp index ee8f1e30f7e8..7a5e3ac62a6f 100644 --- a/Libraries/LibWeb/HTML/HTMLDialogElement.cpp +++ b/Libraries/LibWeb/HTML/HTMLDialogElement.cpp @@ -254,9 +254,8 @@ void HTMLDialogElement::request_close(Optional return_value) m_close_watcher->request_close(false); // 7. Set dialog's enable close watcher for requestClose() to false. // ADHOC: Implemented slightly differently to the spec, as the spec is unnecessarily complex. - // FIXME: This should be set based on dialog closedby state, when implemented. if (m_close_watcher) - m_close_watcher->set_enabled(m_is_modal); + m_close_watcher->set_enabled(closed_by() != "none"); } // https://html.spec.whatwg.org/multipage/interactive-elements.html#dom-dialog-returnvalue @@ -271,6 +270,21 @@ void HTMLDialogElement::set_return_value(String return_value) m_return_value = move(return_value); } +String HTMLDialogElement::closed_by() const +{ + auto value = get_attribute(HTML::AttributeNames::closedby); + + if (value.has_value() && (value.value() == "none" || value.value() == "closerequest" || value.value() == "any")) + return value.value(); + + return m_is_modal ? "closerequest"_string : "none"_string; +} + +WebIDL::ExceptionOr HTMLDialogElement::set_closed_by(String value) +{ + return set_attribute(HTML::AttributeNames::closedby, value); +} + // https://html.spec.whatwg.org/multipage/interactive-elements.html#close-the-dialog void HTMLDialogElement::close_the_dialog(Optional result) { @@ -364,8 +378,7 @@ void HTMLDialogElement::set_close_watcher() m_close_watcher->add_event_listener_without_options(HTML::EventNames::close, DOM::IDLEventListener::create(realm(), close_callback)); // - getEnabledState being to return true if dialog's enable close watcher for requestClose() is true or dialog's computed closed-by state is not None; otherwise false. // ADHOC: Implemented slightly differently to the spec, as the spec is unnecessarily complex. - // FIXME: This should be set based on dialog closedby state, when implemented. - m_close_watcher->set_enabled(m_is_modal); + m_close_watcher->set_enabled(closed_by() != "none"); } // https://html.spec.whatwg.org/multipage/interactive-elements.html#dialog-focusing-steps @@ -385,4 +398,13 @@ void HTMLDialogElement::run_dialog_focusing_steps() run_focusing_steps(control); } +void HTMLDialogElement::attribute_changed(FlyString const& name, Optional const& old_value, Optional const& value, Optional const& namespace_) +{ + Base::attribute_changed(name, old_value, value, namespace_); + + // ADHOC: This is part of the implementation of dialog close watcher's getEnabledState. + if (name == HTML::AttributeNames::closedby && m_close_watcher && old_value != value) + m_close_watcher->set_enabled(closed_by() != "none"); +} + } diff --git a/Libraries/LibWeb/HTML/HTMLDialogElement.h b/Libraries/LibWeb/HTML/HTMLDialogElement.h index de4e3f54aff0..8376fbc0ba04 100644 --- a/Libraries/LibWeb/HTML/HTMLDialogElement.h +++ b/Libraries/LibWeb/HTML/HTMLDialogElement.h @@ -26,6 +26,9 @@ class HTMLDialogElement final : public HTMLElement { String return_value() const; void set_return_value(String); + String closed_by() const; + WebIDL::ExceptionOr set_closed_by(String); + WebIDL::ExceptionOr show(); WebIDL::ExceptionOr show_modal(); void close(Optional return_value); @@ -42,6 +45,9 @@ class HTMLDialogElement final : public HTMLElement { virtual void initialize(JS::Realm&) override; virtual void visit_edges(Cell::Visitor&) override; + // ^DOM::Element + virtual void attribute_changed(FlyString const& name, Optional const& old_value, Optional const& value, Optional const& namespace_) override; + void queue_a_dialog_toggle_event_task(String old_state, String new_state); void close_the_dialog(Optional result); diff --git a/Libraries/LibWeb/HTML/HTMLDialogElement.idl b/Libraries/LibWeb/HTML/HTMLDialogElement.idl index 751c498997cf..61c594632d52 100644 --- a/Libraries/LibWeb/HTML/HTMLDialogElement.idl +++ b/Libraries/LibWeb/HTML/HTMLDialogElement.idl @@ -8,7 +8,7 @@ interface HTMLDialogElement : HTMLElement { [CEReactions, Reflect] attribute boolean open; attribute DOMString returnValue; - [FIXME, CEReactions] attribute DOMString closedBy; + [CEReactions] attribute DOMString closedBy; [CEReactions] undefined show(); [CEReactions] undefined showModal(); [CEReactions] undefined close(optional DOMString returnValue);