Skip to content
Permalink
Browse files
[iOS] Paint <datalist> indicator in RenderTheme
https://bugs.webkit.org/show_bug.cgi?id=231755
rdar://84261604

Reviewed by Tim Horton.

Source/WebCore:

Currently, the <datalist> indicator is painted using the 'content'
property and an SVG image. With the existing implementation, it is
not possible to tint the indicator, when an accent-color is supplied.
To support control tinting, and better align with the way other native
controls are painted, move the painting into RenderTheme.

Covered by existing tests.

* css/html.css:
(input::-webkit-list-button):
* rendering/RenderTheme.cpp:
(WebCore::RenderTheme::paint):
* rendering/RenderTheme.h:
(WebCore::RenderTheme::paintListButton):
* rendering/RenderThemeIOS.h:
* rendering/RenderThemeIOS.mm:
(WebCore::RenderThemeIOS::isControlStyled const):

Do not draw the native indicator if the style has content or the
content has explicitly been set to none. This ensures we maintain
compatibility for pages that still use 'content' to customize the
indicator.

(WebCore::RenderThemeIOS::paintListButton):

Draw the indicator. The path is taken directly from the SVG.

* rendering/style/RenderStyle.cpp:
(WebCore::RenderStyle::RenderStyle):
* rendering/style/RenderStyle.h:

Add setHasExplicitlyClearedContent / hasExplicitlyClearedContent to
detect whether the author has explicitly cleared content, in which
case we do not paint the native indicator.

(WebCore::RenderStyle::setHasExplicitlyClearedContent):
(WebCore::RenderStyle::hasExplicitlyClearedContent const):
(WebCore::RenderStyle::NonInheritedFlags::operator== const):
* style/StyleBuilderCustom.h:
(WebCore::Style::BuilderCustom::applyInitialContent):
(WebCore::Style::BuilderCustom::applyValueContent):
* style/StyleResolver.cpp:
(WebCore::Style::elementTypeHasAppearanceFromUAStyle):

Add the datalist button to the list of element types that have
appearance from UA style, so that we can determine whether or not to
drop native appearance.

LayoutTests:

Rebaseline tests.

* platform/ios-simulator/fast/forms/datalist/datalist-searchinput-appearance-expected.txt:
* platform/ios-simulator/fast/forms/datalist/datalist-textinput-appearance-expected.txt:


Canonical link: https://commits.webkit.org/243034@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@284225 268f45cc-cd09-0410-ab3c-d52691b4dbfc
  • Loading branch information
pxlcoder committed Oct 15, 2021
1 parent 947cad9 commit 8416b00da0bf3aa07af972b996717e8506125fee
Showing 13 changed files with 138 additions and 4 deletions.
@@ -1,3 +1,16 @@
2021-10-14 Aditya Keerthi <akeerthi@apple.com>

[iOS] Paint <datalist> indicator in RenderTheme
https://bugs.webkit.org/show_bug.cgi?id=231755
rdar://84261604

Reviewed by Tim Horton.

Rebaseline tests.

* platform/ios-simulator/fast/forms/datalist/datalist-searchinput-appearance-expected.txt:
* platform/ios-simulator/fast/forms/datalist/datalist-textinput-appearance-expected.txt:

2021-10-14 Eric Hutchison <ehutchison@apple.com>

[ iOS15 Mac wk2 Debug ] imported/w3c/web-platform-tests/webrtc/simulcast/basic.https.html is a flaky failure.
@@ -13,4 +13,4 @@ layer at (0,0) size 800x41
layer at (32,13) size 127x14 backgroundClip at (32,13) size 126x14 clip at (32,13) size 126x14
RenderBlock {DIV} at (0,0) size 127x14
layer at (151,6) size 25x28
RenderImage {DIV} at (134,-7) size 26x28
RenderBlock (relative positioned) {DIV} at (134,-7) size 26x28
@@ -11,4 +11,4 @@ layer at (0,0) size 800x41
layer at (17,13) size 131x14 backgroundClip at (17,13) size 130x14 clip at (17,13) size 130x14
RenderBlock {DIV} at (0,0) size 131x14
layer at (140,6) size 25x28
RenderImage {DIV} at (123,-7) size 26x28
RenderBlock (relative positioned) {DIV} at (123,-7) size 26x28
@@ -1,3 +1,59 @@
2021-10-14 Aditya Keerthi <akeerthi@apple.com>

[iOS] Paint <datalist> indicator in RenderTheme
https://bugs.webkit.org/show_bug.cgi?id=231755
rdar://84261604

Reviewed by Tim Horton.

Currently, the <datalist> indicator is painted using the 'content'
property and an SVG image. With the existing implementation, it is
not possible to tint the indicator, when an accent-color is supplied.
To support control tinting, and better align with the way other native
controls are painted, move the painting into RenderTheme.

Covered by existing tests.

* css/html.css:
(input::-webkit-list-button):
* rendering/RenderTheme.cpp:
(WebCore::RenderTheme::paint):
* rendering/RenderTheme.h:
(WebCore::RenderTheme::paintListButton):
* rendering/RenderThemeIOS.h:
* rendering/RenderThemeIOS.mm:
(WebCore::RenderThemeIOS::isControlStyled const):

Do not draw the native indicator if the style has content or the
content has explicitly been set to none. This ensures we maintain
compatibility for pages that still use 'content' to customize the
indicator.

(WebCore::RenderThemeIOS::paintListButton):

Draw the indicator. The path is taken directly from the SVG.

* rendering/style/RenderStyle.cpp:
(WebCore::RenderStyle::RenderStyle):
* rendering/style/RenderStyle.h:

Add setHasExplicitlyClearedContent / hasExplicitlyClearedContent to
detect whether the author has explicitly cleared content, in which
case we do not paint the native indicator.

(WebCore::RenderStyle::setHasExplicitlyClearedContent):
(WebCore::RenderStyle::hasExplicitlyClearedContent const):
(WebCore::RenderStyle::NonInheritedFlags::operator== const):
* style/StyleBuilderCustom.h:
(WebCore::Style::BuilderCustom::applyInitialContent):
(WebCore::Style::BuilderCustom::applyValueContent):
* style/StyleResolver.cpp:
(WebCore::Style::elementTypeHasAppearanceFromUAStyle):

Add the datalist button to the list of element types that have
appearance from UA style, so that we can determine whether or not to
drop native appearance.

2021-10-14 Kate Cheney <katherine_cheney@apple.com>

