--- a/gfx/src/nsITheme.h
+++ b/gfx/src/nsITheme.h
@@ -19,16 +19,17 @@ class gfxContext;
class nsAttrValue;
class nsPresContext;
class nsDeviceContext;
class nsIFrame;
class nsAtom;
class nsIWidget;
namespace mozilla {
+class ComputedStyle;
namespace layers {
class StackingContextHelper;
class WebRenderLayerManager;
}
namespace wr {
class DisplayListBuilder;
class IpcResourceUpdateQueue;
}
@@ -68,16 +69,24 @@ public:
*/
NS_IMETHOD DrawWidgetBackground(gfxContext* aContext,
nsIFrame* aFrame,
uint8_t aWidgetType,
const nsRect& aRect,
const nsRect& aDirtyRect) = 0;
/**
+ * Get the used color of the given widget when it's specified as auto.
+ * It's currently only used for scrollbar-*-color properties.
+ */
+ virtual nscolor GetWidgetAutoColor(mozilla::ComputedStyle* aStyle,
+ uint8_t aWidgetType)
+ { return NS_RGB(0, 0, 0); }
+
+ /**
* Create WebRender commands for the theme background.
* @return true if the theme knows how to create WebRender commands for the
* given widget type, false if DrawWidgetBackground need sto be called
* instead.
*/
virtual bool CreateWebRenderCommandsForWidget(mozilla::wr::DisplayListBuilder& aBuilder,
mozilla::wr::IpcResourceUpdateQueue& aResources,
const mozilla::layers::StackingContextHelper& aSc,
--- a/layout/style/nsComputedDOMStyle.cpp
+++ b/layout/style/nsComputedDOMStyle.cpp
@@ -1176,16 +1176,42 @@ nsComputedDOMStyle::SetToRGBAColor(nsROC
void
nsComputedDOMStyle::SetValueFromComplexColor(nsROCSSPrimitiveValue* aValue,
const StyleComplexColor& aColor)
{
SetToRGBAColor(aValue, aColor.CalcColor(mComputedStyle));
}
+void
+nsComputedDOMStyle::SetValueForWidgetColor(nsROCSSPrimitiveValue* aValue,
+ const StyleComplexColor& aColor,
+ uint8_t aWidgetType)
+{
+ if (!aColor.mIsAuto) {
+ SetToRGBAColor(aValue, aColor.CalcColor(mComputedStyle));
+ return;
+ }
+ nsPresContext* presContext = mPresShell->GetPresContext();
+ MOZ_ASSERT(presContext);
+ if (nsContentUtils::ShouldResistFingerprinting(presContext->GetDocShell())) {
+ // Return transparent when resisting fingerprinting.
+ SetToRGBAColor(aValue, NS_RGBA(0, 0, 0, 0));
+ return;
+ }
+ if (nsITheme* theme = presContext->GetTheme()) {
+ nscolor color = theme->GetWidgetAutoColor(mComputedStyle, aWidgetType);
+ SetToRGBAColor(aValue, color);
+ } else {
+ // If we don't have theme, we don't know what value it should be,
+ // just give it a transparent fallback.
+ SetToRGBAColor(aValue, NS_RGBA(0, 0, 0, 0));
+ }
+}
+
already_AddRefed<CSSValue>
nsComputedDOMStyle::DoGetColor()
{
RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
SetToRGBAColor(val, StyleColor()->mColor);
return val.forget();
}
@@ -3767,16 +3793,34 @@ nsComputedDOMStyle::DoGetScrollSnapCoord
SetValueToPosition(sd->mScrollSnapCoordinate[i], itemList);
valueList->AppendCSSValue(itemList.forget());
}
return valueList.forget();
}
}
already_AddRefed<CSSValue>
+nsComputedDOMStyle::DoGetScrollbarFaceColor()
+{
+ RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
+ SetValueForWidgetColor(val, StyleUserInterface()->mScrollbarFaceColor,
+ NS_THEME_SCROLLBARTHUMB_VERTICAL);
+ return val.forget();
+}
+
+already_AddRefed<CSSValue>
+nsComputedDOMStyle::DoGetScrollbarTrackColor()
+{
+ RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
+ SetValueForWidgetColor(val, StyleUserInterface()->mScrollbarTrackColor,
+ NS_THEME_SCROLLBAR_VERTICAL);
+ return val.forget();
+}
+
+already_AddRefed<CSSValue>
nsComputedDOMStyle::DoGetOutlineWidth()
{
RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
const nsStyleOutline* outline = StyleOutline();
nscoord width;
if (outline->mOutlineStyle == NS_STYLE_BORDER_STYLE_NONE) {
--- a/layout/style/nsComputedDOMStyle.h
+++ b/layout/style/nsComputedDOMStyle.h
@@ -504,16 +504,18 @@ private:
already_AddRefed<CSSValue> DoGetOverscrollBehaviorY();
already_AddRefed<CSSValue> DoGetScrollSnapType();
already_AddRefed<CSSValue> DoGetScrollSnapTypeX();
already_AddRefed<CSSValue> DoGetScrollSnapTypeY();
already_AddRefed<CSSValue> DoGetScrollSnapPointsX();
already_AddRefed<CSSValue> DoGetScrollSnapPointsY();
already_AddRefed<CSSValue> DoGetScrollSnapDestination();
already_AddRefed<CSSValue> DoGetScrollSnapCoordinate();
+ already_AddRefed<CSSValue> DoGetScrollbarFaceColor();
+ already_AddRefed<CSSValue> DoGetScrollbarTrackColor();
already_AddRefed<CSSValue> DoGetShapeImageThreshold();
already_AddRefed<CSSValue> DoGetShapeMargin();
already_AddRefed<CSSValue> DoGetShapeOutside();
/* User interface properties */
already_AddRefed<CSSValue> DoGetCaretColor();
already_AddRefed<CSSValue> DoGetCursor();
already_AddRefed<CSSValue> DoGetForceBrokenImageIcon();
@@ -616,16 +618,19 @@ private:
/* Custom properties */
already_AddRefed<CSSValue> DoGetCustomProperty(const nsAString& aPropertyName);
/* Helper functions */
void SetToRGBAColor(nsROCSSPrimitiveValue* aValue, nscolor aColor);
void SetValueFromComplexColor(nsROCSSPrimitiveValue* aValue,
const mozilla::StyleComplexColor& aColor);
+ void SetValueForWidgetColor(nsROCSSPrimitiveValue* aValue,
+ const mozilla::StyleComplexColor& aColor,
+ uint8_t aWidgetType);
void SetValueToStyleImage(const nsStyleImage& aStyleImage,
nsROCSSPrimitiveValue* aValue);
void SetValueToPositionCoord(const mozilla::Position::Coord& aCoord,
nsROCSSPrimitiveValue* aValue);
void SetValueToPosition(const mozilla::Position& aPosition,
nsDOMCSSValueList* aValueList);
void SetValueToURLValue(const mozilla::css::URLValueData* aURL,
nsROCSSPrimitiveValue* aValue);
--- a/layout/style/nsComputedDOMStylePropertyList.h
+++ b/layout/style/nsComputedDOMStylePropertyList.h
@@ -228,16 +228,18 @@ COMPUTED_STYLE_PROP(ruby_position,
COMPUTED_STYLE_PROP(scale, Scale)
COMPUTED_STYLE_PROP(scroll_behavior, ScrollBehavior)
COMPUTED_STYLE_PROP(scroll_snap_coordinate, ScrollSnapCoordinate)
COMPUTED_STYLE_PROP(scroll_snap_destination, ScrollSnapDestination)
COMPUTED_STYLE_PROP(scroll_snap_points_x, ScrollSnapPointsX)
COMPUTED_STYLE_PROP(scroll_snap_points_y, ScrollSnapPointsY)
COMPUTED_STYLE_PROP(scroll_snap_type_x, ScrollSnapTypeX)
COMPUTED_STYLE_PROP(scroll_snap_type_y, ScrollSnapTypeY)
+COMPUTED_STYLE_PROP(scrollbar_face_color, ScrollbarFaceColor)
+COMPUTED_STYLE_PROP(scrollbar_track_color, ScrollbarTrackColor)
COMPUTED_STYLE_PROP(shape_image_threshold, ShapeImageThreshold)
COMPUTED_STYLE_PROP(shape_margin, ShapeMargin)
COMPUTED_STYLE_PROP(shape_outside, ShapeOutside)
//// COMPUTED_STYLE_PROP(size, Size)
COMPUTED_STYLE_PROP(table_layout, TableLayout)
COMPUTED_STYLE_PROP(text_align, TextAlign)
COMPUTED_STYLE_PROP(text_align_last, TextAlignLast)
COMPUTED_STYLE_PROP(text_combine_upright, TextCombineUpright)
--- a/layout/style/nsStyleStruct.cpp
+++ b/layout/style/nsStyleStruct.cpp
@@ -4614,28 +4614,32 @@ nsCursorImage::operator==(const nsCursor
nsStyleUserInterface::nsStyleUserInterface(const nsPresContext* aContext)
: mUserInput(StyleUserInput::Auto)
, mUserModify(StyleUserModify::ReadOnly)
, mUserFocus(StyleUserFocus::None)
, mPointerEvents(NS_STYLE_POINTER_EVENTS_AUTO)
, mCursor(NS_STYLE_CURSOR_AUTO)
, mCaretColor(StyleComplexColor::Auto())
+ , mScrollbarFaceColor(StyleComplexColor::Auto())
+ , mScrollbarTrackColor(StyleComplexColor::Auto())
{
MOZ_COUNT_CTOR(nsStyleUserInterface);
}
nsStyleUserInterface::nsStyleUserInterface(const nsStyleUserInterface& aSource)
: mUserInput(aSource.mUserInput)
, mUserModify(aSource.mUserModify)
, mUserFocus(aSource.mUserFocus)
, mPointerEvents(aSource.mPointerEvents)
, mCursor(aSource.mCursor)
, mCursorImages(aSource.mCursorImages)
, mCaretColor(aSource.mCaretColor)
+ , mScrollbarFaceColor(aSource.mScrollbarFaceColor)
+ , mScrollbarTrackColor(aSource.mScrollbarTrackColor)
{
MOZ_COUNT_CTOR(nsStyleUserInterface);
}
nsStyleUserInterface::~nsStyleUserInterface()
{
MOZ_COUNT_DTOR(nsStyleUserInterface);
}
@@ -4694,17 +4698,19 @@ nsStyleUserInterface::CalcDifference(con
hint |= nsChangeHint_NeutralChange;
}
}
if (mUserFocus != aNewData.mUserFocus) {
hint |= nsChangeHint_NeutralChange;
}
- if (mCaretColor != aNewData.mCaretColor) {
+ if (mCaretColor != aNewData.mCaretColor ||
+ mScrollbarFaceColor != aNewData.mScrollbarFaceColor ||
+ mScrollbarTrackColor != aNewData.mScrollbarTrackColor) {
hint |= nsChangeHint_RepaintFrame;
}
return hint;
}
//-----------------------
// nsStyleUIReset
--- a/layout/style/nsStyleStruct.h
+++ b/layout/style/nsStyleStruct.h
@@ -2886,17 +2886,25 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsSt
mozilla::StyleUserModify mUserModify; // [inherited] (modify-content)
mozilla::StyleUserFocus mUserFocus; // [inherited] (auto-select)
uint8_t mPointerEvents; // [inherited] see nsStyleConsts.h
uint8_t mCursor; // [inherited] See nsStyleConsts.h
nsTArray<nsCursorImage> mCursorImages; // [inherited] images and coords
mozilla::StyleComplexColor mCaretColor; // [inherited]
+ mozilla::StyleComplexColor mScrollbarFaceColor; // [inherited]
+ mozilla::StyleComplexColor mScrollbarTrackColor; // [inherited]
+
inline uint8_t GetEffectivePointerEvents(nsIFrame* aFrame) const;
+
+ bool HasCustomScrollbars() const
+ {
+ return !mScrollbarFaceColor.mIsAuto || !mScrollbarTrackColor.mIsAuto;
+ }
};
struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleXUL
{
explicit nsStyleXUL(const nsPresContext* aContext);
nsStyleXUL(const nsStyleXUL& aSource);
~nsStyleXUL();
void FinishStyle(nsPresContext*, const nsStyleXUL*) {}
--- a/layout/style/test/property_database.js
+++ b/layout/style/test/property_database.js
@@ -8358,8 +8358,27 @@ if (IsCSSPropertyPrefEnabled("layout.css
if (IsCSSPropertyPrefEnabled("layout.css.prefixes.gradients")) {
gCSSProperties["background-image"].invalid_values.push(
"-moz-linear-gradient(unset, 10px 10px, from(blue))",
"-moz-linear-gradient(unset, 10px 10px, blue 0)",
"-moz-repeating-linear-gradient(unset, 10px 10px, blue 0)",
);
}
}
+
+if (IsCSSPropertyPrefEnabled("layout.css.scrollbar-colors.enabled")) {
+ gCSSProperties["scrollbar-face-color"] = {
+ domProp: "scrollbarFaceColor",
+ inherited: true,
+ type: CSS_TYPE_LONGHAND,
+ initial_values: [ "auto" ],
+ other_values: [ "red", "blue", "#ffff00" ],
+ invalid_values: [ "ffff00" ]
+ };
+ gCSSProperties["scrollbar-track-color"] = {
+ domProp: "scrollbarTrackColor",
+ inherited: true,
+ type: CSS_TYPE_LONGHAND,
+ initial_values: [ "auto" ],
+ other_values: [ "red", "blue", "#ffff00" ],
+ invalid_values: [ "ffff00" ]
+ };
+}
--- a/layout/style/test/test_transitions_per_property.html
+++ b/layout/style/test/test_transitions_per_property.html
@@ -331,16 +331,29 @@ if (IsCSSPropertyPrefEnabled("layout.css
if (IsCSSPropertyPrefEnabled("layout.css.individual-transform.enabled") &&
SpecialPowers.DOMWindowUtils.isStyledByServo) {
supported_properties["rotate"] = [ test_rotate_transition ];
supported_properties["scale"] = [ test_scale_transition ];
supported_properties["translate"] = [ test_translate_transition ];
}
+if (IsCSSPropertyPrefEnabled("layout.css.scrollbar-colors.enabled")) {
+ supported_properties["scrollbar-face-color"] = [
+ test_color_transition,
+ test_true_currentcolor_transition,
+ test_auto_color_transition,
+ ];
+ supported_properties["scrollbar-track-color"] = [
+ test_color_transition,
+ test_true_currentcolor_transition,
+ test_auto_color_transition,
+ ];
+}
+
var div = document.getElementById("display");
var OMTAdiv = document.getElementById("transformTest");
var cs = getComputedStyle(div, "");
var OMTACs = getComputedStyle(OMTAdiv, "");
var winUtils = SpecialPowers.getDOMWindowUtils(window);
function computeMatrix(v) {
div.style.setProperty("transform", v, "");
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -2837,16 +2837,19 @@ pref("layout.css.initial-letter.enabled"
pref("layout.css.mix-blend-mode.enabled", true);
// Is support for isolation enabled?
pref("layout.css.isolation.enabled", true);
// Is support for CSS Filters enabled?
pref("layout.css.filters.enabled", true);
+// Is support for CSS Scrollbar color properties enabled?
+pref("layout.css.scrollbar-colors.enabled", false);
+
// Set the threshold distance in CSS pixels below which scrolling will snap to
// an edge, when scroll snapping is set to "proximity".
pref("layout.css.scroll-snap.proximity-threshold", 200);
// When selecting the snap point for CSS scroll snapping, the velocity of the
// scroll frame is clamped to this speed, in CSS pixels / s.
pref("layout.css.scroll-snap.prediction-max-velocity", 2000);
--- a/servo/components/style/properties/gecko.mako.rs
+++ b/servo/components/style/properties/gecko.mako.rs
@@ -1436,16 +1436,17 @@ impl Clone for ${style_struct.gecko_stru
<%
style_struct = next(x for x in data.style_structs if x.name == style_struct_name)
longhands = [x for x in style_struct.longhands
if not (skip_longhands == "*" or x.name in skip_longhands.split())]
# Types used with predefined_type()-defined properties that we can auto-generate.
predefined_types = {
"Color": impl_color,
+ "ColorOrAuto": impl_color,
"GreaterThanOrEqualToOneNumber": impl_simple,
"Integer": impl_simple,
"length::LengthOrAuto": impl_style_coord,
"length::LengthOrNormal": impl_style_coord,
"length::NonNegativeLengthOrAuto": impl_style_coord,
"length::NonNegativeLengthOrPercentageOrNormal": impl_style_coord,
"FlexBasis": impl_style_coord,
"Length": impl_absolute_length,
@@ -5258,17 +5259,17 @@ clip-path
pub fn clone_color(&self) -> longhands::color::computed_value::T {
let color = ${get_gecko_property("mColor")} as u32;
convert_nscolor_to_rgba(color)
}
</%self:impl_trait>
<%self:impl_trait style_struct_name="InheritedUI"
- skip_longhands="cursor caret-color">
+ skip_longhands="cursor">
pub fn set_cursor(&mut self, v: longhands::cursor::computed_value::T) {
use style_traits::cursor::CursorKind;
self.gecko.mCursor = match v.keyword {
CursorKind::Auto => structs::NS_STYLE_CURSOR_AUTO,
CursorKind::None => structs::NS_STYLE_CURSOR_NONE,
CursorKind::Default => structs::NS_STYLE_CURSOR_DEFAULT,
CursorKind::Pointer => structs::NS_STYLE_CURSOR_POINTER,
@@ -5405,18 +5406,16 @@ clip-path
None
};
CursorImage { url, hotspot }
}).collect::<Vec<_>>().into_boxed_slice();
longhands::cursor::computed_value::T { images, keyword }
}
-
- <%call expr="impl_color('caret_color', 'mCaretColor')"></%call>
</%self:impl_trait>
<%self:impl_trait style_struct_name="Column"
skip_longhands="column-count column-rule-width">
#[allow(unused_unsafe)]
pub fn set_column_count(&mut self, v: longhands::column_count::computed_value::T) {
use gecko_bindings::structs::{NS_STYLE_COLUMN_COUNT_AUTO, nsStyleColumn_kMaxColumnCount};
--- a/servo/components/style/properties/longhand/inherited_ui.mako.rs
+++ b/servo/components/style/properties/longhand/inherited_ui.mako.rs
@@ -45,8 +45,30 @@
"caret-color",
"ColorOrAuto",
"Either::Second(Auto)",
spec="https://drafts.csswg.org/css-ui/#caret-color",
animation_value_type="AnimatedCaretColor",
ignored_when_colors_disabled=True,
products="gecko",
)}
+
+// Only scrollbar-face-color and scrollbar-track-color are added here.
+// These two are the only common parts of scrollbar among Windows and
+// macOS. We may or may not want to provide other properties to allow
+// finer-grain control.
+//
+// NOTE The syntax in spec is currently `normal | <color>`, but I think
+// reusing `auto | <color>` as `caret-color` makes more sense. See
+// https://github.com/w3c/csswg-drafts/issues/2660
+% for part in ["face", "track"]:
+${helpers.predefined_type(
+ "scrollbar-%s-color" % part,
+ "ColorOrAuto",
+ "Either::Second(Auto)",
+ spec="https://drafts.csswg.org/css-scrollbars-1/#scrollbar-color-properties",
+ gecko_pref="layout.css.scrollbar-colors.enabled",
+ animation_value_type="ColorOrAuto",
+ ignored_when_colors_disabled=True,
+ enabled_in="chrome",
+ products="gecko",
+)}
+% endfor