diff --git a/widget/public/nsILookAndFeel.h b/widget/public/nsILookAndFeel.h index 252a9dfbc978..ed490b79e4a2 100644 --- a/widget/public/nsILookAndFeel.h +++ b/widget/public/nsILookAndFeel.h @@ -303,9 +303,27 @@ public: /** * If this metric != 0, support window dragging on the menubar. */ - eMetric_MenuBarDrag + eMetric_MenuBarDrag, + /** + * Return the appropriate WindowsThemeIdentifier for the current theme. + */ + eMetric_WindowsThemeIdentifier } nsMetricID; + /** + * Windows themes we currently detect. + */ + enum WindowsThemeIdentifier { + eWindowsTheme_Generic = 0, // unrecognized theme + eWindowsTheme_Classic, + eWindowsTheme_Aero, + eWindowsTheme_LunaBlue, + eWindowsTheme_LunaOlive, + eWindowsTheme_LunaSilver, + eWindowsTheme_Royale, + eWindowsTheme_Zune + }; + enum { eMetric_ScrollArrowStartBackward = 0x1000, eMetric_ScrollArrowStartForward = 0x0100, diff --git a/widget/src/android/nsLookAndFeel.cpp b/widget/src/android/nsLookAndFeel.cpp index 72a62c0e15bc..217ffce64c84 100644 --- a/widget/src/android/nsLookAndFeel.cpp +++ b/widget/src/android/nsLookAndFeel.cpp @@ -368,6 +368,7 @@ nsLookAndFeel::GetMetric(const nsMetricID aID, PRInt32 &aMetric) case eMetric_WindowsDefaultTheme: case eMetric_TouchEnabled: case eMetric_MaemoClassic: + case eMetric_WindowsThemeIdentifier: aMetric = 0; rv = NS_ERROR_NOT_IMPLEMENTED; break; diff --git a/widget/src/cocoa/nsLookAndFeel.mm b/widget/src/cocoa/nsLookAndFeel.mm index f19db57b5469..dfc763f2b4aa 100644 --- a/widget/src/cocoa/nsLookAndFeel.mm +++ b/widget/src/cocoa/nsLookAndFeel.mm @@ -382,6 +382,7 @@ NS_IMETHODIMP nsLookAndFeel::GetMetric(const nsMetricID aID, PRInt32 & aMetric) case eMetric_WindowsDefaultTheme: case eMetric_TouchEnabled: case eMetric_MaemoClassic: + case eMetric_WindowsThemeIdentifier: aMetric = 0; res = NS_ERROR_NOT_IMPLEMENTED; break; diff --git a/widget/src/gtk2/nsLookAndFeel.cpp b/widget/src/gtk2/nsLookAndFeel.cpp index 8d05574008a7..5d248fe651b7 100644 --- a/widget/src/gtk2/nsLookAndFeel.cpp +++ b/widget/src/gtk2/nsLookAndFeel.cpp @@ -513,6 +513,7 @@ NS_IMETHODIMP nsLookAndFeel::GetMetric(const nsMetricID aID, PRInt32 & aMetric) case eMetric_DWMCompositor: case eMetric_WindowsClassic: case eMetric_WindowsDefaultTheme: + case eMetric_WindowsThemeIdentifier: aMetric = 0; res = NS_ERROR_NOT_IMPLEMENTED; break; diff --git a/widget/src/os2/nsLookAndFeel.cpp b/widget/src/os2/nsLookAndFeel.cpp index cb6fbf995dc5..28f44b43130d 100644 --- a/widget/src/os2/nsLookAndFeel.cpp +++ b/widget/src/os2/nsLookAndFeel.cpp @@ -325,6 +325,7 @@ NS_IMETHODIMP nsLookAndFeel::GetMetric(const nsMetricID aID, PRInt32 & aMetric) case eMetric_WindowsClassic: case eMetric_WindowsDefaultTheme: case eMetric_TouchEnabled: + case eMetric_WindowsThemeIdentifier: aMetric = 0; res = NS_ERROR_NOT_IMPLEMENTED; break; diff --git a/widget/src/windows/nsLookAndFeel.cpp b/widget/src/windows/nsLookAndFeel.cpp index c916811f8874..a363e9b53687 100644 --- a/widget/src/windows/nsLookAndFeel.cpp +++ b/widget/src/windows/nsLookAndFeel.cpp @@ -450,42 +450,10 @@ NS_IMETHODIMP nsLookAndFeel::GetMetric(const nsMetricID aID, PRInt32 & aMetric) #endif break; case eMetric_WindowsDefaultTheme: - aMetric = 0; -#ifndef WINCE - if (nsUXThemeData::getCurrentThemeName) { - WCHAR themeFileName[MAX_PATH + 1] = {L'\0'}; - HRESULT hresult = - nsUXThemeData::getCurrentThemeName(themeFileName, MAX_PATH, - NULL, 0, NULL, 0); - - // WIN2K and earlier will not have getCurrentThemeName defined, so - // they will never make it this far. Unless we want to save 6.0 - // users a handful of clock cycles by skipping checks for the - // 5.x themes (or vice-versa), we can use a single loop for all - // the different Windows versions. - if (hresult == S_OK && nsWindow::GetWindowsVersion() <= WIN7_VERSION) { - LPCWSTR defThemes[] = { - L"luna.msstyles", - L"aero.msstyles" - }; - - LPWSTR curTheme = wcsrchr(themeFileName, L'\\'); - curTheme = curTheme ? curTheme + 1 : themeFileName; - - for (unsigned i = 0; i < NS_ARRAY_LENGTH(defThemes); ++i) { - if (!lstrcmpiW(curTheme, defThemes[i])) { - aMetric = 1; - } - } - } else { - res = NS_ERROR_NOT_IMPLEMENTED; - } - } - else -#endif /* WINCE */ - { - res = NS_ERROR_NOT_IMPLEMENTED; - } + aMetric = nsUXThemeData::IsDefaultWindowTheme(); + break; + case eMetric_WindowsThemeIdentifier: + aMetric = nsUXThemeData::GetNativeThemeId(); break; case eMetric_MacGraphiteTheme: case eMetric_MaemoClassic: diff --git a/widget/src/windows/nsUXThemeData.cpp b/widget/src/windows/nsUXThemeData.cpp index 126c6f37326c..350cfbfbbda4 100644 --- a/widget/src/windows/nsUXThemeData.cpp +++ b/widget/src/windows/nsUXThemeData.cpp @@ -23,6 +23,7 @@ * * Contributor(s): * Rob Arnold (Original Author) + * Jim Mathies * * Alternatively, the contents of this file may be used under the terms of * either of the GNU General Public License Version 2 or later (the "GPL"), @@ -336,3 +337,127 @@ nsUXThemeData::UpdateTitlebarInfo(HWND aWnd) sTitlebarInfoPopulated = PR_TRUE; } + +// visual style (aero glass, aero basic) +// theme (aero, luna, zune) +// theme color (silver, olive, blue) +// system colors + +struct THEMELIST { + LPCWSTR name; + int type; +}; + +const THEMELIST knownThemes[] = { + { L"aero.msstyles", WINTHEME_AERO }, + { L"luna.msstyles", WINTHEME_LUNA }, + { L"zune.msstyles", WINTHEME_ZUNE }, + { L"royale.msstyles", WINTHEME_ROYALE } +}; + +const THEMELIST knownColors[] = { + { L"normalcolor", WINTHEMECOLOR_NORMAL }, + { L"homestead", WINTHEMECOLOR_HOMESTEAD }, + { L"metallic", WINTHEMECOLOR_METALLIC } +}; + +nsILookAndFeel::WindowsThemeIdentifier +nsUXThemeData::sThemeId = nsILookAndFeel::eWindowsTheme_Generic; + +PRBool +nsUXThemeData::sIsDefaultWindowsTheme = PR_FALSE; + +// static +nsILookAndFeel::WindowsThemeIdentifier +nsUXThemeData::GetNativeThemeId() +{ + return sThemeId; +} + +// static +PRBool nsUXThemeData::IsDefaultWindowTheme() +{ + return sIsDefaultWindowsTheme; +} + +// static +void +nsUXThemeData::UpdateNativeThemeInfo() +{ + sIsDefaultWindowsTheme = PR_FALSE; + sThemeId = nsILookAndFeel::eWindowsTheme_Generic; + + if (!IsAppThemed() || !getCurrentThemeName) { + sThemeId = nsILookAndFeel::eWindowsTheme_Classic; + return; + } + + WCHAR themeFileName[MAX_PATH + 1]; + WCHAR themeColor[MAX_PATH + 1]; + if (FAILED(getCurrentThemeName(themeFileName, + MAX_PATH, + themeColor, + MAX_PATH, + NULL, 0))) { + sThemeId = nsILookAndFeel::eWindowsTheme_Classic; + return; + } + + LPCWSTR themeName = wcsrchr(themeFileName, L'\\'); + themeName = themeName ? themeName + 1 : themeFileName; + + WindowsTheme theme = WINTHEME_UNRECOGNIZED; + for (int i = 0; i < NS_ARRAY_LENGTH(knownThemes); ++i) { + if (!lstrcmpiW(themeName, knownThemes[i].name)) { + theme = (WindowsTheme)knownThemes[i].type; + break; + } + } + + if (theme == WINTHEME_UNRECOGNIZED) + return; + + if (theme == WINTHEME_AERO || theme == WINTHEME_LUNA) + sIsDefaultWindowsTheme = PR_TRUE; + + if (theme != WINTHEME_LUNA) { + switch(theme) { + case WINTHEME_AERO: + sThemeId = nsILookAndFeel::eWindowsTheme_Aero; + return; + case WINTHEME_ZUNE: + sThemeId = nsILookAndFeel::eWindowsTheme_Zune; + return; + case WINTHEME_ROYALE: + sThemeId = nsILookAndFeel::eWindowsTheme_Royale; + return; + default: + NS_WARNING("unhandled theme type."); + return; + } + } + + // calculate the luna color scheme + WindowsThemeColor color = WINTHEMECOLOR_UNRECOGNIZED; + for (int i = 0; i < NS_ARRAY_LENGTH(knownColors); ++i) { + if (!lstrcmpiW(themeColor, knownColors[i].name)) { + color = (WindowsThemeColor)knownColors[i].type; + break; + } + } + + switch(color) { + case WINTHEMECOLOR_NORMAL: + sThemeId = nsILookAndFeel::eWindowsTheme_LunaBlue; + return; + case WINTHEMECOLOR_HOMESTEAD: + sThemeId = nsILookAndFeel::eWindowsTheme_LunaOlive; + return; + case WINTHEMECOLOR_METALLIC: + sThemeId = nsILookAndFeel::eWindowsTheme_LunaSilver; + return; + default: + NS_WARNING("unhandled theme color."); + return; + } +} diff --git a/widget/src/windows/nsUXThemeData.h b/widget/src/windows/nsUXThemeData.h index ae81115d90c5..d9077608b36c 100644 --- a/widget/src/windows/nsUXThemeData.h +++ b/widget/src/windows/nsUXThemeData.h @@ -43,6 +43,7 @@ #include #include "nscore.h" +#include "nsILookAndFeel.h" #if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN #include @@ -91,6 +92,22 @@ enum nsUXThemeClass { eUXNumClasses }; +// Native windows style constants +enum WindowsTheme { + WINTHEME_UNRECOGNIZED = 0, + WINTHEME_CLASSIC = 1, // no theme + WINTHEME_AERO = 2, + WINTHEME_LUNA = 3, + WINTHEME_ROYALE = 4, + WINTHEME_ZUNE = 5 +}; +enum WindowsThemeColor { + WINTHEMECOLOR_UNRECOGNIZED = 0, + WINTHEMECOLOR_NORMAL = 1, + WINTHEMECOLOR_HOMESTEAD = 2, + WINTHEMECOLOR_METALLIC = 3 +}; + #define CMDBUTTONIDX_MINIMIZE 0 #define CMDBUTTONIDX_RESTORE 1 #define CMDBUTTONIDX_CLOSE 2 @@ -115,6 +132,8 @@ public: static PRPackedBool sHaveCompositor; static PRBool sTitlebarInfoPopulated; static SIZE sCommandButtons[3]; + static nsILookAndFeel::WindowsThemeIdentifier sThemeId; + static PRBool sIsDefaultWindowsTheme; static void Initialize(); static void Teardown(); @@ -129,6 +148,10 @@ public: static void InitTitlebarInfo(); static void UpdateTitlebarInfo(HWND aWnd); + static void UpdateNativeThemeInfo(); + static nsILookAndFeel::WindowsThemeIdentifier GetNativeThemeId(); + static PRBool IsDefaultWindowTheme(); + static inline BOOL IsAppThemed() { return isAppThemed && isAppThemed(); } diff --git a/widget/src/windows/nsWindow.cpp b/widget/src/windows/nsWindow.cpp index 720f258da740..1964b1eb543a 100644 --- a/widget/src/windows/nsWindow.cpp +++ b/widget/src/windows/nsWindow.cpp @@ -447,6 +447,8 @@ nsWindow::nsWindow() : nsBaseWidget() // Init titlebar button info for custom frames. nsUXThemeData::InitTitlebarInfo(); + // Init theme data + nsUXThemeData::UpdateNativeThemeInfo(); } // !sInstanceCount mIdleService = nsnull; @@ -4541,6 +4543,7 @@ PRBool nsWindow::ProcessMessage(UINT msg, WPARAM &wParam, LPARAM &lParam, { // Update non-client margin offsets UpdateNonClientMargins(); + nsUXThemeData::UpdateNativeThemeInfo(); DispatchStandardEvent(NS_THEMECHANGED);