LibWeb/CSS: Update definition for cursor property

No functional changes. The main difference is renaming the cursor enum
to match the spec term `<cursor-predefined>`, which is a bit more
verbose but clearer in meaning.

Corresponds to 1a57a4025c
This commit is contained in:
Sam Atkins 2025-07-09 10:39:22 +01:00 committed by Jelle Raaijmakers
commit 0809eacd97
Notes: github-actions[bot] 2025-07-09 11:22:44 +00:00
6 changed files with 51 additions and 49 deletions

View file

@ -1061,16 +1061,16 @@ Vector<CursorData> ComputedProperties::cursor() const
continue; continue;
} }
if (auto keyword = keyword_to_cursor(item->to_keyword()); keyword.has_value()) if (auto keyword = keyword_to_cursor_predefined(item->to_keyword()); keyword.has_value())
cursors.append(keyword.release_value()); cursors.append(keyword.release_value());
} }
} else if (value.is_keyword()) { } else if (value.is_keyword()) {
if (auto keyword = keyword_to_cursor(value.to_keyword()); keyword.has_value()) if (auto keyword = keyword_to_cursor_predefined(value.to_keyword()); keyword.has_value())
cursors.append(keyword.release_value()); cursors.append(keyword.release_value());
} }
if (cursors.is_empty()) if (cursors.is_empty())
cursors.append(Cursor::Auto); cursors.append(CursorPredefined::Auto);
return cursors; return cursors;
} }

View file

@ -86,7 +86,7 @@ struct ScrollbarColorData {
Color track_color { Color::Transparent }; Color track_color { Color::Transparent };
}; };
using CursorData = Variant<NonnullRefPtr<CursorStyleValue const>, Cursor>; using CursorData = Variant<NonnullRefPtr<CursorStyleValue const>, CursorPredefined>;
using ListStyleType = Variant<CounterStyleNameKeyword, String>; using ListStyleType = Variant<CounterStyleNameKeyword, String>;
@ -105,7 +105,7 @@ public:
static CSS::Clip clip() { return CSS::Clip::make_auto(); } static CSS::Clip clip() { return CSS::Clip::make_auto(); }
static CSS::PreferredColorScheme color_scheme() { return CSS::PreferredColorScheme::Auto; } static CSS::PreferredColorScheme color_scheme() { return CSS::PreferredColorScheme::Auto; }
static CSS::ContentVisibility content_visibility() { return CSS::ContentVisibility::Visible; } static CSS::ContentVisibility content_visibility() { return CSS::ContentVisibility::Visible; }
static CursorData cursor() { return { CSS::Cursor::Auto }; } static CursorData cursor() { return { CSS::CursorPredefined::Auto }; }
static CSS::WhiteSpaceCollapse white_space_collapse() { return CSS::WhiteSpaceCollapse::Collapse; } static CSS::WhiteSpaceCollapse white_space_collapse() { return CSS::WhiteSpaceCollapse::Collapse; }
static CSS::WordBreak word_break() { return CSS::WordBreak::Normal; } static CSS::WordBreak word_break() { return CSS::WordBreak::Normal; }
static CSS::LengthOrCalculated word_spacing() { return CSS::Length::make_px(0); } static CSS::LengthOrCalculated word_spacing() { return CSS::Length::make_px(0); }

View file

