Bug 1693688 - Make the non-native theme not return minimum sizes for checkboxes (and most other widgets). r=spohl,mstange

This matches closer what Chrome and Safari do (Safari paints outside of
the box when this happens, but the layout box still respects the
author), see:

  data:text/html,<button style="padding: 0; width: 0">
  data:text/html,<input type=checkbox style="width: 0">

Etc. For checkboxes, this matches what OSX does, too.

Since we still want checkboxes to be slightly larger than what they'd be
otherwise, we add a hook to tweak it when non-native theme is enabled.

Differential Revision: https://phabricator.services.mozilla.com/D105798
This commit is contained in:
Emilio Cobos Álvarez 2021-02-19 18:42:17 +00:00
Родитель 62af70907e
Коммит d1915bcf15
9 изменённых файлов: 39 добавлений и 22 удалений

Просмотреть файл

@ -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

Просмотреть файл

@ -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;

Просмотреть файл

@ -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.

Просмотреть файл

@ -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

Просмотреть файл

@ -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

Просмотреть файл

@ -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<PathBuilder> 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;
}

Просмотреть файл

@ -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;