From bf7f6a9e983d0ef4ba41e14f86597d29754f4980 Mon Sep 17 00:00:00 2001 From: Kenneth Myhra Date: Tue, 8 Feb 2022 21:23:43 +0100 Subject: [PATCH] LibWeb: Implement EventHandler::focus_previous_element() This implements EventHandler::focus_previous_element() so we can cycle backwards through focusable elements on a web page with Shift+Tab. --- .../LibWeb/DOM/NonDocumentTypeChildNode.h | 10 ++++++++++ .../Libraries/LibWeb/Page/EventHandler.cpp | 18 ++++++++++++++++-- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/Userland/Libraries/LibWeb/DOM/NonDocumentTypeChildNode.h b/Userland/Libraries/LibWeb/DOM/NonDocumentTypeChildNode.h index 2683919113..3929382b7c 100644 --- a/Userland/Libraries/LibWeb/DOM/NonDocumentTypeChildNode.h +++ b/Userland/Libraries/LibWeb/DOM/NonDocumentTypeChildNode.h @@ -24,6 +24,15 @@ public: return nullptr; } + Element* previous_element_in_pre_order() + { + for (auto* node = static_cast(this)->previous_in_pre_order(); node; node = node->previous_in_pre_order()) { + if (is(*node)) + return verify_cast(node); + } + return nullptr; + } + Element* next_element_sibling() { for (auto* sibling = static_cast(this)->next_sibling(); sibling; sibling = sibling->next_sibling()) { @@ -43,6 +52,7 @@ public: } const Element* previous_element_sibling() const { return const_cast(this)->previous_element_sibling(); } + const Element* previous_element_in_pre_order() const { return const_cast(this)->previous_element_in_pre_order(); } const Element* next_element_sibling() const { return const_cast(this)->next_element_sibling(); } const Element* next_element_in_pre_order() const { return const_cast(this)->next_element_in_pre_order(); } diff --git a/Userland/Libraries/LibWeb/Page/EventHandler.cpp b/Userland/Libraries/LibWeb/Page/EventHandler.cpp index e45ab08d9a..962011677a 100644 --- a/Userland/Libraries/LibWeb/Page/EventHandler.cpp +++ b/Userland/Libraries/LibWeb/Page/EventHandler.cpp @@ -413,8 +413,22 @@ bool EventHandler::focus_next_element() bool EventHandler::focus_previous_element() { - // FIXME: Implement Shift-Tab cycling backwards through focusable elements! - return false; + if (!m_browsing_context.active_document()) + return false; + auto* element = m_browsing_context.active_document()->focused_element(); + if (!element) { + element = m_browsing_context.active_document()->last_child_of_type(); + if (element && element->is_focusable()) { + m_browsing_context.active_document()->set_focused_element(element); + return true; + } + } + + for (element = element->previous_element_in_pre_order(); element && !element->is_focusable(); element = element->previous_element_in_pre_order()) + ; + + m_browsing_context.active_document()->set_focused_element(element); + return element; } constexpr bool should_ignore_keydown_event(u32 code_point)