Bug 1063162 part 2 - Implement caret-color property. r=dholbert
☠☠ backed out by d9226ec48879 ☠ ☠
authorXidorn Quan <me@upsuper.org>
Thu, 22 Dec 2016 11:04:15 +1100
changeset 371901 148e65bd3f3b156d58836dca9fe8055ae5c2c5d1
parent 371900 5bc2005e01a6db0b2e63a7b0188a90a510a60430
child 371902 4d1a2b1de7f53acaa8cbd41a727efd4637e788a7
push id6996
push userjlorenzo@mozilla.com
push dateMon, 06 Mar 2017 20:48:21 +0000
treeherdermozilla-beta@d89512dab048 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdholbert
bugs1063162
milestone53.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1063162 part 2 - Implement caret-color property. r=dholbert MozReview-Commit-ID: DH7CX1d477R
devtools/shared/css/generated/properties-db.js
layout/generic/nsFrame.cpp
layout/reftests/css-ui/caret-color-01-ref.html
layout/reftests/css-ui/caret-color-01.html
layout/reftests/css-ui/reftest.list
layout/reftests/reftest.list
layout/style/nsCSSPropList.h
layout/style/nsComputedDOMStyle.cpp
layout/style/nsComputedDOMStyle.h
layout/style/nsComputedDOMStylePropertyList.h
layout/style/nsRuleNode.cpp
layout/style/nsStyleStruct.cpp
layout/style/nsStyleStruct.h
layout/style/test/property_database.js
layout/style/test/test_transitions_per_property.html
layout/tools/reftest/reftest-preferences.js
--- a/devtools/shared/css/generated/properties-db.js
+++ b/devtools/shared/css/generated/properties-db.js
@@ -2852,16 +2852,17 @@ exports.CSS_PROPERTIES = {
       "-moz-box-direction",
       "-moz-box-flex",
       "-moz-box-ordinal-group",
       "-moz-box-orient",
       "-moz-box-pack",
       "box-shadow",
       "box-sizing",
       "caption-side",
+      "caret-color",
       "clear",
       "clip",
       "clip-path",
       "clip-rule",
       "color",
       "color-adjust",
       "color-interpolation",
       "color-interpolation-filters",
@@ -5256,16 +5257,38 @@ exports.CSS_PROPERTIES = {
       "initial",
       "left",
       "right",
       "top",
       "top-outside",
       "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": [
       "clear"
     ],
     "supports": [],
     "values": [
       "both",
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -1877,18 +1877,17 @@ nsIFrame::DisplayCaret(nsDisplayListBuil
     return;
 
   aList->AppendNewToTop(new (aBuilder) nsDisplayCaret(aBuilder, this));
 }
 
 nscolor
 nsIFrame::GetCaretColorAt(int32_t aOffset)
 {
-  // Use text color.
-  return StyleColor()->mColor;
+  return StyleColor()->CalcComplexColor(StyleUserInterface()->mCaretColor);
 }
 
 bool
 nsFrame::DisplayBackgroundUnconditional(nsDisplayListBuilder* aBuilder,
                                         const nsDisplayListSet& aLists,
                                         bool aForceBackground)
 {
   // Here we don't try to detect background propagation. Frames that might
new file mode 100644
--- /dev/null
+++ b/layout/reftests/css-ui/caret-color-01-ref.html
@@ -0,0 +1,2 @@
+<!DOCTYPE html>
+<div style="width: 16px; height: 16px; background: green"></div>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/css-ui/caret-color-01.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<style>
+@font-face {
+  font-family: Ahem;
+  src: url(../fonts/Ahem.ttf);
+}
+textarea {
+  caret-color: green;
+  font: 16px/1 Ahem;
+  outline: none;
+  border: 0 none;
+  resize: none;
+  padding: 0;
+  margin: 0;
+}
+</style>
+<textarea autofocus></textarea>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/css-ui/reftest.list
@@ -0,0 +1,1 @@
+pref(ui.caretWidth,16) needs-focus == caret-color-01.html caret-color-01-ref.html
--- a/layout/reftests/reftest.list
+++ b/layout/reftests/reftest.list
@@ -125,16 +125,19 @@ include text-overflow/reftest.list
 include css-selectors/reftest.list
 
 # css sizing
 include css-sizing/reftest.list
 
 # css transitions
 include css-transitions/reftest.list
 
+# css ui
+include css-ui/reftest.list
+
 # css :-moz-ui-invalid
 include css-ui-invalid/reftest.list
 
 # css :-moz-ui-valid
 include css-ui-valid/reftest.list
 
 # css values and units
 include css-valuesandunits/reftest.list
--- a/layout/style/nsCSSPropList.h
+++ b/layout/style/nsCSSPropList.h
@@ -1376,16 +1376,27 @@ CSS_PROP_TABLEBORDER(
     caption_side,
     CaptionSide,
     CSS_PROPERTY_PARSE_VALUE,
     "",
     VARIANT_HK,
     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,
     Clear,
     CSS_PROPERTY_PARSE_VALUE,
     "",
     VARIANT_HK,
     kClearKTable,
--- a/layout/style/nsComputedDOMStyle.cpp
+++ b/layout/style/nsComputedDOMStyle.cpp
@@ -4133,16 +4133,24 @@ nsComputedDOMStyle::DoGetUnicodeBidi()
   RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
   val->SetIdent(
     nsCSSProps::ValueToKeywordEnum(StyleTextReset()->mUnicodeBidi,
                                    nsCSSProps::kUnicodeBidiKTable));
   return val.forget();
 }
 
 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);
 
   const nsStyleUserInterface *ui = StyleUserInterface();
 
   for (const nsCursorImage& item : ui->mCursorImages) {
     RefPtr<nsDOMCSSValueList> itemList = GetROCSSValueList(false);
--- a/layout/style/nsComputedDOMStyle.h
+++ b/layout/style/nsComputedDOMStyle.h
@@ -482,16 +482,17 @@ private:
   already_AddRefed<CSSValue> DoGetScrollSnapTypeY();
   already_AddRefed<CSSValue> DoGetScrollSnapPointsX();
   already_AddRefed<CSSValue> DoGetScrollSnapPointsY();
   already_AddRefed<CSSValue> DoGetScrollSnapDestination();
   already_AddRefed<CSSValue> DoGetScrollSnapCoordinate();
   already_AddRefed<CSSValue> DoGetShapeOutside();
 
   /* User interface properties */
+  already_AddRefed<CSSValue> DoGetCaretColor();
   already_AddRefed<CSSValue> DoGetCursor();
   already_AddRefed<CSSValue> DoGetForceBrokenImageIcon();
   already_AddRefed<CSSValue> DoGetIMEMode();
   already_AddRefed<CSSValue> DoGetUserFocus();
   already_AddRefed<CSSValue> DoGetUserInput();
   already_AddRefed<CSSValue> DoGetUserModify();
   already_AddRefed<CSSValue> DoGetUserSelect();
   already_AddRefed<CSSValue> DoGetWindowDragging();
--- a/layout/style/nsComputedDOMStylePropertyList.h
+++ b/layout/style/nsComputedDOMStylePropertyList.h
@@ -96,16 +96,17 @@ COMPUTED_STYLE_PROP(border_top_right_rad
 COMPUTED_STYLE_PROP(border_top_style,              BorderTopStyle)
 COMPUTED_STYLE_PROP(border_top_width,              BorderTopWidth)
 //// COMPUTED_STYLE_PROP(border_width,             BorderWidth)
 COMPUTED_STYLE_PROP(bottom,                        Bottom)
 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)
 COMPUTED_STYLE_PROP(color_adjust,                  ColorAdjust)
 COMPUTED_STYLE_PROP(column_count,                  ColumnCount)
 COMPUTED_STYLE_PROP(column_fill,                   ColumnFill)
 COMPUTED_STYLE_PROP(column_gap,                    ColumnGap)
 //// COMPUTED_STYLE_PROP(column_rule,              ColumnRule)
--- a/layout/style/nsRuleNode.cpp
+++ b/layout/style/nsRuleNode.cpp
@@ -1134,16 +1134,18 @@ SetComplexColor(const nsCSSValue& aValue
              (UnsetTo == eUnsetInherit && unit == eCSSUnit_Unset)) {
     aConditions.SetUncacheable();
     aResult = aParentColor;
   } else if (unit == eCSSUnit_EnumColor &&
              aValue.GetIntValue() == NS_COLOR_CURRENTCOLOR) {
     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, resultColor, aConditions)) {
       MOZ_ASSERT_UNREACHABLE("Unknown color value");
       return;
     }
     aResult = StyleComplexColor::FromColor(resultColor);
@@ -5286,16 +5288,24 @@ nsRuleNode::ComputeUserInterfaceData(voi
 
   // pointer-events: enum, inherit, initial
   SetValue(*aRuleData->ValueForPointerEvents(), ui->mPointerEvents,
            conditions,
            SETVAL_ENUMERATED | SETVAL_UNSET_INHERIT,
            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)
 }
 
 const void*
 nsRuleNode::ComputeUIResetData(void* aStartStruct,
                                const nsRuleData* aRuleData,
                                nsStyleContext* aContext,
                                nsRuleNode* aHighestNode,
--- a/layout/style/nsStyleStruct.cpp
+++ b/layout/style/nsStyleStruct.cpp
@@ -3968,27 +3968,29 @@ nsCursorImage::operator==(const nsCursor
 }
 
 nsStyleUserInterface::nsStyleUserInterface(StyleStructContext aContext)
   : mUserInput(StyleUserInput::Auto)
   , mUserModify(StyleUserModify::ReadOnly)
   , mUserFocus(StyleUserFocus::None)
   , mPointerEvents(NS_STYLE_POINTER_EVENTS_AUTO)
   , mCursor(NS_STYLE_CURSOR_AUTO)
+  , mCaretColor(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)
 {
   MOZ_COUNT_CTOR(nsStyleUserInterface);
 }
 
 nsStyleUserInterface::~nsStyleUserInterface()
 {
   MOZ_COUNT_DTOR(nsStyleUserInterface);
 }
@@ -4040,16 +4042,20 @@ nsStyleUserInterface::CalcDifference(con
       hint |= nsChangeHint_NeutralChange;
     }
   }
 
   if (mUserFocus != aNewData.mUserFocus) {
     hint |= nsChangeHint_NeutralChange;
   }
 
+  if (mCaretColor != aNewData.mCaretColor) {
+    hint |= nsChangeHint_RepaintFrame;
+  }
+
   return hint;
 }
 
 //-----------------------
 // nsStyleUIReset
 //
 
 nsStyleUIReset::nsStyleUIReset(StyleStructContext aContext)
--- a/layout/style/nsStyleStruct.h
+++ b/layout/style/nsStyleStruct.h
@@ -3388,16 +3388,17 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsSt
 
   mozilla::StyleUserInput   mUserInput;       // [inherited]
   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]
 
   inline uint8_t GetEffectivePointerEvents(nsIFrame* aFrame) const;
 };
 
 struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleXUL
 {
   explicit nsStyleXUL(StyleStructContext aContext);
   nsStyleXUL(const nsStyleXUL& aSource);
--- a/layout/style/test/property_database.js
+++ b/layout/style/test/property_database.js
@@ -2831,16 +2831,28 @@ var gCSSProperties = {
   "caption-side": {
     domProp: "captionSide",
     inherited: true,
     type: CSS_TYPE_LONGHAND,
     initial_values: [ "top" ],
     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,
     type: CSS_TYPE_LONGHAND,
     initial_values: [ "none" ],
     other_values: [ "left", "right", "both" ],
     invalid_values: []
   },
--- a/layout/style/test/test_transitions_per_property.html
+++ b/layout/style/test/test_transitions_per_property.html
@@ -124,16 +124,19 @@ var supported_properties = {
                         test_length_pair_transition_clamped ],
     "border-top-color": [ test_color_transition,
                           test_true_currentcolor_transition ],
     "border-top-width": [ test_length_transition,
                            test_length_clamped ],
     "bottom": [ test_length_transition, test_percent_transition,
                 test_length_percent_calc_transition,
                 test_length_unclamped, test_percent_unclamped ],
+    "caret-color": [ test_color_transition,
+                     test_true_currentcolor_transition,
+                     test_auto_color_transition ],
     "clip": [ test_rect_transition ],
     "clip-path": [ test_clip_path_transition ],
     "color": [ test_color_transition,
                test_currentcolor_transition ],
     "fill": [ test_color_transition,
               test_currentcolor_transition ],
     "fill-opacity" : [ test_float_zeroToOne_transition,
                        // opacity is clamped in computed style
--- a/layout/tools/reftest/reftest-preferences.js
+++ b/layout/tools/reftest/reftest-preferences.js
@@ -3,16 +3,17 @@
 // more interested in testing the behavior of XBL as it works in chrome,
 // so we want this pref to be false.
 user_pref("dom.use_xbl_scopes_for_remote_xul", false);
 user_pref("gfx.color_management.mode", 2);
 user_pref("gfx.color_management.force_srgb", true);
 user_pref("gfx.logging.level", 1);
 user_pref("browser.dom.window.dump.enabled", true);
 user_pref("ui.caretBlinkTime", -1);
+user_pref("ui.caretWidth", 1);
 user_pref("dom.send_after_paint_to_content", true);
 // no slow script dialogs
 user_pref("dom.max_script_run_time", 0);
 user_pref("dom.max_chrome_script_run_time", 0);
 user_pref("hangmonitor.timeout", 0);
 // Ensure autoplay is enabled for all platforms.
 user_pref("media.autoplay.enabled", true);
 // Disable updates