Explorar o código

LibWeb: Implement the :focus-within selector

This matches if it has focus, or any nodes inside it do.
Sam Atkins %!s(int64=3) %!d(string=hai) anos
pai
achega
d60b3be29a

+ 2 - 0
Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp

@@ -506,6 +506,8 @@ Result<Selector::SimpleSelector, Parser::ParsingResult> Parser::parse_simple_sel
                 simple_selector.pseudo_class.type = Selector::SimpleSelector::PseudoClass::Type::FirstOfType;
             } else if (pseudo_name.equals_ignoring_case("focus")) {
                 simple_selector.pseudo_class.type = Selector::SimpleSelector::PseudoClass::Type::Focus;
+            } else if (pseudo_name.equals_ignoring_case("focus-within")) {
+                simple_selector.pseudo_class.type = Selector::SimpleSelector::PseudoClass::Type::FocusWithin;
             } else if (pseudo_name.equals_ignoring_case("hover")) {
                 simple_selector.pseudo_class.type = Selector::SimpleSelector::PseudoClass::Type::Hover;
             } else if (pseudo_name.equals_ignoring_case("last-child")) {

+ 3 - 0
Userland/Libraries/LibWeb/CSS/Selector.h

@@ -60,6 +60,7 @@ public:
                 Visited,
                 Hover,
                 Focus,
+                FocusWithin,
                 FirstChild,
                 LastChild,
                 OnlyChild,
@@ -185,6 +186,8 @@ constexpr StringView pseudo_class_name(Selector::SimpleSelector::PseudoClass::Ty
         return "hover"sv;
     case Selector::SimpleSelector::PseudoClass::Type::Focus:
         return "focus"sv;
+    case Selector::SimpleSelector::PseudoClass::Type::FocusWithin:
+        return "focus-within"sv;
     case Selector::SimpleSelector::PseudoClass::Type::FirstChild:
         return "first-child"sv;
     case Selector::SimpleSelector::PseudoClass::Type::LastChild:

+ 4 - 0
Userland/Libraries/LibWeb/CSS/SelectorEngine.cpp

@@ -137,6 +137,10 @@ static inline bool matches_pseudo_class(CSS::Selector::SimpleSelector::PseudoCla
         return matches_hover_pseudo_class(element);
     case CSS::Selector::SimpleSelector::PseudoClass::Type::Focus:
         return element.is_focused();
+    case CSS::Selector::SimpleSelector::PseudoClass::Type::FocusWithin: {
+        auto* focused_element = element.document().focused_element();
+        return focused_element && element.is_inclusive_ancestor_of(*focused_element);
+    }
     case CSS::Selector::SimpleSelector::PseudoClass::Type::FirstChild:
         return !element.previous_element_sibling();
     case CSS::Selector::SimpleSelector::PseudoClass::Type::LastChild:

+ 3 - 0
Userland/Libraries/LibWeb/Dump.cpp

@@ -405,6 +405,9 @@ void dump_selector(StringBuilder& builder, CSS::Selector const& selector)
                 case CSS::Selector::SimpleSelector::PseudoClass::Type::Focus:
                     pseudo_class_description = "Focus";
                     break;
+                case CSS::Selector::SimpleSelector::PseudoClass::Type::FocusWithin:
+                    pseudo_class_description = "FocusWithin";
+                    break;
                 case CSS::Selector::SimpleSelector::PseudoClass::Type::Empty:
                     pseudo_class_description = "Empty";
                     break;