1/* 2 * Copyright (C) 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. 3 * Copyright (C) 2008, 2009 Google, Inc. 4 * 5 * This library is free software; you can redistribute it and/or 6 * modify it under the terms of the GNU Library General Public 7 * License as published by the Free Software Foundation; either 8 * version 2 of the License, or (at your option) any later version. 9 * 10 * This library is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 * Library General Public License for more details. 14 * 15 * You should have received a copy of the GNU Library General Public License 16 * along with this library; see the file COPYING.LIB. If not, write to 17 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 18 * Boston, MA 02110-1301, USA. 19 */ 20 21#import "config.h" 22#import "core/rendering/RenderThemeChromiumMac.h" 23 24#import "core/CSSValueKeywords.h" 25#import "core/HTMLNames.h" 26#import "core/UserAgentStyleSheets.h" 27#import "core/css/CSSValueList.h" 28#import "core/dom/Document.h" 29#import "core/dom/Element.h" 30#import "core/fileapi/FileList.h" 31#import "core/frame/FrameView.h" 32#import "core/html/HTMLInputElement.h" 33#import "core/html/HTMLMediaElement.h" 34#import "core/html/HTMLMeterElement.h" 35#import "core/html/TimeRanges.h" 36#import "core/html/shadow/MediaControlElements.h" 37#import "core/rendering/PaintInfo.h" 38#import "core/rendering/RenderLayer.h" 39#import "core/rendering/RenderMedia.h" 40#import "core/rendering/RenderMediaControls.h" 41#import "core/rendering/RenderMeter.h" 42#import "core/rendering/RenderProgress.h" 43#import "core/rendering/RenderSlider.h" 44#import "core/rendering/RenderView.h" 45#import "core/rendering/style/ShadowList.h" 46#import "platform/LayoutTestSupport.h" 47#import "platform/SharedBuffer.h" 48#import "platform/graphics/BitmapImage.h" 49#import "platform/graphics/GraphicsContextStateSaver.h" 50#import "platform/graphics/Image.h" 51#import "platform/graphics/ImageBuffer.h" 52#import "platform/mac/ColorMac.h" 53#import "platform/mac/LocalCurrentGraphicsContext.h" 54#import "platform/mac/ThemeMac.h" 55#import "platform/mac/WebCoreNSCellExtras.h" 56#import "platform/text/PlatformLocale.h" 57#import "platform/text/StringTruncator.h" 58#import <AvailabilityMacros.h> 59#import <Carbon/Carbon.h> 60#import <Cocoa/Cocoa.h> 61#import <math.h> 62#import <wtf/RetainPtr.h> 63#import <wtf/StdLibExtras.h> 64 65// The methods in this file are specific to the Mac OS X platform. 66 67// We estimate the animation rate of a Mac OS X progress bar is 33 fps. 68// Hard code the value here because we haven't found API for it. 69const double progressAnimationFrameRate = 0.033; 70 71// Mac OS X progress bar animation seems to have 256 frames. 72const double progressAnimationNumFrames = 256; 73 74@interface WebCoreRenderThemeNotificationObserver : NSObject 75{ 76 blink::RenderTheme *_theme; 77} 78 79- (id)initWithTheme:(blink::RenderTheme *)theme; 80- (void)systemColorsDidChange:(NSNotification *)notification; 81 82@end 83 84@implementation WebCoreRenderThemeNotificationObserver 85 86- (id)initWithTheme:(blink::RenderTheme *)theme 87{ 88 if (!(self = [super init])) 89 return nil; 90 91 _theme = theme; 92 return self; 93} 94 95- (void)systemColorsDidChange:(NSNotification *)unusedNotification 96{ 97 ASSERT_UNUSED(unusedNotification, [[unusedNotification name] isEqualToString:NSSystemColorsDidChangeNotification]); 98 _theme->platformColorsDidChange(); 99} 100 101@end 102 103@interface NSTextFieldCell (WKDetails) 104- (CFDictionaryRef)_coreUIDrawOptionsWithFrame:(NSRect)cellFrame inView:(NSView *)controlView includeFocus:(BOOL)includeFocus; 105@end 106 107 108@interface WebCoreTextFieldCell : NSTextFieldCell 109- (CFDictionaryRef)_coreUIDrawOptionsWithFrame:(NSRect)cellFrame inView:(NSView *)controlView includeFocus:(BOOL)includeFocus; 110@end 111 112@implementation WebCoreTextFieldCell 113- (CFDictionaryRef)_coreUIDrawOptionsWithFrame:(NSRect)cellFrame inView:(NSView *)controlView includeFocus:(BOOL)includeFocus 114{ 115 // FIXME: This is a post-Lion-only workaround for <rdar://problem/11385461>. When that bug is resolved, we should remove this code. 116 CFMutableDictionaryRef coreUIDrawOptions = CFDictionaryCreateMutableCopy(NULL, 0, [super _coreUIDrawOptionsWithFrame:cellFrame inView:controlView includeFocus:includeFocus]); 117 CFDictionarySetValue(coreUIDrawOptions, @"borders only", kCFBooleanTrue); 118 return (CFDictionaryRef)[NSMakeCollectable(coreUIDrawOptions) autorelease]; 119} 120@end 121 122@interface RTCMFlippedView : NSView 123{} 124 125- (BOOL)isFlipped; 126- (NSText *)currentEditor; 127 128@end 129 130@implementation RTCMFlippedView 131 132- (BOOL)isFlipped { 133 return [[NSGraphicsContext currentContext] isFlipped]; 134} 135 136- (NSText *)currentEditor { 137 return nil; 138} 139 140@end 141 142// Forward declare Mac SPIs. 143extern "C" { 144void _NSDrawCarbonThemeBezel(NSRect frame, BOOL enabled, BOOL flipped); 145// Request for public API: rdar://13787640 146void _NSDrawCarbonThemeListBox(NSRect frame, BOOL enabled, BOOL flipped, BOOL always_yes); 147} 148 149namespace blink { 150 151using namespace HTMLNames; 152 153RenderThemeChromiumMac::RenderThemeChromiumMac() 154 : m_notificationObserver(AdoptNS, [[WebCoreRenderThemeNotificationObserver alloc] initWithTheme:this]) 155{ 156 [[NSNotificationCenter defaultCenter] addObserver:m_notificationObserver.get() 157 selector:@selector(systemColorsDidChange:) 158 name:NSSystemColorsDidChangeNotification 159 object:nil]; 160} 161 162RenderThemeChromiumMac::~RenderThemeChromiumMac() 163{ 164 [[NSNotificationCenter defaultCenter] removeObserver:m_notificationObserver.get()]; 165} 166 167Color RenderThemeChromiumMac::platformActiveSelectionBackgroundColor() const 168{ 169 NSColor* color = [[NSColor selectedTextBackgroundColor] colorUsingColorSpaceName:NSDeviceRGBColorSpace]; 170 return Color(static_cast<int>(255.0 * [color redComponent]), static_cast<int>(255.0 * [color greenComponent]), static_cast<int>(255.0 * [color blueComponent])); 171} 172 173Color RenderThemeChromiumMac::platformInactiveSelectionBackgroundColor() const 174{ 175 NSColor* color = [[NSColor secondarySelectedControlColor] colorUsingColorSpaceName:NSDeviceRGBColorSpace]; 176 return Color(static_cast<int>(255.0 * [color redComponent]), static_cast<int>(255.0 * [color greenComponent]), static_cast<int>(255.0 * [color blueComponent])); 177} 178 179Color RenderThemeChromiumMac::platformActiveSelectionForegroundColor() const 180{ 181 return Color::black; 182} 183 184Color RenderThemeChromiumMac::platformActiveListBoxSelectionBackgroundColor() const 185{ 186 NSColor* color = [[NSColor alternateSelectedControlColor] colorUsingColorSpaceName:NSDeviceRGBColorSpace]; 187 return Color(static_cast<int>(255.0 * [color redComponent]), static_cast<int>(255.0 * [color greenComponent]), static_cast<int>(255.0 * [color blueComponent])); 188} 189 190Color RenderThemeChromiumMac::platformActiveListBoxSelectionForegroundColor() const 191{ 192 return Color::white; 193} 194 195Color RenderThemeChromiumMac::platformInactiveListBoxSelectionForegroundColor() const 196{ 197 return Color::black; 198} 199 200Color RenderThemeChromiumMac::platformFocusRingColor() const 201{ 202 static const RGBA32 oldAquaFocusRingColor = 0xFF7DADD9; 203 if (usesTestModeFocusRingColor()) 204 return oldAquaFocusRingColor; 205 206 return systemColor(CSSValueWebkitFocusRingColor); 207} 208 209Color RenderThemeChromiumMac::platformInactiveListBoxSelectionBackgroundColor() const 210{ 211 return platformInactiveSelectionBackgroundColor(); 212} 213 214static FontWeight toFontWeight(NSInteger appKitFontWeight) 215{ 216 ASSERT(appKitFontWeight > 0 && appKitFontWeight < 15); 217 if (appKitFontWeight > 14) 218 appKitFontWeight = 14; 219 else if (appKitFontWeight < 1) 220 appKitFontWeight = 1; 221 222 static FontWeight fontWeights[] = { 223 FontWeight100, 224 FontWeight100, 225 FontWeight200, 226 FontWeight300, 227 FontWeight400, 228 FontWeight500, 229 FontWeight600, 230 FontWeight600, 231 FontWeight700, 232 FontWeight800, 233 FontWeight800, 234 FontWeight900, 235 FontWeight900, 236 FontWeight900 237 }; 238 return fontWeights[appKitFontWeight - 1]; 239} 240 241void RenderThemeChromiumMac::systemFont(CSSValueID cssValueId, FontDescription& fontDescription) const 242{ 243 DEFINE_STATIC_LOCAL(FontDescription, systemFont, ()); 244 DEFINE_STATIC_LOCAL(FontDescription, smallSystemFont, ()); 245 DEFINE_STATIC_LOCAL(FontDescription, menuFont, ()); 246 DEFINE_STATIC_LOCAL(FontDescription, labelFont, ()); 247 DEFINE_STATIC_LOCAL(FontDescription, miniControlFont, ()); 248 DEFINE_STATIC_LOCAL(FontDescription, smallControlFont, ()); 249 DEFINE_STATIC_LOCAL(FontDescription, controlFont, ()); 250 251 FontDescription* cachedDesc; 252 NSFont* font = nil; 253 switch (cssValueId) { 254 case CSSValueSmallCaption: 255 cachedDesc = &smallSystemFont; 256 if (!smallSystemFont.isAbsoluteSize()) 257 font = [NSFont systemFontOfSize:[NSFont smallSystemFontSize]]; 258 break; 259 case CSSValueMenu: 260 cachedDesc = &menuFont; 261 if (!menuFont.isAbsoluteSize()) 262 font = [NSFont menuFontOfSize:[NSFont systemFontSize]]; 263 break; 264 case CSSValueStatusBar: 265 cachedDesc = &labelFont; 266 if (!labelFont.isAbsoluteSize()) 267 font = [NSFont labelFontOfSize:[NSFont labelFontSize]]; 268 break; 269 case CSSValueWebkitMiniControl: 270 cachedDesc = &miniControlFont; 271 if (!miniControlFont.isAbsoluteSize()) 272 font = [NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:NSMiniControlSize]]; 273 break; 274 case CSSValueWebkitSmallControl: 275 cachedDesc = &smallControlFont; 276 if (!smallControlFont.isAbsoluteSize()) 277 font = [NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:NSSmallControlSize]]; 278 break; 279 case CSSValueWebkitControl: 280 cachedDesc = &controlFont; 281 if (!controlFont.isAbsoluteSize()) 282 font = [NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:NSRegularControlSize]]; 283 break; 284 default: 285 cachedDesc = &systemFont; 286 if (!systemFont.isAbsoluteSize()) 287 font = [NSFont systemFontOfSize:[NSFont systemFontSize]]; 288 } 289 290 if (font) { 291 NSFontManager *fontManager = [NSFontManager sharedFontManager]; 292 cachedDesc->setIsAbsoluteSize(true); 293 cachedDesc->setGenericFamily(FontDescription::NoFamily); 294 cachedDesc->firstFamily().setFamily([font webCoreFamilyName]); 295 cachedDesc->setSpecifiedSize([font pointSize]); 296 cachedDesc->setWeight(toFontWeight([fontManager weightOfFont:font])); 297 cachedDesc->setStyle([fontManager traitsOfFont:font] & NSItalicFontMask ? FontStyleItalic : FontStyleNormal); 298 } 299 fontDescription = *cachedDesc; 300} 301 302static RGBA32 convertNSColorToColor(NSColor *color) 303{ 304 NSColor *colorInColorSpace = [color colorUsingColorSpaceName:NSDeviceRGBColorSpace]; 305 if (colorInColorSpace) { 306 static const double scaleFactor = nextafter(256.0, 0.0); 307 return makeRGB(static_cast<int>(scaleFactor * [colorInColorSpace redComponent]), 308 static_cast<int>(scaleFactor * [colorInColorSpace greenComponent]), 309 static_cast<int>(scaleFactor * [colorInColorSpace blueComponent])); 310 } 311 312 // This conversion above can fail if the NSColor in question is an NSPatternColor 313 // (as many system colors are). These colors are actually a repeating pattern 314 // not just a solid color. To work around this we simply draw a 1x1 image of 315 // the color and use that pixel's color. It might be better to use an average of 316 // the colors in the pattern instead. 317 NSBitmapImageRep *offscreenRep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:nil 318 pixelsWide:1 319 pixelsHigh:1 320 bitsPerSample:8 321 samplesPerPixel:4 322 hasAlpha:YES 323 isPlanar:NO 324 colorSpaceName:NSDeviceRGBColorSpace 325 bytesPerRow:4 326 bitsPerPixel:32]; 327 328 [NSGraphicsContext saveGraphicsState]; 329 [NSGraphicsContext setCurrentContext:[NSGraphicsContext graphicsContextWithBitmapImageRep:offscreenRep]]; 330 NSEraseRect(NSMakeRect(0, 0, 1, 1)); 331 [color drawSwatchInRect:NSMakeRect(0, 0, 1, 1)]; 332 [NSGraphicsContext restoreGraphicsState]; 333 334 NSUInteger pixel[4]; 335 [offscreenRep getPixel:pixel atX:0 y:0]; 336 337 [offscreenRep release]; 338 339 return makeRGB(pixel[0], pixel[1], pixel[2]); 340} 341 342static RGBA32 menuBackgroundColor() 343{ 344 NSBitmapImageRep *offscreenRep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:nil 345 pixelsWide:1 346 pixelsHigh:1 347 bitsPerSample:8 348 samplesPerPixel:4 349 hasAlpha:YES 350 isPlanar:NO 351 colorSpaceName:NSDeviceRGBColorSpace 352 bytesPerRow:4 353 bitsPerPixel:32]; 354 355 CGContextRef context = static_cast<CGContextRef>([[NSGraphicsContext graphicsContextWithBitmapImageRep:offscreenRep] graphicsPort]); 356 CGRect rect = CGRectMake(0, 0, 1, 1); 357 HIThemeMenuDrawInfo drawInfo; 358 drawInfo.version = 0; 359 drawInfo.menuType = kThemeMenuTypePopUp; 360 HIThemeDrawMenuBackground(&rect, &drawInfo, context, kHIThemeOrientationInverted); 361 362 NSUInteger pixel[4]; 363 [offscreenRep getPixel:pixel atX:0 y:0]; 364 365 [offscreenRep release]; 366 367 return makeRGB(pixel[0], pixel[1], pixel[2]); 368} 369 370void RenderThemeChromiumMac::platformColorsDidChange() 371{ 372 m_systemColorCache.clear(); 373 RenderTheme::platformColorsDidChange(); 374} 375 376Color RenderThemeChromiumMac::systemColor(CSSValueID cssValueId) const 377{ 378 { 379 HashMap<int, RGBA32>::iterator it = m_systemColorCache.find(cssValueId); 380 if (it != m_systemColorCache.end()) 381 return it->value; 382 } 383 384 Color color; 385 bool needsFallback = false; 386 switch (cssValueId) { 387 case CSSValueActiveborder: 388 color = convertNSColorToColor([NSColor keyboardFocusIndicatorColor]); 389 break; 390 case CSSValueActivecaption: 391 color = convertNSColorToColor([NSColor windowFrameTextColor]); 392 break; 393 case CSSValueAppworkspace: 394 color = convertNSColorToColor([NSColor headerColor]); 395 break; 396 case CSSValueBackground: 397 // Use theme independent default 398 needsFallback = true; 399 break; 400 case CSSValueButtonface: 401 // We use this value instead of NSColor's controlColor to avoid website 402 // incompatibilities. We may want to change this to use the NSColor in 403 // future. 404 color = 0xFFC0C0C0; 405 break; 406 case CSSValueButtonhighlight: 407 color = convertNSColorToColor([NSColor controlHighlightColor]); 408 break; 409 case CSSValueButtonshadow: 410 color = convertNSColorToColor([NSColor controlShadowColor]); 411 break; 412 case CSSValueButtontext: 413 color = convertNSColorToColor([NSColor controlTextColor]); 414 break; 415 case CSSValueCaptiontext: 416 color = convertNSColorToColor([NSColor textColor]); 417 break; 418 case CSSValueGraytext: 419 color = convertNSColorToColor([NSColor disabledControlTextColor]); 420 break; 421 case CSSValueHighlight: 422 color = convertNSColorToColor([NSColor selectedTextBackgroundColor]); 423 break; 424 case CSSValueHighlighttext: 425 color = convertNSColorToColor([NSColor selectedTextColor]); 426 break; 427 case CSSValueInactiveborder: 428 color = convertNSColorToColor([NSColor controlBackgroundColor]); 429 break; 430 case CSSValueInactivecaption: 431 color = convertNSColorToColor([NSColor controlBackgroundColor]); 432 break; 433 case CSSValueInactivecaptiontext: 434 color = convertNSColorToColor([NSColor textColor]); 435 break; 436 case CSSValueInfobackground: 437 // There is no corresponding NSColor for this so we use a hard coded 438 // value. 439 color = 0xFFFBFCC5; 440 break; 441 case CSSValueInfotext: 442 color = convertNSColorToColor([NSColor textColor]); 443 break; 444 case CSSValueMenu: 445 color = menuBackgroundColor(); 446 break; 447 case CSSValueMenutext: 448 color = convertNSColorToColor([NSColor selectedMenuItemTextColor]); 449 break; 450 case CSSValueScrollbar: 451 color = convertNSColorToColor([NSColor scrollBarColor]); 452 break; 453 case CSSValueText: 454 color = convertNSColorToColor([NSColor textColor]); 455 break; 456 case CSSValueThreeddarkshadow: 457 color = convertNSColorToColor([NSColor controlDarkShadowColor]); 458 break; 459 case CSSValueThreedshadow: 460 color = convertNSColorToColor([NSColor shadowColor]); 461 break; 462 case CSSValueThreedface: 463 // We use this value instead of NSColor's controlColor to avoid website 464 // incompatibilities. We may want to change this to use the NSColor in 465 // future. 466 color = 0xFFC0C0C0; 467 break; 468 case CSSValueThreedhighlight: 469 color = convertNSColorToColor([NSColor highlightColor]); 470 break; 471 case CSSValueThreedlightshadow: 472 color = convertNSColorToColor([NSColor controlLightHighlightColor]); 473 break; 474 case CSSValueWebkitFocusRingColor: 475 color = convertNSColorToColor([NSColor keyboardFocusIndicatorColor]); 476 break; 477 case CSSValueWindow: 478 color = convertNSColorToColor([NSColor windowBackgroundColor]); 479 break; 480 case CSSValueWindowframe: 481 color = convertNSColorToColor([NSColor windowFrameColor]); 482 break; 483 case CSSValueWindowtext: 484 color = convertNSColorToColor([NSColor windowFrameTextColor]); 485 break; 486 default: 487 needsFallback = true; 488 break; 489 } 490 491 if (needsFallback) 492 color = RenderTheme::systemColor(cssValueId); 493 494 m_systemColorCache.set(cssValueId, color.rgb()); 495 496 return color; 497} 498 499bool RenderThemeChromiumMac::isControlStyled(const RenderStyle* style, const CachedUAStyle* uaStyle) const 500{ 501 ASSERT(uaStyle); 502 if (style->appearance() == TextFieldPart || style->appearance() == TextAreaPart) 503 return style->border() != uaStyle->border || style->boxShadow(); 504 505 // FIXME: This is horrible, but there is not much else that can be done. 506 // Menu lists cannot draw properly when scaled. They can't really draw 507 // properly when transformed either. We can't detect the transform case at 508 // style adjustment time so that will just have to stay broken. We can 509 // however detect that we're zooming. If zooming is in effect we treat it 510 // like the control is styled. 511 if (style->appearance() == MenulistPart && style->effectiveZoom() != 1.0f) 512 return true; 513 // FIXME: NSSearchFieldCell doesn't work well when scaled. 514 if (style->appearance() == SearchFieldPart && style->effectiveZoom() != 1) 515 return true; 516 517 return RenderTheme::isControlStyled(style, uaStyle); 518} 519 520const int sliderThumbShadowBlur = 1; 521 522void RenderThemeChromiumMac::adjustPaintInvalidationRect(const RenderObject* o, IntRect& r) 523{ 524 ControlPart part = o->style()->appearance(); 525 526#if USE(NEW_THEME) 527 switch (part) { 528 case CheckboxPart: 529 case RadioPart: 530 case PushButtonPart: 531 case SquareButtonPart: 532 case ButtonPart: 533 case InnerSpinButtonPart: 534 return RenderTheme::adjustPaintInvalidationRect(o, r); 535 default: 536 break; 537 } 538#endif 539 540 float zoomLevel = o->style()->effectiveZoom(); 541 542 if (part == MenulistPart) { 543 setPopupButtonCellState(o, r); 544 IntSize size = popupButtonSizes()[[popupButton() controlSize]]; 545 size.setHeight(size.height() * zoomLevel); 546 size.setWidth(r.width()); 547 r = ThemeMac::inflateRect(r, size, popupButtonMargins(), zoomLevel); 548 } else if (part == SliderThumbHorizontalPart || part == SliderThumbVerticalPart) { 549 r.setHeight(r.height() + sliderThumbShadowBlur); 550 } 551} 552 553FloatRect RenderThemeChromiumMac::convertToPaintingRect(const RenderObject* inputRenderer, const RenderObject* partRenderer, const FloatRect& inputRect, const IntRect& r) const 554{ 555 FloatRect partRect(inputRect); 556 557 // Compute an offset between the part renderer and the input renderer. 558 FloatSize offsetFromInputRenderer; 559 const RenderObject* renderer = partRenderer; 560 while (renderer && renderer != inputRenderer) { 561 RenderObject* containingRenderer = renderer->container(); 562 offsetFromInputRenderer -= roundedIntSize(renderer->offsetFromContainer(containingRenderer, LayoutPoint())); 563 renderer = containingRenderer; 564 } 565 // If the input renderer was not a container, something went wrong. 566 ASSERT(renderer == inputRenderer); 567 // Move the rect into partRenderer's coords. 568 partRect.move(offsetFromInputRenderer); 569 // Account for the local drawing offset (tx, ty). 570 partRect.move(r.x(), r.y()); 571 572 return partRect; 573} 574 575void RenderThemeChromiumMac::updateCheckedState(NSCell* cell, const RenderObject* o) 576{ 577 bool oldIndeterminate = [cell state] == NSMixedState; 578 bool indeterminate = isIndeterminate(o); 579 bool checked = isChecked(o); 580 581 if (oldIndeterminate != indeterminate) { 582 [cell setState:indeterminate ? NSMixedState : (checked ? NSOnState : NSOffState)]; 583 return; 584 } 585 586 bool oldChecked = [cell state] == NSOnState; 587 if (checked != oldChecked) 588 [cell setState:checked ? NSOnState : NSOffState]; 589} 590 591void RenderThemeChromiumMac::updateEnabledState(NSCell* cell, const RenderObject* o) 592{ 593 bool oldEnabled = [cell isEnabled]; 594 bool enabled = isEnabled(o); 595 if (enabled != oldEnabled) 596 [cell setEnabled:enabled]; 597} 598 599void RenderThemeChromiumMac::updateFocusedState(NSCell* cell, const RenderObject* o) 600{ 601 bool oldFocused = [cell showsFirstResponder]; 602 bool focused = isFocused(o) && o->style()->outlineStyleIsAuto(); 603 if (focused != oldFocused) 604 [cell setShowsFirstResponder:focused]; 605} 606 607void RenderThemeChromiumMac::updatePressedState(NSCell* cell, const RenderObject* o) 608{ 609 bool oldPressed = [cell isHighlighted]; 610 bool pressed = o->node() && o->node()->active(); 611 if (pressed != oldPressed) 612 [cell setHighlighted:pressed]; 613} 614 615NSControlSize RenderThemeChromiumMac::controlSizeForFont(RenderStyle* style) const 616{ 617 int fontSize = style->fontSize(); 618 if (fontSize >= 16) 619 return NSRegularControlSize; 620 if (fontSize >= 11) 621 return NSSmallControlSize; 622 return NSMiniControlSize; 623} 624 625// We don't use controlSizeForFont() for search field decorations because it 626// needs to fit into the search field. The font size will already be modified by 627// setFontFromControlSize() called on the search field. 628static NSControlSize searchFieldControlSizeForFont(RenderStyle* style) 629{ 630 int fontSize = style->fontSize(); 631 if (fontSize >= 13) 632 return NSRegularControlSize; 633 if (fontSize >= 11) 634 return NSSmallControlSize; 635 return NSMiniControlSize; 636} 637 638void RenderThemeChromiumMac::setControlSize(NSCell* cell, const IntSize* sizes, const IntSize& minSize, float zoomLevel) 639{ 640 NSControlSize size; 641 if (minSize.width() >= static_cast<int>(sizes[NSRegularControlSize].width() * zoomLevel) && 642 minSize.height() >= static_cast<int>(sizes[NSRegularControlSize].height() * zoomLevel)) 643 size = NSRegularControlSize; 644 else if (minSize.width() >= static_cast<int>(sizes[NSSmallControlSize].width() * zoomLevel) && 645 minSize.height() >= static_cast<int>(sizes[NSSmallControlSize].height() * zoomLevel)) 646 size = NSSmallControlSize; 647 else 648 size = NSMiniControlSize; 649 // Only update if we have to, since AppKit does work even if the size is the 650 // same. 651 if (size != [cell controlSize]) 652 [cell setControlSize:size]; 653} 654 655IntSize RenderThemeChromiumMac::sizeForFont(RenderStyle* style, const IntSize* sizes) const 656{ 657 if (style->effectiveZoom() != 1.0f) { 658 IntSize result = sizes[controlSizeForFont(style)]; 659 return IntSize(result.width() * style->effectiveZoom(), result.height() * style->effectiveZoom()); 660 } 661 return sizes[controlSizeForFont(style)]; 662} 663 664IntSize RenderThemeChromiumMac::sizeForSystemFont(RenderStyle* style, const IntSize* sizes) const 665{ 666 if (style->effectiveZoom() != 1.0f) { 667 IntSize result = sizes[controlSizeForSystemFont(style)]; 668 return IntSize(result.width() * style->effectiveZoom(), result.height() * style->effectiveZoom()); 669 } 670 return sizes[controlSizeForSystemFont(style)]; 671} 672 673void RenderThemeChromiumMac::setSizeFromFont(RenderStyle* style, const IntSize* sizes) const 674{ 675 // FIXME: Check is flawed, since it doesn't take min-width/max-width into 676 // account. 677 IntSize size = sizeForFont(style, sizes); 678 if (style->width().isIntrinsicOrAuto() && size.width() > 0) 679 style->setWidth(Length(size.width(), Fixed)); 680 if (style->height().isAuto() && size.height() > 0) 681 style->setHeight(Length(size.height(), Fixed)); 682} 683 684void RenderThemeChromiumMac::setFontFromControlSize(RenderStyle* style, NSControlSize controlSize) const 685{ 686 FontDescription fontDescription; 687 fontDescription.setIsAbsoluteSize(true); 688 fontDescription.setGenericFamily(FontDescription::SerifFamily); 689 690 NSFont* font = [NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:controlSize]]; 691 fontDescription.firstFamily().setFamily([font webCoreFamilyName]); 692 fontDescription.setComputedSize([font pointSize] * style->effectiveZoom()); 693 fontDescription.setSpecifiedSize([font pointSize] * style->effectiveZoom()); 694 695 // Reset line height. 696 style->setLineHeight(RenderStyle::initialLineHeight()); 697 698 if (style->setFontDescription(fontDescription)) 699 style->font().update(nullptr); 700} 701 702NSControlSize RenderThemeChromiumMac::controlSizeForSystemFont(RenderStyle* style) const 703{ 704 float fontSize = style->fontSize(); 705 float zoomLevel = style->effectiveZoom(); 706 if (zoomLevel != 1) 707 fontSize /= zoomLevel; 708 if (fontSize >= [NSFont systemFontSizeForControlSize:NSRegularControlSize]) 709 return NSRegularControlSize; 710 if (fontSize >= [NSFont systemFontSizeForControlSize:NSSmallControlSize]) 711 return NSSmallControlSize; 712 return NSMiniControlSize; 713} 714 715bool RenderThemeChromiumMac::paintTextField(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r) 716{ 717 LocalCurrentGraphicsContext localContext(paintInfo.context, r); 718 719#if __MAC_OS_X_VERSION_MIN_REQUIRED <= 1070 720 bool useNSTextFieldCell = o->style()->hasAppearance() 721 && o->style()->visitedDependentColor(CSSPropertyBackgroundColor) == Color::white 722 && !o->style()->hasBackgroundImage(); 723 724 // We do not use NSTextFieldCell to draw styled text fields on Lion and 725 // SnowLeopard because there are a number of bugs on those platforms that 726 // require NSTextFieldCell to be in charge of painting its own 727 // background. We need WebCore to paint styled backgrounds, so we'll use 728 // this AppKit SPI function instead. 729 if (!useNSTextFieldCell) { 730 _NSDrawCarbonThemeBezel(r, isEnabled(o) && !isReadOnlyControl(o), YES); 731 return false; 732 } 733#endif 734 735 NSTextFieldCell *textField = this->textField(); 736 737 GraphicsContextStateSaver stateSaver(*paintInfo.context); 738 739 [textField setEnabled:(isEnabled(o) && !isReadOnlyControl(o))]; 740 [textField drawWithFrame:NSRect(r) inView:documentViewFor(o)]; 741 742 [textField setControlView:nil]; 743 744 return false; 745} 746 747bool RenderThemeChromiumMac::paintCapsLockIndicator(RenderObject*, const PaintInfo& paintInfo, const IntRect& r) 748{ 749 // This draws the caps lock indicator as it was done by 750 // WKDrawCapsLockIndicator. 751 LocalCurrentGraphicsContext localContext(paintInfo.context, r); 752 CGContextRef c = localContext.cgContext(); 753 CGMutablePathRef shape = CGPathCreateMutable(); 754 755 // To draw the caps lock indicator, draw the shape into a small 756 // square that is then scaled to the size of r. 757 const CGFloat kSquareSize = 17; 758 759 // Create a rounted square shape. 760 CGPathMoveToPoint(shape, NULL, 16.5, 4.5); 761 CGPathAddArc(shape, NULL, 12.5, 12.5, 4, 0, M_PI_2, false); 762 CGPathAddArc(shape, NULL, 4.5, 12.5, 4, M_PI_2, M_PI, false); 763 CGPathAddArc(shape, NULL, 4.5, 4.5, 4, M_PI, 3*M_PI/2, false); 764 CGPathAddArc(shape, NULL, 12.5, 4.5, 4, 3*M_PI/2, 0, false); 765 766 // Draw the arrow - note this is drawing in a flipped coordinate system, so 767 // the arrow is pointing down. 768 CGPathMoveToPoint(shape, NULL, 8.5, 2); // Tip point. 769 CGPathAddLineToPoint(shape, NULL, 4, 7); 770 CGPathAddLineToPoint(shape, NULL, 6.25, 7); 771 CGPathAddLineToPoint(shape, NULL, 6.25, 10.25); 772 CGPathAddLineToPoint(shape, NULL, 10.75, 10.25); 773 CGPathAddLineToPoint(shape, NULL, 10.75, 7); 774 CGPathAddLineToPoint(shape, NULL, 13, 7); 775 CGPathAddLineToPoint(shape, NULL, 8.5, 2); 776 777 // Draw the rectangle that underneath (or above in the flipped system) the 778 // arrow. 779 CGPathAddLineToPoint(shape, NULL, 10.75, 12); 780 CGPathAddLineToPoint(shape, NULL, 6.25, 12); 781 CGPathAddLineToPoint(shape, NULL, 6.25, 14.25); 782 CGPathAddLineToPoint(shape, NULL, 10.75, 14.25); 783 CGPathAddLineToPoint(shape, NULL, 10.75, 12); 784 785 // Scale and translate the shape. 786 CGRect cgr = r; 787 CGFloat maxX = CGRectGetMaxX(cgr); 788 CGFloat minY = CGRectGetMinY(cgr); 789 CGFloat heightScale = r.height() / kSquareSize; 790 CGAffineTransform transform = CGAffineTransformMake( 791 heightScale, 0, // A B 792 0, heightScale, // C D 793 maxX - r.height(), minY); // Tx Ty 794 795 CGMutablePathRef paintPath = CGPathCreateMutable(); 796 CGPathAddPath(paintPath, &transform, shape); 797 CGPathRelease(shape); 798 799 CGContextSetRGBFillColor(c, 0, 0, 0, 0.4); 800 CGContextBeginPath(c); 801 CGContextAddPath(c, paintPath); 802 CGContextFillPath(c); 803 CGPathRelease(paintPath); 804 805 return false; 806} 807 808bool RenderThemeChromiumMac::paintTextArea(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r) 809{ 810 LocalCurrentGraphicsContext localContext(paintInfo.context, r); 811 _NSDrawCarbonThemeListBox(r, isEnabled(o) && !isReadOnlyControl(o), YES, YES); 812 return false; 813} 814 815const int* RenderThemeChromiumMac::popupButtonMargins() const 816{ 817 static const int margins[3][4] = 818 { 819 { 0, 3, 1, 3 }, 820 { 0, 3, 2, 3 }, 821 { 0, 1, 0, 1 } 822 }; 823 return margins[[popupButton() controlSize]]; 824} 825 826const IntSize* RenderThemeChromiumMac::popupButtonSizes() const 827{ 828 static const IntSize sizes[3] = { IntSize(0, 21), IntSize(0, 18), IntSize(0, 15) }; 829 return sizes; 830} 831 832const int* RenderThemeChromiumMac::popupButtonPadding(NSControlSize size) const 833{ 834 static const int padding[3][4] = 835 { 836 { 2, 26, 3, 8 }, 837 { 2, 23, 3, 8 }, 838 { 2, 22, 3, 10 } 839 }; 840 return padding[size]; 841} 842 843bool RenderThemeChromiumMac::paintMenuList(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r) 844{ 845 setPopupButtonCellState(o, r); 846 847 NSPopUpButtonCell* popupButton = this->popupButton(); 848 849 float zoomLevel = o->style()->effectiveZoom(); 850 IntSize size = popupButtonSizes()[[popupButton controlSize]]; 851 size.setHeight(size.height() * zoomLevel); 852 size.setWidth(r.width()); 853 854 // Now inflate it to account for the shadow. 855 IntRect inflatedRect = r; 856 if (r.width() >= minimumMenuListSize(o->style())) 857 inflatedRect = ThemeMac::inflateRect(inflatedRect, size, popupButtonMargins(), zoomLevel); 858 859 LocalCurrentGraphicsContext localContext(paintInfo.context, ThemeMac::inflateRectForFocusRing(inflatedRect)); 860 GraphicsContextStateSaver stateSaver(*paintInfo.context); 861 862 // On Leopard, the cell will draw outside of the given rect, so we have to 863 // clip to the rect. 864 paintInfo.context->clip(inflatedRect); 865 866 if (zoomLevel != 1.0f) { 867 inflatedRect.setWidth(inflatedRect.width() / zoomLevel); 868 inflatedRect.setHeight(inflatedRect.height() / zoomLevel); 869 paintInfo.context->translate(inflatedRect.x(), inflatedRect.y()); 870 paintInfo.context->scale(zoomLevel, zoomLevel); 871 paintInfo.context->translate(-inflatedRect.x(), -inflatedRect.y()); 872 } 873 874 NSView *view = documentViewFor(o); 875 [popupButton drawWithFrame:inflatedRect inView:view]; 876#if !BUTTON_CELL_DRAW_WITH_FRAME_DRAWS_FOCUS_RING 877 if (isFocused(o) && o->style()->outlineStyleIsAuto()) 878 [popupButton _web_drawFocusRingWithFrame:inflatedRect inView:view]; 879#endif 880 [popupButton setControlView:nil]; 881 882 return false; 883} 884 885IntSize RenderThemeChromiumMac::meterSizeForBounds(const RenderMeter* renderMeter, const IntRect& bounds) const 886{ 887 if (NoControlPart == renderMeter->style()->appearance()) 888 return bounds.size(); 889 890 NSLevelIndicatorCell* cell = levelIndicatorFor(renderMeter); 891 // Makes enough room for cell's intrinsic size. 892 NSSize cellSize = [cell cellSizeForBounds:IntRect(IntPoint(), bounds.size())]; 893 return IntSize(bounds.width() < cellSize.width ? cellSize.width : bounds.width(), 894 bounds.height() < cellSize.height ? cellSize.height : bounds.height()); 895} 896 897bool RenderThemeChromiumMac::paintMeter(RenderObject* renderObject, const PaintInfo& paintInfo, const IntRect& rect) 898{ 899 if (!renderObject->isMeter()) 900 return true; 901 902 LocalCurrentGraphicsContext localContext(paintInfo.context, rect); 903 904 NSLevelIndicatorCell* cell = levelIndicatorFor(toRenderMeter(renderObject)); 905 GraphicsContextStateSaver stateSaver(*paintInfo.context); 906 907 [cell drawWithFrame:rect inView:documentViewFor(renderObject)]; 908 [cell setControlView:nil]; 909 return false; 910} 911 912bool RenderThemeChromiumMac::supportsMeter(ControlPart part) const 913{ 914 switch (part) { 915 case RelevancyLevelIndicatorPart: 916 case DiscreteCapacityLevelIndicatorPart: 917 case RatingLevelIndicatorPart: 918 case MeterPart: 919 case ContinuousCapacityLevelIndicatorPart: 920 return true; 921 default: 922 return false; 923 } 924} 925 926NSLevelIndicatorStyle RenderThemeChromiumMac::levelIndicatorStyleFor(ControlPart part) const 927{ 928 switch (part) { 929 case RelevancyLevelIndicatorPart: 930 return NSRelevancyLevelIndicatorStyle; 931 case DiscreteCapacityLevelIndicatorPart: 932 return NSDiscreteCapacityLevelIndicatorStyle; 933 case RatingLevelIndicatorPart: 934 return NSRatingLevelIndicatorStyle; 935 case MeterPart: 936 case ContinuousCapacityLevelIndicatorPart: 937 default: 938 return NSContinuousCapacityLevelIndicatorStyle; 939 } 940} 941 942NSLevelIndicatorCell* RenderThemeChromiumMac::levelIndicatorFor(const RenderMeter* renderMeter) const 943{ 944 RenderStyle* style = renderMeter->style(); 945 ASSERT(style->appearance() != NoControlPart); 946 947 if (!m_levelIndicator) 948 m_levelIndicator.adoptNS([[NSLevelIndicatorCell alloc] initWithLevelIndicatorStyle:NSContinuousCapacityLevelIndicatorStyle]); 949 NSLevelIndicatorCell* cell = m_levelIndicator.get(); 950 951 HTMLMeterElement* element = renderMeter->meterElement(); 952 double value = element->value(); 953 954 // Because NSLevelIndicatorCell does not support optimum-in-the-middle type 955 // coloring, we explicitly control the color instead giving low and high 956 // value to NSLevelIndicatorCell as is. 957 switch (element->gaugeRegion()) { 958 case HTMLMeterElement::GaugeRegionOptimum: 959 // Make meter the green. 960 [cell setWarningValue:value + 1]; 961 [cell setCriticalValue:value + 2]; 962 break; 963 case HTMLMeterElement::GaugeRegionSuboptimal: 964 // Make the meter yellow. 965 [cell setWarningValue:value - 1]; 966 [cell setCriticalValue:value + 1]; 967 break; 968 case HTMLMeterElement::GaugeRegionEvenLessGood: 969 // Make the meter red. 970 [cell setWarningValue:value - 2]; 971 [cell setCriticalValue:value - 1]; 972 break; 973 } 974 975 [cell setLevelIndicatorStyle:levelIndicatorStyleFor(style->appearance())]; 976 [cell setBaseWritingDirection:style->isLeftToRightDirection() ? NSWritingDirectionLeftToRight : NSWritingDirectionRightToLeft]; 977 [cell setMinValue:element->min()]; 978 [cell setMaxValue:element->max()]; 979 RetainPtr<NSNumber> valueObject = [NSNumber numberWithDouble:value]; 980 [cell setObjectValue:valueObject.get()]; 981 982 return cell; 983} 984 985const IntSize* RenderThemeChromiumMac::progressBarSizes() const 986{ 987 static const IntSize sizes[3] = { IntSize(0, 20), IntSize(0, 12), IntSize(0, 12) }; 988 return sizes; 989} 990 991const int* RenderThemeChromiumMac::progressBarMargins(NSControlSize controlSize) const 992{ 993 static const int margins[3][4] = 994 { 995 { 0, 0, 1, 0 }, 996 { 0, 0, 1, 0 }, 997 { 0, 0, 1, 0 }, 998 }; 999 return margins[controlSize]; 1000} 1001 1002int RenderThemeChromiumMac::minimumProgressBarHeight(RenderStyle* style) const 1003{ 1004 return sizeForSystemFont(style, progressBarSizes()).height(); 1005} 1006 1007double RenderThemeChromiumMac::animationRepeatIntervalForProgressBar(RenderProgress*) const 1008{ 1009 return progressAnimationFrameRate; 1010} 1011 1012double RenderThemeChromiumMac::animationDurationForProgressBar(RenderProgress*) const 1013{ 1014 return progressAnimationNumFrames * progressAnimationFrameRate; 1015} 1016 1017bool RenderThemeChromiumMac::paintProgressBar(RenderObject* renderObject, const PaintInfo& paintInfo, const IntRect& rect) 1018{ 1019 if (!renderObject->isProgress()) 1020 return true; 1021 1022 float zoomLevel = renderObject->style()->effectiveZoom(); 1023 int controlSize = controlSizeForFont(renderObject->style()); 1024 IntSize size = progressBarSizes()[controlSize]; 1025 size.setHeight(size.height() * zoomLevel); 1026 size.setWidth(rect.width()); 1027 1028 // Now inflate it to account for the shadow. 1029 IntRect inflatedRect = rect; 1030 if (rect.height() <= minimumProgressBarHeight(renderObject->style())) 1031 inflatedRect = ThemeMac::inflateRect(inflatedRect, size, progressBarMargins(controlSize), zoomLevel); 1032 1033 RenderProgress* renderProgress = toRenderProgress(renderObject); 1034 HIThemeTrackDrawInfo trackInfo; 1035 trackInfo.version = 0; 1036 if (controlSize == NSRegularControlSize) 1037 trackInfo.kind = renderProgress->position() < 0 ? kThemeLargeIndeterminateBar : kThemeLargeProgressBar; 1038 else 1039 trackInfo.kind = renderProgress->position() < 0 ? kThemeMediumIndeterminateBar : kThemeMediumProgressBar; 1040 1041 trackInfo.bounds = IntRect(IntPoint(), inflatedRect.size()); 1042 trackInfo.min = 0; 1043 trackInfo.max = std::numeric_limits<SInt32>::max(); 1044 trackInfo.value = lround(renderProgress->position() * nextafter(trackInfo.max, 0)); 1045 trackInfo.trackInfo.progress.phase = lround(renderProgress->animationProgress() * nextafter(progressAnimationNumFrames, 0)); 1046 trackInfo.attributes = kThemeTrackHorizontal; 1047 trackInfo.enableState = isActive(renderObject) ? kThemeTrackActive : kThemeTrackInactive; 1048 trackInfo.reserved = 0; 1049 trackInfo.filler1 = 0; 1050 1051 OwnPtr<ImageBuffer> imageBuffer = ImageBuffer::create(inflatedRect.size()); 1052 if (!imageBuffer) 1053 return true; 1054 1055 LocalCurrentGraphicsContext localContext(imageBuffer->context(), IntRect(IntPoint(), inflatedRect.size())); 1056 CGContextRef cgContext = localContext.cgContext(); 1057 HIThemeDrawTrack(&trackInfo, 0, cgContext, kHIThemeOrientationNormal); 1058 1059 GraphicsContextStateSaver stateSaver(*paintInfo.context); 1060 1061 if (!renderProgress->style()->isLeftToRightDirection()) { 1062 paintInfo.context->translate(2 * inflatedRect.x() + inflatedRect.width(), 0); 1063 paintInfo.context->scale(-1, 1); 1064 } 1065 1066 paintInfo.context->drawImageBuffer(imageBuffer.get(), 1067 FloatRect(inflatedRect.location(), imageBuffer->size())); 1068 return false; 1069} 1070 1071const float baseFontSize = 11.0f; 1072const float baseArrowHeight = 4.0f; 1073const float baseArrowWidth = 5.0f; 1074const float baseSpaceBetweenArrows = 2.0f; 1075const int arrowPaddingLeft = 6; 1076const int arrowPaddingRight = 6; 1077const int paddingBeforeSeparator = 4; 1078const int baseBorderRadius = 5; 1079const int styledPopupPaddingLeft = 8; 1080const int styledPopupPaddingTop = 1; 1081const int styledPopupPaddingBottom = 2; 1082 1083bool RenderThemeChromiumMac::paintMenuListButton(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r) 1084{ 1085 IntRect bounds = IntRect(r.x() + o->style()->borderLeftWidth(), 1086 r.y() + o->style()->borderTopWidth(), 1087 r.width() - o->style()->borderLeftWidth() - o->style()->borderRightWidth(), 1088 r.height() - o->style()->borderTopWidth() - o->style()->borderBottomWidth()); 1089 // Since we actually know the size of the control here, we restrict the font 1090 // scale to make sure the arrows will fit vertically in the bounds 1091 float fontScale = std::min(o->style()->fontSize() / baseFontSize, bounds.height() / (baseArrowHeight * 2 + baseSpaceBetweenArrows)); 1092 float centerY = bounds.y() + bounds.height() / 2.0f; 1093 float arrowHeight = baseArrowHeight * fontScale; 1094 float arrowWidth = baseArrowWidth * fontScale; 1095 float leftEdge = bounds.maxX() - arrowPaddingRight * o->style()->effectiveZoom() - arrowWidth; 1096 float spaceBetweenArrows = baseSpaceBetweenArrows * fontScale; 1097 1098 if (bounds.width() < arrowWidth + arrowPaddingLeft * o->style()->effectiveZoom()) 1099 return false; 1100 1101 GraphicsContextStateSaver stateSaver(*paintInfo.context); 1102 1103 paintInfo.context->setFillColor(o->style()->visitedDependentColor(CSSPropertyColor)); 1104 paintInfo.context->setStrokeStyle(NoStroke); 1105 1106 FloatPoint arrow1[3]; 1107 arrow1[0] = FloatPoint(leftEdge, centerY - spaceBetweenArrows / 2.0f); 1108 arrow1[1] = FloatPoint(leftEdge + arrowWidth, centerY - spaceBetweenArrows / 2.0f); 1109 arrow1[2] = FloatPoint(leftEdge + arrowWidth / 2.0f, centerY - spaceBetweenArrows / 2.0f - arrowHeight); 1110 1111 // Draw the top arrow. 1112 paintInfo.context->drawConvexPolygon(3, arrow1, true); 1113 1114 FloatPoint arrow2[3]; 1115 arrow2[0] = FloatPoint(leftEdge, centerY + spaceBetweenArrows / 2.0f); 1116 arrow2[1] = FloatPoint(leftEdge + arrowWidth, centerY + spaceBetweenArrows / 2.0f); 1117 arrow2[2] = FloatPoint(leftEdge + arrowWidth / 2.0f, centerY + spaceBetweenArrows / 2.0f + arrowHeight); 1118 1119 // Draw the bottom arrow. 1120 paintInfo.context->drawConvexPolygon(3, arrow2, true); 1121 return false; 1122} 1123 1124static const IntSize* menuListButtonSizes() 1125{ 1126 static const IntSize sizes[3] = { IntSize(0, 21), IntSize(0, 18), IntSize(0, 15) }; 1127 return sizes; 1128} 1129 1130void RenderThemeChromiumMac::adjustMenuListStyle(RenderStyle* style, Element* e) const 1131{ 1132 NSControlSize controlSize = controlSizeForFont(style); 1133 1134 style->resetBorder(); 1135 style->resetPadding(); 1136 1137 // Height is locked to auto. 1138 style->setHeight(Length(Auto)); 1139 1140 // White-space is locked to pre. 1141 style->setWhiteSpace(PRE); 1142 1143 // Set the foreground color to black or gray when we have the aqua look. 1144 // Cast to RGB32 is to work around a compiler bug. 1145 style->setColor(e && !e->isDisabledFormControl() ? static_cast<RGBA32>(Color::black) : Color::darkGray); 1146 1147 // Set the button's vertical size. 1148 setSizeFromFont(style, menuListButtonSizes()); 1149 1150 // Our font is locked to the appropriate system font size for the 1151 // control. To clarify, we first use the CSS-specified font to figure out a 1152 // reasonable control size, but once that control size is determined, we 1153 // throw that font away and use the appropriate system font for the control 1154 // size instead. 1155 setFontFromControlSize(style, controlSize); 1156} 1157 1158const int autofillPopupHorizontalPadding = 4; 1159 1160// These functions are called with MenuListPart or MenulistButtonPart appearance 1161// by RenderMenuList, or with TextFieldPart appearance by 1162// AutofillPopupMenuClient. We assume only AutofillPopupMenuClient gives 1163// TexfieldPart appearance here. We want to change only Autofill padding. In 1164// the future, we have to separate Autofill popup window logic from WebKit to 1165// Chromium. 1166int RenderThemeChromiumMac::popupInternalPaddingLeft(RenderStyle* style) const 1167{ 1168 if (style->appearance() == TextFieldPart) 1169 return autofillPopupHorizontalPadding; 1170 1171 if (style->appearance() == MenulistPart) 1172 return popupButtonPadding(controlSizeForFont(style))[ThemeMac::LeftMargin] * style->effectiveZoom(); 1173 if (style->appearance() == MenulistButtonPart) 1174 return styledPopupPaddingLeft * style->effectiveZoom(); 1175 return 0; 1176} 1177 1178int RenderThemeChromiumMac::popupInternalPaddingRight(RenderStyle* style) const 1179{ 1180 if (style->appearance() == TextFieldPart) 1181 return autofillPopupHorizontalPadding; 1182 1183 if (style->appearance() == MenulistPart) 1184 return popupButtonPadding(controlSizeForFont(style))[ThemeMac::RightMargin] * style->effectiveZoom(); 1185 if (style->appearance() == MenulistButtonPart) { 1186 float fontScale = style->fontSize() / baseFontSize; 1187 float arrowWidth = baseArrowWidth * fontScale; 1188 return static_cast<int>(ceilf(arrowWidth + (arrowPaddingLeft + arrowPaddingRight + paddingBeforeSeparator) * style->effectiveZoom())); 1189 } 1190 return 0; 1191} 1192 1193int RenderThemeChromiumMac::popupInternalPaddingTop(RenderStyle* style) const 1194{ 1195 if (style->appearance() == MenulistPart) 1196 return popupButtonPadding(controlSizeForFont(style))[ThemeMac::TopMargin] * style->effectiveZoom(); 1197 if (style->appearance() == MenulistButtonPart) 1198 return styledPopupPaddingTop * style->effectiveZoom(); 1199 return 0; 1200} 1201 1202int RenderThemeChromiumMac::popupInternalPaddingBottom(RenderStyle* style) const 1203{ 1204 if (style->appearance() == MenulistPart) 1205 return popupButtonPadding(controlSizeForFont(style))[ThemeMac::BottomMargin] * style->effectiveZoom(); 1206 if (style->appearance() == MenulistButtonPart) 1207 return styledPopupPaddingBottom * style->effectiveZoom(); 1208 return 0; 1209} 1210 1211void RenderThemeChromiumMac::adjustMenuListButtonStyle(RenderStyle* style, Element*) const 1212{ 1213 float fontScale = style->fontSize() / baseFontSize; 1214 1215 style->resetPadding(); 1216 style->setBorderRadius(IntSize(int(baseBorderRadius + fontScale - 1), int(baseBorderRadius + fontScale - 1))); // FIXME: Round up? 1217 1218 const int minHeight = 15; 1219 style->setMinHeight(Length(minHeight, Fixed)); 1220 1221 style->setLineHeight(RenderStyle::initialLineHeight()); 1222} 1223 1224void RenderThemeChromiumMac::setPopupButtonCellState(const RenderObject* o, const IntRect& r) 1225{ 1226 NSPopUpButtonCell* popupButton = this->popupButton(); 1227 1228 // Set the control size based off the rectangle we're painting into. 1229 setControlSize(popupButton, popupButtonSizes(), r.size(), o->style()->effectiveZoom()); 1230 1231 // Update the various states we respond to. 1232 updateActiveState(popupButton, o); 1233 updateCheckedState(popupButton, o); 1234 updateEnabledState(popupButton, o); 1235 updatePressedState(popupButton, o); 1236#if BUTTON_CELL_DRAW_WITH_FRAME_DRAWS_FOCUS_RING 1237 updateFocusedState(popupButton, o); 1238#endif 1239} 1240 1241const IntSize* RenderThemeChromiumMac::menuListSizes() const 1242{ 1243 static const IntSize sizes[3] = { IntSize(9, 0), IntSize(5, 0), IntSize(0, 0) }; 1244 return sizes; 1245} 1246 1247int RenderThemeChromiumMac::minimumMenuListSize(RenderStyle* style) const 1248{ 1249 return sizeForSystemFont(style, menuListSizes()).width(); 1250} 1251 1252const int sliderTrackWidth = 5; 1253const int sliderTrackBorderWidth = 1; 1254 1255bool RenderThemeChromiumMac::paintSliderTrack(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r) 1256{ 1257 paintSliderTicks(o, paintInfo, r); 1258 1259 float zoomLevel = o->style()->effectiveZoom(); 1260 FloatRect unzoomedRect = r; 1261 1262 if (o->style()->appearance() == SliderHorizontalPart || o->style()->appearance() == MediaSliderPart) { 1263 unzoomedRect.setY(ceilf(unzoomedRect.y() + unzoomedRect.height() / 2 - zoomLevel * sliderTrackWidth / 2)); 1264 unzoomedRect.setHeight(zoomLevel * sliderTrackWidth); 1265 } else if (o->style()->appearance() == SliderVerticalPart) { 1266 unzoomedRect.setX(ceilf(unzoomedRect.x() + unzoomedRect.width() / 2 - zoomLevel * sliderTrackWidth / 2)); 1267 unzoomedRect.setWidth(zoomLevel * sliderTrackWidth); 1268 } 1269 1270 if (zoomLevel != 1) { 1271 unzoomedRect.setWidth(unzoomedRect.width() / zoomLevel); 1272 unzoomedRect.setHeight(unzoomedRect.height() / zoomLevel); 1273 } 1274 1275 GraphicsContextStateSaver stateSaver(*paintInfo.context); 1276 if (zoomLevel != 1) { 1277 paintInfo.context->translate(unzoomedRect.x(), unzoomedRect.y()); 1278 paintInfo.context->scale(zoomLevel, zoomLevel); 1279 paintInfo.context->translate(-unzoomedRect.x(), -unzoomedRect.y()); 1280 } 1281 1282 Color fillColor(205, 205, 205); 1283 Color borderGradientTopColor(109, 109, 109); 1284 Color borderGradientBottomColor(181, 181, 181); 1285 Color shadowColor(0, 0, 0, 118); 1286 1287 if (!isEnabled(o)) { 1288 Color tintColor(255, 255, 255, 128); 1289 fillColor = fillColor.blend(tintColor); 1290 borderGradientTopColor = borderGradientTopColor.blend(tintColor); 1291 borderGradientBottomColor = borderGradientBottomColor.blend(tintColor); 1292 shadowColor = shadowColor.blend(tintColor); 1293 } 1294 1295 Color tintColor; 1296 if (!isEnabled(o)) 1297 tintColor = Color(255, 255, 255, 128); 1298 1299 bool isVerticalSlider = o->style()->appearance() == SliderVerticalPart; 1300 1301 int fillRadiusSize = (sliderTrackWidth - sliderTrackBorderWidth) / 2; 1302 IntSize fillRadius(fillRadiusSize, fillRadiusSize); 1303 IntRect fillBounds = enclosedIntRect(unzoomedRect); 1304 RoundedRect fillRect(fillBounds, fillRadius, fillRadius, fillRadius, fillRadius); 1305 paintInfo.context->fillRoundedRect(fillRect, fillColor); 1306 1307 IntSize shadowOffset(isVerticalSlider ? 1 : 0, 1308 isVerticalSlider ? 0 : 1); 1309 int shadowBlur = 3; 1310 int shadowSpread = 0; 1311 paintInfo.context->save(); 1312 paintInfo.context->drawInnerShadow(fillRect, shadowColor, shadowOffset, shadowBlur, shadowSpread); 1313 paintInfo.context->restore(); 1314 1315 RefPtr<Gradient> borderGradient = Gradient::create(fillBounds.minXMinYCorner(), 1316 isVerticalSlider ? fillBounds.maxXMinYCorner() : fillBounds.minXMaxYCorner()); 1317 borderGradient->addColorStop(0.0, borderGradientTopColor); 1318 borderGradient->addColorStop(1.0, borderGradientBottomColor); 1319 Path borderPath; 1320 FloatRect borderRect(unzoomedRect); 1321 borderRect.inflate(-sliderTrackBorderWidth / 2.0); 1322 float borderRadiusSize = (isVerticalSlider ? borderRect.width() : borderRect.height()) / 2; 1323 FloatSize borderRadius(borderRadiusSize, borderRadiusSize); 1324 borderPath.addRoundedRect(borderRect, borderRadius, borderRadius, borderRadius, borderRadius); 1325 paintInfo.context->setStrokeGradient(borderGradient); 1326 paintInfo.context->setStrokeThickness(sliderTrackBorderWidth); 1327 paintInfo.context->strokePath(borderPath); 1328 return false; 1329} 1330 1331const int sliderThumbWidth = 15; 1332const int sliderThumbHeight = 15; 1333const int sliderThumbBorderWidth = 1; 1334 1335bool RenderThemeChromiumMac::paintSliderThumb(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r) 1336{ 1337 GraphicsContextStateSaver stateSaver(*paintInfo.context); 1338 float zoomLevel = o->style()->effectiveZoom(); 1339 1340 FloatRect unzoomedRect(r.x(), r.y(), sliderThumbWidth, sliderThumbHeight); 1341 if (zoomLevel != 1.0f) { 1342 paintInfo.context->translate(unzoomedRect.x(), unzoomedRect.y()); 1343 paintInfo.context->scale(zoomLevel, zoomLevel); 1344 paintInfo.context->translate(-unzoomedRect.x(), -unzoomedRect.y()); 1345 } 1346 1347 Color fillGradientTopColor(250, 250, 250); 1348 Color fillGradientUpperMiddleColor(244, 244, 244); 1349 Color fillGradientLowerMiddleColor(236, 236, 236); 1350 Color fillGradientBottomColor(238, 238, 238); 1351 Color borderGradientTopColor(151, 151, 151); 1352 Color borderGradientBottomColor(128, 128, 128); 1353 Color shadowColor(0, 0, 0, 36); 1354 1355 if (!isEnabled(o)) { 1356 Color tintColor(255, 255, 255, 128); 1357 fillGradientTopColor = fillGradientTopColor.blend(tintColor); 1358 fillGradientUpperMiddleColor = fillGradientUpperMiddleColor.blend(tintColor); 1359 fillGradientLowerMiddleColor = fillGradientLowerMiddleColor.blend(tintColor); 1360 fillGradientBottomColor = fillGradientBottomColor.blend(tintColor); 1361 borderGradientTopColor = borderGradientTopColor.blend(tintColor); 1362 borderGradientBottomColor = borderGradientBottomColor.blend(tintColor); 1363 shadowColor = shadowColor.blend(tintColor); 1364 } else if (isPressed(o)) { 1365 Color tintColor(0, 0, 0, 32); 1366 fillGradientTopColor = fillGradientTopColor.blend(tintColor); 1367 fillGradientUpperMiddleColor = fillGradientUpperMiddleColor.blend(tintColor); 1368 fillGradientLowerMiddleColor = fillGradientLowerMiddleColor.blend(tintColor); 1369 fillGradientBottomColor = fillGradientBottomColor.blend(tintColor); 1370 borderGradientTopColor = borderGradientTopColor.blend(tintColor); 1371 borderGradientBottomColor = borderGradientBottomColor.blend(tintColor); 1372 shadowColor = shadowColor.blend(tintColor); 1373 } 1374 1375 FloatRect borderBounds = unzoomedRect; 1376 borderBounds.inflate(sliderThumbBorderWidth / 2.0); 1377 1378 borderBounds.inflate(-sliderThumbBorderWidth); 1379 FloatSize shadowOffset(0, 1); 1380 paintInfo.context->setShadow(shadowOffset, sliderThumbShadowBlur, shadowColor); 1381 paintInfo.context->setFillColor(Color::black); 1382 paintInfo.context->fillEllipse(borderBounds); 1383 paintInfo.context->clearShadow(); 1384 1385 IntRect fillBounds = enclosedIntRect(unzoomedRect); 1386 RefPtr<Gradient> fillGradient = Gradient::create(fillBounds.minXMinYCorner(), fillBounds.minXMaxYCorner()); 1387 fillGradient->addColorStop(0.0, fillGradientTopColor); 1388 fillGradient->addColorStop(0.52, fillGradientUpperMiddleColor); 1389 fillGradient->addColorStop(0.52, fillGradientLowerMiddleColor); 1390 fillGradient->addColorStop(1.0, fillGradientBottomColor); 1391 paintInfo.context->setFillGradient(fillGradient); 1392 paintInfo.context->fillEllipse(borderBounds); 1393 1394 RefPtr<Gradient> borderGradient = Gradient::create(fillBounds.minXMinYCorner(), fillBounds.minXMaxYCorner()); 1395 borderGradient->addColorStop(0.0, borderGradientTopColor); 1396 borderGradient->addColorStop(1.0, borderGradientBottomColor); 1397 paintInfo.context->setStrokeGradient(borderGradient); 1398 paintInfo.context->setStrokeThickness(sliderThumbBorderWidth); 1399 paintInfo.context->strokeEllipse(borderBounds); 1400 1401 if (isFocused(o)) { 1402 Path borderPath; 1403 borderPath.addEllipse(borderBounds); 1404 paintInfo.context->drawFocusRing(borderPath, 5, -2, focusRingColor()); 1405 } 1406 1407 return false; 1408} 1409 1410bool RenderThemeChromiumMac::paintSearchField(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r) 1411{ 1412 LocalCurrentGraphicsContext localContext(paintInfo.context, r); 1413 1414 NSSearchFieldCell* search = this->search(); 1415 setSearchCellState(o, r); 1416 [search setControlSize:searchFieldControlSizeForFont(o->style())]; 1417 1418 GraphicsContextStateSaver stateSaver(*paintInfo.context); 1419 1420 float zoomLevel = o->style()->effectiveZoom(); 1421 1422 IntRect unzoomedRect = r; 1423 1424 if (zoomLevel != 1.0f) { 1425 unzoomedRect.setWidth(unzoomedRect.width() / zoomLevel); 1426 unzoomedRect.setHeight(unzoomedRect.height() / zoomLevel); 1427 paintInfo.context->translate(unzoomedRect.x(), unzoomedRect.y()); 1428 paintInfo.context->scale(zoomLevel, zoomLevel); 1429 paintInfo.context->translate(-unzoomedRect.x(), -unzoomedRect.y()); 1430 } 1431 1432 // Set the search button to nil before drawing. Then reset it so we can 1433 // draw it later. 1434 [search setSearchButtonCell:nil]; 1435 1436 [search drawWithFrame:NSRect(unzoomedRect) inView:documentViewFor(o)]; 1437 1438 [search setControlView:nil]; 1439 [search resetSearchButtonCell]; 1440 1441 return false; 1442} 1443 1444void RenderThemeChromiumMac::setSearchCellState(RenderObject* o, const IntRect&) 1445{ 1446 NSSearchFieldCell* search = this->search(); 1447 1448 // Update the various states we respond to. 1449 updateActiveState(search, o); 1450 updateEnabledState(search, o); 1451 updateFocusedState(search, o); 1452} 1453 1454const IntSize* RenderThemeChromiumMac::searchFieldSizes() const 1455{ 1456 static const IntSize sizes[3] = { IntSize(0, 22), IntSize(0, 19), IntSize(0, 15) }; 1457 return sizes; 1458} 1459 1460static const int* searchFieldHorizontalPaddings() 1461{ 1462 static const int sizes[3] = { 3, 2, 1 }; 1463 return sizes; 1464} 1465 1466void RenderThemeChromiumMac::setSearchFieldSize(RenderStyle* style) const 1467{ 1468 // If the width and height are both specified, then we have nothing to do. 1469 if (!style->width().isIntrinsicOrAuto() && !style->height().isAuto()) 1470 return; 1471 1472 // Use the font size to determine the intrinsic width of the control. 1473 setSizeFromFont(style, searchFieldSizes()); 1474} 1475 1476const int searchFieldBorderWidth = 2; 1477void RenderThemeChromiumMac::adjustSearchFieldStyle(RenderStyle* style, Element*) const 1478{ 1479 // Override border. 1480 style->resetBorder(); 1481 const short borderWidth = searchFieldBorderWidth * style->effectiveZoom(); 1482 style->setBorderLeftWidth(borderWidth); 1483 style->setBorderLeftStyle(INSET); 1484 style->setBorderRightWidth(borderWidth); 1485 style->setBorderRightStyle(INSET); 1486 style->setBorderBottomWidth(borderWidth); 1487 style->setBorderBottomStyle(INSET); 1488 style->setBorderTopWidth(borderWidth); 1489 style->setBorderTopStyle(INSET); 1490 1491 // Override height. 1492 style->setHeight(Length(Auto)); 1493 setSearchFieldSize(style); 1494 1495 NSControlSize controlSize = controlSizeForFont(style); 1496 1497 // Override padding size to match AppKit text positioning. 1498 const int verticalPadding = 1 * style->effectiveZoom(); 1499 const int horizontalPadding = searchFieldHorizontalPaddings()[controlSize] * style->effectiveZoom(); 1500 style->setPaddingLeft(Length(horizontalPadding, Fixed)); 1501 style->setPaddingRight(Length(horizontalPadding, Fixed)); 1502 style->setPaddingTop(Length(verticalPadding, Fixed)); 1503 style->setPaddingBottom(Length(verticalPadding, Fixed)); 1504 1505 setFontFromControlSize(style, controlSize); 1506 1507 style->setBoxShadow(nullptr); 1508} 1509 1510bool RenderThemeChromiumMac::paintSearchFieldCancelButton(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r) 1511{ 1512 if (!o->node()) 1513 return false; 1514 Element* input = o->node()->shadowHost(); 1515 if (!input) 1516 input = toElement(o->node()); 1517 1518 if (!input->renderer()->isBox()) 1519 return false; 1520 1521 GraphicsContextStateSaver stateSaver(*paintInfo.context); 1522 1523 float zoomLevel = o->style()->effectiveZoom(); 1524 FloatRect unzoomedRect(r); 1525 if (zoomLevel != 1.0f) { 1526 unzoomedRect.setWidth(unzoomedRect.width() / zoomLevel); 1527 unzoomedRect.setHeight(unzoomedRect.height() / zoomLevel); 1528 paintInfo.context->translate(unzoomedRect.x(), unzoomedRect.y()); 1529 paintInfo.context->scale(zoomLevel, zoomLevel); 1530 paintInfo.context->translate(-unzoomedRect.x(), -unzoomedRect.y()); 1531 } 1532 1533 Color fillColor(200, 200, 200); 1534 1535 if (isPressed(o)) { 1536 Color tintColor(0, 0, 0, 32); 1537 fillColor = fillColor.blend(tintColor); 1538 } 1539 1540 float centerX = unzoomedRect.x() + unzoomedRect.width() / 2; 1541 float centerY = unzoomedRect.y() + unzoomedRect.height() / 2; 1542 // The line width is 3px on a regular sized, high DPI NSCancelButtonCell 1543 // (which is 28px wide). 1544 float lineWidth = unzoomedRect.width() * 3 / 28; 1545 // The line length is 16px on a regular sized, high DPI NSCancelButtonCell. 1546 float lineLength = unzoomedRect.width() * 16 / 28; 1547 1548 Path xPath; 1549 FloatSize lineRectRadius(lineWidth / 2, lineWidth / 2); 1550 xPath.addRoundedRect(FloatRect(-lineLength / 2, -lineWidth / 2, lineLength, lineWidth), 1551 lineRectRadius, lineRectRadius, lineRectRadius, lineRectRadius); 1552 xPath.addRoundedRect(FloatRect(-lineWidth / 2, -lineLength / 2, lineWidth, lineLength), 1553 lineRectRadius, lineRectRadius, lineRectRadius, lineRectRadius); 1554 1555 paintInfo.context->translate(centerX, centerY); 1556 paintInfo.context->rotate(deg2rad(45.0)); 1557 paintInfo.context->clipOut(xPath); 1558 paintInfo.context->rotate(deg2rad(-45.0)); 1559 paintInfo.context->translate(-centerX, -centerY); 1560 1561 paintInfo.context->setFillColor(fillColor); 1562 paintInfo.context->fillEllipse(unzoomedRect); 1563 1564 return false; 1565} 1566 1567const IntSize* RenderThemeChromiumMac::cancelButtonSizes() const 1568{ 1569 static const IntSize sizes[3] = { IntSize(14, 14), IntSize(11, 11), IntSize(9, 9) }; 1570 return sizes; 1571} 1572 1573void RenderThemeChromiumMac::adjustSearchFieldCancelButtonStyle(RenderStyle* style, Element*) const 1574{ 1575 IntSize size = sizeForSystemFont(style, cancelButtonSizes()); 1576 style->setWidth(Length(size.width(), Fixed)); 1577 style->setHeight(Length(size.height(), Fixed)); 1578 style->setBoxShadow(nullptr); 1579} 1580 1581const IntSize* RenderThemeChromiumMac::resultsButtonSizes() const 1582{ 1583 static const IntSize sizes[3] = { IntSize(15, 14), IntSize(16, 13), IntSize(14, 11) }; 1584 return sizes; 1585} 1586 1587void RenderThemeChromiumMac::adjustSearchFieldDecorationStyle(RenderStyle* style, Element*) const 1588{ 1589 NSControlSize controlSize = controlSizeForSystemFont(style); 1590 IntSize searchFieldSize = searchFieldSizes()[controlSize]; 1591 int width = searchFieldSize.height() / 2 - searchFieldBorderWidth - searchFieldHorizontalPaddings()[controlSize]; 1592 style->setWidth(Length(width, Fixed)); 1593 style->setHeight(Length(0, Fixed)); 1594 style->setBoxShadow(nullptr); 1595} 1596 1597bool RenderThemeChromiumMac::paintSearchFieldDecoration(RenderObject*, const PaintInfo&, const IntRect&) 1598{ 1599 return false; 1600} 1601 1602void RenderThemeChromiumMac::adjustSearchFieldResultsDecorationStyle(RenderStyle* style, Element*) const 1603{ 1604 IntSize size = sizeForSystemFont(style, resultsButtonSizes()); 1605 style->setWidth(Length(size.width(), Fixed)); 1606 style->setHeight(Length(size.height(), Fixed)); 1607 style->setBoxShadow(nullptr); 1608} 1609 1610bool RenderThemeChromiumMac::paintSearchFieldResultsDecoration(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r) 1611{ 1612 if (!o->node()) 1613 return false; 1614 Node* input = o->node()->shadowHost(); 1615 if (!input) 1616 input = o->node(); 1617 if (!input->renderer()->isBox()) 1618 return false; 1619 1620 GraphicsContextStateSaver stateSaver(*paintInfo.context); 1621 1622 float zoomLevel = o->style()->effectiveZoom(); 1623 FloatRect unzoomedRect(r); 1624 if (zoomLevel != 1) { 1625 unzoomedRect.setWidth(unzoomedRect.width() / zoomLevel); 1626 unzoomedRect.setHeight(unzoomedRect.height() / zoomLevel); 1627 paintInfo.context->translate(unzoomedRect.x(), unzoomedRect.y()); 1628 paintInfo.context->scale(zoomLevel, zoomLevel); 1629 paintInfo.context->translate(-unzoomedRect.x(), -unzoomedRect.y()); 1630 } 1631 1632 LocalCurrentGraphicsContext localContext(paintInfo.context, r); 1633 1634 NSSearchFieldCell* search = this->search(); 1635 setSearchCellState(input->renderer(), r); 1636 [search setControlSize:searchFieldControlSizeForFont(o->style())]; 1637 if ([search searchMenuTemplate] != nil) 1638 [search setSearchMenuTemplate:nil]; 1639 1640 updateActiveState([search searchButtonCell], o); 1641 1642 [[search searchButtonCell] drawWithFrame:unzoomedRect inView:documentViewFor(o)]; 1643 [[search searchButtonCell] setControlView:nil]; 1644 return false; 1645} 1646 1647IntSize RenderThemeChromiumMac::sliderTickSize() const 1648{ 1649 return IntSize(1, 3); 1650} 1651 1652int RenderThemeChromiumMac::sliderTickOffsetFromTrackCenter() const 1653{ 1654 return -9; 1655} 1656 1657void RenderThemeChromiumMac::adjustSliderThumbSize(RenderStyle* style, Element*) const 1658{ 1659 float zoomLevel = style->effectiveZoom(); 1660 if (style->appearance() == SliderThumbHorizontalPart || style->appearance() == SliderThumbVerticalPart) { 1661 style->setWidth(Length(static_cast<int>(sliderThumbWidth * zoomLevel), Fixed)); 1662 style->setHeight(Length(static_cast<int>(sliderThumbHeight * zoomLevel), Fixed)); 1663 } 1664 1665 adjustMediaSliderThumbSize(style); 1666} 1667 1668NSPopUpButtonCell* RenderThemeChromiumMac::popupButton() const 1669{ 1670 if (!m_popupButton) { 1671 m_popupButton.adoptNS([[NSPopUpButtonCell alloc] initTextCell:@"" pullsDown:NO]); 1672 [m_popupButton.get() setUsesItemFromMenu:NO]; 1673 [m_popupButton.get() setFocusRingType:NSFocusRingTypeExterior]; 1674 } 1675 1676 return m_popupButton.get(); 1677} 1678 1679NSSearchFieldCell* RenderThemeChromiumMac::search() const 1680{ 1681 if (!m_search) { 1682 m_search.adoptNS([[NSSearchFieldCell alloc] initTextCell:@""]); 1683 [m_search.get() setBezelStyle:NSTextFieldRoundedBezel]; 1684 [m_search.get() setBezeled:YES]; 1685 [m_search.get() setEditable:YES]; 1686 [m_search.get() setFocusRingType:NSFocusRingTypeExterior]; 1687 SEL sel = @selector(setCenteredLook:); 1688 if ([m_search.get() respondsToSelector:sel]) { 1689 BOOL boolValue = NO; 1690 NSMethodSignature* signature = [NSSearchFieldCell instanceMethodSignatureForSelector:sel]; 1691 NSInvocation* invocation = [NSInvocation invocationWithMethodSignature:signature]; 1692 [invocation setTarget:m_search.get()]; 1693 [invocation setSelector:sel]; 1694 [invocation setArgument:&boolValue atIndex:2]; 1695 [invocation invoke]; 1696 } 1697 } 1698 1699 return m_search.get(); 1700} 1701 1702NSTextFieldCell* RenderThemeChromiumMac::textField() const 1703{ 1704 if (!m_textField) { 1705 m_textField.adoptNS([[WebCoreTextFieldCell alloc] initTextCell:@""]); 1706 [m_textField.get() setBezeled:YES]; 1707 [m_textField.get() setEditable:YES]; 1708 [m_textField.get() setFocusRingType:NSFocusRingTypeExterior]; 1709#if __MAC_OS_X_VERSION_MIN_REQUIRED <= 1070 1710 [m_textField.get() setDrawsBackground:YES]; 1711 [m_textField.get() setBackgroundColor:[NSColor whiteColor]]; 1712#else 1713 // Post-Lion, WebCore can be in charge of paintinng the background 1714 // thanks to the workaround in place for <rdar://problem/11385461>, 1715 // which is implemented above as _coreUIDrawOptionsWithFrame. 1716 [m_textField.get() setDrawsBackground:NO]; 1717#endif 1718 } 1719 1720 return m_textField.get(); 1721} 1722 1723String RenderThemeChromiumMac::fileListNameForWidth(Locale& locale, const FileList* fileList, const Font& font, int width) const 1724{ 1725 if (width <= 0) 1726 return String(); 1727 1728 String strToTruncate; 1729 if (fileList->isEmpty()) { 1730 strToTruncate = locale.queryString(WebLocalizedString::FileButtonNoFileSelectedLabel); 1731 } else if (fileList->length() == 1) { 1732 File* file = fileList->item(0); 1733 if (file->userVisibility() == File::IsUserVisible) 1734 strToTruncate = [[NSFileManager defaultManager] displayNameAtPath:(fileList->item(0)->path())]; 1735 else 1736 strToTruncate = file->name(); 1737 } else { 1738 // FIXME: Localization of fileList->length(). 1739 return StringTruncator::rightTruncate(locale.queryString(WebLocalizedString::MultipleFileUploadText, String::number(fileList->length())), width, font); 1740 } 1741 1742 return StringTruncator::centerTruncate(strToTruncate, width, font); 1743} 1744 1745NSView* FlippedView() 1746{ 1747 static NSView* view = [[RTCMFlippedView alloc] init]; 1748 return view; 1749} 1750 1751RenderTheme& RenderTheme::theme() 1752{ 1753 DEFINE_STATIC_REF(RenderTheme, renderTheme, (RenderThemeChromiumMac::create())); 1754 return *renderTheme; 1755} 1756 1757PassRefPtr<RenderTheme> RenderThemeChromiumMac::create() 1758{ 1759 return adoptRef(new RenderThemeChromiumMac); 1760} 1761 1762bool RenderThemeChromiumMac::usesTestModeFocusRingColor() const 1763{ 1764 return LayoutTestSupport::isRunningLayoutTest(); 1765} 1766 1767NSView* RenderThemeChromiumMac::documentViewFor(RenderObject*) const 1768{ 1769 return FlippedView(); 1770} 1771 1772// Updates the control tint (a.k.a. active state) of |cell| (from |o|). In the 1773// Chromium port, the renderer runs as a background process and controls' 1774// NSCell(s) lack a parent NSView. Therefore controls don't have their tint 1775// color updated correctly when the application is activated/deactivated. 1776// FocusController's setActive() is called when the application is 1777// activated/deactivated, which causes a paint invalidation at which time this 1778// code is called. 1779// This function should be called before drawing any NSCell-derived controls, 1780// unless you're sure it isn't needed. 1781void RenderThemeChromiumMac::updateActiveState(NSCell* cell, const RenderObject* o) 1782{ 1783 NSControlTint oldTint = [cell controlTint]; 1784 NSControlTint tint = isActive(o) ? [NSColor currentControlTint] : 1785 static_cast<NSControlTint>(NSClearControlTint); 1786 1787 if (tint != oldTint) 1788 [cell setControlTint:tint]; 1789} 1790 1791bool RenderThemeChromiumMac::shouldShowPlaceholderWhenFocused() const 1792{ 1793 return true; 1794} 1795 1796void RenderThemeChromiumMac::adjustMediaSliderThumbSize(RenderStyle* style) const 1797{ 1798 RenderMediaControls::adjustMediaSliderThumbSize(style); 1799} 1800 1801bool RenderThemeChromiumMac::paintMediaPlayButton(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect) 1802{ 1803 return RenderMediaControls::paintMediaControlsPart(MediaPlayButton, object, paintInfo, rect); 1804} 1805 1806bool RenderThemeChromiumMac::paintMediaOverlayPlayButton(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect) 1807{ 1808 return RenderMediaControls::paintMediaControlsPart(MediaOverlayPlayButton, object, paintInfo, rect); 1809} 1810 1811bool RenderThemeChromiumMac::paintMediaMuteButton(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect) 1812{ 1813 return RenderMediaControls::paintMediaControlsPart(MediaMuteButton, object, paintInfo, rect); 1814} 1815 1816bool RenderThemeChromiumMac::paintMediaSliderTrack(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect) 1817{ 1818 return RenderMediaControls::paintMediaControlsPart(MediaSlider, object, paintInfo, rect); 1819} 1820 1821String RenderThemeChromiumMac::extraFullScreenStyleSheet() 1822{ 1823 // FIXME: Chromium may wish to style its default media controls differently in fullscreen. 1824 return String(); 1825} 1826 1827String RenderThemeChromiumMac::extraDefaultStyleSheet() 1828{ 1829 return RenderTheme::extraDefaultStyleSheet() + 1830 String(themeChromiumCss, sizeof(themeChromiumCss)) + 1831 String(themeInputMultipleFieldsCss, sizeof(themeInputMultipleFieldsCss)) + 1832 String(themeMacCss, sizeof(themeMacCss)); 1833} 1834 1835bool RenderThemeChromiumMac::paintMediaVolumeSliderContainer(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect) 1836{ 1837 return true; 1838} 1839 1840bool RenderThemeChromiumMac::paintMediaVolumeSliderTrack(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect) 1841{ 1842 return RenderMediaControls::paintMediaControlsPart(MediaVolumeSlider, object, paintInfo, rect); 1843} 1844 1845bool RenderThemeChromiumMac::paintMediaVolumeSliderThumb(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect) 1846{ 1847 return RenderMediaControls::paintMediaControlsPart(MediaVolumeSliderThumb, object, paintInfo, rect); 1848} 1849 1850bool RenderThemeChromiumMac::paintMediaSliderThumb(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect) 1851{ 1852 return RenderMediaControls::paintMediaControlsPart(MediaSliderThumb, object, paintInfo, rect); 1853} 1854 1855String RenderThemeChromiumMac::formatMediaControlsTime(float time) const 1856{ 1857 return RenderMediaControls::formatMediaControlsTime(time); 1858} 1859 1860String RenderThemeChromiumMac::formatMediaControlsCurrentTime(float currentTime, float duration) const 1861{ 1862 return RenderMediaControls::formatMediaControlsCurrentTime(currentTime, duration); 1863} 1864 1865bool RenderThemeChromiumMac::paintMediaFullscreenButton(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect) 1866{ 1867 return RenderMediaControls::paintMediaControlsPart(MediaEnterFullscreenButton, object, paintInfo, rect); 1868} 1869 1870bool RenderThemeChromiumMac::paintMediaToggleClosedCaptionsButton(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect) 1871{ 1872 return RenderMediaControls::paintMediaControlsPart(MediaShowClosedCaptionsButton, object, paintInfo, rect); 1873} 1874 1875bool RenderThemeChromiumMac::shouldUseFallbackTheme(RenderStyle* style) const 1876{ 1877 ControlPart part = style->appearance(); 1878 if (part == CheckboxPart || part == RadioPart) 1879 return style->effectiveZoom() != 1; 1880 return false; 1881} 1882 1883} // namespace blink 1884