diff --git a/Libraries/LibWeb/DOM/Document.h b/Libraries/LibWeb/DOM/Document.h index 15c3e7d747d..1c030d453aa 100644 --- a/Libraries/LibWeb/DOM/Document.h +++ b/Libraries/LibWeb/DOM/Document.h @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -433,6 +434,9 @@ public: void set_focused_element(GC::Ptr); + HTML::FocusTrigger last_focus_trigger() const { return m_last_focus_trigger; } + void set_last_focus_trigger(HTML::FocusTrigger trigger) { m_last_focus_trigger = trigger; } + Element const* active_element() const { return m_active_element.ptr(); } void set_active_element(GC::Ptr); @@ -1013,6 +1017,8 @@ private: bool m_editable { false }; GC::Ptr m_focused_element; + HTML::FocusTrigger m_last_focus_trigger { HTML::FocusTrigger::Other }; + GC::Ptr m_active_element; GC::Ptr m_target_element; diff --git a/Libraries/LibWeb/HTML/Focus.cpp b/Libraries/LibWeb/HTML/Focus.cpp index 9c143e0d95d..b8fe2594af6 100644 --- a/Libraries/LibWeb/HTML/Focus.cpp +++ b/Libraries/LibWeb/HTML/Focus.cpp @@ -193,7 +193,7 @@ static Vector> focus_chain(DOM::Node* subject) // https://html.spec.whatwg.org/multipage/interaction.html#focusing-steps // FIXME: This should accept more types. -void run_focusing_steps(DOM::Node* new_focus_target, DOM::Node* fallback_target, [[maybe_unused]] Optional focus_trigger) +void run_focusing_steps(DOM::Node* new_focus_target, DOM::Node* fallback_target, FocusTrigger focus_trigger) { // FIXME: 1. If new focus target is not a focusable area, then set new focus target // to the result of getting the focusable area for new focus target, @@ -234,6 +234,9 @@ void run_focusing_steps(DOM::Node* new_focus_target, DOM::Node* fallback_target, // 7. Let new chain be the focus chain of new focus target. auto new_chain = focus_chain(new_focus_target); + // AD-HOC: Remember last focus trigger for :focus-visible / focus indication. + new_focus_target->document().set_last_focus_trigger(focus_trigger); + // 8. Run the focus update steps with old chain, new chain, and new focus target respectively. run_focus_update_steps(old_chain, new_chain, new_focus_target); } diff --git a/Libraries/LibWeb/HTML/Focus.h b/Libraries/LibWeb/HTML/Focus.h index 03ab002b947..5d690e39028 100644 --- a/Libraries/LibWeb/HTML/Focus.h +++ b/Libraries/LibWeb/HTML/Focus.h @@ -12,7 +12,14 @@ namespace Web::HTML { -void run_focusing_steps(DOM::Node* new_focus_target, DOM::Node* fallback_target = nullptr, Optional focus_trigger = {}); +enum class FocusTrigger : u8 { + Click, + Key, + Script, + Other, +}; + +void run_focusing_steps(DOM::Node* new_focus_target, DOM::Node* fallback_target = nullptr, FocusTrigger focus_trigger = FocusTrigger::Other); void run_unfocusing_steps(DOM::Node* old_focus_target); } diff --git a/Libraries/LibWeb/HTML/HTMLOrSVGElement.cpp b/Libraries/LibWeb/HTML/HTMLOrSVGElement.cpp index 1c272e60505..d1a19024438 100644 --- a/Libraries/LibWeb/HTML/HTMLOrSVGElement.cpp +++ b/Libraries/LibWeb/HTML/HTMLOrSVGElement.cpp @@ -31,7 +31,7 @@ void HTMLOrSVGElement::focus() return; // 2. Run the focusing steps for this. - run_focusing_steps(static_cast(this)); + run_focusing_steps(static_cast(this), nullptr, FocusTrigger::Script); // FIXME: 3. If options["focusVisible"] is true, or does not exist but in an implementation-defined way the user agent determines it would be best to do so, then indicate focus. diff --git a/Libraries/LibWeb/Page/EventHandler.cpp b/Libraries/LibWeb/Page/EventHandler.cpp index 8d9c8340192..c9df777b97f 100644 --- a/Libraries/LibWeb/Page/EventHandler.cpp +++ b/Libraries/LibWeb/Page/EventHandler.cpp @@ -679,7 +679,7 @@ EventResult EventHandler::handle_mousedown(CSSPixelPoint viewport_position, CSSP // When a user activates a click focusable focusable area, the user agent must run the focusing steps on the focusable area with focus trigger set to "click". // Spec Note: Note that focusing is not an activation behavior, i.e. calling the click() method on an element or dispatching a synthetic click event on it won't cause the element to get focused. if (focus_candidate) - HTML::run_focusing_steps(focus_candidate, nullptr, "click"sv); + HTML::run_focusing_steps(focus_candidate, nullptr, HTML::FocusTrigger::Click); else if (auto* focused_element = document->focused_element()) HTML::run_unfocusing_steps(focused_element);