diff --git a/Userland/Libraries/LibWeb/HTML/NavigateEvent.cpp b/Userland/Libraries/LibWeb/HTML/NavigateEvent.cpp index e50d6c0f177..5fc2b6adc0a 100644 --- a/Userland/Libraries/LibWeb/HTML/NavigateEvent.cpp +++ b/Userland/Libraries/LibWeb/HTML/NavigateEvent.cpp @@ -14,7 +14,9 @@ #include #include #include +#include #include +#include #include #include @@ -196,4 +198,89 @@ void NavigateEvent::process_scroll_behavior() } } +// https://html.spec.whatwg.org/multipage/nav-history-apis.html#potentially-process-scroll-behavior +void NavigateEvent::potentially_process_scroll_behavior() +{ + // 1. Assert: event's interception state is "committed" or "scrolled". + VERIFY(m_interception_state != InterceptionState::Committed && m_interception_state != InterceptionState::Scrolled); + + // 2. If event's interception state is "scrolled", then return. + if (m_interception_state == InterceptionState::Scrolled) + return; + + // 3. If event's scroll behavior is "manual", then return. + // NOTE: If it was left as null, then we treat that as "after-transition", and continue onward. + if (m_scroll_behavior == Bindings::NavigationScrollBehavior::Manual) + return; + + // 4. Process scroll behavior given event. + process_scroll_behavior(); +} + +// https://html.spec.whatwg.org/multipage/nav-history-apis.html#potentially-reset-the-focus +void NavigateEvent::potentially_reset_the_focus() +{ + // 1. Assert: event's interception state is "committed" or "scrolled". + VERIFY(m_interception_state == InterceptionState::Committed || m_interception_state == InterceptionState::Scrolled); + + // 2. Let navigation be event's relevant global object's navigation API. + auto& relevant_global_object = verify_cast(HTML::relevant_global_object(*this)); + auto navigation = relevant_global_object.navigation(); + + // 3. Let focusChanged be navigation's focus changed during ongoing navigation. + auto focus_changed = navigation->focus_changed_during_ongoing_navigation(); + + // 4. Set navigation's focus changed during ongoing navigation to false. + navigation->set_focus_changed_during_ongoing_navigation(false); + + // 5. If focusChanged is true, then return. + if (focus_changed) + return; + + // 6. If event's focus reset behavior is "manual", then return. + // NOTE: If it was left as null, then we treat that as "after-transition", and continue onward. + if (m_focus_reset_behavior == Bindings::NavigationFocusReset::Manual) + return; + + // 7. Let document be event's relevant global object's associated Document. + auto& document = relevant_global_object.associated_document(); + + // 8. FIXME: Let focusTarget be the autofocus delegate for document. + JS::GCPtr focus_target = nullptr; + + // 9. If focusTarget is null, then set focusTarget to document's body element. + if (focus_target == nullptr) + focus_target = document.body(); + + // 10. If focusTarget is null, then set focusTarget to document's document element. + if (focus_target == nullptr) + focus_target = document.document_element(); + + // FIXME: 11. Run the focusing steps for focusTarget, with document's viewport as the fallback target. + run_focusing_steps(focus_target, nullptr); + + // FIXME: 12. Move the sequential focus navigation starting point to focusTarget. +} + +// https://html.spec.whatwg.org/multipage/nav-history-apis.html#navigateevent-finish +void NavigateEvent::finish(bool did_fulfill) +{ + // 1. Assert: event's interception state is not "intercepted" or "finished". + VERIFY(m_interception_state != InterceptionState::Intercepted && m_interception_state != InterceptionState::Finished); + + // 2. If event's interception state is "none", then return. + if (m_interception_state == InterceptionState::None) + return; + + // 3. Potentially reset the focus given event. + potentially_reset_the_focus(); + + // 4. If didFulfill is true, then potentially process scroll behavior given event. + if (did_fulfill) + potentially_process_scroll_behavior(); + + // 5. Set event's interception state to "finished". + m_interception_state = InterceptionState::Finished; +} + } diff --git a/Userland/Libraries/LibWeb/HTML/NavigateEvent.h b/Userland/Libraries/LibWeb/HTML/NavigateEvent.h index 211fdf0c225..5141d4a6f74 100644 --- a/Userland/Libraries/LibWeb/HTML/NavigateEvent.h +++ b/Userland/Libraries/LibWeb/HTML/NavigateEvent.h @@ -64,6 +64,8 @@ public: JS::NonnullGCPtr abort_controller() const { return *m_abort_controller; } + void finish(bool did_fulfill); + private: NavigateEvent(JS::Realm&, FlyString const& event_name, NavigateEventInit const& event_init); @@ -72,6 +74,8 @@ private: WebIDL::ExceptionOr perform_shared_checks(); void process_scroll_behavior(); + void potentially_process_scroll_behavior(); + void potentially_reset_the_focus(); // https://html.spec.whatwg.org/multipage/nav-history-apis.html#concept-navigateevent-interception-state enum class InterceptionState { diff --git a/Userland/Libraries/LibWeb/HTML/Navigation.h b/Userland/Libraries/LibWeb/HTML/Navigation.h index 05d34b0f7f8..2f40c7fab4b 100644 --- a/Userland/Libraries/LibWeb/HTML/Navigation.h +++ b/Userland/Libraries/LibWeb/HTML/Navigation.h @@ -110,9 +110,12 @@ public: virtual ~Navigation() override; - // Internal Getters + // Internal Getters/Setters JS::GCPtr ongoing_navigate_event() const { return m_ongoing_navigate_event; } + bool focus_changed_during_ongoing_navigation() const { return m_focus_changed_during_ongoing_navigation; } + void set_focus_changed_during_ongoing_navigation(bool b) { m_focus_changed_during_ongoing_navigation = b; } + private: explicit Navigation(JS::Realm&);