diff options
author | athenian200 <athenian200@outlook.com> | 2020-09-29 11:31:46 -0500 |
---|---|---|
committer | athenian200 <athenian200@outlook.com> | 2020-10-18 10:04:12 -0500 |
commit | 8e3832bacbbef4a549f64df5c978a5672e47ff2e (patch) | |
tree | 6a3afb705aa7ae2a9f2be65cd6f5628fcc72131a | |
parent | 5ad0a15f6a60e24fb260e4a0d0d8050e42c33114 (diff) | |
download | UXP-8e3832bacbbef4a549f64df5c978a5672e47ff2e.tar UXP-8e3832bacbbef4a549f64df5c978a5672e47ff2e.tar.gz UXP-8e3832bacbbef4a549f64df5c978a5672e47ff2e.tar.lz UXP-8e3832bacbbef4a549f64df5c978a5672e47ff2e.tar.xz UXP-8e3832bacbbef4a549f64df5c978a5672e47ff2e.zip |
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.js | 23 | ||||
-rw-r--r-- | layout/generic/nsFrame.cpp | 3 | ||||
-rw-r--r-- | layout/style/StyleAnimationValue.cpp | 12 | ||||
-rw-r--r-- | layout/style/StyleComplexColor.h | 21 | ||||
-rw-r--r-- | layout/style/nsCSSPropList.h | 11 | ||||
-rw-r--r-- | layout/style/nsComputedDOMStyle.cpp | 8 | ||||
-rw-r--r-- | layout/style/nsComputedDOMStyle.h | 1 | ||||
-rw-r--r-- | layout/style/nsComputedDOMStylePropertyList.h | 1 | ||||
-rw-r--r-- | layout/style/nsRuleNode.cpp | 15 | ||||
-rw-r--r-- | layout/style/nsStyleStruct.cpp | 6 | ||||
-rw-r--r-- | layout/style/nsStyleStruct.h | 1 | ||||
-rw-r--r-- | layout/style/test/property_database.js | 12 | ||||
-rw-r--r-- | layout/style/test/test_transitions_per_property.html | 15 |
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 25d9e2d33..cc17feb73 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 72923c4b7..7f67c7d68 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 a0f52b4ea..d931961d4 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 4acf90a56..6385b57a1 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 890019245..4f79db5a5 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 1032be651..c0cc0f84b 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 5af518c2e..35a614268 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 557281810..8d4d8e45e 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 036d97f86..66345390e 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 3b19a4418..4c610cf08 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 f49cdc43e..d3fad3093 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 bc4383630..a7014c043 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 29e2ae24c..f188f4f6f 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"); |