Bug 333910 - nsITheme for menu/scrollbox arrows, r=mstange,gijs
authorstefanh@inbox.com
Mon, 08 Sep 2014 10:45:00 +0100
changeset 231837 af792af2f5c7f64fdc60a50f157cb610702fe933
parent 231686 1ee2c06d271fd585845af22bcb41f4f97a09da34
child 231838 e54edf3b633c08bbb908e5c4823f4f5fe50e22d0
push id4187
push userbhearsum@mozilla.com
push dateFri, 28 Nov 2014 15:29:12 +0000
treeherdermozilla-beta@f23cc6a30c11 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmstange, gijs
bugs333910
milestone35.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 333910 - nsITheme for menu/scrollbox arrows, r=mstange,gijs
browser/themes/osx/customizableui/panelUIOverlay.css
toolkit/themes/osx/global/global.css
toolkit/themes/osx/global/jar.mn
toolkit/themes/osx/global/menu.css
toolkit/themes/osx/global/menu/menu-arrow.png
toolkit/themes/osx/global/menu/menu-arrow@2x.png
toolkit/themes/osx/global/scrollbox.css
widget/cocoa/nsNativeThemeCocoa.h
widget/cocoa/nsNativeThemeCocoa.mm
--- a/browser/themes/osx/customizableui/panelUIOverlay.css
+++ b/browser/themes/osx/customizableui/panelUIOverlay.css
@@ -134,25 +134,25 @@ menu.subviewbutton,
 menuitem.subviewbutton:not(.panel-subview-footer) {
   padding-top: 2px;
   padding-bottom: 2px;
 }
 
 /* Override OSX-specific toolkit styles for the bookmarks panel */
 menu.subviewbutton > .menu-right {
   -moz-margin-end: 0;
-}
-menu.subviewbutton > .menu-right > image {
-  -moz-image-region: rect(0, 9px, 10px, 0);
+  -moz-appearance: none;
 }
 
