diff --git a/widget/windows/nsNativeThemeWin.cpp b/widget/windows/nsNativeThemeWin.cpp index df7cdf8e59bb..66b0ac0f4672 100644 --- a/widget/windows/nsNativeThemeWin.cpp +++ b/widget/windows/nsNativeThemeWin.cpp @@ -56,7 +56,8 @@ nsNativeThemeWin::nsNativeThemeWin() mProgressDeterminateTimeStamp(TimeStamp::Now()), mProgressIndeterminateTimeStamp(TimeStamp::Now()), mBorderCacheValid(), - mMinimumWidgetSizeCacheValid() { + mMinimumWidgetSizeCacheValid(), + mGutterSizeCacheValid(false) { // If there is a relevant change in forms.css for windows platform, // static widget style variables (e.g. sButtonBorderSize) should be // reinitialized here. @@ -225,6 +226,17 @@ static SIZE GetGutterSize(HANDLE theme, HDC hdc) { return ret; } +SIZE nsNativeThemeWin::GetCachedGutterSize(HANDLE theme) { + if (mGutterSizeCacheValid) { + return mGutterSizeCache; + } + + mGutterSizeCache = GetGutterSize(theme, nullptr); + mGutterSizeCacheValid = true; + + return mGutterSizeCache; +} + /* DrawThemeBGRTLAware - render a theme part based on rtl state. * Some widgets are not direction-neutral and need to be drawn reversed for * RTL. Windows provides a way to do this with SetLayout, but this reverses @@ -2070,9 +2082,9 @@ LayoutDeviceIntSize nsNativeThemeWin::GetMinimumWidgetSize( return Theme::GetMinimumWidgetSize(aPresContext, aFrame, aAppearance); } + mozilla::Maybe themeClass = GetThemeClass(aAppearance); HTHEME theme = NULL; - Maybe themeClass = GetThemeClass(aAppearance); - if (themeClass.isSome()) { + if (!themeClass.isNothing()) { theme = nsUXThemeData::GetTheme(themeClass.value()); } if (!theme) { @@ -2117,7 +2129,28 @@ LayoutDeviceIntSize nsNativeThemeWin::GetMinimumWidgetSize( ScaleForFrameDPI(&result, aFrame); return result; } + case StyleAppearance::Menuitem: + case StyleAppearance::Checkmenuitem: + case StyleAppearance::Radiomenuitem: + if (!IsTopLevelMenu(aFrame)) { + SIZE gutterSize(GetCachedGutterSize(theme)); + LayoutDeviceIntSize result(gutterSize.cx, gutterSize.cy); + ScaleForFrameDPI(&result, aFrame); + return result; + } + break; + case StyleAppearance::Menuimage: + case StyleAppearance::Menucheckbox: + case StyleAppearance::Menuradio: { + SIZE boxSize(GetCachedGutterSize(theme)); + LayoutDeviceIntSize result(boxSize.cx + 2, boxSize.cy); + ScaleForFrameDPI(&result, aFrame); + return result; + } + + case StyleAppearance::Menuitemtext: + return {}; case StyleAppearance::ProgressBar: // Best-fit size for progress meters is too large for most @@ -2302,6 +2335,7 @@ nsNativeThemeWin::ThemeChanged() { nsUXThemeData::Invalidate(); memset(mBorderCacheValid, 0, sizeof(mBorderCacheValid)); memset(mMinimumWidgetSizeCacheValid, 0, sizeof(mMinimumWidgetSizeCacheValid)); + mGutterSizeCacheValid = false; return NS_OK; } @@ -2589,6 +2623,12 @@ LayoutDeviceIntSize nsNativeThemeWin::ClassicGetMinimumWidgetSize( case StyleAppearance::Checkbox: result.width = result.height = 13; break; + case StyleAppearance::Menucheckbox: + case StyleAppearance::Menuradio: + case StyleAppearance::Menuarrow: + result.width = ::GetSystemMetrics(SM_CXMENUCHECK); + result.height = ::GetSystemMetrics(SM_CYMENUCHECK); + break; case StyleAppearance::SpinnerUpbutton: case StyleAppearance::SpinnerDownbutton: result.width = ::GetSystemMetrics(SM_CXVSCROLL); diff --git a/widget/windows/nsNativeThemeWin.h b/widget/windows/nsNativeThemeWin.h index 8125ca2637d8..f56e5f9bc70e 100644 --- a/widget/windows/nsNativeThemeWin.h +++ b/widget/windows/nsNativeThemeWin.h @@ -141,6 +141,8 @@ class nsNativeThemeWin : public Theme { THEMESIZE aSizeReq, LayoutDeviceIntSize* aResult); + SIZE GetCachedGutterSize(HANDLE theme); + private: TimeStamp mProgressDeterminateTimeStamp; TimeStamp mProgressIndeterminateTimeStamp; @@ -163,6 +165,9 @@ class nsNativeThemeWin : public Theme { [(eUXNumClasses * THEME_PART_DISTINCT_VALUE_COUNT + 7) / 8]; LayoutDeviceIntSize mMinimumWidgetSizeCache[eUXNumClasses * THEME_PART_DISTINCT_VALUE_COUNT]; + + bool mGutterSizeCacheValid; + SIZE mGutterSizeCache; }; } // namespace mozilla::widget