@ -150,7 +150,7 @@
"anonymous", "anonymous",
"use-credentials" "use-credentials"
], ],
"cursor": [ "cursor-predefined": [
"auto", "auto",
"default", "default",
"none", "none",

View file

@ -1050,10 +1050,11 @@ RefPtr<CSSStyleValue const> Parser::parse_counter_set_value(TokenStream<Componen
return parse_counter_definitions_value(tokens, AllowReversed::No, 0); return parse_counter_definitions_value(tokens, AllowReversed::No, 0);
} }
// https://drafts.csswg.org/css-ui-3/#cursor // https://drafts.csswg.org/css-ui-4/#cursor
RefPtr<CSSStyleValue const> Parser::parse_cursor_value(TokenStream<ComponentValue>& tokens) RefPtr<CSSStyleValue const> Parser::parse_cursor_value(TokenStream<ComponentValue>& tokens)
{ {
// [ [<url> [<x> <y>]?,]* <built-in-cursor> ] // <cursor-image>#? <cursor-predefined>
// <cursor-image> = <url> <number>{2}?
// So, any number of custom cursor definitions, and then a mandatory cursor name keyword, all comma-separated. // So, any number of custom cursor definitions, and then a mandatory cursor name keyword, all comma-separated.
auto transaction = tokens.begin_transaction(); auto transaction = tokens.begin_transaction();
@ -1069,7 +1070,7 @@ RefPtr<CSSStyleValue const> Parser::parse_cursor_value(TokenStream<ComponentValu
// Cursor keyword // Cursor keyword
part_tokens.discard_whitespace(); part_tokens.discard_whitespace();
auto keyword_value = parse_keyword_value(part_tokens); auto keyword_value = parse_keyword_value(part_tokens);
if (!keyword_value || !keyword_to_cursor(keyword_value->to_keyword()).has_value()) if (!keyword_value || !keyword_to_cursor_predefined(keyword_value->to_keyword()).has_value())
return {}; return {};
part_tokens.discard_whitespace(); part_tokens.discard_whitespace();
@ -1079,7 +1080,7 @@ RefPtr<CSSStyleValue const> Parser::parse_cursor_value(TokenStream<ComponentValu
cursors.append(keyword_value.release_nonnull()); cursors.append(keyword_value.release_nonnull());
} else { } else {
// Custom cursor definition // Custom cursor definition
// <url> [<x> <y>]? // <cursor-image> = <url> <number>{2}?
// "Conforming user agents may, instead of <url>, support <image> which is a superset." // "Conforming user agents may, instead of <url>, support <image> which is a superset."
part_tokens.discard_whitespace(); part_tokens.discard_whitespace();
@ -1090,7 +1091,7 @@ RefPtr<CSSStyleValue const> Parser::parse_cursor_value(TokenStream<ComponentValu
part_tokens.discard_whitespace(); part_tokens.discard_whitespace();
if (part_tokens.has_next_token()) { if (part_tokens.has_next_token()) {
// x and y, which are both <number> // <number>{2}, which are the x and y coordinates of the hotspot
auto x = parse_number(part_tokens); auto x = parse_number(part_tokens);
part_tokens.discard_whitespace(); part_tokens.discard_whitespace();
auto y = parse_number(part_tokens); auto y = parse_number(part_tokens);

View file

@ -1386,7 +1386,8 @@
"initial": "auto", "initial": "auto",
"valid-types": [ "valid-types": [
"url", "url",
"cursor" "cursor-predefined",
"number [-∞,∞]"
] ]
}, },
"cx": { "cx": {

View file

@ -98,62 +98,62 @@ static Gfx::Cursor resolve_cursor(Layout::NodeWithStyle const& layout_node, Vect
{ {
for (auto const& cursor : cursor_data) { for (auto const& cursor : cursor_data) {
auto result = cursor.visit( auto result = cursor.visit(
[auto_cursor](CSS::Cursor css_cursor) -> Optional<Gfx::Cursor> { [auto_cursor](CSS::CursorPredefined css_cursor) -> Optional<Gfx::Cursor> {
switch (css_cursor) { switch (css_cursor) {
case CSS::Cursor::Crosshair: case CSS::CursorPredefined::Crosshair:
case CSS::Cursor::Cell: case CSS::CursorPredefined::Cell:
return Gfx::StandardCursor::Crosshair; return Gfx::StandardCursor::Crosshair;
case CSS::Cursor::Grab: case CSS::CursorPredefined::Grab:
case CSS::Cursor::Grabbing: case CSS::CursorPredefined::Grabbing:
return Gfx::StandardCursor::Drag; return Gfx::StandardCursor::Drag;
case CSS::Cursor::Pointer: case CSS::CursorPredefined::Pointer:
return Gfx::StandardCursor::Hand; return Gfx::StandardCursor::Hand;
case CSS::Cursor::Help: case CSS::CursorPredefined::Help:
return Gfx::StandardCursor::Help; return Gfx::StandardCursor::Help;
case CSS::Cursor::None: case CSS::CursorPredefined::None:
return Gfx::StandardCursor::Hidden; return Gfx::StandardCursor::Hidden;
case CSS::Cursor::NotAllowed: case CSS::CursorPredefined::NotAllowed:
return Gfx::StandardCursor::Disallowed; return Gfx::StandardCursor::Disallowed;
case CSS::Cursor::Text: case CSS::CursorPredefined::Text:
case CSS::Cursor::VerticalText: case CSS::CursorPredefined::VerticalText:
return Gfx::StandardCursor::IBeam; return Gfx::StandardCursor::IBeam;
case CSS::Cursor::Move: case CSS::CursorPredefined::Move:
case CSS::Cursor::AllScroll: case CSS::CursorPredefined::AllScroll:
return Gfx::StandardCursor::Move; return Gfx::StandardCursor::Move;
case CSS::Cursor::Progress: case CSS::CursorPredefined::Progress:
case CSS::Cursor::Wait: case CSS::CursorPredefined::Wait:
return Gfx::StandardCursor::Wait; return Gfx::StandardCursor::Wait;
case CSS::Cursor::ColResize: case CSS::CursorPredefined::ColResize:
return Gfx::StandardCursor::ResizeColumn; return Gfx::StandardCursor::ResizeColumn;
case CSS::Cursor::EResize: case CSS::CursorPredefined::EResize:
case CSS::Cursor::WResize: case CSS::CursorPredefined::WResize:
case CSS::Cursor::EwResize: case CSS::CursorPredefined::EwResize:
return Gfx::StandardCursor::ResizeHorizontal; return Gfx::StandardCursor::ResizeHorizontal;
case CSS::Cursor::RowResize: case CSS::CursorPredefined::RowResize:
return Gfx::StandardCursor::ResizeRow; return Gfx::StandardCursor::ResizeRow;
case CSS::Cursor::NResize: case CSS::CursorPredefined::NResize:
case CSS::Cursor::SResize: case CSS::CursorPredefined::SResize:
case CSS::Cursor::NsResize: case CSS::CursorPredefined::NsResize:
return Gfx::StandardCursor::ResizeVertical; return Gfx::StandardCursor::ResizeVertical;
case CSS::Cursor::NeResize: case CSS::CursorPredefined::NeResize:
case CSS::Cursor::SwResize: case CSS::CursorPredefined::SwResize:
case CSS::Cursor::NeswResize: case CSS::CursorPredefined::NeswResize:
return Gfx::StandardCursor::ResizeDiagonalBLTR; return Gfx::StandardCursor::ResizeDiagonalBLTR;
case CSS::Cursor::NwResize: case CSS::CursorPredefined::NwResize:
case CSS::Cursor::SeResize: case CSS::CursorPredefined::SeResize:
case CSS::Cursor::NwseResize: case CSS::CursorPredefined::NwseResize:
return Gfx::StandardCursor::ResizeDiagonalTLBR; return Gfx::StandardCursor::ResizeDiagonalTLBR;
case CSS::Cursor::ZoomIn: case CSS::CursorPredefined::ZoomIn:
case CSS::Cursor::ZoomOut: case CSS::CursorPredefined::ZoomOut:
return Gfx::StandardCursor::Zoom; return Gfx::StandardCursor::Zoom;
case CSS::Cursor::Auto: case CSS::CursorPredefined::Auto:
return auto_cursor; return auto_cursor;
case CSS::Cursor::ContextMenu: case CSS::CursorPredefined::ContextMenu:
case CSS::Cursor::Alias: case CSS::CursorPredefined::Alias:
case CSS::Cursor::Copy: case CSS::CursorPredefined::Copy:
case CSS::Cursor::NoDrop: case CSS::CursorPredefined::NoDrop:
// FIXME: No corresponding GFX Standard Cursor, fallthrough to None // FIXME: No corresponding GFX Standard Cursor, fallthrough to None
case CSS::Cursor::Default: case CSS::CursorPredefined::Default:
default: default:
return Gfx::StandardCursor::None; return Gfx::StandardCursor::None;
} }