Bug 243078 - Native Theme Rendering for Windows XP Menus, toolbars

patch by silver@warwickcompsoc.co.uk r=dougt sr=neil
This commit is contained in:
timeless%mozdev.org 2005-10-07 00:31:36 +00:00
Родитель 491b4ef092
Коммит c644049326
14 изменённых файлов: 427 добавлений и 151 удалений

Просмотреть файл

@ -261,7 +261,7 @@
<toolbaritem id="personal-bookmarks" title="&bookmarksItem.title;" flex="1" <toolbaritem id="personal-bookmarks" title="&bookmarksItem.title;" flex="1"
class="chromeclass-directories"> class="chromeclass-directories">
<stack id="bookmarks-stack" flex="1" style="min-width:0px; width:0px;" <stack id="bookmarks-stack" flex="1" style="min-width:0px; width:0px; overflow: hidden;"
onpopupshowing="BookmarksToolbar.setOpenedMenu(event);" onpopupshowing="BookmarksToolbar.setOpenedMenu(event);"
onpopuphidden="BookmarksToolbar.unsetOpenedMenu(event);"> onpopuphidden="BookmarksToolbar.unsetOpenedMenu(event);">
<hbox id="bookmarks-ptf" class="bookmarks-toolbar-items" contextmenu="bookmarks-context-menu" <hbox id="bookmarks-ptf" class="bookmarks-toolbar-items" contextmenu="bookmarks-context-menu"

Просмотреть файл

@ -979,36 +979,29 @@ var BookmarksToolbar =
if (!buttons) if (!buttons)
return; return;
var chevron = document.getElementById("bookmarks-chevron"); var chevron = document.getElementById("bookmarks-chevron");
var width = window.innerWidth; var myToolbarItem = buttons.parentNode.parentNode;
if (width == 0) { // hack for bug 266737
var width = myToolbarItem.boxObject.width;
if (width <= 0) { // hack for bug 266737
window.addEventListener('focus', BookmarksToolbar.resizeFunc, false); window.addEventListener('focus', BookmarksToolbar.resizeFunc, false);
return; return;
} }
var myToolbar = buttons.parentNode.parentNode.parentNode;
for (var i = myToolbar.childNodes.length-1; i >= 0; i--){
var anItem = myToolbar.childNodes[i];
if (anItem.id == "personal-bookmarks") {
break;
}
width -= anItem.boxObject.width;
}
var chevronWidth = 0; var chevronWidth = 0;
chevron.collapsed = false; chevron.collapsed = false;
chevronWidth = chevron.boxObject.width; chevronWidth = chevron.boxObject.width;
chevron.collapsed = true; chevron.collapsed = true;
var overflowed = false; 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<buttons.childNodes.length; i++) { for (var i=0; i<buttons.childNodes.length; i++) {
var button = buttons.childNodes[i]; var button = buttons.childNodes[i];
button.collapsed = overflowed; button.collapsed = overflowed;
if (i == buttons.childNodes.length - 1) // last ptf item... if (i == buttons.childNodes.length - 1) // last ptf item...
chevronWidth = 0; chevronWidth = 0;
var offset = isLTR ? button.boxObject.x if (usedWidth + button.boxObject.width + chevronWidth > width) {
: width - button.boxObject.x;
if (offset + button.boxObject.width + chevronWidth > width) {
overflowed = true; overflowed = true;
// This button doesn't fit. Show it in the menu. Hide it in the toolbar. // This button doesn't fit. Show it in the menu. Hide it in the toolbar.
if (!button.collapsed) if (!button.collapsed)
@ -1016,11 +1009,10 @@ var BookmarksToolbar =
if (chevron.collapsed) { if (chevron.collapsed) {
chevron.collapsed = false; chevron.collapsed = false;
var overflowPadder = document.getElementById("overflow-padder"); var overflowPadder = document.getElementById("overflow-padder");
offset = isLTR ? buttons.boxObject.x overflowPadder.width = width - chevron.boxObject.width;
: width - buttons.boxObject.x - buttons.boxObject.width;
overflowPadder.width = width - chevron.boxObject.width - offset;
} }
} }
usedWidth += button.boxObject.width;
} }
BookmarksToolbarRDFObserver._overflowTimerInEffect = false; BookmarksToolbarRDFObserver._overflowTimerInEffect = false;
}, },

