diff --git a/Userland/Libraries/LibWeb/CSS/SelectorEngine.cpp b/Userland/Libraries/LibWeb/CSS/SelectorEngine.cpp index 0983b429260..6df4294bf01 100644 --- a/Userland/Libraries/LibWeb/CSS/SelectorEngine.cpp +++ b/Userland/Libraries/LibWeb/CSS/SelectorEngine.cpp @@ -140,7 +140,7 @@ static inline bool matches_link_pseudo_class(DOM::Element const& element) return element.has_attribute(HTML::AttributeNames::href); } -static inline bool matches_hover_pseudo_class(DOM::Element const& element) +bool matches_hover_pseudo_class(DOM::Element const& element) { auto* hovered_node = element.document().hovered_node(); if (!hovered_node) diff --git a/Userland/Libraries/LibWeb/CSS/SelectorEngine.h b/Userland/Libraries/LibWeb/CSS/SelectorEngine.h index 28f1e07d74d..96b821ec053 100644 --- a/Userland/Libraries/LibWeb/CSS/SelectorEngine.h +++ b/Userland/Libraries/LibWeb/CSS/SelectorEngine.h @@ -21,4 +21,6 @@ bool matches(CSS::Selector const&, Optional style_she [[nodiscard]] bool fast_matches(CSS::Selector const&, Optional style_sheet_for_rule, DOM::Element const&, JS::GCPtr shadow_host); [[nodiscard]] bool can_use_fast_matches(CSS::Selector const&); +[[nodiscard]] bool matches_hover_pseudo_class(DOM::Element const&); + } diff --git a/Userland/Libraries/LibWeb/CSS/StyleComputer.cpp b/Userland/Libraries/LibWeb/CSS/StyleComputer.cpp index 0711e3d971c..6072a570b97 100644 --- a/Userland/Libraries/LibWeb/CSS/StyleComputer.cpp +++ b/Userland/Libraries/LibWeb/CSS/StyleComputer.cpp @@ -356,16 +356,22 @@ Vector StyleComputer::collect_matching_rules(DOM::Element const& e auto const& rule_cache = rule_cache_for_cascade_origin(cascade_origin); + bool is_hovered = SelectorEngine::matches_hover_pseudo_class(element); + Vector rules_to_run; auto add_rules_to_run = [&](Vector const& rules) { rules_to_run.grow_capacity(rules_to_run.size() + rules.size()); if (pseudo_element.has_value()) { for (auto const& rule : rules) { + if (rule.must_be_hovered && !is_hovered) + continue; if (rule.contains_pseudo_element && filter_namespace_rule(element, rule) && filter_layer(qualified_layer_name, rule)) rules_to_run.unchecked_append(rule); } } else { for (auto const& rule : rules) { + if (rule.must_be_hovered && !is_hovered) + continue; if (!rule.contains_pseudo_element && filter_namespace_rule(element, rule) && filter_layer(qualified_layer_name, rule)) rules_to_run.unchecked_append(rule); } @@ -2692,6 +2698,7 @@ NonnullOwnPtr StyleComputer::make_rule_cache_for_casca size_t num_pseudo_element_rules = 0; size_t num_root_rules = 0; size_t num_attribute_rules = 0; + size_t num_hover_rules = 0; Vector matching_rules; size_t style_sheet_index = 0; @@ -2711,6 +2718,7 @@ NonnullOwnPtr StyleComputer::make_rule_cache_for_casca cascade_origin, false, SelectorEngine::can_use_fast_matches(selector), + false, }; bool contains_root_pseudo_class = false; @@ -2729,6 +2737,27 @@ NonnullOwnPtr StyleComputer::make_rule_cache_for_casca ++num_root_rules; } } + + if (!matching_rule.must_be_hovered) { + if (simple_selector.type == CSS::Selector::SimpleSelector::Type::PseudoClass && simple_selector.pseudo_class().type == CSS::PseudoClass::Hover) { + matching_rule.must_be_hovered = true; + ++num_hover_rules; + } + if (simple_selector.type == CSS::Selector::SimpleSelector::Type::PseudoClass + && (simple_selector.pseudo_class().type == CSS::PseudoClass::Is + || simple_selector.pseudo_class().type == CSS::PseudoClass::Where)) { + auto const& argument_selectors = simple_selector.pseudo_class().argument_selector_list; + + if (argument_selectors.size() == 1) { + auto const& simple_argument_selector = argument_selectors.first()->compound_selectors().last().simple_selectors.last(); + if (simple_argument_selector.type == CSS::Selector::SimpleSelector::Type::PseudoClass + && simple_argument_selector.pseudo_class().type == CSS::PseudoClass::Hover) { + matching_rule.must_be_hovered = true; + ++num_hover_rules; + } + } + } + } } // NOTE: We traverse the simple selectors in reverse order to make sure that class/ID buckets are preferred over tag buckets diff --git a/Userland/Libraries/LibWeb/CSS/StyleComputer.h b/Userland/Libraries/LibWeb/CSS/StyleComputer.h index fbe90dbeac9..30e0a960220 100644 --- a/Userland/Libraries/LibWeb/CSS/StyleComputer.h +++ b/Userland/Libraries/LibWeb/CSS/StyleComputer.h @@ -92,6 +92,7 @@ struct MatchingRule { CascadeOrigin cascade_origin; bool contains_pseudo_element { false }; bool can_use_fast_matches { false }; + bool must_be_hovered { false }; bool skip { false }; };