From d5e3fc289ebfdc2d41dbb3574e7da51030b4ae4d Mon Sep 17 00:00:00 2001 From: "joshmoz%gmail.com" Date: Wed, 11 Apr 2007 00:25:11 +0000 Subject: [PATCH] Draw native scrollbars using nsITheme on Mac OS X. Don't use a cocoa control. Fixes a whole host of clipping and visibility bugs and bugs 339447, 369293, 370439. r=josh sr=roc git-svn-id: svn://10.0.0.236/trunk@224386 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/content/base/src/nsGkAtomList.h | 1 + .../layout/xul/base/src/nsScrollbarFrame.cpp | 6 + .../layout/xul/base/src/nsScrollbarFrame.h | 2 + .../classic/global/mac/nativescrollbars.css | 49 +- .../pinstripe/global/nativescrollbars.css | 55 +- mozilla/widget/src/cocoa/Makefile.in | 1 - mozilla/widget/src/cocoa/nsLookAndFeel.h | 3 + mozilla/widget/src/cocoa/nsLookAndFeel.mm | 5 + mozilla/widget/src/cocoa/nsNativeScrollbar.h | 138 ---- mozilla/widget/src/cocoa/nsNativeScrollbar.mm | 775 ------------------ mozilla/widget/src/cocoa/nsNativeThemeCocoa.h | 8 +- .../widget/src/cocoa/nsNativeThemeCocoa.mm | 256 +++++- mozilla/widget/src/cocoa/nsWidgetFactory.mm | 6 - .../widget/src/xpwidgets/nsWidgetAtomList.h | 6 + 14 files changed, 354 insertions(+), 957 deletions(-) delete mode 100644 mozilla/widget/src/cocoa/nsNativeScrollbar.h delete mode 100644 mozilla/widget/src/cocoa/nsNativeScrollbar.mm diff --git a/mozilla/content/base/src/nsGkAtomList.h b/mozilla/content/base/src/nsGkAtomList.h index 4a6826c1b2f..cf00d7bb5aa 100755 --- a/mozilla/content/base/src/nsGkAtomList.h +++ b/mozilla/content/base/src/nsGkAtomList.h @@ -1377,6 +1377,7 @@ GK_ATOM(positionedInlineFrame, "PositionedInlineFrame") GK_ATOM(canvasFrame, "CanvasFrame") GK_ATOM(rootFrame, "RootFrame") GK_ATOM(scrollFrame, "ScrollFrame") +GK_ATOM(scrollbarFrame, "ScrollbarFrame") GK_ATOM(sequenceFrame, "SequenceFrame") GK_ATOM(tableCaptionFrame, "TableCaptionFrame") GK_ATOM(tableCellFrame, "TableCellFrame") diff --git a/mozilla/layout/xul/base/src/nsScrollbarFrame.cpp b/mozilla/layout/xul/base/src/nsScrollbarFrame.cpp index 4b89dd31204..15641fc4e00 100644 --- a/mozilla/layout/xul/base/src/nsScrollbarFrame.cpp +++ b/mozilla/layout/xul/base/src/nsScrollbarFrame.cpp @@ -112,6 +112,12 @@ nsScrollbarFrame::IsContainingBlock() const return PR_TRUE; } +nsIAtom* +nsScrollbarFrame::GetType() const +{ + return nsGkAtoms::scrollbarFrame; +} + NS_IMETHODIMP nsScrollbarFrame::AttributeChanged(PRInt32 aNameSpaceID, nsIAtom* aAttribute, diff --git a/mozilla/layout/xul/base/src/nsScrollbarFrame.h b/mozilla/layout/xul/base/src/nsScrollbarFrame.h index e7af55842c6..b7c9f84b3fb 100644 --- a/mozilla/layout/xul/base/src/nsScrollbarFrame.h +++ b/mozilla/layout/xul/base/src/nsScrollbarFrame.h @@ -99,6 +99,8 @@ public: virtual PRBool IsContainingBlock() const; + virtual nsIAtom* GetType() const; + // nsIScrollbarFrame virtual void SetScrollbarMediatorContent(nsIContent* aMediator); virtual nsIScrollbarMediator* GetScrollbarMediator(); diff --git a/mozilla/themes/classic/global/mac/nativescrollbars.css b/mozilla/themes/classic/global/mac/nativescrollbars.css index 331e1cac1c9..36929eb0103 100644 --- a/mozilla/themes/classic/global/mac/nativescrollbars.css +++ b/mozilla/themes/classic/global/mac/nativescrollbars.css @@ -47,15 +47,54 @@ scrollbar { -moz-appearance: scrollbar; - -moz-binding: url(chrome://global/content/bindings/nativescrollbar.xml#scrollbar); - min-width: 16px; + -moz-binding: url(chrome://global/content/bindings/scrollbar.xml#scrollbar); cursor: default; + background-color: white; } html|select[size]:not([size="0"]):not([size="1"]) > scrollbar, html|select[multiple] > scrollbar { -moz-appearance: scrollbar-small; - min-width: 11px; +} + +/* ..... track ..... */ + +slider { + -moz-appearance: scrollbartrack-vertical; +} + +slider[orient="horizontal"] { + -moz-appearance: scrollbartrack-horizontal; +} + +/* ..... thumb ..... */ + +thumb { + -moz-appearance: scrollbarthumb-vertical; +} + +thumb[orient="horizontal"] { + -moz-appearance: scrollbarthumb-horizontal; +} + +/* ..... increment ..... */ + +scrollbarbutton[type="increment"] { + -moz-appearance: scrollbarbutton-right; +} + +scrollbar[orient="vertical"] > scrollbarbutton[type="increment"] { + -moz-appearance: scrollbarbutton-down; +} + +/* ..... decrement ..... */ + +scrollbarbutton[type="decrement"] { + -moz-appearance: scrollbarbutton-left; +} + +scrollbar[orient="vertical"] > scrollbarbutton[type="decrement"] { + -moz-appearance: scrollbarbutton-up; } /* ::::: square at the corner of two scrollbars ::::: */ @@ -63,7 +102,6 @@ html|select[multiple] > scrollbar { scrollcorner { /* XXX -moz-appearance: scrollcorner; */ -moz-binding: url(chrome://global/content/bindings/scrollbar.xml#scrollbar-base); - width: 16px; cursor: default; background-color: white; } @@ -74,8 +112,7 @@ scrollcorner { @media print { html|div scrollbar { -moz-appearance: scrollbar; - -moz-binding: url(chrome://global/content/bindings/nativescrollbar.xml#scrollbar); - min-width: 16px; + -moz-binding: url(chrome://global/content/bindings/scrollbar.xml#scrollbar); cursor: default; } } diff --git a/mozilla/toolkit/themes/pinstripe/global/nativescrollbars.css b/mozilla/toolkit/themes/pinstripe/global/nativescrollbars.css index 75ce09a545b..61995694018 100644 --- a/mozilla/toolkit/themes/pinstripe/global/nativescrollbars.css +++ b/mozilla/toolkit/themes/pinstripe/global/nativescrollbars.css @@ -47,8 +47,7 @@ scrollbar { -moz-appearance: scrollbar; - -moz-binding: url(chrome://global/content/bindings/nativescrollbar.xml#scrollbar); - min-width: 16px; + -moz-binding: url(chrome://global/content/bindings/scrollbar.xml#scrollbar); cursor: default; background-color: white; } @@ -56,7 +55,46 @@ scrollbar { html|select[size]:not([size="0"]):not([size="1"]) > scrollbar, html|select[multiple] > scrollbar { -moz-appearance: scrollbar-small; - min-width: 11px; +} + +/* ..... track ..... */ + +slider { + -moz-appearance: scrollbartrack-vertical; +} + +slider[orient="horizontal"] { + -moz-appearance: scrollbartrack-horizontal; +} + +/* ..... thumb ..... */ + +thumb { + -moz-appearance: scrollbarthumb-vertical; +} + +thumb[orient="horizontal"] { + -moz-appearance: scrollbarthumb-horizontal; +} + +/* ..... increment ..... */ + +scrollbarbutton[type="increment"] { + -moz-appearance: scrollbarbutton-right; +} + +scrollbar[orient="vertical"] > scrollbarbutton[type="increment"] { + -moz-appearance: scrollbarbutton-down; +} + +/* ..... decrement ..... */ + +scrollbarbutton[type="decrement"] { + -moz-appearance: scrollbarbutton-left; +} + +scrollbar[orient="vertical"] > scrollbarbutton[type="decrement"] { + -moz-appearance: scrollbarbutton-up; } /* ::::: square at the corner of two scrollbars ::::: */ @@ -75,16 +113,7 @@ scrollcorner { @media print { html|div scrollbar { -moz-appearance: scrollbar; - -moz-binding: url(chrome://global/content/bindings/nativescrollbar.xml#scrollbar); - min-width: 16px; + -moz-binding: url(chrome://global/content/bindings/scrollbar.xml#scrollbar); cursor: default; } } - -/* ::::: slider ::::: */ - -thumb { - background: url("chrome://global/skin/icons/thumb.png") transparent center no-repeat; - min-width: 15px; -} - diff --git a/mozilla/widget/src/cocoa/Makefile.in b/mozilla/widget/src/cocoa/Makefile.in index 124d20804c5..ef04cc6f4e1 100644 --- a/mozilla/widget/src/cocoa/Makefile.in +++ b/mozilla/widget/src/cocoa/Makefile.in @@ -105,7 +105,6 @@ CMMSRCS = \ nsChildView.mm \ nsWindowMap.mm \ nsWidgetFactory.mm \ - nsNativeScrollbar.mm \ nsCursorManager.mm \ nsMacCursor.mm \ nsScreenCocoa.mm \ diff --git a/mozilla/widget/src/cocoa/nsLookAndFeel.h b/mozilla/widget/src/cocoa/nsLookAndFeel.h index 18a21cb2b1c..e642b151ba2 100644 --- a/mozilla/widget/src/cocoa/nsLookAndFeel.h +++ b/mozilla/widget/src/cocoa/nsLookAndFeel.h @@ -50,6 +50,9 @@ public: protected: + // Apple hasn't defined a constant for scollbars with two arrows on each end, so we'll use this one. + static const int kThemeScrollBarArrowsBoth = 2; + typedef enum { //theme accent variation colours on Mac OS, //offsets into Platinum theme variation colour table diff --git a/mozilla/widget/src/cocoa/nsLookAndFeel.mm b/mozilla/widget/src/cocoa/nsLookAndFeel.mm index 9b214bcdc63..4bd00f3181c 100644 --- a/mozilla/widget/src/cocoa/nsLookAndFeel.mm +++ b/mozilla/widget/src/cocoa/nsLookAndFeel.mm @@ -524,6 +524,11 @@ NS_IMETHODIMP nsLookAndFeel::GetMetric(const nsMetricID aID, PRInt32 & aMetric) case kThemeScrollBarArrowsSingle: aMetric = eMetric_ScrollArrowStyleSingle; break; + // This constant isn'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; default: NS_WARNING("Not handling all possible ThemeScrollBarArrowStyle values"); // fall through so we default to BothAtBottom diff --git a/mozilla/widget/src/cocoa/nsNativeScrollbar.h b/mozilla/widget/src/cocoa/nsNativeScrollbar.h deleted file mode 100644 index 4c7aa881251..00000000000 --- a/mozilla/widget/src/cocoa/nsNativeScrollbar.h +++ /dev/null @@ -1,138 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is mozilla.org code. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 2002 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the NPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#ifndef nsNativeScrollbar_h_ -#define nsNativeScrollbar_h_ - -#import -#import - -#include "mozView.h" -#include "nsChildView.h" - -#include "nsINativeScrollbar.h" -#include "nsIContent.h" - -class nsIScrollbarMediator; - -@class NativeScrollbarView; - -// -// nsNativeScrollbar -// -// A wrapper around a MacOS native scrollbar that knows how to work -// with a stub gecko frame to scroll in the GFXScrollFrame mechanism -// - -class nsNativeScrollbar : public nsChildView, public nsINativeScrollbar -{ -private: - typedef nsChildView Inherited; - -public: - nsNativeScrollbar(); - virtual ~nsNativeScrollbar(); - - NS_DECL_ISUPPORTS_INHERITED - NS_DECL_NSINATIVESCROLLBAR - - // called from the NativeScrollbarView when someone hits a part - // of the scrollbar. - void DoScroll(NSScrollerPart inPart); - -protected: - - // nsWindow Interface - virtual PRBool DispatchMouseEvent(nsMouseEvent &aEvent); - NS_IMETHOD Enable(PRBool aState); - NS_IMETHOD IsEnabled(PRBool* outState); - - NSScroller* GetControl() { return (NSScroller*)mView; } - - void UpdateContentPosition(PRUint32 inNewPos); - - void RecreateHorizontalScrollbar(); - - virtual NSView* CreateCocoaView(NSRect inFrame); - - void UpdateScroller(); - - NativeScrollbarView* ScrollbarView() const { return (NativeScrollbarView*)mView; } - -// DATA -private: - - nsIContent* mContent; // the content node that affects the scrollbar's value - nsIScrollbarMediator* mMediator; // for scrolling with outliners - nsISupports* mScrollbar; // for calling into the mediator - - PRUint32 mValue; - PRUint32 mMaxValue; - PRUint32 mVisibleImageSize; - PRUint32 mLineIncrement; - PRBool mIsEnabled; -}; - - -@interface NativeScrollbarView : NSScroller -{ - // Our window [WEAK] - NSWindow* mWindow; - - // the nsNativeScrollbar that created this view. It retains this NSView, so - // the link back to it must be weak. [WEAK] - nsNativeScrollbar* mGeckoChild; - - // YES when we're in a tracking loop - BOOL mInTracking; - - // rects that were invalidated during a draw, so have pending drawing - NSMutableArray* mPendingDirtyRects; - BOOL mPendingFullDisplay; -} - - // default initializer -- (id)initWithFrame:(NSRect)frameRect geckoChild:(nsNativeScrollbar*)inChild; - // overridden parent class initializer -- (id)initWithFrame:(NSRect)frameRect; - -- (IBAction)scroll:(NSScroller*)sender; - -@end - - -#endif // nsNativeScrollbar_h_ diff --git a/mozilla/widget/src/cocoa/nsNativeScrollbar.mm b/mozilla/widget/src/cocoa/nsNativeScrollbar.mm deleted file mode 100644 index 6a669c0ab23..00000000000 --- a/mozilla/widget/src/cocoa/nsNativeScrollbar.mm +++ /dev/null @@ -1,775 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is mozilla.org code. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 2002 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Mark Mentovai - * Stuart Morgan - * Josh Aas - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the NPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#include "nsNativeScrollbar.h" -#include "nsIDeviceContext.h" - -#include "nsReadableUtils.h" -#include "nsWidgetAtoms.h" -#include "nsINameSpaceManager.h" -#include "nsIDOMElement.h" -#include "nsIScrollbarMediator.h" -#include "nsIRollupListener.h" - -// category of NSScroller methods to quiet warnings - -@interface NSScroller(NativeScrollViewExtensions) -- (void)trackPagingArea:(id)aEvent; -@end - -NS_IMPL_ISUPPORTS_INHERITED1(nsNativeScrollbar, nsChildView, nsINativeScrollbar) - -static const float kHorizScrollbarInitW = 100; -static const float kHorizScrollbarInitH = 16; - -extern nsIRollupListener * gRollupListener; -extern nsIWidget * gRollupWidget; - -inline void BoundsCheck(PRInt32 low, PRUint32& value, PRUint32 high) -{ - if ((PRInt32) value < low) - value = low; - if (value > high) - value = high; -} - -nsNativeScrollbar::nsNativeScrollbar() - : nsChildView() - , mContent(nsnull) - , mMediator(nsnull) - , mScrollbar(nsnull) - , mValue(0) - , mMaxValue(0) - , mVisibleImageSize(0) - , mLineIncrement(0) - , mIsEnabled(PR_TRUE) -{ -} - - -nsNativeScrollbar::~nsNativeScrollbar() -{ -} - -// -// CreateCocoaView -// -// Create a NativeScrollbarView for insertion into the cocoa view hierarchy. -// Cocoa sets the orientation of a scrollbar at creation time by looking -// at its frame and taking the longer side to be the orientation. Since -// chances are good at this point gecko just wants us to be 1x1, assume -// we're going to be vertical. If later when we get a content node assigned -// we find we're horizontal, we can update then. -// -NSView* -nsNativeScrollbar::CreateCocoaView(NSRect inFrame) -{ - return [[[NativeScrollbarView alloc] initWithFrame:inFrame geckoChild:this] autorelease]; -} - - -// -// DoScroll -// -// Called from the action proc of the scrollbar, adjust the control's -// value as well as the value in the content node which communicates -// to gecko that the document is scrolling. -// -void -nsNativeScrollbar::DoScroll(NSScrollerPart inPart) -{ - PRUint32 oldPos, newPos; - PRUint32 incr; - PRUint32 visibleImageSize; - GetPosition(&oldPos); - GetLineIncrement(&incr); - GetViewSize(&visibleImageSize); - switch ( inPart ) { - - // - // For the up/down buttons, scroll up or down by the line height and - // update the attributes on the content node (the scroll frame listens - // for these attributes and will scroll accordingly). However, - // if we have a mediator, we're in an outliner and we have to scroll by - // lines. Outliner ignores the params to ScrollbarButtonPressed() except - // to check if one is greater than the other to indicate direction. - // - - case NSScrollerDecrementLine: // scroll up/left - newPos = oldPos - (mLineIncrement ? mLineIncrement : 1); - if ( mMediator ) { - BoundsCheck(0, newPos, mMaxValue); - mMediator->ScrollbarButtonPressed(mScrollbar, oldPos, newPos); - } else { - UpdateContentPosition(newPos); - } - break; - - case NSScrollerIncrementLine: // scroll down/right - newPos = oldPos + (mLineIncrement ? mLineIncrement : 1); - if ( mMediator ) { - BoundsCheck(0, newPos, mMaxValue); - mMediator->ScrollbarButtonPressed(mScrollbar, oldPos, newPos); - } else { - UpdateContentPosition(newPos); - } - break; - - // - // For page up/down, scroll by the page height and update the attributes - // on the content node (as above). If we have a mediator, we're in an - // outliner so tell it directly that the position has changed. Note that - // outliner takes signed values, so we have to convert our unsigned to - // signed values first. - // - - case NSScrollerDecrementPage: // scroll up a page - newPos = oldPos - visibleImageSize; - UpdateContentPosition(newPos); - if ( mMediator ) { - PRInt32 op = oldPos, np = mValue; - if ( np < 0 ) - np = 0; - mMediator->PositionChanged(mScrollbar, op, np); - } - break; - - case NSScrollerIncrementPage: // scroll down a page - newPos = oldPos + visibleImageSize; - UpdateContentPosition(newPos); - if ( mMediator ) { - PRInt32 op = oldPos, np = mValue; - if ( np < 0 ) - np = 0; - mMediator->PositionChanged(mScrollbar, op, np); - } - break; - - // - // The scroller handles changing the value on the thumb for - // us, so read it, convert it back to the range gecko is expecting, - // and tell the content. - // - case NSScrollerKnob: - case NSScrollerKnobSlot: - newPos = (int) ([ScrollbarView() floatValue] * mMaxValue); - UpdateContentPosition(newPos); - if ( mMediator ) { - PRInt32 op = oldPos, np = mValue; - if ( np < 0 ) - np = 0; - mMediator->PositionChanged(mScrollbar, op, np); - } - break; - - default: - ; // do nothing - } -} - - -// -// UpdateContentPosition -// -// Tell the content node that the scrollbar has changed value and -// then update the scrollbar's position -// -void -nsNativeScrollbar::UpdateContentPosition(PRUint32 inNewPos) -{ - if ( inNewPos == mValue || !mContent ) // break any possible recursion - return; - - // guarantee |inNewPos| is in the range of [0, mMaxValue] so it's correctly unsigned - BoundsCheck(0, inNewPos, mMaxValue); - - // convert the int to a string - nsAutoString buffer; - buffer.AppendInt(inNewPos); - - mContent->SetAttr(kNameSpaceID_None, nsWidgetAtoms::curpos, buffer, PR_TRUE); - SetPosition(inNewPos); -} - - - -// -// DispatchMouseEvent -// -// We don't need to do much here, cocoa will handle tracking the mouse for us. Returning -// true means that the event is handled. -// -PRBool -nsNativeScrollbar::DispatchMouseEvent(nsMouseEvent &aEvent) -{ - return PR_TRUE; -} - - -// -// SetMaxRange -// -// Set the maximum range of a scroll bar. This should be set to the -// full scrollable area minus the visible area. -// -NS_IMETHODIMP -nsNativeScrollbar::SetMaxRange(PRUint32 aEndRange) -{ - if ((PRInt32)aEndRange < 0) - aEndRange = 0; - - mMaxValue = aEndRange; - UpdateScroller(); - return NS_OK; -} - - -// -// GetMaxRange -// -// Get the maximum range of a scroll bar -// -NS_IMETHODIMP -nsNativeScrollbar::GetMaxRange(PRUint32* aMaxRange) -{ - *aMaxRange = mMaxValue; - return NS_OK; -} - - -// -// SetPosition -// -// Set the current position of the slider and redraw the scrollbar. We have -// to convert between the integer values gecko uses (0,mMaxValue) to the float -// values that cocoa uses (0,1). -// -NS_IMETHODIMP -nsNativeScrollbar::SetPosition(PRUint32 aPos) -{ - NativeScrollbarView* scrollbarView = ScrollbarView(); - - if ((PRInt32)aPos < 0) - aPos = 0; - - // while we _should_ be ensuring that we don't set our value higher - // than our max value, the gfx scrollview code plays fast and loose - // with the rules while going back/forward and adjusts the value to the - // previous value long before it sets the max. As a result, we would - // lose the given value (since max would most likely be 0). The only - // way around that is to relax our restrictions a little bit. (bug 135191) - // mValue = ((PRInt32)aPos) > mMaxValue ? mMaxValue : ((int)aPos); - mValue = aPos; - if ( mMaxValue ) - [scrollbarView setFloatValue:(mValue / (float)mMaxValue)]; - else - [scrollbarView setFloatValue:0.0]; - - return NS_OK; -} - - -// -// GetPosition -// -// Get the current position of the slider -// -NS_IMETHODIMP -nsNativeScrollbar::GetPosition(PRUint32* aPos) -{ - *aPos = mValue; - return NS_OK; -} - - -// -// SetViewSize -// -// Change the knob proportion to be the ratio of the size of the visible image (given in |aSize|) -// to the total area (visible + max). Recall that the max size is the total minus the -// visible area. -// -NS_IMETHODIMP -nsNativeScrollbar::SetViewSize(PRUint32 aSize) -{ - if ((PRInt32)aSize < 0) - aSize = 0; - - mVisibleImageSize = aSize; - - UpdateScroller(); - return NS_OK; -} - - -// -// GetViewSize -// -// Get the height of the visible view area. -// -NS_IMETHODIMP -nsNativeScrollbar::GetViewSize(PRUint32* aSize) -{ - *aSize = mVisibleImageSize; - return NS_OK; -} - - -// -// SetLineIncrement -// -// Set the line increment of the scroll bar -// -NS_IMETHODIMP -nsNativeScrollbar::SetLineIncrement(PRUint32 aLineIncrement) -{ - mLineIncrement = (((int)aLineIncrement) > 0 ? aLineIncrement : 1); - return NS_OK; -} - - -// -// GetLineIncrement -// -// Get the line increment of the scroll bar -// -NS_IMETHODIMP -nsNativeScrollbar::GetLineIncrement(PRUint32* aLineIncrement) -{ - *aLineIncrement = mLineIncrement; - return NS_OK; -} - - -// -// GetNarrowSize -// -// Ask the appearance manager for the dimensions of the narrow axis -// of the scrollbar. We cheat and assume the width of a vertical scrollbar -// is the same as the height of a horizontal scrollbar. *shrug*. Shoot me. -// -NS_IMETHODIMP -nsNativeScrollbar::GetNarrowSize(PRInt32* outSize) -{ - if ( *outSize ) - return NS_ERROR_FAILURE; - SInt32 width = 0; - ::GetThemeMetric(kThemeMetricScrollBarWidth, &width); - *outSize = width; - return NS_OK; -} - - -// -// SetContent -// -// Hook up this native scrollbar to the rest of gecko. We care about -// the content so we can set attributes on it to affect the scrollview. We -// care about the mediator for so we can do row-based scrolling. -// -NS_IMETHODIMP -nsNativeScrollbar::SetContent(nsIContent* inContent, nsISupports* inScrollbar, - nsIScrollbarMediator* inMediator) -{ - mContent = inContent; - mMediator = inMediator; - mScrollbar = inScrollbar; - - if ( mContent ) { - // we may have to re-create the scrollbar view as horizontal. Check the - // 'orient' attribute and rebuild the view with all the settings - // present in the current view - if (mContent->AttrValueIs(kNameSpaceID_None, nsWidgetAtoms::orient, - nsWidgetAtoms::horizontal, eCaseMatters)) - RecreateHorizontalScrollbar(); - } - - return NS_OK; -} - - -// -// RecreateHorizontalScrollbar -// -// Replace the vertical scroller we created earlier with a horizontal scroller -// of the same dimensions and values -// -void -nsNativeScrollbar::RecreateHorizontalScrollbar() -{ - // Use a horizontal frame so that Cocoa thinks it's a horizontal scroller. - NSRect orientation = NSMakeRect(0, 0, - kHorizScrollbarInitW, kHorizScrollbarInitH); - - NativeScrollbarView* oldScrollbarView = ScrollbarView(); - - // Create the new horizontal scroller, init it, and reset the old values. - mView = [[NativeScrollbarView alloc] initWithFrame:orientation - geckoChild:this]; - - NativeScrollbarView* newScrollbarView = ScrollbarView(); - - [newScrollbarView setNativeWindow:[oldScrollbarView nativeWindow]]; - [newScrollbarView setFrame:[oldScrollbarView bounds]]; - - [newScrollbarView setHidden:[oldScrollbarView isHidden]]; - [newScrollbarView setEnabled:[oldScrollbarView isEnabled]]; - [newScrollbarView setFloatValue:[oldScrollbarView floatValue] - knobProportion:[oldScrollbarView knobProportion]]; - - // Hook up the new view and get rid of the previous one. - [mParentView replaceSubview:oldScrollbarView with:newScrollbarView]; - [oldScrollbarView release]; -} - - -// -// Enable -// -// Enable/disable this scrollbar -// -NS_IMETHODIMP -nsNativeScrollbar::Enable(PRBool aState) -{ - if (aState != mVisible) { - mIsEnabled = aState; - UpdateScroller(); - } - return NS_OK; -} - - -NS_IMETHODIMP -nsNativeScrollbar::IsEnabled(PRBool* outState) -{ - if (outState) - *outState = mIsEnabled; - return NS_OK; -} - - -void -nsNativeScrollbar::UpdateScroller() -{ - NativeScrollbarView* scrollbarView = ScrollbarView(); - - // Update the current value based on the new range. We need to recompute the - // float value in case we had to set the value to 0 because gecko cheated - // and set the position before it set the max value. - float knobProp = 1.0f; - if ((mVisibleImageSize + mMaxValue) > 0) - knobProp = (float)mVisibleImageSize / (float)(mVisibleImageSize + mMaxValue); - [scrollbarView setFloatValue:(mValue / (float)mMaxValue) knobProportion:knobProp]; - - BOOL enableScrollbar = (mIsEnabled && (mMaxValue > 0)); - [scrollbarView setEnabled:enableScrollbar]; - - Invalidate(FALSE); -} - - -#pragma mark - - -@interface NativeScrollbarView(Private) - -- (void)processPendingRedraws; - -@end - -@implementation NativeScrollbarView - -// -// -initWithFrame:geckoChild -// Designated Initializer -// -// Init our superclass and make the connection to the gecko nsIWidget we're -// mirroring -// -- (id)initWithFrame:(NSRect)frameRect geckoChild:(nsNativeScrollbar*)inChild -{ - if ((self = [super initWithFrame:frameRect])) - { - NS_ASSERTION(inChild, "Need to provide a tether between this and a nsChildView class"); - mGeckoChild = inChild; - - // make ourselves the target of the scroll and set the action message - [self setTarget:self]; - [self setAction:@selector(scroll:)]; - } - return self; -} - - -// -// -initWithFrame -// -// overridden parent class initializer -// -- (id)initWithFrame:(NSRect)frameRect -{ - NS_WARNING("You're calling the wrong initializer. You really want -initWithFrame:geckoChild"); - if ((self = [self initWithFrame:frameRect geckoChild:nsnull])) - { - } - return self; -} - - -- (void)setFrame:(NSRect)frameRect -{ - // maybe make this a small scrollbar - SInt32 smallScrollbarWidth = 0; - ::GetThemeMetric(kThemeMetricSmallScrollBarWidth, &smallScrollbarWidth); - if ((SInt32)frameRect.size.width == smallScrollbarWidth || - (SInt32)frameRect.size.height == smallScrollbarWidth) { - [self setControlSize:NSSmallControlSize]; - } - else { - [self setControlSize:NSRegularControlSize]; - } - - [super setFrame:frameRect]; -} - - -- (NSWindow*)nativeWindow -{ - NSWindow* currWin = [self window]; - if (currWin) - return currWin; - else - return mWindow; -} - -- (void) setNativeWindow: (NSWindow*)aWindow -{ - mWindow = aWindow; -} - - -- (BOOL)isFlipped -{ - return YES; -} - - -// -// -widget -// -// return our gecko child view widget. Note this does not AddRef. -// -- (nsIWidget*) widget -{ - return NS_STATIC_CAST(nsIWidget*, mGeckoChild); -} - -- (void)setNeedsPendingDisplay -{ - mPendingFullDisplay = YES; - [self performSelector:@selector(processPendingRedraws) withObject:nil afterDelay:0]; -} - -- (void)setNeedsPendingDisplayInRect:(NSRect)invalidRect -{ - if (!mPendingDirtyRects) - mPendingDirtyRects = [[NSMutableArray alloc] initWithCapacity:1]; - [mPendingDirtyRects addObject:[NSValue valueWithRect:invalidRect]]; - [self performSelector:@selector(processPendingRedraws) withObject:nil afterDelay:0]; -} - -// -// -processPendingRedraws -// -// Clears the queue of any pending invalides -// -- (void)processPendingRedraws -{ - if (mPendingFullDisplay) { - [self setNeedsDisplay:YES]; - } - else { - unsigned int count = [mPendingDirtyRects count]; - for (unsigned int i = 0; i < count; ++i) { - [self setNeedsDisplayInRect:[[mPendingDirtyRects objectAtIndex:i] rectValue]]; - } - } - mPendingFullDisplay = NO; - [mPendingDirtyRects release]; - mPendingDirtyRects = nil; -} - -- (void)scrollRect:(NSRect)aRect by:(NSSize)offset -{ - // Update any pending dirty rects to reflect the new scroll position - if (mPendingDirtyRects) { - unsigned int count = [mPendingDirtyRects count]; - for (unsigned int i = 0; i < count; ++i) { - NSRect oldRect = [[mPendingDirtyRects objectAtIndex:i] rectValue]; - NSRect newRect = NSOffsetRect(oldRect, offset.width, offset.height); - [mPendingDirtyRects replaceObjectAtIndex:i - withObject:[NSValue valueWithRect:newRect]]; - } - } - [super scrollRect:aRect by:offset]; -} - -// -// -mouseMoved -// -// our parent view will try to forward this message down to us. The -// default behavior for NSResponder is to forward it up the chain. Can you -// say "infinite recursion"? I thought so. Just stub out the action to -// break the cycle of madness. -// -- (void)mouseMoved:(NSEvent*)theEvent -{ - // do nothing -} - -// -// -widgetDestroyed -// -// the gecko nsNativeScrollbar is being destroyed. -// -- (void)widgetDestroyed -{ - mGeckoChild = nsnull; - - if (mInTracking) - { - // To get out of the NSScroller tracking loop, we post a fake mouseup event. - // We have to do this here, before we are ripped out of the view hierarchy. - [NSApp postEvent:[NSEvent mouseEventWithType:NSLeftMouseUp - location:[NSEvent mouseLocation] - modifierFlags:0 - timestamp:[[NSApp currentEvent] timestamp] - windowNumber:[[self window] windowNumber] - context:NULL - eventNumber:0 - clickCount:0 - pressure:1.0] - atStart:YES]; - - mInTracking = NO; - } -} - -// contextMenu, from mozView protocol -- (NSMenu*)contextMenu -{ - return nil; -} - -// -// -scroll -// -// the action message we've set up to be called when the scrollbar needs -// to adjust its value. Feed back into the owning widget to process -// how much to scroll and adjust the correct attributes. -// -- (IBAction)scroll:(NSScroller*)sender -{ - // roll up popup windows if there are any - if (gRollupListener && gRollupWidget && - gRollupWidget->GetNativeData(NS_NATIVE_WINDOW) != [self nativeWindow]) { - gRollupListener->Rollup(); - } - - if (mGeckoChild) - mGeckoChild->DoScroll([sender hitPart]); -} - - -// -// -trackKnob: -// -// overridden to toggle mInTracking on and off -// -- (void)trackKnob:(NSEvent *)theEvent -{ - mInTracking = YES; - NS_DURING // be sure we always turn mInTracking off. - [super trackKnob:theEvent]; - NS_HANDLER - NS_ENDHANDLER - mInTracking = NO; -} - -// -// -trackScrollButtons: -// -// overridden to toggle mInTracking on and off -// -- (void)trackScrollButtons:(NSEvent *)theEvent -{ - mInTracking = YES; - NS_DURING // be sure we always turn mInTracking off. - [super trackScrollButtons:theEvent]; - NS_HANDLER - NS_ENDHANDLER - mInTracking = NO; -} - -// -// -trackPagingArea: -// -// this method is not documented, but was seen in sampling. We have -// to override it to toggle mInTracking. -// -- (void)trackPagingArea:(id)theEvent -{ - mInTracking = YES; - NS_DURING // be sure we always turn mInTracking off. - [super trackPagingArea:theEvent]; - NS_HANDLER - NS_ENDHANDLER - mInTracking = NO; -} - -#ifdef ACCESSIBILITY -// XXXhakan: need to find out what needs to be done here to make these scrollbars accessible. -- (BOOL)accessibilityIsIgnored -{ - return YES; -} -#endif - -@end - diff --git a/mozilla/widget/src/cocoa/nsNativeThemeCocoa.h b/mozilla/widget/src/cocoa/nsNativeThemeCocoa.h index bf0f1cd1cc7..125e8163e7e 100644 --- a/mozilla/widget/src/cocoa/nsNativeThemeCocoa.h +++ b/mozilla/widget/src/cocoa/nsNativeThemeCocoa.h @@ -92,7 +92,7 @@ protected: static const int kAquaMinButtonWidth = 68; static const int kAquaDropdownLeftEndcap = 9; static const int kAquaDropwdonRightEndcap = 20; // wider on right to encompass the button - + nsresult GetSystemColor(PRUint8 aWidgetType, nsILookAndFeel::nsColorID& aColorID); nsresult GetSystemFont(PRUint8 aWidgetType, nsSystemFontID& aFont); @@ -125,6 +125,12 @@ protected: void DrawCheckboxRadio (CGContextRef context, ThemeButtonKind inKind, const HIRect& inBoxRect, PRBool inChecked, PRBool inDisabled, PRInt32 inState); + // Scrollbars + void DrawScrollbar(CGContextRef aCGContext, const HIRect& aBoxRect, nsIFrame *aFrame); + void GetScrollbarPressStates (nsIFrame *aFrame, PRInt32 aButtonStates[]); + void GetScrollbarDrawInfo (HIThemeTrackDrawInfo& aTdi, nsIFrame *aFrame, + const HIRect& aRect, PRBool aShouldGetButtonStates); + nsIFrame* GetParentScrollbarFrame(nsIFrame *aFrame); }; #endif // nsNativeThemeCocoa_h_ diff --git a/mozilla/widget/src/cocoa/nsNativeThemeCocoa.mm b/mozilla/widget/src/cocoa/nsNativeThemeCocoa.mm index b88a7cdffff..87733eb43cb 100644 --- a/mozilla/widget/src/cocoa/nsNativeThemeCocoa.mm +++ b/mozilla/widget/src/cocoa/nsNativeThemeCocoa.mm @@ -22,6 +22,7 @@ * Contributor(s): * Vladimir Vukicevic (HITheme rewrite) * Josh Aas + * Colin Barrett * * Alternatively, the contents of this file may be used under the terms of * either of the GNU General Public License Version 2 or later (the "GPL"), @@ -58,11 +59,16 @@ #include "gfxQuartzSurface.h" #define DRAW_IN_FRAME_DEBUG 0 +#define SCROLLBARS_VISUAL_DEBUG 0 extern "C" { CG_EXTERN void CGContextSetCTM(CGContextRef, CGAffineTransform); } +// Copied from nsLookAndFeel.h +// Apple hasn't defined a constant for scollbars with two arrows on each end, so we'll use this one. +static const int kThemeScrollBarArrowsBoth = 2; + #define HITHEME_ORIENTATION kHIThemeOrientationNormal NS_IMPL_ISUPPORTS1(nsNativeThemeCocoa, nsITheme) @@ -105,6 +111,7 @@ nsNativeThemeCocoa::DrawCheckboxRadio(CGContextRef cgContext, ThemeButtonKind in HIThemeDrawButton(&inBoxRect, &bdi, cgContext, HITHEME_ORIENTATION, NULL); } + void nsNativeThemeCocoa::DrawButton(CGContextRef cgContext, ThemeButtonKind inKind, const HIRect& inBoxRect, PRBool inIsDefault, PRBool inDisabled, @@ -154,6 +161,7 @@ nsNativeThemeCocoa::DrawButton(CGContextRef cgContext, ThemeButtonKind inKind, HIThemeDrawButton(&drawRect, &bdi, cgContext, HITHEME_ORIENTATION, NULL); } + void nsNativeThemeCocoa::DrawSpinButtons(CGContextRef cgContext, ThemeButtonKind inKind, const HIRect& inBoxRect, PRBool inDisabled, @@ -174,6 +182,7 @@ nsNativeThemeCocoa::DrawSpinButtons(CGContextRef cgContext, ThemeButtonKind inKi HIThemeDrawButton(&inBoxRect, &bdi, cgContext, HITHEME_ORIENTATION, NULL); } + void nsNativeThemeCocoa::DrawFrame(CGContextRef cgContext, HIThemeFrameKind inKind, const HIRect& inBoxRect, PRBool inIsDisabled, PRInt32 inState) @@ -208,6 +217,7 @@ nsNativeThemeCocoa::DrawFrame(CGContextRef cgContext, HIThemeFrameKind inKind, HIThemeDrawFrame(&drawRect, &fdi, cgContext, HITHEME_ORIENTATION); } + void nsNativeThemeCocoa::DrawProgress(CGContextRef cgContext, const HIRect& inBoxRect, PRBool inIsIndeterminate, @@ -306,6 +316,114 @@ nsNativeThemeCocoa::DrawTab(CGContextRef cgContext, const HIRect& inBoxRect, HIThemeDrawTab(&inBoxRect, &tdi, cgContext, HITHEME_ORIENTATION, NULL); } + +static UInt8 +ConvertToPressState(PRInt32 aButtonState, UInt8 aPressState) +{ + // If the button is pressed, return the press state passed in. Otherwise, return 0. + return ((aButtonState & NS_EVENT_STATE_ACTIVE) && (aButtonState & NS_EVENT_STATE_HOVER)) ? aPressState : 0; +} + + +void +nsNativeThemeCocoa::GetScrollbarPressStates(nsIFrame *aFrame, PRInt32 aButtonStates[]) +{ + static nsIContent::AttrValuesArray attributeValues[] = { + &nsWidgetAtoms::scrollbarUpTop, + &nsWidgetAtoms::scrollbarDownTop, + &nsWidgetAtoms::scrollbarUpBottom, + &nsWidgetAtoms::scrollbarDownBottom, + nsnull + }; + + // Get the state of any scrollbar buttons in our child frames + for (nsIFrame *childFrame = aFrame->GetFirstChild(nsnull); + childFrame; + childFrame = childFrame->GetNextSibling()) { + + nsIContent *childContent = childFrame->GetContent(); + if (!childContent) continue; + PRInt32 attrIndex = childContent->FindAttrValueIn(kNameSpaceID_None, nsWidgetAtoms::sbattr, + attributeValues, eCaseMatters); + if (attrIndex < 0) continue; + + PRInt32 currentState = GetContentState(childFrame, NS_THEME_BUTTON); + aButtonStates[attrIndex] = currentState; + } +} + + +void +nsNativeThemeCocoa::GetScrollbarDrawInfo(HIThemeTrackDrawInfo& aTdi, nsIFrame *aFrame, + const HIRect& aRect, PRBool aShouldGetButtonStates) +{ + PRInt32 curpos = CheckIntAttr(aFrame, nsWidgetAtoms::curpos); + PRInt32 minpos = CheckIntAttr(aFrame, nsWidgetAtoms::minpos); + PRInt32 maxpos = CheckIntAttr(aFrame, nsWidgetAtoms::maxpos); + + PRBool isHorizontal = aFrame->GetContent()->AttrValueIs(kNameSpaceID_None, nsWidgetAtoms::orient, + nsWidgetAtoms::horizontal, eCaseMatters); + PRBool isSmall = aFrame->GetStyleDisplay()->mAppearance == NS_THEME_SCROLLBAR_SMALL; + + aTdi.version = 0; + aTdi.kind = isSmall ? kThemeSmallScrollBar : kThemeMediumScrollBar; + aTdi.bounds = aRect; + aTdi.min = minpos; + aTdi.max = maxpos; + aTdi.value = curpos; + aTdi.attributes = kThemeTrackShowThumb; + if (isHorizontal) + aTdi.attributes |= kThemeTrackHorizontal; + + aTdi.trackInfo.scrollbar.viewsize = (SInt32)(isHorizontal ? (aRect.size.width) : (aRect.size.height)); + + // 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) { + 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) | + ConvertToPressState(buttonStates[2], kThemeBottomInsideArrowPressed) | + ConvertToPressState(buttonStates[3], kThemeBottomOutsideArrowPressed); + } else { + // It seems that unless all four buttons are showing, kThemeTopOutsideArrowPressed is the correct constant for + // the up scrollbar button. + aTdi.trackInfo.scrollbar.pressState = ConvertToPressState(buttonStates[0], kThemeTopOutsideArrowPressed) | + ConvertToPressState(buttonStates[2], kThemeTopOutsideArrowPressed) | + ConvertToPressState(buttonStates[3], kThemeBottomOutsideArrowPressed); + } + } +} + + +void +nsNativeThemeCocoa::DrawScrollbar(CGContextRef aCGContext, const HIRect& aBoxRect, nsIFrame *aFrame) +{ + HIThemeTrackDrawInfo tdi; + GetScrollbarDrawInfo(tdi, aFrame, aBoxRect, PR_TRUE); //True means we want the press states + ::HIThemeDrawTrack(&tdi, NULL, aCGContext, HITHEME_ORIENTATION); +} + + +nsIFrame* +nsNativeThemeCocoa::GetParentScrollbarFrame(nsIFrame *aFrame) +{ + // Walk our parents to find a scrollbar frame + nsIFrame *scrollbarFrame = aFrame; + do { + if (scrollbarFrame->GetType() == nsWidgetAtoms::scrollbarFrame) break; + } while ((scrollbarFrame = scrollbarFrame->GetParent())); + + // We return null if we can't find a parent scrollbar frame + return scrollbarFrame; +} + + NS_IMETHODIMP nsNativeThemeCocoa::DrawWidgetBackground(nsIRenderingContext* aContext, nsIFrame* aFrame, PRUint8 aWidgetType, const nsRect& aRect, @@ -627,18 +745,35 @@ nsNativeThemeCocoa::DrawWidgetBackground(nsIRenderingContext* aContext, nsIFrame // do nothing, drawn by scale break; - case NS_THEME_SCROLLBAR_GRIPPER_HORIZONTAL: - case NS_THEME_SCROLLBAR_GRIPPER_VERTICAL: + case NS_THEME_SCROLLBAR_SMALL: + case NS_THEME_SCROLLBAR: { + DrawScrollbar(cgContext, macRect, aFrame); + } + break; case NS_THEME_SCROLLBAR_THUMB_VERTICAL: case NS_THEME_SCROLLBAR_THUMB_HORIZONTAL: +#if SCROLLBARS_VISUAL_DEBUG + CGContextSetRGBFillColor(cgContext, 1.0, 1.0, 0, 0.6); + CGContextFillRect(cgContext, macRect); + break; +#endif case NS_THEME_SCROLLBAR_BUTTON_UP: + case NS_THEME_SCROLLBAR_BUTTON_LEFT: +#if SCROLLBARS_VISUAL_DEBUG + CGContextSetRGBFillColor(cgContext, 1.0, 0, 0, 0.6); + CGContextFillRect(cgContext, macRect); + break; +#endif case NS_THEME_SCROLLBAR_BUTTON_DOWN: + case NS_THEME_SCROLLBAR_BUTTON_RIGHT: +#if SCROLLBARS_VISUAL_DEBUG + CGContextSetRGBFillColor(cgContext, 0, 1.0, 0, 0.6); + CGContextFillRect(cgContext, macRect); + break; +#endif case NS_THEME_SCROLLBAR_TRACK_HORIZONTAL: case NS_THEME_SCROLLBAR_TRACK_VERTICAL: - case NS_THEME_SCROLLBAR_BUTTON_LEFT: - case NS_THEME_SCROLLBAR_BUTTON_RIGHT: - // Scrollbars are now native on mac, via nsNativeScrollbarFrame. - // So, this should never be called. + // do nothing, drawn by scrollbar break; case NS_THEME_LISTBOX: @@ -706,11 +841,36 @@ nsNativeThemeCocoa::GetWidgetBorder(nsIDeviceContext* aContext, 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); + + 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; + + if (isHorizontal) + aResult->SizeTo(endcapSize, 0, 0, 0); + else + aResult->SizeTo(0, endcapSize, 0, 0); + } + } + break; } return NS_OK; } + // return false here to indicate that CSS padding values should be used PRBool nsNativeThemeCocoa::GetWidgetPadding(nsIDeviceContext* aContext, @@ -746,6 +906,7 @@ nsNativeThemeCocoa::GetWidgetPadding(nsIDeviceContext* aContext, return PR_FALSE; } + PRBool nsNativeThemeCocoa::GetWidgetOverflow(nsIDeviceContext* aContext, nsIFrame* aFrame, PRUint8 aWidgetType, nsRect* aResult) @@ -780,6 +941,7 @@ nsNativeThemeCocoa::GetWidgetOverflow(nsIDeviceContext* aContext, nsIFrame* aFra return PR_FALSE; } + NS_IMETHODIMP nsNativeThemeCocoa::GetMinimumWidgetSize(nsIRenderingContext* aContext, nsIFrame* aFrame, @@ -934,16 +1096,46 @@ nsNativeThemeCocoa::GetMinimumWidgetSize(nsIRenderingContext* aContext, *aIsOverridable = PR_FALSE; break; } - - case NS_THEME_SCROLLBAR: - case NS_THEME_SCROLLBAR_BUTTON_UP: - case NS_THEME_SCROLLBAR_BUTTON_DOWN: - case NS_THEME_SCROLLBAR_BUTTON_LEFT: - case NS_THEME_SCROLLBAR_BUTTON_RIGHT: + + // Get the rect of the thumb from HITheme, so we can return it to Gecko, which has different ideas about + // how big the thumb should be. This is kind of a hack. case NS_THEME_SCROLLBAR_THUMB_HORIZONTAL: case NS_THEME_SCROLLBAR_THUMB_VERTICAL: - case NS_THEME_SCROLLBAR_GRIPPER_HORIZONTAL: - case NS_THEME_SCROLLBAR_GRIPPER_VERTICAL: + { + // Find our parent scrollbar frame. If we can't, abort. + nsIFrame *scrollbarFrame = GetParentScrollbarFrame(aFrame); + if (!scrollbarFrame) return NS_ERROR_FAILURE; + + // We need to get the device context to convert from app units :( + nsRect scrollbarRect = scrollbarFrame->GetRect(); + nsCOMPtr dctx; + aContext->GetDeviceContext(*getter_AddRefs(dctx)); + PRInt32 p2a = dctx->AppUnitsPerDevPixel(); + CGRect macRect = CGRectMake(NSAppUnitsToIntPixels(scrollbarRect.x, p2a), + NSAppUnitsToIntPixels(scrollbarRect.y, p2a), + NSAppUnitsToIntPixels(scrollbarRect.width, p2a), + NSAppUnitsToIntPixels(scrollbarRect.height, p2a)); + + // False here means not to get scrollbar button state information. + HIThemeTrackDrawInfo tdi; + GetScrollbarDrawInfo(tdi, scrollbarFrame, macRect, PR_FALSE); + + HIRect thumbRect; + ::HIThemeGetTrackPartBounds(&tdi, kControlIndicatorPart, &thumbRect); + + // HITheme is just lying to us, I guess... + PRInt32 thumbAdjust = ((scrollbarFrame->GetStyleDisplay()->mAppearance == NS_THEME_SCROLLBAR_SMALL) ? + 2 : 4); + + if (aWidgetType == NS_THEME_SCROLLBAR_THUMB_VERTICAL) + aResult->SizeTo(nscoord(thumbRect.size.width), nscoord(thumbRect.size.height - thumbAdjust)); + else + aResult->SizeTo(nscoord(thumbRect.size.width - thumbAdjust), nscoord(thumbRect.size.height)); + *aIsOverridable = PR_FALSE; + break; + } + + case NS_THEME_SCROLLBAR: case NS_THEME_SCROLLBAR_TRACK_VERTICAL: case NS_THEME_SCROLLBAR_TRACK_HORIZONTAL: { @@ -951,12 +1143,44 @@ nsNativeThemeCocoa::GetMinimumWidgetSize(nsIRenderingContext* aContext, // really doesn't matter if the scrollbar is vertical or horizontal // and the width metric is a really good metric for every piece // of the scrollbar. + + nsIFrame *scrollbarFrame = GetParentScrollbarFrame(aFrame); + if (!scrollbarFrame) return NS_ERROR_FAILURE; + + PRInt32 themeMetric = (scrollbarFrame->GetStyleDisplay()->mAppearance == NS_THEME_SCROLLBAR_SMALL) ? + kThemeMetricSmallScrollBarWidth : + kThemeMetricScrollBarWidth; SInt32 scrollbarWidth = 0; - ::GetThemeMetric(kThemeMetricScrollBarWidth, &scrollbarWidth); + ::GetThemeMetric(themeMetric, &scrollbarWidth); aResult->SizeTo(scrollbarWidth, scrollbarWidth); *aIsOverridable = PR_FALSE; break; } + + case NS_THEME_SCROLLBAR_BUTTON_UP: + case NS_THEME_SCROLLBAR_BUTTON_DOWN: + case NS_THEME_SCROLLBAR_BUTTON_LEFT: + case NS_THEME_SCROLLBAR_BUTTON_RIGHT: + { + nsIFrame *scrollbarFrame = GetParentScrollbarFrame(aFrame); + if (!scrollbarFrame) return NS_ERROR_FAILURE; + + // Since there is no NS_THEME_SCROLLBAR_BUTTON_UP_SMALL we need to ask the parent what appearance style it has. + PRInt32 themeMetric = (scrollbarFrame->GetStyleDisplay()->mAppearance == NS_THEME_SCROLLBAR_SMALL) ? + kThemeMetricSmallScrollBarWidth : + kThemeMetricScrollBarWidth; + SInt32 scrollbarWidth = 0; + ::GetThemeMetric(themeMetric, &scrollbarWidth); + + // It seems that for both sizes of scrollbar, the buttons are one pixel "longer". + if (aWidgetType == NS_THEME_SCROLLBAR_BUTTON_LEFT || aWidgetType == NS_THEME_SCROLLBAR_BUTTON_RIGHT) + aResult->SizeTo(scrollbarWidth+1, scrollbarWidth); + else + aResult->SizeTo(scrollbarWidth, scrollbarWidth+1); + + *aIsOverridable = PR_FALSE; + break; + } } return NS_OK; @@ -1092,8 +1316,6 @@ nsNativeThemeCocoa::ThemeSupportsWidget(nsPresContext* aPresContext, nsIFrame* a case NS_THEME_SCROLLBAR_BUTTON_RIGHT: case NS_THEME_SCROLLBAR_THUMB_HORIZONTAL: case NS_THEME_SCROLLBAR_THUMB_VERTICAL: - case NS_THEME_SCROLLBAR_GRIPPER_HORIZONTAL: - case NS_THEME_SCROLLBAR_GRIPPER_VERTICAL: case NS_THEME_SCROLLBAR_TRACK_VERTICAL: case NS_THEME_SCROLLBAR_TRACK_HORIZONTAL: retVal = PR_TRUE; diff --git a/mozilla/widget/src/cocoa/nsWidgetFactory.mm b/mozilla/widget/src/cocoa/nsWidgetFactory.mm index 228ec84430c..15cf7b90467 100644 --- a/mozilla/widget/src/cocoa/nsWidgetFactory.mm +++ b/mozilla/widget/src/cocoa/nsWidgetFactory.mm @@ -64,7 +64,6 @@ #include "nsSound.h" #include "nsIdleServiceX.h" -#include "nsNativeScrollbar.h" #include "nsScreenManagerCocoa.h" #include "nsDeviceContextSpecX.h" #include "nsPrintOptionsX.h" @@ -78,7 +77,6 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsLookAndFeel) NS_GENERIC_FACTORY_CONSTRUCTOR(nsMenuBarX) NS_GENERIC_FACTORY_CONSTRUCTOR(nsMenuX) NS_GENERIC_FACTORY_CONSTRUCTOR(nsMenuItemX) -NS_GENERIC_FACTORY_CONSTRUCTOR(nsNativeScrollbar) NS_GENERIC_FACTORY_CONSTRUCTOR(nsSound) NS_GENERIC_FACTORY_CONSTRUCTOR(nsTransferable) NS_GENERIC_FACTORY_CONSTRUCTOR(nsHTMLFormatConverter) @@ -167,10 +165,6 @@ static const nsModuleComponentInfo gComponents[] = NS_BIDIKEYBOARD_CID, "@mozilla.org/widget/bidikeyboard;1", nsBidiKeyboardConstructor }, - { "Native Scrollbar", - NS_NATIVESCROLLBAR_CID, - "@mozilla.org/widget/nativescrollbar;1", - nsNativeScrollbarConstructor }, { "Native Theme Renderer", NS_THEMERENDERER_CID, "@mozilla.org/chrome/chrome-native-theme;1", diff --git a/mozilla/widget/src/xpwidgets/nsWidgetAtomList.h b/mozilla/widget/src/xpwidgets/nsWidgetAtomList.h index 210a12937a5..16784e2d4d9 100644 --- a/mozilla/widget/src/xpwidgets/nsWidgetAtomList.h +++ b/mozilla/widget/src/xpwidgets/nsWidgetAtomList.h @@ -100,6 +100,12 @@ WIDGET_ATOM(orient, "orient") WIDGET_ATOM(radio, "radio") WIDGET_ATOM(readonly, "readonly") WIDGET_ATOM(Reload, "Reload") +WIDGET_ATOM(sbattr, "sbattr") +WIDGET_ATOM(scrollbarFrame, "ScrollbarFrame") +WIDGET_ATOM(scrollbarDownBottom, "scrollbar-down-bottom") +WIDGET_ATOM(scrollbarDownTop, "scrollbar-down-top") +WIDGET_ATOM(scrollbarUpBottom, "scrollbar-up-bottom") +WIDGET_ATOM(scrollbarUpTop, "scrollbar-up-top") WIDGET_ATOM(Search, "Search") WIDGET_ATOM(selected, "selected") WIDGET_ATOM(sortdirection, "sortDirection")