Просмотреть файл

@ -55,6 +55,11 @@
min-height: 26px; min-height: 26px;
} }
#navigator-toolbox {
border-bottom-width: 1px;
-moz-border-bottom-colors: ThreeDShadow;
}
/* ..... fix searchbar "add engine" padding issue ..... */ /* ..... fix searchbar "add engine" padding issue ..... */
#searchbar .searchbar-dropmarker menuseparator + menuitem { #searchbar .searchbar-dropmarker menuseparator + menuitem {
@ -106,6 +111,8 @@ toolbarbutton.bookmark-item[open="true"] {
.bookmarks-toolbar-customize { .bookmarks-toolbar-customize {
display: none; display: none;
max-width: 15em !important; max-width: 15em !important;
border: none !important;
-moz-appearance: none !important;
} }
toolbarpaletteitem[place="toolbar"] .bookmarks-toolbar-customize { toolbarpaletteitem[place="toolbar"] .bookmarks-toolbar-customize {
@ -136,12 +143,12 @@ menuitem.bookmark-item {
/* ..... fix bookmarks padding issue ..... */ /* ..... fix bookmarks padding issue ..... */
#menu_BookmarksPopup menuitem { #menu_BookmarksPopup menuitem, .openintabs-menuitem {
-moz-padding-start: 4px; -moz-padding-start: 3px;
} }
#menu_BookmarksPopup menuitem.menuitem-iconic { #menu_BookmarksPopup menuitem.menuitem-iconic {
-moz-padding-start: 0px; -moz-padding-start: 0px;
} }

Просмотреть файл

@ -144,6 +144,7 @@ CSS_KEY(-moz-malayalam, _moz_malayalam)
CSS_KEY(-moz-marker, _moz_marker) // Disabled because not supported correctly. CSS_KEY(-moz-marker, _moz_marker) // Disabled because not supported correctly.
CSS_KEY(-moz-menuhover, _moz_menuhover) CSS_KEY(-moz-menuhover, _moz_menuhover)
CSS_KEY(-moz-menuhovertext, _moz_menuhovertext) 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-middle-with-baseline, _moz_middle_with_baseline)
CSS_KEY(-moz-myanmar, _moz_myanmar) CSS_KEY(-moz-myanmar, _moz_myanmar)
CSS_KEY(-moz-none, _moz_none) CSS_KEY(-moz-none, _moz_none)

Просмотреть файл

