Bug 355789 - Use vista native uxtheme for menu rendering. Patch by Rob Arnold <robarnold@mozilla.com>. r=vladimir, a=[wanted-1.9]
authorsdwilsh@shawnwilsher.com
Mon, 06 Aug 2007 10:45:57 -0700
changeset 4313 5981a4c540f27ca6f941886dffd7d23235693741
parent 4312 ad476a76958106bbed27b9745bffd7daee0bfe3f
child 4314 8b96da4e125d2ed4997fb0f398843c8d07fa05e8
push idunknown
push userunknown
push dateunknown
reviewersvladimir
bugs355789
milestone1.9a8pre
Bug 355789 - Use vista native uxtheme for menu rendering. Patch by Rob Arnold <robarnold@mozilla.com>. r=vladimir, a=[wanted-1.9]
browser/themes/winstripe/browser/browser.css
gfx/public/nsThemeConstants.h
layout/style/nsCSSKeywordList.h
layout/style/nsCSSProps.cpp
toolkit/themes/winstripe/global/menu.css
toolkit/themes/winstripe/global/popup.css
widget/src/windows/nsLookAndFeel.cpp
widget/src/windows/nsNativeThemeWin.cpp
widget/src/windows/nsNativeThemeWin.h
widget/src/windows/nsWindow.cpp
widget/src/windows/nsWindow.h
--- a/browser/themes/winstripe/browser/browser.css
+++ b/browser/themes/winstripe/browser/browser.css
@@ -1208,16 +1208,23 @@ toolbarpaletteitem:not([place="toolbar"]
   list-style-image: url("chrome://browser/skin/Throbber-small.png");
 }
 
 #navigator-throbber[busy="true"] {
   list-style-image: url("chrome://global/skin/throbber/Throbber-small.gif");
   opacity: 0.5;
 }
 
+/* the default settings for the throbber hbox is too tall for vista menus */
+#navigator-throbber > hbox {
+  border-top: 0px;
+  border-bottom: 0px;
+  padding-bottom: 1px;
+}
+
 toolbar[iconsize="small"] #navigator-throbber,
 toolbar[mode="text"] #navigator-throbber {
   list-style-image: url("chrome://browser/skin/Throbber-small.png");
 }
 toolbar[iconsize="small"] #navigator-throbber[busy="true"],
 toolbar[mode="text"] #navigator-throbber[busy="true"] {
   list-style-image: url("chrome://global/skin/throbber/Throbber-small.gif");
   opacity: 0.5;
--- a/gfx/public/nsThemeConstants.h
+++ b/gfx/public/nsThemeConstants.h
@@ -211,8 +211,13 @@
 #define NS_THEME_CHECKMENUITEM                             213
 #define NS_THEME_RADIOMENUITEM                             214
 
 // menu checkbox/radio appearances
 #define NS_THEME_MENUCHECKBOX                              215
 #define NS_THEME_MENURADIO                                 216
 #define NS_THEME_MENUSEPARATOR                             217
 #define NS_THEME_MENUARROW                                 218
+// An image in the menu gutter, like in bookmarks or history
+#define NS_THEME_MENUIMAGE                                 219
+// For text on non-iconic menuitems only
+#define NS_THEME_MENUITEMTEXT                              220
+
--- a/layout/style/nsCSSKeywordList.h
+++ b/layout/style/nsCSSKeywordList.h
@@ -523,16 +523,18 @@ CSS_KEY(menubar, menubar)
 CSS_KEY(menupopup, menupopup)
 CSS_KEY(menuitem, menuitem)
 CSS_KEY(checkmenuitem, checkmenuitem)
 CSS_KEY(radiomenuitem, radiomenuitem)
 CSS_KEY(menucheckbox, menucheckbox)
 CSS_KEY(menuradio, menuradio)
 CSS_KEY(menuseparator, menuseparator)
 CSS_KEY(menuarrow, menuarrow)
+CSS_KEY(menuimage, menuimage)
+CSS_KEY(menuitemtext, menuitemtext)
 CSS_KEY(menulist, menulist)
 CSS_KEY(menulist-button, menulistbutton)
 CSS_KEY(menulist-text, menulisttext)
 CSS_KEY(menulist-textfield, menulisttextfield)
 CSS_KEY(scale-horizontal, scale_horizontal)
 CSS_KEY(scale-vertical, scale_vertical)
 CSS_KEY(scalethumb-horizontal, scalethumb_horizontal)
 CSS_KEY(scalethumb-vertical, scalethumb_vertical)
--- a/layout/style/nsCSSProps.cpp
+++ b/layout/style/nsCSSProps.cpp
@@ -254,16 +254,18 @@ const PRInt32 nsCSSProps::kAppearanceKTa
   eCSSKeyword_menupopup,              NS_THEME_MENUPOPUP,
   eCSSKeyword_menuitem,               NS_THEME_MENUITEM,
   eCSSKeyword_checkmenuitem,          NS_THEME_CHECKMENUITEM,
   eCSSKeyword_radiomenuitem,          NS_THEME_RADIOMENUITEM,
   eCSSKeyword_menucheckbox,           NS_THEME_MENUCHECKBOX,
   eCSSKeyword_menuradio,              NS_THEME_MENURADIO,
   eCSSKeyword_menuseparator,          NS_THEME_MENUSEPARATOR,
   eCSSKeyword_menuarrow,              NS_THEME_MENUARROW,
+  eCSSKeyword_menuimage,              NS_THEME_MENUIMAGE,
+  eCSSKeyword_menuitemtext,           NS_THEME_MENUITEMTEXT,
   eCSSKeyword_UNKNOWN,-1
 };
 
 // Keyword id tables for variant/enum parsing
 const PRInt32 nsCSSProps::kAzimuthKTable[] = {
   eCSSKeyword_left_side,    NS_STYLE_AZIMUTH_LEFT_SIDE,
   eCSSKeyword_far_left,     NS_STYLE_AZIMUTH_FAR_LEFT,
   eCSSKeyword_left,         NS_STYLE_AZIMUTH_LEFT,
--- a/toolkit/themes/winstripe/global/menu.css
+++ b/toolkit/themes/winstripe/global/menu.css
@@ -75,17 +75,18 @@ menuitem.spell-suggestion {
 .menu-text,
 .menu-iconic-text {
   margin: 0px !important;
   padding: 0px;
   color: inherit;
 }
 
 .menu-text {
-  -moz-margin-start: 1.28em !important;
+  -moz-padding-start: 1.28em !important;
+  -moz-appearance: menuitemtext;
 }
 
 .menu-text,
 .menu-iconic-text {
   font-weight: inherit;
   padding-left: 2px;
   padding-right: 2px;
 }
@@ -104,19 +105,21 @@ menuitem.spell-suggestion {
 }
 
 .menu-iconic-left,
 .menu-right {
   min-width:  1.28em;
   min-height: 1.21em;
 }
 
+menu.menu-iconic > .menu-iconic-left,
 menuitem.menuitem-iconic > .menu-iconic-left {
   /* there's only space for 15px - make room for one more */
   -moz-margin-start: -1px;
+  -moz-appearance: menuimage;
 }
 
 /* ..... menu arrow box ..... */
 
 .menu-right {
   -moz-appearance: menuarrow;
   -moz-margin-end: -2px;
   list-style-image: none;
@@ -137,17 +140,17 @@ menubar > menu[_moz-menuactive="true"][o
 
 /* ..... internal content .... */
 
 .menubar-left {
   color: inherit;
 }
 
 .menubar-text {
-  margin: 2px 6px 2px 6px !important;
+  margin: 1px 6px 2px 6px !important;
   color: inherit;
 }
 
 /* ::::: menu/menuitems in popups ::::: */
 
 menupopup > menu,
 popup > menu,
 menupopup > menuitem,
@@ -164,16 +167,17 @@ popup > menuitem[_moz-menuactive="true"]
 }
 
 /* ::::: menu/menuitems in menulist popups ::::: */
 
 .menulist-menupopup > menuitem,
 menulist > menupopup > menuitem,
 .menulist-menupopup > menu,
 menulist > menupopup > menu {
+  -moz-appearance: none;
   border: 1px solid transparent;
   padding-top: 1px;
   -moz-padding-end: 30px;
   padding-bottom: 1px;
   -moz-padding-start: 5px;
   max-width: none;
   font: message-box;
   color: -moz-FieldText;
@@ -183,16 +187,22 @@ menulist > menupopup > menu {
 menulist > menupopup > menuitem > .menu-iconic-left,
 .menulist-menupopup > menu > .menu-iconic-left,
 menulist > menupopup > menu > .menu-iconic-left {
   display: none;
 }
 
 menulist > menupopup > menuitem[_moz-menuactive="true"] {
   border: 1px dotted #F5DB95;
+  background-color: highlight;
+  color: highlighttext;
+}
+
+menulist > menupopup > menuitem[_moz-menuactive="true"][disabled="true"] {
+  color: GrayText;
 }
 
 menulist > menupopup > menuitem > .menu-iconic-text {
   margin: 0 !important;
 }
 
 /* ::::: checkbox and radio menuitems ::::: */
 
@@ -210,24 +220,25 @@ menuitem[type="radio"] {
 }
 menuitem[type="radio"] > .menu-iconic-left {
   -moz-appearance: menuradio;
 }
 
 /* ::::: menuseparator ::::: */
 
 menuseparator {
-  margin: 3px 1px 4px 1px;
+  -moz-appearance: menuseparator;
+  padding: 3px 1px 4px 1px;
   border-top: 1px solid ThreeDShadow;
   border-bottom: 1px solid ThreeDHighlight;
 }
 
 menulist > menupopup > menuseparator,
 .menulist-menupopup > menuseparator {
-  margin: 6px 0 5px 0;
+  padding: 6px 0 5px 0;
   border-top: 1px solid #000000;
   border-bottom: none;
 }
 
 /* ::::: autocomplete ::::: */
 
 .autocomplete-history-popup > menuitem {
   max-width: none !important;
--- a/toolkit/themes/winstripe/global/popup.css
+++ b/toolkit/themes/winstripe/global/popup.css
@@ -42,27 +42,33 @@
 
 @namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");
 
 /* ::::: menupopup ::::: */
 
 menupopup,
 popup,
 panel {
-  -moz-appearance: menupopup;
   border: 3px solid transparent;
   -moz-border-top-colors   : ThreeDLightShadow ThreeDHighlight ThreeDFace;
   -moz-border-left-colors  : ThreeDLightShadow ThreeDHighlight ThreeDFace;
   -moz-border-right-colors : ThreeDDarkShadow  ThreeDShadow    ThreeDFace;
   -moz-border-bottom-colors: ThreeDDarkShadow  ThreeDShadow    ThreeDFace;
   padding: 0px;
   min-width: 1px;
   background: Menu;
 }
 
+menupopup,
+/* auto complete popups don't render well as vista menus */
+popup:not([type="autocomplete"])
+{
+  -moz-appearance: menupopup;
+}
+
 menupopup > menu > menupopup,
 popup > menu > menupopup {
  /* align submenus */
   -moz-margin-start: -3px;
   margin-top: -3px;
 }
 
 /* ::::: tooltip ::::: */
@@ -98,9 +104,8 @@ menulist > menupopup,
   -moz-border-top-colors: -moz-FieldText;
   -moz-border-right-colors: -moz-FieldText;
   -moz-border-bottom-colors: -moz-FieldText;
   -moz-border-left-colors: -moz-FieldText;
   padding: 0px;
   min-width: 0px;
   background-color: -moz-Field;
 }
-
--- a/widget/src/windows/nsLookAndFeel.cpp
+++ b/widget/src/windows/nsLookAndFeel.cpp
@@ -39,16 +39,44 @@
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsLookAndFeel.h"
 #include "nsXPLookAndFeel.h"
 #include <windows.h>
 #include <shellapi.h>
 #include "nsWindow.h"
 
+#ifndef WINCE
+typedef HANDLE (WINAPI*OpenThemeDataPtr)(HWND hwnd, LPCWSTR pszClassList);
+typedef HRESULT (WINAPI*CloseThemeDataPtr)(HANDLE hTheme);
+typedef HRESULT (WINAPI*GetThemeColorPtr)(HANDLE hTheme, int iPartId,
+                                          int iStateId, int iPropId, OUT COLORREF* pFont);
+typedef BOOL (WINAPI*IsAppThemedPtr)(VOID);
+
+static OpenThemeDataPtr openTheme = NULL;
+static CloseThemeDataPtr closeTheme = NULL;
+static GetThemeColorPtr getThemeColor = NULL;
+static IsAppThemedPtr isAppThemed = NULL;
+
+static const char kThemeLibraryName[] = "uxtheme.dll";
+static HINSTANCE gThemeDLLInst = NULL;
+static HANDLE gMenuTheme = NULL;
+
+#define MENU_POPUPITEM 14
+
+#define MPI_NORMAL 1
+#define MPI_HOT 2
+#define MPI_DISABLED 3
+#define MPI_DISABLEDHOT 4
+
+// From tmschema.h in the Vista SDK
+#define TMT_TEXTCOLOR 3803
+
+#endif
+
 // Constants only found in new (2K+, XP+, etc.) Windows.
 #ifndef COLOR_MENUHILIGHT
 #define COLOR_MENUHILIGHT    29
 #endif
 #ifndef SPI_GETFLATMENU
 #define SPI_GETFLATMENU      0x1022
 #endif
 #ifndef SPI_GETMENUSHOWDELAY
@@ -78,16 +106,25 @@ nsLookAndFeel::nsLookAndFeel() : nsXPLoo
 {
 #ifndef WINCE
   gShell32DLLInst = LoadLibrary("Shell32.dll");
   if (gShell32DLLInst)
   {
       gSHAppBarMessage = (SHAppBarMessagePtr) GetProcAddress(gShell32DLLInst,
                                                              "SHAppBarMessage");
   }
+  gThemeDLLInst = LoadLibrary(kThemeLibraryName);
+  if(gThemeDLLInst)
+  {
+    openTheme = (OpenThemeDataPtr)GetProcAddress(gThemeDLLInst, "OpenThemeData");
+    closeTheme = (CloseThemeDataPtr)GetProcAddress(gThemeDLLInst, "CloseThemeData");
+    getThemeColor = (GetThemeColorPtr)GetProcAddress(gThemeDLLInst, "GetThemeColor");
+    isAppThemed = (IsAppThemedPtr)GetProcAddress(gThemeDLLInst, "IsAppThemed");
+    gMenuTheme = openTheme(NULL, L"Menu");
+  }
 #endif
 }
 
 nsLookAndFeel::~nsLookAndFeel()
 {
 #ifndef WINCE
    if (gShell32DLLInst)
    {
@@ -193,18 +230,56 @@ nsresult nsLookAndFeel::NativeGetColor(c
       break;
     case eColor_graytext:
       idx = COLOR_GRAYTEXT;
       break;
     case eColor_highlight:
     case eColor__moz_menuhover:
       idx = COLOR_HIGHLIGHT;
       break;
+    case eColor__moz_menubarhovertext:OSVERSIONINFOEX:
+#ifndef WINCE
+      if (GetWindowsVersion() < VISTA_VERSION || !isAppThemed())
+#endif
+      {
+        // GetSystemParam will return 0 on failure and we get non-flat as
+        // desired for Windows 2000 and sometimes on XP.
+        idx = (GetSystemParam(SPI_GETFLATMENU, 0)) ?
+                COLOR_HIGHLIGHTTEXT :
+                COLOR_MENUTEXT;
+        break;
+      }
+      // Fall through
+    case eColor__moz_menuhovertext:
+#ifndef WINCE
+      if (isAppThemed && isAppThemed() && GetWindowsVersion() >= VISTA_VERSION)
+      {
+        COLORREF color;
+        HRESULT hr;
+        hr = getThemeColor(gMenuTheme, MENU_POPUPITEM, MPI_HOT, TMT_TEXTCOLOR, &color);
+        if (hr == S_OK)
+        {
+          aColor = COLOREF_2_NSRGB(color);
+          return NS_OK;
+        }
+        // Since we don't get theme changed messages, check if we lost the handle
+        else if (hr == E_HANDLE)
+        {
+          closeTheme(gMenuTheme);
+          gMenuTheme = openTheme(NULL, L"Menu");
+          // gMenuTheme shouldn't be null since it was non-null before so we
+          // are running on Vista or higher
+          getThemeColor(gMenuTheme, MENU_POPUPITEM, MPI_HOT, TMT_TEXTCOLOR, &color);
+          aColor = COLOREF_2_NSRGB(color);
+          return NS_OK;
+        }
+        // fall through to highlight case
+      }
+#endif
     case eColor_highlighttext:
-    case eColor__moz_menuhovertext:
       idx = COLOR_HIGHLIGHTTEXT;
       break;
     case eColor_inactiveborder:
       idx = COLOR_INACTIVEBORDER;
       break;
     case eColor_inactivecaption:
       idx = COLOR_INACTIVECAPTION;
       break;
@@ -265,24 +340,16 @@ nsresult nsLookAndFeel::NativeGetColor(c
       idx = COLOR_WINDOWTEXT;
       break;
     case eColor__moz_dragtargetzone:
       idx = COLOR_HIGHLIGHTTEXT;
       break;
     case eColor__moz_buttondefault:
       idx = COLOR_3DDKSHADOW;
       break;
-    case eColor__moz_menubarhovertext: {
-     // GetSystemParam will return 0 on failure and we get non-flat as
-     // desired for Windows 2000 and sometimes on XP.
-      idx = (GetSystemParam(SPI_GETFLATMENU, 0)) ?
-                COLOR_HIGHLIGHTTEXT :
-                COLOR_MENUTEXT;
-      break;
-    }
     default:
       idx = COLOR_WINDOW;
       break;
     }
 
   DWORD color = ::GetSysColor(idx);
   aColor = COLOREF_2_NSRGB(color);
 
--- a/widget/src/windows/nsNativeThemeWin.cpp
+++ b/widget/src/windows/nsNativeThemeWin.cpp
@@ -54,16 +54,17 @@
 #include "nsIEventStateManager.h"
 #include "nsINameSpaceManager.h"
 #include "nsILookAndFeel.h"
 #include "nsIDOMHTMLInputElement.h"
 #include "nsIMenuFrame.h"
 #include "nsWidgetAtoms.h"
 #include <malloc.h>
 
+#include "gfxPlatform.h"
 #include "gfxContext.h"
 #include "gfxMatrix.h"
 #include "gfxWindowsSurface.h"
 #include "gfxWindowsNativeDrawing.h"
 
 /* 
  * The following constants are used to determine how a widget is drawn using
  * Windows' Theme API. For more information on theme parts and states see
@@ -133,16 +134,75 @@
 #define TABP_PANEL           10
 
 // Tooltip constants
 #define TTP_STANDARD         1
 
 // Dropdown constants
 #define CBP_DROPMARKER       1
 
+// Menu Constants
+#define MENU_BARBACKGROUND 7
+#define MENU_BARITEM 8
+#define MENU_POPUPBACKGROUND 9
+#define MENU_POPUPBORDERS 10
+#define MENU_POPUPCHECK 11
+#define MENU_POPUPCHECKBACKGROUND 12
+#define MENU_POPUPGUTTER 13
+#define MENU_POPUPITEM 14
+#define MENU_POPUPSEPARATOR 15
+#define MENU_POPUPSUBMENU 16
+#define MENU_SYSTEMCLOSE 17
+#define MENU_SYSTEMMAXIMIZE 18
+#define MENU_SYSTEMMINIMIZE 19
+#define MENU_SYSTEMRESTORE 20
+
+#define MB_ACTIVE 1
+#define MB_INACTIVE 2
+
+#define MS_NORMAL    1
+#define MS_SELECTED  2
+#define MS_DEMOTED   3
+
+#define MBI_NORMAL 1
+#define MBI_HOT 2
+#define MBI_PUSHED 3
+#define MBI_DISABLED 4
+#define MBI_DISABLEDHOT 5
+#define MBI_DISABLEDPUSHED 6
+
+#define MC_CHECKMARKNORMAL 1
+#define MC_CHECKMARKDISABLED 2
+#define MC_BULLETNORMAL 3
+#define MC_BULLETDISABLED 4
+
+#define MCB_DISABLED 1
+#define MCB_NORMAL 2
+#define MCB_BITMAP 3
+
+#define MPI_NORMAL 1
+#define MPI_HOT 2
+#define MPI_DISABLED 3
+#define MPI_DISABLEDHOT 4
+
+#define MSM_NORMAL 1
+#define MSM_DISABLED 2
+
+// Theme size constants
+// minimum size
+#define TS_MIN 0
+// size without stretching
+#define TS_TRUE 1
+// size that theme mgr will use to draw part
+#define TS_DRAW 2
+
+#define TMT_SIZINGMARGINS 3601
+#define TMT_CONTENTMARGINS 3602
+#define TMT_CAPTIONMARGINS 3603
+
 // Rebar constants
 #define RP_BAND              3
 
 // Constants only found in new (98+, 2K+, XP+, etc.) Windows.
 #ifdef DFCS_HOT
 #undef DFCS_HOT
 #endif
 #define DFCS_HOT             0x00001000
@@ -160,43 +220,55 @@
 // Our extra constants for passing a little bit more info to the renderer.
 #define DFCS_RTL             0x00010000
 
 // Toolbar separator dimension which can't be gotten from Windows
 #define TB_SEPARATOR_HEIGHT  2
 
 NS_IMPL_ISUPPORTS1(nsNativeThemeWin, nsITheme)
 
+struct MARGINS
+{
+  int cxLeftWidth;
+  int cxRightWidth;
+  int cyTopHeight;
+  int cyBottomHeight;
+};
+
 typedef HANDLE (WINAPI*OpenThemeDataPtr)(HWND hwnd, LPCWSTR pszClassList);
 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 *pDestRect,
                                           uint uEdge, uint uFlags,
                                           const RECT* pContentRect);
 typedef HRESULT (WINAPI*GetThemeContentRectPtr)(HANDLE hTheme, HDC hdc, int iPartId,
                                           int iStateId, const RECT* pRect,
                                           RECT* pContentRect);
 typedef HRESULT (WINAPI*GetThemePartSizePtr)(HANDLE hTheme, HDC hdc, int iPartId,
                                        int iStateId, RECT* prc, int ts,
                                        SIZE* psz);
 typedef HRESULT (WINAPI*GetThemeSysFontPtr)(HANDLE hTheme, int iFontId, OUT LOGFONT* pFont);
-typedef HRESULT (WINAPI*GetThemeColorPtr)(HANDLE hTheme, HDC hdc, int iPartId,
+typedef HRESULT (WINAPI*GetThemeColorPtr)(HANDLE hTheme, int iPartId,
                                    int iStateId, int iPropId, OUT COLORREF* pFont);
+typedef HRESULT (WINAPI*GetThemeMarginsPtr)(HANDLE hTheme, HDC hdc, int iPartId,
+                                         int iStateid, int iPropId,
+                                         LPRECT prc, MARGINS *pMargins);
 
 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;
 static GetThemeColorPtr getThemeColor = NULL;
+static GetThemeMarginsPtr getThemeMargins = NULL;
 
 static const char kThemeLibraryName[] = "uxtheme.dll";
 
 static inline bool IsCheckboxWidgetType(PRUint8 aWidgetType)
 {
   return (aWidgetType == NS_THEME_CHECKBOX || aWidgetType == NS_THEME_CHECKBOX_SMALL);
 }
 
@@ -216,27 +288,29 @@ nsNativeThemeWin::nsNativeThemeWin() {
   mScrollbarTheme = NULL;
   mSpinTheme = NULL;
   mScaleTheme = NULL;
   mStatusbarTheme = NULL;
   mTabTheme = NULL;
   mTreeViewTheme = NULL;
   mComboBoxTheme = NULL;
   mHeaderTheme = NULL;
+  mMenuTheme = NULL;
 
   mThemeDLL = ::LoadLibrary(kThemeLibraryName);
   if (mThemeDLL) {
     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");
     getThemeColor = (GetThemeColorPtr)GetProcAddress(mThemeDLL, "GetThemeColor");
+    getThemeMargins = (GetThemeMarginsPtr)GetProcAddress(mThemeDLL, "GetThemeMargins");
   }
   mOsVersion.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
   GetVersionEx(&mOsVersion);
 
   UpdateConfig();
 
   // If there is a relevant change in forms.css for windows platform,
   // static widget style variables (e.g. sButtonBorderSize) should be 
@@ -256,16 +330,93 @@ nsNativeThemeWin::~nsNativeThemeWin() {
 static void GetNativeRect(const nsRect& aSrc, RECT& aDst) 
 {
   aDst.top = aSrc.y;
   aDst.bottom = aSrc.y + aSrc.height;
   aDst.left = aSrc.x;
   aDst.right = aSrc.x + aSrc.width;
 }
 
+static PRBool IsTopLevelMenu(nsIFrame *aFrame)
+{
+  PRBool isTopLevel(PR_FALSE);
+  nsIMenuFrame *menuFrame(nsnull);
+  CallQueryInterface(aFrame, &menuFrame);
+
+  if (menuFrame) {
+    isTopLevel = menuFrame->IsOnMenuBar();
+  }
+  return isTopLevel;
+}
+
+
+static SIZE GetCheckboxSize(HANDLE theme, HDC hdc)
+{
+    SIZE checkboxSize;
+    getThemePartSize(theme, hdc, MENU_POPUPCHECK, MC_CHECKMARKNORMAL, NULL, TS_TRUE, &checkboxSize);
+
+    MARGINS checkboxSizing;
+    MARGINS checkboxContent;
+    getThemeMargins(theme, hdc, MENU_POPUPCHECKBACKGROUND, MCB_NORMAL, TMT_SIZINGMARGINS, NULL, &checkboxSizing);
+    getThemeMargins(theme, hdc, MENU_POPUPCHECKBACKGROUND, MCB_NORMAL, TMT_CONTENTMARGINS, NULL, &checkboxContent);
+
+    int leftMargin = checkboxSizing.cxLeftWidth;
+    int rightMargin = checkboxSizing.cxRightWidth;
+    int topMargin = checkboxSizing.cyTopHeight;
+    int bottomMargin = checkboxSizing.cyBottomHeight;
+
+    int width = leftMargin + checkboxSize.cx + rightMargin;
+    int height = topMargin + checkboxSize.cy + bottomMargin;
+    SIZE ret;
+    ret.cx = width;
+    ret.cy = height;
+    return ret;
+}
+static SIZE GetCheckboxBounds(HANDLE theme, HDC hdc)
+{
+    MARGINS checkboxSizing;
+    MARGINS checkboxContent;
+    getThemeMargins(theme, hdc, MENU_POPUPCHECKBACKGROUND, MCB_NORMAL, TMT_SIZINGMARGINS, NULL, &checkboxSizing);
+    getThemeMargins(theme, hdc, MENU_POPUPCHECKBACKGROUND, MCB_NORMAL, TMT_CONTENTMARGINS, NULL, &checkboxContent);
+
+#define posdx(d) ((d) > 0 ? d : 0)
+
+    int dx = posdx(checkboxContent.cxRightWidth - checkboxSizing.cxRightWidth) + posdx(checkboxContent.cxLeftWidth - checkboxSizing.cxLeftWidth);
+    int dy = posdx(checkboxContent.cyTopHeight - checkboxSizing.cyTopHeight) + posdx(checkboxContent.cyBottomHeight - checkboxSizing.cyBottomHeight);
+
+#undef posdx
+
+    SIZE ret(GetCheckboxSize(theme,hdc));
+    ret.cx += dx;
+    ret.cy += dy;
+    return ret;
+}
+static SIZE GetGutterSize(HANDLE theme, HDC hdc)
+{
+    SIZE gutterSize;
+    getThemePartSize(theme, hdc, MENU_POPUPGUTTER, 0, NULL, TS_TRUE, &gutterSize);
+
+    SIZE checkboxSize(GetCheckboxBounds(theme, hdc));
+
+    SIZE itemSize;
+    getThemePartSize(theme, hdc, MENU_POPUPITEM, MPI_NORMAL, NULL, TS_TRUE, &itemSize);
+
+    int width = max(itemSize.cx, checkboxSize.cx + gutterSize.cx);
+    int height = max(itemSize.cy, checkboxSize.cy);
+    SIZE ret;
+    ret.cx = width;
+    ret.cy = height;
+    return ret;
+}
+
+static PRBool IsFrameRTL(nsIFrame *frame)
+{
+  return frame->GetStyleVisibility()->mDirection == NS_STYLE_DIRECTION_RTL;
+}
+
 void
 nsNativeThemeWin::UpdateConfig()
 {
   // On Windows 2000 this SystemParametersInfo call will fail
   //   and we get non-flat as desired.
   BOOL useFlat = PR_FALSE;
   mFlatMenus = ::SystemParametersInfo(SPI_GETFLATMENU, 0, &useFlat, 0) ?
                    useFlat : PR_FALSE;
@@ -384,16 +535,30 @@ nsNativeThemeWin::GetTheme(PRUint8 aWidg
     case NS_THEME_LISTBOX_LISTITEM:
     case NS_THEME_TREEVIEW:
     case NS_THEME_TREEVIEW_TWISTY_OPEN:
     case NS_THEME_TREEVIEW_TREEITEM: {
       if (!mTreeViewTheme)
         mTreeViewTheme = openTheme(NULL, L"Listview");
       return mTreeViewTheme;
     }
+    case NS_THEME_MENUBAR:
+    case NS_THEME_MENUPOPUP:
+    case NS_THEME_MENUITEM:
+    case NS_THEME_CHECKMENUITEM:
+    case NS_THEME_RADIOMENUITEM:
+    case NS_THEME_MENUCHECKBOX:
+    case NS_THEME_MENURADIO:
+    case NS_THEME_MENUSEPARATOR:
+    case NS_THEME_MENUARROW:
+    case NS_THEME_MENUIMAGE:
+    case NS_THEME_MENUITEMTEXT:
+      if (!mMenuTheme)
+        mMenuTheme = openTheme(NULL, L"Menu");
+      return mMenuTheme;
   }
   return NULL;
 }
 
 nsresult 
 nsNativeThemeWin::GetThemePartAndState(nsIFrame* aFrame, PRUint8 aWidgetType, 
                                        PRInt32& aPart, PRInt32& aState)
 {
@@ -811,16 +976,99 @@ nsNativeThemeWin::GetThemePartAndState(n
         else if (eventState & NS_EVENT_STATE_HOVER)
           aState = TS_HOVER;
         else 
           aState = TS_NORMAL;
       }
 
       return NS_OK;
     }
+    case NS_THEME_MENUPOPUP: {
+      aPart = MENU_POPUPBACKGROUND;
+      aState = MB_ACTIVE;
+      return NS_OK;
+    }
+    case NS_THEME_MENUITEM:
+    case NS_THEME_CHECKMENUITEM: 
+    case NS_THEME_RADIOMENUITEM: {
+      PRBool isTopLevel = PR_FALSE;
+      PRBool isOpen = PR_FALSE;
+      PRBool isHover = PR_FALSE;
+      nsIMenuFrame *menuFrame;
+      CallQueryInterface(aFrame, &menuFrame);
+
+      isTopLevel = IsTopLevelMenu(aFrame);
+
+      if (menuFrame)
+        isOpen = menuFrame->IsOpen();
+      isHover = CheckBooleanAttr(aFrame, nsWidgetAtoms::mozmenuactive);
+
+      if (isTopLevel) {
+        aPart = MENU_BARITEM;
+
+        if (isOpen)
+          aState = MBI_PUSHED;
+        else if (isHover)
+          aState = MBI_HOT;
+        else
+          aState = MBI_NORMAL;
+
+        // the disabled states are offset by 3
+        if (IsDisabled(aFrame))
+          aState += 3;
+      } else {
+        aPart = MENU_POPUPITEM;
+
+        if (isHover)
+          aState = MPI_HOT;
+        else
+          aState = MPI_NORMAL;
+
+        // the disabled states are offset by 2
+        if (IsDisabled(aFrame))
+          aState += 2;
+      }
+
+      return NS_OK;
+    }
+    case NS_THEME_MENUSEPARATOR:
+      aPart = MENU_POPUPSEPARATOR;
+      aState = 0;
+      return NS_OK;
+    case NS_THEME_MENUARROW:
+      aPart = MENU_POPUPSUBMENU;
+      aState = IsDisabled(aFrame) ? MSM_DISABLED : MSM_NORMAL;
+      return NS_OK;
+    case NS_THEME_MENUCHECKBOX:
+    case NS_THEME_MENURADIO:
+      {
+        PRBool isChecked;
+        PRBool isDisabled;
+
+        isChecked = CheckBooleanAttr(aFrame, nsWidgetAtoms::checked);
+        isDisabled = CheckBooleanAttr(aFrame, nsWidgetAtoms::disabled);
+
+        aPart = MENU_POPUPCHECK;
+        aState = MC_CHECKMARKNORMAL;
+
+        // Radio states are offset by 2
+        if (aWidgetType == NS_THEME_MENURADIO)
+          aState += 2;
+
+        // the disabled states are offset by 1
+        if (isDisabled)
+          aState += 1;
+
+        return NS_OK;
+      }
+    case NS_THEME_MENUITEMTEXT:
+    case NS_THEME_MENUIMAGE:
+      aPart = -1;
+      aState = 0;
+      return NS_OK;
   }
 
   aPart = 0;
   aState = 0;
   return NS_ERROR_FAILURE;
 }
 
 NS_IMETHODIMP
@@ -921,16 +1169,75 @@ RENDER_AGAIN:
       // need to subtract one from the left position, otherwise the scale's
       // border isn't visible
       contentRect.left += adjustment - 1;
       contentRect.right -= adjustment;
     }
 
     drawThemeBG(theme, hdc, part, state, &contentRect, &clipRect);
   }
+  else if (aWidgetType == NS_THEME_MENUCHECKBOX || aWidgetType == NS_THEME_MENURADIO)
+  {
+      PRBool isChecked = PR_FALSE;
+      isChecked = CheckBooleanAttr(aFrame, nsWidgetAtoms::checked);
+
+      if (isChecked)
+      {
+        int bgState = MCB_NORMAL;
+        PRBool isDisabled = IsDisabled(aFrame);
+
+        // the disabled states are offset by 1
+        if (isDisabled)
+          bgState += 1;
+
+        SIZE checkboxSize(GetCheckboxSize(theme,hdc));
+
+        RECT checkRect = widgetRect;
+        checkRect.right = checkRect.left+checkboxSize.cx;
+
+        // Center the checkbox vertically in the menuitem
+        checkRect.top += (checkRect.bottom - checkRect.top)/2 - checkboxSize.cy/2;
+        checkRect.bottom = checkRect.top + checkboxSize.cy;
+
+        drawThemeBG(theme, hdc, MENU_POPUPCHECKBACKGROUND, bgState, &checkRect, &clipRect);
+        drawThemeBG(theme, hdc, MENU_POPUPCHECK, state, &checkRect, &clipRect);
+      }
+  }
+  else if (aWidgetType == NS_THEME_MENUPOPUP)
+  {
+    drawThemeBG(theme, hdc, MENU_POPUPBORDERS, /* state */ 0, &widgetRect, &clipRect);
+    SIZE borderSize;
+    getThemePartSize(theme, hdc, MENU_POPUPBORDERS, 0, NULL, TS_TRUE, &borderSize);
+
+    RECT bgRect = widgetRect;
+    bgRect.top += borderSize.cy;
+    bgRect.bottom -= borderSize.cy;
+    bgRect.left += borderSize.cx;
+    bgRect.right -= borderSize.cx;
+
+    drawThemeBG(theme, hdc, MENU_POPUPBACKGROUND, /* state */ 0, &bgRect, &clipRect);
+
+    SIZE gutterSize(GetGutterSize(theme, hdc));
+
+    RECT gutterRect;
+    gutterRect.top = bgRect.top;
+    gutterRect.bottom = bgRect.bottom;
+    gutterRect.left = bgRect.left;
+    gutterRect.right = gutterRect.left+gutterSize.cx;
+    drawThemeBG(theme, hdc, MENU_POPUPGUTTER, /* state */ 0, &gutterRect, &clipRect);
+  }
+  else if (aWidgetType == NS_THEME_MENUSEPARATOR)
+  {
+    SIZE gutterSize(GetGutterSize(theme,hdc));
+
+    RECT sepRect = widgetRect;
+    sepRect.left += gutterSize.cx;
+    
+    drawThemeBG(theme, hdc, MENU_POPUPSEPARATOR, /* state */ 0, &sepRect, &clipRect);
+  }
   // If part is negative, the element wishes us to not render a themed
   // background, instead opting to be drawn specially below.
   else 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
@@ -986,17 +1293,20 @@ nsNativeThemeWin::GetWidgetBorder(nsIDev
 
   (*aResult).top = (*aResult).bottom = (*aResult).left = (*aResult).right = 0;
 
   if (!WidgetIsContainer(aWidgetType) ||
       aWidgetType == NS_THEME_TOOLBOX || 
       aWidgetType == NS_THEME_STATUSBAR || 
       aWidgetType == NS_THEME_RESIZER || aWidgetType == NS_THEME_TAB_PANEL ||
       aWidgetType == NS_THEME_SCROLLBAR_TRACK_HORIZONTAL ||
-      aWidgetType == NS_THEME_SCROLLBAR_TRACK_VERTICAL)
+      aWidgetType == NS_THEME_SCROLLBAR_TRACK_VERTICAL ||
+      aWidgetType == NS_THEME_MENUITEM || aWidgetType == NS_THEME_CHECKMENUITEM ||
+      aWidgetType == NS_THEME_RADIOMENUITEM || aWidgetType == NS_THEME_MENUPOPUP ||
+      aWidgetType == NS_THEME_MENUIMAGE || aWidgetType == NS_THEME_MENUITEMTEXT)
     return NS_OK; // Don't worry about it.
 
   if (!getThemeContentRect)
     return NS_ERROR_FAILURE;
 
   PRInt32 part, state;
   nsresult rv = GetThemePartAndState(aFrame, aWidgetType, part, state);
   if (NS_FAILED(rv))
@@ -1050,38 +1360,103 @@ nsNativeThemeWin::GetWidgetBorder(nsIDev
 }
 
 PRBool
 nsNativeThemeWin::GetWidgetPadding(nsIDeviceContext* aContext, 
                                    nsIFrame* aFrame,
                                    PRUint8 aWidgetType,
                                    nsMargin* aResult)
 {
-  return PR_FALSE;
+  HANDLE theme = GetTheme(aWidgetType);
+  if (!theme && aWidgetType != NS_THEME_MENUITEMTEXT)
+    return PR_FALSE;
+
+  if (aWidgetType == NS_THEME_MENUPOPUP)
+  {
+    SIZE popupSize;
+    getThemePartSize(theme, NULL, MENU_POPUPBORDERS, /* state */ 0, NULL, TS_TRUE, &popupSize);
+    aResult->top = aResult->bottom = popupSize.cy;
+    aResult->left = aResult->right = popupSize.cx;
+    return PR_TRUE;
+  }
+
+  PRInt32 right, left, top, bottom;
+  right = left = top = bottom = 0;
+  switch (aWidgetType)
+  {
+    case NS_THEME_MENUIMAGE:
+        right = 9;
+        left = 3;
+        break;
+    case NS_THEME_MENUCHECKBOX:
+    case NS_THEME_MENURADIO:
+        right = 11;
+        left = 0;
+        break;
+    case NS_THEME_MENUITEMTEXT:
+        if (!theme)
+        {
+          left = 16;
+        }
+        else
+        {
+          // There seem to be exactly 4 pixels from the edge
+          // of the gutter to the text
+          SIZE size(GetGutterSize(theme, NULL));
+          left = size.cx + 4;
+        }
+        break;
+    case NS_THEME_MENUSEPARATOR:
+        {
+          SIZE size(GetGutterSize(theme, NULL));
+          left = size.cx + 5;
+          top = 10;
+          bottom = 7;
+        }
+        break;
+    default:
+        return PR_FALSE;
+  }
+
+  if (IsFrameRTL(aFrame))
+  {
+    aResult->right = left;
+    aResult->left = right;
+  }
+  else
+  {
+    aResult->right = right;
+    aResult->left = left;
+  }
+  
+  return PR_TRUE;
 }
 
 NS_IMETHODIMP
 nsNativeThemeWin::GetMinimumWidgetSize(nsIRenderingContext* aContext, nsIFrame* aFrame,
                                        PRUint8 aWidgetType,
                                        nsSize* aResult, PRBool* aIsOverridable)
 {
   (*aResult).width = (*aResult).height = 0;
   *aIsOverridable = PR_TRUE;
 
   HANDLE theme = GetTheme(aWidgetType);
   if (!theme)
     return ClassicGetMinimumWidgetSize(aContext, aFrame, aWidgetType, aResult, aIsOverridable);
- 
+
   if (aWidgetType == NS_THEME_TOOLBOX || aWidgetType == NS_THEME_TOOLBAR || 
       aWidgetType == NS_THEME_STATUSBAR || aWidgetType == NS_THEME_PROGRESSBAR_CHUNK ||
       aWidgetType == NS_THEME_PROGRESSBAR_CHUNK_VERTICAL ||
       aWidgetType == NS_THEME_TAB_PANELS || aWidgetType == NS_THEME_TAB_PANEL ||
-      aWidgetType == NS_THEME_LISTBOX || aWidgetType == NS_THEME_TREEVIEW)
+      aWidgetType == NS_THEME_LISTBOX || aWidgetType == NS_THEME_TREEVIEW || aWidgetType == NS_THEME_MENUITEMTEXT)
     return NS_OK; // Don't worry about it.
 
+  if (aWidgetType == NS_THEME_MENUITEM && IsTopLevelMenu(aFrame))
+      return NS_OK; // Don't worry about it for top level menus
+
   if (!getThemePartSize)
     return NS_ERROR_FAILURE;
   
   // Call GetSystemMetrics to determine size for WinXP scrollbars
   // (GetThemeSysSize API returns the optimal size for the theme, but 
   //  Windows appears to always use metrics when drawing standard scrollbars)
   switch (aWidgetType) {
     case NS_THEME_SCROLLBAR_THUMB_VERTICAL:
@@ -1089,16 +1464,43 @@ nsNativeThemeWin::GetMinimumWidgetSize(n
     case NS_THEME_SCROLLBAR_BUTTON_UP:
     case NS_THEME_SCROLLBAR_BUTTON_DOWN:
     case NS_THEME_SCROLLBAR_BUTTON_LEFT:
     case NS_THEME_SCROLLBAR_BUTTON_RIGHT:
     case NS_THEME_SCROLLBAR_TRACK_HORIZONTAL:
     case NS_THEME_SCROLLBAR_TRACK_VERTICAL:
     case NS_THEME_DROPDOWN_BUTTON: 
       return ClassicGetMinimumWidgetSize(aContext, aFrame, aWidgetType, aResult, aIsOverridable);
+    case NS_THEME_MENUITEM:
+    case NS_THEME_CHECKMENUITEM:
+    case NS_THEME_RADIOMENUITEM:
+      if(!IsTopLevelMenu(aFrame))
+      {
+        SIZE gutterSize(GetGutterSize(theme, NULL));
+        aResult->width = gutterSize.cx;
+        aResult->height = gutterSize.cy;
+        return NS_OK;
+      }
+      break;
+    case NS_THEME_MENUIMAGE:
+      aResult->width = 1;
+    case NS_THEME_MENUCHECKBOX:
+    case NS_THEME_MENURADIO:
+      {
+        SIZE boxSize(GetGutterSize(theme, NULL));
+        aResult->width += boxSize.cx+2;
+        aResult->height = boxSize.cy;
+        *aIsOverridable = PR_FALSE;
+      }
+    case NS_THEME_MENUITEMTEXT:
+      return NS_OK;
+    case NS_THEME_MENUARROW:
+      aResult->width = 26;
+      aResult->height = 16;
+      return NS_OK;
   }
 
   if (aWidgetType == NS_THEME_SCALE_THUMB_HORIZONTAL ||
       aWidgetType == NS_THEME_SCALE_THUMB_VERTICAL) {
       *aIsOverridable = PR_FALSE;
   }
 
   PRInt32 part, state;
@@ -1123,17 +1525,21 @@ nsNativeThemeWin::GetMinimumWidgetSize(n
   aResult->width = sz.cx;
   aResult->height = sz.cy;
 
   if (aWidgetType == NS_THEME_SPINNER_UP_BUTTON ||
       aWidgetType == NS_THEME_SPINNER_DOWN_BUTTON) {
     aResult->width++;
     aResult->height = aResult->height / 2 + 1;
   }
-
+  else if (aWidgetType == NS_THEME_MENUSEPARATOR)
+  {
+    SIZE gutterSize(GetGutterSize(theme,hdc));
+    aResult->width += gutterSize.cx;
+  }
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsNativeThemeWin::WidgetStateChanged(nsIFrame* aFrame, PRUint8 aWidgetType, 
                                      nsIAtom* aAttribute, PRBool* aShouldRepaint)
 {
   // Some widget types just never change state.
@@ -1229,31 +1635,37 @@ nsNativeThemeWin::CloseData()
   if (mComboBoxTheme) {
     closeTheme(mComboBoxTheme);
     mComboBoxTheme = NULL;
   }
   if (mHeaderTheme) {
     closeTheme(mHeaderTheme);
     mHeaderTheme = NULL;
   }
+  if (mMenuTheme) {
+    closeTheme(mMenuTheme);
+    mMenuTheme = NULL;
+  }
 }
 
 NS_IMETHODIMP
 nsNativeThemeWin::ThemeChanged()
 {
   CloseData();
   UpdateConfig();
   return NS_OK;
 }
 
 PRBool 
 nsNativeThemeWin::ThemeSupportsWidget(nsPresContext* aPresContext,
                                       nsIFrame* aFrame,
                                       PRUint8 aWidgetType)
 {
+  if (gfxPlatform::UseGlitz())
+    return PR_FALSE;
   // XXXdwh We can go even further and call the API to ask if support exists for
   // specific widgets.
 
   if (aPresContext && !aPresContext->PresShell()->IsThemeSupportEnabled())
     return PR_FALSE;
 
   HANDLE theme = NULL;
   if (aWidgetType == NS_THEME_CHECKBOX_CONTAINER)
@@ -1347,16 +1759,18 @@ nsNativeThemeWin::ClassicThemeSupportsWi
     case NS_THEME_TAB_PANEL:
     case NS_THEME_TAB_PANELS:
     case NS_THEME_MENUITEM:
     case NS_THEME_CHECKMENUITEM:
     case NS_THEME_RADIOMENUITEM:
     case NS_THEME_MENUCHECKBOX:
     case NS_THEME_MENURADIO:
     case NS_THEME_MENUARROW:
+    case NS_THEME_MENUSEPARATOR:
+    case NS_THEME_MENUITEMTEXT:
       return PR_TRUE;
   }
   return PR_FALSE;
 }
 
 nsresult
 nsNativeThemeWin::ClassicGetWidgetBorder(nsIDeviceContext* aContext, 
                                   nsIFrame* aFrame,
@@ -1539,16 +1953,22 @@ nsNativeThemeWin::ClassicGetMinimumWidge
       (*aResult).height = ::GetSystemMetrics(SM_CXHTHUMB);
       (*aResult).width = (*aResult).height >> 1;
       *aIsOverridable = PR_FALSE;
       break;
     case NS_THEME_SCROLLBAR_TRACK_HORIZONTAL:
       (*aResult).width = ::GetSystemMetrics(SM_CXHTHUMB) << 1;
       break;
     }
+    case NS_THEME_MENUSEPARATOR:
+    {
+      aResult->width = 0;
+      aResult->height = 10;
+      break;
+    }
     default:
       return NS_ERROR_FAILURE;
   }  
   return NS_OK;
 }
 
 
 nsresult nsNativeThemeWin::ClassicGetThemePartAndState(nsIFrame* aFrame, PRUint8 aWidgetType,
@@ -1799,16 +2219,20 @@ nsresult nsNativeThemeWin::ClassicGetThe
       }
 
       return NS_OK;    
     }
     case NS_THEME_RESIZER:    
       aPart = DFC_SCROLL;
       aState = DFCS_SCROLLSIZEGRIP;
       return NS_OK;
+    case NS_THEME_MENUSEPARATOR:
+      aPart = 0;
+      aState = 0;
+      return NS_OK;
   }
   return NS_ERROR_FAILURE;
 }
 
 // Draw classic Windows tab
 // (no system API for this, but DrawEdge can draw all the parts of a tab)
 static void DrawTab(HDC hdc, const RECT& R, PRInt32 aPosition, PRBool aSelected,
                     PRBool aDrawLeft, PRBool aDrawRight)
@@ -2252,16 +2676,31 @@ RENDER_AGAIN:
       else if (aWidgetType == NS_THEME_MENURADIO)
         DrawMenuImage(hdc, widgetRect, DFCS_MENUBULLET, color);
       else if (aWidgetType == NS_THEME_MENUARROW)
         DrawMenuImage(hdc, widgetRect, 
                       (state & DFCS_RTL) ? DFCS_MENUARROWRIGHT : DFCS_MENUARROW,
                       color);
       break;
     }
+    case NS_THEME_MENUSEPARATOR: {
+      // separators are offset by a bit (see menu.css)
+      widgetRect.left++;
+      widgetRect.right--;
+
+      // This magic number is brought to you by the value in menu.css
+      widgetRect.top += 4;
+      // Our rectangles are 1 pixel high (see border size in menu.css)
+      widgetRect.bottom = widgetRect.top+1;
+      ::FillRect(hdc, &widgetRect, (HBRUSH)(COLOR_3DSHADOW+1));
+      widgetRect.top++;
+      widgetRect.bottom++;
+      ::FillRect(hdc, &widgetRect, (HBRUSH)(COLOR_3DHILIGHT+1));
+      break;
+    }
 #endif
     default:
       rv = NS_ERROR_FAILURE;
       break;
   }
 
   nativeDrawing.EndNativeDrawing();
 
