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.
--- 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-