1643ca7872b450ea4efacab6188849e5aac2ba161Steve Block/*
2643ca7872b450ea4efacab6188849e5aac2ba161Steve Block * Copyright (C) 2008 Apple Inc. All Rights Reserved.
3643ca7872b450ea4efacab6188849e5aac2ba161Steve Block * Copyright (C) 2009 Google Inc. All Rights Reserved.
4643ca7872b450ea4efacab6188849e5aac2ba161Steve Block *
5643ca7872b450ea4efacab6188849e5aac2ba161Steve Block * Redistribution and use in source and binary forms, with or without
6643ca7872b450ea4efacab6188849e5aac2ba161Steve Block * modification, are permitted provided that the following conditions
7643ca7872b450ea4efacab6188849e5aac2ba161Steve Block * are met:
8643ca7872b450ea4efacab6188849e5aac2ba161Steve Block * 1. Redistributions of source code must retain the above copyright
9643ca7872b450ea4efacab6188849e5aac2ba161Steve Block *    notice, this list of conditions and the following disclaimer.
10643ca7872b450ea4efacab6188849e5aac2ba161Steve Block * 2. Redistributions in binary form must reproduce the above copyright
11643ca7872b450ea4efacab6188849e5aac2ba161Steve Block *    notice, this list of conditions and the following disclaimer in the
12643ca7872b450ea4efacab6188849e5aac2ba161Steve Block *    documentation and/or other materials provided with the distribution.
13643ca7872b450ea4efacab6188849e5aac2ba161Steve Block *
14643ca7872b450ea4efacab6188849e5aac2ba161Steve Block * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
15643ca7872b450ea4efacab6188849e5aac2ba161Steve Block * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16643ca7872b450ea4efacab6188849e5aac2ba161Steve Block * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17643ca7872b450ea4efacab6188849e5aac2ba161Steve Block * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
18643ca7872b450ea4efacab6188849e5aac2ba161Steve Block * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19643ca7872b450ea4efacab6188849e5aac2ba161Steve Block * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20643ca7872b450ea4efacab6188849e5aac2ba161Steve Block * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21643ca7872b450ea4efacab6188849e5aac2ba161Steve Block * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22643ca7872b450ea4efacab6188849e5aac2ba161Steve Block * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23643ca7872b450ea4efacab6188849e5aac2ba161Steve Block * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24643ca7872b450ea4efacab6188849e5aac2ba161Steve Block * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25643ca7872b450ea4efacab6188849e5aac2ba161Steve Block */
26643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
27643ca7872b450ea4efacab6188849e5aac2ba161Steve Block#include "config.h"
28643ca7872b450ea4efacab6188849e5aac2ba161Steve Block#include "ScrollbarThemeChromiumMac.h"
29643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
30cad810f21b803229eb11403f9209855525a25d57Steve Block#include "FrameView.h"
31643ca7872b450ea4efacab6188849e5aac2ba161Steve Block#include "ImageBuffer.h"
32ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch#include "PlatformBridge.h"
33643ca7872b450ea4efacab6188849e5aac2ba161Steve Block#include "PlatformMouseEvent.h"
34643ca7872b450ea4efacab6188849e5aac2ba161Steve Block#include "ScrollView.h"
35643ca7872b450ea4efacab6188849e5aac2ba161Steve Block#include <Carbon/Carbon.h>
36643ca7872b450ea4efacab6188849e5aac2ba161Steve Block#include <wtf/StdLibExtras.h>
37643ca7872b450ea4efacab6188849e5aac2ba161Steve Block#include <wtf/UnusedParam.h>
38643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
39cad810f21b803229eb11403f9209855525a25d57Steve Block
40643ca7872b450ea4efacab6188849e5aac2ba161Steve Block// FIXME: There are repainting problems due to Aqua scroll bar buttons' visual overflow.
41643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
42643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockusing namespace std;
43643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockusing namespace WebCore;
44643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
45643ca7872b450ea4efacab6188849e5aac2ba161Steve Block// This file (and its associated .h file) is a clone of ScrollbarThemeMac.mm.
46643ca7872b450ea4efacab6188849e5aac2ba161Steve Block// Because we want to draw tickmarks in the scrollbar, we must maintain a fork.
47643ca7872b450ea4efacab6188849e5aac2ba161Steve Block// Please maintain this file by performing parallel changes to it.
48643ca7872b450ea4efacab6188849e5aac2ba161Steve Block//
49643ca7872b450ea4efacab6188849e5aac2ba161Steve Block// The only changes from ScrollbarThemeMac should be:
50643ca7872b450ea4efacab6188849e5aac2ba161Steve Block// - The classname change from ScrollbarThemeMac to ScrollbarThemeChromiumMac.
51643ca7872b450ea4efacab6188849e5aac2ba161Steve Block// - In paint() the code to paint the track, tickmarks, and thumb separately.
52cad810f21b803229eb11403f9209855525a25d57Steve Block// - In paint() the thumb is drawn via ChromeBridge/WebThemeEngine.
53643ca7872b450ea4efacab6188849e5aac2ba161Steve Block//
54643ca7872b450ea4efacab6188849e5aac2ba161Steve Block// For all other differences, if it was introduced in this file, then the
55643ca7872b450ea4efacab6188849e5aac2ba161Steve Block// maintainer forgot to include it in the list; otherwise it is an update that
56643ca7872b450ea4efacab6188849e5aac2ba161Steve Block// should have been applied to this file but was not.
57643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
58643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockstatic HashSet<Scrollbar*>* gScrollbars;
59643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
60643ca7872b450ea4efacab6188849e5aac2ba161Steve Block@interface ScrollbarPrefsObserver : NSObject
61643ca7872b450ea4efacab6188849e5aac2ba161Steve Block{
62643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
63643ca7872b450ea4efacab6188849e5aac2ba161Steve Block}
64643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
65643ca7872b450ea4efacab6188849e5aac2ba161Steve Block+ (void)registerAsObserver;
66643ca7872b450ea4efacab6188849e5aac2ba161Steve Block+ (void)appearancePrefsChanged:(NSNotification*)theNotification;
67643ca7872b450ea4efacab6188849e5aac2ba161Steve Block+ (void)behaviorPrefsChanged:(NSNotification*)theNotification;
68643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
69643ca7872b450ea4efacab6188849e5aac2ba161Steve Block@end
70643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
71643ca7872b450ea4efacab6188849e5aac2ba161Steve Block@implementation ScrollbarPrefsObserver
72643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
73643ca7872b450ea4efacab6188849e5aac2ba161Steve Block+ (void)appearancePrefsChanged:(NSNotification*)unusedNotification
74643ca7872b450ea4efacab6188849e5aac2ba161Steve Block{
75643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    UNUSED_PARAM(unusedNotification);
76643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
77643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    static_cast<ScrollbarThemeChromiumMac*>(ScrollbarTheme::nativeTheme())->preferencesChanged();
78643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    if (!gScrollbars)
79643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        return;
80643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    HashSet<Scrollbar*>::iterator end = gScrollbars->end();
81643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    for (HashSet<Scrollbar*>::iterator it = gScrollbars->begin(); it != end; ++it) {
82643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        (*it)->styleChanged();
83643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        (*it)->invalidate();
84643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    }
85643ca7872b450ea4efacab6188849e5aac2ba161Steve Block}
86643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
87643ca7872b450ea4efacab6188849e5aac2ba161Steve Block+ (void)behaviorPrefsChanged:(NSNotification*)unusedNotification
88643ca7872b450ea4efacab6188849e5aac2ba161Steve Block{
89643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    UNUSED_PARAM(unusedNotification);
90643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
91643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    static_cast<ScrollbarThemeChromiumMac*>(ScrollbarTheme::nativeTheme())->preferencesChanged();
92643ca7872b450ea4efacab6188849e5aac2ba161Steve Block}
93643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
94643ca7872b450ea4efacab6188849e5aac2ba161Steve Block+ (void)registerAsObserver
95643ca7872b450ea4efacab6188849e5aac2ba161Steve Block{
96643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    [[NSDistributedNotificationCenter defaultCenter] addObserver:self selector:@selector(appearancePrefsChanged:) name:@"AppleAquaScrollBarVariantChanged" object:nil suspensionBehavior:NSNotificationSuspensionBehaviorDeliverImmediately];
97643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    [[NSDistributedNotificationCenter defaultCenter] addObserver:self selector:@selector(behaviorPrefsChanged:) name:@"AppleNoRedisplayAppearancePreferenceChanged" object:nil suspensionBehavior:NSNotificationSuspensionBehaviorCoalesce];
98643ca7872b450ea4efacab6188849e5aac2ba161Steve Block}
99643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
100643ca7872b450ea4efacab6188849e5aac2ba161Steve Block@end
101643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
102643ca7872b450ea4efacab6188849e5aac2ba161Steve Blocknamespace WebCore {
103643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
104643ca7872b450ea4efacab6188849e5aac2ba161Steve BlockScrollbarTheme* ScrollbarTheme::nativeTheme()
105643ca7872b450ea4efacab6188849e5aac2ba161Steve Block{
106643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    DEFINE_STATIC_LOCAL(ScrollbarThemeChromiumMac, theme, ());
107643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    return &theme;
108643ca7872b450ea4efacab6188849e5aac2ba161Steve Block}
109643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
110643ca7872b450ea4efacab6188849e5aac2ba161Steve Block// FIXME: Get these numbers from CoreUI.
111643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockstatic int cScrollbarThickness[] = { 15, 11 };
112643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockstatic int cRealButtonLength[] = { 28, 21 };
113643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockstatic int cButtonInset[] = { 14, 11 };
114643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockstatic int cButtonHitInset[] = { 3, 2 };
115643ca7872b450ea4efacab6188849e5aac2ba161Steve Block// cRealButtonLength - cButtonInset
116643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockstatic int cButtonLength[] = { 14, 10 };
117643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockstatic int cThumbMinLength[] = { 26, 20 };
118643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
119643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockstatic int cOuterButtonLength[] = { 16, 14 }; // The outer button in a double button pair is a bit bigger.
120643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockstatic int cOuterButtonOverlap = 2;
121643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
122643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockstatic float gInitialButtonDelay = 0.5f;
123643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockstatic float gAutoscrollButtonDelay = 0.05f;
124643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockstatic bool gJumpOnTrackClick = false;
125643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockstatic ScrollbarButtonsPlacement gButtonPlacement = ScrollbarButtonsDoubleEnd;
126643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
127643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockstatic void updateArrowPlacement()
128643ca7872b450ea4efacab6188849e5aac2ba161Steve Block{
129643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    NSString *buttonPlacement = [[NSUserDefaults standardUserDefaults] objectForKey:@"AppleScrollBarVariant"];
130643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    if ([buttonPlacement isEqualToString:@"Single"])
131643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        gButtonPlacement = ScrollbarButtonsSingle;
132643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    else if ([buttonPlacement isEqualToString:@"DoubleMin"])
133643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        gButtonPlacement = ScrollbarButtonsDoubleStart;
134643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    else if ([buttonPlacement isEqualToString:@"DoubleBoth"])
135643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        gButtonPlacement = ScrollbarButtonsDoubleBoth;
136643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    else
137643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        gButtonPlacement = ScrollbarButtonsDoubleEnd; // The default is ScrollbarButtonsDoubleEnd.
138643ca7872b450ea4efacab6188849e5aac2ba161Steve Block}
139643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
140643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockvoid ScrollbarThemeChromiumMac::registerScrollbar(Scrollbar* scrollbar)
141643ca7872b450ea4efacab6188849e5aac2ba161Steve Block{
142643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    if (!gScrollbars)
143643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        gScrollbars = new HashSet<Scrollbar*>;
144643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    gScrollbars->add(scrollbar);
145643ca7872b450ea4efacab6188849e5aac2ba161Steve Block}
146643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
147643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockvoid ScrollbarThemeChromiumMac::unregisterScrollbar(Scrollbar* scrollbar)
148643ca7872b450ea4efacab6188849e5aac2ba161Steve Block{
149643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    gScrollbars->remove(scrollbar);
150643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    if (gScrollbars->isEmpty()) {
151643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        delete gScrollbars;
152643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        gScrollbars = 0;
153643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    }
154643ca7872b450ea4efacab6188849e5aac2ba161Steve Block}
155643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
156643ca7872b450ea4efacab6188849e5aac2ba161Steve BlockScrollbarThemeChromiumMac::ScrollbarThemeChromiumMac()
157643ca7872b450ea4efacab6188849e5aac2ba161Steve Block{
158643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    static bool initialized;
159643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    if (!initialized) {
160643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        initialized = true;
161643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        [ScrollbarPrefsObserver registerAsObserver];
162643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        preferencesChanged();
163643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    }
164643ca7872b450ea4efacab6188849e5aac2ba161Steve Block}
165643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
166643ca7872b450ea4efacab6188849e5aac2ba161Steve BlockScrollbarThemeChromiumMac::~ScrollbarThemeChromiumMac()
167643ca7872b450ea4efacab6188849e5aac2ba161Steve Block{
168643ca7872b450ea4efacab6188849e5aac2ba161Steve Block}
169643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
170643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockvoid ScrollbarThemeChromiumMac::preferencesChanged()
171643ca7872b450ea4efacab6188849e5aac2ba161Steve Block{
172643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
173643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    [defaults synchronize];
174643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    updateArrowPlacement();
175643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    gInitialButtonDelay = [defaults floatForKey:@"NSScrollerButtonDelay"];
176643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    gAutoscrollButtonDelay = [defaults floatForKey:@"NSScrollerButtonPeriod"];
177643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    gJumpOnTrackClick = [defaults boolForKey:@"AppleScrollerPagingBehavior"];
178643ca7872b450ea4efacab6188849e5aac2ba161Steve Block}
179643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
180643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockint ScrollbarThemeChromiumMac::scrollbarThickness(ScrollbarControlSize controlSize)
181643ca7872b450ea4efacab6188849e5aac2ba161Steve Block{
182643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    return cScrollbarThickness[controlSize];
183643ca7872b450ea4efacab6188849e5aac2ba161Steve Block}
184643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
185643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockdouble ScrollbarThemeChromiumMac::initialAutoscrollTimerDelay()
186643ca7872b450ea4efacab6188849e5aac2ba161Steve Block{
187643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    return gInitialButtonDelay;
188643ca7872b450ea4efacab6188849e5aac2ba161Steve Block}
189643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
190643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockdouble ScrollbarThemeChromiumMac::autoscrollTimerDelay()
191643ca7872b450ea4efacab6188849e5aac2ba161Steve Block{
192643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    return gAutoscrollButtonDelay;
193643ca7872b450ea4efacab6188849e5aac2ba161Steve Block}
194643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
195643ca7872b450ea4efacab6188849e5aac2ba161Steve BlockScrollbarButtonsPlacement ScrollbarThemeChromiumMac::buttonsPlacement() const
196643ca7872b450ea4efacab6188849e5aac2ba161Steve Block{
197643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    return gButtonPlacement;
198643ca7872b450ea4efacab6188849e5aac2ba161Steve Block}
199643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
200643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockbool ScrollbarThemeChromiumMac::hasButtons(Scrollbar* scrollbar)
201643ca7872b450ea4efacab6188849e5aac2ba161Steve Block{
202643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    return scrollbar->enabled() && (scrollbar->orientation() == HorizontalScrollbar ?
203643ca7872b450ea4efacab6188849e5aac2ba161Steve Block             scrollbar->width() :
204643ca7872b450ea4efacab6188849e5aac2ba161Steve Block             scrollbar->height()) >= 2 * (cRealButtonLength[scrollbar->controlSize()] - cButtonHitInset[scrollbar->controlSize()]);
205643ca7872b450ea4efacab6188849e5aac2ba161Steve Block}
206643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
207643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockbool ScrollbarThemeChromiumMac::hasThumb(Scrollbar* scrollbar)
208643ca7872b450ea4efacab6188849e5aac2ba161Steve Block{
209643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    return scrollbar->enabled() && (scrollbar->orientation() == HorizontalScrollbar ?
210643ca7872b450ea4efacab6188849e5aac2ba161Steve Block             scrollbar->width() :
211643ca7872b450ea4efacab6188849e5aac2ba161Steve Block             scrollbar->height()) >= 2 * cButtonInset[scrollbar->controlSize()] + cThumbMinLength[scrollbar->controlSize()] + 1;
212643ca7872b450ea4efacab6188849e5aac2ba161Steve Block}
213643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
214643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockstatic IntRect buttonRepaintRect(const IntRect& buttonRect, ScrollbarOrientation orientation, ScrollbarControlSize controlSize, bool start)
215643ca7872b450ea4efacab6188849e5aac2ba161Steve Block{
216643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    IntRect paintRect(buttonRect);
217643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    if (orientation == HorizontalScrollbar) {
218643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        paintRect.setWidth(cRealButtonLength[controlSize]);
219643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        if (!start)
220643ca7872b450ea4efacab6188849e5aac2ba161Steve Block            paintRect.setX(buttonRect.x() - (cRealButtonLength[controlSize] - buttonRect.width()));
221643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    } else {
222643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        paintRect.setHeight(cRealButtonLength[controlSize]);
223643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        if (!start)
224643ca7872b450ea4efacab6188849e5aac2ba161Steve Block            paintRect.setY(buttonRect.y() - (cRealButtonLength[controlSize] - buttonRect.height()));
225643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    }
226643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
227643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    return paintRect;
228643ca7872b450ea4efacab6188849e5aac2ba161Steve Block}
229643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
230643ca7872b450ea4efacab6188849e5aac2ba161Steve BlockIntRect ScrollbarThemeChromiumMac::backButtonRect(Scrollbar* scrollbar, ScrollbarPart part, bool painting)
231643ca7872b450ea4efacab6188849e5aac2ba161Steve Block{
232643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    IntRect result;
233643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
234643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    if (part == BackButtonStartPart && (buttonsPlacement() == ScrollbarButtonsNone || buttonsPlacement() == ScrollbarButtonsDoubleEnd))
235643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        return result;
236643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
237643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    if (part == BackButtonEndPart && (buttonsPlacement() == ScrollbarButtonsNone || buttonsPlacement() == ScrollbarButtonsDoubleStart || buttonsPlacement() == ScrollbarButtonsSingle))
238643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        return result;
239643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
240643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    int thickness = scrollbarThickness(scrollbar->controlSize());
241643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    bool outerButton = part == BackButtonStartPart && (buttonsPlacement() == ScrollbarButtonsDoubleStart || buttonsPlacement() == ScrollbarButtonsDoubleBoth);
242643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    if (outerButton) {
243643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        if (scrollbar->orientation() == HorizontalScrollbar)
244643ca7872b450ea4efacab6188849e5aac2ba161Steve Block            result = IntRect(scrollbar->x(), scrollbar->y(), cOuterButtonLength[scrollbar->controlSize()] + painting ? cOuterButtonOverlap : 0, thickness);
245643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        else
246643ca7872b450ea4efacab6188849e5aac2ba161Steve Block            result = IntRect(scrollbar->x(), scrollbar->y(), thickness, cOuterButtonLength[scrollbar->controlSize()] + painting ? cOuterButtonOverlap : 0);
247643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        return result;
248643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    }
249643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
250643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // Our repaint rect is slightly larger, since we are a button that is adjacent to the track.
251643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    if (scrollbar->orientation() == HorizontalScrollbar) {
252643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        int start = part == BackButtonStartPart ? scrollbar->x() : scrollbar->x() + scrollbar->width() - cOuterButtonLength[scrollbar->controlSize()] - cButtonLength[scrollbar->controlSize()];
253643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        result = IntRect(start, scrollbar->y(), cButtonLength[scrollbar->controlSize()], thickness);
254643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    } else {
255643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        int start = part == BackButtonStartPart ? scrollbar->y() : scrollbar->y() + scrollbar->height() - cOuterButtonLength[scrollbar->controlSize()] - cButtonLength[scrollbar->controlSize()];
256643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        result = IntRect(scrollbar->x(), start, thickness, cButtonLength[scrollbar->controlSize()]);
257643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    }
258643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
259643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    if (painting)
260643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        return buttonRepaintRect(result, scrollbar->orientation(), scrollbar->controlSize(), part == BackButtonStartPart);
261643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    return result;
262643ca7872b450ea4efacab6188849e5aac2ba161Steve Block}
263643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
264643ca7872b450ea4efacab6188849e5aac2ba161Steve BlockIntRect ScrollbarThemeChromiumMac::forwardButtonRect(Scrollbar* scrollbar, ScrollbarPart part, bool painting)
265643ca7872b450ea4efacab6188849e5aac2ba161Steve Block{
266643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    IntRect result;
267643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
268643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    if (part == ForwardButtonEndPart && (buttonsPlacement() == ScrollbarButtonsNone || buttonsPlacement() == ScrollbarButtonsDoubleStart))
269643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        return result;
270643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
271643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    if (part == ForwardButtonStartPart && (buttonsPlacement() == ScrollbarButtonsNone || buttonsPlacement() == ScrollbarButtonsDoubleEnd || buttonsPlacement() == ScrollbarButtonsSingle))
272643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        return result;
273643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
274643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    int thickness = scrollbarThickness(scrollbar->controlSize());
275643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    int outerButtonLength = cOuterButtonLength[scrollbar->controlSize()];
276643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    int buttonLength = cButtonLength[scrollbar->controlSize()];
277643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
278643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    bool outerButton = part == ForwardButtonEndPart && (buttonsPlacement() == ScrollbarButtonsDoubleEnd || buttonsPlacement() == ScrollbarButtonsDoubleBoth);
279643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    if (outerButton) {
280643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        if (scrollbar->orientation() == HorizontalScrollbar) {
281643ca7872b450ea4efacab6188849e5aac2ba161Steve Block            result = IntRect(scrollbar->x() + scrollbar->width() - outerButtonLength, scrollbar->y(), outerButtonLength, thickness);
282643ca7872b450ea4efacab6188849e5aac2ba161Steve Block            if (painting)
283643ca7872b450ea4efacab6188849e5aac2ba161Steve Block                result.inflateX(cOuterButtonOverlap);
284643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        } else {
285643ca7872b450ea4efacab6188849e5aac2ba161Steve Block            result = IntRect(scrollbar->x(), scrollbar->y() + scrollbar->height() - outerButtonLength, thickness, outerButtonLength);
286643ca7872b450ea4efacab6188849e5aac2ba161Steve Block            if (painting)
287643ca7872b450ea4efacab6188849e5aac2ba161Steve Block                result.inflateY(cOuterButtonOverlap);
288643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        }
289643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        return result;
290643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    }
291643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
292643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    if (scrollbar->orientation() == HorizontalScrollbar) {
293643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        int start = part == ForwardButtonEndPart ? scrollbar->x() + scrollbar->width() - buttonLength : scrollbar->x() + outerButtonLength;
294643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        result = IntRect(start, scrollbar->y(), buttonLength, thickness);
295643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    } else {
296643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        int start = part == ForwardButtonEndPart ? scrollbar->y() + scrollbar->height() - buttonLength : scrollbar->y() + outerButtonLength;
297643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        result = IntRect(scrollbar->x(), start, thickness, buttonLength);
298643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    }
299643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    if (painting)
300643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        return buttonRepaintRect(result, scrollbar->orientation(), scrollbar->controlSize(), part == ForwardButtonStartPart);
301643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    return result;
302643ca7872b450ea4efacab6188849e5aac2ba161Steve Block}
303643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
304643ca7872b450ea4efacab6188849e5aac2ba161Steve BlockIntRect ScrollbarThemeChromiumMac::trackRect(Scrollbar* scrollbar, bool painting)
305643ca7872b450ea4efacab6188849e5aac2ba161Steve Block{
306643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    if (painting || !hasButtons(scrollbar))
307643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        return scrollbar->frameRect();
308643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
309643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    IntRect result;
310643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    int thickness = scrollbarThickness(scrollbar->controlSize());
311643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    int startWidth = 0;
312643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    int endWidth = 0;
313643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    int outerButtonLength = cOuterButtonLength[scrollbar->controlSize()];
314643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    int buttonLength = cButtonLength[scrollbar->controlSize()];
315643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    int doubleButtonLength = outerButtonLength + buttonLength;
316643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    switch (buttonsPlacement()) {
317643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        case ScrollbarButtonsSingle:
318643ca7872b450ea4efacab6188849e5aac2ba161Steve Block            startWidth = buttonLength;
319643ca7872b450ea4efacab6188849e5aac2ba161Steve Block            endWidth = buttonLength;
320643ca7872b450ea4efacab6188849e5aac2ba161Steve Block            break;
321643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        case ScrollbarButtonsDoubleStart:
322643ca7872b450ea4efacab6188849e5aac2ba161Steve Block            startWidth = doubleButtonLength;
323643ca7872b450ea4efacab6188849e5aac2ba161Steve Block            break;
324643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        case ScrollbarButtonsDoubleEnd:
325643ca7872b450ea4efacab6188849e5aac2ba161Steve Block            endWidth = doubleButtonLength;
326643ca7872b450ea4efacab6188849e5aac2ba161Steve Block            break;
327643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        case ScrollbarButtonsDoubleBoth:
328643ca7872b450ea4efacab6188849e5aac2ba161Steve Block            startWidth = doubleButtonLength;
329643ca7872b450ea4efacab6188849e5aac2ba161Steve Block            endWidth = doubleButtonLength;
330643ca7872b450ea4efacab6188849e5aac2ba161Steve Block            break;
331643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        default:
332643ca7872b450ea4efacab6188849e5aac2ba161Steve Block            break;
333643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    }
334643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
335643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    int totalWidth = startWidth + endWidth;
336643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    if (scrollbar->orientation() == HorizontalScrollbar)
337643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        return IntRect(scrollbar->x() + startWidth, scrollbar->y(), scrollbar->width() - totalWidth, thickness);
338643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    return IntRect(scrollbar->x(), scrollbar->y() + startWidth, thickness, scrollbar->height() - totalWidth);
339643ca7872b450ea4efacab6188849e5aac2ba161Steve Block}
340643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
341643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockint ScrollbarThemeChromiumMac::minimumThumbLength(Scrollbar* scrollbar)
342643ca7872b450ea4efacab6188849e5aac2ba161Steve Block{
343643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    return cThumbMinLength[scrollbar->controlSize()];
344643ca7872b450ea4efacab6188849e5aac2ba161Steve Block}
345643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
346643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockbool ScrollbarThemeChromiumMac::shouldCenterOnThumb(Scrollbar*, const PlatformMouseEvent& evt)
347643ca7872b450ea4efacab6188849e5aac2ba161Steve Block{
348643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    if (evt.button() != LeftButton)
349643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        return false;
350643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    if (gJumpOnTrackClick)
351643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        return !evt.altKey();
352643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    return evt.altKey();
353643ca7872b450ea4efacab6188849e5aac2ba161Steve Block}
354643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
355643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockstatic int scrollbarPartToHIPressedState(ScrollbarPart part)
356643ca7872b450ea4efacab6188849e5aac2ba161Steve Block{
357643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    switch (part) {
358643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        case BackButtonStartPart:
359643ca7872b450ea4efacab6188849e5aac2ba161Steve Block            return kThemeTopOutsideArrowPressed;
360643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        case BackButtonEndPart:
361643ca7872b450ea4efacab6188849e5aac2ba161Steve Block            return kThemeTopOutsideArrowPressed; // This does not make much sense.  For some reason the outside constant is required.
362643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        case ForwardButtonStartPart:
363643ca7872b450ea4efacab6188849e5aac2ba161Steve Block            return kThemeTopInsideArrowPressed;
364643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        case ForwardButtonEndPart:
365643ca7872b450ea4efacab6188849e5aac2ba161Steve Block            return kThemeBottomOutsideArrowPressed;
366643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        case ThumbPart:
367643ca7872b450ea4efacab6188849e5aac2ba161Steve Block            return kThemeThumbPressed;
368643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        default:
369643ca7872b450ea4efacab6188849e5aac2ba161Steve Block            return 0;
370643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    }
371643ca7872b450ea4efacab6188849e5aac2ba161Steve Block}
372643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
373ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdochstatic PlatformBridge::ThemePaintState scrollbarStateToThemeState(Scrollbar* scrollbar) {
374cad810f21b803229eb11403f9209855525a25d57Steve Block    if (!scrollbar->enabled())
375ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        return PlatformBridge::StateDisabled;
376ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch    if (!scrollbar->scrollableArea()->isActive())
377ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        return PlatformBridge::StateInactive;
378cad810f21b803229eb11403f9209855525a25d57Steve Block    if (scrollbar->pressedPart() == ThumbPart)
379ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        return PlatformBridge::StatePressed;
380cad810f21b803229eb11403f9209855525a25d57Steve Block
381ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch    return PlatformBridge::StateActive;
382cad810f21b803229eb11403f9209855525a25d57Steve Block}
383cad810f21b803229eb11403f9209855525a25d57Steve Block
384643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockbool ScrollbarThemeChromiumMac::paint(Scrollbar* scrollbar, GraphicsContext* context, const IntRect& damageRect)
385643ca7872b450ea4efacab6188849e5aac2ba161Steve Block{
386643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    HIThemeTrackDrawInfo trackInfo;
387643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    trackInfo.version = 0;
388643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    trackInfo.kind = scrollbar->controlSize() == RegularScrollbar ? kThemeMediumScrollBar : kThemeSmallScrollBar;
389643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    trackInfo.bounds = scrollbar->frameRect();
390643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    trackInfo.min = 0;
391643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    trackInfo.max = scrollbar->maximum();
392643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    trackInfo.value = scrollbar->currentPos();
393d0825bca7fe65beaee391d30da42e937db621564Steve Block    trackInfo.trackInfo.scrollbar.viewsize = scrollbar->visibleSize();
394643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    trackInfo.attributes = 0;
395643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    if (scrollbar->orientation() == HorizontalScrollbar)
396643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        trackInfo.attributes |= kThemeTrackHorizontal;
397643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
398643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    if (!scrollbar->enabled())
399643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        trackInfo.enableState = kThemeTrackDisabled;
400643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    else
401ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        trackInfo.enableState = scrollbar->scrollableArea()->isActive() ? kThemeTrackActive : kThemeTrackInactive;
402643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
403643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    if (!hasButtons(scrollbar))
404643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        trackInfo.enableState = kThemeTrackNothingToScroll;
405643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    trackInfo.trackInfo.scrollbar.pressState = scrollbarPartToHIPressedState(scrollbar->pressedPart());
406643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
407643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    CGAffineTransform currentCTM = CGContextGetCTM(context->platformContext());
408643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
409643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // The Aqua scrollbar is buggy when rotated and scaled.  We will just draw into a bitmap if we detect a scale or rotation.
410643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    bool canDrawDirectly = currentCTM.a == 1.0f && currentCTM.b == 0.0f && currentCTM.c == 0.0f && (currentCTM.d == 1.0f || currentCTM.d == -1.0f);
411643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    GraphicsContext* drawingContext = context;
412643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    OwnPtr<ImageBuffer> imageBuffer;
413643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    if (!canDrawDirectly) {
414643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        trackInfo.bounds = IntRect(IntPoint(), scrollbar->frameRect().size());
415643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
416643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        IntRect bufferRect(scrollbar->frameRect());
417643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        bufferRect.intersect(damageRect);
418643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        bufferRect.move(-scrollbar->frameRect().x(), -scrollbar->frameRect().y());
419643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
420643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        imageBuffer = ImageBuffer::create(bufferRect.size());
421643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        if (!imageBuffer)
422643ca7872b450ea4efacab6188849e5aac2ba161Steve Block            return true;
423643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
424643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        drawingContext = imageBuffer->context();
425643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    }
426643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
427643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // Draw thumbless.
428643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    HIThemeDrawTrack(&trackInfo, 0, drawingContext->platformContext(), kHIThemeOrientationNormal);
429643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
430643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    Vector<IntRect> tickmarks;
431ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch    scrollbar->scrollableArea()->getTickmarks(tickmarks);
432643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    if (scrollbar->orientation() == VerticalScrollbar && tickmarks.size()) {
433643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        drawingContext->save();
434643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        drawingContext->setShouldAntialias(false);
435a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        drawingContext->setStrokeColor(Color(0xCC, 0xAA, 0x00, 0xFF), ColorSpaceDeviceRGB);
436a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        drawingContext->setFillColor(Color(0xFF, 0xDD, 0x00, 0xFF), ColorSpaceDeviceRGB);
437643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
438643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        IntRect thumbArea = trackRect(scrollbar, false);
439643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        if (!canDrawDirectly) {
440643ca7872b450ea4efacab6188849e5aac2ba161Steve Block            thumbArea.setX(0);
441643ca7872b450ea4efacab6188849e5aac2ba161Steve Block            thumbArea.setY(0);
442643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        }
443643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        // The ends are rounded and the thumb doesn't go there.
444643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        thumbArea.inflateY(-thumbArea.width());
445643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
446643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        for (Vector<IntRect>::const_iterator i = tickmarks.begin(); i != tickmarks.end(); ++i) {
447643ca7872b450ea4efacab6188849e5aac2ba161Steve Block            // Calculate how far down (in %) the tick-mark should appear.
448643ca7872b450ea4efacab6188849e5aac2ba161Steve Block            const float percent = static_cast<float>(i->y()) / scrollbar->totalSize();
449643ca7872b450ea4efacab6188849e5aac2ba161Steve Block            if (percent < 0.0 || percent > 1.0)
450643ca7872b450ea4efacab6188849e5aac2ba161Steve Block              continue;
451643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
452643ca7872b450ea4efacab6188849e5aac2ba161Steve Block            // Calculate how far down (in pixels) the tick-mark should appear.
4532fc2651226baac27029e38c9d6ef883fa32084dbSteve Block            const int yPos = static_cast<int>((thumbArea.y() + (thumbArea.height() * percent))) & ~1;
454643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
455643ca7872b450ea4efacab6188849e5aac2ba161Steve Block            // Paint.
456643ca7872b450ea4efacab6188849e5aac2ba161Steve Block            const int indent = 2;
4572fc2651226baac27029e38c9d6ef883fa32084dbSteve Block            FloatRect tickRect(thumbArea.x() + indent, yPos, thumbArea.width() - 2 * indent - 1, 2);
458643ca7872b450ea4efacab6188849e5aac2ba161Steve Block            drawingContext->fillRect(tickRect);
459643ca7872b450ea4efacab6188849e5aac2ba161Steve Block            drawingContext->strokeRect(tickRect, 1);
460643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        }
461643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
462643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        drawingContext->restore();
463643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    }
464643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
465643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    if (hasThumb(scrollbar)) {
466ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        PlatformBridge::ThemePaintScrollbarInfo scrollbarInfo;
467ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        scrollbarInfo.orientation = scrollbar->orientation() == HorizontalScrollbar ? PlatformBridge::ScrollbarOrientationHorizontal : PlatformBridge::ScrollbarOrientationVertical;
468ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        scrollbarInfo.parent = scrollbar->parent() && scrollbar->parent()->isFrameView() && static_cast<FrameView*>(scrollbar->parent())->isScrollViewScrollbar(scrollbar) ? PlatformBridge::ScrollbarParentScrollView : PlatformBridge::ScrollbarParentRenderLayer;
469cad810f21b803229eb11403f9209855525a25d57Steve Block        scrollbarInfo.maxValue = scrollbar->maximum();
470cad810f21b803229eb11403f9209855525a25d57Steve Block        scrollbarInfo.currentValue = scrollbar->currentPos();
471cad810f21b803229eb11403f9209855525a25d57Steve Block        scrollbarInfo.visibleSize = scrollbar->visibleSize();
472cad810f21b803229eb11403f9209855525a25d57Steve Block        scrollbarInfo.totalSize = scrollbar->totalSize();
473cad810f21b803229eb11403f9209855525a25d57Steve Block
474ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        PlatformBridge::paintScrollbarThumb(
475cad810f21b803229eb11403f9209855525a25d57Steve Block            drawingContext,
476cad810f21b803229eb11403f9209855525a25d57Steve Block            scrollbarStateToThemeState(scrollbar),
477ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch            scrollbar->controlSize() == RegularScrollbar ? PlatformBridge::SizeRegular : PlatformBridge::SizeSmall,
478cad810f21b803229eb11403f9209855525a25d57Steve Block            scrollbar->frameRect(),
479cad810f21b803229eb11403f9209855525a25d57Steve Block            scrollbarInfo);
480643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    }
481643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
482f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    if (!canDrawDirectly)
483a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        context->drawImageBuffer(imageBuffer.get(), ColorSpaceDeviceRGB, scrollbar->frameRect().location());
484643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
485643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    return true;
486643ca7872b450ea4efacab6188849e5aac2ba161Steve Block}
487643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
488643ca7872b450ea4efacab6188849e5aac2ba161Steve Block}
489643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
490