diff --git a/gfx/src/nsITheme.h b/gfx/src/nsITheme.h index 496dc2204945..feb7104d3138 100644 --- a/gfx/src/nsITheme.h +++ b/gfx/src/nsITheme.h @@ -150,6 +150,14 @@ class nsITheme : public nsISupports { return false; } + /** + * Get the preferred content-box size of a checkbox / radio button, in app + * units. Historically 9px. + */ + virtual nscoord GetCheckboxRadioPrefSize() { + return mozilla::CSSPixel::ToAppUnits(9); + } + /** * Get the minimum border-box size of a widget, in *pixels* (in * |aResult|). If |aIsOverridable| is set to true, this size is a diff --git a/layout/forms/nsCheckboxRadioFrame.cpp b/layout/forms/nsCheckboxRadioFrame.cpp index bc4154eedff0..f9b2eff5196a 100644 --- a/layout/forms/nsCheckboxRadioFrame.cpp +++ b/layout/forms/nsCheckboxRadioFrame.cpp @@ -14,7 +14,6 @@ #include "nsStyleConsts.h" using namespace mozilla; -using mozilla::dom::Element; using mozilla::dom::HTMLInputElement; //#define FCF_NOISY @@ -37,6 +36,13 @@ NS_QUERYFRAME_HEAD(nsCheckboxRadioFrame) NS_QUERYFRAME_ENTRY(nsIFormControlFrame) NS_QUERYFRAME_TAIL_INHERITING(nsAtomicContainerFrame) +nscoord nsCheckboxRadioFrame::DefaultSize() { + if (StyleDisplay()->HasAppearance()) { + return PresContext()->Theme()->GetCheckboxRadioPrefSize(); + } + return CSSPixel::ToAppUnits(9); +} + /* virtual */ nscoord nsCheckboxRadioFrame::GetMinISize(gfxContext* aRenderingContext) { nscoord result; diff --git a/layout/forms/nsCheckboxRadioFrame.h b/layout/forms/nsCheckboxRadioFrame.h index e3737c246580..d6e8b1629a84 100644 --- a/layout/forms/nsCheckboxRadioFrame.h +++ b/layout/forms/nsCheckboxRadioFrame.h @@ -86,12 +86,7 @@ class nsCheckboxRadioFrame final : public nsAtomicContainerFrame, protected: virtual ~nsCheckboxRadioFrame(); - static nscoord DefaultSize() { - // XXXmats We have traditionally always returned 9px for GetMin/PrefISize - // but we might want to factor in what the theme says, something like: - // GetMinimumWidgetSize - GetWidgetPadding - GetWidgetBorder. - return nsPresContext::CSSPixelsToAppUnits(9); - } + nscoord DefaultSize(); /** * Get the state of the checked attribute. diff --git a/layout/reftests/forms/input/checkbox/checkbox-minimum-size-ref.html b/layout/reftests/forms/input/checkbox/checkbox-minimum-size-notref.html similarity index 100% rename from layout/reftests/forms/input/checkbox/checkbox-minimum-size-ref.html rename to layout/reftests/forms/input/checkbox/checkbox-minimum-size-notref.html diff --git a/layout/reftests/forms/input/checkbox/reftest.list b/layout/reftests/forms/input/checkbox/reftest.list index b5b85958c7c9..956d4d9d56f0 100644 --- a/layout/reftests/forms/input/checkbox/reftest.list +++ b/layout/reftests/forms/input/checkbox/reftest.list @@ -11,9 +11,9 @@ != indeterminate-native-checked.html indeterminate-native-checked-notref.html != indeterminate-native-unchecked.html indeterminate-native-unchecked-notref.html == indeterminate-selector.html indeterminate-selector-ref.html -skip-if(!gtkWidget) == gtk-theme-width-height.html gtk-theme-width-height-ref.html +skip-if(!gtkWidget||!nativeThemePref) == gtk-theme-width-height.html gtk-theme-width-height-ref.html == checkbox-baseline.html checkbox-baseline-ref.html == checkbox-radio-color.html checkbox-radio-color-ref.html skip-if(gtkWidget&&nativeThemePref) == checkbox-clamp-01.html checkbox-clamp-01-ref.html skip-if(OSX||winWidget) fails-if(geckoview&&webrender) fuzzy-if(gtkWidget&&nativeThemePref,25-25,32-32) fails-if(Android&&nativeThemePref) == checkbox-clamp-02.html checkbox-clamp-02-ref.html -fails-if(OSX&&nativeThemePref) == checkbox-minimum-size.html checkbox-minimum-size-ref.html +fails-if(!OSX&&nativeThemePref) != checkbox-minimum-size.html checkbox-minimum-size-notref.html diff --git a/layout/reftests/forms/input/radio/radio-minimum-size-ref.html b/layout/reftests/forms/input/radio/radio-minimum-size-notref.html similarity index 100% rename from layout/reftests/forms/input/radio/radio-minimum-size-ref.html rename to layout/reftests/forms/input/radio/radio-minimum-size-notref.html diff --git a/layout/reftests/forms/input/radio/reftest.list b/layout/reftests/forms/input/radio/reftest.list index db4798a92017..91c2786261be 100644 --- a/layout/reftests/forms/input/radio/reftest.list +++ b/layout/reftests/forms/input/radio/reftest.list @@ -4,7 +4,7 @@ == unchecked-appearance-none.html about:blank != checked-native.html about:blank != checked-native-notref.html about:blank -skip-if(!gtkWidget) == gtk-theme-width-height.html gtk-theme-width-height-ref.html +skip-if(!gtkWidget||!nativeThemePref) == gtk-theme-width-height.html gtk-theme-width-height-ref.html skip-if(gtkWidget&&nativeThemePref) == radio-clamp-01.html radio-clamp-01-ref.html skip-if(OSX||winWidget||Android) fuzzy-if(gtkWidget&&nativeThemePref,24-24,16-16) == radio-clamp-02.html radio-clamp-02-ref.html # gtkWidget, Bug 1599622 -fails-if(OSX&&nativeThemePref) == radio-minimum-size.html radio-minimum-size-ref.html +fails-if(!OSX&&nativeThemePref) != radio-minimum-size.html radio-minimum-size-notref.html diff --git a/widget/nsNativeBasicTheme.cpp b/widget/nsNativeBasicTheme.cpp index 143f4fc7eca1..1940a4995cad 100644 --- a/widget/nsNativeBasicTheme.cpp +++ b/widget/nsNativeBasicTheme.cpp @@ -655,9 +655,12 @@ void nsNativeBasicTheme::PaintCheckboxControl(DrawTarget* aDrawTarget, } } -// Returns the right scale to cover aRect in the smaller dimension. -static float ScaleToWidgetRect(const LayoutDeviceRect& aRect) { - return std::min(aRect.width, aRect.height) / kMinimumWidgetSize; + +// Returns the right scale for points in a 14x14 unit box centered at 0x0 to +// fill aRect in the smaller dimension. +static float ScaleToFillRect(const LayoutDeviceRect& aRect) { + static constexpr float kPathPointsScale = 14.0f; + return std::min(aRect.width, aRect.height) / kPathPointsScale; } void nsNativeBasicTheme::PaintCheckMark(DrawTarget* aDrawTarget, @@ -669,7 +672,7 @@ void nsNativeBasicTheme::PaintCheckMark(DrawTarget* aDrawTarget, const float checkPolygonY[] = {0.5f, 4.0f, 4.0f, -2.5f, -4.0f, -4.0f, 1.0f, 1.25f, -1.0f}; const int32_t checkNumPoints = sizeof(checkPolygonX) / sizeof(float); - const float scale = ScaleToWidgetRect(aRect); + const float scale = ScaleToFillRect(aRect); auto center = aRect.Center().ToUnknownPoint(); RefPtr builder = aDrawTarget->CreatePathBuilder(); @@ -689,7 +692,7 @@ void nsNativeBasicTheme::PaintIndeterminateMark(DrawTarget* aDrawTarget, const LayoutDeviceRect& aRect, const EventStates& aState) { const CSSCoord borderWidth = 2.0f; - const float scale = ScaleToWidgetRect(aRect); + const float scale = ScaleToFillRect(aRect); Rect rect = aRect.ToUnknownRect(); rect.y += (rect.height / 2) - (borderWidth * scale / 2); @@ -788,7 +791,7 @@ void nsNativeBasicTheme::PaintRadioCheckmark(DrawTarget* aDrawTarget, const EventStates& aState, DPIRatio aDpiRatio) { const CSSCoord borderWidth = 2.0f; - const float scale = ScaleToWidgetRect(aRect); + const float scale = ScaleToFillRect(aRect); auto [backgroundColor, checkColor] = ComputeRadioCheckmarkColors(aState); LayoutDeviceRect rect(aRect); @@ -853,7 +856,7 @@ void nsNativeBasicTheme::PaintArrow(DrawTarget* aDrawTarget, const float aArrowPolygonY[], const int32_t aArrowNumPoints, const sRGBColor aFillColor) { - const float scale = ScaleToWidgetRect(aRect); + const float scale = ScaleToFillRect(aRect); auto center = aRect.Center().ToUnknownPoint(); @@ -900,7 +903,7 @@ void nsNativeBasicTheme::PaintSpinnerButton(nsIFrame* aFrame, const float arrowPolygonY[] = {-1.875f, 2.625f, 2.625f, -1.875f, -4.125f, -4.125f, 0.375f, 0.375f, -4.125f, -4.125f}; const int32_t arrowNumPoints = ArrayLength(arrowPolygonX); - const float scaleX = ScaleToWidgetRect(aRect); + const float scaleX = ScaleToFillRect(aRect); const float scaleY = aAppearance == StyleAppearance::SpinnerDownbutton ? scaleX : -scaleX; @@ -1546,6 +1549,10 @@ auto nsNativeBasicTheme::GetScrollbarSizes(nsPresContext* aPresContext, return {s, s}; } +nscoord nsNativeBasicTheme::GetCheckboxRadioPrefSize() { + return CSSPixel::ToAppUnits(10); +} + NS_IMETHODIMP nsNativeBasicTheme::GetMinimumWidgetSize(nsPresContext* aPresContext, nsIFrame* aFrame, @@ -1554,7 +1561,8 @@ nsNativeBasicTheme::GetMinimumWidgetSize(nsPresContext* aPresContext, bool* aIsOverridable) { DPIRatio dpiRatio = GetDPIRatio(aFrame, aAppearance); - aResult->width = aResult->height = (kMinimumWidgetSize * dpiRatio).Rounded(); + aResult->width = aResult->height = 0; + *aIsOverridable = true; switch (aAppearance) { case StyleAppearance::Button: @@ -1621,7 +1629,6 @@ nsNativeBasicTheme::GetMinimumWidgetSize(nsPresContext* aPresContext, break; } - *aIsOverridable = true; return NS_OK; } diff --git a/widget/nsNativeBasicTheme.h b/widget/nsNativeBasicTheme.h index 5f32482c753f..9a3e8bfb46b1 100644 --- a/widget/nsNativeBasicTheme.h +++ b/widget/nsNativeBasicTheme.h @@ -83,7 +83,6 @@ static const gfx::sRGBColor sScrollbarButtonHoverColor(gfx::sRGBColor(0.86f, 0.86f, 0.86f)); -static const CSSCoord kMinimumWidgetSize = 14.0f; static const CSSCoord kMinimumScrollbarSize = 17.0f; static const CSSCoord kMinimumThinScrollbarSize = 6.0f; static const CSSCoord kMinimumColorPickerHeight = 32.0f; @@ -175,6 +174,8 @@ class nsNativeBasicTheme : protected nsNativeTheme, public nsITheme { Overlay) override; static nscolor AdjustUnthemedScrollbarThumbColor(nscolor, EventStates); + nscoord GetCheckboxRadioPrefSize() override; + protected: nsNativeBasicTheme() = default; virtual ~nsNativeBasicTheme() = default;