Bug 656990 - Ensure compatibility with OS X 10.7's arrowless scrollbar. Original patch by Steven Michaud <smichaud@pobox.com>, r=mstange; backported by smorgan and me. a=smorgan,me for Camino 2.1 series. CAMINO_2_1_1_MINIBRANCH CAMINO_2_1_1_RELEASE
authorSmokey Ardisson <alqahira@ardisson.org>
Wed, 26 Oct 2011 23:39:55 -0400
branchCAMINO_2_1_1_MINIBRANCH
changeset 35270 16fcae991ddda514e2553a404e768e7b66b1576b
parent 35269 d188be78b435df7ec65258f065f02f405e1a1e67
child 35271 856aceaa37785f93a9b4925f6e825991d6b76d07
push id2025
push useralqahira@ardisson.org
push dateFri, 17 Feb 2012 21:54:31 +0000
reviewersmstange, backported, smorgan, me
bugs656990
milestone1.9.2.27
Bug 656990 - Ensure compatibility with OS X 10.7's arrowless scrollbar. Original patch by Steven Michaud <smichaud@pobox.com>, r=mstange; backported by smorgan and me. a=smorgan,me for Camino 2.1 series.
widget/public/nsILookAndFeel.h
widget/src/cocoa/nsLookAndFeel.mm
widget/src/cocoa/nsNativeThemeCocoa.mm
widget/src/cocoa/nsToolkit.h
widget/src/cocoa/nsToolkit.mm
--- a/widget/public/nsILookAndFeel.h
+++ b/widget/public/nsILookAndFeel.h
@@ -39,20 +39,20 @@
 #define __nsILookAndFeel
 #include "nsISupports.h"
 #include "nsColor.h"
 
   // for |#ifdef NS_DEBUG|
 struct nsSize;
 
 
-// {3fd2930f-1040-4d08-b638-0b3f134e6b6f}
+// {e13adf95-577b-4c66-a713-c42cc7df6da5}
 #define NS_ILOOKANDFEEL_IID \