--- a/widget/src/windows/nsNativeThemeWin.h
+++ b/widget/src/windows/nsNativeThemeWin.h
@@ -131,15 +131,16 @@ private:
   HANDLE mScrollbarTheme;
   HANDLE mScaleTheme;
   HANDLE mSpinTheme;
   HANDLE mStatusbarTheme;
   HANDLE mTabTheme;
   HANDLE mTreeViewTheme;
   HANDLE mComboBoxTheme;
   HANDLE mHeaderTheme;
+  HANDLE mMenuTheme;
 
   BOOL mFlatMenus;
   OSVERSIONINFO mOsVersion;
 };
 
 // Creator function
 extern NS_METHOD NS_NewNativeThemeWin(nsISupports *aOuter, REFNSIID aIID, void **aResult);
--- a/widget/src/windows/nsWindow.cpp
+++ b/widget/src/windows/nsWindow.cpp
@@ -334,30 +334,33 @@ static PRBool IsCursorTranslucencySuppor
   }
 
   return isSupported;
 }
 
 
 static PRBool IsWin2k()
 {
+  return GetWindowsVersion() == WIN2K_VERSION;
+}
+
+PRInt32 GetWindowsVersion()
+{
+  static PRInt32 version = 0;
   static PRBool didCheck = PR_FALSE;
-  static PRBool isWin2k = PR_FALSE;
-
-  if (!didCheck) {
-    didCheck = PR_TRUE;
-    OSVERSIONINFO versionInfo;
-  
-    versionInfo.dwOSVersionInfoSize = sizeof(versionInfo);
-    if (::GetVersionEx(&versionInfo))
-      isWin2k = versionInfo.dwMajorVersion == 5 &&
-                versionInfo.dwMinorVersion == 0;
-  }
-
-  return isWin2k;
+
+  if (!didCheck)
+  {
+    OSVERSIONINFOEX osInfo;
+    osInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
+    // This cast is safe and supposed to be here, don't worry
+    ::GetVersionEx((OSVERSIONINFO*)&osInfo);
+    version = (osInfo.dwMajorVersion & 0xff) << 8 | (osInfo.dwMinorVersion & 0xff);
+  }
+  return version;
 }
 
 
 // Pick some random timer ID.  Is there a better way?
 #define NS_FLASH_TIMER_ID 0x011231984
 
 static NS_DEFINE_CID(kCClipboardCID,       NS_CLIPBOARD_CID);
 static NS_DEFINE_IID(kRenderingContextCID, NS_RENDERING_CONTEXT_CID);