-@media (min-resolution: 2dppx) {
-  menu.subviewbutton > .menu-right > image {
-    -moz-image-region: rect(0, 18px, 20px, 0);
-  }
+menu.subviewbutton > .menu-right > image {
+ /* We don't want the arrow to highlight when the .subviewbutton is hovered,
+  * so we set the -moz-appearance rule on the image
+  * (which doesn't inherit the _moz-menuactive attribute) instead.
+  */
+  -moz-appearance: menuarrow;
 }
 
 .widget-overflow-list .toolbarbutton-1 > .toolbarbutton-menubutton-dropmarker {
   -moz-margin-start: 4px;
 }
 
 .PanelUI-subView menuseparator,
 .cui-widget-panelview menuseparator {
--- a/toolkit/themes/osx/global/global.css
+++ b/toolkit/themes/osx/global/global.css
@@ -308,36 +308,47 @@ notification > button > .button-box > .b
   background-position: right bottom;
 }
 
 /* autorepeatbuttons in menus */
 
 .popup-internal-box > autorepeatbutton {
   height: 15px;
   position: relative;
+  list-style-image: none;
   /* Here we're using a little magic.
    * The arrow button is supposed to overlay the scrollbox, blocking
    * everything under it from reaching the screen. However, the menu background
    * is slightly transparent, so how can we block something completely without
    * messing up the transparency? It's easy: The native theming of the
    * "menuitem" appearance uses CGContextClearRect before drawing, which
    * clears everything under it.
    * Without help from native theming this effect wouldn't be achievable.
    */
   -moz-appearance: menuitem;
 }
 
 .popup-internal-box > .autorepeatbutton-up {
+  padding-top: 1px; /* 4px padding-top from the .popup-internal-box. */
   margin-bottom: -15px;
 }
 
+.popup-internal-box > .autorepeatbutton-up > .autorepeatbutton-icon {
+  -moz-appearance: button-arrow-up;
+}
+
 .popup-internal-box > .autorepeatbutton-down {
+  padding-top: 5px;
   margin-top: -15px;
 }
 
+.popup-internal-box > .autorepeatbutton-down > .autorepeatbutton-icon {
+  -moz-appearance: button-arrow-down;
+}
+
 .popup-internal-box > autorepeatbutton[disabled="true"] {
   visibility: collapse;
 }
 
 /* :::::: Close button icons ::::: */
 
 .close-icon {
   list-style-image: url("chrome://global/skin/icons/close.png");
--- a/toolkit/themes/osx/global/jar.mn
+++ b/toolkit/themes/osx/global/jar.mn
@@ -176,18 +176,16 @@ toolkit.jar:
   skin/classic/global/media/throbber.png                             (media/throbber.png)
   skin/classic/global/media/stalled.png                              (media/stalled.png)
   skin/classic/global/media/volume-empty.png                         (media/volume-empty.png)
   skin/classic/global/media/volume-empty@2x.png                      (media/volume-empty@2x.png)
   skin/classic/global/media/volume-full.png                          (media/volume-full.png)
   skin/classic/global/media/volume-full@2x.png                       (media/volume-full@2x.png)
   skin/classic/global/media/clicktoplay-bgtexture.png                (media/clicktoplay-bgtexture.png)
   skin/classic/global/media/videoClickToPlayButton.svg               (media/videoClickToPlayButton.svg)
-  skin/classic/global/menu/menu-arrow.png                            (menu/menu-arrow.png)
-  skin/classic/global/menu/menu-arrow@2x.png                         (menu/menu-arrow@2x.png)
   skin/classic/global/menu/shared-menu-check.png                     (../../shared/menu-check.png)
   skin/classic/global/menu/shared-menu-check@2x.png                  (../../shared/menu-check@2x.png)
 * skin/classic/global/in-content/common.css                          (in-content/common.css)
   skin/classic/global/in-content/check.png                           (../../shared/in-content/check.png)
   skin/classic/global/in-content/check@2x.png                        (../../shared/in-content/check@2x.png)
   skin/classic/global/in-content/dropdown.png                        (../../shared/in-content/dropdown.png)
   skin/classic/global/in-content/dropdown@2x.png                     (../../shared/in-content/dropdown@2x.png)
   skin/classic/global/in-content/dropdown-disabled.png               (../../shared/in-content/dropdown-disabled.png)
--- a/toolkit/themes/osx/global/menu.css
+++ b/toolkit/themes/osx/global/menu.css
@@ -71,57 +71,32 @@ menuitem[src] > .menu-iconic-left > .men
   width: 16px;
 }
 
 /* ..... menu arrow box ..... */
 
 .menu-right,
 .menu-accel-container {
   -moz-margin-start: 21px;
+  -moz-margin-end: -9px;
   -moz-box-pack: end;
 }
 
-.menu-accel-container {
-  -moz-margin-end: -9px;
+/* The native menuarrow we use is 9px wide on 10.7+ and 8px wide on 10.6,
+ * so it needs to be 'pulled in' one pixel more by the negative margin in
+ * order to align properly: */
+@media not all and (-moz-mac-lion-theme) {
+  .menu-right {
+    -moz-margin-end: -10px;
+  }
 }
 
 .menu-right {
-  -moz-margin-end: -10px;
-  width: 9px;
-  list-style-image: url("chrome://global/skin/menu/menu-arrow.png");
-  -moz-image-region: rect(0, 9px, 10px, 0);
-}
-
-.menu-right[_moz-menuactive="true"]:not([disabled="true"]) {
-  -moz-image-region: rect(0, 18px, 10px, 9px);
-}
-
-.menu-right[disabled="true"] {
-  -moz-image-region: rect(0, 27px, 10px, 18px);
-}
-
-.menu-right:-moz-locale-dir(rtl) {
-  transform: scaleX(-1);
-}
-
-@media (min-resolution: 2dppx) {
-  .menu-right > image {
-    list-style-image: url("chrome://global/skin/menu/menu-arrow@2x.png");
-    -moz-image-region: rect(0, 18px, 20px, 0);
-    width: 9px;
-    height: 10px;
-  }
-
-  .menu-right[_moz-menuactive="true"]:not([disabled="true"]) > image {
-    -moz-image-region: rect(0, 36px, 20px, 18px);
-  }
-
-  .menu-right[disabled="true"] > image {
-    -moz-image-region: rect(0, 54px, 20px, 36px);
-  }
+  list-style-image: none;
+  -moz-appearance: menuarrow;
 }
 
 /* ::::: menu/menuitems in menubar ::::: */
 
 menubar > menu {
   -moz-appearance: none;
   padding: 2px 5px 2px 7px;
   margin: 1px 0;
deleted file mode 100644
index b80f2e37d826847c57d34da10c955df3c2b88964..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
index 98eee11ba779834f2a2f302fbf9407686f01cb3e..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
--- a/toolkit/themes/osx/global/scrollbox.css
+++ b/toolkit/themes/osx/global/scrollbox.css
@@ -26,71 +26,37 @@
  
 .autorepeatbutton-down[orient="horizontal"][disabled="true"],
 .scrollbutton-down[orient="horizontal"][disabled="true"] {
   list-style-image: url("chrome://global/skin/arrow/arrow-rit-dis.gif");
   -moz-image-region: auto; /* cut off inheritance */
 }
 
 /* Vertical enabled */
-.autorepeatbutton-up:not([orient="horizontal"]) {
-  padding-bottom: 5px;
-}
-
-.autorepeatbutton-down:not([orient="horizontal"]) {
-  padding-top: 5px;
-}
-
-.autorepeatbutton-up:not([orient="horizontal"]) > .autorepeatbutton-icon {
-  transform: rotate(-90deg);
-}
-
-.autorepeatbutton-down:not([orient="horizontal"]) > .autorepeatbutton-icon {
-  transform: rotate(90deg);
-}
-
+.autorepeatbutton-up:not([orient="horizontal"]),
 .scrollbutton-up {
   list-style-image: url("chrome://global/skin/arrow/arrow-up-sharp.gif");
   -moz-image-region: auto; /* cut off inheritance */
 }
 
+.autorepeatbutton-down:not([orient="horizontal"]),
 .scrollbutton-down {
   list-style-image: url("chrome://global/skin/arrow/arrow-dn-sharp.gif");
   -moz-image-region: auto; /* cut off inheritance */
 }
 
 /* Vertical disabled */
 .autorepeatbutton-up[disabled="true"]:not([orient="horizontal"]),
-.autorepeatbutton-down[disabled="true"]:not([orient="horizontal"]) {
-  -moz-image-region: rect(0, 27px, 10px, 18px);
-}
-
 .scrollbutton-up[disabled="true"] {
   list-style-image: url("chrome://global/skin/arrow/arrow-up-dis.gif");
   -moz-image-region: auto; /* cut off inheritance */
 }
 
+.autorepeatbutton-down[disabled="true"]:not([orient="horizontal"]),
 .scrollbutton-down[disabled="true"] {
   list-style-image: url("chrome://global/skin/arrow/arrow-dn-dis.gif");
   -moz-image-region: auto; /* cut off inheritance */
 }
 
 .scrollbutton-up > .toolbarbutton-text,
 .scrollbutton-down > .toolbarbutton-text {
   display: none;
 }
-
-autorepeatbutton {
-  list-style-image: url("chrome://global/skin/menu/menu-arrow.png");
-  -moz-image-region: rect(0, 9px, 10px, 0);
-  -moz-box-align: center;
-  -moz-box-pack: center;
-  padding: 1px;
-}
-
-@media (min-resolution: 2dppx) {
-  autorepeatbutton > .autorepeatbutton-icon {
-    list-style-image: url("chrome://global/skin/menu/menu-arrow@2x.png");
-    -moz-image-region: rect(0, 18px, 20px, 0);
-    width: 9px;
-    height: 10px;
-  }
-}
--- a/widget/cocoa/nsNativeThemeCocoa.h
+++ b/widget/cocoa/nsNativeThemeCocoa.h
@@ -99,17 +99,18 @@ protected:
                            mozilla::EventStates inState, nsIFrame* aFrame);
   void DrawSearchField(CGContextRef cgContext, const HIRect& inBoxRect,
                        nsIFrame* aFrame, mozilla::EventStates inState);
   void DrawPushButton(CGContextRef cgContext, const HIRect& inBoxRect,
                       mozilla::EventStates inState, uint8_t aWidgetType,
                       nsIFrame* aFrame);
   void DrawMenuIcon(CGContextRef cgContext, const CGRect& aRect,
                     mozilla::EventStates inState, nsIFrame* aFrame,
-                    const NSSize& aIconSize, const NSString* aImageName);
+                    const NSSize& aIconSize, const NSString* aImageName,
+                    bool aCenterHorizontally);
   void DrawButton(CGContextRef context, ThemeButtonKind inKind,
                   const HIRect& inBoxRect, bool inIsDefault, 
                   ThemeButtonValue inValue, ThemeButtonAdornment inAdornment,
                   mozilla::EventStates inState, nsIFrame* aFrame);
   void DrawFocusOutline(CGContextRef cgContext, const HIRect& inBoxRect,
                         mozilla::EventStates inState, uint8_t aWidgetType,
                         nsIFrame* aFrame);
   void DrawDropdown(CGContextRef context, const HIRect& inBoxRect,
--- a/widget/cocoa/nsNativeThemeCocoa.mm
+++ b/widget/cocoa/nsNativeThemeCocoa.mm
@@ -1032,33 +1032,42 @@ nsNativeThemeCocoa::DrawSearchField(CGCo
                        IsFrameRTL(aFrame));
 
   [cell setContext:nullptr];
 
   NS_OBJC_END_TRY_ABORT_BLOCK;
 }
 
 static const NSSize kCheckmarkSize = NSMakeSize(11, 11);
+static const NSSize kMenuarrowSize = nsCocoaFeatures::OnLionOrLater() ?
+                                     NSMakeSize(9, 10) : NSMakeSize(8, 10);
+static const NSSize kMenuScrollArrowSize = NSMakeSize(10, 8);
 static const NSString* kCheckmarkImage = @"image.MenuOnState";
+static const NSString* kMenuarrowRightImage = @"image.MenuSubmenu";
+static const NSString* kMenuarrowLeftImage = @"image.MenuSubmenuLeft";
+static const NSString* kMenuDownScrollArrowImage = @"image.MenuScrollDown";
+static const NSString* kMenuUpScrollArrowImage = @"image.MenuScrollUp";
 static const CGFloat kMenuIconIndent = 6.0f;
 
 void
 nsNativeThemeCocoa::DrawMenuIcon(CGContextRef cgContext, const CGRect& aRect,
                                  EventStates inState, nsIFrame* aFrame,
-                                 const NSSize& aIconSize, const NSString* aImageName)
+                                 const NSSize& aIconSize, const NSString* aImageName,
+                                 bool aCenterHorizontally)
 {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
 
   // Adjust size and position of our drawRect.
   CGFloat paddingX = std::max(CGFloat(0.0), aRect.size.width - aIconSize.width);
   CGFloat paddingY = std::max(CGFloat(0.0), aRect.size.height - aIconSize.height);
   CGFloat paddingStartX = std::min(paddingX, kMenuIconIndent);
   CGFloat paddingEndX = std::max(CGFloat(0.0), paddingX - kMenuIconIndent);
   CGRect drawRect = CGRectMake(
-    aRect.origin.x + (IsFrameRTL(aFrame) ? paddingEndX : paddingStartX),
+    aRect.origin.x + (aCenterHorizontally ? ceil(paddingX / 2) :
+                      IsFrameRTL(aFrame) ? paddingEndX : paddingStartX),
     aRect.origin.y + ceil(paddingY / 2),
     aIconSize.width, aIconSize.height);
 
   BOOL isDisabled = IsDisabled(aFrame, inState);
   BOOL isActive = CheckBooleanAttr(aFrame, nsGkAtoms::menuactive);
 
   // On 10.6 and at least on 10.7.0, Apple doesn’t seem to have implemented all
   // keys and values used on 10.7.5 and later. We can however draw menu icons
@@ -2341,21 +2350,28 @@ nsNativeThemeCocoa::DrawWidgetBackground
       
       // The rounded corners draw outside the frame.
       CGRect deflatedRect = CGRectMake(macRect.origin.x, macRect.origin.y + 4,
                                        macRect.size.width, macRect.size.height - 8);
       HIThemeDrawMenuBackground(&deflatedRect, &mdi, cgContext, HITHEME_ORIENTATION);
     }
       break;
 