-{ 0xc23ca876, 0x6ecf, 0x49c6, \
-    { 0xb2, 0xb4, 0x5b, 0xe5, 0x16, 0xb5, 0x0e, 0x28 } }
+{ 0xe13adf95, 0x577b, 0x4c66, \
+    { 0xa7, 0x13, 0xc4, 0x2c, 0xc7, 0xdf, 0x6d, 0xa5 } }
 
 class nsILookAndFeel: public nsISupports {
 public:
     NS_DECLARE_STATIC_IID_ACCESSOR(NS_ILOOKANDFEEL_IID)
 
   // When modifying this list, also modify nsXPLookAndFeel::sColorPrefs
   // in widget/src/xpwidgts/nsXPLookAndFeel.cpp.
   typedef enum {
@@ -325,16 +325,17 @@ public:
 
     /**
      * If this metric != 0, show icons in menus.
      */
     eMetric_ImagesInMenus
   } nsMetricID;
 
   enum {
+    eMetric_ScrollArrowNone = 0,
     eMetric_ScrollArrowStartBackward = 0x1000,
     eMetric_ScrollArrowStartForward = 0x0100,
     eMetric_ScrollArrowEndBackward = 0x0010,
     eMetric_ScrollArrowEndForward = 0x0001,
     eMetric_ScrollArrowStyleSingle =                      // single arrow at each end
       eMetric_ScrollArrowStartBackward|eMetric_ScrollArrowEndForward, 
     eMetric_ScrollArrowStyleBothAtBottom =                // both arrows at bottom/right, none at top/left
       eMetric_ScrollArrowEndBackward|eMetric_ScrollArrowEndForward,
--- a/widget/src/cocoa/nsLookAndFeel.mm
+++ b/widget/src/cocoa/nsLookAndFeel.mm
@@ -549,38 +549,43 @@ NS_IMETHODIMP nsLookAndFeel::GetMetric(c
     case eMetric_SkipNavigatingDisabledMenuItem:
       aMetric = 1;
       break;
     case eMetric_DragThresholdX:
     case eMetric_DragThresholdY:
       aMetric = 4;
       break;
     case eMetric_ScrollArrowStyle:
-      ThemeScrollBarArrowStyle arrowStyle;
-      ::GetThemeScrollBarArrowStyle ( &arrowStyle );
-      switch (arrowStyle) {
-        case kThemeScrollBarArrowsSingle:
-          aMetric = eMetric_ScrollArrowStyleSingle;
-          break;
-        // These constants aren't selectable in System Preferences like the other two (don't know why) 
-        // `defaults write -g AppleScrollBarVariant DoubleBoth` to enable it.
-        case kThemeScrollBarArrowsBoth:
-          aMetric = eMetric_ScrollArrowStyleBothAtEachEnd;
-          break;
-        // `defaults write -g AppleScrollBarVariant DoubleMin` to enable it.
-        case kThemeScrollBarArrowsUpperLeft:
-          aMetric = eMetric_ScrollArrowStyleBothAtTop;
-          break;
-        default:
-          NS_WARNING("Not handling all possible ThemeScrollBarArrowStyle values");
-          // fall through so we default to BothAtBottom
-        case kThemeScrollBarArrowsLowerRight:
-          aMetric = eMetric_ScrollArrowStyleBothAtBottom;
+      if (nsToolkit::OnLionOrLater()) {
+        // OS X Lion's scrollbars have no arrows
+        aMetric = eMetric_ScrollArrowNone;
+      } else {
+        ThemeScrollBarArrowStyle arrowStyle;
+        ::GetThemeScrollBarArrowStyle ( &arrowStyle );
+        switch (arrowStyle) {
+          case kThemeScrollBarArrowsSingle:
+            aMetric = eMetric_ScrollArrowStyleSingle;
+            break;
+          // These constants aren't selectable in System Preferences like the other two (don't know why) 
+          // `defaults write -g AppleScrollBarVariant DoubleBoth` to enable it.
+          case kThemeScrollBarArrowsBoth:
+            aMetric = eMetric_ScrollArrowStyleBothAtEachEnd;
+            break;
+          // `defaults write -g AppleScrollBarVariant DoubleMin` to enable it.
+          case kThemeScrollBarArrowsUpperLeft:
+            aMetric = eMetric_ScrollArrowStyleBothAtTop;
+            break;
+          default:
+            NS_WARNING("Not handling all possible ThemeScrollBarArrowStyle values");
+            // fall through so we default to BothAtBottom
+          case kThemeScrollBarArrowsLowerRight:
+            aMetric = eMetric_ScrollArrowStyleBothAtBottom;
+        }
       }
-        break;
+      break;
     case eMetric_ScrollSliderStyle:
       ThemeScrollBarThumbStyle thumbStyle;
       ::GetThemeScrollBarThumbStyle ( &thumbStyle );
       switch (thumbStyle) {
         case kThemeScrollBarThumbNormal:
           aMetric = eMetric_ScrollThumbStyleNormal;
           break;
         default:
--- a/widget/src/cocoa/nsNativeThemeCocoa.mm
+++ b/widget/src/cocoa/nsNativeThemeCocoa.mm
@@ -1254,19 +1254,22 @@ nsNativeThemeCocoa::GetScrollbarDrawInfo
   }
   else if (longSideLength < (isSmall ? MIN_SMALL_SCROLLBAR_SIZE : MIN_SCROLLBAR_SIZE)) {
     aTdi.enableState = kThemeTrackNothingToScroll;
     return;
   }
 
   aTdi.trackInfo.scrollbar.pressState = 0;
 
-  // Only go get these scrollbar button states if we need it. For example, there's no reaon to look up scrollbar button 
-  // states when we're only creating a TrackDrawInfo to determine the size of the thumb.
-  if (aShouldGetButtonStates) {
+  // Only go get these scrollbar button states if we need it. For example,
+  // there's no reason to look up scrollbar button states when we're only
+  // creating a TrackDrawInfo to determine the size of the thumb. There's
+  // also no reason to do this on Lion or later, whose scrollbars have no
+  // arrow buttons.
+  if (aShouldGetButtonStates && !nsToolkit::OnLionOrLater()) {
     PRInt32 buttonStates[] = {0, 0, 0, 0};
     GetScrollbarPressStates(aFrame, buttonStates);
     ThemeScrollBarArrowStyle arrowStyle;
     ::GetThemeScrollBarArrowStyle(&arrowStyle);
     // If all four buttons are visible
     if (arrowStyle == kThemeScrollBarArrowsBoth) {
       aTdi.trackInfo.scrollbar.pressState = ConvertToPressState(buttonStates[0], kThemeTopOutsideArrowPressed) |
                                             ConvertToPressState(buttonStates[1], kThemeTopInsideArrowPressed) |
@@ -2025,34 +2028,37 @@ nsNativeThemeCocoa::GetWidgetBorder(nsID
       ::GetThemeMetric(kThemeMetricListBoxFrameOutset, &frameOutset);
       aResult->SizeTo(frameOutset, frameOutset, frameOutset, frameOutset);
       break;
     }
 
     case NS_THEME_SCROLLBAR_TRACK_HORIZONTAL:
     case NS_THEME_SCROLLBAR_TRACK_VERTICAL:
     {
-      // There's only an endcap to worry about when both arrows are on the bottom
-      ThemeScrollBarArrowStyle arrowStyle;
-      ::GetThemeScrollBarArrowStyle(&arrowStyle);
-      if (arrowStyle == kThemeScrollBarArrowsLowerRight) {
-        PRBool isHorizontal = (aWidgetType == NS_THEME_SCROLLBAR_TRACK_HORIZONTAL);
+      // On Lion and later, scrollbars have no arrows.
+      if (!nsToolkit::OnLionOrLater()) {
+        // There's only an endcap to worry about when both arrows are on the bottom
+        ThemeScrollBarArrowStyle arrowStyle;
+        ::GetThemeScrollBarArrowStyle(&arrowStyle);
+        if (arrowStyle == kThemeScrollBarArrowsLowerRight) {
+          PRBool isHorizontal = (aWidgetType == NS_THEME_SCROLLBAR_TRACK_HORIZONTAL);
 
-        nsIFrame *scrollbarFrame = GetParentScrollbarFrame(aFrame);
-        if (!scrollbarFrame) return NS_ERROR_FAILURE;
-        PRBool isSmall = (scrollbarFrame->GetStyleDisplay()->mAppearance == NS_THEME_SCROLLBAR_SMALL);
+          nsIFrame *scrollbarFrame = GetParentScrollbarFrame(aFrame);
+          if (!scrollbarFrame) return NS_ERROR_FAILURE;
+          PRBool isSmall = (scrollbarFrame->GetStyleDisplay()->mAppearance == NS_THEME_SCROLLBAR_SMALL);
 
-        // There isn't a metric for this, so just hardcode a best guess at the value.
-        // This value is even less exact due to the fact that the endcap is partially concave.
-        PRInt32 endcapSize = isSmall ? 5 : 6;
+          // There isn't a metric for this, so just hardcode a best guess at the value.
+          // This value is even less exact due to the fact that the endcap is partially concave.
+          PRInt32 endcapSize = isSmall ? 5 : 6;
 
-        if (isHorizontal)
-          aResult->SizeTo(endcapSize, 0, 0, 0);
-        else
-          aResult->SizeTo(0, endcapSize, 0, 0);
+          if (isHorizontal)
+            aResult->SizeTo(endcapSize, 0, 0, 0);
+          else
+            aResult->SizeTo(0, endcapSize, 0, 0);
+        }
       }
       break;
     }
 
     case NS_THEME_STATUSBAR:
       aResult->SizeTo(0, 1, 0, 0);
       break;
   }
--- a/widget/src/cocoa/nsToolkit.h
+++ b/widget/src/cocoa/nsToolkit.h
@@ -44,32 +44,34 @@
 #import <Carbon/Carbon.h>
 #import <Cocoa/Cocoa.h>
 #import <objc/Object.h>
 #import <IOKit/IOKitLib.h>
 
 #define MAC_OS_X_VERSION_10_4_HEX 0x00001040
 #define MAC_OS_X_VERSION_10_5_HEX 0x00001050
 #define MAC_OS_X_VERSION_10_6_HEX 0x00001060
+#define MAC_OS_X_VERSION_10_7_HEX 0x00001070
 
 class nsToolkit : public nsIToolkit
 {
 public:
                      nsToolkit();
   virtual            ~nsToolkit();
 
   NS_DECL_ISUPPORTS
   NS_DECL_NSITOOLKIT
 
   // Returns the OS X version as returned from Gestalt(gestaltSystemVersion, ...)
   static PRInt32     OSXVersion();
   
   // Convenience functions to check the OS version
   static PRBool      OnLeopardOrLater();
   static PRBool      OnSnowLeopardOrLater();
+  static PRBool      OnLionOrLater();
   
   static void        PostSleepWakeNotification(const char* aNotification);
 
   static nsresult    SwizzleMethods(Class aClass, SEL orgMethod, SEL posedMethod,
                                     PRBool classMethods = PR_FALSE);
 
 protected:
 
--- a/widget/src/cocoa/nsToolkit.mm
+++ b/widget/src/cocoa/nsToolkit.mm
@@ -409,16 +409,21 @@ PRBool nsToolkit::OnLeopardOrLater()
     return (OSXVersion() >= MAC_OS_X_VERSION_10_5_HEX) ? PR_TRUE : PR_FALSE;
 }
 
 PRBool nsToolkit::OnSnowLeopardOrLater()
 {
     return (OSXVersion() >= MAC_OS_X_VERSION_10_6_HEX) ? PR_TRUE : PR_FALSE;
 }
 
+PRBool nsToolkit::OnLionOrLater()
+{
+  return (OSXVersion() >= MAC_OS_X_VERSION_10_7_HEX);
+}
+
 // An alternative to [NSObject poseAsClass:] that isn't deprecated on OS X
 // Leopard and is available to 64-bit binaries on Leopard and above.  Based on
 // ideas and code from http://www.cocoadev.com/index.pl?MethodSwizzling.
 // Since the Method type becomes an opaque type as of Objective-C 2.0, we'll
 // have to switch to using accessor methods like method_exchangeImplementations()
 // when we build 64-bit binaries that use Objective-C 2.0 (on and for Leopard
 // and above).  But these accessor methods aren't available in Objective-C 1
 // (or on Tiger).  So we need to access Method's members directly for (Tiger-