Bug 1428676 pt 1. Add a '-moz-menulist-button' value to '-moz-appearance'. r=emilio
authorJonathan Watt <jwatt@jwatt.org>
Tue, 19 Jun 2018 20:12:45 +0100
changeset 484635 e6b8bc93e51db6c44b2a537e604deaef69e4f7d0
parent 484634 64b3367f923659247a54c771266d7531c87b8c18
child 484636 4ebcaa67c3f763e0c3a0e549d2cf798b240c2215
push id9719
push userffxbld-merge
push dateFri, 24 Aug 2018 17:49:46 +0000
treeherdermozilla-beta@719ec98fba77 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersemilio
bugs1428676
milestone63.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1428676 pt 1. Add a '-moz-menulist-button' value to '-moz-appearance'. r=emilio The '-moz-menulist-button' value currently behavies identically to the 'menulist-button' value. This is not implemented as an alias because later patches in this patch series will change the behavior of our pre-existing 'menulist-button' value to more closely match what Chrome does.
devtools/shared/css/generated/properties-db.js
layout/style/ServoStyleConsts.h
servo/components/style/properties/longhands/box.mako.rs
servo/components/style/values/specified/box.rs
widget/cocoa/nsNativeThemeCocoa.mm
widget/gtk/nsNativeThemeGTK.cpp
widget/headless/HeadlessThemeGTK.cpp
widget/windows/nsNativeThemeWin.cpp
--- a/devtools/shared/css/generated/properties-db.js
+++ b/devtools/shared/css/generated/properties-db.js
@@ -191,16 +191,17 @@ exports.CSS_PROPERTIES = {
       "-moz-mac-fullscreen-button",
       "-moz-mac-help-button",
       "-moz-mac-source-list",
       "-moz-mac-source-list-selection",
       "-moz-mac-vibrancy-dark",
       "-moz-mac-vibrancy-light",
       "-moz-mac-vibrant-titlebar-dark",
       "-moz-mac-vibrant-titlebar-light",
+      "-moz-menulist-button",
       "-moz-win-borderless-glass",
       "-moz-win-browsertabbar-toolbox",
       "-moz-win-communications-toolbox",
       "-moz-win-exclude-glass",
       "-moz-win-glass",
       "-moz-win-media-toolbox",
       "-moz-window-button-box",
       "-moz-window-button-box-maximized",
--- a/layout/style/ServoStyleConsts.h
+++ b/layout/style/ServoStyleConsts.h
@@ -73,16 +73,18 @@ enum class StyleAppearance : uint8_t {
   Menuseparator,
   Menuarrow,
   // An image in the menu gutter, like in bookmarks or history.
   Menuimage,
   // A horizontal meter bar.
   Meterbar,
   // The meter bar's meter indicator.
   Meterchunk,
+  // The dropdown button(s) that open up a dropdown list.
+  MozMenulistButton,
   // For HTML's <input type=number>
   NumberInput,
   // A horizontal progress bar.
   Progressbar,
   // The progress bar's progress indicator
   Progresschunk,
   // A vertical progress bar.
   ProgressbarVertical,
--- a/servo/components/style/properties/longhands/box.mako.rs
+++ b/servo/components/style/properties/longhands/box.mako.rs
@@ -510,17 +510,16 @@
 // Non-standard
 ${helpers.predefined_type(
     "-moz-appearance",
     "Appearance",
     "computed::Appearance::None",
     products="gecko",
     alias="-webkit-appearance:layout.css.webkit-appearance.enabled",
     spec="Nonstandard (https://developer.mozilla.org/en-US/docs/Web/CSS/-moz-appearance)",
-    needs_context=False,
     animation_value_type="discrete",
 )}
 
 ${helpers.predefined_type("-moz-binding", "url::UrlOrNone", "computed::url::UrlOrNone::none()",
                           products="gecko",
                           animation_value_type="none",
                           gecko_ffi_name="mBinding",
                           spec="Nonstandard (https://developer.mozilla.org/en-US/docs/Web/CSS/-moz-binding)")}
--- a/servo/components/style/values/specified/box.rs
+++ b/servo/components/style/values/specified/box.rs
@@ -15,32 +15,35 @@ use style_traits::{CssWriter, KeywordsCo
 use values::{CustomIdent, KeyframesName};
 use values::generics::box_::AnimationIterationCount as GenericAnimationIterationCount;
 use values::generics::box_::Perspective as GenericPerspective;
 use values::generics::box_::VerticalAlign as GenericVerticalAlign;
 use values::specified::{AllowQuirks, Number};
 use values::specified::length::{LengthOrPercentage, NonNegativeLength};
 
 #[cfg(feature = "gecko")]
+fn in_ua_or_chrome_sheet(context: &ParserContext) -> bool {
+    use stylesheets::Origin;
+    context.stylesheet_origin == Origin::UserAgent ||
+    context.chrome_rules_enabled()
+}
+
+#[cfg(feature = "gecko")]
 fn moz_display_values_enabled(context: &ParserContext) -> bool {
     use gecko_bindings::structs;
-    use stylesheets::Origin;
-    context.stylesheet_origin == Origin::UserAgent ||
-    context.chrome_rules_enabled() ||
+    in_ua_or_chrome_sheet(context) ||
     unsafe {
         structs::StaticPrefs_sVarCache_layout_css_xul_display_values_content_enabled
     }
 }
 
 #[cfg(feature = "gecko")]
 fn moz_box_display_values_enabled(context: &ParserContext) -> bool {
     use gecko_bindings::structs;
-    use stylesheets::Origin;
-    context.stylesheet_origin == Origin::UserAgent ||
-    context.chrome_rules_enabled() ||
+    in_ua_or_chrome_sheet(context) ||
     unsafe {
         structs::StaticPrefs_sVarCache_layout_css_xul_box_display_values_content_enabled
     }
 }
 
 /// Defines an element’s display type, which consists of
 /// the two basic qualities of how an element generates boxes
 /// <https://drafts.csswg.org/css-display/#propdef-display>
@@ -943,16 +946,19 @@ pub enum Appearance {
     Menuseparator,
     Menuarrow,
     /// An image in the menu gutter, like in bookmarks or history.
     Menuimage,
     /// A horizontal meter bar.
     Meterbar,
     /// The meter bar's meter indicator.
     Meterchunk,
+    /// The "arrowed" part of the dropdown button that open up a dropdown list.
+    #[parse(condition = "in_ua_or_chrome_sheet")]
+    MozMenulistButton,
     /// For HTML's <input type=number>
     NumberInput,
     /// A horizontal progress bar.
     Progressbar,
     /// The progress bar's progress indicator
     Progresschunk,
     /// A vertical progress bar.
     ProgressbarVertical,
--- a/widget/cocoa/nsNativeThemeCocoa.mm
+++ b/widget/cocoa/nsNativeThemeCocoa.mm
@@ -3322,16 +3322,17 @@ nsNativeThemeCocoa::ComputeWidgetInfo(ns
       DropdownParams params;
       params.controlParams = controlParams;
       params.pullsDown = false;
       params.editable = aWidgetType == StyleAppearance::MenulistTextfield;
       return Some(WidgetInfo::Dropdown(params));
     }
 
     case StyleAppearance::MenulistButton:
+    case StyleAppearance::MozMenulistButton:
       return Some(WidgetInfo::Button(
         ButtonParams{ComputeControlParams(aFrame, eventState),
                      ButtonType::eArrowButton}));
 
     case StyleAppearance::Groupbox:
       return Some(WidgetInfo::GroupBox());
 
     case StyleAppearance::Textfield:
@@ -3863,16 +3864,17 @@ nsNativeThemeCocoa::CreateWebRenderComma
     case StyleAppearance::Toolbarbutton:
     case StyleAppearance::Separator:
     case StyleAppearance::Toolbar:
     case StyleAppearance::MozWindowTitlebar:
     case StyleAppearance::Statusbar:
     case StyleAppearance::Menulist:
     case StyleAppearance::MenulistTextfield:
     case StyleAppearance::MenulistButton:
+    case StyleAppearance::MozMenulistButton:
     case StyleAppearance::Groupbox:
     case StyleAppearance::Textfield:
     case StyleAppearance::NumberInput:
     case StyleAppearance::Searchfield:
     case StyleAppearance::Progressbar:
     case StyleAppearance::ProgressbarVertical:
     case StyleAppearance::Meterbar:
     case StyleAppearance::Treetwisty:
@@ -4028,16 +4030,17 @@ nsNativeThemeCocoa::GetWidgetBorder(nsDe
       // nsCheckboxRadioFrame::GetIntrinsicWidth and nsCheckboxRadioFrame::GetIntrinsicHeight
       // assume a border width of 2px.
       result.SizeTo(2, 2, 2, 2);
       break;
     }
 
     case StyleAppearance::Menulist:
     case StyleAppearance::MenulistButton:
+    case StyleAppearance::MozMenulistButton:
       result = DirectionAwareMargin(kAquaDropdownBorder, aFrame);
       break;
 
     case StyleAppearance::MenulistTextfield:
       result = DirectionAwareMargin(kAquaComboboxBorder, aFrame);
       break;
 
     case StyleAppearance::NumberInput:
@@ -4155,16 +4158,17 @@ nsNativeThemeCocoa::GetWidgetOverflow(ns
     case StyleAppearance::Toolbarbutton:
     case StyleAppearance::NumberInput:
     case StyleAppearance::Textfield:
     case StyleAppearance::TextfieldMultiline:
     case StyleAppearance::Searchfield:
     case StyleAppearance::Listbox:
     case StyleAppearance::Menulist:
     case StyleAppearance::MenulistButton:
+    case StyleAppearance::MozMenulistButton:
     case StyleAppearance::MenulistTextfield:
     case StyleAppearance::Checkbox:
     case StyleAppearance::Radio:
     case StyleAppearance::Tab:
     case StyleAppearance::FocusOutline:
     {
       overflow.SizeTo(kMaxFocusRingWidth,
                       kMaxFocusRingWidth,
@@ -4285,16 +4289,17 @@ nsNativeThemeCocoa::GetMinimumWidgetSize
       }
       aResult->SizeTo(buttonWidth, buttonHeight);
       *aIsOverridable = true;
       break;
     }
 
     case StyleAppearance::Menulist:
     case StyleAppearance::MenulistButton:
+    case StyleAppearance::MozMenulistButton:
     {
       SInt32 popupHeight = 0;
       ::GetThemeMetric(kThemeMetricPopupButtonHeight, &popupHeight);
       aResult->SizeTo(0, popupHeight);
       break;
     }
 
     case StyleAppearance::NumberInput:
@@ -4611,26 +4616,28 @@ nsNativeThemeCocoa::ThemeChanged()
   return NS_OK;
 }
 
 bool
 nsNativeThemeCocoa::ThemeSupportsWidget(nsPresContext* aPresContext, nsIFrame* aFrame,
                                       WidgetType aWidgetType)
 {
   // if this is a dropdown button in a combobox the answer is always no
-  if (aWidgetType == StyleAppearance::MenulistButton) {
+  if (aWidgetType == StyleAppearance::MenulistButton ||
+      aWidgetType == StyleAppearance::MozMenulistButton) {
     nsIFrame* parentFrame = aFrame->GetParent();
     if (parentFrame && parentFrame->IsComboboxControlFrame())
       return false;
   }
 
   switch (aWidgetType) {
     // Combobox dropdowns don't support native theming in vertical mode.
     case StyleAppearance::Menulist:
     case StyleAppearance::MenulistButton:
+    case StyleAppearance::MozMenulistButton:
     case StyleAppearance::MenulistText:
     case StyleAppearance::MenulistTextfield:
       if (aFrame && aFrame->GetWritingMode().IsVertical()) {
         return false;
       }
       MOZ_FALLTHROUGH;
 
     case StyleAppearance::Listbox:
@@ -4750,16 +4757,17 @@ nsNativeThemeCocoa::ThemeSupportsWidget(
 }
 
 bool
 nsNativeThemeCocoa::WidgetIsContainer(WidgetType aWidgetType)
 {
   // flesh this out at some point
   switch (aWidgetType) {
    case StyleAppearance::MenulistButton:
+   case StyleAppearance::MozMenulistButton:
    case StyleAppearance::Radio:
    case StyleAppearance::Checkbox:
    case StyleAppearance::Progressbar:
    case StyleAppearance::Meterbar:
    case StyleAppearance::Range:
    case StyleAppearance::MozMacHelpButton:
    case StyleAppearance::MozMacDisclosureButtonOpen:
    case StyleAppearance::MozMacDisclosureButtonClosed:
--- a/widget/gtk/nsNativeThemeGTK.cpp
+++ b/widget/gtk/nsNativeThemeGTK.cpp
@@ -299,17 +299,18 @@ nsNativeThemeGTK::GetGtkWidgetAndState(S
 
       aState->focused = TRUE;
       aState->depressed = TRUE; // see moz_gtk_entry_paint()
     } else if (aWidgetType == StyleAppearance::Button ||
                aWidgetType == StyleAppearance::Toolbarbutton ||
                aWidgetType == StyleAppearance::Dualbutton ||
                aWidgetType == StyleAppearance::ToolbarbuttonDropdown ||
                aWidgetType == StyleAppearance::Menulist ||
-               aWidgetType == StyleAppearance::MenulistButton) {
+               aWidgetType == StyleAppearance::MenulistButton ||
+               aWidgetType == StyleAppearance::MozMenulistButton) {
       aState->active &= aState->inHover;
     } else if (aWidgetType == StyleAppearance::Treetwisty ||
                aWidgetType == StyleAppearance::Treetwistyopen) {
       nsTreeBodyFrame *treeBodyFrame = do_QueryFrame(aFrame);
       if (treeBodyFrame) {
         const mozilla::AtomArray& atoms =
           treeBodyFrame->GetPropertyArrayForCurrentDrawingItem();
         aState->selected = atoms.Contains(nsGkAtoms::selected);
@@ -416,26 +417,29 @@ nsNativeThemeGTK::GetGtkWidgetAndState(S
 
       // A button with drop down menu open or an activated toggle button
       // should always appear depressed.
       if (aWidgetType == StyleAppearance::Button ||
           aWidgetType == StyleAppearance::Toolbarbutton ||
           aWidgetType == StyleAppearance::Dualbutton ||
           aWidgetType == StyleAppearance::ToolbarbuttonDropdown ||
           aWidgetType == StyleAppearance::Menulist ||
-          aWidgetType == StyleAppearance::MenulistButton) {
+          aWidgetType == StyleAppearance::MenulistButton ||
+          aWidgetType == StyleAppearance::MozMenulistButton) {
         bool menuOpen = IsOpenButton(aFrame);
         aState->depressed = IsCheckedButton(aFrame) || menuOpen;
         // we must not highlight buttons with open drop down menus on hover.
         aState->inHover = aState->inHover && !menuOpen;
       }
 
       // When the input field of the drop down button has focus, some themes
       // should draw focus for the drop down button as well.
-      if (aWidgetType == StyleAppearance::MenulistButton && aWidgetFlags) {
+      if ((aWidgetType == StyleAppearance::MenulistButton ||
+           aWidgetType == StyleAppearance::MozMenulistButton) &&
+          aWidgetFlags) {
         *aWidgetFlags = CheckBooleanAttr(aFrame, nsGkAtoms::parentfocused);
       }
     }
   }
 
   switch (aWidgetType) {
   case StyleAppearance::Button:
     if (aWidgetFlags)
@@ -618,16 +622,17 @@ nsNativeThemeGTK::GetGtkWidgetAndState(S
         *aWidgetFlags = IsFrameContentNodeInNamespace(aFrame, kNameSpaceID_XHTML);
     break;
   case StyleAppearance::MenulistText:
     return false; // nothing to do, but prevents the bg from being drawn
   case StyleAppearance::MenulistTextfield:
     aGtkWidgetType = MOZ_GTK_DROPDOWN_ENTRY;
     break;
   case StyleAppearance::MenulistButton:
+  case StyleAppearance::MozMenulistButton:
     aGtkWidgetType = MOZ_GTK_DROPDOWN_ARROW;
     break;
   case StyleAppearance::ToolbarbuttonDropdown:
   case StyleAppearance::ButtonArrowDown:
   case StyleAppearance::ButtonArrowUp:
   case StyleAppearance::ButtonArrowNext:
   case StyleAppearance::ButtonArrowPrevious:
     aGtkWidgetType = MOZ_GTK_TOOLBARBUTTON_ARROW;
@@ -1393,16 +1398,17 @@ nsNativeThemeGTK::GetWidgetPadding(nsDev
     case StyleAppearance::MozWindowButtonClose:
     case StyleAppearance::MozWindowButtonMinimize:
     case StyleAppearance::MozWindowButtonMaximize:
     case StyleAppearance::MozWindowButtonRestore:
     case StyleAppearance::Dualbutton:
     case StyleAppearance::TabScrollArrowBack:
     case StyleAppearance::TabScrollArrowForward:
     case StyleAppearance::MenulistButton:
+    case StyleAppearance::MozMenulistButton:
     case StyleAppearance::ToolbarbuttonDropdown:
     case StyleAppearance::ButtonArrowUp:
     case StyleAppearance::ButtonArrowDown:
     case StyleAppearance::ButtonArrowNext:
     case StyleAppearance::ButtonArrowPrevious:
     case StyleAppearance::RangeThumb:
     // Radios and checkboxes return a fixed size in GetMinimumWidgetSize
     // and have a meaningful baseline, so they can't have
@@ -1595,16 +1601,17 @@ nsNativeThemeGTK::GetMinimumWidgetSize(n
     case StyleAppearance::TabScrollArrowBack:
     case StyleAppearance::TabScrollArrowForward:
       {
         moz_gtk_get_tab_scroll_arrow_size(&aResult->width, &aResult->height);
         *aIsOverridable = false;
       }
       break;
   case StyleAppearance::MenulistButton:
+  case StyleAppearance::MozMenulistButton:
     {
       moz_gtk_get_combo_box_entry_button_size(&aResult->width,
                                               &aResult->height);
       *aIsOverridable = false;
     }
     break;
   case StyleAppearance::Menuseparator:
     {
@@ -1947,16 +1954,17 @@ nsNativeThemeGTK::ThemeSupportsWidget(ns
   case StyleAppearance::MozWindowTitlebar:
   case StyleAppearance::MozWindowTitlebarMaximized:
     // GtkHeaderBar is available on GTK 3.10+, which is used for styling
     // title bars and title buttons.
     return gtk_check_version(3, 10, 0) == nullptr &&
            !IsWidgetStyled(aPresContext, aFrame, aWidgetType);
 
   case StyleAppearance::MenulistButton:
+  case StyleAppearance::MozMenulistButton:
     if (aFrame && aFrame->GetWritingMode().IsVertical()) {
       return false;
     }
     // "Native" dropdown buttons cause padding and margin problems, but only
     // in HTML so allow them in XUL.
     return (!aFrame || IsFrameContentNodeInNamespace(aFrame, kNameSpaceID_XUL)) &&
            !IsWidgetStyled(aPresContext, aFrame, aWidgetType);
 
@@ -1969,16 +1977,17 @@ nsNativeThemeGTK::ThemeSupportsWidget(ns
   return false;
 }
 
 NS_IMETHODIMP_(bool)
 nsNativeThemeGTK::WidgetIsContainer(StyleAppearance aWidgetType)
 {
   // XXXdwh At some point flesh all of this out.
   if (aWidgetType == StyleAppearance::MenulistButton ||
+      aWidgetType == StyleAppearance::MozMenulistButton ||
       aWidgetType == StyleAppearance::Radio ||
       aWidgetType == StyleAppearance::RangeThumb ||
       aWidgetType == StyleAppearance::Checkbox ||
       aWidgetType == StyleAppearance::TabScrollArrowBack ||
       aWidgetType == StyleAppearance::TabScrollArrowForward ||
       aWidgetType == StyleAppearance::ButtonArrowUp ||
       aWidgetType == StyleAppearance::ButtonArrowDown ||
       aWidgetType == StyleAppearance::ButtonArrowNext ||
--- a/widget/headless/HeadlessThemeGTK.cpp
+++ b/widget/headless/HeadlessThemeGTK.cpp
@@ -83,16 +83,17 @@ HeadlessThemeGTK::GetWidgetBorder(nsDevi
       break;
     case StyleAppearance::Menulist:
       result.top = 6;
       result.right = 22;
       result.bottom = 6;
       result.left = 7;
       break;
     case StyleAppearance::MenulistButton:
+    case StyleAppearance::MozMenulistButton:
       result.top = 1;
       result.right = 1;
       result.bottom = 1;
       result.left = 0;
       break;
     case StyleAppearance::MenulistTextfield:
       result.top = 1;
       result.right = 0;
@@ -130,16 +131,17 @@ HeadlessThemeGTK::GetWidgetPadding(nsDev
     case StyleAppearance::ToolbarbuttonDropdown:
     case StyleAppearance::ButtonArrowUp:
     case StyleAppearance::ButtonArrowDown:
     case StyleAppearance::ButtonArrowNext:
     case StyleAppearance::ButtonArrowPrevious:
     case StyleAppearance::TabScrollArrowBack:
     case StyleAppearance::TabScrollArrowForward:
     case StyleAppearance::MenulistButton:
+    case StyleAppearance::MozMenulistButton:
     case StyleAppearance::RangeThumb:
     case StyleAppearance::ButtonFocus:
       aResult->top = 0;
       aResult->right = 0;
       aResult->bottom = 0;
       aResult->left = 0;
       return true;
     case StyleAppearance::Menuitem:
@@ -267,16 +269,17 @@ HeadlessThemeGTK::GetMinimumWidgetSize(n
       aResult->height = 31;
       *aIsOverridable = false;
       break;
     case StyleAppearance::Menulist:
       aResult->width = 44;
       aResult->height = 27;
       break;
     case StyleAppearance::MenulistButton:
+    case StyleAppearance::MozMenulistButton:
       aResult->width = 29;
       aResult->height = 28;
       *aIsOverridable = false;
       break;
     case StyleAppearance::ScalethumbHorizontal:
     case StyleAppearance::RangeThumb:
       aResult->width = 14;
       aResult->height = 18;
@@ -404,28 +407,30 @@ HeadlessThemeGTK::ThemeSupportsWidget(ns
     case StyleAppearance::Menuitem:
     case StyleAppearance::Checkmenuitem:
     case StyleAppearance::Radiomenuitem:
     case StyleAppearance::Menuseparator:
     case StyleAppearance::Menuarrow:
     case StyleAppearance::MozGtkInfoBar:
       return !IsWidgetStyled(aPresContext, aFrame, aWidgetType);
     case StyleAppearance::MenulistButton:
+    case StyleAppearance::MozMenulistButton:
       return (!aFrame || IsFrameContentNodeInNamespace(aFrame, kNameSpaceID_XUL)) &&
               !IsWidgetStyled(aPresContext, aFrame, aWidgetType);
     default:
       break;
   }
   return false;
 }
 
 NS_IMETHODIMP_(bool)
 HeadlessThemeGTK::WidgetIsContainer(WidgetType aWidgetType)
 {
     if (aWidgetType == StyleAppearance::MenulistButton ||
+        aWidgetType == StyleAppearance::MozMenulistButton ||
         aWidgetType == StyleAppearance::Radio ||
         aWidgetType == StyleAppearance::RangeThumb ||
         aWidgetType == StyleAppearance::Checkbox ||
         aWidgetType == StyleAppearance::TabScrollArrowBack ||
         aWidgetType == StyleAppearance::TabScrollArrowForward ||
         aWidgetType == StyleAppearance::ButtonArrowUp ||
         aWidgetType == StyleAppearance::ButtonArrowDown ||
         aWidgetType == StyleAppearance::ButtonArrowNext ||
--- a/widget/windows/nsNativeThemeWin.cpp
+++ b/widget/windows/nsNativeThemeWin.cpp
@@ -780,16 +780,17 @@ mozilla::Maybe<nsUXThemeClass> nsNativeT
       return Some(eUXSpin);
     case StyleAppearance::Statusbar:
     case StyleAppearance::Statusbarpanel:
     case StyleAppearance::Resizerpanel:
     case StyleAppearance::Resizer:
       return Some(eUXStatus);
     case StyleAppearance::Menulist:
     case StyleAppearance::MenulistButton:
+    case StyleAppearance::MozMenulistButton:
       return Some(eUXCombobox);
     case StyleAppearance::Treeheadercell:
     case StyleAppearance::Treeheadersortarrow:
       return Some(eUXHeader);
     case StyleAppearance::Listbox:
     case StyleAppearance::Listitem:
     case StyleAppearance::Treeview:
     case StyleAppearance::Treetwistyopen:
@@ -1292,17 +1293,18 @@ nsNativeThemeWin::GetThemePartAndState(n
         else if (eventState.HasState(NS_EVENT_STATE_HOVER))
           aState = TS_HOVER;
         else
           aState = TS_NORMAL;
       }
 
       return NS_OK;
     }
-    case StyleAppearance::MenulistButton: {
+    case StyleAppearance::MenulistButton:
+    case StyleAppearance::MozMenulistButton: {
       bool isHTML = IsHTMLContent(aFrame);
       nsIFrame* parentFrame = aFrame->GetParent();
       bool isMenulist = !isHTML && parentFrame->IsMenuFrame();
       bool isOpen = false;
 
       // HTML select and XUL menulist dropdown buttons get state from the parent.
       if (isHTML || isMenulist)
         aFrame = parentFrame;
@@ -1823,17 +1825,18 @@ RENDER_AGAIN:
       renderRect.left = glyphSize.cx;
       renderRect.right = renderRect.left + glyphSize.cx;
     }
     DrawThemeBGRTLAware(theme, hdc, part, state, &renderRect, &clipRect,
                         IsFrameRTL(aFrame));
   }
   // The following widgets need to be RTL-aware
   else if (aWidgetType == StyleAppearance::Resizer ||
-           aWidgetType == StyleAppearance::MenulistButton)
+           aWidgetType == StyleAppearance::MenulistButton ||
+           aWidgetType == StyleAppearance::MozMenulistButton)
   {
     DrawThemeBGRTLAware(theme, hdc, part, state,
                         &widgetRect, &clipRect, IsFrameRTL(aFrame));
   }
   else if (aWidgetType == StyleAppearance::NumberInput ||
            aWidgetType == StyleAppearance::Textfield ||
            aWidgetType == StyleAppearance::TextfieldMultiline) {
     DrawThemeBackground(theme, hdc, part, state, &widgetRect, &clipRect);
@@ -2253,16 +2256,18 @@ nsNativeThemeWin::GetWidgetOverflow(nsDe
                                     nsRect* aOverflowRect)
 {
   /* This is disabled for now, because it causes invalidation problems --
    * see bug 420381.  The effect of not updating the overflow area is that
    * for dropdown buttons in content areas, there is a 1px border on 3 sides
    * where, if invalidated, the dropdown control probably won't be repainted.
    * This is fairly minor, as by default there is nothing in that area, and
    * a border only shows up if the widget is being hovered.
+   *
+   * TODO(jwatt): Figure out what do to about StyleAppearance::MozMenulistButton too.
    */
 #if 0
   /* We explicitly draw dropdown buttons in HTML content 1px bigger up, right,
    * and bottom so that they overlap the dropdown's border like they're
    * supposed to.
    */
   if (aWidgetType == StyleAppearance::MenulistButton &&
       IsHTMLContent(aFrame) &&
@@ -2346,17 +2351,18 @@ nsNativeThemeWin::GetMinimumWidgetSize(n
     case StyleAppearance::ScrollbarthumbVertical:
     case StyleAppearance::ScrollbarthumbHorizontal:
     case StyleAppearance::ScrollbarbuttonUp:
     case StyleAppearance::ScrollbarbuttonDown:
     case StyleAppearance::ScrollbarbuttonLeft:
     case StyleAppearance::ScrollbarbuttonRight:
     case StyleAppearance::ScrollbarHorizontal:
     case StyleAppearance::ScrollbarVertical:
-    case StyleAppearance::MenulistButton: {
+    case StyleAppearance::MenulistButton:
+    case StyleAppearance::MozMenulistButton: {
       rv = ClassicGetMinimumWidgetSize(aFrame, aWidgetType, aResult, aIsOverridable);
       ScaleForFrameDPI(aResult, aFrame);
       return rv;
     }
     case StyleAppearance::Menuitem:
     case StyleAppearance::Checkmenuitem:
     case StyleAppearance::Radiomenuitem:
       if(!IsTopLevelMenu(aFrame))
@@ -2561,17 +2567,19 @@ nsNativeThemeWin::WidgetStateChanged(nsI
       aWidgetType == StyleAppearance::MozWindowButtonMaximize ||
       aWidgetType == StyleAppearance::MozWindowButtonRestore) {
     *aShouldRepaint = true;
     return NS_OK;
   }
 
   // We need to repaint the dropdown arrow in vista HTML combobox controls when
   // the control is closed to get rid of the hover effect.
-  if ((aWidgetType == StyleAppearance::Menulist || aWidgetType == StyleAppearance::MenulistButton) &&
+  if ((aWidgetType == StyleAppearance::Menulist ||
+       aWidgetType == StyleAppearance::MenulistButton ||
+       aWidgetType == StyleAppearance::MozMenulistButton) &&
       IsHTMLContent(aFrame))
   {
     *aShouldRepaint = true;
     return NS_OK;
   }
 
   // XXXdwh Not sure what can really be done here.  Can at least guess for
   // specific widgets that they're highly unlikely to have certain states.
@@ -2638,16 +2646,17 @@ nsNativeThemeWin::ThemeSupportsWidget(ns
   return false;
 }
 
 bool 
 nsNativeThemeWin::WidgetIsContainer(WidgetType aWidgetType)
 {
   // XXXdwh At some point flesh all of this out.
   if (aWidgetType == StyleAppearance::MenulistButton || 
+      aWidgetType == StyleAppearance::MozMenulistButton || 
       aWidgetType == StyleAppearance::Radio ||
       aWidgetType == StyleAppearance::Checkbox)
     return false;
   return true;
 }
 
 bool
 nsNativeThemeWin::ThemeDrawsFocusForWidget(WidgetType aWidgetType)
@@ -2783,16 +2792,17 @@ nsNativeThemeWin::ClassicThemeSupportsWi
     case StyleAppearance::ScrollbarHorizontal:
     case StyleAppearance::ScrollbarNonDisappearing:
     case StyleAppearance::Scrollcorner:
     case StyleAppearance::ScaleHorizontal:
     case StyleAppearance::ScaleVertical:
     case StyleAppearance::ScalethumbHorizontal:
     case StyleAppearance::ScalethumbVertical:
     case StyleAppearance::MenulistButton:
+    case StyleAppearance::MozMenulistButton:
     case StyleAppearance::InnerSpinButton:
     case StyleAppearance::SpinnerUpbutton:
     case StyleAppearance::SpinnerDownbutton:
     case StyleAppearance::Listbox:
     case StyleAppearance::Treeview:
     case StyleAppearance::MenulistTextfield:
     case StyleAppearance::Menulist:
     case StyleAppearance::Tooltip:
@@ -2993,16 +3003,17 @@ nsNativeThemeWin::ClassicGetMinimumWidge
       *aIsOverridable = false;
       break;
     case StyleAppearance::ScalethumbVertical:
       (*aResult).width = 20;
       (*aResult).height = 12;
       *aIsOverridable = false;
       break;
     case StyleAppearance::MenulistButton:
+    case StyleAppearance::MozMenulistButton:
       (*aResult).width = ::GetSystemMetrics(SM_CXVSCROLL);
       break;
     case StyleAppearance::Menulist:
     case StyleAppearance::Button:
     case StyleAppearance::Groupbox:
     case StyleAppearance::Listbox:
     case StyleAppearance::Treeview:
     case StyleAppearance::NumberInput:
@@ -3272,17 +3283,18 @@ nsresult nsNativeThemeWin::ClassicGetThe
     case StyleAppearance::Tab:
     case StyleAppearance::Tabpanel:
     case StyleAppearance::Tabpanels:
     case StyleAppearance::Menubar:
     case StyleAppearance::Menupopup:
     case StyleAppearance::Groupbox:
       // these don't use DrawFrameControl
       return NS_OK;
-    case StyleAppearance::MenulistButton: {
+    case StyleAppearance::MenulistButton:
+    case StyleAppearance::MozMenulistButton: {
 
       aPart = DFC_SCROLL;
       aState = DFCS_SCROLLCOMBOBOX;
 
       nsIFrame* parentFrame = aFrame->GetParent();
       bool isHTML = IsHTMLContent(aFrame);
       bool isMenulist = !isHTML && parentFrame->IsMenuFrame();
       bool isOpen = false;
@@ -3657,16 +3669,17 @@ RENDER_AGAIN:
     case StyleAppearance::ScrollbarbuttonUp:
     case StyleAppearance::ScrollbarbuttonDown:
     case StyleAppearance::ScrollbarbuttonLeft:
     case StyleAppearance::ScrollbarbuttonRight:
     case StyleAppearance::InnerSpinButton:
     case StyleAppearance::SpinnerUpbutton:
     case StyleAppearance::SpinnerDownbutton:
     case StyleAppearance::MenulistButton:
+    case StyleAppearance::MozMenulistButton:
     case StyleAppearance::Resizer: {
       int32_t oldTA;
       // setup DC to make DrawFrameControl draw correctly
       oldTA = ::SetTextAlign(hdc, TA_TOP | TA_LEFT | TA_NOUPDATECP);
       ::DrawFrameControl(hdc, &widgetRect, part, state);
       ::SetTextAlign(hdc, oldTA);
       break;
     }
@@ -4088,16 +4101,17 @@ nsNativeThemeWin::GetWidgetNativeDrawing
     case StyleAppearance::Menupopup:
     case StyleAppearance::Menuitem:
       break;
 
     // the dropdown button /almost/ renders correctly with scaling,
     // except that the graphic in the dropdown button (the downward arrow)
     // doesn't get scaled up.
     case StyleAppearance::MenulistButton:
+    case StyleAppearance::MozMenulistButton:
     // these are definitely no; they're all graphics that don't get scaled up
     case StyleAppearance::Checkbox:
     case StyleAppearance::Radio:
     case StyleAppearance::Groupbox:
     case StyleAppearance::Checkmenuitem:
     case StyleAppearance::Radiomenuitem:
     case StyleAppearance::Menucheckbox:
     case StyleAppearance::Menuradio: