diff --git a/Userland/Libraries/LibWeb/CSS/Parser/DeprecatedCSSParser.cpp b/Userland/Libraries/LibWeb/CSS/Parser/DeprecatedCSSParser.cpp index cd48a1b2a0..5c72d24598 100644 --- a/Userland/Libraries/LibWeb/CSS/Parser/DeprecatedCSSParser.cpp +++ b/Userland/Libraries/LibWeb/CSS/Parser/DeprecatedCSSParser.cpp @@ -563,6 +563,8 @@ public: simple_selector.pseudo_class = CSS::Selector::SimpleSelector::PseudoClass::Link; } else if (pseudo_name.equals_ignoring_case("visited")) { simple_selector.pseudo_class = CSS::Selector::SimpleSelector::PseudoClass::Visited; + } else if (pseudo_name.equals_ignoring_case("active")) { + simple_selector.pseudo_class = CSS::Selector::SimpleSelector::PseudoClass::Active; } else if (pseudo_name.equals_ignoring_case("hover")) { simple_selector.pseudo_class = CSS::Selector::SimpleSelector::PseudoClass::Hover; } else if (pseudo_name.equals_ignoring_case("focus")) { diff --git a/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp b/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp index 0ed2a9e7be..dce9f251ad 100644 --- a/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp +++ b/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp @@ -200,6 +200,8 @@ Vector Parser::parse_selectors(Vector pa simple_selector.pseudo_class = CSS::Selector::SimpleSelector::PseudoClass::Link; } else if (pseudo_name.equals_ignoring_case("visited")) { simple_selector.pseudo_class = CSS::Selector::SimpleSelector::PseudoClass::Visited; + } else if (pseudo_name.equals_ignoring_case("active")) { + simple_selector.pseudo_class = CSS::Selector::SimpleSelector::PseudoClass::Active; } else if (pseudo_name.equals_ignoring_case("hover")) { simple_selector.pseudo_class = CSS::Selector::SimpleSelector::PseudoClass::Hover; } else if (pseudo_name.equals_ignoring_case("focus")) { diff --git a/Userland/Libraries/LibWeb/CSS/Selector.h b/Userland/Libraries/LibWeb/CSS/Selector.h index eb648bde8c..2a4eb11be0 100644 --- a/Userland/Libraries/LibWeb/CSS/Selector.h +++ b/Userland/Libraries/LibWeb/CSS/Selector.h @@ -43,6 +43,7 @@ public: Enabled, Checked, Not, + Active, }; PseudoClass pseudo_class { PseudoClass::None }; diff --git a/Userland/Libraries/LibWeb/CSS/SelectorEngine.cpp b/Userland/Libraries/LibWeb/CSS/SelectorEngine.cpp index 7669a57f6f..99916b6303 100644 --- a/Userland/Libraries/LibWeb/CSS/SelectorEngine.cpp +++ b/Userland/Libraries/LibWeb/CSS/SelectorEngine.cpp @@ -44,13 +44,18 @@ static bool matches(const CSS::Selector::SimpleSelector& component, const DOM::E case CSS::Selector::SimpleSelector::PseudoClass::Visited: // FIXME: Maybe match this selector sometimes? return false; + case CSS::Selector::SimpleSelector::PseudoClass::Active: + if (!element.is_active()) + return false; + break; case CSS::Selector::SimpleSelector::PseudoClass::Hover: if (!matches_hover_pseudo_class(element)) return false; break; case CSS::Selector::SimpleSelector::PseudoClass::Focus: - // FIXME: Implement matches_focus_pseudo_class(element) - return false; + if (!element.is_focused()) + return false; + break; case CSS::Selector::SimpleSelector::PseudoClass::FirstChild: if (element.previous_element_sibling()) return false; diff --git a/Userland/Libraries/LibWeb/DOM/Document.cpp b/Userland/Libraries/LibWeb/DOM/Document.cpp index 712c963f12..68824b541a 100644 --- a/Userland/Libraries/LibWeb/DOM/Document.cpp +++ b/Userland/Libraries/LibWeb/DOM/Document.cpp @@ -876,6 +876,17 @@ void Document::set_focused_element(Element* element) m_layout_root->set_needs_display(); } +void Document::set_active_element(Element* element) +{ + if (m_active_element == element) + return; + + m_active_element = element; + + if (m_layout_root) + m_layout_root->set_needs_display(); +} + void Document::set_ready_state(const String& ready_state) { m_ready_state = ready_state; diff --git a/Userland/Libraries/LibWeb/DOM/Document.h b/Userland/Libraries/LibWeb/DOM/Document.h index d9934f3421..74c184e032 100644 --- a/Userland/Libraries/LibWeb/DOM/Document.h +++ b/Userland/Libraries/LibWeb/DOM/Document.h @@ -208,6 +208,10 @@ public: void set_focused_element(Element*); + const Element* active_element() const { return m_active_element; } + + void set_active_element(Element*); + bool created_for_appropriate_template_contents() const { return m_created_for_appropriate_template_contents; } void set_created_for_appropriate_template_contents(bool value) { m_created_for_appropriate_template_contents = value; } @@ -323,6 +327,7 @@ private: bool m_editable { false }; WeakPtr m_focused_element; + WeakPtr m_active_element; bool m_created_for_appropriate_template_contents { false }; RefPtr m_associated_inert_template_document; diff --git a/Userland/Libraries/LibWeb/DOM/Element.cpp b/Userland/Libraries/LibWeb/DOM/Element.cpp index 26f5e0af68..b7ef8fba34 100644 --- a/Userland/Libraries/LibWeb/DOM/Element.cpp +++ b/Userland/Libraries/LibWeb/DOM/Element.cpp @@ -327,6 +327,11 @@ bool Element::is_focused() const return document().focused_element() == this; } +bool Element::is_active() const +{ + return document().active_element() == this; +} + NonnullRefPtr Element::get_elements_by_tag_name(FlyString const& tag_name) { // FIXME: Support "*" for tag_name diff --git a/Userland/Libraries/LibWeb/DOM/Element.h b/Userland/Libraries/LibWeb/DOM/Element.h index 2b320c7e51..c4b360f84e 100644 --- a/Userland/Libraries/LibWeb/DOM/Element.h +++ b/Userland/Libraries/LibWeb/DOM/Element.h @@ -86,6 +86,8 @@ public: bool is_focused() const; virtual bool is_focusable() const { return false; } + bool is_active() const; + NonnullRefPtr get_elements_by_tag_name(FlyString const&); NonnullRefPtr get_elements_by_class_name(FlyString const&); diff --git a/Userland/Libraries/LibWeb/Dump.cpp b/Userland/Libraries/LibWeb/Dump.cpp index 8d806c6bd3..0b4bb29d12 100644 --- a/Userland/Libraries/LibWeb/Dump.cpp +++ b/Userland/Libraries/LibWeb/Dump.cpp @@ -341,6 +341,9 @@ void dump_selector(StringBuilder& builder, const CSS::Selector& selector) case CSS::Selector::SimpleSelector::PseudoClass::Visited: pseudo_class_description = "Visited"; break; + case CSS::Selector::SimpleSelector::PseudoClass::Active: + pseudo_class_description = "Active"; + break; case CSS::Selector::SimpleSelector::PseudoClass::None: pseudo_class_description = "None"; break; diff --git a/Userland/Libraries/LibWeb/Page/EventHandler.cpp b/Userland/Libraries/LibWeb/Page/EventHandler.cpp index 14d14d596d..1fca7e74bd 100644 --- a/Userland/Libraries/LibWeb/Page/EventHandler.cpp +++ b/Userland/Libraries/LibWeb/Page/EventHandler.cpp @@ -237,6 +237,7 @@ bool EventHandler::handle_mousedown(const Gfx::IntPoint& position, unsigned butt auto anchor = href.substring_view(1, href.length() - 1); m_frame.scroll_to_anchor(anchor); } else { + document->set_active_element(link); if (m_frame.is_top_level()) { if (auto* page = m_frame.page()) page->client().page_did_click_link(url, link->target(), modifiers);