Bug 574454 - Implement frame rendering and metrics in native themeing. r=vlad.

This commit is contained in:
Jim Mathies 2010-08-09 20:49:35 -05:00
parent 338ca40404
commit 7ce80112ae
8 changed files with 497 additions and 15 deletions

View File

@ -23,6 +23,7 @@
* Tim Hill (tim@prismelite.com)
* James Ross (silver@warwickcompsoc.co.uk)
* Simon Bünzli (zeniko@gmail.com)
* Jim Mathies (jmathies@mozilla.com)
*
* 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"),
@ -105,8 +106,7 @@ static int FrameRect(HDC inDC, CONST RECT *inRect, HBRUSH inBrush)
return 1;
}
static BOOL
GetViewportOrgEx(HDC hdc, LPPOINT lpPoint)
static BOOL GetViewportOrgEx(HDC hdc, LPPOINT lpPoint)
{
SetViewportOrgEx(hdc, 0, 0, lpPoint);
if (lpPoint->x != 0 || lpPoint->y != 0)
@ -115,12 +115,51 @@ GetViewportOrgEx(HDC hdc, LPPOINT lpPoint)
}
#endif
static inline bool IsHTMLContent(nsIFrame *frame)
static inline PRBool IsHTMLContent(nsIFrame *frame)
{
nsIContent* content = frame->GetContent();
return content && content->IsHTML();
}
static PRInt32 GetTopLevelWindowActiveState(nsIFrame *aFrame)
{
// Get the widget. nsIFrame's GetNearestWidget walks up the view chain
// until it finds a real window.
nsIWidget* widget = aFrame->GetNearestWidget();
nsWindow * window = static_cast<nsWindow*>(widget);
if (widget && !window->IsTopLevelWidget() &&
!(window = window->GetParentWindow(PR_FALSE)))
return PR_FALSE;
if (window->GetWindowHandle() == ::GetActiveWindow())
return mozilla::widget::themeconst::FS_ACTIVE;
return mozilla::widget::themeconst::FS_INACTIVE;
}
static PRInt32 GetWindowFrameButtonState(nsIFrame *aFrame, PRInt32 eventState)
{
if (GetTopLevelWindowActiveState(aFrame) ==
mozilla::widget::themeconst::FS_INACTIVE)
return mozilla::widget::themeconst::BS_INACTIVE;
if (eventState & NS_EVENT_STATE_ACTIVE)
return mozilla::widget::themeconst::BS_PUSHED;
else if (eventState & NS_EVENT_STATE_HOVER)
return mozilla::widget::themeconst::BS_HOT;
else
return mozilla::widget::themeconst::BS_NORMAL;
}
static PRInt32 GetClassicWindowFrameButtonState(PRInt32 eventState)
{
if (eventState & NS_EVENT_STATE_ACTIVE)
return DFCS_BUTTONPUSH|DFCS_PUSHED;
else if (eventState & NS_EVENT_STATE_HOVER)
return DFCS_BUTTONPUSH|DFCS_HOT;
else
return DFCS_BUTTONPUSH;
}
nsNativeThemeWin::nsNativeThemeWin() {
// If there is a relevant change in forms.css for windows platform,
// static widget style variables (e.g. sButtonBorderSize) should be
@ -367,6 +406,16 @@ nsNativeThemeWin::GetTheme(PRUint8 aWidgetType)
case NS_THEME_MENUIMAGE:
case NS_THEME_MENUITEMTEXT:
return nsUXThemeData::GetTheme(eUXMenu);
case NS_THEME_WINDOW_TITLEBAR:
case NS_THEME_WINDOW_TITLEBAR_MAXIMIZED:
case NS_THEME_WINDOW_FRAME_LEFT:
case NS_THEME_WINDOW_FRAME_RIGHT:
case NS_THEME_WINDOW_FRAME_BOTTOM:
case NS_THEME_WINDOW_BUTTON_CLOSE:
case NS_THEME_WINDOW_BUTTON_MINIMIZE:
case NS_THEME_WINDOW_BUTTON_MAXIMIZE:
case NS_THEME_WINDOW_BUTTON_RESTORE:
return nsUXThemeData::GetTheme(eUXWindowFrame);
}
return NULL;
}
@ -976,6 +1025,43 @@ nsNativeThemeWin::GetThemePartAndState(nsIFrame* aFrame, PRUint8 aWidgetType,
aPart = -1;
aState = 0;
return NS_OK;
case NS_THEME_WINDOW_TITLEBAR:
aPart = mozilla::widget::themeconst::WP_CAPTION;
aState = GetTopLevelWindowActiveState(aFrame);
return NS_OK;
case NS_THEME_WINDOW_TITLEBAR_MAXIMIZED:
aPart = mozilla::widget::themeconst::WP_MAXCAPTION;
aState = GetTopLevelWindowActiveState(aFrame);
return NS_OK;
case NS_THEME_WINDOW_FRAME_LEFT:
aPart = mozilla::widget::themeconst::WP_FRAMELEFT;
aState = GetTopLevelWindowActiveState(aFrame);
return NS_OK;
case NS_THEME_WINDOW_FRAME_RIGHT:
aPart = mozilla::widget::themeconst::WP_FRAMERIGHT;
aState = GetTopLevelWindowActiveState(aFrame);
return NS_OK;
case NS_THEME_WINDOW_FRAME_BOTTOM:
aPart = mozilla::widget::themeconst::WP_FRAMEBOTTOM;
aState = GetTopLevelWindowActiveState(aFrame);
return NS_OK;
case NS_THEME_WINDOW_BUTTON_CLOSE:
aPart = mozilla::widget::themeconst::WP_CLOSEBUTTON;
aState = GetWindowFrameButtonState(aFrame, GetContentState(aFrame, aWidgetType));
return NS_OK;
case NS_THEME_WINDOW_BUTTON_MINIMIZE:
aPart = mozilla::widget::themeconst::WP_MINBUTTON;
aState = GetWindowFrameButtonState(aFrame, GetContentState(aFrame, aWidgetType));
return NS_OK;
case NS_THEME_WINDOW_BUTTON_MAXIMIZE:
aPart = mozilla::widget::themeconst::WP_MAXBUTTON;
aState = GetWindowFrameButtonState(aFrame, GetContentState(aFrame, aWidgetType));
return NS_OK;
case NS_THEME_WINDOW_BUTTON_RESTORE:
aPart = mozilla::widget::themeconst::WP_RESTOREBUTTON;
aState = GetWindowFrameButtonState(aFrame, GetContentState(aFrame, aWidgetType));
return NS_OK;
}
aPart = 0;
@ -1026,6 +1112,32 @@ nsNativeThemeWin::DrawWidgetBackground(nsIRenderingContext* aContext,
dr.size.height += 2.0;
}
#if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN
// ^^ without the right sdk, assume xp theming and fall through.
if (nsUXThemeData::CheckForCompositor()) {
switch (aWidgetType) {
case NS_THEME_WINDOW_TITLEBAR:
case NS_THEME_WINDOW_TITLEBAR_MAXIMIZED:
case NS_THEME_WINDOW_FRAME_LEFT:
case NS_THEME_WINDOW_FRAME_RIGHT:
case NS_THEME_WINDOW_FRAME_BOTTOM:
// Nothing to draw, these areas are glass. Minimum dimensions
// should be set, so xul content should be layed out correctly.
return NS_OK;
break;
case NS_THEME_WINDOW_BUTTON_CLOSE:
case NS_THEME_WINDOW_BUTTON_MINIMIZE:
case NS_THEME_WINDOW_BUTTON_MAXIMIZE:
case NS_THEME_WINDOW_BUTTON_RESTORE:
// Not conventional bitmaps, can't be retrieved. If we fall
// through here and call the theme library we'll get aero
// basic bitmaps.
return NS_OK;
break;
}
}
#endif // MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN
nsRefPtr<gfxContext> ctx = aContext->ThebesContext();
gfxWindowsNativeDrawing nativeDrawing(ctx, dr, GetWidgetNativeDrawingFlags(aWidgetType));
@ -1645,6 +1757,50 @@ nsNativeThemeWin::GetMinimumWidgetSize(nsIRenderingContext* aContext, nsIFrame*
sizeReq = TS_MIN;
}
break;
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.
aResult->width = nsUXThemeData::sCommandButtons[CMDBUTTONIDX_RESTORE].cx;
aResult->height = nsUXThemeData::sCommandButtons[CMDBUTTONIDX_RESTORE].cy;
*aIsOverridable = PR_FALSE;
return NS_OK;
case NS_THEME_WINDOW_BUTTON_MINIMIZE:
if (nsWindow::GetWindowsVersion() < VISTA_VERSION)
break;
aResult->width = nsUXThemeData::sCommandButtons[CMDBUTTONIDX_MINIMIZE].cx;
aResult->height = nsUXThemeData::sCommandButtons[CMDBUTTONIDX_MINIMIZE].cy;
*aIsOverridable = PR_FALSE;
return NS_OK;
case NS_THEME_WINDOW_BUTTON_CLOSE:
if (nsWindow::GetWindowsVersion() < VISTA_VERSION)
break;
aResult->width = nsUXThemeData::sCommandButtons[CMDBUTTONIDX_CLOSE].cx;
aResult->height = nsUXThemeData::sCommandButtons[CMDBUTTONIDX_CLOSE].cy;
*aIsOverridable = PR_FALSE;
return NS_OK;
case NS_THEME_WINDOW_TITLEBAR:
case NS_THEME_WINDOW_TITLEBAR_MAXIMIZED:
aResult->height = GetSystemMetrics(SM_CYCAPTION);
aResult->height += GetSystemMetrics(SM_CYFRAME);
*aIsOverridable = PR_FALSE;
return NS_OK;
case NS_THEME_WINDOW_FRAME_LEFT:
case NS_THEME_WINDOW_FRAME_RIGHT:
case NS_THEME_WINDOW_FRAME_BOTTOM:
aResult->width = GetSystemMetrics(SM_CXFRAME);
aResult->height = GetSystemMetrics(SM_CYFRAME);
*aIsOverridable = PR_FALSE;
return NS_OK;
}
PRInt32 part, state;
@ -1703,6 +1859,19 @@ nsNativeThemeWin::WidgetStateChanged(nsIFrame* aFrame, PRUint8 aWidgetType,
return NS_OK;
}
if (aWidgetType == NS_THEME_WINDOW_TITLEBAR ||
aWidgetType == NS_THEME_WINDOW_TITLEBAR_MAXIMIZED ||
aWidgetType == NS_THEME_WINDOW_FRAME_LEFT ||
aWidgetType == NS_THEME_WINDOW_FRAME_RIGHT ||
aWidgetType == NS_THEME_WINDOW_FRAME_BOTTOM ||
aWidgetType == NS_THEME_WINDOW_BUTTON_CLOSE ||
aWidgetType == NS_THEME_WINDOW_BUTTON_MINIMIZE ||
aWidgetType == NS_THEME_WINDOW_BUTTON_MINIMIZE ||
aWidgetType == NS_THEME_WINDOW_BUTTON_RESTORE) {
*aShouldRepaint = PR_TRUE;
return NS_OK;
}
// On Vista, the scrollbar buttons need to change state when the track has/doesn't have hover
if (!nsUXThemeData::sIsVistaOrLater &&
(aWidgetType == NS_THEME_SCROLLBAR_TRACK_VERTICAL ||
@ -1890,6 +2059,15 @@ nsNativeThemeWin::ClassicThemeSupportsWidget(nsPresContext* aPresContext,
case NS_THEME_MENUARROW:
case NS_THEME_MENUSEPARATOR:
case NS_THEME_MENUITEMTEXT:
case NS_THEME_WINDOW_TITLEBAR:
case NS_THEME_WINDOW_TITLEBAR_MAXIMIZED:
case NS_THEME_WINDOW_FRAME_LEFT:
case NS_THEME_WINDOW_FRAME_RIGHT:
case NS_THEME_WINDOW_FRAME_BOTTOM:
case NS_THEME_WINDOW_BUTTON_CLOSE:
case NS_THEME_WINDOW_BUTTON_MINIMIZE:
case NS_THEME_WINDOW_BUTTON_MAXIMIZE:
case NS_THEME_WINDOW_BUTTON_RESTORE:
return PR_TRUE;
}
return PR_FALSE;
@ -2103,6 +2281,36 @@ nsNativeThemeWin::ClassicGetMinimumWidgetSize(nsIRenderingContext* aContext, nsI
aResult->height = 10;
break;
}
case NS_THEME_WINDOW_TITLEBAR_MAXIMIZED:
case NS_THEME_WINDOW_TITLEBAR:
aResult->height = GetSystemMetrics(SM_CYCAPTION);
aResult->height += GetSystemMetrics(SM_CYFRAME);
aResult->width = 0;
break;
case NS_THEME_WINDOW_FRAME_LEFT:
case NS_THEME_WINDOW_FRAME_RIGHT:
aResult->width = GetSystemMetrics(SM_CXFRAME);
aResult->height = 0;
break;
case NS_THEME_WINDOW_FRAME_BOTTOM:
aResult->height = GetSystemMetrics(SM_CYFRAME);
aResult->width = 0;
break;
case NS_THEME_WINDOW_BUTTON_CLOSE:
case NS_THEME_WINDOW_BUTTON_MINIMIZE:
case NS_THEME_WINDOW_BUTTON_MAXIMIZE:
case NS_THEME_WINDOW_BUTTON_RESTORE:
aResult->width = GetSystemMetrics(SM_CXSIZE);
aResult->height = GetSystemMetrics(SM_CYSIZE);
// XXX I have no idea why these caption metrics are always off,
// but they are.
aResult->width -= 2;
aResult->height -= 4;
break;
default:
return NS_ERROR_FAILURE;
}
@ -2387,6 +2595,50 @@ nsresult nsNativeThemeWin::ClassicGetThemePartAndState(nsIFrame* aFrame, PRUint8
aPart = 0;
aState = 0;
return NS_OK;
case NS_THEME_WINDOW_TITLEBAR:
aPart = mozilla::widget::themeconst::WP_CAPTION;
aState = GetTopLevelWindowActiveState(aFrame);
return NS_OK;
case NS_THEME_WINDOW_TITLEBAR_MAXIMIZED:
aPart = mozilla::widget::themeconst::WP_MAXCAPTION;
aState = GetTopLevelWindowActiveState(aFrame);
return NS_OK;
case NS_THEME_WINDOW_FRAME_LEFT:
aPart = mozilla::widget::themeconst::WP_FRAMELEFT;
aState = GetTopLevelWindowActiveState(aFrame);
return NS_OK;
case NS_THEME_WINDOW_FRAME_RIGHT:
aPart = mozilla::widget::themeconst::WP_FRAMERIGHT;
aState = GetTopLevelWindowActiveState(aFrame);
return NS_OK;
case NS_THEME_WINDOW_FRAME_BOTTOM:
aPart = mozilla::widget::themeconst::WP_FRAMEBOTTOM;
aState = GetTopLevelWindowActiveState(aFrame);
return NS_OK;
case NS_THEME_WINDOW_BUTTON_CLOSE:
aPart = DFC_CAPTION;
aState = DFCS_CAPTIONCLOSE |
GetClassicWindowFrameButtonState(GetContentState(aFrame,
aWidgetType));
return NS_OK;
case NS_THEME_WINDOW_BUTTON_MINIMIZE:
aPart = DFC_CAPTION;
aState = DFCS_CAPTIONMIN |
GetClassicWindowFrameButtonState(GetContentState(aFrame,
aWidgetType));
return NS_OK;
case NS_THEME_WINDOW_BUTTON_MAXIMIZE:
aPart = DFC_CAPTION;
aState = DFCS_CAPTIONMAX |
GetClassicWindowFrameButtonState(GetContentState(aFrame,
aWidgetType));
return NS_OK;
case NS_THEME_WINDOW_BUTTON_RESTORE:
aPart = DFC_CAPTION;
aState = DFCS_CAPTIONRESTORE |
GetClassicWindowFrameButtonState(GetContentState(aFrame,
aWidgetType));
return NS_OK;
}
return NS_ERROR_FAILURE;
}
@ -2858,6 +3110,87 @@ RENDER_AGAIN:
break;
}
#endif
case NS_THEME_WINDOW_TITLEBAR:
case NS_THEME_WINDOW_TITLEBAR_MAXIMIZED:
{
// inset the caption area so it doesn't overflow.
RECT rect = widgetRect;
PRInt32 offset = GetSystemMetrics(SM_CXFRAME);
rect.top += offset;
rect.left += offset;
rect.right -= offset;
rect.bottom -= 1;
// if enabled, draw a gradient titlebar background, otherwise
// fill with a solid color.
BOOL bFlag = TRUE;
SystemParametersInfo(SPI_GETGRADIENTCAPTIONS, 0, &bFlag, NULL);
if (!bFlag) {
if (state == mozilla::widget::themeconst::FS_ACTIVE)
FillRect(hdc, &rect, (HBRUSH)(COLOR_ACTIVECAPTION+1));
else
FillRect(hdc, &rect, (HBRUSH)(COLOR_INACTIVECAPTION+1));
} else {
DWORD startColor, endColor;
if (state == mozilla::widget::themeconst::FS_ACTIVE) {
startColor = GetSysColor(COLOR_ACTIVECAPTION);
endColor = GetSysColor(COLOR_GRADIENTACTIVECAPTION);
} else {
startColor = GetSysColor(COLOR_INACTIVECAPTION);
endColor = GetSysColor(COLOR_GRADIENTINACTIVECAPTION);
}
TRIVERTEX vertex[2];
vertex[0].x = rect.left;
vertex[0].y = rect.top;
vertex[0].Red = GetRValue(startColor) << 8;
vertex[0].Green = GetGValue(startColor) << 8;
vertex[0].Blue = GetBValue(startColor) << 8;
vertex[0].Alpha = 0;
vertex[1].x = rect.right;
vertex[1].y = rect.bottom;
vertex[1].Red = GetRValue(endColor) << 8;
vertex[1].Green = GetGValue(endColor) << 8;
vertex[1].Blue = GetBValue(endColor) << 8;
vertex[1].Alpha = 0;
GRADIENT_RECT gRect;
gRect.UpperLeft = 0;
gRect.LowerRight = 1;
// available on win2k & up
GradientFill(hdc, vertex, 2, &gRect, 1, GRADIENT_FILL_RECT_H);
}
// frame things up with the left, top, and right raised borders.
DrawEdge(hdc, &widgetRect, EDGE_RAISED, BF_TOP|BF_LEFT|BF_RIGHT);
break;
}
case NS_THEME_WINDOW_FRAME_LEFT:
DrawEdge(hdc, &widgetRect, EDGE_RAISED, BF_LEFT);
break;
case NS_THEME_WINDOW_FRAME_RIGHT:
DrawEdge(hdc, &widgetRect, EDGE_RAISED, BF_RIGHT);
break;
case NS_THEME_WINDOW_FRAME_BOTTOM:
DrawEdge(hdc, &widgetRect, EDGE_RAISED, BF_BOTTOM);
break;
case NS_THEME_WINDOW_BUTTON_CLOSE:
case NS_THEME_WINDOW_BUTTON_MINIMIZE:
case NS_THEME_WINDOW_BUTTON_MAXIMIZE:
case NS_THEME_WINDOW_BUTTON_RESTORE:
{
PRInt32 oldTA = SetTextAlign(hdc, TA_TOP | TA_LEFT | TA_NOUPDATECP);
DrawFrameControl(hdc, &widgetRect, part, state);
SetTextAlign(hdc, oldTA);
break;
}
default:
rv = NS_ERROR_FAILURE;
break;

View File

@ -227,3 +227,63 @@
// Toolbar separator dimension which can't be gotten from Windows
#define TB_SEPARATOR_HEIGHT 2
namespace mozilla {
namespace widget {
namespace themeconst {
// Pulled from sdk/include/vsstyle.h
enum {
WP_CAPTION = 1,
WP_SMALLCAPTION = 2,
WP_MINCAPTION = 3,
WP_SMALLMINCAPTION = 4,
WP_MAXCAPTION = 5,
WP_SMALLMAXCAPTION = 6,
WP_FRAMELEFT = 7,
WP_FRAMERIGHT = 8,
WP_FRAMEBOTTOM = 9,
WP_SMALLFRAMELEFT = 10,
WP_SMALLFRAMERIGHT = 11,
WP_SMALLFRAMEBOTTOM = 12,
WP_SYSBUTTON = 13,
WP_MDISYSBUTTON = 14,
WP_MINBUTTON = 15,
WP_MDIMINBUTTON = 16,
WP_MAXBUTTON = 17,
WP_CLOSEBUTTON = 18,
WP_SMALLCLOSEBUTTON = 19,
WP_MDICLOSEBUTTON = 20,
WP_RESTOREBUTTON = 21,
WP_MDIRESTOREBUTTON = 22,
WP_HELPBUTTON = 23,
WP_MDIHELPBUTTON = 24,
WP_HORZSCROLL = 25,
WP_HORZTHUMB = 26,
WP_VERTSCROLL = 27,
WP_VERTTHUMB = 28,
WP_DIALOG = 29,
WP_CAPTIONSIZINGTEMPLATE = 30,
WP_SMALLCAPTIONSIZINGTEMPLATE = 31,
WP_FRAMELEFTSIZINGTEMPLATE = 32,
WP_SMALLFRAMELEFTSIZINGTEMPLATE = 33,
WP_FRAMERIGHTSIZINGTEMPLATE = 34,
WP_SMALLFRAMERIGHTSIZINGTEMPLATE = 35,
WP_FRAMEBOTTOMSIZINGTEMPLATE = 36,
WP_SMALLFRAMEBOTTOMSIZINGTEMPLATE = 37,
WP_FRAME = 38,
};
enum FRAMESTATES {
FS_ACTIVE = 1,
FS_INACTIVE = 2,
};
enum {
BS_NORMAL = 1,
BS_HOT = 2,
BS_PUSHED = 3,
BS_DISABLED = 4,
BS_INACTIVE = 5, /* undocumented, inactive caption button */
};
}}} // mozilla::widget::themeconst

View File

@ -70,6 +70,9 @@ nsUXThemeData::sIsVistaOrLater = PR_FALSE;
PRPackedBool
nsUXThemeData::sHaveCompositor = PR_FALSE;
PRBool nsUXThemeData::sTitlebarInfoPopulated = PR_FALSE;
SIZE nsUXThemeData::sCommandButtons[3];
nsUXThemeData::OpenThemeDataPtr nsUXThemeData::openTheme = NULL;
nsUXThemeData::CloseThemeDataPtr nsUXThemeData::closeTheme = NULL;
nsUXThemeData::DrawThemeBackgroundPtr nsUXThemeData::drawThemeBG = NULL;
@ -223,8 +226,48 @@ const wchar_t *nsUXThemeData::GetClassName(nsUXThemeClass cls) {
return L"Listview";
case eUXMenu:
return L"Menu";
case eUXWindowFrame:
return L"Window";
default:
NS_NOTREACHED("unknown uxtheme class");
return L"";
}
}
// static
void
nsUXThemeData::InitTitlebarInfo()
{
// 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;
}
// static
void
nsUXThemeData::UpdateTitlebarInfo(TITLEBARINFOEX& info)
{
if (sTitlebarInfoPopulated)
return;
// 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 ||
(info.rgrect[5].right - info.rgrect[5].left) == 0)
return;
// minimize
sCommandButtons[0].cx = info.rgrect[2].right - info.rgrect[2].left;
sCommandButtons[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;
// close
sCommandButtons[2].cx = info.rgrect[5].right - info.rgrect[5].left;
sCommandButtons[2].cy = info.rgrect[5].bottom - info.rgrect[5].top;
sTitlebarInfoPopulated = PR_TRUE;
}

View File

@ -48,6 +48,8 @@
#include <dwmapi.h>
#endif
#include "nsWindowDefs.h"
// These window messages are not defined in dwmapi.h
#ifndef WM_DWMCOMPOSITIONCHANGED
#define WM_DWMCOMPOSITIONCHANGED 0x031E
@ -85,9 +87,13 @@ enum nsUXThemeClass {
eUXHeader,
eUXListview,
eUXMenu,
eUXWindowFrame,
eUXNumClasses
};
#define CMDBUTTONIDX_MINIMIZE 0
#define CMDBUTTONIDX_RESTORE 1
#define CMDBUTTONIDX_CLOSE 2
class nsUXThemeData {
static HMODULE sThemeDLL;
@ -107,11 +113,18 @@ public:
static PRPackedBool sIsXPOrLater;
static PRPackedBool sIsVistaOrLater;
static PRPackedBool sHaveCompositor;
static PRBool sTitlebarInfoPopulated;
static SIZE sCommandButtons[3];
static void Initialize();
static void Teardown();
static void Invalidate();
static HANDLE GetTheme(nsUXThemeClass cls);
// nsWindow calls this to update desktop settings info
static void InitTitlebarInfo();
static void UpdateTitlebarInfo(TITLEBARINFOEX& info);
static inline BOOL IsAppThemed() {
return isAppThemed && isAppThemed();
}

View File

@ -157,6 +157,7 @@
#include "nsHashKeys.h"
#include "nsString.h"
#include "mozilla/Services.h"
#include "nsNativeThemeWin.h"
#if defined(WINCE)
#include "nsWindowCE.h"
@ -414,29 +415,34 @@ nsWindow::nsWindow() : nsBaseWidget()
// Global initialization
if (!sInstanceCount) {
#if !defined(WINCE)
gKbdLayout.LoadLayout(::GetKeyboardLayout(0));
gKbdLayout.LoadLayout(::GetKeyboardLayout(0));
#endif
// Init IME handler
nsIMM32Handler::Initialize();
// Init IME handler
nsIMM32Handler::Initialize();
#ifdef NS_ENABLE_TSF
nsTextStore::Initialize();
nsTextStore::Initialize();
#endif
#if !defined(WINCE)
if (SUCCEEDED(::OleInitialize(NULL)))
sIsOleInitialized = TRUE;
NS_ASSERTION(sIsOleInitialized, "***** OLE is not initialized!\n");
if (SUCCEEDED(::OleInitialize(NULL)))
sIsOleInitialized = TRUE;
NS_ASSERTION(sIsOleInitialized, "***** OLE is not initialized!\n");
#endif
#if defined(HEAP_DUMP_EVENT)
InitHeapDump();
InitHeapDump();
#endif
#if !defined(WINCE)
InitTrackPointHack();
InitTrackPointHack();
#endif
// Init titlebar button info for custom frames.
if (GetWindowsVersion() >= VISTA_VERSION) {
nsUXThemeData::InitTitlebarInfo();
}
} // !sInstanceCount
mIdleService = nsnull;
@ -1228,6 +1234,16 @@ 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;
}

View File

@ -248,6 +248,7 @@ public:
WNDPROC GetPrevWindowProc() { return mPrevWndProc; }
static nsWindow* GetNSWindowPtr(HWND aWnd);
WindowHook& GetWindowHook() { return mWindowHook; }
nsWindow* GetParentWindow(PRBool aIncludeOwner);
/**
* Misc.
@ -297,7 +298,6 @@ protected:
static BOOL SetNSWindowPtr(HWND aWnd, nsWindow * ptr);
LPARAM lParamToScreen(LPARAM lParam);
LPARAM lParamToClient(LPARAM lParam);
nsWindow* GetParentWindow(PRBool aIncludeOwner);
virtual void SubclassWindow(BOOL bState);
PRBool CanTakeFocus();
PRBool UpdateNonClientMargins(PRInt32 aSizeMode = -1, PRBool aReflowWindow = PR_TRUE);

View File

@ -394,6 +394,7 @@ EventMsgInfo gAllEvents[] = {
{"WM_TABLET_QUERYSYSTEMGESTURESTATUS", 0x02CC},
{"WM_GESTURE", 0x0119},
{"WM_GESTURENOTIFY", 0x011A},
{"WM_GETTITLEBARINFOEX", 0x033F},
{NULL, 0x0}
};

View File

@ -110,6 +110,14 @@
#define FAPPCOMMAND_MASK 0xF000
#ifndef WM_GETTITLEBARINFOEX
#define WM_GETTITLEBARINFOEX 0x033F
#endif
#ifndef CCHILDREN_TITLEBAR
#define CCHILDREN_TITLEBAR 5
#endif
#ifndef APPCOMMAND_BROWSER_BACKWARD
#define APPCOMMAND_BROWSER_BACKWARD 1
#define APPCOMMAND_BROWSER_FORWARD 2
@ -172,8 +180,6 @@
#define MOUSE_INPUT_SOURCE() nsIDOMNSMouseEvent::MOZ_SOURCE_MOUSE
#endif
/**************************************************************
*
* SECTION: enums
@ -259,6 +265,16 @@ struct KeyPair {
: mGeneral(PRUint8(aGeneral)), mSpecific(PRUint8(aSpecific)) {}
};
#ifndef TITLEBARINFOEX
struct TITLEBARINFOEX
{
DWORD cbSize;
RECT rcTitleBar;
DWORD rgstate[CCHILDREN_TITLEBAR + 1];
RECT rgrect[CCHILDREN_TITLEBAR + 1];
};
#endif
/**************************************************************
*
* SECTION: macros