1 /* vim: se cin sw=2 ts=2 et : */
2 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
4 * ***** BEGIN LICENSE BLOCK *****
5 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
7 * The contents of this file are subject to the Mozilla Public License Version
8 * 1.1 (the "License"); you may not use this file except in compliance with
9 * the License. You may obtain a copy of the License at
10 * http://www.mozilla.org/MPL/
12 * Software distributed under the License is distributed on an "AS IS" basis,
13 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14 * for the specific language governing rights and limitations under the
17 * The Original Code is the Mozilla browser.
19 * The Initial Developer of the Original Code is
20 * Netscape Communications Corporation.
21 * Portions created by the Initial Developer are Copyright (C) 1999
22 * the Initial Developer. All Rights Reserved.
25 * Rob Arnold <robarnold@mozilla.com> (Original Author)
26 * Jim Mathies <jmathies@mozilla.com>
28 * Alternatively, the contents of this file may be used under the terms of
29 * either of the GNU General Public License Version 2 or later (the "GPL"),
30 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
31 * in which case the provisions of the GPL or the LGPL are applicable instead
32 * of those above. If you wish to allow use of your version of this file only
33 * under the terms of either the GPL or the LGPL, and not to allow others to
34 * use your version of this file under the terms of the MPL, indicate your
35 * decision by deleting the provisions above and replace them with the notice
36 * and other provisions required by the GPL or the LGPL. If you do not delete
37 * the provisions above, a recipient may use your version of this file under
38 * the terms of any one of the MPL, the GPL or the LGPL.
40 * ***** END LICENSE BLOCK ***** */
42 #include "nsUXThemeData.h"
44 // For GetWindowsVersion
46 #include "nsUXThemeConstants.h"
49 nsUXThemeData::kThemeLibraryName
[] = L
"uxtheme.dll";
50 #if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN
52 nsUXThemeData::kDwmLibraryName
[] = L
"dwmapi.dll";
56 nsUXThemeData::sThemes
[eUXNumClasses
];
59 nsUXThemeData::sThemeDLL
= NULL
;
60 #if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN
62 nsUXThemeData::sDwmDLL
= NULL
;
66 nsUXThemeData::sFlatMenus
= FALSE
;
68 nsUXThemeData::sIsXPOrLater
= PR_FALSE
;
70 nsUXThemeData::sIsVistaOrLater
= PR_FALSE
;
72 PRBool
nsUXThemeData::sTitlebarInfoPopulatedAero
= PR_FALSE
;
73 PRBool
nsUXThemeData::sTitlebarInfoPopulatedThemed
= PR_FALSE
;
74 SIZE
nsUXThemeData::sCommandButtons
[4];
76 nsUXThemeData::OpenThemeDataPtr
nsUXThemeData::openTheme
= NULL
;
77 nsUXThemeData::CloseThemeDataPtr
nsUXThemeData::closeTheme
= NULL
;
78 nsUXThemeData::DrawThemeBackgroundPtr
nsUXThemeData::drawThemeBG
= NULL
;
79 nsUXThemeData::DrawThemeEdgePtr
nsUXThemeData::drawThemeEdge
= NULL
;
80 nsUXThemeData::GetThemeContentRectPtr
nsUXThemeData::getThemeContentRect
= NULL
;
81 nsUXThemeData::GetThemeBackgroundRegionPtr
nsUXThemeData::getThemeBackgroundRegion
= NULL
;
82 nsUXThemeData::GetThemePartSizePtr
nsUXThemeData::getThemePartSize
= NULL
;
83 nsUXThemeData::GetThemeSysFontPtr
nsUXThemeData::getThemeSysFont
= NULL
;
84 nsUXThemeData::GetThemeColorPtr
nsUXThemeData::getThemeColor
= NULL
;
85 nsUXThemeData::GetThemeMarginsPtr
nsUXThemeData::getThemeMargins
= NULL
;
86 nsUXThemeData::IsAppThemedPtr
nsUXThemeData::isAppThemed
= NULL
;
87 nsUXThemeData::GetCurrentThemeNamePtr
nsUXThemeData::getCurrentThemeName
= NULL
;
88 nsUXThemeData::GetThemeSysColorPtr
nsUXThemeData::getThemeSysColor
= NULL
;
89 nsUXThemeData::IsThemeBackgroundPartiallyTransparentPtr
nsUXThemeData::isThemeBackgroundPartiallyTransparent
= NULL
;
91 #if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN
92 nsUXThemeData::DwmExtendFrameIntoClientAreaProc
nsUXThemeData::dwmExtendFrameIntoClientAreaPtr
= NULL
;
93 nsUXThemeData::DwmIsCompositionEnabledProc
nsUXThemeData::dwmIsCompositionEnabledPtr
= NULL
;
94 nsUXThemeData::DwmSetIconicThumbnailProc
nsUXThemeData::dwmSetIconicThumbnailPtr
= NULL
;
95 nsUXThemeData::DwmSetIconicLivePreviewBitmapProc
nsUXThemeData::dwmSetIconicLivePreviewBitmapPtr
= NULL
;
96 nsUXThemeData::DwmGetWindowAttributeProc
nsUXThemeData::dwmGetWindowAttributePtr
= NULL
;
97 nsUXThemeData::DwmSetWindowAttributeProc
nsUXThemeData::dwmSetWindowAttributePtr
= NULL
;
98 nsUXThemeData::DwmInvalidateIconicBitmapsProc
nsUXThemeData::dwmInvalidateIconicBitmapsPtr
= NULL
;
99 nsUXThemeData::DwmDefWindowProcProc
nsUXThemeData::dwmDwmDefWindowProcPtr
= NULL
;
103 nsUXThemeData::Teardown() {
106 FreeLibrary(sThemeDLL
);
107 #if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN
109 FreeLibrary(sDwmDLL
);
114 nsUXThemeData::Initialize()
116 ::ZeroMemory(sThemes
, sizeof(sThemes
));
117 NS_ASSERTION(!sThemeDLL
, "nsUXThemeData being initialized twice!");
119 PRInt32 version
= nsWindow::GetWindowsVersion();
120 sIsXPOrLater
= version
>= WINXP_VERSION
;
121 sIsVistaOrLater
= version
>= VISTA_VERSION
;
124 openTheme
= (OpenThemeDataPtr
)GetProcAddress(sThemeDLL
, "OpenThemeData");
125 closeTheme
= (CloseThemeDataPtr
)GetProcAddress(sThemeDLL
, "CloseThemeData");
126 drawThemeBG
= (DrawThemeBackgroundPtr
)GetProcAddress(sThemeDLL
, "DrawThemeBackground");
127 drawThemeEdge
= (DrawThemeEdgePtr
)GetProcAddress(sThemeDLL
, "DrawThemeEdge");
128 getThemeContentRect
= (GetThemeContentRectPtr
)GetProcAddress(sThemeDLL
, "GetThemeBackgroundContentRect");
129 getThemeBackgroundRegion
= (GetThemeBackgroundRegionPtr
)GetProcAddress(sThemeDLL
, "GetThemeBackgroundRegion");
130 getThemePartSize
= (GetThemePartSizePtr
)GetProcAddress(sThemeDLL
, "GetThemePartSize");
131 getThemeSysFont
= (GetThemeSysFontPtr
)GetProcAddress(sThemeDLL
, "GetThemeSysFont");
132 getThemeColor
= (GetThemeColorPtr
)GetProcAddress(sThemeDLL
, "GetThemeColor");
133 getThemeMargins
= (GetThemeMarginsPtr
)GetProcAddress(sThemeDLL
, "GetThemeMargins");
134 isAppThemed
= (IsAppThemedPtr
)GetProcAddress(sThemeDLL
, "IsAppThemed");
135 getCurrentThemeName
= (GetCurrentThemeNamePtr
)GetProcAddress(sThemeDLL
, "GetCurrentThemeName");
136 getThemeSysColor
= (GetThemeSysColorPtr
)GetProcAddress(sThemeDLL
, "GetThemeSysColor");
137 isThemeBackgroundPartiallyTransparent
= (IsThemeBackgroundPartiallyTransparentPtr
)GetProcAddress(sThemeDLL
, "IsThemeBackgroundPartiallyTransparent");
139 #if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN
141 dwmExtendFrameIntoClientAreaPtr
= (DwmExtendFrameIntoClientAreaProc
)::GetProcAddress(sDwmDLL
, "DwmExtendFrameIntoClientArea");
142 dwmIsCompositionEnabledPtr
= (DwmIsCompositionEnabledProc
)::GetProcAddress(sDwmDLL
, "DwmIsCompositionEnabled");
143 dwmSetIconicThumbnailPtr
= (DwmSetIconicThumbnailProc
)::GetProcAddress(sDwmDLL
, "DwmSetIconicThumbnail");
144 dwmSetIconicLivePreviewBitmapPtr
= (DwmSetIconicLivePreviewBitmapProc
)::GetProcAddress(sDwmDLL
, "DwmSetIconicLivePreviewBitmap");
145 dwmGetWindowAttributePtr
= (DwmGetWindowAttributeProc
)::GetProcAddress(sDwmDLL
, "DwmGetWindowAttribute");
146 dwmSetWindowAttributePtr
= (DwmSetWindowAttributeProc
)::GetProcAddress(sDwmDLL
, "DwmSetWindowAttribute");
147 dwmInvalidateIconicBitmapsPtr
= (DwmInvalidateIconicBitmapsProc
)::GetProcAddress(sDwmDLL
, "DwmInvalidateIconicBitmaps");
148 dwmDwmDefWindowProcPtr
= (DwmDefWindowProcProc
)::GetProcAddress(sDwmDLL
, "DwmDefWindowProc");
149 CheckForCompositor(PR_TRUE
);
157 nsUXThemeData::Invalidate() {
158 for(int i
= 0; i
< eUXNumClasses
; i
++) {
160 closeTheme(sThemes
[i
]);
165 BOOL useFlat
= PR_FALSE
;
166 sFlatMenus
= ::SystemParametersInfo(SPI_GETFLATMENU
, 0, &useFlat
, 0) ?
169 // Contrary to Microsoft's documentation, SPI_GETFLATMENU will not fail
170 // on Windows 2000, and it is also possible (though unlikely) for WIN2K
171 // to be misconfigured in such a way that it would return true, so we
172 // shall give WIN2K special treatment
173 sFlatMenus
= PR_FALSE
;
178 nsUXThemeData::GetTheme(nsUXThemeClass cls
) {
179 NS_ASSERTION(cls
< eUXNumClasses
, "Invalid theme class!");
184 sThemes
[cls
] = openTheme(NULL
, GetClassName(cls
));
190 nsUXThemeData::GetThemeDLL() {
191 if (!sThemeDLL
&& sIsXPOrLater
)
192 sThemeDLL
= ::LoadLibraryW(kThemeLibraryName
);
196 #if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN
198 nsUXThemeData::GetDwmDLL() {
199 if (!sDwmDLL
&& sIsVistaOrLater
)
200 sDwmDLL
= ::LoadLibraryW(kDwmLibraryName
);
205 const wchar_t *nsUXThemeData::GetClassName(nsUXThemeClass cls
) {
216 return L
"Media::Rebar";
217 case eUXCommunicationsRebar
:
218 return L
"Communications::Rebar";
219 case eUXBrowserTabBarRebar
:
220 return L
"BrowserTabBar::Rebar";
223 case eUXMediaToolbar
:
224 return L
"Media::Toolbar";
225 case eUXCommunicationsToolbar
:
226 return L
"Communications::Toolbar";
250 NS_NOTREACHED("unknown uxtheme class");
257 nsUXThemeData::InitTitlebarInfo()
259 // Pre-populate with generic metrics. These likley will not match
260 // the current theme, but they insure the buttons at least show up.
261 sCommandButtons
[0].cx
= GetSystemMetrics(SM_CXSIZE
);
262 sCommandButtons
[0].cy
= GetSystemMetrics(SM_CYSIZE
);
263 sCommandButtons
[1].cx
= sCommandButtons
[2].cx
= sCommandButtons
[0].cx
;
264 sCommandButtons
[1].cy
= sCommandButtons
[2].cy
= sCommandButtons
[0].cy
;
265 sCommandButtons
[3].cx
= sCommandButtons
[0].cx
* 3;
266 sCommandButtons
[3].cy
= sCommandButtons
[0].cy
;
268 // Use system metrics for pre-vista, otherwise trigger a
269 // refresh on the next layout.
270 sTitlebarInfoPopulatedAero
= sTitlebarInfoPopulatedThemed
=
271 (nsWindow::GetWindowsVersion() < VISTA_VERSION
);
276 nsUXThemeData::UpdateTitlebarInfo(HWND aWnd
)
281 #if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN
282 if (!sTitlebarInfoPopulatedAero
&& nsUXThemeData::CheckForCompositor()) {
284 if (SUCCEEDED(nsUXThemeData::dwmGetWindowAttributePtr(aWnd
,
285 DWMWA_CAPTION_BUTTON_BOUNDS
,
287 sizeof(captionButtons
)))) {
288 sCommandButtons
[CMDBUTTONIDX_BUTTONBOX
].cx
= captionButtons
.right
- captionButtons
.left
- 3;
289 sCommandButtons
[CMDBUTTONIDX_BUTTONBOX
].cy
= (captionButtons
.bottom
- captionButtons
.top
) - 1;
290 sTitlebarInfoPopulatedAero
= PR_TRUE
;
295 if (sTitlebarInfoPopulatedThemed
)
298 // Query a temporary, visible window with command buttons to get
299 // the right metrics.
300 nsAutoString className
;
301 className
.AssignLiteral(kClassNameTemp
);
304 wc
.lpfnWndProc
= ::DefWindowProcW
;
307 wc
.hInstance
= nsToolkit::mDllInstance
;
310 wc
.hbrBackground
= NULL
;
311 wc
.lpszMenuName
= NULL
;
312 wc
.lpszClassName
= className
.get();
313 ::RegisterClassW(&wc
);
315 // Create a transparent descendant of the window passed in. This
316 // keeps the window from showing up on the desktop or the taskbar.
317 // Note the parent (browser) window is usually still hidden, we
318 // don't want to display it, so we can't query it directly.
319 HWND hWnd
= CreateWindowExW(WS_EX_LAYERED
,
320 className
.get(), L
"",
322 0, 0, 0, 0, aWnd
, NULL
,
323 nsToolkit::mDllInstance
, NULL
);
324 NS_ASSERTION(hWnd
, "UpdateTitlebarInfo window creation failed.");
326 ShowWindow(hWnd
, SW_SHOW
);
327 TITLEBARINFOEX info
= {0};
328 info
.cbSize
= sizeof(TITLEBARINFOEX
);
329 SendMessage(hWnd
, WM_GETTITLEBARINFOEX
, 0, (LPARAM
)&info
);
332 // Only set if we have valid data for all three buttons we use.
333 if ((info
.rgrect
[2].right
- info
.rgrect
[2].left
) == 0 ||
334 (info
.rgrect
[3].right
- info
.rgrect
[3].left
) == 0 ||
335 (info
.rgrect
[5].right
- info
.rgrect
[5].left
) == 0) {
336 NS_WARNING("WM_GETTITLEBARINFOEX query failed to find usable metrics.");
340 sCommandButtons
[0].cx
= info
.rgrect
[2].right
- info
.rgrect
[2].left
;
341 sCommandButtons
[0].cy
= info
.rgrect
[2].bottom
- info
.rgrect
[2].top
;
343 sCommandButtons
[1].cx
= info
.rgrect
[3].right
- info
.rgrect
[3].left
;
344 sCommandButtons
[1].cy
= info
.rgrect
[3].bottom
- info
.rgrect
[3].top
;
346 sCommandButtons
[2].cx
= info
.rgrect
[5].right
- info
.rgrect
[5].left
;
347 sCommandButtons
[2].cy
= info
.rgrect
[5].bottom
- info
.rgrect
[5].top
;
349 sTitlebarInfoPopulatedThemed
= PR_TRUE
;
352 // visual style (aero glass, aero basic)
353 // theme (aero, luna, zune)
354 // theme color (silver, olive, blue)
362 const THEMELIST knownThemes
[] = {
363 { L
"aero.msstyles", WINTHEME_AERO
},
364 { L
"luna.msstyles", WINTHEME_LUNA
},
365 { L
"zune.msstyles", WINTHEME_ZUNE
},
366 { L
"royale.msstyles", WINTHEME_ROYALE
}
369 const THEMELIST knownColors
[] = {
370 { L
"normalcolor", WINTHEMECOLOR_NORMAL
},
371 { L
"homestead", WINTHEMECOLOR_HOMESTEAD
},
372 { L
"metallic", WINTHEMECOLOR_METALLIC
}
375 nsILookAndFeel::WindowsThemeIdentifier
376 nsUXThemeData::sThemeId
= nsILookAndFeel::eWindowsTheme_Generic
;
379 nsUXThemeData::sIsDefaultWindowsTheme
= PR_FALSE
;
382 nsILookAndFeel::WindowsThemeIdentifier
383 nsUXThemeData::GetNativeThemeId()
389 PRBool
nsUXThemeData::IsDefaultWindowTheme()
391 return sIsDefaultWindowsTheme
;
396 nsUXThemeData::UpdateNativeThemeInfo()
398 // Trigger a refresh of themed button metrics if needed
399 sTitlebarInfoPopulatedThemed
= (nsWindow::GetWindowsVersion() < VISTA_VERSION
);
401 sIsDefaultWindowsTheme
= PR_FALSE
;
402 sThemeId
= nsILookAndFeel::eWindowsTheme_Generic
;
404 if (!IsAppThemed() || !getCurrentThemeName
) {
405 sThemeId
= nsILookAndFeel::eWindowsTheme_Classic
;
409 WCHAR themeFileName
[MAX_PATH
+ 1];
410 WCHAR themeColor
[MAX_PATH
+ 1];
411 if (FAILED(getCurrentThemeName(themeFileName
,
416 sThemeId
= nsILookAndFeel::eWindowsTheme_Classic
;
420 LPCWSTR themeName
= wcsrchr(themeFileName
, L
'\\');
421 themeName
= themeName
? themeName
+ 1 : themeFileName
;
423 WindowsTheme theme
= WINTHEME_UNRECOGNIZED
;
424 for (int i
= 0; i
< NS_ARRAY_LENGTH(knownThemes
); ++i
) {
425 if (!lstrcmpiW(themeName
, knownThemes
[i
].name
)) {
426 theme
= (WindowsTheme
)knownThemes
[i
].type
;
431 if (theme
== WINTHEME_UNRECOGNIZED
)
434 if (theme
== WINTHEME_AERO
|| theme
== WINTHEME_LUNA
)
435 sIsDefaultWindowsTheme
= PR_TRUE
;
437 if (theme
!= WINTHEME_LUNA
) {
440 sThemeId
= nsILookAndFeel::eWindowsTheme_Aero
;
443 sThemeId
= nsILookAndFeel::eWindowsTheme_Zune
;
445 case WINTHEME_ROYALE
:
446 sThemeId
= nsILookAndFeel::eWindowsTheme_Royale
;
449 NS_WARNING("unhandled theme type.");
454 // calculate the luna color scheme
455 WindowsThemeColor color
= WINTHEMECOLOR_UNRECOGNIZED
;
456 for (int i
= 0; i
< NS_ARRAY_LENGTH(knownColors
); ++i
) {
457 if (!lstrcmpiW(themeColor
, knownColors
[i
].name
)) {
458 color
= (WindowsThemeColor
)knownColors
[i
].type
;
464 case WINTHEMECOLOR_NORMAL
:
465 sThemeId
= nsILookAndFeel::eWindowsTheme_LunaBlue
;
467 case WINTHEMECOLOR_HOMESTEAD
:
468 sThemeId
= nsILookAndFeel::eWindowsTheme_LunaOlive
;
470 case WINTHEMECOLOR_METALLIC
:
471 sThemeId
= nsILookAndFeel::eWindowsTheme_LunaSilver
;
474 NS_WARNING("unhandled theme color.");