summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorathenian200 <athenian200@outlook.com>2020-09-29 11:31:46 -0500
committerathenian200 <athenian200@outlook.com>2020-10-18 10:04:12 -0500
commit8e3832bacbbef4a549f64df5c978a5672e47ff2e (patch)
tree6a3afb705aa7ae2a9f2be65cd6f5628fcc72131a
parent5ad0a15f6a60e24fb260e4a0d0d8050e42c33114 (diff)
downloaduxp-8e3832bacbbef4a549f64df5c978a5672e47ff2e.tar.gz
Issue #1668 - Part 1: Implement support for caret-color property.
This CSS property allows input carets (that blinking input cursor you see in text fields), to be given a custom color. This was implemented in Firefox 53, and it was such a minor feature that no one ever missed it, but I don't see any harm in implementing this. https://bugzilla.mozilla.org/show_bug.cgi?id=1063162
-rw-r--r--devtools/shared/css/generated/properties-db.js23
-rw-r--r--layout/generic/nsFrame.cpp3
-rw-r--r--layout/style/StyleAnimationValue.cpp12
-rw-r--r--layout/style/StyleComplexColor.h21
-rw-r--r--layout/style/nsCSSPropList.h11
-rw-r--r--layout/style/nsComputedDOMStyle.cpp8
-rw-r--r--layout/style/nsComputedDOMStyle.h1
-rw-r--r--layout/style/nsComputedDOMStylePropertyList.h1
-rw-r--r--layout/style/nsRuleNode.cpp15
-rw-r--r--layout/style/nsStyleStruct.cpp6
-rw-r--r--layout/style/nsStyleStruct.h1
-rw-r--r--layout/style/test/property_database.js12
-rw-r--r--layout/style/test/test_transitions_per_property.html15
13 files changed, 118 insertions, 11 deletions
diff --git a/devtools/shared/css/generated/properties-db.js b/devtools/shared/css/generated/properties-db.js
index 25d9e2d334..cc17feb73f 100644
--- a/devtools/shared/css/generated/properties-db.js
+++ b/devtools/shared/css/generated/properties-db.js
@@ -2872,6 +2872,7 @@ exports.CSS_PROPERTIES = {
"box-shadow",
"box-sizing",
"caption-side",
+ "caret-color",
"clear",
"clip",
"clip-path",
@@ -5277,6 +5278,28 @@ exports.CSS_PROPERTIES = {
"unset"
]
},
+ "caret-color": {
+ "isInherited": true,
+ "subproperties": [
+ "caret-color"
+ ],
+ "supports": [
+ 2
+ ],
+ "values": [
+ "COLOR",
+ "auto",
+ "currentColor",
+ "hsl",
+ "hsla",
+ "inherit",
+ "initial",
+ "rgb",
+ "rgba",
+ "transparent",
+ "unset"
+ ]
+ },
"clear": {
"isInherited": false,
"subproperties": [
diff --git a/layout/generic/nsFrame.cpp b/layout/generic/nsFrame.cpp
index 72923c4b7f..7f67c7d684 100644
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -1831,8 +1831,7 @@ nsIFrame::DisplayCaret(nsDisplayListBuilder* aBuilder,
nscolor
nsIFrame::GetCaretColorAt(int32_t aOffset)
{
- // Use text color.
- return StyleColor()->mColor;
+ return StyleColor()->CalcComplexColor(StyleUserInterface()->mCaretColor);
}
bool
diff --git a/layout/style/StyleAnimationValue.cpp b/layout/style/StyleAnimationValue.cpp
index a0f52b4ea1..d931961d40 100644
--- a/layout/style/StyleAnimationValue.cpp
+++ b/layout/style/StyleAnimationValue.cpp
@@ -4469,8 +4469,12 @@ StyleAnimationValue::ExtractComputedValue(nsCSSPropertyID aProperty,
StyleDataAtOffset<nscolor>(styleStruct, ssOffset));
return true;
case eStyleAnimType_ComplexColor: {
- aComputedValue.SetComplexColorValue(
- StyleDataAtOffset<StyleComplexColor>(styleStruct, ssOffset));
+ auto& color = StyleDataAtOffset<StyleComplexColor>(styleStruct, ssOffset);
+ if (color.mIsAuto) {
+ aComputedValue.SetAutoValue();
+ } else {
+ aComputedValue.SetComplexColorValue(color);
+ }
return true;
}
case eStyleAnimType_PaintServer: {
@@ -4783,7 +4787,9 @@ StyleAnimationValue::SetCurrentColorValue()
void
StyleAnimationValue::SetComplexColorValue(const StyleComplexColor& aColor)
{
- if (aColor.IsCurrentColor()) {
+ if (aColor.mIsAuto) {
+ SetAutoValue();
+ } else if (aColor.IsCurrentColor()) {
SetCurrentColorValue();
} else if (aColor.IsNumericColor()) {
SetColorValue(aColor.mColor);
diff --git a/layout/style/StyleComplexColor.h b/layout/style/StyleComplexColor.h
index 4acf90a56b..6385b57a13 100644
--- a/layout/style/StyleComplexColor.h
+++ b/layout/style/StyleComplexColor.h
@@ -24,16 +24,29 @@ struct StyleComplexColor
{
nscolor mColor;
uint8_t mForegroundRatio;
-
- static StyleComplexColor FromColor(nscolor aColor) { return {aColor, 0}; }
- static StyleComplexColor CurrentColor() { return {NS_RGBA(0, 0, 0, 0), 255}; }
+ // Whether the complex color represents a computed-value time auto
+ // value. This is only a flag indicating that this value should not
+ // be interpolatable with other colors, while other fields still
+ // represents the actual used color of this value.
+ bool mIsAuto;
+
+ static StyleComplexColor FromColor(nscolor aColor) {
+ return {aColor, 0, false};
+ }
+ static StyleComplexColor CurrentColor() {
+ return {NS_RGBA(0, 0, 0, 0), 255, false};
+ }
+ static StyleComplexColor Auto() {
+ return {NS_RGBA(0, 0, 0, 0), 255, true};
+ }
bool IsNumericColor() const { return mForegroundRatio == 0; }
bool IsCurrentColor() const { return mForegroundRatio == 255; }
bool operator==(const StyleComplexColor& aOther) const {
return mForegroundRatio == aOther.mForegroundRatio &&
- (IsCurrentColor() || mColor == aOther.mColor);
+ (IsCurrentColor() || mColor == aOther.mColor) &&
+ mIsAuto == aOther.mIsAuto;
}
bool operator!=(const StyleComplexColor& aOther) const {
return !(*this == aOther);
diff --git a/layout/style/nsCSSPropList.h b/layout/style/nsCSSPropList.h
index 8900192454..4f79db5a55 100644
--- a/layout/style/nsCSSPropList.h
+++ b/layout/style/nsCSSPropList.h
@@ -1394,6 +1394,17 @@ CSS_PROP_TABLEBORDER(
kCaptionSideKTable,
CSS_PROP_NO_OFFSET,
eStyleAnimType_Discrete)
+CSS_PROP_USERINTERFACE(
+ caret-color,
+ caret_color,
+ CaretColor,
+ CSS_PROPERTY_PARSE_VALUE |
+ CSS_PROPERTY_IGNORED_WHEN_COLORS_DISABLED,
+ "",
+ VARIANT_AUTO | VARIANT_HC,
+ nullptr,
+ offsetof(nsStyleUserInterface, mCaretColor),
+ eStyleAnimType_ComplexColor)
CSS_PROP_DISPLAY(
clear,
clear,
diff --git a/layout/style/nsComputedDOMStyle.cpp b/layout/style/nsComputedDOMStyle.cpp
index 1032be6516..c0cc0f84b0 100644
--- a/layout/style/nsComputedDOMStyle.cpp
+++ b/layout/style/nsComputedDOMStyle.cpp
@@ -4189,6 +4189,14 @@ nsComputedDOMStyle::DoGetUnicodeBidi()
}
already_AddRefed<CSSValue>
+nsComputedDOMStyle::DoGetCaretColor()
+{
+ RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
+ SetValueFromComplexColor(val, StyleUserInterface()->mCaretColor);
+ return val.forget();
+}
+
+already_AddRefed<CSSValue>
nsComputedDOMStyle::DoGetCursor()
{
RefPtr<nsDOMCSSValueList> valueList = GetROCSSValueList(true);
diff --git a/layout/style/nsComputedDOMStyle.h b/layout/style/nsComputedDOMStyle.h
index 5af518c2eb..35a6142688 100644
--- a/layout/style/nsComputedDOMStyle.h
+++ b/layout/style/nsComputedDOMStyle.h
@@ -488,6 +488,7 @@ private:
already_AddRefed<CSSValue> DoGetShapeOutside();
/* User interface properties */
+ already_AddRefed<CSSValue> DoGetCaretColor();
already_AddRefed<CSSValue> DoGetCursor();
already_AddRefed<CSSValue> DoGetForceBrokenImageIcon();
already_AddRefed<CSSValue> DoGetIMEMode();
diff --git a/layout/style/nsComputedDOMStylePropertyList.h b/layout/style/nsComputedDOMStylePropertyList.h
index 5572818105..8d4d8e45e2 100644
--- a/layout/style/nsComputedDOMStylePropertyList.h
+++ b/layout/style/nsComputedDOMStylePropertyList.h
@@ -101,6 +101,7 @@ COMPUTED_STYLE_PROP(box_decoration_break, BoxDecorationBreak)
COMPUTED_STYLE_PROP(box_shadow, BoxShadow)
COMPUTED_STYLE_PROP(box_sizing, BoxSizing)
COMPUTED_STYLE_PROP(caption_side, CaptionSide)
+COMPUTED_STYLE_PROP(caret_color, CaretColor)
COMPUTED_STYLE_PROP(clear, Clear)
COMPUTED_STYLE_PROP(clip, Clip)
COMPUTED_STYLE_PROP(color, Color)
diff --git a/layout/style/nsRuleNode.cpp b/layout/style/nsRuleNode.cpp
index 036d97f867..66345390e5 100644
--- a/layout/style/nsRuleNode.cpp
+++ b/layout/style/nsRuleNode.cpp
@@ -1152,13 +1152,16 @@ SetComplexColor(const nsCSSValue& aValue,
aResult = StyleComplexColor::CurrentColor();
} else if (unit == eCSSUnit_ComplexColor) {
aResult = aValue.GetStyleComplexColorValue();
+ } else if (unit == eCSSUnit_Auto) {
+ aResult = StyleComplexColor::Auto();
} else {
+ nscolor resultColor;
if (!SetColor(aValue, aParentColor.mColor, aPresContext,
- nullptr, aResult.mColor, aConditions)) {
+ nullptr, resultColor, aConditions)) {
MOZ_ASSERT_UNREACHABLE("Unknown color value");
return;
}
- aResult.mForegroundRatio = 0;
+ aResult = StyleComplexColor::FromColor(resultColor);
}
}
@@ -5210,6 +5213,14 @@ nsRuleNode::ComputeUserInterfaceData(void* aStartStruct,
parentUI->mPointerEvents,
NS_STYLE_POINTER_EVENTS_AUTO);
+ // caret-color: auto, color, inherit
+ const nsCSSValue* caretColorValue = aRuleData->ValueForCaretColor();
+ SetComplexColor<eUnsetInherit>(*caretColorValue,
+ parentUI->mCaretColor,
+ StyleComplexColor::Auto(),
+ mPresContext,
+ ui->mCaretColor, conditions);
+
COMPUTE_END_INHERITED(UserInterface, ui)
}
diff --git a/layout/style/nsStyleStruct.cpp b/layout/style/nsStyleStruct.cpp
index 3b19a44180..4c610cf085 100644
--- a/layout/style/nsStyleStruct.cpp
+++ b/layout/style/nsStyleStruct.cpp
@@ -4024,6 +4024,7 @@ nsStyleUserInterface::nsStyleUserInterface(StyleStructContext aContext)
, mUserFocus(StyleUserFocus::None)
, mPointerEvents(NS_STYLE_POINTER_EVENTS_AUTO)
, mCursor(NS_STYLE_CURSOR_AUTO)
+ , mCaretColor(StyleComplexColor::Auto())
{
MOZ_COUNT_CTOR(nsStyleUserInterface);
}
@@ -4035,6 +4036,7 @@ nsStyleUserInterface::nsStyleUserInterface(const nsStyleUserInterface& aSource)
, mPointerEvents(aSource.mPointerEvents)
, mCursor(aSource.mCursor)
, mCursorImages(aSource.mCursorImages)
+ , mCaretColor(aSource.mCaretColor)
{
MOZ_COUNT_CTOR(nsStyleUserInterface);
}
@@ -4083,6 +4085,10 @@ nsStyleUserInterface::CalcDifference(const nsStyleUserInterface& aNewData) const
hint |= nsChangeHint_NeutralChange;
}
+ if (mCaretColor != aNewData.mCaretColor) {
+ hint |= nsChangeHint_RepaintFrame;
+ }
+
return hint;
}
diff --git a/layout/style/nsStyleStruct.h b/layout/style/nsStyleStruct.h
index f49cdc43ef..d3fad30934 100644
--- a/layout/style/nsStyleStruct.h
+++ b/layout/style/nsStyleStruct.h
@@ -3414,6 +3414,7 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleUserInterface
uint8_t mCursor; // [inherited] See nsStyleConsts.h
nsTArray<nsCursorImage> mCursorImages; // [inherited] images and coords
+ mozilla::StyleComplexColor mCaretColor; // [inherited]
inline uint8_t GetEffectivePointerEvents(nsIFrame* aFrame) const;
};
diff --git a/layout/style/test/property_database.js b/layout/style/test/property_database.js
index bc43836303..a7014c043b 100644
--- a/layout/style/test/property_database.js
+++ b/layout/style/test/property_database.js
@@ -2837,6 +2837,18 @@ var gCSSProperties = {
other_values: [ "bottom", "left", "right", "top-outside", "bottom-outside" ],
invalid_values: []
},
+ "caret-color": {
+ domProp: "caretColor",
+ inherited: true,
+ type: CSS_TYPE_LONGHAND,
+ prerequisites: { "color": "black" },
+ // Though "auto" is an independent computed-value time keyword value,
+ // it is not distinguishable from currentcolor because getComputedStyle
+ // always returns used value for <color>.
+ initial_values: [ "auto", "currentcolor", "black", "rgb(0,0,0)" ],
+ other_values: [ "green", "transparent", "rgba(128,128,128,.5)", "#123" ],
+ invalid_values: [ "#0", "#00", "#00000", "cc00ff" ]
+ },
"clear": {
domProp: "clear",
inherited: false,
diff --git a/layout/style/test/test_transitions_per_property.html b/layout/style/test/test_transitions_per_property.html
index 29e2ae24c2..f188f4f6fb 100644
--- a/layout/style/test/test_transitions_per_property.html
+++ b/layout/style/test/test_transitions_per_property.html
@@ -1373,6 +1373,21 @@ function test_true_currentcolor_transition(prop, get_color=(x => x), is_shorthan
div.style.removeProperty("color");
}
+function test_auto_color_transition(prop, get_color=(x => x), is_shorthand=false) {
+ const msg_prefix = `color-valued property ${prop}: `;
+ const test_color = "rgb(51, 102, 153)";
+ div.style.setProperty("transition-property", "none", "");
+ div.style.setProperty(prop, "auto", "");
+ let used_value_of_auto = get_color(cs.getPropertyValue(prop));
+ isnot(used_value_of_auto, test_color,
+ msg_prefix + "ensure used auto value is different than our test color");
+
+ div.style.setProperty("transition-property", prop, "");
+ div.style.setProperty(prop, test_color, "");
+ is(get_color(cs.getPropertyValue(prop)), test_color,
+ msg_prefix + "not interpolatable between auto and rgb color");
+}
+
function get_color_from_shorthand_value(value) {
var m = value.match(/rgba?\([^, ]*, [^, ]*, [^, ]*(?:, [^, ]*)?\)/);
isnot(m, null, "shorthand property value should contain color");