diff --git a/Tests/LibWeb/Text/expected/css/getComputedStyle-print-all.txt b/Tests/LibWeb/Text/expected/css/getComputedStyle-print-all.txt index 58e01135bf3..4c5826aa386 100644 --- a/Tests/LibWeb/Text/expected/css/getComputedStyle-print-all.txt +++ b/Tests/LibWeb/Text/expected/css/getComputedStyle-print-all.txt @@ -146,6 +146,7 @@ right: auto row-gap: auto rx: auto ry: auto +scrollbar-gutter: auto scrollbar-width: auto stop-color: rgb(0, 0, 0) stop-opacity: 1 diff --git a/Userland/Libraries/LibWeb/CSS/Enums.json b/Userland/Libraries/LibWeb/CSS/Enums.json index 64579bbefe6..53813ed7b09 100644 --- a/Userland/Libraries/LibWeb/CSS/Enums.json +++ b/Userland/Libraries/LibWeb/CSS/Enums.json @@ -362,6 +362,11 @@ "middle", "end" ], + "scrollbar-gutter": [ + "auto", + "stable", + "both-edges" + ], "scrollbar-width": [ "auto", "thin", diff --git a/Userland/Libraries/LibWeb/CSS/Identifiers.json b/Userland/Libraries/LibWeb/CSS/Identifiers.json index 258575478e0..a77ee7b0526 100644 --- a/Userland/Libraries/LibWeb/CSS/Identifiers.json +++ b/Userland/Libraries/LibWeb/CSS/Identifiers.json @@ -85,6 +85,7 @@ "bolder", "border-box", "both", + "both-edges", "bottom", "break-word", "browser", @@ -328,6 +329,7 @@ "space-evenly", "square", "srgb", + "stable", "standalone", "standard", "start", diff --git a/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp b/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp index 947851aecb5..06cdd6ada7c 100644 --- a/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp +++ b/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp @@ -69,6 +69,7 @@ #include #include #include +#include #include #include #include @@ -5879,6 +5880,70 @@ RefPtr Parser::parse_grid_auto_flow_value(TokenStream Parser::parse_scrollbar_gutter_value(TokenStream& tokens) +{ + // auto | stable && both-edges? + if (!tokens.has_next_token()) + return nullptr; + + auto transaction = tokens.begin_transaction(); + + auto parse_stable = [&]() -> Optional { + auto transaction = tokens.begin_transaction(); + auto token = tokens.next_token(); + if (!token.is(Token::Type::Ident)) + return {}; + auto const& ident = token.token().ident(); + if (ident.equals_ignoring_ascii_case("auto"sv)) { + transaction.commit(); + return false; + } else if (ident.equals_ignoring_ascii_case("stable"sv)) { + transaction.commit(); + return true; + } + return {}; + }; + + auto parse_both_edges = [&]() -> Optional { + auto transaction = tokens.begin_transaction(); + auto token = tokens.next_token(); + if (!token.is(Token::Type::Ident)) + return {}; + auto const& ident = token.token().ident(); + if (ident.equals_ignoring_ascii_case("both-edges"sv)) { + transaction.commit(); + return true; + } + return {}; + }; + + Optional stable; + Optional both_edges; + if (stable = parse_stable(); stable.has_value()) { + if (stable.value()) + both_edges = parse_both_edges(); + } else if (both_edges = parse_both_edges(); both_edges.has_value()) { + stable = parse_stable(); + if (!stable.has_value() || !stable.value()) + return nullptr; + } + + if (tokens.has_next_token()) + return nullptr; + + transaction.commit(); + + ScrollbarGutter gutter_value; + if (both_edges.has_value()) + gutter_value = ScrollbarGutter::BothEdges; + else if (stable.has_value() && stable.value()) + gutter_value = ScrollbarGutter::Stable; + else + gutter_value = ScrollbarGutter::Auto; + return ScrollbarGutterStyleValue::create(gutter_value); +} + RefPtr Parser::parse_grid_auto_track_sizes(TokenStream& tokens) { // https://www.w3.org/TR/css-grid-2/#auto-tracks @@ -6473,6 +6538,10 @@ Parser::ParseErrorOr> Parser::parse_css_value(Property if (auto parsed_value = parse_quotes_value(tokens); parsed_value && !tokens.has_next_token()) return parsed_value.release_nonnull(); return ParseError::SyntaxError; + case PropertyID::ScrollbarGutter: + if (auto parsed_value = parse_scrollbar_gutter_value(tokens); parsed_value && !tokens.has_next_token()) + return parsed_value.release_nonnull(); + return ParseError::SyntaxError; case PropertyID::TextDecoration: if (auto parsed_value = parse_text_decoration_value(tokens); parsed_value && !tokens.has_next_token()) return parsed_value.release_nonnull(); diff --git a/Userland/Libraries/LibWeb/CSS/Parser/Parser.h b/Userland/Libraries/LibWeb/CSS/Parser/Parser.h index fd3f1aaa494..1db62d2510e 100644 --- a/Userland/Libraries/LibWeb/CSS/Parser/Parser.h +++ b/Userland/Libraries/LibWeb/CSS/Parser/Parser.h @@ -320,6 +320,7 @@ private: RefPtr parse_place_items_value(TokenStream&); RefPtr parse_place_self_value(TokenStream&); RefPtr parse_quotes_value(TokenStream&); + RefPtr parse_scrollbar_gutter_value(TokenStream&); enum class AllowInsetKeyword { No, Yes, diff --git a/Userland/Libraries/LibWeb/CSS/Properties.json b/Userland/Libraries/LibWeb/CSS/Properties.json index a21cf642c37..22ace52dce6 100644 --- a/Userland/Libraries/LibWeb/CSS/Properties.json +++ b/Userland/Libraries/LibWeb/CSS/Properties.json @@ -2139,6 +2139,13 @@ "unitless-length" ] }, + "scrollbar-gutter": { + "affects-layout": false, + "animation-type": "discrete", + "__comment": "This property should affect layout per-spec, but ladybird always uses overlay scrollbars so it doesn't in practice.", + "inherited": false, + "initial": "auto" + }, "scrollbar-width": { "affects-layout": false, "animation-type": "by-computed-value", diff --git a/Userland/Libraries/LibWeb/CSS/StyleProperties.cpp b/Userland/Libraries/LibWeb/CSS/StyleProperties.cpp index d4f61e74fb3..aa2b4a612e9 100644 --- a/Userland/Libraries/LibWeb/CSS/StyleProperties.cpp +++ b/Userland/Libraries/LibWeb/CSS/StyleProperties.cpp @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include diff --git a/Userland/Libraries/LibWeb/CSS/StyleValue.cpp b/Userland/Libraries/LibWeb/CSS/StyleValue.cpp index 70c293f99c3..c3cf075fc78 100644 --- a/Userland/Libraries/LibWeb/CSS/StyleValue.cpp +++ b/Userland/Libraries/LibWeb/CSS/StyleValue.cpp @@ -47,6 +47,7 @@ #include #include #include +#include #include #include #include diff --git a/Userland/Libraries/LibWeb/CSS/StyleValue.h b/Userland/Libraries/LibWeb/CSS/StyleValue.h index 04f84900781..89e32a4f605 100644 --- a/Userland/Libraries/LibWeb/CSS/StyleValue.h +++ b/Userland/Libraries/LibWeb/CSS/StyleValue.h @@ -119,6 +119,7 @@ using StyleValueVector = Vector>; __ENUMERATE_STYLE_VALUE_TYPE(Rect, rect) \ __ENUMERATE_STYLE_VALUE_TYPE(Resolution, resolution) \ __ENUMERATE_STYLE_VALUE_TYPE(Revert, revert) \ + __ENUMERATE_STYLE_VALUE_TYPE(ScrollbarGutter, scrollbar_gutter) \ __ENUMERATE_STYLE_VALUE_TYPE(Shadow, shadow) \ __ENUMERATE_STYLE_VALUE_TYPE(Shorthand, shorthand) \ __ENUMERATE_STYLE_VALUE_TYPE(String, string) \ diff --git a/Userland/Libraries/LibWeb/CSS/StyleValues/ScrollbarGutterStyleValue.h b/Userland/Libraries/LibWeb/CSS/StyleValues/ScrollbarGutterStyleValue.h new file mode 100644 index 00000000000..edc31926372 --- /dev/null +++ b/Userland/Libraries/LibWeb/CSS/StyleValues/ScrollbarGutterStyleValue.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2024, the Ladybird developers. + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include + +namespace Web::CSS { + +class ScrollbarGutterStyleValue final : public StyleValueWithDefaultOperators { +public: + static ValueComparingNonnullRefPtr create(ScrollbarGutter value) + { + return adopt_ref(*new (nothrow) ScrollbarGutterStyleValue(value)); + } + virtual ~ScrollbarGutterStyleValue() override = default; + + ScrollbarGutter value() const { return m_value; } + + virtual String to_string() const override + { + switch (m_value) { + case ScrollbarGutter::Auto: + return "auto"_string; + case ScrollbarGutter::Stable: + return "stable"_string; + case ScrollbarGutter::BothEdges: + return "stable both-edges"_string; + default: + VERIFY_NOT_REACHED(); + } + } + + bool properties_equal(ScrollbarGutterStyleValue const& other) const { return m_value == other.m_value; } + +private: + ScrollbarGutterStyleValue(ScrollbarGutter value) + : StyleValueWithDefaultOperators(Type::ScrollbarGutter) + , m_value(value) + { + } + + ScrollbarGutter m_value; +}; + +} diff --git a/Userland/Libraries/LibWeb/Forward.h b/Userland/Libraries/LibWeb/Forward.h index 5c8bfd42009..e77caee2ee3 100644 --- a/Userland/Libraries/LibWeb/Forward.h +++ b/Userland/Libraries/LibWeb/Forward.h @@ -181,6 +181,7 @@ class ResolutionStyleValue; class RevertStyleValue; class Screen; class ScreenOrientation; +class ScrollbarGutterStyleValue; class Selector; class ShadowStyleValue; class ShorthandStyleValue;