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
This commit is contained in:
joshmoz%gmail.com
2007-04-11 00:25:11 +00:00
parent fce267f89e
commit d5e3fc289e
14 changed files with 354 additions and 957 deletions

View File

@@ -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")

View File

@@ -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,

View File

@@ -99,6 +99,8 @@ public:
virtual PRBool IsContainingBlock() const;
virtual nsIAtom* GetType() const;
// nsIScrollbarFrame
virtual void SetScrollbarMediatorContent(nsIContent* aMediator);
virtual nsIScrollbarMediator* GetScrollbarMediator();

View File

@@ -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;
}
}

View File

@@ -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;
}

View File

@@ -105,7 +105,6 @@ CMMSRCS = \
nsChildView.mm \
nsWindowMap.mm \
nsWidgetFactory.mm \
nsNativeScrollbar.mm \
nsCursorManager.mm \
nsMacCursor.mm \
nsScreenCocoa.mm \

View File

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

View File

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

View File

@@ -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 <Carbon/Carbon.h>
#import <Cocoa/Cocoa.h>
#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<mozView>
{
// 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_

View File

@@ -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 <mark@moxienet.com>
* Stuart Morgan <stuart.morgan@alumni.case.edu>
* Josh Aas <josh@mozilla.com>
*
* 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 <outliner> 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

View File

@@ -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_

View File

@@ -22,6 +22,7 @@
* Contributor(s):
* Vladimir Vukicevic <vladimir@pobox.com> (HITheme rewrite)
* Josh Aas <josh@mozilla.com>
* Colin Barrett <cbarrett@mozilla.com>
*
* 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<nsIDeviceContext> 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;

View File

@@ -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",

View File

@@ -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")