--- a/widget/src/windows/nsWindow.h
+++ b/widget/src/windows/nsWindow.h
@@ -76,16 +76,23 @@ class imgIContainer;
 
 #define IME_MAX_CHAR_POS       64
 
 #define NSRGB_2_COLOREF(color) \
             RGB(NS_GET_R(color),NS_GET_G(color),NS_GET_B(color))
 #define COLOREF_2_NSRGB(color) \
             NS_RGB(GetRValue(color), GetGValue(color), GetBValue(color))
 
+#define WIN2K_VERSION   0x500
+#define WINXP_VERSION   0x501
+#define WIN2K3_VERSION  0x502
+#define VISTA_VERSION   0x600
+
+PRInt32 GetWindowsVersion();
+
 /*
  * ::: IMPORTANT :::
  * External apps and drivers depend on window class names.
  * For example, changing the window classes
  * could break touchpad scrolling or screen readers.
  */
 const PRUint32 kMaxClassNameLength    = 40;
 const LPCWSTR kWClassNameHidden       = L"MozillaHiddenWindowClass";
@@ -414,16 +421,17 @@ protected:
 #endif
   HDC           mMemoryDC;
   HBITMAP       mMemoryBitmap;
   PRUint8*      mMemoryBits;
   PRUint8*      mAlphaMask;
   PRPackedBool  mIsTranslucent;
   PRPackedBool  mIsTopTranslucent;     // Topmost window itself or any of it's child windows has tranlucency enabled
 #endif
+  PRPackedBool  mHasAeroGlass;
   PRPackedBool  mIsTopWidgetWindow;
   PRPackedBool  mHas3DBorder;
   PRPackedBool  mIsShiftDown;
   PRPackedBool  mIsControlDown;
   PRPackedBool  mIsAltDown;
   PRPackedBool  mIsDestroying;
   PRPackedBool  mOnDestroyCalled;
   PRPackedBool  mIsVisible;