+    case NS_THEME_MENUARROW: {
+      bool isRTL = IsFrameRTL(aFrame);
+      DrawMenuIcon(cgContext, macRect, eventState, aFrame, kMenuarrowSize,
+                   isRTL ? kMenuarrowLeftImage : kMenuarrowRightImage, true);
+    }
+      break;
+
     case NS_THEME_MENUITEM:
     case NS_THEME_CHECKMENUITEM: {
       SurfaceFormat format  = thebesCtx->GetDrawTarget()->GetFormat();
       bool isTransparent = (format == SurfaceFormat::R8G8B8A8) ||
-                      (format == SurfaceFormat::B8G8R8A8);
+                           (format == SurfaceFormat::B8G8R8A8);
       if (isTransparent) {
         // Clear the background to get correct transparency.
         CGContextClearRect(cgContext, macRect);
       }
 
       // maybe use kThemeMenuItemHierBackground or PopUpBackground instead of just Plain?
       HIThemeMenuItemDrawInfo drawInfo;
       memset(&drawInfo, 0, sizeof(drawInfo));
@@ -2367,17 +2383,17 @@ nsNativeThemeCocoa::DrawWidgetBackground
                            static_cast<ThemeMenuState>(kThemeMenuSelected) :
                            static_cast<ThemeMenuState>(kThemeMenuActive));
 
       // XXX pass in the menu rect instead of always using the item rect
       HIRect ignored;
       HIThemeDrawMenuItem(&macRect, &macRect, &drawInfo, cgContext, HITHEME_ORIENTATION, &ignored);
 
       if (aWidgetType == NS_THEME_CHECKMENUITEM) {
-        DrawMenuIcon(cgContext, macRect, eventState, aFrame, kCheckmarkSize, kCheckmarkImage);
+        DrawMenuIcon(cgContext, macRect, eventState, aFrame, kCheckmarkSize, kCheckmarkImage, false);
       }
     }
       break;
 
     case NS_THEME_MENUSEPARATOR: {
       ThemeMenuState menuState;
       if (IsDisabled(aFrame, eventState)) {
         menuState = kThemeMenuDisabled;
@@ -2387,16 +2403,23 @@ nsNativeThemeCocoa::DrawWidgetBackground
                     kThemeMenuSelected : kThemeMenuActive;
       }
 
       HIThemeMenuItemDrawInfo midi = { 0, kThemeMenuItemPlain, menuState };
       HIThemeDrawMenuSeparator(&macRect, &macRect, &midi, cgContext, HITHEME_ORIENTATION);
     }
       break;
 
