Title: [283560] trunk/Source
Revision
283560
Author
[email protected]
Date
2021-10-05 11:15:47 -0700 (Tue, 05 Oct 2021)

Log Message

Add an alternate style for form controls, and implement it for checkboxes and radio buttons
https://bugs.webkit.org/show_bug.cgi?id=231160

Reviewed by Sam Weinig.

* rendering/RenderThemeIOS.h:
* rendering/RenderThemeIOS.mm:
(WebCore::RenderThemeIOS::checkboxRadioBackgroundColor):
Add alternate background colors. Currently these are not specified as
semantic colors, so we inline the values.

(WebCore::RenderThemeIOS::checkboxRadioBackgroundGradient):
Add a gradient fill for checkbox and radio button backgrounds.

(WebCore::RenderThemeIOS::paintCheckboxRadioInnerShadow):
Add two inner shadows (really, a shadow and a glow) to the checkbox and radio button.

(WebCore::RenderThemeIOS::paintCheckbox):
(WebCore::RenderThemeIOS::paintRadio):
Drop the border and use a filled background and inner shadows instead,
when the setting is enabled.

* Scripts/Preferences/WebPreferences.yaml:

* Shared/WebPreferencesDefaultValues.cpp:
(WebKit::defaultAlternateFormControlDesignEnabled):
* Shared/WebPreferencesDefaultValues.h:

Modified Paths

Diff

Modified: trunk/Source/WTF/ChangeLog (283559 => 283560)


--- trunk/Source/WTF/ChangeLog	2021-10-05 18:12:24 UTC (rev 283559)
+++ trunk/Source/WTF/ChangeLog	2021-10-05 18:15:47 UTC (rev 283560)
@@ -1,3 +1,12 @@
+2021-10-05  Tim Horton  <[email protected]>
+
+        Add an alternate style for form controls, and implement it for checkboxes and radio buttons
+        https://bugs.webkit.org/show_bug.cgi?id=231160
+
+        Reviewed by Sam Weinig.
+
+        * Scripts/Preferences/WebPreferences.yaml:
+
 2021-10-05  David Kilzer  <[email protected]>
 
         Follow-up #2: WTF::RetainPtr<> allows assignment of two pointer types that are not assignable

Modified: trunk/Source/WTF/Scripts/Preferences/WebPreferences.yaml (283559 => 283560)


--- trunk/Source/WTF/Scripts/Preferences/WebPreferences.yaml	2021-10-05 18:12:24 UTC (rev 283559)
+++ trunk/Source/WTF/Scripts/Preferences/WebPreferences.yaml	2021-10-05 18:15:47 UTC (rev 283560)
@@ -232,6 +232,17 @@
     WebCore:
       default: true
 
+AlternateFormControlDesignEnabled:
+  type: bool
+  condition: PLATFORM(IOS_FAMILY)
+  defaultValue:
+    WebKitLegacy:
+      default: false
+    WebKit:
+      default: WebKit::defaultAlternateFormControlDesignEnabled()
+    WebCore:
+      default: false
+
 AlwaysUseAcceleratedOverflowScroll:
   type: bool
   defaultValue:

Modified: trunk/Source/WebCore/ChangeLog (283559 => 283560)