@ -437,6 +437,7 @@ const PRInt32 nsCSSProps::kColorKTable[] = {
eCSSKeyword__moz_mac_accentdarkestshadow, nsILookAndFeel::eColor__moz_mac_accentdarkestshadow, eCSSKeyword__moz_mac_accentdarkestshadow, nsILookAndFeel::eColor__moz_mac_accentdarkestshadow,
eCSSKeyword__moz_menuhover, nsILookAndFeel::eColor__moz_menuhover, eCSSKeyword__moz_menuhover, nsILookAndFeel::eColor__moz_menuhover,
eCSSKeyword__moz_menuhovertext, nsILookAndFeel::eColor__moz_menuhovertext, eCSSKeyword__moz_menuhovertext, nsILookAndFeel::eColor__moz_menuhovertext,
eCSSKeyword__moz_menubarhovertext, nsILookAndFeel::eColor__moz_menubarhovertext,
eCSSKeyword__moz_visitedhyperlinktext, NS_COLOR_MOZ_VISITEDHYPERLINKTEXT, eCSSKeyword__moz_visitedhyperlinktext, NS_COLOR_MOZ_VISITEDHYPERLINKTEXT,
eCSSKeyword_currentcolor, NS_COLOR_CURRENTCOLOR, eCSSKeyword_currentcolor, NS_COLOR_CURRENTCOLOR,
eCSSKeyword_UNKNOWN,-1 eCSSKeyword_UNKNOWN,-1

Просмотреть файл

@ -100,6 +100,7 @@ textbox.padded {
popup[type="autocomplete"], popup[type="autocomplete"],
.autocomplete-history-popup { .autocomplete-history-popup {
-moz-appearance: none;
border-width: 1px; border-width: 1px;
-moz-border-top-colors: ThreeDDarkShadow; -moz-border-top-colors: ThreeDDarkShadow;
-moz-border-right-colors: ThreeDDarkShadow; -moz-border-right-colors: ThreeDDarkShadow;

Просмотреть файл

@ -171,8 +171,6 @@ sidebarheader {
height: 25px; height: 25px;
background-color: -moz-Dialog; background-color: -moz-Dialog;
-moz-appearance: toolbox; -moz-appearance: toolbox;
border-bottom: 1px solid ThreeDShadow;
border-top: 1px solid ThreeDHighlight;
} }
sidebarheader > label { sidebarheader > label {

Просмотреть файл

@ -46,14 +46,22 @@
menu, menu,
menuitem { menuitem {
-moz-appearance: menuitem;
-moz-box-align: center; -moz-box-align: center;
border: 1px solid transparent;
color: MenuText; color: MenuText;
font: menu; font: menu;
list-style-image: none; list-style-image: none;
-moz-image-region: auto; -moz-image-region: auto;
} }
menuitem[type="checkbox"] {
-moz-appearance: checkmenuitem;
}
menuitem[type="radio"] {
-moz-appearance: radiomenuitem;
}
menuitem[default="true"] { menuitem[default="true"] {
font-weight: bold; font-weight: bold;
} }
@ -70,10 +78,10 @@ menuitem[_moz-menuactive="true"][disabled="true"] {
.menu-iconic-accel, .menu-iconic-accel,
.menu-text, .menu-text,
.menu-iconic-text { .menu-iconic-text {
margin-top: 2px !important; margin-top: 1px !important;
margin-bottom: 2px !important; margin-bottom: 2px !important;
-moz-margin-start: 1px !important; -moz-margin-start: 0px !important;
-moz-margin-end: 2px !important; -moz-margin-end: 0px !important;
color: inherit; color: inherit;
} }
@ -84,99 +92,64 @@ menuitem[_moz-menuactive="true"][disabled="true"] {
.menu-accel, .menu-accel,
.menu-iconic-accel { .menu-iconic-accel {
-moz-padding-end: 17px; -moz-margin-end: 19px !important;
-moz-margin-start: 5px; -moz-margin-start: 8px !important;
color: inherit; color: inherit;
} }
.menu-iconic-text {
-moz-margin-start: 2px !important;
}
.menu-iconic-left { .menu-iconic-left {
min-width: 12px; padding: 1px;
margin-top: 2px; min-width: 15px;
margin-bottom: 2px; min-height: 15px;
-moz-margin-start: 2px;
-moz-margin-end: 2px;
} }
/* ..... menu arrow box ..... */ /* ..... menu arrow box ..... */
.menu-right { .menu-right {
margin-top: 0px; margin-top: 2px;
margin-bottom: 1px; margin-bottom: 3px;
-moz-margin-start: 0px; -moz-padding-end: 6px;
-moz-margin-end: 6px; list-style-image: none;
list-style-image: url("chrome://global/skin/menu/Menu-arrow.png");
-moz-image-region: auto; -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 ::::: */ /* ::::: menu/menuitems in menubar ::::: */
menubar > menu { menubar > menu {
border: 1px solid transparent !important; border: 1px solid transparent;
padding-top: 1px; }
-moz-padding-end: 3px; menubar > menu[_moz-menuactive="true"],
padding-bottom: 1px; menubar > menu[_moz-menuactive="true"][open="true"] {
-moz-padding-start: 2px; color: -moz-MenuBarHoverText;
margin-top: 0px !important;
margin-bottom: 1px !important;
} }
menubar > menu[_moz-menuactive="true"] { menubar > menu[_moz-menuactive="true"] {
padding: 1px 3px 1px 2px !important; border-top-color: ThreeDHighlight;
background-color : Highlight !important; border-left-color: ThreeDHighlight;
color: HighlightText !important; border-right-color: ThreeDShadow;
border-top: 1px solid ThreeDHighlight; border-bottom-color: ThreeDShadow;
border-right: 1px solid ThreeDShadow;
border-bottom: 1px solid ThreeDShadow;
border-left: 1px solid ThreeDHighlight;
} }
menubar > menu[_moz-menuactive="true"][open="true"] { menubar > menu[_moz-menuactive="true"][open="true"] {
border-top: 1px solid ThreeDShadow; border-top-color: ThreeDShadow;
border-right: 1px solid ThreeDHighlight; border-left-color: ThreeDShadow;
border-bottom: 1px solid ThreeDHighlight; border-right-color: ThreeDHighlight;
border-left: 1px solid ThreeDShadow; border-bottom-color: ThreeDHighlight;
padding-top: 1px;
-moz-padding-end: 2px;
padding-bottom: 0px;
-moz-padding-start: 3px;
} }
/* ..... internal content .... */ /* ..... internal content .... */
.menubar-left { .menubar-left {
margin-top: 0px;
margin-bottom: 0px;
-moz-margin-start: 0px;
-moz-margin-end: 2px;
color: inherit; color: inherit;
} }
.menubar-text { .menubar-text {
margin-top: 1px;
-moz-margin-end: 4px !important;
margin-bottom: 1px;
-moz-margin-start: 5px !important; -moz-margin-start: 5px !important;
-moz-margin-end: 4px !important;
padding-top: 1px; padding-top: 1px;
padding-bottom: 3px;
color: inherit; color: inherit;
} }
@ -193,7 +166,7 @@ menupopup > menu[_moz-menuactive="true"],
menupopup > menuitem[_moz-menuactive="true"], menupopup > menuitem[_moz-menuactive="true"],
popup > menu[_moz-menuactive="true"], popup > menu[_moz-menuactive="true"],
popup > menuitem[_moz-menuactive="true"] { popup > menuitem[_moz-menuactive="true"] {
background-color: Highlight; background: Highlight;
color: HighlightText; color: HighlightText;
} }
@ -228,40 +201,6 @@ menulist > menupopup > menuitem > .menu-iconic-text {
margin: 0 !important; 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 ::::: */
menuseparator { menuseparator {

Просмотреть файл

@ -46,14 +46,15 @@
menupopup, menupopup,
popup { popup {
border: 1px solid ThreeDShadow; -moz-appearance: menupopup;
-moz-border-top-colors: ThreeDShadow; border: 2px solid;
-moz-border-right-colors: ThreeDShadow; -moz-border-top-colors: ThreeDLightShadow ThreeDHighlight;
-moz-border-bottom-colors: ThreeDShadow; -moz-border-left-colors: ThreeDLightShadow ThreeDHighlight;
-moz-border-left-colors: ThreeDShadow; -moz-border-right-colors: ThreeDDarkShadow ThreeDShadow;
padding: 2px; -moz-border-bottom-colors: ThreeDDarkShadow ThreeDShadow;
min-width: 1px; padding: 1px;
background-color: Menu; background-color: Menu;
min-width: 1px;
} }
menupopup > menu > menupopup, menupopup > menu > menupopup,
@ -91,6 +92,7 @@ tooltip[titletip="true"] {
menulist > menupopup, menulist > menupopup,
.menulist-menupopup { .menulist-menupopup {
-moz-appearance: none;
border-width: 1px; border-width: 1px;
-moz-border-top-colors: -moz-FieldText; -moz-border-top-colors: -moz-FieldText;
-moz-border-right-colors: -moz-FieldText; -moz-border-right-colors: -moz-FieldText;

Просмотреть файл

@ -46,24 +46,27 @@
toolbox { toolbox {
-moz-appearance: toolbox; -moz-appearance: toolbox;
background-color: -moz-Dialog; border: 2px solid black;
border-top: 2px solid;
-moz-border-top-colors: ThreeDShadow ThreeDHighlight; -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 & menubar ::::: */
toolbar { toolbar,
min-width: 1px; toolbar[type="menubar"], menubar {
min-height: 19px; -moz-appearance: toolbar;
border-top: 1px solid ThreeDHighlight; border-top: 2px solid black;
border-bottom: 1px solid ThreeDShadow; -moz-border-top-colors: ThreeDShadow ThreeDHighlight;
} }
toolbar[type="menubar"], menubar { toolbar:first-child,
min-width: 1px; toolbar[type="menubar"], menubar:first-child {
border-bottom: 1px solid ThreeDShadow; border-top: none;
border-top: 0px !important;
} }
/* ::::: toolbar decorations ::::: */ /* ::::: toolbar decorations ::::: */

Просмотреть файл

@ -133,6 +133,7 @@ public:
eColor__moz_buttonhovertext, //used to button text, when mouse is over 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_menuhover, //used to menu item background, when mouse is over
eColor__moz_menuhovertext, //used to menu item text, 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 //colours needed by Mac Classic skin
eColor__moz_mac_focusring, //ring around text fields and lists eColor__moz_mac_focusring, //ring around text fields and lists

Просмотреть файл

@ -40,7 +40,15 @@
#include "nsXPLookAndFeel.h" #include "nsXPLookAndFeel.h"
#include <windows.h> #include <windows.h>
#include "nsWindow.h" #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() nsLookAndFeel::nsLookAndFeel() : nsXPLookAndFeel()
{ {
} }
@ -221,6 +229,19 @@ nsresult nsLookAndFeel::NativeGetColor(const nsColorID aID, nscolor &aColor)
case eColor__moz_buttondefault: case eColor__moz_buttondefault:
idx = COLOR_3DDKSHADOW; idx = COLOR_3DDKSHADOW;
break; 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: default:
idx = COLOR_WINDOW; idx = COLOR_WINDOW;
break; break;

Просмотреть файл

@ -21,6 +21,7 @@
* *
* Contributor(s): * Contributor(s):
* Tim Hill (tim@prismelite.com) * Tim Hill (tim@prismelite.com)
* James Ross (silver@warwickcompsoc.co.uk)
* *
* 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"),
@ -54,6 +55,7 @@
#include "nsILookAndFeel.h" #include "nsILookAndFeel.h"
#include "nsIDOMHTMLInputElement.h" #include "nsIDOMHTMLInputElement.h"
#include "nsIMenuFrame.h" #include "nsIMenuFrame.h"
#include "nsIMenuParent.h"
#include <malloc.h> #include <malloc.h>
#ifdef MOZ_CAIRO_GFX #ifdef MOZ_CAIRO_GFX
@ -120,6 +122,26 @@
// Dropdown constants // Dropdown constants
#define CBP_DROPMARKER 1 #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) NS_IMPL_ISUPPORTS1(nsNativeThemeWin, nsITheme)
typedef HANDLE (WINAPI*OpenThemeDataPtr)(HWND hwnd, LPCWSTR pszClassList); 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, typedef HRESULT (WINAPI*DrawThemeBackgroundPtr)(HANDLE hTheme, HDC hdc, int iPartId,
int iStateId, const RECT *pRect, int iStateId, const RECT *pRect,
const RECT* pClipRect); 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, typedef HRESULT (WINAPI*GetThemeContentRectPtr)(HANDLE hTheme, HDC hdc, int iPartId,
int iStateId, const RECT* pRect, int iStateId, const RECT* pRect,
RECT* pContentRect); RECT* pContentRect);
@ -140,6 +166,7 @@ typedef HRESULT (WINAPI*GetThemeColorPtr)(HANDLE hTheme, HDC hdc, int iPartId,
static OpenThemeDataPtr openTheme = NULL; static OpenThemeDataPtr openTheme = NULL;
static CloseThemeDataPtr closeTheme = NULL; static CloseThemeDataPtr closeTheme = NULL;
static DrawThemeBackgroundPtr drawThemeBG = NULL; static DrawThemeBackgroundPtr drawThemeBG = NULL;
static DrawThemeEdgePtr drawThemeEdge = NULL;
static GetThemeContentRectPtr getThemeContentRect = NULL; static GetThemeContentRectPtr getThemeContentRect = NULL;
static GetThemePartSizePtr getThemePartSize = NULL; static GetThemePartSizePtr getThemePartSize = NULL;
static GetThemeSysFontPtr getThemeSysFont = NULL; static GetThemeSysFontPtr getThemeSysFont = NULL;
@ -167,6 +194,7 @@ nsNativeThemeWin::nsNativeThemeWin() {
openTheme = (OpenThemeDataPtr)GetProcAddress(mThemeDLL, "OpenThemeData"); openTheme = (OpenThemeDataPtr)GetProcAddress(mThemeDLL, "OpenThemeData");
closeTheme = (CloseThemeDataPtr)GetProcAddress(mThemeDLL, "CloseThemeData"); closeTheme = (CloseThemeDataPtr)GetProcAddress(mThemeDLL, "CloseThemeData");
drawThemeBG = (DrawThemeBackgroundPtr)GetProcAddress(mThemeDLL, "DrawThemeBackground"); drawThemeBG = (DrawThemeBackgroundPtr)GetProcAddress(mThemeDLL, "DrawThemeBackground");
drawThemeEdge = (DrawThemeEdgePtr)GetProcAddress(mThemeDLL, "DrawThemeEdge");
getThemeContentRect = (GetThemeContentRectPtr)GetProcAddress(mThemeDLL, "GetThemeBackgroundContentRect"); getThemeContentRect = (GetThemeContentRectPtr)GetProcAddress(mThemeDLL, "GetThemeBackgroundContentRect");
getThemePartSize = (GetThemePartSizePtr)GetProcAddress(mThemeDLL, "GetThemePartSize"); getThemePartSize = (GetThemePartSizePtr)GetProcAddress(mThemeDLL, "GetThemePartSize");
getThemeSysFont = (GetThemeSysFontPtr)GetProcAddress(mThemeDLL, "GetThemeSysFont"); getThemeSysFont = (GetThemeSysFontPtr)GetProcAddress(mThemeDLL, "GetThemeSysFont");
@ -176,6 +204,9 @@ nsNativeThemeWin::nsNativeThemeWin() {
mInputAtom = do_GetAtom("input"); mInputAtom = do_GetAtom("input");
mInputCheckedAtom = do_GetAtom("_moz-input-checked"); mInputCheckedAtom = do_GetAtom("_moz-input-checked");
mTypeAtom = do_GetAtom("type"); mTypeAtom = do_GetAtom("type");
mMenuActiveAtom = do_GetAtom("_moz-menuactive");
UpdateConfig();
// If there is a relevant change in forms.css for windows platform, // If there is a relevant change in forms.css for windows platform,
// static widget style variables (e.g. sButtonBorderSize) should be // 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; 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 HANDLE
nsNativeThemeWin::GetTheme(PRUint8 aWidgetType) nsNativeThemeWin::GetTheme(PRUint8 aWidgetType)
{ {
@ -547,6 +593,21 @@ nsNativeThemeWin::GetThemePartAndState(nsIFrame* aFrame, PRUint8 aWidgetType,
aPart = aState = 0; aPart = aState = 0;
return NS_OK; // These have no part or state. 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_PANEL:
case NS_THEME_STATUSBAR_RESIZER_PANEL: case NS_THEME_STATUSBAR_RESIZER_PANEL:
case NS_THEME_RESIZER: { 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. // The left edge should not be drawn. Move the widget rect's left coord back.
widgetRect.left -= edgeSize; widgetRect.left -= edgeSize;
} }
else if (aWidgetType == NS_THEME_TOOLBOX) {
drawThemeBG(theme, hdc, part, state, &widgetRect, &clipRect); // 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 // Draw focus rectangles for XP HTML checkboxes and radio buttons
// XXX it'd be nice to draw these outside of the frame // XXX it'd be nice to draw these outside of the frame
@ -765,6 +836,15 @@ nsNativeThemeWin::DrawWidgetBackground(nsIRenderingContext* aContext,
::SetTextColor(hdc, oldColor); ::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); RestoreDC(hdc, -1);
@ -784,11 +864,26 @@ nsNativeThemeWin::GetWidgetBorder(nsIDeviceContext* aContext,
(*aResult).top = (*aResult).bottom = (*aResult).left = (*aResult).right = 0; (*aResult).top = (*aResult).bottom = (*aResult).left = (*aResult).right = 0;
if (!WidgetIsContainer(aWidgetType) || if (!WidgetIsContainer(aWidgetType) ||
aWidgetType == NS_THEME_TOOLBOX || aWidgetType == NS_THEME_TOOLBAR || aWidgetType == NS_THEME_TOOLBOX ||
aWidgetType == NS_THEME_STATUSBAR || aWidgetType == NS_THEME_STATUSBAR ||
aWidgetType == NS_THEME_RESIZER || aWidgetType == NS_THEME_TAB_PANEL) aWidgetType == NS_THEME_RESIZER || aWidgetType == NS_THEME_TAB_PANEL)
return NS_OK; // Don't worry about it. 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) if (!getThemeContentRect)
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
@ -940,7 +1035,8 @@ nsNativeThemeWin::WidgetStateChanged(nsIFrame* aFrame, PRUint8 aWidgetType,
// disabled, checked, dlgtype, default, etc. // disabled, checked, dlgtype, default, etc.
*aShouldRepaint = PR_FALSE; *aShouldRepaint = PR_FALSE;
if (aAttribute == mDisabledAtom || aAttribute == mCheckedAtom || if (aAttribute == mDisabledAtom || aAttribute == mCheckedAtom ||
aAttribute == mSelectedAtom || aAttribute == mReadOnlyAtom) aAttribute == mSelectedAtom || aAttribute == mReadOnlyAtom ||
aAttribute == mMenuActiveAtom)
*aShouldRepaint = PR_TRUE; *aShouldRepaint = PR_TRUE;
} }
@ -1004,6 +1100,7 @@ NS_IMETHODIMP
nsNativeThemeWin::ThemeChanged() nsNativeThemeWin::ThemeChanged()
{ {
CloseData(); CloseData();
UpdateConfig();
return NS_OK; return NS_OK;
} }
@ -1086,6 +1183,11 @@ nsNativeThemeWin::ClassicThemeSupportsWidget(nsPresContext* aPresContext,
case NS_THEME_TAB_RIGHT_EDGE: case NS_THEME_TAB_RIGHT_EDGE:
case NS_THEME_TAB_PANEL: case NS_THEME_TAB_PANEL:
case NS_THEME_TAB_PANELS: 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_TRUE;
} }
return PR_FALSE; return PR_FALSE;
@ -1147,6 +1249,39 @@ nsNativeThemeWin::ClassicGetWidgetBorder(nsIDeviceContext* aContext,
case NS_THEME_PROGRESSBAR_VERTICAL: case NS_THEME_PROGRESSBAR_VERTICAL:
(*aResult).top = (*aResult).left = (*aResult).bottom = (*aResult).right = 1; (*aResult).top = (*aResult).left = (*aResult).bottom = (*aResult).right = 1;
break; 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: default:
(*aResult).top = (*aResult).bottom = (*aResult).left = (*aResult).right = 0; (*aResult).top = (*aResult).bottom = (*aResult).left = (*aResult).right = 0;
break; break;
@ -1318,6 +1453,58 @@ nsresult nsNativeThemeWin::ClassicGetThemePartAndState(nsIFrame* aFrame, PRUint8
return NS_OK; 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_LISTBOX:
case NS_THEME_TREEVIEW: case NS_THEME_TREEVIEW:
case NS_THEME_TEXTFIELD: case NS_THEME_TEXTFIELD:
@ -1340,6 +1527,8 @@ nsresult nsNativeThemeWin::ClassicGetThemePartAndState(nsIFrame* aFrame, PRUint8
case NS_THEME_TAB_RIGHT_EDGE: case NS_THEME_TAB_RIGHT_EDGE:
case NS_THEME_TAB_PANEL: case NS_THEME_TAB_PANEL:
case NS_THEME_TAB_PANELS: case NS_THEME_TAB_PANELS:
case NS_THEME_MENUBAR:
case NS_THEME_MENUPOPUP:
// these don't use DrawFrameControl // these don't use DrawFrameControl
return NS_OK; return NS_OK;
case NS_THEME_DROPDOWN_BUTTON: { 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); ::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, nsresult nsNativeThemeWin::ClassicDrawWidgetBackground(nsIRenderingContext* aContext,
nsIFrame* aFrame, nsIFrame* aFrame,
PRUint8 aWidgetType, PRUint8 aWidgetType,
@ -1600,7 +1832,7 @@ nsresult nsNativeThemeWin::ClassicDrawWidgetBackground(nsIRenderingContext* aCon
case NS_THEME_SPINNER_UP_BUTTON: case NS_THEME_SPINNER_UP_BUTTON:
case NS_THEME_SPINNER_DOWN_BUTTON: case NS_THEME_SPINNER_DOWN_BUTTON:
case NS_THEME_DROPDOWN_BUTTON: case NS_THEME_DROPDOWN_BUTTON:
case NS_THEME_RESIZER: { case NS_THEME_RESIZER: {
PRInt32 oldTA; PRInt32 oldTA;
// setup DC to make DrawFrameControl draw correctly // setup DC to make DrawFrameControl draw correctly
oldTA = ::SetTextAlign(hdc, TA_TOP | TA_LEFT | TA_NOUPDATECP); oldTA = ::SetTextAlign(hdc, TA_TOP | TA_LEFT | TA_NOUPDATECP);
@ -1775,6 +2007,80 @@ nsresult nsNativeThemeWin::ClassicDrawWidgetBackground(nsIRenderingContext* aCon
RestoreDC(hdc, -1); RestoreDC(hdc, -1);
return NS_OK; 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); RestoreDC(hdc, -1);

Просмотреть файл

@ -85,6 +85,7 @@ public:
virtual ~nsNativeThemeWin(); virtual ~nsNativeThemeWin();
protected: protected:
void UpdateConfig();
void CloseData(); void CloseData();
HANDLE GetTheme(PRUint8 aWidgetType); HANDLE GetTheme(PRUint8 aWidgetType);
nsresult GetThemePartAndState(nsIFrame* aFrame, PRUint8 aWidgetType, nsresult GetThemePartAndState(nsIFrame* aFrame, PRUint8 aWidgetType,
@ -125,9 +126,12 @@ private:
HANDLE mComboBoxTheme; HANDLE mComboBoxTheme;
HANDLE mHeaderTheme; HANDLE mHeaderTheme;
BOOL mFlatMenus;
nsCOMPtr<nsIAtom> mInputAtom; nsCOMPtr<nsIAtom> mInputAtom;
nsCOMPtr<nsIAtom> mInputCheckedAtom; nsCOMPtr<nsIAtom> mInputCheckedAtom;
nsCOMPtr<nsIAtom> mTypeAtom; nsCOMPtr<nsIAtom> mTypeAtom;
nsCOMPtr<nsIAtom> mMenuActiveAtom;
}; };
// Creator function // Creator function