Bug 1369508 - Avoid slow and unnecessary GetSystemMetrics calls for Window's command buttons during startup. r=jimm

MozReview-Commit-ID: FUuPvpjB0pB
This commit is contained in:
Jonathan Watt 2017-06-12 21:11:44 +01:00
parent fa05165f7c
commit 076d1e0023
4 changed files with 89 additions and 36 deletions

View File

@ -2251,22 +2251,22 @@ nsNativeThemeWin::GetMinimumWidgetSize(nsPresContext* aPresContext, nsIFrame* aF
// The only way to get accurate titlebar button info is to query a
// window w/buttons when it's visible. nsWindow takes care of this and
// stores that info in nsUXThemeData.
aResult->width = nsUXThemeData::sCommandButtons[CMDBUTTONIDX_RESTORE].cx;
aResult->height = nsUXThemeData::sCommandButtons[CMDBUTTONIDX_RESTORE].cy;
aResult->width = nsUXThemeData::GetCommandButtonMetrics(CMDBUTTONIDX_RESTORE).cx;
aResult->height = nsUXThemeData::GetCommandButtonMetrics(CMDBUTTONIDX_RESTORE).cy;
AddPaddingRect(aResult, CAPTIONBUTTON_RESTORE);
*aIsOverridable = false;
return rv;
case NS_THEME_WINDOW_BUTTON_MINIMIZE:
aResult->width = nsUXThemeData::sCommandButtons[CMDBUTTONIDX_MINIMIZE].cx;
aResult->height = nsUXThemeData::sCommandButtons[CMDBUTTONIDX_MINIMIZE].cy;
aResult->width = nsUXThemeData::GetCommandButtonMetrics(CMDBUTTONIDX_MINIMIZE).cx;
aResult->height = nsUXThemeData::GetCommandButtonMetrics(CMDBUTTONIDX_MINIMIZE).cy;
AddPaddingRect(aResult, CAPTIONBUTTON_MINIMIZE);
*aIsOverridable = false;
return rv;
case NS_THEME_WINDOW_BUTTON_CLOSE:
aResult->width = nsUXThemeData::sCommandButtons[CMDBUTTONIDX_CLOSE].cx;
aResult->height = nsUXThemeData::sCommandButtons[CMDBUTTONIDX_CLOSE].cy;
aResult->width = nsUXThemeData::GetCommandButtonMetrics(CMDBUTTONIDX_CLOSE).cx;
aResult->height = nsUXThemeData::GetCommandButtonMetrics(CMDBUTTONIDX_CLOSE).cy;
AddPaddingRect(aResult, CAPTIONBUTTON_CLOSE);
*aIsOverridable = false;
return rv;
@ -2291,8 +2291,8 @@ nsNativeThemeWin::GetMinimumWidgetSize(nsPresContext* aPresContext, nsIFrame* aF
case NS_THEME_WINDOW_BUTTON_BOX:
case NS_THEME_WINDOW_BUTTON_BOX_MAXIMIZED:
if (nsUXThemeData::CheckForCompositor()) {
aResult->width = nsUXThemeData::sCommandButtons[CMDBUTTONIDX_BUTTONBOX].cx;
aResult->height = nsUXThemeData::sCommandButtons[CMDBUTTONIDX_BUTTONBOX].cy
aResult->width = nsUXThemeData::GetCommandButtonBoxMetrics().cx;
aResult->height = nsUXThemeData::GetCommandButtonBoxMetrics().cy
- GetSystemMetrics(SM_CYFRAME)
- GetSystemMetrics(SM_CXPADDEDBORDER);
if (aWidgetType == NS_THEME_WINDOW_BUTTON_BOX_MAXIMIZED) {

View File

@ -25,13 +25,17 @@ nsUXThemeData::sThemes[eUXNumClasses];
HMODULE
nsUXThemeData::sThemeDLL = nullptr;
const int NUM_COMMAND_BUTTONS = 3;
SIZE nsUXThemeData::sCommandButtonMetrics[NUM_COMMAND_BUTTONS];
bool nsUXThemeData::sCommandButtonMetricsInitialized = false;
SIZE nsUXThemeData::sCommandButtonBoxMetrics;
bool nsUXThemeData::sCommandButtonBoxMetricsInitialized = false;
bool
nsUXThemeData::sFlatMenus = false;
bool nsUXThemeData::sTitlebarInfoPopulatedAero = false;
bool nsUXThemeData::sTitlebarInfoPopulatedThemed = false;
const int NUM_COMMAND_BUTTONS = 4;
SIZE nsUXThemeData::sCommandButtons[NUM_COMMAND_BUTTONS];
void
nsUXThemeData::Teardown() {
@ -132,16 +136,47 @@ const wchar_t *nsUXThemeData::GetClassName(nsUXThemeClass cls) {
// static
void
nsUXThemeData::InitTitlebarInfo()
nsUXThemeData::EnsureCommandButtonMetrics()
{
// Pre-populate with generic metrics. These likley will not match
// the current theme, but they insure the buttons at least show up.
sCommandButtons[0].cx = GetSystemMetrics(SM_CXSIZE);
sCommandButtons[0].cy = GetSystemMetrics(SM_CYSIZE);
sCommandButtons[1].cx = sCommandButtons[2].cx = sCommandButtons[0].cx;
sCommandButtons[1].cy = sCommandButtons[2].cy = sCommandButtons[0].cy;
sCommandButtons[3].cx = sCommandButtons[0].cx * 3;
sCommandButtons[3].cy = sCommandButtons[0].cy;
if (sCommandButtonMetricsInitialized) {
return;
}
sCommandButtonMetricsInitialized = true;
// This code should never need to be evaluated since we should
// obtain the metrics we need when nsWindow::Create() is called.
// The generic metrics that we set here likley will not match the
// current theme, but they insure the buttons at least show up if
// there is some combination of theme settings that we aren't
// handling in nsWindow::Create().
MOZ_ASSERT_UNREACHABLE("We should avoid expensive GetSystemMetrics calls");
sCommandButtonMetrics[0].cx = GetSystemMetrics(SM_CXSIZE);
sCommandButtonMetrics[0].cy = GetSystemMetrics(SM_CYSIZE);
sCommandButtonMetrics[1].cx = sCommandButtonMetrics[2].cx = sCommandButtonMetrics[0].cx;
sCommandButtonMetrics[1].cy = sCommandButtonMetrics[2].cy = sCommandButtonMetrics[0].cy;
// Trigger a refresh on the next layout.
sTitlebarInfoPopulatedAero = sTitlebarInfoPopulatedThemed = false;
}
// static
void
nsUXThemeData::EnsureCommandButtonBoxMetrics()
{
if (sCommandButtonBoxMetricsInitialized) {
return;
}
sCommandButtonBoxMetricsInitialized = true;
EnsureCommandButtonMetrics();
sCommandButtonBoxMetrics.cx = sCommandButtonMetrics[0].cx
+ sCommandButtonMetrics[1].cx
+ sCommandButtonMetrics[2].cx;
sCommandButtonBoxMetrics.cy = sCommandButtonMetrics[0].cy
+ sCommandButtonMetrics[1].cy
+ sCommandButtonMetrics[2].cy;
// Trigger a refresh on the next layout.
sTitlebarInfoPopulatedAero = sTitlebarInfoPopulatedThemed = false;
@ -160,8 +195,12 @@ nsUXThemeData::UpdateTitlebarInfo(HWND aWnd)
DWMWA_CAPTION_BUTTON_BOUNDS,
&captionButtons,
sizeof(captionButtons)))) {
sCommandButtons[CMDBUTTONIDX_BUTTONBOX].cx = captionButtons.right - captionButtons.left - 3;
sCommandButtons[CMDBUTTONIDX_BUTTONBOX].cy = (captionButtons.bottom - captionButtons.top) - 1;
sCommandButtonBoxMetrics.cx = captionButtons.right - captionButtons.left - 3;
sCommandButtonBoxMetrics.cy = (captionButtons.bottom - captionButtons.top) - 1;
sCommandButtonBoxMetricsInitialized = true;
MOZ_ASSERT(sCommandButtonBoxMetrics.cx > 0 &&
sCommandButtonBoxMetrics.cy > 0,
"We must not cache bad command button box dimensions");
sTitlebarInfoPopulatedAero = true;
}
}
@ -218,21 +257,22 @@ nsUXThemeData::UpdateTitlebarInfo(HWND aWnd)
return;
}
// minimize
sCommandButtons[0].cx = info.rgrect[2].right - info.rgrect[2].left;
sCommandButtons[0].cy = info.rgrect[2].bottom - info.rgrect[2].top;
sCommandButtonMetrics[0].cx = info.rgrect[2].right - info.rgrect[2].left;
sCommandButtonMetrics[0].cy = info.rgrect[2].bottom - info.rgrect[2].top;
// maximize/restore
sCommandButtons[1].cx = info.rgrect[3].right - info.rgrect[3].left;
sCommandButtons[1].cy = info.rgrect[3].bottom - info.rgrect[3].top;
sCommandButtonMetrics[1].cx = info.rgrect[3].right - info.rgrect[3].left;
sCommandButtonMetrics[1].cy = info.rgrect[3].bottom - info.rgrect[3].top;
// close
sCommandButtons[2].cx = info.rgrect[5].right - info.rgrect[5].left;
sCommandButtons[2].cy = info.rgrect[5].bottom - info.rgrect[5].top;
sCommandButtonMetrics[2].cx = info.rgrect[5].right - info.rgrect[5].left;
sCommandButtonMetrics[2].cy = info.rgrect[5].bottom - info.rgrect[5].top;
sCommandButtonMetricsInitialized = true;
#ifdef DEBUG
// Verify that all values for the command buttons are positive values
// otherwise we have cached bad values for the caption buttons
for (int i = 0; i < NUM_COMMAND_BUTTONS; i++) {
MOZ_ASSERT(sCommandButtons[i].cx > 0);
MOZ_ASSERT(sCommandButtons[i].cy > 0);
MOZ_ASSERT(sCommandButtonMetrics[i].cx > 0);
MOZ_ASSERT(sCommandButtonMetrics[i].cy > 0);
}
#endif

View File

@ -81,15 +81,24 @@ enum WindowsThemeColor {
class nsUXThemeData {
static HMODULE sThemeDLL;
static HANDLE sThemes[eUXNumClasses];
// We initialize sCommandButtonBoxMetrics separately as a performance
// optimization to avoid fetching dummy values for sCommandButtonMetrics
// when we don't need those.
static SIZE sCommandButtonMetrics[3];
static bool sCommandButtonMetricsInitialized;
static SIZE sCommandButtonBoxMetrics;
static bool sCommandButtonBoxMetricsInitialized;
static const wchar_t *GetClassName(nsUXThemeClass);
static void EnsureCommandButtonMetrics();
static void EnsureCommandButtonBoxMetrics();
public:
static const wchar_t kThemeLibraryName[];
static bool sFlatMenus;
static bool sTitlebarInfoPopulatedAero;
static bool sTitlebarInfoPopulatedThemed;
static SIZE sCommandButtons[4];
static mozilla::LookAndFeel::WindowsTheme sThemeId;
static bool sIsDefaultWindowsTheme;
static bool sIsHighContrastOn;
@ -101,9 +110,16 @@ public:
static HMODULE GetThemeDLL();
// nsWindow calls this to update desktop settings info
static void InitTitlebarInfo();
static void UpdateTitlebarInfo(HWND aWnd);
static SIZE GetCommandButtonMetrics(int aMetric) {
EnsureCommandButtonMetrics();
return sCommandButtonMetrics[aMetric];
}
static SIZE GetCommandButtonBoxMetrics() {
EnsureCommandButtonBoxMetrics();
return sCommandButtonBoxMetrics;
}
static void UpdateNativeThemeInfo();
static mozilla::LookAndFeel::WindowsTheme GetNativeThemeId();
static bool IsDefaultWindowTheme();

View File

@ -663,8 +663,6 @@ nsWindow::nsWindow()
}
NS_ASSERTION(sIsOleInitialized, "***** OLE is not initialized!\n");
MouseScrollHandler::Initialize();
// Init titlebar button info for custom frames.
nsUXThemeData::InitTitlebarInfo();
// Init theme data
nsUXThemeData::UpdateNativeThemeInfo();
RedirectedKeyDownMessageManager::Forget();
@ -3102,7 +3100,7 @@ void nsWindow::UpdateOpaqueRegion(const LayoutDeviceIntRegion& aOpaqueRegion)
// The minimum glass height must be the caption buttons height,
// otherwise the buttons are drawn incorrectly.
largest.y = std::max<uint32_t>(largest.y,
nsUXThemeData::sCommandButtons[CMDBUTTONIDX_BUTTONBOX].cy);
nsUXThemeData::GetCommandButtonBoxMetrics().cy);
}
margins.cyTopHeight = largest.y;
}
@ -5148,7 +5146,6 @@ nsWindow::ProcessMessage(UINT msg, WPARAM& wParam, LPARAM& lParam,
{
// Update non-client margin offsets
UpdateNonClientMargins();
nsUXThemeData::InitTitlebarInfo();
nsUXThemeData::UpdateNativeThemeInfo();
NotifyThemeChanged();