diff options
author | Paul Irwin <paulirwin@gmail.com> | 2021-06-18 16:42:34 -0600 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2021-06-25 01:02:29 +0200 |
commit | 5eb65286b63d5d2698af8b289c2b7372f49e53c6 (patch) | |
tree | dd9bf0f87715985f2ea7e807c548415695d060e4 | |
parent | 457edaa4d28c6d26a8f6091642129c5980ec6824 (diff) | |
download | serenity-5eb65286b63d5d2698af8b289c2b7372f49e53c6.zip |
LibWeb: Support :active pseudo-class for hyperlinks, :focus possibly
Adds support for the :active pseudo-class for hyperlinks (<a> tags
only).
Also, since it was very similar to :focus and an element having a
focused state was already implemented, I went ahead and implemented
that pseudo-class too, although I cannot come up with a working
example to validate it.
-rw-r--r-- | Userland/Libraries/LibWeb/CSS/Parser/DeprecatedCSSParser.cpp | 2 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp | 2 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/CSS/Selector.h | 1 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/CSS/SelectorEngine.cpp | 9 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/DOM/Document.cpp | 11 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/DOM/Document.h | 5 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/DOM/Element.cpp | 5 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/DOM/Element.h | 2 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/Dump.cpp | 3 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/Page/EventHandler.cpp | 1 |
10 files changed, 39 insertions, 2 deletions
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<CSS::Selector::ComplexSelector> Parser::parse_selectors(Vector<String> 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<Element> m_focused_element; + WeakPtr<Element> m_active_element; bool m_created_for_appropriate_template_contents { false }; RefPtr<Document> 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<HTMLCollection> 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<HTMLCollection> get_elements_by_tag_name(FlyString const&); NonnullRefPtr<HTMLCollection> 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); |