From a6b2a57ab860a07f1c2c89c8cd98b4a34212e645 Mon Sep 17 00:00:00 2001 From: Alan Baradlay Date: Mon, 17 Apr 2023 19:04:39 -0700 Subject: [PATCH] Rendering issue with checkbox in flexbox layout https://bugs.webkit.org/show_bug.cgi?id=255419 Reviewed by Antti Koivisto. Form controls with appearance are supposed to set their minimum (intrinsic) widths so that they don't get overlapped (e.g. by getting sized to 0px) in over-constrained situations. * LayoutTests/fast/flexbox/overlapped-form-controls-expected.html: Added. * LayoutTests/fast/flexbox/overlapped-form-controls.html: Added. * Source/WebCore/platform/Theme.cpp: (WebCore::Theme::minimumControlSize const): Canonical link: https://commits.webkit.org/263052@main --- .../overlapped-form-controls-expected.html | 10 ++++++++++ .../fast/flexbox/overlapped-form-controls.html | 15 +++++++++++++++ .../css-flexbox/radiobutton-min-size-expected.txt | 8 -------- Source/WebCore/platform/Theme.cpp | 3 ++- Source/WebCore/rendering/RenderThemeIOS.h | 1 + Source/WebCore/rendering/RenderThemeIOS.mm | 11 +++++++++++ 6 files changed, 39 insertions(+), 9 deletions(-) create mode 100644 LayoutTests/fast/flexbox/overlapped-form-controls-expected.html create mode 100644 LayoutTests/fast/flexbox/overlapped-form-controls.html delete mode 100644 LayoutTests/platform/ios-wk2/imported/w3c/web-platform-tests/css/css-flexbox/radiobutton-min-size-expected.txt diff --git a/LayoutTests/fast/flexbox/overlapped-form-controls-expected.html b/LayoutTests/fast/flexbox/overlapped-form-controls-expected.html new file mode 100644 index 000000000000..4a392701b184 --- /dev/null +++ b/LayoutTests/fast/flexbox/overlapped-form-controls-expected.html @@ -0,0 +1,10 @@ + +
+
\ No newline at end of file diff --git a/LayoutTests/fast/flexbox/overlapped-form-controls.html b/LayoutTests/fast/flexbox/overlapped-form-controls.html new file mode 100644 index 000000000000..39348f581610 --- /dev/null +++ b/LayoutTests/fast/flexbox/overlapped-form-controls.html @@ -0,0 +1,15 @@ + +
PASS if form control is not overlapped.
+
PASS if form control is not overlapped.
diff --git a/LayoutTests/platform/ios-wk2/imported/w3c/web-platform-tests/css/css-flexbox/radiobutton-min-size-expected.txt b/LayoutTests/platform/ios-wk2/imported/w3c/web-platform-tests/css/css-flexbox/radiobutton-min-size-expected.txt deleted file mode 100644 index 3d1950f9ac34..000000000000 --- a/LayoutTests/platform/ios-wk2/imported/w3c/web-platform-tests/css/css-flexbox/radiobutton-min-size-expected.txt +++ /dev/null @@ -1,8 +0,0 @@ -You should see two identical-looking lines, both with a radio button at the beginning. - - -Text -Text - -FAIL two radio button widths are identical assert_equals: width should be equal expected 0 but got 16 - diff --git a/Source/WebCore/platform/Theme.cpp b/Source/WebCore/platform/Theme.cpp index 7b709e5caf39..a119a60d53f6 100644 --- a/Source/WebCore/platform/Theme.cpp +++ b/Source/WebCore/platform/Theme.cpp @@ -51,7 +51,8 @@ LengthSize Theme::controlSize(StyleAppearance, const FontCascade&, const LengthS LengthSize Theme::minimumControlSize(StyleAppearance appearance, const FontCascade& fontCascade, const LengthSize& zoomedSize, const LengthSize& nonShrinkableZoomedSize, float zoom) const { auto minSize = minimumControlSize(appearance, fontCascade, zoomedSize, zoom); - if (appearance == StyleAppearance::Radio) { + // Other StyleAppearance types are composed controls with shadow subtree. + if (appearance == StyleAppearance::Radio || appearance == StyleAppearance::Checkbox) { if (zoomedSize.width.isIntrinsicOrAuto()) minSize.width = nonShrinkableZoomedSize.width; if (zoomedSize.height.isIntrinsicOrAuto()) diff --git a/Source/WebCore/rendering/RenderThemeIOS.h b/Source/WebCore/rendering/RenderThemeIOS.h index 5e500f92856d..78d0f7b4a100 100644 --- a/Source/WebCore/rendering/RenderThemeIOS.h +++ b/Source/WebCore/rendering/RenderThemeIOS.h @@ -204,6 +204,7 @@ class RenderThemeIOS final : public RenderThemeCocoa { Color controlTintColor(const RenderStyle&, OptionSet) const; void adjustStyleForAlternateFormControlDesignTransition(RenderStyle&, const Element*) const; + void adjustMinimumIntrinsicSizeForAppearance(StyleAppearance, RenderStyle&) const; }; } diff --git a/Source/WebCore/rendering/RenderThemeIOS.mm b/Source/WebCore/rendering/RenderThemeIOS.mm index ecdf390a5dbe..9304f572da86 100644 --- a/Source/WebCore/rendering/RenderThemeIOS.mm +++ b/Source/WebCore/rendering/RenderThemeIOS.mm @@ -342,6 +342,7 @@ static IOSGradientRef gradientWithName(IOSGradientType gradientType) void RenderThemeIOS::adjustCheckboxStyle(RenderStyle& style, const Element* element) const { adjustStyleForAlternateFormControlDesignTransition(style, element); + adjustMinimumIntrinsicSizeForAppearance(StyleAppearance::Checkbox, style); if (!style.width().isIntrinsicOrAuto() && !style.height().isAuto()) return; @@ -488,9 +489,19 @@ static void drawJoinedLines(CGContextRef context, const Vector& points, return RenderTheme::isControlStyled(style, userAgentStyle); } +void RenderThemeIOS::adjustMinimumIntrinsicSizeForAppearance(StyleAppearance appearance, RenderStyle& style) const +{ + auto minControlSize = Theme::singleton().minimumControlSize(appearance, style.fontCascade(), { style.minWidth(), style.minHeight() }, { style.width(), style.height() }, style.effectiveZoom()); + if (minControlSize.width.value() > style.minWidth().value()) + style.setMinWidth(WTFMove(minControlSize.width)); + if (minControlSize.height.value() > style.minHeight().value()) + style.setMinHeight(WTFMove(minControlSize.height)); +} + void RenderThemeIOS::adjustRadioStyle(RenderStyle& style, const Element* element) const { adjustStyleForAlternateFormControlDesignTransition(style, element); + adjustMinimumIntrinsicSizeForAppearance(StyleAppearance::Radio, style); if (!style.width().isIntrinsicOrAuto() && !style.height().isAuto()) return;