+    case NS_THEME_BUTTON_ARROW_UP:
+    case NS_THEME_BUTTON_ARROW_DOWN:
+      DrawMenuIcon(cgContext, macRect, eventState, aFrame, kMenuScrollArrowSize,
+                   aWidgetType == NS_THEME_BUTTON_ARROW_UP ?
+                   kMenuUpScrollArrowImage : kMenuDownScrollArrowImage, true);
+      break;
+
     case NS_THEME_TOOLTIP:
       if (nsCocoaFeatures::OnYosemiteOrLater()) {
         CGContextSetRGBFillColor(cgContext, 0.945, 0.942, 0.945, 0.950);
       } else {
         CGContextSetRGBFillColor(cgContext, 0.996, 1.000, 0.792, 0.950);
       }
       CGContextFillRect(cgContext, macRect);
       break;
@@ -3085,16 +3108,31 @@ nsNativeThemeCocoa::GetMinimumWidgetSize
   switch (aWidgetType) {
     case NS_THEME_BUTTON:
     {
       aResult->SizeTo(pushButtonSettings.minimumSizes[miniControlSize].width,
                       pushButtonSettings.naturalSizes[miniControlSize].height);
       break;
     }
 
+    case NS_THEME_BUTTON_ARROW_UP:
+    case NS_THEME_BUTTON_ARROW_DOWN:
+    {
+      aResult->SizeTo(kMenuScrollArrowSize.width, kMenuScrollArrowSize.height);
+      *aIsOverridable = false;
+      break;
+    }
+
+    case NS_THEME_MENUARROW:
+    {
+      aResult->SizeTo(kMenuarrowSize.width, kMenuarrowSize.height);
+      *aIsOverridable = false;
+      break;
+    }
+
     case NS_THEME_MOZ_MAC_HELP_BUTTON:
     {
       aResult->SizeTo(kHelpButtonSize.width, kHelpButtonSize.height);
       *aIsOverridable = false;
       break;
     }
 
     case NS_THEME_TOOLBAR_BUTTON:
@@ -3466,28 +3504,31 @@ nsNativeThemeCocoa::ThemeSupportsWidget(
     case NS_THEME_LISTBOX:
 
     case NS_THEME_DIALOG:
     case NS_THEME_WINDOW:
     case NS_THEME_WINDOW_BUTTON_BOX:
     case NS_THEME_WINDOW_TITLEBAR:
     case NS_THEME_CHECKMENUITEM:
     case NS_THEME_MENUPOPUP:
+    case NS_THEME_MENUARROW:
     case NS_THEME_MENUITEM:
     case NS_THEME_MENUSEPARATOR:
     case NS_THEME_MOZ_MAC_FULLSCREEN_BUTTON:
     case NS_THEME_TOOLTIP:
     
     case NS_THEME_CHECKBOX:
     case NS_THEME_CHECKBOX_CONTAINER:
     case NS_THEME_RADIO:
     case NS_THEME_RADIO_CONTAINER:
     case NS_THEME_GROUPBOX:
     case NS_THEME_MOZ_MAC_HELP_BUTTON:
     case NS_THEME_BUTTON:
+    case NS_THEME_BUTTON_ARROW_UP:
+    case NS_THEME_BUTTON_ARROW_DOWN:
     case NS_THEME_BUTTON_BEVEL:
     case NS_THEME_TOOLBAR_BUTTON:
     case NS_THEME_SPINNER:
     case NS_THEME_SPINNER_UP_BUTTON:
     case NS_THEME_SPINNER_DOWN_BUTTON:
     case NS_THEME_TOOLBAR:
     case NS_THEME_MOZ_MAC_UNIFIED_TOOLBAR:
     case NS_THEME_STATUSBAR:
@@ -3611,18 +3652,21 @@ nsNativeThemeCocoa::ThemeNeedsComboboxDr
 
 bool
 nsNativeThemeCocoa::WidgetAppearanceDependsOnWindowFocus(uint8_t aWidgetType)
 {
   switch (aWidgetType) {
     case NS_THEME_DIALOG:
     case NS_THEME_GROUPBOX:
     case NS_THEME_TAB_PANELS:
+    case NS_THEME_BUTTON_ARROW_UP:
+    case NS_THEME_BUTTON_ARROW_DOWN:
     case NS_THEME_CHECKMENUITEM:
     case NS_THEME_MENUPOPUP:
+    case NS_THEME_MENUARROW:
     case NS_THEME_MENUITEM:
     case NS_THEME_MENUSEPARATOR:
     case NS_THEME_TOOLTIP:
     case NS_THEME_SPINNER:
     case NS_THEME_SPINNER_UP_BUTTON:
     case NS_THEME_SPINNER_DOWN_BUTTON:
     case NS_THEME_TOOLBAR_SEPARATOR:
     case NS_THEME_TOOLBOX: