Skip to content

Commit

Permalink
[iOS] Paint <datalist> indicator in RenderTheme
Browse files Browse the repository at this point in the history
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 8416b00
Show file tree
Hide file tree
Showing 13 changed files with 138 additions and 4 deletions.
13 changes: 13 additions & 0 deletions LayoutTests/ChangeLog
@@ -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.
Expand Down
Expand Up @@ -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
Expand Up @@ -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
56 changes: 56 additions & 0 deletions Source/WebCore/ChangeLog
@@ -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
Expand Down
1 change: 0 additions & 1 deletion Source/WebCore/css/html.css
Expand Up @@ -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;
Expand Down
4 changes: 4 additions & 0 deletions Source/WebCore/rendering/RenderTheme.cpp
Expand Up @@ -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;
Expand Down
1 change: 1 addition & 0 deletions Source/WebCore/rendering/RenderTheme.h
Expand Up @@ -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;
Expand Down
2 changes: 2 additions & 0 deletions Source/WebCore/rendering/RenderThemeIOS.h
Expand Up @@ -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

Expand Down
50 changes: 50 additions & 0 deletions Source/WebCore/rendering/RenderThemeIOS.mm
Expand Up @@ -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);
}

Expand Down Expand Up @@ -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()) {
Expand Down
1 change: 1 addition & 0 deletions Source/WebCore/rendering/style/RenderStyle.cpp
Expand Up @@ -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);

Expand Down
4 changes: 4 additions & 0 deletions Source/WebCore/rendering/style/RenderStyle.h
Expand Up @@ -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);
Expand Down Expand Up @@ -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));
Expand Down Expand Up @@ -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;
}
Expand Down
2 changes: 2 additions & 0 deletions Source/WebCore/style/StyleBuilderCustom.h
Expand Up @@ -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&)
Expand All @@ -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;
}

Expand Down
4 changes: 3 additions & 1 deletion Source/WebCore/style/StyleResolver.cpp
Expand Up @@ -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"
Expand Down Expand Up @@ -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()
Expand Down

0 comments on commit 8416b00

Please sign in to comment.