--- trunk/Source/WebCore/ChangeLog	2021-10-05 18:12:24 UTC (rev 283559)
+++ trunk/Source/WebCore/ChangeLog	2021-10-05 18:15:47 UTC (rev 283560)
@@ -1,3 +1,27 @@
+2021-10-05  Tim Horton  <[email protected]>
+
+        Add an alternate style for form controls, and implement it for checkboxes and radio buttons
+        https://bugs.webkit.org/show_bug.cgi?id=231160
+
+        Reviewed by Sam Weinig.
+
+        * rendering/RenderThemeIOS.h:
+        * rendering/RenderThemeIOS.mm:
+        (WebCore::RenderThemeIOS::checkboxRadioBackgroundColor):
+        Add alternate background colors. Currently these are not specified as
+        semantic colors, so we inline the values.
+
+        (WebCore::RenderThemeIOS::checkboxRadioBackgroundGradient):
+        Add a gradient fill for checkbox and radio button backgrounds.
+
+        (WebCore::RenderThemeIOS::paintCheckboxRadioInnerShadow):
+        Add two inner shadows (really, a shadow and a glow) to the checkbox and radio button.
+
+        (WebCore::RenderThemeIOS::paintCheckbox):
+        (WebCore::RenderThemeIOS::paintRadio):
+        Drop the border and use a filled background and inner shadows instead,
+        when the setting is enabled.
+
 2021-10-05  Simon Fraser  <[email protected]>
 
         REGRESSION (r283335): Momentum scrolling is no longer locked to an axis

Modified: trunk/Source/WebCore/rendering/RenderThemeIOS.h (283559 => 283560)


--- trunk/Source/WebCore/rendering/RenderThemeIOS.h	2021-10-05 18:12:24 UTC (rev 283559)
+++ trunk/Source/WebCore/rendering/RenderThemeIOS.h	2021-10-05 18:15:47 UTC (rev 283560)
@@ -116,12 +116,15 @@
 
 #if ENABLE(IOS_FORM_CONTROL_REFRESH)
     Color checkboxRadioBorderColor(OptionSet<ControlStates::States>, OptionSet<StyleColor::Options>);
-    Color checkboxRadioBackgroundColor(OptionSet<ControlStates::States>, OptionSet<StyleColor::Options>);
+    Color checkboxRadioBackgroundColor(bool useAlternateDesign, OptionSet<ControlStates::States>, OptionSet<StyleColor::Options>);
+    RefPtr<Gradient> checkboxRadioBackgroundGradient(const FloatRect&, OptionSet<ControlStates::States>);
     Color checkboxRadioIndicatorColor(OptionSet<ControlStates::States>, OptionSet<StyleColor::Options>);
 
     bool paintCheckbox(const RenderObject&, const PaintInfo&, const FloatRect&) override;
     bool paintRadio(const RenderObject&, const PaintInfo&, const FloatRect&) override;
 
+    void paintCheckboxRadioInnerShadow(const PaintInfo&, const FloatRoundedRect&, OptionSet<ControlStates::States>);
+
     Seconds animationRepeatIntervalForProgressBar(const RenderProgress&) const final;
 
     bool supportsMeter(ControlPart, const HTMLMeterElement&) const final;

Modified: trunk/Source/WebCore/rendering/RenderThemeIOS.mm (283559 => 283560)


--- trunk/Source/WebCore/rendering/RenderThemeIOS.mm	2021-10-05 18:12:24 UTC (rev 283559)
+++ trunk/Source/WebCore/rendering/RenderThemeIOS.mm	2021-10-05 18:15:47 UTC (rev 283560)
@@ -2058,20 +2058,46 @@
     return defaultBorderColor;
 }
 