Adopt attribution AVCaptureSession SPI for GPU process
@@ -698,7 +698,6 @@ input::-webkit-list-button {
-webkit-user-select: none;
#if defined(WTF_PLATFORM_IOS_FAMILY) && WTF_PLATFORM_IOS_FAMILY
width: 11px;
content: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 71 42"><path fill="-apple-system-blue" d="M35.48 38.029c1.424 0 2.645-.529 3.743-1.668L63.352 11.987c.854-.895 1.343-1.994 1.343-3.296C64.695 6.046 62.579 3.971 59.975 3.971c-1.261 0-2.482.529-3.418 1.465L35.52 26.839 14.443 5.436C13.507 4.5 12.327 3.971 10.984 3.971c-2.604 0-4.679 2.075-4.679 4.72 0 1.302.448 2.401 1.343 3.296l24.129 24.373c1.139 1.139 2.319 1.668 3.703 1.668z"/></svg>');
/* Make it easier to hit the button on iOS */
padding: 7px;
margin: -7px;
@@ -556,6 +556,10 @@ bool RenderTheme::paint(const RenderBox& box, ControlStates& controlStates, cons
case AttachmentPart:
case BorderlessAttachmentPart:
return paintAttachment(box, paintInfo, integralSnappedRect);
#endif
#if ENABLE(DATALIST_ELEMENT)
case ListButtonPart:
return paintListButton(box, paintInfo, devicePixelSnappedRect);
#endif
default:
break;
@@ -357,6 +357,7 @@ class RenderTheme {

#if ENABLE(DATALIST_ELEMENT)
virtual void adjustListButtonStyle(RenderStyle&, const Element*) const;
virtual bool paintListButton(const RenderObject&, const PaintInfo&, const FloatRect&) { return true; }
#endif

virtual void adjustProgressBarStyle(RenderStyle&, const Element*) const;
@@ -134,6 +134,8 @@ class RenderThemeIOS final : public RenderThemeCocoa {
bool paintMeter(const RenderObject&, const PaintInfo&, const IntRect&) final;

#if ENABLE(DATALIST_ELEMENT)
bool paintListButton(const RenderObject&, const PaintInfo&, const FloatRect&) final;

void paintSliderTicks(const RenderObject&, const PaintInfo&, const FloatRect&) final;
#endif

@@ -493,6 +493,11 @@ static void drawJoinedLines(CGContextRef context, const Vector<CGPoint>& points,
if (style.effectiveAppearance() == TextFieldPart || style.effectiveAppearance() == TextAreaPart)
return style.backgroundLayers() != userAgentStyle.backgroundLayers();

#if ENABLE(DATALIST_ELEMENT)
if (style.effectiveAppearance() == ListButtonPart)
return style.hasContent() || style.hasExplicitlyClearedContent();
#endif

return RenderTheme::isControlStyled(style, userAgentStyle);
}

@@ -2530,6 +2535,51 @@ static CGPDFPageRef systemPreviewLogo()

#if ENABLE(DATALIST_ELEMENT)

bool RenderThemeIOS::paintListButton(const RenderObject& box, const PaintInfo& paintInfo, const FloatRect& rect)
{
auto& context = paintInfo.context();
GraphicsContextStateSaver stateSaver(context);

auto& style = box.style();

float paddingTop = floatValueForLength(style.paddingTop(), rect.height());
float paddingRight = floatValueForLength(style.paddingRight(), rect.width());
float paddingBottom = floatValueForLength(style.paddingBottom(), rect.height());
float paddingLeft = floatValueForLength(style.paddingLeft(), rect.width());

FloatRect indicatorRect = rect;
indicatorRect.move(paddingLeft, paddingTop);
indicatorRect.contract(paddingLeft + paddingRight, paddingTop + paddingBottom);

Path path;
path.moveTo({ 35.48, 38.029 });
path.addBezierCurveTo({ 36.904, 38.029 }, { 38.125, 37.5 }, { 39.223, 36.361 });
path.addLineTo({ 63.352, 11.987 });
path.addBezierCurveTo({ 64.206, 11.092 }, { 64.695, 9.993 }, { 64.695, 8.691 });
path.addBezierCurveTo({ 64.695, 6.046 }, { 62.579, 3.971 }, { 59.975, 3.971 });
path.addBezierCurveTo({ 58.714, 3.971 }, { 57.493, 4.5 }, { 56.557, 5.436 });
path.addLineTo({ 35.52, 26.839 });
path.addLineTo({ 14.443, 5.436 });
path.addBezierCurveTo({ 13.507, 4.5 }, { 12.327, 3.971 }, { 10.984, 3.971 });
path.addBezierCurveTo({ 8.38, 3.971 }, { 6.305, 6.046 }, { 6.305, 8.691 });
path.addBezierCurveTo({ 6.305, 9.993 }, { 6.753, 11.092 }, { 7.648, 11.987 });
path.addLineTo({ 31.777, 36.36 });
path.addBezierCurveTo({ 32.916, 37.499 }, { 34.096, 38.028 }, { 35.48, 38.028 });

const FloatSize indicatorSize(71.0f, 42.0f);
float scale = indicatorRect.width() / indicatorSize.width();

AffineTransform transform;
transform.translate(rect.center() - (indicatorSize * scale * 0.5f));
transform.scale(scale);
path.transform(transform);

context.setFillColor(systemColor(CSSValueAppleSystemBlue, box.styleColorOptions()));
context.fillPath(path);

return false;
}

void RenderThemeIOS::paintSliderTicks(const RenderObject& box, const PaintInfo& paintInfo, const FloatRect& rect)
{
if (!box.settings().iOSFormControlRefreshEnabled()) {
@@ -193,6 +193,7 @@ RenderStyle::RenderStyle(CreateDefaultStyleTag)
m_nonInheritedFlags.firstChildState = false;
m_nonInheritedFlags.lastChildState = false;
m_nonInheritedFlags.isLink = false;
m_nonInheritedFlags.hasExplicitlyClearedContent = false;
m_nonInheritedFlags.styleType = static_cast<unsigned>(PseudoId::None);
m_nonInheritedFlags.pseudoBits = static_cast<unsigned>(PseudoId::None);

@@ -1474,6 +1474,8 @@ class RenderStyle {
const ContentData* contentData() const { return m_rareNonInheritedData->content.get(); }
bool contentDataEquivalent(const RenderStyle* otherStyle) const { return const_cast<RenderStyle*>(this)->m_rareNonInheritedData->contentDataEquivalent(*const_cast<RenderStyle*>(otherStyle)->m_rareNonInheritedData); }
void clearContent();
void setHasExplicitlyClearedContent(bool v) { m_nonInheritedFlags.hasExplicitlyClearedContent = v; }
bool hasExplicitlyClearedContent() const { return m_nonInheritedFlags.hasExplicitlyClearedContent; };
void setContent(const String&, bool add = false);
void setContent(RefPtr<StyleImage>&&, bool add = false);
void setContent(std::unique_ptr<CounterContent>, bool add = false);
@@ -1919,6 +1921,7 @@ class RenderStyle {
unsigned firstChildState : 1;
unsigned lastChildState : 1;
unsigned isLink : 1;
unsigned hasExplicitlyClearedContent : 1;

unsigned styleType : 4; // PseudoId
unsigned pseudoBits : (static_cast<unsigned>(PseudoId::FirstInternalPseudoId) - static_cast<unsigned>(PseudoId::FirstPublicPseudoId));
@@ -2057,6 +2060,7 @@ inline bool RenderStyle::NonInheritedFlags::operator==(const NonInheritedFlags&
&& firstChildState == other.firstChildState
&& lastChildState == other.lastChildState
&& isLink == other.isLink
&& hasExplicitlyClearedContent == other.hasExplicitlyClearedContent
&& styleType == other.styleType
&& pseudoBits == other.pseudoBits;
}
@@ -1517,6 +1517,7 @@ inline void BuilderCustom::applyValueStroke(BuilderState& builderState, CSSValue
inline void BuilderCustom::applyInitialContent(BuilderState& builderState)
{
builderState.style().clearContent();
builderState.style().setHasExplicitlyClearedContent(true);
}

inline void BuilderCustom::applyInheritContent(BuilderState&)
@@ -1531,6 +1532,7 @@ inline void BuilderCustom::applyValueContent(BuilderState& builderState, CSSValu
const auto& primitiveValue = downcast<CSSPrimitiveValue>(value);
ASSERT_UNUSED(primitiveValue, primitiveValue.valueID() == CSSValueNormal || primitiveValue.valueID() == CSSValueNone);
builderState.style().clearContent();
builderState.style().setHasExplicitlyClearedContent(true);
return;
}

@@ -61,6 +61,7 @@
#include "SVGElement.h"
#include "SVGFontFaceElement.h"
#include "Settings.h"
#include "ShadowPseudoIds.h"
#include "ShadowRoot.h"
#include "SharedStringHash.h"
#include "StyleAdjuster.h"
@@ -494,7 +495,8 @@ static bool elementTypeHasAppearanceFromUAStyle(const Element& element)
|| localName == HTMLNames::buttonTag
|| localName == HTMLNames::progressTag
|| localName == HTMLNames::selectTag
|| localName == HTMLNames::meterTag;
|| localName == HTMLNames::meterTag
|| (element.isInUserAgentShadowTree() && element.shadowPseudoId() == ShadowPseudoIds::webkitListButton());
}

void Resolver::invalidateMatchedDeclarationsCache()

0 comments on commit 8416b00

Please sign in to comment.