From 8236eec152a838004dd34de38213729aa11f36bb Mon Sep 17 00:00:00 2001 From: Francis Dominic Fajardo Date: Wed, 25 Jun 2025 15:42:59 +0800 Subject: [PATCH] Issue #2765 - Part 1: Scrollbar width should be treated as a non-inherited property Note: non-inherited properties are stored in "reset" style structs. Previous implementation treats it as an inherited property, which doesn't match the spec. This also fixes the incorrect behavior when using the `unset` value for this property by specifying SETVAL_UNSET_INITIAL in the mask. --- layout/generic/nsGfxScrollFrame.cpp | 6 +++--- layout/style/nsCSSPropList.h | 2 +- layout/style/nsComputedDOMStyle.cpp | 2 +- layout/style/nsRuleNode.cpp | 16 ++++++++-------- layout/style/nsStyleStruct.cpp | 18 +++++++++--------- layout/style/nsStyleStruct.h | 2 +- widget/windows/nsNativeThemeWin.cpp | 2 +- 7 files changed, 24 insertions(+), 24 deletions(-) diff --git a/layout/generic/nsGfxScrollFrame.cpp b/layout/generic/nsGfxScrollFrame.cpp index 8328f70da5..e718315731 100644 --- a/layout/generic/nsGfxScrollFrame.cpp +++ b/layout/generic/nsGfxScrollFrame.cpp @@ -1058,7 +1058,7 @@ nsHTMLScrollFrame::Reflow(nsPresContext* aPresContext, // This is only needed for root element because scrollbars of non- // root elements with "scrollbar-width: none" is already suppressed // in ScrollFrameHelper::CreateAnonymousContent. - if (this->StyleUserInterface()->mScrollbarWidth == StyleScrollbarWidth::None) { + if (this->StyleUIReset()->mScrollbarWidth == StyleScrollbarWidth::None) { state.mVScrollbar = ShowScrollbar::Never; state.mHScrollbar = ShowScrollbar::Never; } @@ -4415,7 +4415,7 @@ ScrollFrameHelper::CreateAnonymousContent( canHaveHorizontal = true; canHaveVertical = true; } else { - if (mOuter->StyleUserInterface()->mScrollbarWidth == StyleScrollbarWidth::None) { + if (mOuter->StyleUIReset()->mScrollbarWidth == StyleScrollbarWidth::None) { // If scrollbar-width is none, don't generate scrollbars. canHaveHorizontal = false; canHaveVertical = false; @@ -4448,7 +4448,7 @@ ScrollFrameHelper::CreateAnonymousContent( kNameSpaceID_XUL, nsIDOMNode::ELEMENT_NODE); NS_ENSURE_TRUE(nodeInfo, NS_ERROR_OUT_OF_MEMORY); - StyleScrollbarWidth scrollWidth = mOuter->StyleUserInterface()->mScrollbarWidth; + StyleScrollbarWidth scrollWidth = mOuter->StyleUIReset()->mScrollbarWidth; if (canHaveHorizontal) { RefPtr ni = nodeInfo; diff --git a/layout/style/nsCSSPropList.h b/layout/style/nsCSSPropList.h index cb8c7b73a7..4367dd1e1e 100644 --- a/layout/style/nsCSSPropList.h +++ b/layout/style/nsCSSPropList.h @@ -3723,7 +3723,7 @@ CSS_PROP_DISPLAY( kScrollSnapTypeKTable, CSS_PROP_NO_OFFSET, eStyleAnimType_Discrete) -CSS_PROP_USERINTERFACE( +CSS_PROP_UIRESET( scrollbar-width, scrollbar_width, ScrollbarWidth, diff --git a/layout/style/nsComputedDOMStyle.cpp b/layout/style/nsComputedDOMStyle.cpp index 33a2836590..357df17662 100644 --- a/layout/style/nsComputedDOMStyle.cpp +++ b/layout/style/nsComputedDOMStyle.cpp @@ -3302,7 +3302,7 @@ nsComputedDOMStyle::DoGetScrollbarWidth() { RefPtr val = new nsROCSSPrimitiveValue; val->SetIdent( - nsCSSProps::ValueToKeywordEnum(StyleUserInterface()->mScrollbarWidth, + nsCSSProps::ValueToKeywordEnum(StyleUIReset()->mScrollbarWidth, nsCSSProps::kScrollbarWidthKTable)); return val.forget(); } diff --git a/layout/style/nsRuleNode.cpp b/layout/style/nsRuleNode.cpp index d1d14d0f7a..21af533726 100644 --- a/layout/style/nsRuleNode.cpp +++ b/layout/style/nsRuleNode.cpp @@ -5377,14 +5377,6 @@ nsRuleNode::ComputeUserInterfaceData(void* aStartStruct, // caret-color: auto, color, inherit setComplexColor(aRuleData->ValueForCaretColor(), &nsStyleUserInterface::mCaretColor); - - // scrollbar-width: auto, thin, none - SetValue(*aRuleData->ValueForScrollbarWidth(), - ui->mScrollbarWidth, - conditions, - SETVAL_ENUMERATED, - parentUI->mScrollbarWidth, - StyleScrollbarWidth::Auto); COMPUTE_END_INHERITED(UserInterface, ui) } @@ -5434,6 +5426,14 @@ nsRuleNode::ComputeUIResetData(void* aStartStruct, parentUI->mWindowShadow, NS_STYLE_WINDOW_SHADOW_DEFAULT); + // scrollbar-width: auto, thin, none + SetValue(*aRuleData->ValueForScrollbarWidth(), + ui->mScrollbarWidth, + conditions, + SETVAL_ENUMERATED | SETVAL_UNSET_INITIAL, + parentUI->mScrollbarWidth, + StyleScrollbarWidth::Auto); + COMPUTE_END_RESET(UIReset, ui) } diff --git a/layout/style/nsStyleStruct.cpp b/layout/style/nsStyleStruct.cpp index 334a6e99a8..2839067a82 100644 --- a/layout/style/nsStyleStruct.cpp +++ b/layout/style/nsStyleStruct.cpp @@ -3924,7 +3924,6 @@ nsStyleUserInterface::nsStyleUserInterface(nsPresContext* aContext) , mPointerEvents(NS_STYLE_POINTER_EVENTS_AUTO) , mCursor(NS_STYLE_CURSOR_AUTO) , mCaretColor(StyleComplexColor::Auto()) - , mScrollbarWidth(StyleScrollbarWidth::Auto) { MOZ_COUNT_CTOR(nsStyleUserInterface); } @@ -3937,7 +3936,6 @@ nsStyleUserInterface::nsStyleUserInterface(const nsStyleUserInterface& aSource) , mCursor(aSource.mCursor) , mCursorImages(aSource.mCursorImages) , mCaretColor(aSource.mCaretColor) - , mScrollbarWidth(aSource.mScrollbarWidth) { MOZ_COUNT_CTOR(nsStyleUserInterface); } @@ -3989,13 +3987,6 @@ nsStyleUserInterface::CalcDifference(const nsStyleUserInterface& aNewData) const if (mCaretColor != aNewData.mCaretColor) { hint |= nsChangeHint_RepaintFrame; } - - if (mScrollbarWidth != aNewData.mScrollbarWidth) { - // For scrollbar-width change, we need some special handling similar - // to overflow properties. Specifically, we may need to reconstruct - // the scrollbar or force reflow of the viewport scrollbar. - hint |= nsChangeHint_ScrollbarChange; - } return hint; } @@ -4010,6 +4001,7 @@ nsStyleUIReset::nsStyleUIReset(nsPresContext* aContext) , mIMEMode(NS_STYLE_IME_MODE_AUTO) , mWindowDragging(StyleWindowDragging::Default) , mWindowShadow(NS_STYLE_WINDOW_SHADOW_DEFAULT) + , mScrollbarWidth(StyleScrollbarWidth::Auto) { MOZ_COUNT_CTOR(nsStyleUIReset); } @@ -4020,6 +4012,7 @@ nsStyleUIReset::nsStyleUIReset(const nsStyleUIReset& aSource) , mIMEMode(aSource.mIMEMode) , mWindowDragging(aSource.mWindowDragging) , mWindowShadow(aSource.mWindowShadow) + , mScrollbarWidth(aSource.mScrollbarWidth) { MOZ_COUNT_CTOR(nsStyleUIReset); } @@ -4050,6 +4043,13 @@ nsStyleUIReset::CalcDifference(const nsStyleUIReset& aNewData) const return nsChangeHint_SchedulePaint; } + if (mScrollbarWidth != aNewData.mScrollbarWidth) { + // For scrollbar-width change, we need some special handling similar + // to overflow properties. Specifically, we may need to reconstruct + // the scrollbar or force reflow of the viewport scrollbar. + return nsChangeHint_ScrollbarChange; + } + return nsChangeHint(0); } diff --git a/layout/style/nsStyleStruct.h b/layout/style/nsStyleStruct.h index b29adafcbe..6bdff04185 100644 --- a/layout/style/nsStyleStruct.h +++ b/layout/style/nsStyleStruct.h @@ -3267,6 +3267,7 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleUIReset uint8_t mIMEMode; // [reset] mozilla::StyleWindowDragging mWindowDragging; // [reset] uint8_t mWindowShadow; // [reset] + mozilla::StyleScrollbarWidth mScrollbarWidth; // [reset] }; struct nsCursorImage @@ -3344,7 +3345,6 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleUserInterface uint8_t mCursor; // [inherited] See nsStyleConsts.h nsTArray mCursorImages; // [inherited] images and coords mozilla::StyleComplexColor mCaretColor; // [inherited] - mozilla::StyleScrollbarWidth mScrollbarWidth; inline uint8_t GetEffectivePointerEvents(nsIFrame* aFrame) const; }; diff --git a/widget/windows/nsNativeThemeWin.cpp b/widget/windows/nsNativeThemeWin.cpp index 84772c25f4..5aab75de26 100644 --- a/widget/windows/nsNativeThemeWin.cpp +++ b/widget/windows/nsNativeThemeWin.cpp @@ -1572,7 +1572,7 @@ GetThemeDpiScaleFactor(nsIFrame* aFrame) static bool IsScrollbarWidthThin(nsIFrame* aFrame) { - return aFrame->StyleUserInterface()->mScrollbarWidth == StyleScrollbarWidth::Thin; + return aFrame->StyleUIReset()->mScrollbarWidth == StyleScrollbarWidth::Thin; } NS_IMETHODIMP