From be93c1016de29cf7e6fc4db58563831698071131 Mon Sep 17 00:00:00 2001 From: Stephen Pohl Date: Sun, 26 May 2013 15:05:10 -0700 Subject: [PATCH] Bug 869314: Fix missing dropmarkers in non-native styled combobox controls when overlay scrollbars are used. r=roc --- gfx/src/nsThemeConstants.h | 3 +++ layout/forms/nsComboboxControlFrame.cpp | 18 +++++++++---- layout/generic/nsGfxScrollFrame.cpp | 34 +++++++++++++++++++++++++ layout/generic/nsGfxScrollFrame.h | 11 ++++++++ layout/generic/nsIScrollableFrame.h | 6 ++++- widget/cocoa/nsNativeThemeCocoa.mm | 5 ++++ 6 files changed, 71 insertions(+), 6 deletions(-) diff --git a/gfx/src/nsThemeConstants.h b/gfx/src/nsThemeConstants.h index 0f6fdc9311dc..8e11e8af2063 100644 --- a/gfx/src/nsThemeConstants.h +++ b/gfx/src/nsThemeConstants.h @@ -157,6 +157,9 @@ #define NS_THEME_SCROLLBAR_THUMB_HORIZONTAL 88 #define NS_THEME_SCROLLBAR_THUMB_VERTICAL 89 +// A non-disappearing scrollbar. +#define NS_THEME_SCROLLBAR_NON_DISAPPEARING 90 + // A textfield or text area #define NS_THEME_TEXTFIELD 95 diff --git a/layout/forms/nsComboboxControlFrame.cpp b/layout/forms/nsComboboxControlFrame.cpp index 2bd08d56cfbd..3edd8c98aee4 100644 --- a/layout/forms/nsComboboxControlFrame.cpp +++ b/layout/forms/nsComboboxControlFrame.cpp @@ -56,6 +56,7 @@ #include "mozilla/Likely.h" #include #include "nsTextNode.h" +#include "mozilla/LookAndFeel.h" using namespace mozilla; @@ -738,8 +739,8 @@ nsComboboxControlFrame::GetIntrinsicWidth(nsRenderingContext* aRenderingContext, if (mListControlFrame) { nsIScrollableFrame* scrollable = do_QueryFrame(mListControlFrame); NS_ASSERTION(scrollable, "List must be a scrollable frame"); - scrollbarWidth = - scrollable->GetDesiredScrollbarSizes(presContext, aRenderingContext).LeftRight(); + scrollbarWidth = scrollable->GetNondisappearingScrollbarWidth( + presContext, aRenderingContext); } nscoord displayWidth = 0; @@ -751,11 +752,19 @@ nsComboboxControlFrame::GetIntrinsicWidth(nsRenderingContext* aRenderingContext, if (mDropdownFrame) { nscoord dropdownContentWidth; + bool isUsingOverlayScrollbars = + LookAndFeel::GetInt(LookAndFeel::eIntID_UseOverlayScrollbars) != 0; if (aType == nsLayoutUtils::MIN_WIDTH) { dropdownContentWidth = mDropdownFrame->GetMinWidth(aRenderingContext); + if (isUsingOverlayScrollbars) { + dropdownContentWidth += scrollbarWidth; + } } else { NS_ASSERTION(aType == nsLayoutUtils::PREF_WIDTH, "Unexpected type"); dropdownContentWidth = mDropdownFrame->GetPrefWidth(aRenderingContext); + if (isUsingOverlayScrollbars) { + dropdownContentWidth += scrollbarWidth; + } } dropdownContentWidth = NSCoordSaturatingSubtract(dropdownContentWidth, scrollbarWidth, @@ -850,9 +859,8 @@ nsComboboxControlFrame::Reflow(nsPresContext* aPresContext, else { nsIScrollableFrame* scrollable = do_QueryFrame(mListControlFrame); NS_ASSERTION(scrollable, "List must be a scrollable frame"); - buttonWidth = - scrollable->GetDesiredScrollbarSizes(PresContext(), - aReflowState.rendContext).LeftRight(); + buttonWidth = scrollable->GetNondisappearingScrollbarWidth( + PresContext(), aReflowState.rendContext); if (buttonWidth > aReflowState.ComputedWidth()) { buttonWidth = 0; } diff --git a/layout/generic/nsGfxScrollFrame.cpp b/layout/generic/nsGfxScrollFrame.cpp index 6bb36924331e..f6333dc11573 100644 --- a/layout/generic/nsGfxScrollFrame.cpp +++ b/layout/generic/nsGfxScrollFrame.cpp @@ -932,6 +932,40 @@ nsGfxScrollFrameInner::GetDesiredScrollbarSizes(nsBoxLayoutState* aState) return result; } +nscoord +nsGfxScrollFrameInner::GetNondisappearingScrollbarWidth(nsBoxLayoutState* aState) +{ + NS_ASSERTION(aState && aState->GetRenderingContext(), + "Must have rendering context in layout state for size " + "computations"); + + if (LookAndFeel::GetInt(LookAndFeel::eIntID_UseOverlayScrollbars) != 0) { + // We're using overlay scrollbars, so we need to get the width that + // non-disappearing scrollbars would have. + nsITheme* theme = aState->PresContext()->GetTheme(); + if (theme && + theme->ThemeSupportsWidget(aState->PresContext(), + mVScrollbarBox, + NS_THEME_SCROLLBAR_NON_DISAPPEARING)) { + nsIntSize size; + nsRenderingContext* rendContext = aState->GetRenderingContext(); + if (rendContext) { + bool canOverride = true; + theme->GetMinimumWidgetSize(rendContext, + mVScrollbarBox, + NS_THEME_SCROLLBAR_NON_DISAPPEARING, + &size, + &canOverride); + if (size.width) { + return aState->PresContext()->DevPixelsToAppUnits(size.width); + } + } + } + } + + return GetDesiredScrollbarSizes(aState).LeftRight(); +} + nsresult nsXULScrollFrame::CreateAnonymousContent(nsTArray& aElements) { diff --git a/layout/generic/nsGfxScrollFrame.h b/layout/generic/nsGfxScrollFrame.h index 38dd5d6b3c22..ca4d274ed014 100644 --- a/layout/generic/nsGfxScrollFrame.h +++ b/layout/generic/nsGfxScrollFrame.h @@ -235,6 +235,7 @@ public: } nsMargin GetActualScrollbarSizes() const; nsMargin GetDesiredScrollbarSizes(nsBoxLayoutState* aState); + nscoord GetNondisappearingScrollbarWidth(nsBoxLayoutState* aState); bool IsLTR() const; bool IsScrollbarOnRight() const; bool IsScrollingActive() const { return mScrollingActive || ShouldBuildLayer(); } @@ -486,6 +487,11 @@ public: nsBoxLayoutState bls(aPresContext, aRC, 0); return GetDesiredScrollbarSizes(&bls); } + virtual nscoord GetNondisappearingScrollbarWidth(nsPresContext* aPresContext, + nsRenderingContext* aRC) MOZ_OVERRIDE { + nsBoxLayoutState bls(aPresContext, aRC, 0); + return mInner.GetNondisappearingScrollbarWidth(&bls); + } virtual nsRect GetScrollPortRect() const MOZ_OVERRIDE { return mInner.GetScrollPortRect(); } @@ -744,6 +750,11 @@ public: nsBoxLayoutState bls(aPresContext, aRC, 0); return GetDesiredScrollbarSizes(&bls); } + virtual nscoord GetNondisappearingScrollbarWidth(nsPresContext* aPresContext, + nsRenderingContext* aRC) MOZ_OVERRIDE { + nsBoxLayoutState bls(aPresContext, aRC, 0); + return mInner.GetNondisappearingScrollbarWidth(&bls); + } virtual nsRect GetScrollPortRect() const MOZ_OVERRIDE { return mInner.GetScrollPortRect(); } diff --git a/layout/generic/nsIScrollableFrame.h b/layout/generic/nsIScrollableFrame.h index 725d5f51c4dd..b149b510dcc8 100644 --- a/layout/generic/nsIScrollableFrame.h +++ b/layout/generic/nsIScrollableFrame.h @@ -81,7 +81,11 @@ public: */ virtual nsMargin GetDesiredScrollbarSizes(nsPresContext* aPresContext, nsRenderingContext* aRC) = 0; - + /** + * Return the width for non-disappearing scrollbars. + */ + virtual nscoord GetNondisappearingScrollbarWidth(nsPresContext* aPresContext, + nsRenderingContext* aRC) = 0; /** * Get the area of the scrollport relative to the origin of this frame's * border-box. diff --git a/widget/cocoa/nsNativeThemeCocoa.mm b/widget/cocoa/nsNativeThemeCocoa.mm index ae11394f6d62..4a2760a3c587 100644 --- a/widget/cocoa/nsNativeThemeCocoa.mm +++ b/widget/cocoa/nsNativeThemeCocoa.mm @@ -2846,7 +2846,11 @@ nsNativeThemeCocoa::GetMinimumWidgetSize(nsRenderingContext* aContext, aResult->SizeTo(16, 16); break; } + // Intentional fallthrough to next case. + } + case NS_THEME_SCROLLBAR_NON_DISAPPEARING: + { // yeah, i know i'm cheating a little here, but i figure that it // really doesn't matter if the scrollbar is vertical or horizontal // and the width metric is a really good metric for every piece @@ -3056,6 +3060,7 @@ nsNativeThemeCocoa::ThemeSupportsWidget(nsPresContext* aPresContext, nsIFrame* a case NS_THEME_SCROLLBAR_THUMB_VERTICAL: case NS_THEME_SCROLLBAR_TRACK_VERTICAL: case NS_THEME_SCROLLBAR_TRACK_HORIZONTAL: + case NS_THEME_SCROLLBAR_NON_DISAPPEARING: case NS_THEME_DROPDOWN: case NS_THEME_DROPDOWN_BUTTON: