diff --git a/browser/base/content/browser.xul b/browser/base/content/browser.xul index 46af1ecc3346..7035a520a7ba 100644 --- a/browser/base/content/browser.xul +++ b/browser/base/content/browser.xul @@ -261,7 +261,7 @@ - = 0; i--){ - var anItem = myToolbar.childNodes[i]; - if (anItem.id == "personal-bookmarks") { - break; - } - width -= anItem.boxObject.width; - } + var chevronWidth = 0; chevron.collapsed = false; chevronWidth = chevron.boxObject.width; chevron.collapsed = true; var overflowed = false; - var isLTR=window.getComputedStyle(document.getElementById("PersonalToolbar"),'').direction=='ltr'; - + // This 3 is to account for the 'padding-left: 3px;' in browser.xul. + var usedWidth = 3; for (var i=0; i width) { + if (usedWidth + button.boxObject.width + chevronWidth > width) { overflowed = true; // This button doesn't fit. Show it in the menu. Hide it in the toolbar. if (!button.collapsed) @@ -1016,11 +1009,10 @@ var BookmarksToolbar = if (chevron.collapsed) { chevron.collapsed = false; var overflowPadder = document.getElementById("overflow-padder"); - offset = isLTR ? buttons.boxObject.x - : width - buttons.boxObject.x - buttons.boxObject.width; - overflowPadder.width = width - chevron.boxObject.width - offset; + overflowPadder.width = width - chevron.boxObject.width; } } + usedWidth += button.boxObject.width; } BookmarksToolbarRDFObserver._overflowTimerInEffect = false; }, diff --git a/browser/themes/winstripe/browser/browser.css b/browser/themes/winstripe/browser/browser.css index 30add702d954..4b7f58a16323 100644 --- a/browser/themes/winstripe/browser/browser.css +++ b/browser/themes/winstripe/browser/browser.css @@ -55,6 +55,11 @@ min-height: 26px; } +#navigator-toolbox { + border-bottom-width: 1px; + -moz-border-bottom-colors: ThreeDShadow; +} + /* ..... fix searchbar "add engine" padding issue ..... */ #searchbar .searchbar-dropmarker menuseparator + menuitem { @@ -106,6 +111,8 @@ toolbarbutton.bookmark-item[open="true"] { .bookmarks-toolbar-customize { display: none; max-width: 15em !important; + border: none !important; + -moz-appearance: none !important; } toolbarpaletteitem[place="toolbar"] .bookmarks-toolbar-customize { @@ -136,12 +143,12 @@ menuitem.bookmark-item { /* ..... fix bookmarks padding issue ..... */ -#menu_BookmarksPopup menuitem { --moz-padding-start: 4px; +#menu_BookmarksPopup menuitem, .openintabs-menuitem { + -moz-padding-start: 3px; } #menu_BookmarksPopup menuitem.menuitem-iconic { --moz-padding-start: 0px; + -moz-padding-start: 0px; } diff --git a/layout/style/nsCSSKeywordList.h b/layout/style/nsCSSKeywordList.h index d1227b42b701..c302ec075467 100644 --- a/layout/style/nsCSSKeywordList.h +++ b/layout/style/nsCSSKeywordList.h @@ -144,6 +144,7 @@ CSS_KEY(-moz-malayalam, _moz_malayalam) CSS_KEY(-moz-marker, _moz_marker) // Disabled because not supported correctly. CSS_KEY(-moz-menuhover, _moz_menuhover) CSS_KEY(-moz-menuhovertext, _moz_menuhovertext) +CSS_KEY(-moz-menubarhovertext, _moz_menubarhovertext) CSS_KEY(-moz-middle-with-baseline, _moz_middle_with_baseline) CSS_KEY(-moz-myanmar, _moz_myanmar) CSS_KEY(-moz-none, _moz_none) diff --git a/layout/style/nsCSSProps.cpp b/layout/style/nsCSSProps.cpp index 4ef627eba503..71a88887b811 100644 --- a/layout/style/nsCSSProps.cpp +++ b/layout/style/nsCSSProps.cpp @@ -437,6 +437,7 @@ const PRInt32 nsCSSProps::kColorKTable[] = { eCSSKeyword__moz_mac_accentdarkestshadow, nsILookAndFeel::eColor__moz_mac_accentdarkestshadow, eCSSKeyword__moz_menuhover, nsILookAndFeel::eColor__moz_menuhover, eCSSKeyword__moz_menuhovertext, nsILookAndFeel::eColor__moz_menuhovertext, + eCSSKeyword__moz_menubarhovertext, nsILookAndFeel::eColor__moz_menubarhovertext, eCSSKeyword__moz_visitedhyperlinktext, NS_COLOR_MOZ_VISITEDHYPERLINKTEXT, eCSSKeyword_currentcolor, NS_COLOR_CURRENTCOLOR, eCSSKeyword_UNKNOWN,-1 diff --git a/toolkit/themes/winstripe/global/autocomplete.css b/toolkit/themes/winstripe/global/autocomplete.css index 07a294663c4b..ca1f3a921c1b 100644 --- a/toolkit/themes/winstripe/global/autocomplete.css +++ b/toolkit/themes/winstripe/global/autocomplete.css @@ -100,6 +100,7 @@ textbox.padded { popup[type="autocomplete"], .autocomplete-history-popup { + -moz-appearance: none; border-width: 1px; -moz-border-top-colors: ThreeDDarkShadow; -moz-border-right-colors: ThreeDDarkShadow; diff --git a/toolkit/themes/winstripe/global/global.css b/toolkit/themes/winstripe/global/global.css index ad0920a2d010..41ba2c252d0a 100644 --- a/toolkit/themes/winstripe/global/global.css +++ b/toolkit/themes/winstripe/global/global.css @@ -171,8 +171,6 @@ sidebarheader { height: 25px; background-color: -moz-Dialog; -moz-appearance: toolbox; - border-bottom: 1px solid ThreeDShadow; - border-top: 1px solid ThreeDHighlight; } sidebarheader > label { diff --git a/toolkit/themes/winstripe/global/menu.css b/toolkit/themes/winstripe/global/menu.css index 5366e51699f0..c6d28b925526 100644 --- a/toolkit/themes/winstripe/global/menu.css +++ b/toolkit/themes/winstripe/global/menu.css @@ -46,14 +46,22 @@ menu, menuitem { + -moz-appearance: menuitem; -moz-box-align: center; - border: 1px solid transparent; color: MenuText; font: menu; list-style-image: none; -moz-image-region: auto; } +menuitem[type="checkbox"] { + -moz-appearance: checkmenuitem; +} + +menuitem[type="radio"] { + -moz-appearance: radiomenuitem; +} + menuitem[default="true"] { font-weight: bold; } @@ -70,10 +78,10 @@ menuitem[_moz-menuactive="true"][disabled="true"] { .menu-iconic-accel, .menu-text, .menu-iconic-text { - margin-top: 2px !important; + margin-top: 1px !important; margin-bottom: 2px !important; - -moz-margin-start: 1px !important; - -moz-margin-end: 2px !important; + -moz-margin-start: 0px !important; + -moz-margin-end: 0px !important; color: inherit; } @@ -84,99 +92,64 @@ menuitem[_moz-menuactive="true"][disabled="true"] { .menu-accel, .menu-iconic-accel { - -moz-padding-end: 17px; - -moz-margin-start: 5px; + -moz-margin-end: 19px !important; + -moz-margin-start: 8px !important; color: inherit; } +.menu-iconic-text { + -moz-margin-start: 2px !important; +} + .menu-iconic-left { - min-width: 12px; - margin-top: 2px; - margin-bottom: 2px; - -moz-margin-start: 2px; - -moz-margin-end: 2px; + padding: 1px; + min-width: 15px; + min-height: 15px; } /* ..... menu arrow box ..... */ .menu-right { - margin-top: 0px; - margin-bottom: 1px; - -moz-margin-start: 0px; - -moz-margin-end: 6px; - list-style-image: url("chrome://global/skin/menu/Menu-arrow.png"); + margin-top: 2px; + margin-bottom: 3px; + -moz-padding-end: 6px; + list-style-image: none; -moz-image-region: auto; } -.menu-right[_moz-menuactive="true"] { - list-style-image: url("chrome://global/skin/menu/Menu-arrow-hover.png"); - -moz-image-region: auto; -} - -.menu-right[disabled="true"] { - list-style-image: url("chrome://global/skin/menu/Menu-arrow-disabled.png") !important; - -moz-image-region: auto; -} - -.menu-right[chromedir="rtl"] { - list-style-image: url("chrome://global/skin/menu/Menu-arrow-rtl.png"); -} - -.menu-right[chromedir="rtl"][_moz-menuactive="true"] { - list-style-image: url("chrome://global/skin/menu/Menu-arrow-hover-rtl.png"); -} - -.menu-right[chromedir="rtl"][disabled="true"] { - list-style-image: url("chrome://global/skin/menu/Menu-arrow-disabled-rtl.png") !important; -} - /* ::::: menu/menuitems in menubar ::::: */ menubar > menu { - border: 1px solid transparent !important; - padding-top: 1px; - -moz-padding-end: 3px; - padding-bottom: 1px; - -moz-padding-start: 2px; - margin-top: 0px !important; - margin-bottom: 1px !important; + border: 1px solid transparent; +} +menubar > menu[_moz-menuactive="true"], +menubar > menu[_moz-menuactive="true"][open="true"] { + color: -moz-MenuBarHoverText; } menubar > menu[_moz-menuactive="true"] { - padding: 1px 3px 1px 2px !important; - background-color : Highlight !important; - color: HighlightText !important; - border-top: 1px solid ThreeDHighlight; - border-right: 1px solid ThreeDShadow; - border-bottom: 1px solid ThreeDShadow; - border-left: 1px solid ThreeDHighlight; + border-top-color: ThreeDHighlight; + border-left-color: ThreeDHighlight; + border-right-color: ThreeDShadow; + border-bottom-color: ThreeDShadow; } menubar > menu[_moz-menuactive="true"][open="true"] { - border-top: 1px solid ThreeDShadow; - border-right: 1px solid ThreeDHighlight; - border-bottom: 1px solid ThreeDHighlight; - border-left: 1px solid ThreeDShadow; - padding-top: 1px; - -moz-padding-end: 2px; - padding-bottom: 0px; - -moz-padding-start: 3px; + border-top-color: ThreeDShadow; + border-left-color: ThreeDShadow; + border-right-color: ThreeDHighlight; + border-bottom-color: ThreeDHighlight; } /* ..... internal content .... */ .menubar-left { - margin-top: 0px; - margin-bottom: 0px; - -moz-margin-start: 0px; - -moz-margin-end: 2px; color: inherit; } .menubar-text { - margin-top: 1px; - -moz-margin-end: 4px !important; - margin-bottom: 1px; -moz-margin-start: 5px !important; + -moz-margin-end: 4px !important; padding-top: 1px; + padding-bottom: 3px; color: inherit; } @@ -193,7 +166,7 @@ menupopup > menu[_moz-menuactive="true"], menupopup > menuitem[_moz-menuactive="true"], popup > menu[_moz-menuactive="true"], popup > menuitem[_moz-menuactive="true"] { - background-color: Highlight; + background: Highlight; color: HighlightText; } @@ -228,40 +201,6 @@ menulist > menupopup > menuitem > .menu-iconic-text { margin: 0 !important; } -/* ::::: checkbox menuitem ::::: */ - -menuitem[checked="true"] { - list-style-image: url("chrome://global/skin/menu/menu-check.gif"); - -moz-image-region: auto; -} - -menuitem[checked="true"][disabled="true"] { - list-style-image: url("chrome://global/skin/menu/menu-check-disabled.gif"); - -moz-image-region: auto; -} - -menuitem[checked="true"][_moz-menuactive="true"] { - list-style-image: url("chrome://global/skin/menu/menu-check-hover.gif"); - -moz-image-region: auto; -} - -/* ::::: radio menuitem ::::: */ - -menuitem[checked="true"][type="radio"] { - list-style-image: url("chrome://global/skin/menu/menu-radio.gif"); - -moz-image-region: auto; -} - -menuitem[checked="true"][type="radio"][disabled="true"] { - list-style-image: url("chrome://global/skin/menu/menu-radio-disabled.gif"); - -moz-image-region: auto; -} - -menuitem[checked="true"][type="radio"][_moz-menuactive="true"] { - list-style-image: url("chrome://global/skin/menu/menu-radio-hover.gif"); - -moz-image-region: auto; -} - /* ::::: menuseparator ::::: */ menuseparator { diff --git a/toolkit/themes/winstripe/global/popup.css b/toolkit/themes/winstripe/global/popup.css index 4e20b6bb8560..a661bca81761 100644 --- a/toolkit/themes/winstripe/global/popup.css +++ b/toolkit/themes/winstripe/global/popup.css @@ -46,14 +46,15 @@ menupopup, popup { - border: 1px solid ThreeDShadow; - -moz-border-top-colors: ThreeDShadow; - -moz-border-right-colors: ThreeDShadow; - -moz-border-bottom-colors: ThreeDShadow; - -moz-border-left-colors: ThreeDShadow; - padding: 2px; - min-width: 1px; + -moz-appearance: menupopup; + border: 2px solid; + -moz-border-top-colors: ThreeDLightShadow ThreeDHighlight; + -moz-border-left-colors: ThreeDLightShadow ThreeDHighlight; + -moz-border-right-colors: ThreeDDarkShadow ThreeDShadow; + -moz-border-bottom-colors: ThreeDDarkShadow ThreeDShadow; + padding: 1px; background-color: Menu; + min-width: 1px; } menupopup > menu > menupopup, @@ -91,6 +92,7 @@ tooltip[titletip="true"] { menulist > menupopup, .menulist-menupopup { + -moz-appearance: none; border-width: 1px; -moz-border-top-colors: -moz-FieldText; -moz-border-right-colors: -moz-FieldText; diff --git a/toolkit/themes/winstripe/global/toolbar.css b/toolkit/themes/winstripe/global/toolbar.css index 478a05b71235..b6bcd764c811 100644 --- a/toolkit/themes/winstripe/global/toolbar.css +++ b/toolkit/themes/winstripe/global/toolbar.css @@ -46,24 +46,27 @@ toolbox { -moz-appearance: toolbox; - background-color: -moz-Dialog; - border-top: 2px solid; + border: 2px solid black; -moz-border-top-colors: ThreeDShadow ThreeDHighlight; + -moz-border-left-colors: ThreeDShadow ThreeDHighlight; + -moz-border-right-colors: ThreeDHighlight ThreeDShadow; + -moz-border-bottom-colors: ThreeDHighlight ThreeDShadow; + background-color: ThreeDFace; + color: ButtonText; } /* ::::: toolbar & menubar ::::: */ -toolbar { - min-width: 1px; - min-height: 19px; - border-top: 1px solid ThreeDHighlight; - border-bottom: 1px solid ThreeDShadow; +toolbar, +toolbar[type="menubar"], menubar { + -moz-appearance: toolbar; + border-top: 2px solid black; + -moz-border-top-colors: ThreeDShadow ThreeDHighlight; } -toolbar[type="menubar"], menubar { - min-width: 1px; - border-bottom: 1px solid ThreeDShadow; - border-top: 0px !important; +toolbar:first-child, +toolbar[type="menubar"], menubar:first-child { + border-top: none; } /* ::::: toolbar decorations ::::: */ diff --git a/widget/public/nsILookAndFeel.h b/widget/public/nsILookAndFeel.h index fa6d4e9fa385..8887e8b2dd8f 100644 --- a/widget/public/nsILookAndFeel.h +++ b/widget/public/nsILookAndFeel.h @@ -133,6 +133,7 @@ public: eColor__moz_buttonhovertext, //used to button text, when mouse is over eColor__moz_menuhover, //used to menu item background, when mouse is over eColor__moz_menuhovertext, //used to menu item text, when mouse is over + eColor__moz_menubarhovertext, //used to menu bar item text, when mouse is over //colours needed by Mac Classic skin eColor__moz_mac_focusring, //ring around text fields and lists diff --git a/widget/src/windows/nsLookAndFeel.cpp b/widget/src/windows/nsLookAndFeel.cpp index ac44f1bd26bc..9cb7ad70b865 100644 --- a/widget/src/windows/nsLookAndFeel.cpp +++ b/widget/src/windows/nsLookAndFeel.cpp @@ -40,7 +40,15 @@ #include "nsXPLookAndFeel.h" #include #include "nsWindow.h" - + +// Constants only found in new (98+, 2K+, XP+, etc.) Windows. +#ifndef COLOR_MENUHILIGHT +#define COLOR_MENUHILIGHT 29 +#endif +#ifndef SPI_GETFLATMENU +#define SPI_GETFLATMENU 0x1022 +#endif + nsLookAndFeel::nsLookAndFeel() : nsXPLookAndFeel() { } @@ -221,6 +229,19 @@ nsresult nsLookAndFeel::NativeGetColor(const nsColorID aID, nscolor &aColor) case eColor__moz_buttondefault: idx = COLOR_3DDKSHADOW; break; + case eColor__moz_menubarhovertext: { + BOOL isFlatMenus; + HRESULT rv; + + // This will simply fail on Windows versions prior to XP, so we get + // non-flat as desired. + rv = ::SystemParametersInfo(SPI_GETFLATMENU, 0, &isFlatMenus, 0); + if (rv && isFlatMenus) + idx = COLOR_HIGHLIGHTTEXT; /* flat menus (XP themes and later only) */ + else + idx = COLOR_MENUTEXT; /* 3d menus (pre-XP, some themes) */ + break; + } default: idx = COLOR_WINDOW; break; diff --git a/widget/src/windows/nsNativeThemeWin.cpp b/widget/src/windows/nsNativeThemeWin.cpp index 8b597fdbf1f9..1f0a04713492 100644 --- a/widget/src/windows/nsNativeThemeWin.cpp +++ b/widget/src/windows/nsNativeThemeWin.cpp @@ -21,6 +21,7 @@ * * Contributor(s): * Tim Hill (tim@prismelite.com) + * James Ross (silver@warwickcompsoc.co.uk) * * 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"), @@ -54,6 +55,7 @@ #include "nsILookAndFeel.h" #include "nsIDOMHTMLInputElement.h" #include "nsIMenuFrame.h" +#include "nsIMenuParent.h" #include #ifdef MOZ_CAIRO_GFX @@ -120,6 +122,26 @@ // Dropdown constants #define CBP_DROPMARKER 1 +// Constants only found in new (98+, 2K+, XP+, etc.) Windows. +#ifdef DFCS_HOT +#undef DFCS_HOT +#endif +#define DFCS_HOT 0x00001000 + +#ifdef COLOR_MENUHILIGHT +#undef COLOR_MENUHILIGHT +#endif +#define COLOR_MENUHILIGHT 29 + +#ifdef SPI_GETFLATMENU +#undef SPI_GETFLATMENU +#endif +#define SPI_GETFLATMENU 0x1022 + +// Our extra constants for passing a little but more info to the renderer. +#define DFCS_RTL 0x00010000 +#define DFCS_CONTAINER 0x00020000 + NS_IMPL_ISUPPORTS1(nsNativeThemeWin, nsITheme) typedef HANDLE (WINAPI*OpenThemeDataPtr)(HWND hwnd, LPCWSTR pszClassList); @@ -127,6 +149,10 @@ typedef HRESULT (WINAPI*CloseThemeDataPtr)(HANDLE hTheme); typedef HRESULT (WINAPI*DrawThemeBackgroundPtr)(HANDLE hTheme, HDC hdc, int iPartId, int iStateId, const RECT *pRect, const RECT* pClipRect); +typedef HRESULT (WINAPI*DrawThemeEdgePtr)(HANDLE hTheme, HDC hdc, int iPartId, + int iStateId, const RECT *pRect, + uint uEdge, uint uFlags, + const RECT* pClipRect); typedef HRESULT (WINAPI*GetThemeContentRectPtr)(HANDLE hTheme, HDC hdc, int iPartId, int iStateId, const RECT* pRect, RECT* pContentRect); @@ -140,6 +166,7 @@ typedef HRESULT (WINAPI*GetThemeColorPtr)(HANDLE hTheme, HDC hdc, int iPartId, static OpenThemeDataPtr openTheme = NULL; static CloseThemeDataPtr closeTheme = NULL; static DrawThemeBackgroundPtr drawThemeBG = NULL; +static DrawThemeEdgePtr drawThemeEdge = NULL; static GetThemeContentRectPtr getThemeContentRect = NULL; static GetThemePartSizePtr getThemePartSize = NULL; static GetThemeSysFontPtr getThemeSysFont = NULL; @@ -167,6 +194,7 @@ nsNativeThemeWin::nsNativeThemeWin() { openTheme = (OpenThemeDataPtr)GetProcAddress(mThemeDLL, "OpenThemeData"); closeTheme = (CloseThemeDataPtr)GetProcAddress(mThemeDLL, "CloseThemeData"); drawThemeBG = (DrawThemeBackgroundPtr)GetProcAddress(mThemeDLL, "DrawThemeBackground"); + drawThemeEdge = (DrawThemeEdgePtr)GetProcAddress(mThemeDLL, "DrawThemeEdge"); getThemeContentRect = (GetThemeContentRectPtr)GetProcAddress(mThemeDLL, "GetThemeBackgroundContentRect"); getThemePartSize = (GetThemePartSizePtr)GetProcAddress(mThemeDLL, "GetThemePartSize"); getThemeSysFont = (GetThemeSysFontPtr)GetProcAddress(mThemeDLL, "GetThemeSysFont"); @@ -176,6 +204,9 @@ nsNativeThemeWin::nsNativeThemeWin() { mInputAtom = do_GetAtom("input"); mInputCheckedAtom = do_GetAtom("_moz-input-checked"); mTypeAtom = do_GetAtom("type"); + mMenuActiveAtom = do_GetAtom("_moz-menuactive"); + + UpdateConfig(); // If there is a relevant change in forms.css for windows platform, // static widget style variables (e.g. sButtonBorderSize) should be @@ -200,6 +231,21 @@ static void GetNativeRect(const nsRect& aSrc, RECT& aDst) aDst.right = aSrc.x + aSrc.width; } +void +nsNativeThemeWin::UpdateConfig() +{ + // Check for Windows XP (or later), and check if 'flat menus' are enabled. + BOOL isFlatMenus; + HRESULT rv; + mFlatMenus = PR_FALSE; + + // This will simply fail on Windows versions prior to XP, so we get + // non-flat as desired. + rv = ::SystemParametersInfo(SPI_GETFLATMENU, 0, &isFlatMenus, 0); + if (rv) + mFlatMenus = isFlatMenus; +} + HANDLE nsNativeThemeWin::GetTheme(PRUint8 aWidgetType) { @@ -547,6 +593,21 @@ nsNativeThemeWin::GetThemePartAndState(nsIFrame* aFrame, PRUint8 aWidgetType, aPart = aState = 0; return NS_OK; // These have no part or state. } + case NS_THEME_TOOLBAR: { + // Use -1 to indicate we don't wish to have the theme background drawn + // for this item. We will pass any nessessary information via aState, + // and will render the item using separate code. + aPart = -1; + aState = 0; + if (aFrame) { + nsIContent* content = aFrame->GetContent(); + nsIContent* parent = content->GetParent(); + if (parent && parent->GetChildAt(0) == content) { + aState = 1; + } + } + return NS_OK; + } case NS_THEME_STATUSBAR_PANEL: case NS_THEME_STATUSBAR_RESIZER_PANEL: case NS_THEME_RESIZER: { @@ -745,8 +806,18 @@ nsNativeThemeWin::DrawWidgetBackground(nsIRenderingContext* aContext, // The left edge should not be drawn. Move the widget rect's left coord back. widgetRect.left -= edgeSize; } - - drawThemeBG(theme, hdc, part, state, &widgetRect, &clipRect); + else if (aWidgetType == NS_THEME_TOOLBOX) { + // The toolbox's toolbar elements will show a 1px border top and bottom. + // We want the toolbox's background to end right up against the bottom + // border of the last toolbar, so we simply make it leave a 1px gap at the + // bottom. This gap will get the bottom border of the last toolbar in it. + widgetRect.bottom -= 1; + } + + // If part is negative, the element wishes us to not render a themed + // background, instead opting to be drawn specially below. + if (part >= 0) + drawThemeBG(theme, hdc, part, state, &widgetRect, &clipRect); // Draw focus rectangles for XP HTML checkboxes and radio buttons // XXX it'd be nice to draw these outside of the frame @@ -765,6 +836,15 @@ nsNativeThemeWin::DrawWidgetBackground(nsIRenderingContext* aContext, ::SetTextColor(hdc, oldColor); } } + else if (aWidgetType == NS_THEME_TOOLBAR) { + // state == 1 iff this toolbar is the first inside the toolbox, which + // means we should omit the top border for correct rendering. + if (state == 1) { + drawThemeEdge(theme, hdc, 0, 0, &widgetRect, BDR_RAISEDINNER, BF_BOTTOM, &clipRect); + } else { + drawThemeEdge(theme, hdc, 0, 0, &widgetRect, BDR_RAISEDINNER, BF_TOP | BF_BOTTOM, &clipRect); + } + } RestoreDC(hdc, -1); @@ -784,11 +864,26 @@ nsNativeThemeWin::GetWidgetBorder(nsIDeviceContext* aContext, (*aResult).top = (*aResult).bottom = (*aResult).left = (*aResult).right = 0; if (!WidgetIsContainer(aWidgetType) || - aWidgetType == NS_THEME_TOOLBOX || aWidgetType == NS_THEME_TOOLBAR || + aWidgetType == NS_THEME_TOOLBOX || aWidgetType == NS_THEME_STATUSBAR || aWidgetType == NS_THEME_RESIZER || aWidgetType == NS_THEME_TAB_PANEL) return NS_OK; // Don't worry about it. - + + if (aWidgetType == NS_THEME_TOOLBAR) { + // A normal toolbar has a 1px border above and below it, with 2px of + // space either size. If it is the first toolbar, no top border is needed. + aResult->top = aResult->bottom = 1; + aResult->left = 2; + if (aFrame) { + nsIContent* content = aFrame->GetContent(); + nsIContent* parent = content->GetParent(); + if (parent && parent->GetChildAt(0) == content) { + aResult->top = 0; + } + } + return NS_OK; + } + if (!getThemeContentRect) return NS_ERROR_FAILURE; @@ -940,7 +1035,8 @@ nsNativeThemeWin::WidgetStateChanged(nsIFrame* aFrame, PRUint8 aWidgetType, // disabled, checked, dlgtype, default, etc. *aShouldRepaint = PR_FALSE; if (aAttribute == mDisabledAtom || aAttribute == mCheckedAtom || - aAttribute == mSelectedAtom || aAttribute == mReadOnlyAtom) + aAttribute == mSelectedAtom || aAttribute == mReadOnlyAtom || + aAttribute == mMenuActiveAtom) *aShouldRepaint = PR_TRUE; } @@ -1004,6 +1100,7 @@ NS_IMETHODIMP nsNativeThemeWin::ThemeChanged() { CloseData(); + UpdateConfig(); return NS_OK; } @@ -1086,6 +1183,11 @@ nsNativeThemeWin::ClassicThemeSupportsWidget(nsPresContext* aPresContext, case NS_THEME_TAB_RIGHT_EDGE: case NS_THEME_TAB_PANEL: case NS_THEME_TAB_PANELS: + case NS_THEME_MENUBAR: + case NS_THEME_MENUPOPUP: + case NS_THEME_MENUITEM: + case NS_THEME_CHECKMENUITEM: + case NS_THEME_RADIOMENUITEM: return PR_TRUE; } return PR_FALSE; @@ -1147,6 +1249,39 @@ nsNativeThemeWin::ClassicGetWidgetBorder(nsIDeviceContext* aContext, case NS_THEME_PROGRESSBAR_VERTICAL: (*aResult).top = (*aResult).left = (*aResult).bottom = (*aResult).right = 1; break; + case NS_THEME_MENUBAR: + (*aResult).top = (*aResult).left = (*aResult).bottom = (*aResult).right = 0; + break; + case NS_THEME_MENUPOPUP: + (*aResult).top = (*aResult).left = (*aResult).bottom = (*aResult).right = 2; + break; + case NS_THEME_MENUITEM: + case NS_THEME_CHECKMENUITEM: + case NS_THEME_RADIOMENUITEM: { + PRBool isTopLevel = PR_FALSE; + nsIMenuFrame *menuFrame = nsnull; + CallQueryInterface(aFrame, &menuFrame); + + if (menuFrame) { + // If this is a real menu item, we should check if it is part of the + // main menu bar or not, as this affects rendering. + nsIMenuParent *menuParent = menuFrame->GetMenuParent(); + if (menuParent) + menuParent->IsMenuBar(isTopLevel); + } + + // These values are obtained from visual inspection of equivelant + // native components. + if (isTopLevel) { + (*aResult).top = (*aResult).bottom = 1; + (*aResult).left = 3; + (*aResult).right = 4; + } else { + (*aResult).top = 0; + (*aResult).bottom = (*aResult).left = (*aResult).right = 1; + } + break; + } default: (*aResult).top = (*aResult).bottom = (*aResult).left = (*aResult).right = 0; break; @@ -1318,6 +1453,58 @@ nsresult nsNativeThemeWin::ClassicGetThemePartAndState(nsIFrame* aFrame, PRUint8 return NS_OK; } + case NS_THEME_MENUITEM: + case NS_THEME_CHECKMENUITEM: + case NS_THEME_RADIOMENUITEM: { + PRBool isTopLevel = PR_FALSE; + PRBool isOpen = PR_FALSE; + PRBool isContainer = PR_FALSE; + nsIMenuFrame *menuFrame = nsnull; + CallQueryInterface(aFrame, &menuFrame); + + // We indicate top-level-ness using aPart. 0 is a normal menu item, + // 1 is a top-level menu item. The state of the item is composed of + // DFCS_* flags only. + aPart = 0; + aState = 0; + + if (menuFrame) { + // If this is a real menu item, we should check if it is part of the + // main menu bar or not, and if it is a container, as these affect + // rendering. + nsIMenuParent *menuParent = menuFrame->GetMenuParent(); + if (menuParent) + menuParent->IsMenuBar(isTopLevel); + menuFrame->MenuIsOpen(isOpen); + menuFrame->MenuIsContainer(isContainer); + } + + if (IsDisabled(aFrame)) + aState |= DFCS_INACTIVE; + + if (isTopLevel) { + aPart = 1; + if (isOpen) + aState |= DFCS_PUSHED; + } else { + if (isContainer) + aState |= DFCS_CONTAINER; + if (aFrame->GetStyleVisibility()->mDirection == NS_STYLE_DIRECTION_RTL) + aState |= DFCS_RTL; + } + + if (CheckBooleanAttr(aFrame, mMenuActiveAtom)) + aState |= DFCS_HOT; + + // Only menu items of the appropriate type may have tick or bullet marks. + if (aWidgetType == NS_THEME_CHECKMENUITEM || + aWidgetType == NS_THEME_RADIOMENUITEM) { + if (IsCheckedButton(aFrame)) + aState |= DFCS_CHECKED; + } + + return NS_OK; + } case NS_THEME_LISTBOX: case NS_THEME_TREEVIEW: case NS_THEME_TEXTFIELD: @@ -1340,6 +1527,8 @@ nsresult nsNativeThemeWin::ClassicGetThemePartAndState(nsIFrame* aFrame, PRUint8 case NS_THEME_TAB_RIGHT_EDGE: case NS_THEME_TAB_PANEL: case NS_THEME_TAB_PANELS: + case NS_THEME_MENUBAR: + case NS_THEME_MENUPOPUP: // these don't use DrawFrameControl return NS_OK; case NS_THEME_DROPDOWN_BUTTON: { @@ -1524,6 +1713,49 @@ static void DrawTab(HDC hdc, const RECT& R, PRInt32 aPosition, PRBool aSelected, ::DrawEdge(hdc, &shadeRect, EDGE_RAISED, BF_SOFT | shadeFlag); } +static void DrawMenuImage(HDC hdc, const RECT& rc, PRInt32 aComponent, PRUint32 aColor) +{ + // This procedure creates a memory bitmap to contain the check mark, draws + // it into the bitmap (it is a mask image), then composes it onto the menu + // item in appropriate colors. + HDC hMemoryDC = ::CreateCompatibleDC(hdc); + if (hMemoryDC) { + // XXXjgr We should ideally be caching these, but we wont be notified when + // they change currently, so we can't do so easily. Same for the bitmap. + int checkW = ::GetSystemMetrics(SM_CXMENUCHECK); + int checkH = ::GetSystemMetrics(SM_CYMENUCHECK); + + HBITMAP hMonoBitmap = ::CreateBitmap(checkW, checkH, 1, 1, NULL); + if (hMonoBitmap) { + + HBITMAP hPrevBitmap = (HBITMAP) ::SelectObject(hMemoryDC, hMonoBitmap); + if (hPrevBitmap) { + + // XXXjgr This will go pear-shaped if the image is bigger than the + // provided rect. What should we do? + RECT imgRect = { 0, 0, checkW, checkH }; + POINT imgPos = { + rc.left + (rc.right - rc.left - checkW) / 2, + rc.top + (rc.bottom - rc.top - checkH) / 2 + }; + + ::DrawFrameControl(hMemoryDC, &imgRect, DFC_MENU, aComponent); + COLORREF oldTextCol = ::SetTextColor(hdc, 0x00000000); + COLORREF oldBackCol = ::SetBkColor(hdc, 0x00FFFFFF); + ::BitBlt(hdc, imgPos.x, imgPos.y, checkW, checkH, hMemoryDC, 0, 0, SRCAND); + ::SetTextColor(hdc, ::GetSysColor(aColor)); + ::SetBkColor(hdc, 0x00000000); + ::BitBlt(hdc, imgPos.x, imgPos.y, checkW, checkH, hMemoryDC, 0, 0, SRCPAINT); + ::SetTextColor(hdc, oldTextCol); + ::SetBkColor(hdc, oldBackCol); + ::SelectObject(hMemoryDC, hPrevBitmap); + } + ::DeleteObject(hMonoBitmap); + } + ::DeleteDC(hMemoryDC); + } +} + nsresult nsNativeThemeWin::ClassicDrawWidgetBackground(nsIRenderingContext* aContext, nsIFrame* aFrame, PRUint8 aWidgetType, @@ -1600,7 +1832,7 @@ nsresult nsNativeThemeWin::ClassicDrawWidgetBackground(nsIRenderingContext* aCon case NS_THEME_SPINNER_UP_BUTTON: case NS_THEME_SPINNER_DOWN_BUTTON: case NS_THEME_DROPDOWN_BUTTON: - case NS_THEME_RESIZER: { + case NS_THEME_RESIZER: { PRInt32 oldTA; // setup DC to make DrawFrameControl draw correctly oldTA = ::SetTextAlign(hdc, TA_TOP | TA_LEFT | TA_NOUPDATECP); @@ -1775,6 +2007,80 @@ nsresult nsNativeThemeWin::ClassicDrawWidgetBackground(nsIRenderingContext* aCon RestoreDC(hdc, -1); return NS_OK; + case NS_THEME_MENUBAR: + return NS_OK; + case NS_THEME_MENUPOPUP: + if (mFlatMenus) { + ::FillRect(hdc, &widgetRect, (HBRUSH) (COLOR_MENU+1)); + ::FrameRect(hdc, &widgetRect, ::GetSysColorBrush(COLOR_BTNSHADOW)); + } else { + ::DrawEdge(hdc, &widgetRect, EDGE_RAISED, BF_RECT | BF_MIDDLE); + } + return NS_OK; + case NS_THEME_MENUITEM: + case NS_THEME_CHECKMENUITEM: + case NS_THEME_RADIOMENUITEM: { + // part == 0 for normal items + // part == 1 for top-level menu items + if (mFlatMenus) { + // Not disabled and hot/pushed. + if ((state & (DFCS_HOT | DFCS_PUSHED)) != 0) { + ::FillRect(hdc, &widgetRect, (HBRUSH) (COLOR_MENUHILIGHT+1)); + ::FrameRect(hdc, &widgetRect, ::GetSysColorBrush(COLOR_HIGHLIGHT)); + } + } else { + if (part == 1) { + if ((state & DFCS_INACTIVE) == 0) { + if ((state & DFCS_PUSHED) != 0) { + ::DrawEdge(hdc, &widgetRect, BDR_SUNKENOUTER, BF_RECT); + } else if ((state & DFCS_HOT) != 0) { + ::DrawEdge(hdc, &widgetRect, BDR_RAISEDINNER, BF_RECT); + } + } + } else { + if ((state & (DFCS_HOT | DFCS_PUSHED)) != 0) { + ::FillRect(hdc, &widgetRect, (HBRUSH) (COLOR_HIGHLIGHT+1)); + } + } + } + if (((state & DFCS_CHECKED) != 0) || ((state & DFCS_CONTAINER) != 0)) { + RECT menuRectStart, menuRectEnd; + PRUint32 color = COLOR_MENUTEXT; + + if ((state & DFCS_INACTIVE) != 0) + color = COLOR_GRAYTEXT; + else if ((state & DFCS_HOT) != 0) + color = COLOR_HIGHLIGHTTEXT; + + ::CopyRect(&menuRectStart, &widgetRect); + ::InflateRect(&menuRectStart, -1, -1); + ::CopyRect(&menuRectEnd, &menuRectStart); + + // WARNING: This value of 15 must match the value in menu.css for the min-width of .menu-iconic-left + if ((state & DFCS_RTL) == 0) { + menuRectStart.right = menuRectStart.left + 15; // Left box + menuRectEnd.left = menuRectEnd.right - 15; // Right box + } else { + menuRectStart.left = menuRectStart.right - 15; // Right box + menuRectEnd.right = menuRectEnd.left + 15; // left box + } + + if ((state & DFCS_CHECKED) != 0) { + if (aWidgetType == NS_THEME_CHECKMENUITEM) { + DrawMenuImage(hdc, menuRectStart, DFCS_MENUCHECK, color); + } else if (aWidgetType == NS_THEME_RADIOMENUITEM) { + DrawMenuImage(hdc, menuRectStart, DFCS_MENUBULLET, color); + } + } + if ((state & DFCS_CONTAINER) != 0) { + if ((state & DFCS_RTL) == 0) + DrawMenuImage(hdc, menuRectEnd, DFCS_MENUARROW, color); + else + DrawMenuImage(hdc, menuRectEnd, DFCS_MENUARROWRIGHT, color); + } + } + return NS_OK; + } } RestoreDC(hdc, -1); diff --git a/widget/src/windows/nsNativeThemeWin.h b/widget/src/windows/nsNativeThemeWin.h index 63911e985baa..fae0d6e38112 100644 --- a/widget/src/windows/nsNativeThemeWin.h +++ b/widget/src/windows/nsNativeThemeWin.h @@ -85,6 +85,7 @@ public: virtual ~nsNativeThemeWin(); protected: + void UpdateConfig(); void CloseData(); HANDLE GetTheme(PRUint8 aWidgetType); nsresult GetThemePartAndState(nsIFrame* aFrame, PRUint8 aWidgetType, @@ -125,9 +126,12 @@ private: HANDLE mComboBoxTheme; HANDLE mHeaderTheme; + BOOL mFlatMenus; + nsCOMPtr mInputAtom; nsCOMPtr mInputCheckedAtom; nsCOMPtr mTypeAtom; + nsCOMPtr mMenuActiveAtom; }; // Creator function