1/* 2 * Copyright (C) 2010 Google Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are 6 * met: 7 * 8 * * Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * * Redistributions in binary form must reproduce the above 11 * copyright notice, this list of conditions and the following disclaimer 12 * in the documentation and/or other materials provided with the 13 * distribution. 14 * * Neither the name of Google Inc. nor the names of its 15 * contributors may be used to endorse or promote products derived from 16 * this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31#include "WebThemeEngineDRTMac.h" 32 33#include "third_party/WebKit/Source/WebKit/chromium/public/WebCanvas.h" 34#include "third_party/WebKit/Source/WebKit/chromium/public/WebRect.h" 35#import <AppKit/NSAffineTransform.h> 36#import <AppKit/NSGraphicsContext.h> 37#import <AppKit/NSScroller.h> 38#import <AppKit/NSWindow.h> 39#include <Carbon/Carbon.h> 40 41using WebKit::WebCanvas; 42using WebKit::WebRect; 43using WebKit::WebThemeEngine; 44 45// We can't directly tell the NSScroller to draw itself as active or inactive, 46// instead we have to make it a child of an (in)active window. This class lets 47// us fake that parent window. 48@interface FakeActiveWindow : NSWindow { 49@private 50 BOOL hasActiveControls; 51} 52+ (NSWindow*)alwaysActiveWindow; 53+ (NSWindow*)alwaysInactiveWindow; 54- (id)initWithActiveControls:(BOOL)_hasActiveControls; 55- (BOOL)_hasActiveControls; 56@end 57 58@implementation FakeActiveWindow 59 60static NSWindow* alwaysActiveWindow = nil; 61static NSWindow* alwaysInactiveWindow = nil; 62 63+ (NSWindow*)alwaysActiveWindow 64{ 65 if (alwaysActiveWindow == nil) 66 alwaysActiveWindow = [[self alloc] initWithActiveControls:YES]; 67 return alwaysActiveWindow; 68} 69 70+ (NSWindow*)alwaysInactiveWindow 71{ 72 if (alwaysInactiveWindow == nil) 73 alwaysInactiveWindow = [[self alloc] initWithActiveControls:NO]; 74 return alwaysInactiveWindow; 75} 76 77- (id)initWithActiveControls:(BOOL)_hasActiveControls 78{ 79 self = [super init]; 80 hasActiveControls = _hasActiveControls; 81 return self; 82} 83 84- (BOOL)_hasActiveControls 85{ 86 return hasActiveControls; 87} 88 89@end 90 91void WebThemeEngineDRTMac::paintScrollbarThumb( 92 WebCanvas* canvas, 93 WebThemeEngine::State state, 94 WebThemeEngine::Size size, 95 const WebRect& rect, 96 const WebThemeEngine::ScrollbarInfo& scrollbarInfo) 97{ 98 // To match the Mac port, we still use HITheme for inner scrollbars. 99 if (scrollbarInfo.parent == WebThemeEngine::ScrollbarParentRenderLayer) 100 paintHIThemeScrollbarThumb(canvas, state, size, rect, scrollbarInfo); 101 else 102 paintNSScrollerScrollbarThumb(canvas, state, size, rect, scrollbarInfo); 103} 104 105static ThemeTrackEnableState stateToHIEnableState(WebThemeEngine::State state) 106{ 107 switch (state) { 108 case WebThemeEngine::StateDisabled: 109 return kThemeTrackDisabled; 110 case WebThemeEngine::StateInactive: 111 return kThemeTrackInactive; 112 default: 113 return kThemeTrackActive; 114 } 115} 116 117// Duplicated from webkit/glue/webthemeengine_impl_mac.cc in the downstream 118// Chromium WebThemeEngine implementation. 119void WebThemeEngineDRTMac::paintHIThemeScrollbarThumb( 120 WebCanvas* canvas, 121 WebThemeEngine::State state, 122 WebThemeEngine::Size size, 123 const WebRect& rect, 124 const WebThemeEngine::ScrollbarInfo& scrollbarInfo) 125{ 126 HIThemeTrackDrawInfo trackInfo; 127 trackInfo.version = 0; 128 trackInfo.kind = size == WebThemeEngine::SizeRegular ? kThemeMediumScrollBar : kThemeSmallScrollBar; 129 trackInfo.bounds = CGRectMake(rect.x, rect.y, rect.width, rect.height); 130 trackInfo.min = 0; 131 trackInfo.max = scrollbarInfo.maxValue; 132 trackInfo.value = scrollbarInfo.currentValue; 133 trackInfo.trackInfo.scrollbar.viewsize = scrollbarInfo.visibleSize; 134 trackInfo.attributes = 0; 135 if (scrollbarInfo.orientation == WebThemeEngine::ScrollbarOrientationHorizontal) 136 trackInfo.attributes |= kThemeTrackHorizontal; 137 138 trackInfo.enableState = stateToHIEnableState(state); 139 140 trackInfo.trackInfo.scrollbar.pressState = 141 state == WebThemeEngine::StatePressed ? kThemeThumbPressed : 0; 142 trackInfo.attributes |= (kThemeTrackShowThumb | kThemeTrackHideTrack); 143 HIThemeDrawTrack(&trackInfo, 0, canvas, kHIThemeOrientationNormal); 144} 145 146void WebThemeEngineDRTMac::paintNSScrollerScrollbarThumb( 147 WebCanvas* canvas, 148 WebThemeEngine::State state, 149 WebThemeEngine::Size size, 150 const WebRect& rect, 151 const WebThemeEngine::ScrollbarInfo& scrollbarInfo) 152{ 153 NSScroller* scroller = [[NSScroller alloc] initWithFrame:NSMakeRect(rect.x, rect.y, rect.width, rect.height)]; 154 [scroller setEnabled:state != WebThemeEngine::StateDisabled]; 155 if (state == WebThemeEngine::StateInactive) 156 [[[FakeActiveWindow alwaysInactiveWindow] contentView] addSubview:scroller]; 157 else 158 [[[FakeActiveWindow alwaysActiveWindow] contentView] addSubview:scroller]; 159 160 [scroller setControlSize:size == WebThemeEngine::SizeRegular ? NSRegularControlSize : NSSmallControlSize]; 161 162 double value = double(scrollbarInfo.currentValue) / double(scrollbarInfo.maxValue); 163 [scroller setDoubleValue: value]; 164 165 float knobProportion = float(scrollbarInfo.visibleSize) / float(scrollbarInfo.totalSize); 166 [scroller setKnobProportion: knobProportion]; 167 168 NSGraphicsContext* previousGraphicsContext = [NSGraphicsContext currentContext]; 169 NSGraphicsContext* nsGraphicsContext = [NSGraphicsContext graphicsContextWithGraphicsPort:canvas flipped:YES]; 170 [NSGraphicsContext setCurrentContext:nsGraphicsContext]; 171 172 // Despite passing in frameRect() to the scroller, it always draws at (0, 0). 173 // Force it to draw in the right location by translating the whole graphics 174 // context. 175 [nsGraphicsContext saveGraphicsState]; 176 NSAffineTransform *transform = [NSAffineTransform transform]; 177 [transform translateXBy:rect.x yBy:rect.y]; 178 [transform concat]; 179 180 [scroller drawKnob]; 181 182 [scroller release]; 183 184 [nsGraphicsContext restoreGraphicsState]; 185 [NSGraphicsContext setCurrentContext:previousGraphicsContext]; 186} 187