-Color RenderThemeIOS::checkboxRadioBackgroundColor(OptionSet<ControlStates::States> states, OptionSet<StyleColor::Options> styleColorOptions)
+Color RenderThemeIOS::checkboxRadioBackgroundColor(bool useAlternateDesign, OptionSet<ControlStates::States> states, OptionSet<StyleColor::Options> styleColorOptions)
 {
-    bool empty = !states.containsAny({ ControlStates::States::Checked, ControlStates::States::Indeterminate });
+    bool isEmpty = !states.containsAny({ ControlStates::States::Checked, ControlStates::States::Indeterminate });
+    bool isEnabled = states.contains(ControlStates::States::Enabled);
+    bool isPressed = states.contains(ControlStates::States::Pressed);
 
-    if (!states.contains(ControlStates::States::Enabled))
-        return systemColor(empty ? CSSValueWebkitControlBackground : CSSValueAppleSystemOpaqueTertiaryFill, styleColorOptions);
+    if (useAlternateDesign) {
+        // FIXME (rdar://problem/83895064): The disabled state for the alternate appearance is currently unspecified; this is just a guess.
+        if (!isEnabled)
+            return systemColor(isEmpty ? CSSValueWebkitControlBackground : CSSValueAppleSystemOpaqueTertiaryFill, styleColorOptions);
 
-    auto enabledBackgroundColor = systemColor(empty ? CSSValueWebkitControlBackground : CSSValueAppleSystemBlue, styleColorOptions);
-    if (states.contains(ControlStates::States::Pressed))
+        if (isPressed)
+            return isEmpty ? Color(DisplayP3<float> { 0.773, 0.773, 0.773 }) : Color(DisplayP3<float> { 0.067, 0.38, 0.953 });
+
+        return isEmpty ? Color(DisplayP3<float> { 0.835, 0.835, 0.835 }) : Color(DisplayP3<float> { 0.203, 0.47, 0.964 });
+    }
+
+    if (!isEnabled)
+        return systemColor(isEmpty ? CSSValueWebkitControlBackground : CSSValueAppleSystemOpaqueTertiaryFill, styleColorOptions);
+
+    auto enabledBackgroundColor = systemColor(isEmpty ? CSSValueWebkitControlBackground : CSSValueAppleSystemBlue, styleColorOptions);
+    if (isPressed)
         return enabledBackgroundColor.colorWithAlphaMultipliedBy(pressedStateOpacity);
 
     return enabledBackgroundColor;
 }
 
+RefPtr<Gradient> RenderThemeIOS::checkboxRadioBackgroundGradient(const FloatRect& rect, OptionSet<ControlStates::States> states)
+{
+    bool isPressed = states.contains(ControlStates::States::Pressed);
+    if (isPressed)
+        return nullptr;
+
+    bool isEmpty = !states.containsAny({ ControlStates::States::Checked, ControlStates::States::Indeterminate });
+    auto gradient = Gradient::create(Gradient::LinearData { rect.minXMinYCorner(), rect.maxXMaxYCorner() });
+    gradient->addColorStop({ 0.0f, DisplayP3<float> { 0, 0, 0, isEmpty ? 0.05f : 0.125f }});
+    gradient->addColorStop({ 1.0f, DisplayP3<float> { 0, 0, 0, 0 }});
+    return gradient;
+}
+
 Color RenderThemeIOS::checkboxRadioIndicatorColor(OptionSet<ControlStates::States> states, OptionSet<StyleColor::Options> styleColorOptions)
 {
     if (!states.contains(ControlStates::States::Enabled))
@@ -2084,11 +2110,53 @@
     return enabledIndicatorColor;
 }
 
