Bug 543910 - nsILookAndFeel support for detecting common windows themes. r=neil, a=final.

This commit is contained in:
Jim Mathies 2010-10-09 15:53:44 -05:00
parent d0b53174f7
commit 00bcc039b2
9 changed files with 178 additions and 37 deletions

View File

@ -303,9 +303,27 @@ public:
/** /**
* If this metric != 0, support window dragging on the menubar. * 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; } 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 { enum {
eMetric_ScrollArrowStartBackward = 0x1000, eMetric_ScrollArrowStartBackward = 0x1000,
eMetric_ScrollArrowStartForward = 0x0100, eMetric_ScrollArrowStartForward = 0x0100,

View File

@ -368,6 +368,7 @@ nsLookAndFeel::GetMetric(const nsMetricID aID, PRInt32 &aMetric)
case eMetric_WindowsDefaultTheme: case eMetric_WindowsDefaultTheme:
case eMetric_TouchEnabled: case eMetric_TouchEnabled:
case eMetric_MaemoClassic: case eMetric_MaemoClassic:
case eMetric_WindowsThemeIdentifier:
aMetric = 0; aMetric = 0;
rv = NS_ERROR_NOT_IMPLEMENTED; rv = NS_ERROR_NOT_IMPLEMENTED;
break; break;

View File

@ -382,6 +382,7 @@ NS_IMETHODIMP nsLookAndFeel::GetMetric(const nsMetricID aID, PRInt32 & aMetric)
case eMetric_WindowsDefaultTheme: case eMetric_WindowsDefaultTheme:
case eMetric_TouchEnabled: case eMetric_TouchEnabled:
case eMetric_MaemoClassic: case eMetric_MaemoClassic:
case eMetric_WindowsThemeIdentifier:
aMetric = 0; aMetric = 0;
res = NS_ERROR_NOT_IMPLEMENTED; res = NS_ERROR_NOT_IMPLEMENTED;
break; break;

View File

@ -513,6 +513,7 @@ NS_IMETHODIMP nsLookAndFeel::GetMetric(const nsMetricID aID, PRInt32 & aMetric)
case eMetric_DWMCompositor: case eMetric_DWMCompositor:
case eMetric_WindowsClassic: case eMetric_WindowsClassic:
case eMetric_WindowsDefaultTheme: case eMetric_WindowsDefaultTheme:
case eMetric_WindowsThemeIdentifier:
aMetric = 0; aMetric = 0;
res = NS_ERROR_NOT_IMPLEMENTED; res = NS_ERROR_NOT_IMPLEMENTED;
break; break;

View File

@ -325,6 +325,7 @@ NS_IMETHODIMP nsLookAndFeel::GetMetric(const nsMetricID aID, PRInt32 & aMetric)
case eMetric_WindowsClassic: case eMetric_WindowsClassic:
case eMetric_WindowsDefaultTheme: case eMetric_WindowsDefaultTheme:
case eMetric_TouchEnabled: case eMetric_TouchEnabled:
case eMetric_WindowsThemeIdentifier:
aMetric = 0; aMetric = 0;
res = NS_ERROR_NOT_IMPLEMENTED; res = NS_ERROR_NOT_IMPLEMENTED;
break; break;

View File

@ -450,42 +450,10 @@ NS_IMETHODIMP nsLookAndFeel::GetMetric(const nsMetricID aID, PRInt32 & aMetric)
#endif #endif
break; break;
case eMetric_WindowsDefaultTheme: case eMetric_WindowsDefaultTheme:
aMetric = 0; aMetric = nsUXThemeData::IsDefaultWindowTheme();
#ifndef WINCE break;
if (nsUXThemeData::getCurrentThemeName) { case eMetric_WindowsThemeIdentifier:
WCHAR themeFileName[MAX_PATH + 1] = {L'\0'}; aMetric = nsUXThemeData::GetNativeThemeId();
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;
}
break; break;
case eMetric_MacGraphiteTheme: case eMetric_MacGraphiteTheme:
case eMetric_MaemoClassic: case eMetric_MaemoClassic:

View File

@ -23,6 +23,7 @@
* *
* Contributor(s): * Contributor(s):
* Rob Arnold <robarnold@mozilla.com> (Original Author) * Rob Arnold <robarnold@mozilla.com> (Original Author)
* Jim Mathies <jmathies@mozilla.com>
* *
* Alternatively, the contents of this file may be used under the terms of * 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"), * either of the GNU General Public License Version 2 or later (the "GPL"),
@ -336,3 +337,127 @@ nsUXThemeData::UpdateTitlebarInfo(HWND aWnd)
sTitlebarInfoPopulated = PR_TRUE; 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;
}
}

View File

@ -43,6 +43,7 @@
#include <uxtheme.h> #include <uxtheme.h>
#include "nscore.h" #include "nscore.h"
#include "nsILookAndFeel.h"
#if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN #if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN
#include <dwmapi.h> #include <dwmapi.h>
@ -91,6 +92,22 @@ enum nsUXThemeClass {
eUXNumClasses 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_MINIMIZE 0
#define CMDBUTTONIDX_RESTORE 1 #define CMDBUTTONIDX_RESTORE 1
#define CMDBUTTONIDX_CLOSE 2 #define CMDBUTTONIDX_CLOSE 2
@ -115,6 +132,8 @@ public:
static PRPackedBool sHaveCompositor; static PRPackedBool sHaveCompositor;
static PRBool sTitlebarInfoPopulated; static PRBool sTitlebarInfoPopulated;
static SIZE sCommandButtons[3]; static SIZE sCommandButtons[3];
static nsILookAndFeel::WindowsThemeIdentifier sThemeId;
static PRBool sIsDefaultWindowsTheme;
static void Initialize(); static void Initialize();
static void Teardown(); static void Teardown();
@ -129,6 +148,10 @@ public:
static void InitTitlebarInfo(); static void InitTitlebarInfo();
static void UpdateTitlebarInfo(HWND aWnd); static void UpdateTitlebarInfo(HWND aWnd);
static void UpdateNativeThemeInfo();
static nsILookAndFeel::WindowsThemeIdentifier GetNativeThemeId();
static PRBool IsDefaultWindowTheme();
static inline BOOL IsAppThemed() { static inline BOOL IsAppThemed() {
return isAppThemed && isAppThemed(); return isAppThemed && isAppThemed();
} }

View File

@ -447,6 +447,8 @@ nsWindow::nsWindow() : nsBaseWidget()
// Init titlebar button info for custom frames. // Init titlebar button info for custom frames.
nsUXThemeData::InitTitlebarInfo(); nsUXThemeData::InitTitlebarInfo();
// Init theme data
nsUXThemeData::UpdateNativeThemeInfo();
} // !sInstanceCount } // !sInstanceCount
mIdleService = nsnull; mIdleService = nsnull;
@ -4541,6 +4543,7 @@ PRBool nsWindow::ProcessMessage(UINT msg, WPARAM &wParam, LPARAM &lParam,
{ {
// Update non-client margin offsets // Update non-client margin offsets
UpdateNonClientMargins(); UpdateNonClientMargins();
nsUXThemeData::UpdateNativeThemeInfo();
DispatchStandardEvent(NS_THEMECHANGED); DispatchStandardEvent(NS_THEMECHANGED);