From 597d3e4c58ef3d7fd3dd7751f7cdb5e307d5daa3 Mon Sep 17 00:00:00 2001 From: Jim Mathies Date: Mon, 9 Aug 2010 20:49:35 -0500 Subject: [PATCH] Bug 574454 - Theme code for caption button box, content padding. r=vlad. --- widget/src/windows/nsNativeThemeWin.cpp | 100 ++++++++++++++++++++++-- widget/src/windows/nsUXThemeData.cpp | 14 +++- widget/src/windows/nsUXThemeData.h | 2 +- widget/src/windows/nsWindow.cpp | 14 +--- 4 files changed, 106 insertions(+), 24 deletions(-) diff --git a/widget/src/windows/nsNativeThemeWin.cpp b/widget/src/windows/nsNativeThemeWin.cpp index d7c50299207..d572df4a58c 100644 --- a/widget/src/windows/nsNativeThemeWin.cpp +++ b/widget/src/windows/nsNativeThemeWin.cpp @@ -139,8 +139,11 @@ static PRInt32 GetTopLevelWindowActiveState(nsIFrame *aFrame) static PRInt32 GetWindowFrameButtonState(nsIFrame *aFrame, PRInt32 eventState) { if (GetTopLevelWindowActiveState(aFrame) == - mozilla::widget::themeconst::FS_INACTIVE) + mozilla::widget::themeconst::FS_INACTIVE) { + if (eventState & NS_EVENT_STATE_HOVER) + return mozilla::widget::themeconst::BS_HOT; return mozilla::widget::themeconst::BS_INACTIVE; + } if (eventState & NS_EVENT_STATE_ACTIVE) return mozilla::widget::themeconst::BS_PUSHED; @@ -160,6 +163,22 @@ static PRInt32 GetClassicWindowFrameButtonState(PRInt32 eventState) return DFCS_BUTTONPUSH; } +static void QueryForButtonData(nsIFrame *aFrame) +{ + if (nsUXThemeData::sTitlebarInfoPopulated) + return; + + nsIWidget* widget = aFrame->GetNearestWidget(); + nsWindow * window = static_cast(widget); + if (!window) + return; + if (!window->IsTopLevelWidget() && + !(window = window->GetParentWindow(PR_FALSE))) + return; + + nsUXThemeData::UpdateTitlebarInfo(window->GetWindowHandle()); +} + nsNativeThemeWin::nsNativeThemeWin() { // If there is a relevant change in forms.css for windows platform, // static widget style variables (e.g. sButtonBorderSize) should be @@ -415,6 +434,8 @@ nsNativeThemeWin::GetTheme(PRUint8 aWidgetType) case NS_THEME_WINDOW_BUTTON_MINIMIZE: case NS_THEME_WINDOW_BUTTON_MAXIMIZE: case NS_THEME_WINDOW_BUTTON_RESTORE: + case NS_THEME_WINDOW_BUTTON_BOX: + case NS_THEME_WINDOW_BUTTON_BOX_MAXIMIZED: return nsUXThemeData::GetTheme(eUXWindowFrame); } return NULL; @@ -1062,6 +1083,11 @@ nsNativeThemeWin::GetThemePartAndState(nsIFrame* aFrame, PRUint8 aWidgetType, aPart = mozilla::widget::themeconst::WP_RESTOREBUTTON; aState = GetWindowFrameButtonState(aFrame, GetContentState(aFrame, aWidgetType)); return NS_OK; + case NS_THEME_WINDOW_BUTTON_BOX: + case NS_THEME_WINDOW_BUTTON_BOX_MAXIMIZED: + aPart = -1; + aState = 0; + return NS_OK; } aPart = 0; @@ -1499,6 +1525,53 @@ nsNativeThemeWin::GetWidgetPadding(nsIDeviceContext* aContext, } HANDLE theme = GetTheme(aWidgetType); + + if (aWidgetType == NS_THEME_WINDOW_BUTTON_BOX || + aWidgetType == NS_THEME_WINDOW_BUTTON_BOX_MAXIMIZED) { + aResult->SizeTo(0, 0, 0, 0); + +#if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN + // aero glass doesn't display custom buttons + if (nsUXThemeData::CheckForCompositor()) + return PR_TRUE; +#endif + + // button padding for standard windows + if (aWidgetType == NS_THEME_WINDOW_BUTTON_BOX) { + aResult->top = GetSystemMetrics(SM_CXFRAME); + if (nsUXThemeData::sIsVistaOrLater) { + aResult->right += 2; + } else { + aResult->right += 1; + } + } + + // Adjust horizontal button padding for maximized windows on XP + if (aWidgetType == NS_THEME_WINDOW_BUTTON_BOX_MAXIMIZED && + !nsUXThemeData::sIsVistaOrLater) { + aResult->right += 1; + } + + // Push buttons down + if (theme) { + aResult->top += 1; + } else { + aResult->top += 2; + } + return PR_TRUE; + } + + // Content padding + if (aWidgetType == NS_THEME_WINDOW_TITLEBAR || + aWidgetType == NS_THEME_WINDOW_TITLEBAR_MAXIMIZED) { + aResult->SizeTo(0, 0, 0, 0); + // Maximized windows have an offscreen offset equal to + // the border padding. (windows quirk) + if (aWidgetType == NS_THEME_WINDOW_TITLEBAR_MAXIMIZED) + aResult->top = GetSystemMetrics(SM_CXFRAME); + return PR_TRUE; + } + if (!theme) return PR_FALSE; @@ -1760,30 +1833,39 @@ nsNativeThemeWin::GetMinimumWidgetSize(nsIRenderingContext* aContext, nsIFrame* case NS_THEME_WINDOW_BUTTON_MAXIMIZE: case NS_THEME_WINDOW_BUTTON_RESTORE: - // For XP, use the theme library dimensions, which seem to be accurate. - if (nsWindow::GetWindowsVersion() < VISTA_VERSION) - break; // 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. + QueryForButtonData(aFrame); aResult->width = nsUXThemeData::sCommandButtons[CMDBUTTONIDX_RESTORE].cx; aResult->height = nsUXThemeData::sCommandButtons[CMDBUTTONIDX_RESTORE].cy; + // For XP, subtract 4 from system metrics dimensions. + if (nsWindow::GetWindowsVersion() == WINXP_VERSION) { + aResult->width -= 4; + aResult->height -= 4; + } *aIsOverridable = PR_FALSE; return NS_OK; case NS_THEME_WINDOW_BUTTON_MINIMIZE: - if (nsWindow::GetWindowsVersion() < VISTA_VERSION) - break; + QueryForButtonData(aFrame); aResult->width = nsUXThemeData::sCommandButtons[CMDBUTTONIDX_MINIMIZE].cx; aResult->height = nsUXThemeData::sCommandButtons[CMDBUTTONIDX_MINIMIZE].cy; + if (nsWindow::GetWindowsVersion() == WINXP_VERSION) { + aResult->width -= 4; + aResult->height -= 4; + } *aIsOverridable = PR_FALSE; return NS_OK; case NS_THEME_WINDOW_BUTTON_CLOSE: - if (nsWindow::GetWindowsVersion() < VISTA_VERSION) - break; + QueryForButtonData(aFrame); aResult->width = nsUXThemeData::sCommandButtons[CMDBUTTONIDX_CLOSE].cx; aResult->height = nsUXThemeData::sCommandButtons[CMDBUTTONIDX_CLOSE].cy; + if (nsWindow::GetWindowsVersion() == WINXP_VERSION) { + aResult->width -= 4; + aResult->height -= 4; + } *aIsOverridable = PR_FALSE; return NS_OK; @@ -2068,6 +2150,8 @@ nsNativeThemeWin::ClassicThemeSupportsWidget(nsPresContext* aPresContext, case NS_THEME_WINDOW_BUTTON_MINIMIZE: case NS_THEME_WINDOW_BUTTON_MAXIMIZE: case NS_THEME_WINDOW_BUTTON_RESTORE: + case NS_THEME_WINDOW_BUTTON_BOX: + case NS_THEME_WINDOW_BUTTON_BOX_MAXIMIZED: return PR_TRUE; } return PR_FALSE; diff --git a/widget/src/windows/nsUXThemeData.cpp b/widget/src/windows/nsUXThemeData.cpp index b996042f27f..fda4648f9f5 100644 --- a/widget/src/windows/nsUXThemeData.cpp +++ b/widget/src/windows/nsUXThemeData.cpp @@ -170,6 +170,8 @@ nsUXThemeData::Invalidate() { // shall give WIN2K special treatment sFlatMenus = PR_FALSE; } + // Refresh titlebar button info + sTitlebarInfoPopulated = PR_FALSE; } HANDLE @@ -244,15 +246,23 @@ nsUXThemeData::InitTitlebarInfo() sCommandButtons[0].cy = GetSystemMetrics(SM_CYSIZE); sCommandButtons[1].cx = sCommandButtons[2].cx = sCommandButtons[0].cx; sCommandButtons[1].cy = sCommandButtons[2].cy = sCommandButtons[0].cy; + + // Use system metrics for pre-vista + if (nsWindow::GetWindowsVersion() < VISTA_VERSION) + sTitlebarInfoPopulated = PR_TRUE; } // static void -nsUXThemeData::UpdateTitlebarInfo(TITLEBARINFOEX& info) +nsUXThemeData::UpdateTitlebarInfo(HWND aWnd) { - if (sTitlebarInfoPopulated) + if (sTitlebarInfoPopulated || !aWnd) return; + TITLEBARINFOEX info = {0}; + info.cbSize = sizeof(TITLEBARINFOEX); + SendMessage(aWnd, WM_GETTITLEBARINFOEX, 0, (LPARAM)&info); + // Only set if we have valid data for all three buttons we use. if ((info.rgrect[2].right - info.rgrect[2].left) == 0 || (info.rgrect[3].right - info.rgrect[3].left) == 0 || diff --git a/widget/src/windows/nsUXThemeData.h b/widget/src/windows/nsUXThemeData.h index 979aa2a1bee..a5c1d09316b 100644 --- a/widget/src/windows/nsUXThemeData.h +++ b/widget/src/windows/nsUXThemeData.h @@ -123,7 +123,7 @@ public: // nsWindow calls this to update desktop settings info static void InitTitlebarInfo(); - static void UpdateTitlebarInfo(TITLEBARINFOEX& info); + static void UpdateTitlebarInfo(HWND aWnd); static inline BOOL IsAppThemed() { return isAppThemed && isAppThemed(); diff --git a/widget/src/windows/nsWindow.cpp b/widget/src/windows/nsWindow.cpp index 3db9c889e01..d98db26b40b 100644 --- a/widget/src/windows/nsWindow.cpp +++ b/widget/src/windows/nsWindow.cpp @@ -440,9 +440,7 @@ nsWindow::nsWindow() : nsBaseWidget() #endif // Init titlebar button info for custom frames. - if (GetWindowsVersion() >= VISTA_VERSION) { - nsUXThemeData::InitTitlebarInfo(); - } + nsUXThemeData::InitTitlebarInfo(); } // !sInstanceCount mIdleService = nsnull; @@ -1234,16 +1232,6 @@ NS_METHOD nsWindow::Show(PRBool bState) Invalidate(PR_FALSE); #endif - // Update titlebar metric info when the window is shown. - if (!nsUXThemeData::sTitlebarInfoPopulated && bState && - GetWindowsVersion() >= VISTA_VERSION && - (mWindowType == eWindowType_toplevel || mWindowType == eWindowType_dialog) && - (mBorderStyle == eBorderStyle_default || mBorderStyle == eBorderStyle_all)) { - TITLEBARINFOEX info = {0}; - info.cbSize = sizeof(TITLEBARINFOEX); - SendMessage(mWnd, WM_GETTITLEBARINFOEX, 0, (LPARAM)&info); - nsUXThemeData::UpdateTitlebarInfo(info); - } return NS_OK; }