+void RenderThemeIOS::paintCheckboxRadioInnerShadow(const PaintInfo& paintInfo, const FloatRoundedRect& roundedRect, OptionSet<ControlStates::States> states)
+{
+    auto& context = paintInfo.context();
+    GraphicsContextStateSaver stateSaver { context };
+
+    if (auto gradient = checkboxRadioBackgroundGradient(roundedRect.rect(), states)) {
+        context.setFillGradient(*gradient);
+
+        Path path;
+        path.addRoundedRect(roundedRect);
+        context.fillPath(path);
+    }
+
+    const FloatSize innerShadowOffset { 2, 2 };
+    constexpr auto innerShadowBlur = 3.0f;
+
+    bool isEmpty = !states.containsAny({ ControlStates::States::Checked, ControlStates::States::Indeterminate });
+    auto firstShadowColor = DisplayP3<float> { 0, 0, 0, isEmpty ? 0.05f : 0.1f };
+    context.setShadow(innerShadowOffset, innerShadowBlur, firstShadowColor);
+    context.setFillColor(Color::black);
+
+    Path innerShadowPath;
+    FloatRect innerShadowRect = roundedRect.rect();
+    innerShadowRect.inflate(std::max<float>(innerShadowOffset.width(), innerShadowOffset.height()) + innerShadowBlur);
+    innerShadowPath.addRect(innerShadowRect);
+
+    FloatRoundedRect innerShadowHoleRect = roundedRect;
+    // FIXME: This is not from the spec; but without it we get antialiasing fringe from the fill; we need a better solution.
+    innerShadowHoleRect.inflate(0.5);
+    innerShadowPath.addRoundedRect(innerShadowHoleRect);
+
+    context.setFillRule(WindRule::EvenOdd);
+    context.fillPath(innerShadowPath);
+
+    constexpr auto secondShadowColor = DisplayP3<float> { 1, 1, 1, 0.5f };
+    context.setShadow(FloatSize { 0, 0 }, 1, secondShadowColor);
+
+    context.fillPath(innerShadowPath);
+}
+
 bool RenderThemeIOS::paintCheckbox(const RenderObject& box, const PaintInfo& paintInfo, const FloatRect& rect)
 {
     if (!box.settings().iOSFormControlRefreshEnabled())
         return true;
 
+    bool useAlternateDesign = box.settings().alternateFormControlDesignEnabled();
+
     auto& context = paintInfo.context();
     GraphicsContextStateSaver stateSaver { context };
 
@@ -2100,7 +2168,7 @@
     auto controlStates = extractControlStatesForRenderer(box);
     auto styleColorOptions = box.styleColorOptions();
 
-    auto backgroundColor = checkboxRadioBackgroundColor(controlStates, styleColorOptions);
+    auto backgroundColor = checkboxRadioBackgroundColor(useAlternateDesign, controlStates, styleColorOptions);
 
     bool checked = controlStates.contains(ControlStates::States::Checked);
     bool indeterminate = controlStates.contains(ControlStates::States::Indeterminate);
@@ -2109,17 +2177,29 @@
     if (empty) {
         Path path;
         path.addRoundedRect(checkboxRect);
-        context.setStrokeColor(checkboxRadioBorderColor(controlStates, styleColorOptions));
-        context.setStrokeThickness(checkboxRadioBorderWidth * 2);
-        context.setStrokeStyle(SolidStroke);
+        if (!useAlternateDesign) {
+            context.setStrokeColor(checkboxRadioBorderColor(controlStates, styleColorOptions));
+            context.setStrokeThickness(checkboxRadioBorderWidth * 2);
+            context.setStrokeStyle(SolidStroke);
+        }
+            
         context.setFillColor(backgroundColor);
         context.clipPath(path);
         context.drawPath(path);
+
+        if (useAlternateDesign)
+            paintCheckboxRadioInnerShadow(paintInfo, checkboxRect, controlStates);
+
         return false;
     }
 
     context.fillRoundedRect(checkboxRect, backgroundColor);
 
+    if (useAlternateDesign) {
+        context.clipRoundedRect(checkboxRect);
+        paintCheckboxRadioInnerShadow(paintInfo, checkboxRect, controlStates);
+    }
+
     Path path;
     if (checked) {
         path.moveTo({ 28.174f, 68.652f });
@@ -2163,6 +2243,8 @@
     if (!box.settings().iOSFormControlRefreshEnabled())
         return true;
 
+    bool useAlternateDesign = box.settings().alternateFormControlDesignEnabled();
+
     auto& context = paintInfo.context();
     GraphicsContextStateSaver stateSaver(context);
 
@@ -2169,12 +2251,19 @@
     auto controlStates = extractControlStatesForRenderer(box);
     auto styleColorOptions = box.styleColorOptions();
 
-    auto backgroundColor = checkboxRadioBackgroundColor(controlStates, styleColorOptions);
+    auto backgroundColor = checkboxRadioBackgroundColor(useAlternateDesign, controlStates, styleColorOptions);
 
+    FloatRoundedRect radioRect { rect, FloatRoundedRect::Radii(rect.width() / 2, rect.height() / 2) };
+
     if (controlStates.contains(ControlStates::States::Checked)) {
         context.setFillColor(backgroundColor);
         context.fillEllipse(rect);
 
+        if (useAlternateDesign) {
+            context.clipRoundedRect(radioRect);
+            paintCheckboxRadioInnerShadow(paintInfo, radioRect, controlStates);
+        }
+
         // The inner circle is 6 / 14 the size of the surrounding circle,
         // leaving 8 / 14 around it. (8 / 14) / 2 = 2 / 7.
         constexpr float innerInverseRatio = 2 / 7.0f;
@@ -2188,12 +2277,17 @@
     } else {
         Path path;
         path.addEllipse(rect);
-        context.setStrokeColor(checkboxRadioBorderColor(controlStates, styleColorOptions));
-        context.setStrokeThickness(checkboxRadioBorderWidth * 2);
-        context.setStrokeStyle(SolidStroke);
+        if (!useAlternateDesign) {
+            context.setStrokeColor(checkboxRadioBorderColor(controlStates, styleColorOptions));
+            context.setStrokeThickness(checkboxRadioBorderWidth * 2);
+            context.setStrokeStyle(SolidStroke);
+        }
         context.setFillColor(backgroundColor);
         context.clipPath(path);
         context.drawPath(path);
+
+        if (useAlternateDesign)
+            paintCheckboxRadioInnerShadow(paintInfo, radioRect, controlStates);
     }
 
     return false;

Modified: trunk/Source/WebKit/ChangeLog (283559 => 283560)


--- trunk/Source/WebKit/ChangeLog	2021-10-05 18:12:24 UTC (rev 283559)
+++ trunk/Source/WebKit/ChangeLog	2021-10-05 18:15:47 UTC (rev 283560)
@@ -1,3 +1,14 @@
+2021-10-05  Tim Horton  <[email protected]>
+
+        Add an alternate style for form controls, and implement it for checkboxes and radio buttons
+        https://bugs.webkit.org/show_bug.cgi?id=231160
+
+        Reviewed by Sam Weinig.
+
+        * Shared/WebPreferencesDefaultValues.cpp:
+        (WebKit::defaultAlternateFormControlDesignEnabled):
+        * Shared/WebPreferencesDefaultValues.h:
+
 2021-10-05  Alex Christensen  <[email protected]>
 
         Implement missing functions in PrivateClickMeasurementDaemonClient

Modified: trunk/Source/WebKit/Shared/WebPreferencesDefaultValues.cpp (283559 => 283560)


--- trunk/Source/WebKit/Shared/WebPreferencesDefaultValues.cpp	2021-10-05 18:12:24 UTC (rev 283559)
+++ trunk/Source/WebKit/Shared/WebPreferencesDefaultValues.cpp	2021-10-05 18:15:47 UTC (rev 283560)
@@ -62,8 +62,15 @@
     return !result;
 }
 
+#if !USE(APPLE_INTERNAL_SDK)
+bool defaultAlternateFormControlDesignEnabled()
+{
+    return false;
+}
 #endif
 
+#endif
+
 #if PLATFORM(MAC)
 
 bool defaultPassiveWheelListenersAsDefaultOnDocument()

Modified: trunk/Source/WebKit/Shared/WebPreferencesDefaultValues.h (283559 => 283560)


--- trunk/Source/WebKit/Shared/WebPreferencesDefaultValues.h	2021-10-05 18:12:24 UTC (rev 283559)
+++ trunk/Source/WebKit/Shared/WebPreferencesDefaultValues.h	2021-10-05 18:15:47 UTC (rev 283560)
@@ -40,6 +40,7 @@
 #if PLATFORM(IOS_FAMILY)
 bool defaultPassiveTouchListenersAsDefaultOnDocument();
 bool defaultCSSOMViewScrollingAPIEnabled();
+bool defaultAlternateFormControlDesignEnabled();
 #if ENABLE(TEXT_AUTOSIZING)
 bool defaultTextAutosizingUsesIdempotentMode();
 #endif
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to