mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-07-28 11:49:44 +00:00
LibWeb/CSS: Implement the color-scheme CSS property
This commit is contained in:
parent
89296b88a0
commit
ce5cd012b9
Notes:
github-actions[bot]
2025-01-08 11:19:41 +00:00
Author: https://github.com/Gingeh
Commit: ce5cd012b9
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/3146
Reviewed-by: https://github.com/AtkinsSJ ✅
36 changed files with 618 additions and 370 deletions
|
@ -4,7 +4,6 @@
|
||||||
|
|
||||||
@media (prefers-color-scheme: dark) {
|
@media (prefers-color-scheme: dark) {
|
||||||
:root {
|
:root {
|
||||||
--background: rgb(23, 23, 23);
|
|
||||||
--separator: dimgray;
|
--separator: dimgray;
|
||||||
--separator-accent: rgb(57, 57, 57);
|
--separator-accent: rgb(57, 57, 57);
|
||||||
--tab-controls: rgb(57, 57, 57);
|
--tab-controls: rgb(57, 57, 57);
|
||||||
|
@ -30,7 +29,6 @@
|
||||||
|
|
||||||
@media (prefers-color-scheme: light) {
|
@media (prefers-color-scheme: light) {
|
||||||
:root {
|
:root {
|
||||||
--background: white;
|
|
||||||
--separator: lightgray;
|
--separator: lightgray;
|
||||||
--separator-accent: white;
|
--separator-accent: white;
|
||||||
--tab-controls: rgb(229, 229, 229);
|
--tab-controls: rgb(229, 229, 229);
|
||||||
|
@ -54,7 +52,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
html {
|
html {
|
||||||
background-color: var(--background);
|
color-scheme: light dark;
|
||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
|
@ -186,7 +184,7 @@ body {
|
||||||
left: 0;
|
left: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
background-color: var(--tab-controls);
|
background-color: var(--tab-controls);
|
||||||
border-top: 2px solid var(--background);
|
border-top: 2px solid Canvas;
|
||||||
display: flex;
|
display: flex;
|
||||||
padding: 0.5em;
|
padding: 0.5em;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,11 +4,8 @@
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<title>New Tab</title>
|
<title>New Tab</title>
|
||||||
<style>
|
<style>
|
||||||
/* FIXME: We should be able to remove the HTML style when "color-scheme" is supported */
|
html {
|
||||||
@media (prefers-color-scheme: dark) {
|
color-scheme: light dark;
|
||||||
html {
|
|
||||||
background-color: rgb(20, 20, 20);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
|
|
|
@ -4,15 +4,8 @@
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<title>Index of %path%</title>
|
<title>Index of %path%</title>
|
||||||
<style>
|
<style>
|
||||||
/* FIXME: We should be able to remove the HTML style when "color-scheme" is supported */
|
html {
|
||||||
@media (prefers-color-scheme: dark) {
|
color-scheme: light dark;
|
||||||
html {
|
|
||||||
background-color: rgb(20, 20, 20);
|
|
||||||
color: rgb(235, 235, 235);
|
|
||||||
}
|
|
||||||
a {
|
|
||||||
color: cornflowerblue;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
header {
|
header {
|
||||||
|
|
|
@ -4,12 +4,8 @@
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<title>Error!</title>
|
<title>Error!</title>
|
||||||
<style>
|
<style>
|
||||||
/* FIXME: We should be able to remove the HTML style when "color-scheme" is supported */
|
html {
|
||||||
@media (prefers-color-scheme: dark) {
|
color-scheme: light dark;
|
||||||
html {
|
|
||||||
background-color: rgb(20, 20, 20);
|
|
||||||
color: rgb(235, 235, 235);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
h1 {
|
h1 {
|
||||||
|
|
|
@ -4,12 +4,8 @@
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<title>About %browser_name%</title>
|
<title>About %browser_name%</title>
|
||||||
<style>
|
<style>
|
||||||
/* FIXME: We should be able to remove the HTML style when "color-scheme" is supported */
|
html {
|
||||||
@media (prefers-color-scheme: dark) {
|
color-scheme: light dark;
|
||||||
html {
|
|
||||||
background-color: rgb(20, 20, 20);
|
|
||||||
color: rgb(235, 235, 235);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
img {
|
img {
|
||||||
float: left;
|
float: left;
|
||||||
|
|
|
@ -126,6 +126,7 @@ set(SOURCES
|
||||||
CSS/StyleValues/BasicShapeStyleValue.cpp
|
CSS/StyleValues/BasicShapeStyleValue.cpp
|
||||||
CSS/StyleValues/BorderRadiusStyleValue.cpp
|
CSS/StyleValues/BorderRadiusStyleValue.cpp
|
||||||
CSS/StyleValues/CalculatedStyleValue.cpp
|
CSS/StyleValues/CalculatedStyleValue.cpp
|
||||||
|
CSS/StyleValues/ColorSchemeStyleValue.cpp
|
||||||
CSS/StyleValues/ConicGradientStyleValue.cpp
|
CSS/StyleValues/ConicGradientStyleValue.cpp
|
||||||
CSS/StyleValues/ContentStyleValue.cpp
|
CSS/StyleValues/ContentStyleValue.cpp
|
||||||
CSS/StyleValues/CounterDefinitionsStyleValue.cpp
|
CSS/StyleValues/CounterDefinitionsStyleValue.cpp
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
#include <LibWeb/CSS/StyleValues/CSSColorValue.h>
|
#include <LibWeb/CSS/StyleValues/CSSColorValue.h>
|
||||||
#include <LibWeb/CSS/StyleValues/CSSKeywordValue.h>
|
#include <LibWeb/CSS/StyleValues/CSSKeywordValue.h>
|
||||||
#include <LibWeb/CSS/StyleValues/CalculatedStyleValue.h>
|
#include <LibWeb/CSS/StyleValues/CalculatedStyleValue.h>
|
||||||
|
#include <LibWeb/CSS/StyleValues/ColorSchemeStyleValue.h>
|
||||||
#include <LibWeb/CSS/StyleValues/ConicGradientStyleValue.h>
|
#include <LibWeb/CSS/StyleValues/ConicGradientStyleValue.h>
|
||||||
#include <LibWeb/CSS/StyleValues/ContentStyleValue.h>
|
#include <LibWeb/CSS/StyleValues/ContentStyleValue.h>
|
||||||
#include <LibWeb/CSS/StyleValues/CounterDefinitionsStyleValue.h>
|
#include <LibWeb/CSS/StyleValues/CounterDefinitionsStyleValue.h>
|
||||||
|
@ -116,6 +117,12 @@ CSSColorValue const& CSSStyleValue::as_color() const
|
||||||
return static_cast<CSSColorValue const&>(*this);
|
return static_cast<CSSColorValue const&>(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ColorSchemeStyleValue const& CSSStyleValue::as_color_scheme() const
|
||||||
|
{
|
||||||
|
VERIFY(is_color_scheme());
|
||||||
|
return static_cast<ColorSchemeStyleValue const&>(*this);
|
||||||
|
}
|
||||||
|
|
||||||
ConicGradientStyleValue const& CSSStyleValue::as_conic_gradient() const
|
ConicGradientStyleValue const& CSSStyleValue::as_conic_gradient() const
|
||||||
{
|
{
|
||||||
VERIFY(is_conic_gradient());
|
VERIFY(is_conic_gradient());
|
||||||
|
|
|
@ -96,6 +96,7 @@ public:
|
||||||
BorderRadius,
|
BorderRadius,
|
||||||
Calculated,
|
Calculated,
|
||||||
Color,
|
Color,
|
||||||
|
ColorScheme,
|
||||||
ConicGradient,
|
ConicGradient,
|
||||||
Content,
|
Content,
|
||||||
Counter,
|
Counter,
|
||||||
|
@ -178,6 +179,10 @@ public:
|
||||||
CSSColorValue const& as_color() const;
|
CSSColorValue const& as_color() const;
|
||||||
CSSColorValue& as_color() { return const_cast<CSSColorValue&>(const_cast<CSSStyleValue const&>(*this).as_color()); }
|
CSSColorValue& as_color() { return const_cast<CSSColorValue&>(const_cast<CSSStyleValue const&>(*this).as_color()); }
|
||||||
|
|
||||||
|
bool is_color_scheme() const { return type() == Type::ColorScheme; }
|
||||||
|
ColorSchemeStyleValue const& as_color_scheme() const;
|
||||||
|
ColorSchemeStyleValue& as_color_scheme() { return const_cast<ColorSchemeStyleValue&>(const_cast<CSSStyleValue const&>(*this).as_color_scheme()); }
|
||||||
|
|
||||||
bool is_conic_gradient() const { return type() == Type::ConicGradient; }
|
bool is_conic_gradient() const { return type() == Type::ConicGradient; }
|
||||||
ConicGradientStyleValue const& as_conic_gradient() const;
|
ConicGradientStyleValue const& as_conic_gradient() const;
|
||||||
ConicGradientStyleValue& as_conic_gradient() { return const_cast<ConicGradientStyleValue&>(const_cast<CSSStyleValue const&>(*this).as_conic_gradient()); }
|
ConicGradientStyleValue& as_conic_gradient() { return const_cast<ConicGradientStyleValue&>(const_cast<CSSStyleValue const&>(*this).as_conic_gradient()); }
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
#include <LibWeb/CSS/ComputedProperties.h>
|
#include <LibWeb/CSS/ComputedProperties.h>
|
||||||
#include <LibWeb/CSS/StyleValues/AngleStyleValue.h>
|
#include <LibWeb/CSS/StyleValues/AngleStyleValue.h>
|
||||||
#include <LibWeb/CSS/StyleValues/CSSKeywordValue.h>
|
#include <LibWeb/CSS/StyleValues/CSSKeywordValue.h>
|
||||||
|
#include <LibWeb/CSS/StyleValues/ColorSchemeStyleValue.h>
|
||||||
#include <LibWeb/CSS/StyleValues/ContentStyleValue.h>
|
#include <LibWeb/CSS/StyleValues/ContentStyleValue.h>
|
||||||
#include <LibWeb/CSS/StyleValues/CounterDefinitionsStyleValue.h>
|
#include <LibWeb/CSS/StyleValues/CounterDefinitionsStyleValue.h>
|
||||||
#include <LibWeb/CSS/StyleValues/CounterStyleValue.h>
|
#include <LibWeb/CSS/StyleValues/CounterStyleValue.h>
|
||||||
|
@ -228,6 +229,34 @@ Color ComputedProperties::color_or_fallback(CSS::PropertyID id, Layout::NodeWith
|
||||||
return value.to_color(node);
|
return value.to_color(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://drafts.csswg.org/css-color-adjust-1/#determine-the-used-color-scheme
|
||||||
|
CSS::PreferredColorScheme ComputedProperties::color_scheme(CSS::PreferredColorScheme preferred_scheme) const
|
||||||
|
{
|
||||||
|
// To determine the used color scheme of an element:
|
||||||
|
auto const& scheme_value = property(CSS::PropertyID::ColorScheme).as_color_scheme();
|
||||||
|
|
||||||
|
// 1. If the user’s preferred color scheme, as indicated by the prefers-color-scheme media feature,
|
||||||
|
// is present among the listed color schemes, and is supported by the user agent,
|
||||||
|
// that’s the element’s used color scheme.
|
||||||
|
if (preferred_scheme != CSS::PreferredColorScheme::Auto && scheme_value.schemes().contains_slow(preferred_color_scheme_to_string(preferred_scheme)))
|
||||||
|
return preferred_scheme;
|
||||||
|
|
||||||
|
// 2. Otherwise, if the user has indicated an overriding preference for their chosen color scheme,
|
||||||
|
// and the only keyword is not present in color-scheme for the element,
|
||||||
|
// the user agent must override the color scheme with the user’s preferred color scheme.
|
||||||
|
// See § 2.3 Overriding the Color Scheme.
|
||||||
|
// FIXME: We don't currently support setting an "overriding preference" for color schemes.
|
||||||
|
|
||||||
|
// 3. Otherwise, if the user agent supports at least one of the listed color schemes,
|
||||||
|
// the used color scheme is the first supported color scheme in the list.
|
||||||
|
auto first_supported = scheme_value.schemes().first_matching([](auto scheme) { return preferred_color_scheme_from_string(scheme) != CSS::PreferredColorScheme::Auto; });
|
||||||
|
if (first_supported.has_value())
|
||||||
|
return preferred_color_scheme_from_string(first_supported.value());
|
||||||
|
|
||||||
|
// 4. Otherwise, the used color scheme is the browser default. (Same as normal.)
|
||||||
|
return CSS::PreferredColorScheme::Light;
|
||||||
|
}
|
||||||
|
|
||||||
NonnullRefPtr<Gfx::Font const> ComputedProperties::font_fallback(bool monospace, bool bold, float point_size)
|
NonnullRefPtr<Gfx::Font const> ComputedProperties::font_fallback(bool monospace, bool bold, float point_size)
|
||||||
{
|
{
|
||||||
if (monospace && bold)
|
if (monospace && bold)
|
||||||
|
|
|
@ -74,6 +74,7 @@ public:
|
||||||
Optional<LengthPercentage> length_percentage(CSS::PropertyID) const;
|
Optional<LengthPercentage> length_percentage(CSS::PropertyID) const;
|
||||||
LengthBox length_box(CSS::PropertyID left_id, CSS::PropertyID top_id, CSS::PropertyID right_id, CSS::PropertyID bottom_id, const CSS::Length& default_value) const;
|
LengthBox length_box(CSS::PropertyID left_id, CSS::PropertyID top_id, CSS::PropertyID right_id, CSS::PropertyID bottom_id, const CSS::Length& default_value) const;
|
||||||
Color color_or_fallback(CSS::PropertyID, Layout::NodeWithStyle const&, Color fallback) const;
|
Color color_or_fallback(CSS::PropertyID, Layout::NodeWithStyle const&, Color fallback) const;
|
||||||
|
CSS::PreferredColorScheme color_scheme(CSS::PreferredColorScheme) const;
|
||||||
Optional<CSS::TextAnchor> text_anchor() const;
|
Optional<CSS::TextAnchor> text_anchor() const;
|
||||||
Optional<CSS::TextAlign> text_align() const;
|
Optional<CSS::TextAlign> text_align() const;
|
||||||
Optional<CSS::TextJustify> text_justify() const;
|
Optional<CSS::TextJustify> text_justify() const;
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
#include <LibWeb/CSS/GridTrackSize.h>
|
#include <LibWeb/CSS/GridTrackSize.h>
|
||||||
#include <LibWeb/CSS/LengthBox.h>
|
#include <LibWeb/CSS/LengthBox.h>
|
||||||
#include <LibWeb/CSS/PercentageOr.h>
|
#include <LibWeb/CSS/PercentageOr.h>
|
||||||
|
#include <LibWeb/CSS/PreferredColorScheme.h>
|
||||||
#include <LibWeb/CSS/Ratio.h>
|
#include <LibWeb/CSS/Ratio.h>
|
||||||
#include <LibWeb/CSS/Size.h>
|
#include <LibWeb/CSS/Size.h>
|
||||||
#include <LibWeb/CSS/StyleValues/AbstractImageStyleValue.h>
|
#include <LibWeb/CSS/StyleValues/AbstractImageStyleValue.h>
|
||||||
|
@ -76,6 +77,7 @@ public:
|
||||||
static CSS::CaptionSide caption_side() { return CSS::CaptionSide::Top; }
|
static CSS::CaptionSide caption_side() { return CSS::CaptionSide::Top; }
|
||||||
static CSS::Clear clear() { return CSS::Clear::None; }
|
static CSS::Clear clear() { return CSS::Clear::None; }
|
||||||
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::ContentVisibility content_visibility() { return CSS::ContentVisibility::Visible; }
|
static CSS::ContentVisibility content_visibility() { return CSS::ContentVisibility::Visible; }
|
||||||
static CSS::Cursor cursor() { return CSS::Cursor::Auto; }
|
static CSS::Cursor cursor() { return CSS::Cursor::Auto; }
|
||||||
static CSS::WhiteSpace white_space() { return CSS::WhiteSpace::Normal; }
|
static CSS::WhiteSpace white_space() { return CSS::WhiteSpace::Normal; }
|
||||||
|
@ -351,6 +353,7 @@ public:
|
||||||
CSS::CaptionSide caption_side() const { return m_inherited.caption_side; }
|
CSS::CaptionSide caption_side() const { return m_inherited.caption_side; }
|
||||||
CSS::Clear clear() const { return m_noninherited.clear; }
|
CSS::Clear clear() const { return m_noninherited.clear; }
|
||||||
CSS::Clip clip() const { return m_noninherited.clip; }
|
CSS::Clip clip() const { return m_noninherited.clip; }
|
||||||
|
CSS::PreferredColorScheme color_scheme() const { return m_inherited.color_scheme; }
|
||||||
CSS::ContentVisibility content_visibility() const { return m_inherited.content_visibility; }
|
CSS::ContentVisibility content_visibility() const { return m_inherited.content_visibility; }
|
||||||
CSS::Cursor cursor() const { return m_inherited.cursor; }
|
CSS::Cursor cursor() const { return m_inherited.cursor; }
|
||||||
CSS::ContentData content() const { return m_noninherited.content; }
|
CSS::ContentData content() const { return m_noninherited.content; }
|
||||||
|
@ -543,6 +546,7 @@ protected:
|
||||||
CSS::Length border_spacing_vertical { InitialValues::border_spacing() };
|
CSS::Length border_spacing_vertical { InitialValues::border_spacing() };
|
||||||
CSS::CaptionSide caption_side { InitialValues::caption_side() };
|
CSS::CaptionSide caption_side { InitialValues::caption_side() };
|
||||||
Color color { InitialValues::color() };
|
Color color { InitialValues::color() };
|
||||||
|
CSS::PreferredColorScheme color_scheme { InitialValues::color_scheme() };
|
||||||
Optional<Color> accent_color {};
|
Optional<Color> accent_color {};
|
||||||
Color webkit_text_fill_color { InitialValues::color() };
|
Color webkit_text_fill_color { InitialValues::color() };
|
||||||
CSS::ContentVisibility content_visibility { InitialValues::content_visibility() };
|
CSS::ContentVisibility content_visibility { InitialValues::content_visibility() };
|
||||||
|
@ -724,6 +728,7 @@ public:
|
||||||
void set_border_spacing_vertical(CSS::Length border_spacing_vertical) { m_inherited.border_spacing_vertical = border_spacing_vertical; }
|
void set_border_spacing_vertical(CSS::Length border_spacing_vertical) { m_inherited.border_spacing_vertical = border_spacing_vertical; }
|
||||||
void set_caption_side(CSS::CaptionSide caption_side) { m_inherited.caption_side = caption_side; }
|
void set_caption_side(CSS::CaptionSide caption_side) { m_inherited.caption_side = caption_side; }
|
||||||
void set_color(Color color) { m_inherited.color = color; }
|
void set_color(Color color) { m_inherited.color = color; }
|
||||||
|
void set_color_scheme(CSS::PreferredColorScheme color_scheme) { m_inherited.color_scheme = color_scheme; }
|
||||||
void set_clip(CSS::Clip const& clip) { m_noninherited.clip = clip; }
|
void set_clip(CSS::Clip const& clip) { m_noninherited.clip = clip; }
|
||||||
void set_content(ContentData const& content) { m_noninherited.content = content; }
|
void set_content(ContentData const& content) { m_noninherited.content = content; }
|
||||||
void set_content_visibility(CSS::ContentVisibility content_visibility) { m_inherited.content_visibility = content_visibility; }
|
void set_content_visibility(CSS::ContentVisibility content_visibility) { m_inherited.content_visibility = content_visibility; }
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
|
|
||||||
html {
|
html {
|
||||||
font-family: serif;
|
font-family: serif;
|
||||||
color: CanvasText;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
|
@ -54,15 +53,12 @@ button, input[type=submit], input[type=button], input[type=reset], select, ::fil
|
||||||
border: 1px solid ButtonBorder;
|
border: 1px solid ButtonBorder;
|
||||||
color: ButtonText;
|
color: ButtonText;
|
||||||
cursor: default;
|
cursor: default;
|
||||||
|
/* FIXME: For some reason this filter is required for the :hover style to work */
|
||||||
|
filter: contrast(100%);
|
||||||
}
|
}
|
||||||
|
|
||||||
button:disabled, input[type=submit]:disabled, input[type=button]:disabled, input[type=reset]:disabled, select:disabled {
|
button:disabled, input[type=submit]:disabled, input[type=button]:disabled, input[type=reset]:disabled, select:disabled {
|
||||||
/* FIXME: There isn't a <system-color> keyword for this, so this is a slightly lightened
|
filter: contrast(70%);
|
||||||
* version of our light ButtonFace color. Once we support `color-scheme: dark`
|
|
||||||
* we'll need to use a different color for that.
|
|
||||||
*/
|
|
||||||
background-color: #e5e0d7;
|
|
||||||
color: GrayText;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type=image] {
|
input[type=image] {
|
||||||
|
@ -70,11 +66,7 @@ input[type=image] {
|
||||||
}
|
}
|
||||||
|
|
||||||
button:hover, input[type=submit]:hover, input[type=button]:hover, input[type=reset]:hover, select:hover {
|
button:hover, input[type=submit]:hover, input[type=button]:hover, input[type=reset]:hover, select:hover {
|
||||||
/* FIXME: There isn't a <system-color> keyword for this, so this is a slightly lightened
|
filter: contrast(70%);
|
||||||
* version of our light ButtonFace color. Once we support `color-scheme: dark`
|
|
||||||
* we'll need to use a different color for that.
|
|
||||||
*/
|
|
||||||
background-color: #e5e0d7;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
option {
|
option {
|
||||||
|
@ -95,7 +87,7 @@ input[type=range]::-webkit-slider-runnable-track {
|
||||||
height: 4px;
|
height: 4px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
margin-top: 6px;
|
margin-top: 6px;
|
||||||
background-color: Background;
|
background-color: AccentColorText;
|
||||||
border: 1px solid rgba(0, 0, 0, 0.5);
|
border: 1px solid rgba(0, 0, 0, 0.5);
|
||||||
}
|
}
|
||||||
input[type=range]::-webkit-slider-thumb {
|
input[type=range]::-webkit-slider-thumb {
|
||||||
|
@ -143,7 +135,7 @@ progress::-webkit-progress-bar, progress::-webkit-progress-value {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
progress::-webkit-progress-bar {
|
progress::-webkit-progress-bar {
|
||||||
background-color: Background;
|
background-color: AccentColorText;
|
||||||
border: 1px solid rgba(0, 0, 0, 0.5);
|
border: 1px solid rgba(0, 0, 0, 0.5);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -862,6 +854,8 @@ progress {
|
||||||
/* https://github.com/whatwg/html/pull/9546
|
/* https://github.com/whatwg/html/pull/9546
|
||||||
*/
|
*/
|
||||||
input[type=checkbox][switch] {
|
input[type=checkbox][switch] {
|
||||||
|
/* FIXME: Workaround until we can properly style dark switches */
|
||||||
|
color-scheme: light;
|
||||||
appearance: none;
|
appearance: none;
|
||||||
height: 1em;
|
height: 1em;
|
||||||
width: 1.8em;
|
width: 1.8em;
|
||||||
|
|
|
@ -42,6 +42,7 @@
|
||||||
#include <LibWeb/CSS/StyleValues/CSSLCHLike.h>
|
#include <LibWeb/CSS/StyleValues/CSSLCHLike.h>
|
||||||
#include <LibWeb/CSS/StyleValues/CSSLabLike.h>
|
#include <LibWeb/CSS/StyleValues/CSSLabLike.h>
|
||||||
#include <LibWeb/CSS/StyleValues/CSSRGB.h>
|
#include <LibWeb/CSS/StyleValues/CSSRGB.h>
|
||||||
|
#include <LibWeb/CSS/StyleValues/ColorSchemeStyleValue.h>
|
||||||
#include <LibWeb/CSS/StyleValues/ContentStyleValue.h>
|
#include <LibWeb/CSS/StyleValues/ContentStyleValue.h>
|
||||||
#include <LibWeb/CSS/StyleValues/CounterDefinitionsStyleValue.h>
|
#include <LibWeb/CSS/StyleValues/CounterDefinitionsStyleValue.h>
|
||||||
#include <LibWeb/CSS/StyleValues/CounterStyleValue.h>
|
#include <LibWeb/CSS/StyleValues/CounterStyleValue.h>
|
||||||
|
@ -3612,6 +3613,71 @@ RefPtr<CSSStyleValue> Parser::parse_color_value(TokenStream<ComponentValue>& tok
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RefPtr<CSSStyleValue> Parser::parse_color_scheme_value(TokenStream<ComponentValue>& tokens)
|
||||||
|
{
|
||||||
|
// normal | [ light | dark | <custom-ident> ]+ && only?
|
||||||
|
|
||||||
|
// normal
|
||||||
|
{
|
||||||
|
auto transaction = tokens.begin_transaction();
|
||||||
|
tokens.discard_whitespace();
|
||||||
|
if (tokens.consume_a_token().is_ident("normal"sv)) {
|
||||||
|
if (tokens.has_next_token())
|
||||||
|
return {};
|
||||||
|
transaction.commit();
|
||||||
|
return ColorSchemeStyleValue::normal();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool only = false;
|
||||||
|
Vector<String> schemes;
|
||||||
|
|
||||||
|
// only? && (..)
|
||||||
|
{
|
||||||
|
auto transaction = tokens.begin_transaction();
|
||||||
|
tokens.discard_whitespace();
|
||||||
|
if (tokens.consume_a_token().is_ident("only"sv)) {
|
||||||
|
only = true;
|
||||||
|
transaction.commit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// [ light | dark | <custom-ident> ]+
|
||||||
|
tokens.discard_whitespace();
|
||||||
|
while (tokens.has_next_token()) {
|
||||||
|
auto transaction = tokens.begin_transaction();
|
||||||
|
|
||||||
|
// The 'normal', 'light', 'dark', and 'only' keywords are not valid <custom-ident>s in this property.
|
||||||
|
// Note: only 'normal' is blacklisted here because 'light' and 'dark' aren't parsed differently and 'only' is checked for afterwards
|
||||||
|
auto ident = parse_custom_ident_value(tokens, { "normal"sv });
|
||||||
|
if (!ident)
|
||||||
|
return {};
|
||||||
|
|
||||||
|
if (ident->custom_ident() == "only"_fly_string)
|
||||||
|
break;
|
||||||
|
|
||||||
|
schemes.append(ident->custom_ident().to_string());
|
||||||
|
tokens.discard_whitespace();
|
||||||
|
transaction.commit();
|
||||||
|
}
|
||||||
|
|
||||||
|
// (..) && only?
|
||||||
|
if (!only) {
|
||||||
|
auto transaction = tokens.begin_transaction();
|
||||||
|
tokens.discard_whitespace();
|
||||||
|
if (tokens.consume_a_token().is_ident("only"sv)) {
|
||||||
|
only = true;
|
||||||
|
transaction.commit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tokens.discard_whitespace();
|
||||||
|
if (tokens.has_next_token() || schemes.is_empty())
|
||||||
|
return {};
|
||||||
|
|
||||||
|
return ColorSchemeStyleValue::create(schemes, only);
|
||||||
|
}
|
||||||
|
|
||||||
// https://drafts.csswg.org/css-lists-3/#counter-functions
|
// https://drafts.csswg.org/css-lists-3/#counter-functions
|
||||||
RefPtr<CSSStyleValue> Parser::parse_counter_value(TokenStream<ComponentValue>& tokens)
|
RefPtr<CSSStyleValue> Parser::parse_counter_value(TokenStream<ComponentValue>& tokens)
|
||||||
{
|
{
|
||||||
|
@ -8460,6 +8526,10 @@ Parser::ParseErrorOr<NonnullRefPtr<CSSStyleValue>> Parser::parse_css_value(Prope
|
||||||
if (auto parsed_value = parse_shadow_value(tokens, AllowInsetKeyword::Yes); parsed_value && !tokens.has_next_token())
|
if (auto parsed_value = parse_shadow_value(tokens, AllowInsetKeyword::Yes); parsed_value && !tokens.has_next_token())
|
||||||
return parsed_value.release_nonnull();
|
return parsed_value.release_nonnull();
|
||||||
return ParseError::SyntaxError;
|
return ParseError::SyntaxError;
|
||||||
|
case PropertyID::ColorScheme:
|
||||||
|
if (auto parsed_value = parse_color_scheme_value(tokens); parsed_value && !tokens.has_next_token())
|
||||||
|
return parsed_value.release_nonnull();
|
||||||
|
return ParseError::SyntaxError;
|
||||||
case PropertyID::Columns:
|
case PropertyID::Columns:
|
||||||
if (auto parsed_value = parse_columns_value(tokens); parsed_value && !tokens.has_next_token())
|
if (auto parsed_value = parse_columns_value(tokens); parsed_value && !tokens.has_next_token())
|
||||||
return parsed_value.release_nonnull();
|
return parsed_value.release_nonnull();
|
||||||
|
|
|
@ -292,6 +292,7 @@ private:
|
||||||
RefPtr<CSSStyleValue> parse_oklch_color_value(TokenStream<ComponentValue>&);
|
RefPtr<CSSStyleValue> parse_oklch_color_value(TokenStream<ComponentValue>&);
|
||||||
RefPtr<CSSStyleValue> parse_color_function(TokenStream<ComponentValue>&);
|
RefPtr<CSSStyleValue> parse_color_function(TokenStream<ComponentValue>&);
|
||||||
RefPtr<CSSStyleValue> parse_color_value(TokenStream<ComponentValue>&);
|
RefPtr<CSSStyleValue> parse_color_value(TokenStream<ComponentValue>&);
|
||||||
|
RefPtr<CSSStyleValue> parse_color_scheme_value(TokenStream<ComponentValue>&);
|
||||||
RefPtr<CSSStyleValue> parse_counter_value(TokenStream<ComponentValue>&);
|
RefPtr<CSSStyleValue> parse_counter_value(TokenStream<ComponentValue>&);
|
||||||
enum class AllowReversed {
|
enum class AllowReversed {
|
||||||
No,
|
No,
|
||||||
|
|
|
@ -866,6 +866,12 @@
|
||||||
"hashless-hex-color"
|
"hashless-hex-color"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"color-scheme": {
|
||||||
|
"affects-layout": false,
|
||||||
|
"animation-type": "discrete",
|
||||||
|
"inherited": true,
|
||||||
|
"initial": "normal"
|
||||||
|
},
|
||||||
"column-count": {
|
"column-count": {
|
||||||
"animation-type": "by-computed-value",
|
"animation-type": "by-computed-value",
|
||||||
"inherited": false,
|
"inherited": false,
|
||||||
|
|
|
@ -141,16 +141,19 @@ Color CSSKeywordValue::to_color(Optional<Layout::NodeWithStyle const&> node) con
|
||||||
return node->computed_values().color();
|
return node->computed_values().color();
|
||||||
}
|
}
|
||||||
|
|
||||||
// First, handle <system-color>s, since they don't require a node.
|
PreferredColorScheme scheme = PreferredColorScheme::Light;
|
||||||
|
if (node.has_value()) {
|
||||||
|
scheme = node->computed_values().color_scheme();
|
||||||
|
}
|
||||||
|
|
||||||
|
// First, handle <system-color>s, since they don't strictly require a node.
|
||||||
// https://www.w3.org/TR/css-color-4/#css-system-colors
|
// https://www.w3.org/TR/css-color-4/#css-system-colors
|
||||||
// https://www.w3.org/TR/css-color-4/#deprecated-system-colors
|
// https://www.w3.org/TR/css-color-4/#deprecated-system-colors
|
||||||
switch (keyword()) {
|
switch (keyword()) {
|
||||||
case Keyword::Accentcolor:
|
case Keyword::Accentcolor:
|
||||||
return SystemColor::accent_color();
|
return SystemColor::accent_color(scheme);
|
||||||
case Keyword::Accentcolortext:
|
case Keyword::Accentcolortext:
|
||||||
return SystemColor::accent_color_text();
|
return SystemColor::accent_color_text(scheme);
|
||||||
case Keyword::Activetext:
|
|
||||||
return SystemColor::active_text();
|
|
||||||
case Keyword::Buttonborder:
|
case Keyword::Buttonborder:
|
||||||
case Keyword::Activeborder:
|
case Keyword::Activeborder:
|
||||||
case Keyword::Inactiveborder:
|
case Keyword::Inactiveborder:
|
||||||
|
@ -159,14 +162,14 @@ Color CSSKeywordValue::to_color(Optional<Layout::NodeWithStyle const&> node) con
|
||||||
case Keyword::Threedlightshadow:
|
case Keyword::Threedlightshadow:
|
||||||
case Keyword::Threedshadow:
|
case Keyword::Threedshadow:
|
||||||
case Keyword::Windowframe:
|
case Keyword::Windowframe:
|
||||||
return SystemColor::button_border();
|
return SystemColor::button_border(scheme);
|
||||||
case Keyword::Buttonface:
|
case Keyword::Buttonface:
|
||||||
case Keyword::Buttonhighlight:
|
case Keyword::Buttonhighlight:
|
||||||
case Keyword::Buttonshadow:
|
case Keyword::Buttonshadow:
|
||||||
case Keyword::Threedface:
|
case Keyword::Threedface:
|
||||||
return SystemColor::button_face();
|
return SystemColor::button_face(scheme);
|
||||||
case Keyword::Buttontext:
|
case Keyword::Buttontext:
|
||||||
return SystemColor::button_text();
|
return SystemColor::button_text(scheme);
|
||||||
case Keyword::Canvas:
|
case Keyword::Canvas:
|
||||||
case Keyword::Appworkspace:
|
case Keyword::Appworkspace:
|
||||||
case Keyword::Background:
|
case Keyword::Background:
|
||||||
|
@ -175,35 +178,33 @@ Color CSSKeywordValue::to_color(Optional<Layout::NodeWithStyle const&> node) con
|
||||||
case Keyword::Menu:
|
case Keyword::Menu:
|
||||||
case Keyword::Scrollbar:
|
case Keyword::Scrollbar:
|
||||||
case Keyword::Window:
|
case Keyword::Window:
|
||||||
return SystemColor::canvas();
|
return SystemColor::canvas(scheme);
|
||||||
case Keyword::Canvastext:
|
case Keyword::Canvastext:
|
||||||
case Keyword::Activecaption:
|
case Keyword::Activecaption:
|
||||||
case Keyword::Captiontext:
|
case Keyword::Captiontext:
|
||||||
case Keyword::Infotext:
|
case Keyword::Infotext:
|
||||||
case Keyword::Menutext:
|
case Keyword::Menutext:
|
||||||
case Keyword::Windowtext:
|
case Keyword::Windowtext:
|
||||||
return SystemColor::canvas_text();
|
return SystemColor::canvas_text(scheme);
|
||||||
case Keyword::Field:
|
case Keyword::Field:
|
||||||
return SystemColor::field();
|
return SystemColor::field(scheme);
|
||||||
case Keyword::Fieldtext:
|
case Keyword::Fieldtext:
|
||||||
return SystemColor::field_text();
|
return SystemColor::field_text(scheme);
|
||||||
case Keyword::Graytext:
|
case Keyword::Graytext:
|
||||||
case Keyword::Inactivecaptiontext:
|
case Keyword::Inactivecaptiontext:
|
||||||
return SystemColor::gray_text();
|
return SystemColor::gray_text(scheme);
|
||||||
case Keyword::Highlight:
|
case Keyword::Highlight:
|
||||||
return SystemColor::highlight();
|
return SystemColor::highlight(scheme);
|
||||||
case Keyword::Highlighttext:
|
case Keyword::Highlighttext:
|
||||||
return SystemColor::highlight_text();
|
return SystemColor::highlight_text(scheme);
|
||||||
case Keyword::Mark:
|
case Keyword::Mark:
|
||||||
return SystemColor::mark();
|
return SystemColor::mark(scheme);
|
||||||
case Keyword::Marktext:
|
case Keyword::Marktext:
|
||||||
return SystemColor::mark_text();
|
return SystemColor::mark_text(scheme);
|
||||||
case Keyword::Selecteditem:
|
case Keyword::Selecteditem:
|
||||||
return SystemColor::selected_item();
|
return SystemColor::selected_item(scheme);
|
||||||
case Keyword::Selecteditemtext:
|
case Keyword::Selecteditemtext:
|
||||||
return SystemColor::selected_item_text();
|
return SystemColor::selected_item_text(scheme);
|
||||||
case Keyword::Visitedtext:
|
|
||||||
return SystemColor::visited_text();
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -213,9 +214,19 @@ Color CSSKeywordValue::to_color(Optional<Layout::NodeWithStyle const&> node) con
|
||||||
return Color::Black;
|
return Color::Black;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto& document = node->document();
|
auto const& document = node->document();
|
||||||
if (keyword() == Keyword::LibwebLink || keyword() == Keyword::Linktext)
|
|
||||||
return document.normal_link_color();
|
switch (keyword()) {
|
||||||
|
case Keyword::LibwebLink:
|
||||||
|
case Keyword::Linktext:
|
||||||
|
return document.normal_link_color().value_or(SystemColor::link_text(scheme));
|
||||||
|
case Keyword::Visitedtext:
|
||||||
|
return document.visited_link_color().value_or(SystemColor::visited_text(scheme));
|
||||||
|
case Keyword::Activetext:
|
||||||
|
return document.active_link_color().value_or(SystemColor::active_text(scheme));
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
auto palette = document.page().palette();
|
auto palette = document.page().palette();
|
||||||
switch (keyword()) {
|
switch (keyword()) {
|
||||||
|
|
34
Libraries/LibWeb/CSS/StyleValues/ColorSchemeStyleValue.cpp
Normal file
34
Libraries/LibWeb/CSS/StyleValues/ColorSchemeStyleValue.cpp
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2025, Ladybird contributors
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "ColorSchemeStyleValue.h"
|
||||||
|
#include <LibWeb/CSS/Serialize.h>
|
||||||
|
|
||||||
|
namespace Web::CSS {
|
||||||
|
|
||||||
|
String ColorSchemeStyleValue::to_string(SerializationMode) const
|
||||||
|
{
|
||||||
|
if (schemes().is_empty())
|
||||||
|
return "normal"_string;
|
||||||
|
|
||||||
|
StringBuilder builder;
|
||||||
|
bool first = true;
|
||||||
|
for (auto const& scheme : schemes()) {
|
||||||
|
if (first) {
|
||||||
|
first = false;
|
||||||
|
} else {
|
||||||
|
builder.append(' ');
|
||||||
|
}
|
||||||
|
builder.append(serialize_an_identifier(scheme));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (only())
|
||||||
|
builder.append(" only"sv);
|
||||||
|
|
||||||
|
return MUST(builder.to_string());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
44
Libraries/LibWeb/CSS/StyleValues/ColorSchemeStyleValue.h
Normal file
44
Libraries/LibWeb/CSS/StyleValues/ColorSchemeStyleValue.h
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2025, Ladybird contributors
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <LibWeb/CSS/CSSStyleValue.h>
|
||||||
|
|
||||||
|
namespace Web::CSS {
|
||||||
|
|
||||||
|
class ColorSchemeStyleValue final : public StyleValueWithDefaultOperators<ColorSchemeStyleValue> {
|
||||||
|
public:
|
||||||
|
static ValueComparingNonnullRefPtr<ColorSchemeStyleValue> create(Vector<String> schemes, bool only)
|
||||||
|
{
|
||||||
|
return adopt_ref(*new (nothrow) ColorSchemeStyleValue(move(schemes), only));
|
||||||
|
}
|
||||||
|
static ValueComparingNonnullRefPtr<ColorSchemeStyleValue> normal()
|
||||||
|
{
|
||||||
|
return adopt_ref(*new (nothrow) ColorSchemeStyleValue({}, false));
|
||||||
|
}
|
||||||
|
virtual ~ColorSchemeStyleValue() override = default;
|
||||||
|
|
||||||
|
Vector<String> const& schemes() const { return m_properties.schemes; }
|
||||||
|
bool const& only() const { return m_properties.only; }
|
||||||
|
virtual String to_string(SerializationMode) const override;
|
||||||
|
|
||||||
|
bool properties_equal(ColorSchemeStyleValue const& other) const { return m_properties == other.m_properties; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
ColorSchemeStyleValue(Vector<String> schemes, bool only)
|
||||||
|
: StyleValueWithDefaultOperators(Type::ColorScheme)
|
||||||
|
, m_properties { .schemes = move(schemes), .only = only }
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Properties {
|
||||||
|
Vector<String> schemes;
|
||||||
|
bool only;
|
||||||
|
bool operator==(Properties const&) const = default;
|
||||||
|
} m_properties;
|
||||||
|
};
|
||||||
|
}
|
|
@ -8,98 +8,134 @@
|
||||||
|
|
||||||
namespace Web::CSS::SystemColor {
|
namespace Web::CSS::SystemColor {
|
||||||
|
|
||||||
Color accent_color()
|
Color accent_color(PreferredColorScheme)
|
||||||
{
|
{
|
||||||
return Color(61, 174, 233);
|
return Color(61, 174, 233);
|
||||||
}
|
}
|
||||||
|
|
||||||
Color accent_color_text()
|
Color accent_color_text(PreferredColorScheme)
|
||||||
{
|
{
|
||||||
return Color(255, 255, 255);
|
return Color(255, 255, 255);
|
||||||
}
|
}
|
||||||
|
|
||||||
Color active_text()
|
Color active_text(PreferredColorScheme scheme)
|
||||||
{
|
{
|
||||||
|
if (scheme == PreferredColorScheme::Dark) {
|
||||||
|
return Color(213, 97, 82);
|
||||||
|
}
|
||||||
return Color(255, 0, 0);
|
return Color(255, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
Color button_border()
|
Color button_border(PreferredColorScheme scheme)
|
||||||
{
|
{
|
||||||
|
if (scheme == PreferredColorScheme::Dark) {
|
||||||
|
return Color(72, 72, 72);
|
||||||
|
}
|
||||||
return Color(128, 128, 128);
|
return Color(128, 128, 128);
|
||||||
}
|
}
|
||||||
|
|
||||||
Color button_face()
|
Color button_face(PreferredColorScheme scheme)
|
||||||
{
|
{
|
||||||
|
if (scheme == PreferredColorScheme::Dark) {
|
||||||
|
return Color(32, 29, 25);
|
||||||
|
}
|
||||||
return Color(212, 208, 200);
|
return Color(212, 208, 200);
|
||||||
}
|
}
|
||||||
|
|
||||||
Color button_text()
|
Color button_text(PreferredColorScheme scheme)
|
||||||
{
|
{
|
||||||
|
if (scheme == PreferredColorScheme::Dark) {
|
||||||
|
return Color(235, 235, 235);
|
||||||
|
}
|
||||||
return Color(0, 0, 0);
|
return Color(0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
Color canvas()
|
Color canvas(PreferredColorScheme scheme)
|
||||||
{
|
{
|
||||||
|
if (scheme == PreferredColorScheme::Dark) {
|
||||||
|
return Color(20, 20, 20);
|
||||||
|
}
|
||||||
return Color(255, 255, 255);
|
return Color(255, 255, 255);
|
||||||
}
|
}
|
||||||
|
|
||||||
Color canvas_text()
|
Color canvas_text(PreferredColorScheme scheme)
|
||||||
{
|
{
|
||||||
|
if (scheme == PreferredColorScheme::Dark) {
|
||||||
|
return Color(235, 235, 235);
|
||||||
|
}
|
||||||
return Color(0, 0, 0);
|
return Color(0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
Color field()
|
Color field(PreferredColorScheme scheme)
|
||||||
{
|
{
|
||||||
|
if (scheme == PreferredColorScheme::Dark) {
|
||||||
|
return Color(32, 29, 25);
|
||||||
|
}
|
||||||
return Color(255, 255, 255);
|
return Color(255, 255, 255);
|
||||||
}
|
}
|
||||||
|
|
||||||
Color field_text()
|
Color field_text(PreferredColorScheme scheme)
|
||||||
{
|
{
|
||||||
|
if (scheme == PreferredColorScheme::Dark) {
|
||||||
|
return Color(235, 235, 235);
|
||||||
|
}
|
||||||
return Color(0, 0, 0);
|
return Color(0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
Color gray_text()
|
Color gray_text(PreferredColorScheme)
|
||||||
{
|
{
|
||||||
return Color(128, 128, 128);
|
return Color(128, 128, 128);
|
||||||
}
|
}
|
||||||
|
|
||||||
Color highlight()
|
Color highlight(PreferredColorScheme)
|
||||||
{
|
{
|
||||||
return Color(61, 174, 233);
|
return Color(61, 174, 233);
|
||||||
}
|
}
|
||||||
|
|
||||||
Color highlight_text()
|
Color highlight_text(PreferredColorScheme scheme)
|
||||||
{
|
{
|
||||||
|
if (scheme == PreferredColorScheme::Dark) {
|
||||||
|
return Color(20, 20, 20);
|
||||||
|
}
|
||||||
return Color(255, 255, 255);
|
return Color(255, 255, 255);
|
||||||
}
|
}
|
||||||
|
|
||||||
Color link_text()
|
Color link_text(PreferredColorScheme scheme)
|
||||||
{
|
{
|
||||||
|
if (scheme == PreferredColorScheme::Dark) {
|
||||||
|
return Color(100, 149, 237);
|
||||||
|
}
|
||||||
return Color(0, 0, 238);
|
return Color(0, 0, 238);
|
||||||
}
|
}
|
||||||
|
|
||||||
Color mark()
|
Color mark(PreferredColorScheme)
|
||||||
{
|
{
|
||||||
return Color(255, 255, 0);
|
return Color(255, 255, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
Color mark_text()
|
Color mark_text(PreferredColorScheme)
|
||||||
{
|
{
|
||||||
return Color(0, 0, 0);
|
return Color(0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
Color selected_item()
|
Color selected_item(PreferredColorScheme)
|
||||||
{
|
{
|
||||||
return Color(61, 174, 233);
|
return Color(61, 174, 233);
|
||||||
}
|
}
|
||||||
|
|
||||||
Color selected_item_text()
|
Color selected_item_text(PreferredColorScheme scheme)
|
||||||
{
|
{
|
||||||
|
if (scheme == PreferredColorScheme::Dark) {
|
||||||
|
return Color(20, 20, 20);
|
||||||
|
}
|
||||||
return Color(255, 255, 255);
|
return Color(255, 255, 255);
|
||||||
}
|
}
|
||||||
|
|
||||||
Color visited_text()
|
Color visited_text(PreferredColorScheme scheme)
|
||||||
{
|
{
|
||||||
|
if (scheme == PreferredColorScheme::Dark) {
|
||||||
|
return Color(156, 113, 212);
|
||||||
|
}
|
||||||
return Color(85, 26, 139);
|
return Color(85, 26, 139);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,29 +7,28 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <LibGfx/Color.h>
|
#include <LibGfx/Color.h>
|
||||||
|
#include <LibWeb/CSS/PreferredColorScheme.h>
|
||||||
|
|
||||||
// https://www.w3.org/TR/css-color-4/#css-system-colors
|
// https://www.w3.org/TR/css-color-4/#css-system-colors
|
||||||
namespace Web::CSS::SystemColor {
|
namespace Web::CSS::SystemColor {
|
||||||
|
|
||||||
// FIXME: Provide colors for `color-scheme: dark` once we support that.
|
Color accent_color(PreferredColorScheme);
|
||||||
Color accent_color();
|
Color accent_color_text(PreferredColorScheme);
|
||||||
Color accent_color_text();
|
Color active_text(PreferredColorScheme);
|
||||||
Color active_text();
|
Color button_border(PreferredColorScheme);
|
||||||
Color button_border();
|
Color button_face(PreferredColorScheme);
|
||||||
Color button_face();
|
Color button_text(PreferredColorScheme);
|
||||||
Color button_text();
|
Color canvas(PreferredColorScheme);
|
||||||
Color canvas();
|
Color canvas_text(PreferredColorScheme);
|
||||||
Color canvas_text();
|
Color field(PreferredColorScheme);
|
||||||
Color field();
|
Color field_text(PreferredColorScheme);
|
||||||
Color field_text();
|
Color gray_text(PreferredColorScheme);
|
||||||
Color gray_text();
|
Color highlight(PreferredColorScheme);
|
||||||
Color highlight();
|
Color highlight_text(PreferredColorScheme);
|
||||||
Color highlight_text();
|
Color link_text(PreferredColorScheme);
|
||||||
Color link_text();
|
Color mark(PreferredColorScheme);
|
||||||
Color mark();
|
Color mark_text(PreferredColorScheme);
|
||||||
Color mark_text();
|
Color selected_item(PreferredColorScheme);
|
||||||
Color selected_item();
|
Color selected_item_text(PreferredColorScheme);
|
||||||
Color selected_item_text();
|
Color visited_text(PreferredColorScheme);
|
||||||
Color visited_text();
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1769,25 +1769,19 @@ void Document::release_events()
|
||||||
// Do nothing
|
// Do nothing
|
||||||
}
|
}
|
||||||
|
|
||||||
Color Document::normal_link_color() const
|
Optional<Color> Document::normal_link_color() const
|
||||||
{
|
{
|
||||||
if (m_normal_link_color.has_value())
|
return m_normal_link_color;
|
||||||
return m_normal_link_color.value();
|
|
||||||
return CSS::SystemColor::link_text();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Color Document::active_link_color() const
|
Optional<Color> Document::active_link_color() const
|
||||||
{
|
{
|
||||||
if (m_active_link_color.has_value())
|
return m_active_link_color;
|
||||||
return m_active_link_color.value();
|
|
||||||
return CSS::SystemColor::active_text();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Color Document::visited_link_color() const
|
Optional<Color> Document::visited_link_color() const
|
||||||
{
|
{
|
||||||
if (m_visited_link_color.has_value())
|
return m_visited_link_color;
|
||||||
return m_visited_link_color.value();
|
|
||||||
return CSS::SystemColor::visited_text();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/webappapis.html#relevant-settings-object
|
// https://html.spec.whatwg.org/multipage/webappapis.html#relevant-settings-object
|
||||||
|
@ -5912,13 +5906,38 @@ RefPtr<Painting::DisplayList> Document::record_display_list(PaintConfig config)
|
||||||
auto display_list = Painting::DisplayList::create();
|
auto display_list = Painting::DisplayList::create();
|
||||||
Painting::DisplayListRecorder display_list_recorder(display_list);
|
Painting::DisplayListRecorder display_list_recorder(display_list);
|
||||||
|
|
||||||
|
// https://drafts.csswg.org/css-color-adjust-1/#color-scheme-effect
|
||||||
|
// On the root element, the used color scheme additionally must affect the surface color of the canvas, and the viewport’s scrollbars.
|
||||||
|
auto color_scheme = CSS::PreferredColorScheme::Light;
|
||||||
|
if (auto* html_element = this->html_element(); html_element && html_element->layout_node()) {
|
||||||
|
if (html_element->layout_node()->computed_values().color_scheme() == CSS::PreferredColorScheme::Dark)
|
||||||
|
color_scheme = CSS::PreferredColorScheme::Dark;
|
||||||
|
}
|
||||||
|
|
||||||
|
// .. in the case of embedded documents typically rendered over a transparent canvas
|
||||||
|
// (such as provided via an HTML iframe element), if the used color scheme of the element
|
||||||
|
// and the used color scheme of the embedded document’s root element do not match,
|
||||||
|
// then the UA must use an opaque canvas of the Canvas color appropriate to the
|
||||||
|
// embedded document’s used color scheme instead of a transparent canvas.
|
||||||
|
bool opaque_canvas = false;
|
||||||
|
if (auto container_element = navigable()->container(); container_element && container_element->layout_node()) {
|
||||||
|
auto container_scheme = container_element->layout_node()->computed_values().color_scheme();
|
||||||
|
if (container_scheme == CSS::PreferredColorScheme::Auto)
|
||||||
|
container_scheme = CSS::PreferredColorScheme::Light;
|
||||||
|
|
||||||
|
opaque_canvas = container_scheme != color_scheme;
|
||||||
|
}
|
||||||
|
|
||||||
if (config.canvas_fill_rect.has_value()) {
|
if (config.canvas_fill_rect.has_value()) {
|
||||||
display_list_recorder.fill_rect(config.canvas_fill_rect.value(), CSS::SystemColor::canvas());
|
display_list_recorder.fill_rect(config.canvas_fill_rect.value(), CSS::SystemColor::canvas(color_scheme));
|
||||||
}
|
}
|
||||||
|
|
||||||
auto viewport_rect = page().css_to_device_rect(this->viewport_rect());
|
auto viewport_rect = page().css_to_device_rect(this->viewport_rect());
|
||||||
Gfx::IntRect bitmap_rect { {}, viewport_rect.size().to_type<int>() };
|
Gfx::IntRect bitmap_rect { {}, viewport_rect.size().to_type<int>() };
|
||||||
|
|
||||||
|
if (opaque_canvas)
|
||||||
|
display_list_recorder.fill_rect(bitmap_rect, CSS::SystemColor::canvas(color_scheme));
|
||||||
|
|
||||||
display_list_recorder.fill_rect(bitmap_rect, background_color());
|
display_list_recorder.fill_rect(bitmap_rect, background_color());
|
||||||
if (!paintable()) {
|
if (!paintable()) {
|
||||||
VERIFY_NOT_REACHED();
|
VERIFY_NOT_REACHED();
|
||||||
|
|
|
@ -233,13 +233,13 @@ public:
|
||||||
Color background_color() const;
|
Color background_color() const;
|
||||||
Vector<CSS::BackgroundLayerData> const* background_layers() const;
|
Vector<CSS::BackgroundLayerData> const* background_layers() const;
|
||||||
|
|
||||||
Color normal_link_color() const;
|
Optional<Color> normal_link_color() const;
|
||||||
void set_normal_link_color(Color);
|
void set_normal_link_color(Color);
|
||||||
|
|
||||||
Color active_link_color() const;
|
Optional<Color> active_link_color() const;
|
||||||
void set_active_link_color(Color);
|
void set_active_link_color(Color);
|
||||||
|
|
||||||
Color visited_link_color() const;
|
Optional<Color> visited_link_color() const;
|
||||||
void set_visited_link_color(Color);
|
void set_visited_link_color(Color);
|
||||||
|
|
||||||
void update_style();
|
void update_style();
|
||||||
|
|
|
@ -116,6 +116,7 @@ class BasicShapeStyleValue;
|
||||||
class BorderRadiusStyleValue;
|
class BorderRadiusStyleValue;
|
||||||
class CalculatedStyleValue;
|
class CalculatedStyleValue;
|
||||||
class Clip;
|
class Clip;
|
||||||
|
class ColorSchemeStyleValue;
|
||||||
class ConicGradientStyleValue;
|
class ConicGradientStyleValue;
|
||||||
class ContentStyleValue;
|
class ContentStyleValue;
|
||||||
class CounterDefinitionsStyleValue;
|
class CounterDefinitionsStyleValue;
|
||||||
|
|
|
@ -1181,8 +1181,7 @@ void HTMLInputElement::computed_properties_changed()
|
||||||
if (!appearance.has_value() || *appearance == CSS::Appearance::None)
|
if (!appearance.has_value() || *appearance == CSS::Appearance::None)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
auto palette = document().page().palette();
|
auto accent_color = MUST(String::from_utf8(CSS::string_from_keyword(CSS::Keyword::Accentcolor)));
|
||||||
auto accent_color = palette.color(ColorRole::Accent).to_string();
|
|
||||||
|
|
||||||
auto const& accent_color_property = computed_properties()->property(CSS::PropertyID::AccentColor);
|
auto const& accent_color_property = computed_properties()->property(CSS::PropertyID::AccentColor);
|
||||||
if (accent_color_property.has_color())
|
if (accent_color_property.has_color())
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
|
|
||||||
#include <LibWeb/Bindings/HTMLProgressElementPrototype.h>
|
#include <LibWeb/Bindings/HTMLProgressElementPrototype.h>
|
||||||
#include <LibWeb/CSS/ComputedProperties.h>
|
#include <LibWeb/CSS/ComputedProperties.h>
|
||||||
|
#include <LibWeb/CSS/StyleValues/CSSKeywordValue.h>
|
||||||
#include <LibWeb/CSS/StyleValues/DisplayStyleValue.h>
|
#include <LibWeb/CSS/StyleValues/DisplayStyleValue.h>
|
||||||
#include <LibWeb/DOM/Document.h>
|
#include <LibWeb/DOM/Document.h>
|
||||||
#include <LibWeb/DOM/ElementFactory.h>
|
#include <LibWeb/DOM/ElementFactory.h>
|
||||||
|
@ -132,8 +133,7 @@ void HTMLProgressElement::update_progress_value_element()
|
||||||
|
|
||||||
void HTMLProgressElement::computed_properties_changed()
|
void HTMLProgressElement::computed_properties_changed()
|
||||||
{
|
{
|
||||||
auto palette = document().page().palette();
|
auto accent_color = MUST(String::from_utf8(CSS::string_from_keyword(CSS::Keyword::Accentcolor)));
|
||||||
auto accent_color = palette.color(ColorRole::Accent).to_string();
|
|
||||||
|
|
||||||
auto const& accent_color_property = computed_properties()->property(CSS::PropertyID::AccentColor);
|
auto const& accent_color_property = computed_properties()->property(CSS::PropertyID::AccentColor);
|
||||||
if (accent_color_property.has_color())
|
if (accent_color_property.has_color())
|
||||||
|
|
|
@ -328,7 +328,15 @@ void NodeWithStyle::apply_style(const CSS::ComputedProperties& computed_style)
|
||||||
{
|
{
|
||||||
auto& computed_values = mutable_computed_values();
|
auto& computed_values = mutable_computed_values();
|
||||||
|
|
||||||
// NOTE: color must be set first to ensure currentColor can be resolved in other properties (e.g. background-color).
|
// NOTE: color-scheme must be set first to ensure system colors can be resolved correctly.
|
||||||
|
auto preferred_color_scheme = document().page().preferred_color_scheme();
|
||||||
|
// FIXME: We can't just check for Auto because page().preferred_color_scheme() returns garbage data after startup.
|
||||||
|
if (preferred_color_scheme != CSS::PreferredColorScheme::Dark && preferred_color_scheme != CSS::PreferredColorScheme::Light) {
|
||||||
|
preferred_color_scheme = document().page().palette().is_dark() ? CSS::PreferredColorScheme::Dark : CSS::PreferredColorScheme::Light;
|
||||||
|
}
|
||||||
|
computed_values.set_color_scheme(computed_style.color_scheme(preferred_color_scheme));
|
||||||
|
|
||||||
|
// NOTE: color must be set second to ensure currentColor can be resolved in other properties (e.g. background-color).
|
||||||
computed_values.set_color(computed_style.color_or_fallback(CSS::PropertyID::Color, *this, CSS::InitialValues::color()));
|
computed_values.set_color(computed_style.color_or_fallback(CSS::PropertyID::Color, *this, CSS::InitialValues::color()));
|
||||||
|
|
||||||
// NOTE: We have to be careful that font-related properties get set in the right order.
|
// NOTE: We have to be careful that font-related properties get set in the right order.
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <AK/CircularQueue.h>
|
#include <AK/CircularQueue.h>
|
||||||
|
#include <LibWeb/CSS/StyleValues/CSSKeywordValue.h>
|
||||||
#include <LibWeb/DOM/Document.h>
|
#include <LibWeb/DOM/Document.h>
|
||||||
#include <LibWeb/Layout/Node.h>
|
#include <LibWeb/Layout/Node.h>
|
||||||
|
|
||||||
|
@ -579,7 +580,7 @@ Optional<BordersData> borders_data_for_outline(Layout::Node const& layout_node,
|
||||||
if (outline_style == CSS::OutlineStyle::Auto) {
|
if (outline_style == CSS::OutlineStyle::Auto) {
|
||||||
// `auto` lets us do whatever we want for the outline. 2px of the link colour seems reasonable.
|
// `auto` lets us do whatever we want for the outline. 2px of the link colour seems reasonable.
|
||||||
line_style = CSS::LineStyle::Dotted;
|
line_style = CSS::LineStyle::Dotted;
|
||||||
outline_color = layout_node.document().normal_link_color();
|
outline_color = CSS::CSSKeywordValue::create(CSS::Keyword::Linktext)->to_color(*static_cast<Layout::NodeWithStyle const*>(&layout_node));
|
||||||
outline_width = 2;
|
outline_width = 2;
|
||||||
} else {
|
} else {
|
||||||
line_style = CSS::keyword_to_line_style(CSS::to_keyword(outline_style)).value_or(CSS::LineStyle::None);
|
line_style = CSS::keyword_to_line_style(CSS::to_keyword(outline_style)).value_or(CSS::LineStyle::None);
|
||||||
|
|
|
@ -72,10 +72,8 @@ void CheckBoxPaintable::paint(PaintContext& context, PaintPhase phase) const
|
||||||
auto checkbox_rect = context.enclosing_device_rect(absolute_rect()).to_type<int>();
|
auto checkbox_rect = context.enclosing_device_rect(absolute_rect()).to_type<int>();
|
||||||
auto checkbox_radius = checkbox_rect.width() / 5;
|
auto checkbox_radius = checkbox_rect.width() / 5;
|
||||||
|
|
||||||
auto& palette = context.palette();
|
|
||||||
|
|
||||||
auto shade = [&](Color color, float amount) {
|
auto shade = [&](Color color, float amount) {
|
||||||
return InputColors::get_shade(color, amount, palette.is_dark());
|
return InputColors::get_shade(color, amount, computed_values().color_scheme());
|
||||||
};
|
};
|
||||||
|
|
||||||
auto modify_color = [&](Color color) {
|
auto modify_color = [&](Color color) {
|
||||||
|
@ -84,7 +82,7 @@ void CheckBoxPaintable::paint(PaintContext& context, PaintPhase phase) const
|
||||||
return color;
|
return color;
|
||||||
};
|
};
|
||||||
|
|
||||||
auto input_colors = compute_input_colors(palette, computed_values().accent_color());
|
auto input_colors = compute_input_colors(computed_values().color_scheme(), computed_values().accent_color());
|
||||||
|
|
||||||
auto increase_contrast = [&](Color color, Color background) {
|
auto increase_contrast = [&](Color color, Color background) {
|
||||||
auto constexpr min_contrast = 2;
|
auto constexpr min_contrast = 2;
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
#include <AK/Optional.h>
|
#include <AK/Optional.h>
|
||||||
#include <LibGfx/Color.h>
|
#include <LibGfx/Color.h>
|
||||||
#include <LibGfx/Palette.h>
|
#include <LibGfx/Palette.h>
|
||||||
|
#include <LibWeb/CSS/SystemColor.h>
|
||||||
|
|
||||||
namespace Web::Painting {
|
namespace Web::Painting {
|
||||||
|
|
||||||
|
@ -25,24 +26,24 @@ struct InputColors {
|
||||||
Color background_color(bool enabled) { return enabled ? base : light_gray; }
|
Color background_color(bool enabled) { return enabled ? base : light_gray; }
|
||||||
Color border_color(bool enabled) { return enabled ? gray : mid_gray; }
|
Color border_color(bool enabled) { return enabled ? gray : mid_gray; }
|
||||||
|
|
||||||
static Color get_shade(Color color, float amount, bool is_dark_theme)
|
static Color get_shade(Color color, float amount, CSS::PreferredColorScheme color_scheme)
|
||||||
{
|
{
|
||||||
return color.mixed_with(is_dark_theme ? Color::Black : Color::White, amount);
|
auto base_color = CSS::SystemColor::canvas(color_scheme);
|
||||||
|
return color.mixed_with(base_color, amount);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static InputColors compute_input_colors(Palette const& palette, Optional<Color> accent_color)
|
static InputColors compute_input_colors(CSS::PreferredColorScheme color_scheme, Optional<Color> accent_color)
|
||||||
{
|
{
|
||||||
// These shades have been picked to work well for all themes and have enough variation to paint
|
// These shades have been picked to work well for all themes and have enough variation to paint
|
||||||
// all input states (disabled, enabled, checked, etc).
|
// all input states (disabled, enabled, checked, etc).
|
||||||
bool dark_theme = palette.is_dark();
|
auto base_text_color = CSS::SystemColor::canvas_text(color_scheme);
|
||||||
auto base_text_color = palette.color(ColorRole::BaseText);
|
auto accent = accent_color.value_or(CSS::SystemColor::accent_color(color_scheme));
|
||||||
auto accent = accent_color.value_or(palette.color(ColorRole::Accent));
|
auto base = InputColors::get_shade(base_text_color.inverted(), 0.8f, color_scheme);
|
||||||
auto base = InputColors::get_shade(base_text_color.inverted(), 0.8f, dark_theme);
|
auto dark_gray = InputColors::get_shade(base_text_color, 0.3f, color_scheme);
|
||||||
auto dark_gray = InputColors::get_shade(base_text_color, 0.3f, dark_theme);
|
auto gray = InputColors::get_shade(dark_gray, 0.4f, color_scheme);
|
||||||
auto gray = InputColors::get_shade(dark_gray, 0.4f, dark_theme);
|
auto mid_gray = InputColors::get_shade(gray, 0.3f, color_scheme);
|
||||||
auto mid_gray = InputColors::get_shade(gray, 0.3f, dark_theme);
|
auto light_gray = InputColors::get_shade(mid_gray, 0.3f, color_scheme);
|
||||||
auto light_gray = InputColors::get_shade(mid_gray, 0.3f, dark_theme);
|
|
||||||
return InputColors {
|
return InputColors {
|
||||||
.accent = accent,
|
.accent = accent,
|
||||||
.base = base,
|
.base = base,
|
||||||
|
|
|
@ -692,10 +692,10 @@ void paint_text_fragment(PaintContext& context, TextPaintable const& paintable,
|
||||||
|
|
||||||
auto selection_rect = context.enclosing_device_rect(fragment.selection_rect()).to_type<int>();
|
auto selection_rect = context.enclosing_device_rect(fragment.selection_rect()).to_type<int>();
|
||||||
if (!selection_rect.is_empty()) {
|
if (!selection_rect.is_empty()) {
|
||||||
painter.fill_rect(selection_rect, CSS::SystemColor::highlight());
|
painter.fill_rect(selection_rect, CSS::SystemColor::highlight(paintable.computed_values().color_scheme()));
|
||||||
DisplayListRecorderStateSaver saver(painter);
|
DisplayListRecorderStateSaver saver(painter);
|
||||||
painter.add_clip_rect(selection_rect);
|
painter.add_clip_rect(selection_rect);
|
||||||
painter.draw_text_run(baseline_start, *glyph_run, CSS::SystemColor::highlight_text(), fragment_absolute_device_rect.to_type<int>(), scale, fragment.orientation());
|
painter.draw_text_run(baseline_start, *glyph_run, CSS::SystemColor::highlight_text(paintable.computed_values().color_scheme()), fragment_absolute_device_rect.to_type<int>(), scale, fragment.orientation());
|
||||||
}
|
}
|
||||||
|
|
||||||
paint_text_decoration(context, paintable, fragment);
|
paint_text_decoration(context, paintable, fragment);
|
||||||
|
|
|
@ -49,9 +49,8 @@ void RadioButtonPaintable::paint(PaintContext& context, PaintPhase phase) const
|
||||||
|
|
||||||
auto const& radio_button = static_cast<HTML::HTMLInputElement const&>(layout_box().dom_node());
|
auto const& radio_button = static_cast<HTML::HTMLInputElement const&>(layout_box().dom_node());
|
||||||
|
|
||||||
auto& palette = context.palette();
|
|
||||||
bool enabled = layout_box().dom_node().enabled();
|
bool enabled = layout_box().dom_node().enabled();
|
||||||
auto input_colors = compute_input_colors(palette, computed_values().accent_color());
|
auto input_colors = compute_input_colors(computed_values().color_scheme(), computed_values().accent_color());
|
||||||
|
|
||||||
auto background_color = input_colors.background_color(enabled);
|
auto background_color = input_colors.background_color(enabled);
|
||||||
auto accent = input_colors.accent;
|
auto accent = input_colors.accent;
|
||||||
|
@ -71,7 +70,7 @@ void RadioButtonPaintable::paint(PaintContext& context, PaintPhase phase) const
|
||||||
return input_colors.mid_gray;
|
return input_colors.mid_gray;
|
||||||
auto color = radio_color();
|
auto color = radio_color();
|
||||||
if (being_pressed())
|
if (being_pressed())
|
||||||
color = InputColors::get_shade(color, 0.3f, palette.is_dark());
|
color = InputColors::get_shade(color, 0.3f, computed_values().color_scheme());
|
||||||
return color;
|
return color;
|
||||||
}();
|
}();
|
||||||
|
|
||||||
|
|
|
@ -130,12 +130,6 @@ String ProcessManager::generate_html()
|
||||||
<title>Task Manager</title>
|
<title>Task Manager</title>
|
||||||
<style>
|
<style>
|
||||||
@media (prefers-color-scheme: dark) {
|
@media (prefers-color-scheme: dark) {
|
||||||
/* FIXME: We should be able to remove the HTML style when "color-scheme" is supported */
|
|
||||||
html {
|
|
||||||
background-color: rgb(30, 30, 30);
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
tr:nth-child(even) {
|
tr:nth-child(even) {
|
||||||
background: rgb(57, 57, 57);
|
background: rgb(57, 57, 57);
|
||||||
}
|
}
|
||||||
|
@ -147,6 +141,10 @@ String ProcessManager::generate_html()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
html {
|
||||||
|
color-scheme: light dark;
|
||||||
|
}
|
||||||
|
|
||||||
table {
|
table {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
border-collapse: collapse;
|
border-collapse: collapse;
|
||||||
|
|
|
@ -79,13 +79,6 @@ String highlight_source(URL::URL const& url, URL::URL const& base_url, StringVie
|
||||||
|
|
||||||
constexpr inline StringView HTML_HIGHLIGHTER_STYLE = R"~~~(
|
constexpr inline StringView HTML_HIGHLIGHTER_STYLE = R"~~~(
|
||||||
@media (prefers-color-scheme: dark) {
|
@media (prefers-color-scheme: dark) {
|
||||||
/* FIXME: We should be able to remove the HTML style when "color-scheme" is supported */
|
|
||||||
html {
|
|
||||||
background-color: rgb(30, 30, 30);
|
|
||||||
color: white;
|
|
||||||
counter-reset: line;
|
|
||||||
}
|
|
||||||
|
|
||||||
:root {
|
:root {
|
||||||
--comment-color: lightgreen;
|
--comment-color: lightgreen;
|
||||||
--keyword-color: orangered;
|
--keyword-color: orangered;
|
||||||
|
@ -111,6 +104,10 @@ constexpr inline StringView HTML_HIGHLIGHTER_STYLE = R"~~~(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
html {
|
||||||
|
color-scheme: light dark;
|
||||||
|
}
|
||||||
|
|
||||||
.html {
|
.html {
|
||||||
font-size: 10pt;
|
font-size: 10pt;
|
||||||
font-family: Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
|
font-family: Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
All supported properties and their default values exposed from CSSStyleDeclaration from getComputedStyle:
|
All supported properties and their default values exposed from CSSStyleDeclaration from getComputedStyle:
|
||||||
'cssText': ''
|
'cssText': ''
|
||||||
'length': '212'
|
'length': '213'
|
||||||
'parentRule': 'null'
|
'parentRule': 'null'
|
||||||
'cssFloat': 'none'
|
'cssFloat': 'none'
|
||||||
'WebkitAlignContent': 'normal'
|
'WebkitAlignContent': 'normal'
|
||||||
|
@ -250,6 +250,8 @@ All supported properties and their default values exposed from CSSStyleDeclarati
|
||||||
'clipRule': 'nonzero'
|
'clipRule': 'nonzero'
|
||||||
'clip-rule': 'nonzero'
|
'clip-rule': 'nonzero'
|
||||||
'color': 'rgb(0, 0, 0)'
|
'color': 'rgb(0, 0, 0)'
|
||||||
|
'colorScheme': 'normal'
|
||||||
|
'color-scheme': 'normal'
|
||||||
'columnCount': 'auto'
|
'columnCount': 'auto'
|
||||||
'column-count': 'auto'
|
'column-count': 'auto'
|
||||||
'columnGap': 'normal'
|
'columnGap': 'normal'
|
||||||
|
|
|
@ -7,211 +7,212 @@ All properties associated with getComputedStyle(document.body):
|
||||||
"4": "caption-side",
|
"4": "caption-side",
|
||||||
"5": "clip-rule",
|
"5": "clip-rule",
|
||||||
"6": "color",
|
"6": "color",
|
||||||
"7": "cursor",
|
"7": "color-scheme",
|
||||||
"8": "direction",
|
"8": "cursor",
|
||||||
"9": "fill",
|
"9": "direction",
|
||||||
"10": "fill-opacity",
|
"10": "fill",
|
||||||
"11": "fill-rule",
|
"11": "fill-opacity",
|
||||||
"12": "font-family",
|
"12": "fill-rule",
|
||||||
"13": "font-feature-settings",
|
"13": "font-family",
|
||||||
"14": "font-language-override",
|
"14": "font-feature-settings",
|
||||||
"15": "font-size",
|
"15": "font-language-override",
|
||||||
"16": "font-style",
|
"16": "font-size",
|
||||||
"17": "font-variant-alternates",
|
"17": "font-style",
|
||||||
"18": "font-variant-caps",
|
"18": "font-variant-alternates",
|
||||||
"19": "font-variant-east-asian",
|
"19": "font-variant-caps",
|
||||||
"20": "font-variant-emoji",
|
"20": "font-variant-east-asian",
|
||||||
"21": "font-variant-ligatures",
|
"21": "font-variant-emoji",
|
||||||
"22": "font-variant-numeric",
|
"22": "font-variant-ligatures",
|
||||||
"23": "font-variant-position",
|
"23": "font-variant-numeric",
|
||||||
"24": "font-variation-settings",
|
"24": "font-variant-position",
|
||||||
"25": "font-weight",
|
"25": "font-variation-settings",
|
||||||
"26": "font-width",
|
"26": "font-weight",
|
||||||
"27": "image-rendering",
|
"27": "font-width",
|
||||||
"28": "letter-spacing",
|
"28": "image-rendering",
|
||||||
"29": "line-height",
|
"29": "letter-spacing",
|
||||||
"30": "list-style-image",
|
"30": "line-height",
|
||||||
"31": "list-style-position",
|
"31": "list-style-image",
|
||||||
"32": "list-style-type",
|
"32": "list-style-position",
|
||||||
"33": "math-depth",
|
"33": "list-style-type",
|
||||||
"34": "math-shift",
|
"34": "math-depth",
|
||||||
"35": "math-style",
|
"35": "math-shift",
|
||||||
"36": "pointer-events",
|
"36": "math-style",
|
||||||
"37": "quotes",
|
"37": "pointer-events",
|
||||||
"38": "stroke",
|
"38": "quotes",
|
||||||
"39": "stroke-dasharray",
|
"39": "stroke",
|
||||||
"40": "stroke-dashoffset",
|
"40": "stroke-dasharray",
|
||||||
"41": "stroke-linecap",
|
"41": "stroke-dashoffset",
|
||||||
"42": "stroke-linejoin",
|
"42": "stroke-linecap",
|
||||||
"43": "stroke-miterlimit",
|
"43": "stroke-linejoin",
|
||||||
"44": "stroke-opacity",
|
"44": "stroke-miterlimit",
|
||||||
"45": "stroke-width",
|
"45": "stroke-opacity",
|
||||||
"46": "tab-size",
|
"46": "stroke-width",
|
||||||
"47": "text-align",
|
"47": "tab-size",
|
||||||
"48": "text-anchor",
|
"48": "text-align",
|
||||||
"49": "text-decoration-line",
|
"49": "text-anchor",
|
||||||
"50": "text-indent",
|
"50": "text-decoration-line",
|
||||||
"51": "text-justify",
|
"51": "text-indent",
|
||||||
"52": "text-shadow",
|
"52": "text-justify",
|
||||||
"53": "text-transform",
|
"53": "text-shadow",
|
||||||
"54": "visibility",
|
"54": "text-transform",
|
||||||
"55": "white-space",
|
"55": "visibility",
|
||||||
"56": "word-break",
|
"56": "white-space",
|
||||||
"57": "word-spacing",
|
"57": "word-break",
|
||||||
"58": "word-wrap",
|
"58": "word-spacing",
|
||||||
"59": "writing-mode",
|
"59": "word-wrap",
|
||||||
"60": "align-content",
|
"60": "writing-mode",
|
||||||
"61": "align-items",
|
"61": "align-content",
|
||||||
"62": "align-self",
|
"62": "align-items",
|
||||||
"63": "animation-delay",
|
"63": "align-self",
|
||||||
"64": "animation-direction",
|
"64": "animation-delay",
|
||||||
"65": "animation-duration",
|
"65": "animation-direction",
|
||||||
"66": "animation-fill-mode",
|
"66": "animation-duration",
|
||||||
"67": "animation-iteration-count",
|
"67": "animation-fill-mode",
|
||||||
"68": "animation-name",
|
"68": "animation-iteration-count",
|
||||||
"69": "animation-play-state",
|
"69": "animation-name",
|
||||||
"70": "animation-timing-function",
|
"70": "animation-play-state",
|
||||||
"71": "appearance",
|
"71": "animation-timing-function",
|
||||||
"72": "aspect-ratio",
|
"72": "appearance",
|
||||||
"73": "backdrop-filter",
|
"73": "aspect-ratio",
|
||||||
"74": "background-attachment",
|
"74": "backdrop-filter",
|
||||||
"75": "background-clip",
|
"75": "background-attachment",
|
||||||
"76": "background-color",
|
"76": "background-clip",
|
||||||
"77": "background-image",
|
"77": "background-color",
|
||||||
"78": "background-origin",
|
"78": "background-image",
|
||||||
"79": "background-position-x",
|
"79": "background-origin",
|
||||||
"80": "background-position-y",
|
"80": "background-position-x",
|
||||||
"81": "background-repeat",
|
"81": "background-position-y",
|
||||||
"82": "background-size",
|
"82": "background-repeat",
|
||||||
"83": "border-bottom-color",
|
"83": "background-size",
|
||||||
"84": "border-bottom-left-radius",
|
"84": "border-bottom-color",
|
||||||
"85": "border-bottom-right-radius",
|
"85": "border-bottom-left-radius",
|
||||||
"86": "border-bottom-style",
|
"86": "border-bottom-right-radius",
|
||||||
"87": "border-bottom-width",
|
"87": "border-bottom-style",
|
||||||
"88": "border-left-color",
|
"88": "border-bottom-width",
|
||||||
"89": "border-left-style",
|
"89": "border-left-color",
|
||||||
"90": "border-left-width",
|
"90": "border-left-style",
|
||||||
"91": "border-right-color",
|
"91": "border-left-width",
|
||||||
"92": "border-right-style",
|
"92": "border-right-color",
|
||||||
"93": "border-right-width",
|
"93": "border-right-style",
|
||||||
"94": "border-top-color",
|
"94": "border-right-width",
|
||||||
"95": "border-top-left-radius",
|
"95": "border-top-color",
|
||||||
"96": "border-top-right-radius",
|
"96": "border-top-left-radius",
|
||||||
"97": "border-top-style",
|
"97": "border-top-right-radius",
|
||||||
"98": "border-top-width",
|
"98": "border-top-style",
|
||||||
"99": "bottom",
|
"99": "border-top-width",
|
||||||
"100": "box-shadow",
|
"100": "bottom",
|
||||||
"101": "box-sizing",
|
"101": "box-shadow",
|
||||||
"102": "clear",
|
"102": "box-sizing",
|
||||||
"103": "clip",
|
"103": "clear",
|
||||||
"104": "clip-path",
|
"104": "clip",
|
||||||
"105": "column-count",
|
"105": "clip-path",
|
||||||
"106": "column-gap",
|
"106": "column-count",
|
||||||
"107": "column-span",
|
"107": "column-gap",
|
||||||
"108": "column-width",
|
"108": "column-span",
|
||||||
"109": "content",
|
"109": "column-width",
|
||||||
"110": "content-visibility",
|
"110": "content",
|
||||||
"111": "counter-increment",
|
"111": "content-visibility",
|
||||||
"112": "counter-reset",
|
"112": "counter-increment",
|
||||||
"113": "counter-set",
|
"113": "counter-reset",
|
||||||
"114": "cx",
|
"114": "counter-set",
|
||||||
"115": "cy",
|
"115": "cx",
|
||||||
"116": "display",
|
"116": "cy",
|
||||||
"117": "filter",
|
"117": "display",
|
||||||
"118": "flex-basis",
|
"118": "filter",
|
||||||
"119": "flex-direction",
|
"119": "flex-basis",
|
||||||
"120": "flex-grow",
|
"120": "flex-direction",
|
||||||
"121": "flex-shrink",
|
"121": "flex-grow",
|
||||||
"122": "flex-wrap",
|
"122": "flex-shrink",
|
||||||
"123": "float",
|
"123": "flex-wrap",
|
||||||
"124": "grid-auto-columns",
|
"124": "float",
|
||||||
"125": "grid-auto-flow",
|
"125": "grid-auto-columns",
|
||||||
"126": "grid-auto-rows",
|
"126": "grid-auto-flow",
|
||||||
"127": "grid-column-end",
|
"127": "grid-auto-rows",
|
||||||
"128": "grid-column-start",
|
"128": "grid-column-end",
|
||||||
"129": "grid-row-end",
|
"129": "grid-column-start",
|
||||||
"130": "grid-row-start",
|
"130": "grid-row-end",
|
||||||
"131": "grid-template-areas",
|
"131": "grid-row-start",
|
||||||
"132": "grid-template-columns",
|
"132": "grid-template-areas",
|
||||||
"133": "grid-template-rows",
|
"133": "grid-template-columns",
|
||||||
"134": "height",
|
"134": "grid-template-rows",
|
||||||
"135": "inline-size",
|
"135": "height",
|
||||||
"136": "inset-block-end",
|
"136": "inline-size",
|
||||||
"137": "inset-block-start",
|
"137": "inset-block-end",
|
||||||
"138": "inset-inline-end",
|
"138": "inset-block-start",
|
||||||
"139": "inset-inline-start",
|
"139": "inset-inline-end",
|
||||||
"140": "justify-content",
|
"140": "inset-inline-start",
|
||||||
"141": "justify-items",
|
"141": "justify-content",
|
||||||
"142": "justify-self",
|
"142": "justify-items",
|
||||||
"143": "left",
|
"143": "justify-self",
|
||||||
"144": "margin-block-end",
|
"144": "left",
|
||||||
"145": "margin-block-start",
|
"145": "margin-block-end",
|
||||||
"146": "margin-bottom",
|
"146": "margin-block-start",
|
||||||
"147": "margin-inline-end",
|
"147": "margin-bottom",
|
||||||
"148": "margin-inline-start",
|
"148": "margin-inline-end",
|
||||||
"149": "margin-left",
|
"149": "margin-inline-start",
|
||||||
"150": "margin-right",
|
"150": "margin-left",
|
||||||
"151": "margin-top",
|
"151": "margin-right",
|
||||||
"152": "mask",
|
"152": "margin-top",
|
||||||
"153": "mask-image",
|
"153": "mask",
|
||||||
"154": "mask-type",
|
"154": "mask-image",
|
||||||
"155": "max-height",
|
"155": "mask-type",
|
||||||
"156": "max-inline-size",
|
"156": "max-height",
|
||||||
"157": "max-width",
|
"157": "max-inline-size",
|
||||||
"158": "min-height",
|
"158": "max-width",
|
||||||
"159": "min-inline-size",
|
"159": "min-height",
|
||||||
"160": "min-width",
|
"160": "min-inline-size",
|
||||||
"161": "object-fit",
|
"161": "min-width",
|
||||||
"162": "object-position",
|
"162": "object-fit",
|
||||||
"163": "opacity",
|
"163": "object-position",
|
||||||
"164": "order",
|
"164": "opacity",
|
||||||
"165": "outline-color",
|
"165": "order",
|
||||||
"166": "outline-offset",
|
"166": "outline-color",
|
||||||
"167": "outline-style",
|
"167": "outline-offset",
|
||||||
"168": "outline-width",
|
"168": "outline-style",
|
||||||
"169": "overflow-x",
|
"169": "outline-width",
|
||||||
"170": "overflow-y",
|
"170": "overflow-x",
|
||||||
"171": "padding-block-end",
|
"171": "overflow-y",
|
||||||
"172": "padding-block-start",
|
"172": "padding-block-end",
|
||||||
"173": "padding-bottom",
|
"173": "padding-block-start",
|
||||||
"174": "padding-inline-end",
|
"174": "padding-bottom",
|
||||||
"175": "padding-inline-start",
|
"175": "padding-inline-end",
|
||||||
"176": "padding-left",
|
"176": "padding-inline-start",
|
||||||
"177": "padding-right",
|
"177": "padding-left",
|
||||||
"178": "padding-top",
|
"178": "padding-right",
|
||||||
"179": "position",
|
"179": "padding-top",
|
||||||
"180": "r",
|
"180": "position",
|
||||||
"181": "right",
|
"181": "r",
|
||||||
"182": "rotate",
|
"182": "right",
|
||||||
"183": "row-gap",
|
"183": "rotate",
|
||||||
"184": "rx",
|
"184": "row-gap",
|
||||||
"185": "ry",
|
"185": "rx",
|
||||||
"186": "scale",
|
"186": "ry",
|
||||||
"187": "scrollbar-gutter",
|
"187": "scale",
|
||||||
"188": "scrollbar-width",
|
"188": "scrollbar-gutter",
|
||||||
"189": "stop-color",
|
"189": "scrollbar-width",
|
||||||
"190": "stop-opacity",
|
"190": "stop-color",
|
||||||
"191": "table-layout",
|
"191": "stop-opacity",
|
||||||
"192": "text-decoration-color",
|
"192": "table-layout",
|
||||||
"193": "text-decoration-style",
|
"193": "text-decoration-color",
|
||||||
"194": "text-decoration-thickness",
|
"194": "text-decoration-style",
|
||||||
"195": "text-overflow",
|
"195": "text-decoration-thickness",
|
||||||
"196": "top",
|
"196": "text-overflow",
|
||||||
"197": "transform",
|
"197": "top",
|
||||||
"198": "transform-box",
|
"198": "transform",
|
||||||
"199": "transform-origin",
|
"199": "transform-box",
|
||||||
"200": "transition-delay",
|
"200": "transform-origin",
|
||||||
"201": "transition-duration",
|
"201": "transition-delay",
|
||||||
"202": "transition-property",
|
"202": "transition-duration",
|
||||||
"203": "transition-timing-function",
|
"203": "transition-property",
|
||||||
"204": "translate",
|
"204": "transition-timing-function",
|
||||||
"205": "unicode-bidi",
|
"205": "translate",
|
||||||
"206": "user-select",
|
"206": "unicode-bidi",
|
||||||
"207": "vertical-align",
|
"207": "user-select",
|
||||||
"208": "width",
|
"208": "vertical-align",
|
||||||
"209": "x",
|
"209": "width",
|
||||||
"210": "y",
|
"210": "x",
|
||||||
"211": "z-index"
|
"211": "y",
|
||||||
|
"212": "z-index"
|
||||||
}
|
}
|
||||||
All properties associated with document.body.style by default:
|
All properties associated with document.body.style by default:
|
||||||
{}
|
{}
|
||||||
|
|
|
@ -5,6 +5,7 @@ border-spacing: 0px
|
||||||
caption-side: top
|
caption-side: top
|
||||||
clip-rule: nonzero
|
clip-rule: nonzero
|
||||||
color: rgb(0, 0, 0)
|
color: rgb(0, 0, 0)
|
||||||
|
color-scheme: normal
|
||||||
cursor: auto
|
cursor: auto
|
||||||
direction: ltr
|
direction: ltr
|
||||||
fill: rgb(0, 0, 0)
|
fill: rgb(0, 0, 0)
|
||||||
|
@ -132,7 +133,7 @@ grid-row-start: auto
|
||||||
grid-template-areas: none
|
grid-template-areas: none
|
||||||
grid-template-columns: auto
|
grid-template-columns: auto
|
||||||
grid-template-rows: auto
|
grid-template-rows: auto
|
||||||
height: 2278px
|
height: 2295px
|
||||||
inline-size: auto
|
inline-size: auto
|
||||||
inset-block-end: auto
|
inset-block-end: auto
|
||||||
inset-block-start: auto
|
inset-block-start: auto
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue