1 /* 2 * Copyright (C) 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. 3 * 4 * This library is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU Library General Public 6 * License as published by the Free Software Foundation; either 7 * version 2 of the License, or (at your option) any later version. 8 * 9 * This library is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 * Library General Public License for more details. 13 * 14 * You should have received a copy of the GNU Library General Public License 15 * along with this library; see the file COPYING.LIB. If not, write to 16 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 17 * Boston, MA 02110-1301, USA. 18 */ 19 20 #import "config.h" 21 #import "RenderThemeMac.h" 22 23 #import "BitmapImage.h" 24 #import "ColorMac.h" 25 #import "CSSStyleSelector.h" 26 #import "CSSValueKeywords.h" 27 #import "Document.h" 28 #import "Element.h" 29 #import "FrameView.h" 30 #import "GraphicsContext.h" 31 #import "HTMLInputElement.h" 32 #import "HTMLMediaElement.h" 33 #import "HTMLNames.h" 34 #import "Image.h" 35 #import "LocalCurrentGraphicsContext.h" 36 #import "MediaControlElements.h" 37 #import "RenderMedia.h" 38 #import "RenderSlider.h" 39 #import "RenderView.h" 40 #import "SharedBuffer.h" 41 #import "TimeRanges.h" 42 #import "WebCoreSystemInterface.h" 43 #import "UserAgentStyleSheets.h" 44 #import <Carbon/Carbon.h> 45 #import <Cocoa/Cocoa.h> 46 #import <wtf/RetainPtr.h> 47 #import <wtf/StdLibExtras.h> 48 #import <math.h> 49 50 #ifdef BUILDING_ON_TIGER 51 typedef int NSInteger; 52 typedef unsigned NSUInteger; 53 #endif 54 55 using std::min; 56 57 // The methods in this file are specific to the Mac OS X platform. 58 59 // FIXME: The platform-independent code in this class should be factored out and merged with RenderThemeSafari. 60 61 @interface WebCoreRenderThemeNotificationObserver : NSObject 62 { 63 WebCore::RenderTheme *_theme; 64 } 65 66 - (id)initWithTheme:(WebCore::RenderTheme *)theme; 67 - (void)systemColorsDidChange:(NSNotification *)notification; 68 69 @end 70 71 @implementation WebCoreRenderThemeNotificationObserver 72 73 - (id)initWithTheme:(WebCore::RenderTheme *)theme 74 { 75 [super init]; 76 _theme = theme; 77 78 return self; 79 } 80 81 - (void)systemColorsDidChange:(NSNotification *)unusedNotification 82 { 83 ASSERT_UNUSED(unusedNotification, [[unusedNotification name] isEqualToString:NSSystemColorsDidChangeNotification]); 84 _theme->platformColorsDidChange(); 85 } 86 87 @end 88 89 namespace WebCore { 90 91 using namespace HTMLNames; 92 93 enum { 94 topMargin, 95 rightMargin, 96 bottomMargin, 97 leftMargin 98 }; 99 100 enum { 101 topPadding, 102 rightPadding, 103 bottomPadding, 104 leftPadding 105 }; 106 107 PassRefPtr<RenderTheme> RenderTheme::themeForPage(Page*) 108 { 109 static RenderTheme* rt = RenderThemeMac::create().releaseRef(); 110 return rt; 111 } 112 113 PassRefPtr<RenderTheme> RenderThemeMac::create() 114 { 115 return adoptRef(new RenderThemeMac); 116 } 117 118 RenderThemeMac::RenderThemeMac() 119 : m_isSliderThumbHorizontalPressed(false) 120 , m_isSliderThumbVerticalPressed(false) 121 , m_notificationObserver(AdoptNS, [[WebCoreRenderThemeNotificationObserver alloc] initWithTheme:this]) 122 { 123 [[NSNotificationCenter defaultCenter] addObserver:m_notificationObserver.get() 124 selector:@selector(systemColorsDidChange:) 125 name:NSSystemColorsDidChangeNotification 126 object:nil]; 127 } 128 129 RenderThemeMac::~RenderThemeMac() 130 { 131 [[NSNotificationCenter defaultCenter] removeObserver:m_notificationObserver.get()]; 132 } 133 134 Color RenderThemeMac::platformActiveSelectionBackgroundColor() const 135 { 136 NSColor* color = [[NSColor selectedTextBackgroundColor] colorUsingColorSpaceName:NSDeviceRGBColorSpace]; 137 return Color(static_cast<int>(255.0 * [color redComponent]), static_cast<int>(255.0 * [color greenComponent]), static_cast<int>(255.0 * [color blueComponent])); 138 } 139 140 Color RenderThemeMac::platformInactiveSelectionBackgroundColor() const 141 { 142 NSColor* color = [[NSColor secondarySelectedControlColor] colorUsingColorSpaceName:NSDeviceRGBColorSpace]; 143 return Color(static_cast<int>(255.0 * [color redComponent]), static_cast<int>(255.0 * [color greenComponent]), static_cast<int>(255.0 * [color blueComponent])); 144 } 145 146 Color RenderThemeMac::platformActiveListBoxSelectionBackgroundColor() const 147 { 148 NSColor* color = [[NSColor alternateSelectedControlColor] colorUsingColorSpaceName:NSDeviceRGBColorSpace]; 149 return Color(static_cast<int>(255.0 * [color redComponent]), static_cast<int>(255.0 * [color greenComponent]), static_cast<int>(255.0 * [color blueComponent])); 150 } 151 152 Color RenderThemeMac::platformActiveListBoxSelectionForegroundColor() const 153 { 154 return Color::white; 155 } 156 157 Color RenderThemeMac::platformInactiveListBoxSelectionForegroundColor() const 158 { 159 return Color::black; 160 } 161 162 Color RenderThemeMac::platformFocusRingColor() const 163 { 164 if (usesTestModeFocusRingColor()) 165 return oldAquaFocusRingColor(); 166 167 return systemColor(CSSValueWebkitFocusRingColor); 168 } 169 170 Color RenderThemeMac::platformInactiveListBoxSelectionBackgroundColor() const 171 { 172 return platformInactiveSelectionBackgroundColor(); 173 } 174 175 static FontWeight toFontWeight(NSInteger appKitFontWeight) 176 { 177 ASSERT(appKitFontWeight > 0 && appKitFontWeight < 15); 178 if (appKitFontWeight > 14) 179 appKitFontWeight = 14; 180 else if (appKitFontWeight < 1) 181 appKitFontWeight = 1; 182 183 static FontWeight fontWeights[] = { 184 FontWeight100, 185 FontWeight100, 186 FontWeight200, 187 FontWeight300, 188 FontWeight400, 189 FontWeight500, 190 FontWeight600, 191 FontWeight600, 192 FontWeight700, 193 FontWeight800, 194 FontWeight800, 195 FontWeight900, 196 FontWeight900, 197 FontWeight900 198 }; 199 return fontWeights[appKitFontWeight - 1]; 200 } 201 202 void RenderThemeMac::systemFont(int cssValueId, FontDescription& fontDescription) const 203 { 204 DEFINE_STATIC_LOCAL(FontDescription, systemFont, ()); 205 DEFINE_STATIC_LOCAL(FontDescription, smallSystemFont, ()); 206 DEFINE_STATIC_LOCAL(FontDescription, menuFont, ()); 207 DEFINE_STATIC_LOCAL(FontDescription, labelFont, ()); 208 DEFINE_STATIC_LOCAL(FontDescription, miniControlFont, ()); 209 DEFINE_STATIC_LOCAL(FontDescription, smallControlFont, ()); 210 DEFINE_STATIC_LOCAL(FontDescription, controlFont, ()); 211 212 FontDescription* cachedDesc; 213 NSFont* font = nil; 214 switch (cssValueId) { 215 case CSSValueSmallCaption: 216 cachedDesc = &smallSystemFont; 217 if (!smallSystemFont.isAbsoluteSize()) 218 font = [NSFont systemFontOfSize:[NSFont smallSystemFontSize]]; 219 break; 220 case CSSValueMenu: 221 cachedDesc = &menuFont; 222 if (!menuFont.isAbsoluteSize()) 223 font = [NSFont menuFontOfSize:[NSFont systemFontSize]]; 224 break; 225 case CSSValueStatusBar: 226 cachedDesc = &labelFont; 227 if (!labelFont.isAbsoluteSize()) 228 font = [NSFont labelFontOfSize:[NSFont labelFontSize]]; 229 break; 230 case CSSValueWebkitMiniControl: 231 cachedDesc = &miniControlFont; 232 if (!miniControlFont.isAbsoluteSize()) 233 font = [NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:NSMiniControlSize]]; 234 break; 235 case CSSValueWebkitSmallControl: 236 cachedDesc = &smallControlFont; 237 if (!smallControlFont.isAbsoluteSize()) 238 font = [NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:NSSmallControlSize]]; 239 break; 240 case CSSValueWebkitControl: 241 cachedDesc = &controlFont; 242 if (!controlFont.isAbsoluteSize()) 243 font = [NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:NSRegularControlSize]]; 244 break; 245 default: 246 cachedDesc = &systemFont; 247 if (!systemFont.isAbsoluteSize()) 248 font = [NSFont systemFontOfSize:[NSFont systemFontSize]]; 249 } 250 251 if (font) { 252 NSFontManager *fontManager = [NSFontManager sharedFontManager]; 253 cachedDesc->setIsAbsoluteSize(true); 254 cachedDesc->setGenericFamily(FontDescription::NoFamily); 255 cachedDesc->firstFamily().setFamily([font familyName]); 256 cachedDesc->setSpecifiedSize([font pointSize]); 257 cachedDesc->setWeight(toFontWeight([fontManager weightOfFont:font])); 258 cachedDesc->setItalic([fontManager traitsOfFont:font] & NSItalicFontMask); 259 } 260 fontDescription = *cachedDesc; 261 } 262 263 static RGBA32 convertNSColorToColor(NSColor *color) 264 { 265 NSColor *colorInColorSpace = [color colorUsingColorSpaceName:NSDeviceRGBColorSpace]; 266 if (colorInColorSpace) { 267 static const double scaleFactor = nextafter(256.0, 0.0); 268 return makeRGB(static_cast<int>(scaleFactor * [colorInColorSpace redComponent]), 269 static_cast<int>(scaleFactor * [colorInColorSpace greenComponent]), 270 static_cast<int>(scaleFactor * [colorInColorSpace blueComponent])); 271 } 272 273 // This conversion above can fail if the NSColor in question is an NSPatternColor 274 // (as many system colors are). These colors are actually a repeating pattern 275 // not just a solid color. To work around this we simply draw a 1x1 image of 276 // the color and use that pixel's color. It might be better to use an average of 277 // the colors in the pattern instead. 278 NSBitmapImageRep *offscreenRep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:nil 279 pixelsWide:1 280 pixelsHigh:1 281 bitsPerSample:8 282 samplesPerPixel:4 283 hasAlpha:YES 284 isPlanar:NO 285 colorSpaceName:NSDeviceRGBColorSpace 286 bytesPerRow:4 287 bitsPerPixel:32]; 288 289 [NSGraphicsContext saveGraphicsState]; 290 [NSGraphicsContext setCurrentContext:[NSGraphicsContext graphicsContextWithBitmapImageRep:offscreenRep]]; 291 NSEraseRect(NSMakeRect(0, 0, 1, 1)); 292 [color drawSwatchInRect:NSMakeRect(0, 0, 1, 1)]; 293 [NSGraphicsContext restoreGraphicsState]; 294 295 NSUInteger pixel[4]; 296 [offscreenRep getPixel:pixel atX:0 y:0]; 297 298 [offscreenRep release]; 299 300 return makeRGB(pixel[0], pixel[1], pixel[2]); 301 } 302 303 static RGBA32 menuBackgroundColor() 304 { 305 NSBitmapImageRep *offscreenRep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:nil 306 pixelsWide:1 307 pixelsHigh:1 308 bitsPerSample:8 309 samplesPerPixel:4 310 hasAlpha:YES 311 isPlanar:NO 312 colorSpaceName:NSDeviceRGBColorSpace 313 bytesPerRow:4 314 bitsPerPixel:32]; 315 316 CGContextRef context = static_cast<CGContextRef>([[NSGraphicsContext graphicsContextWithBitmapImageRep:offscreenRep] graphicsPort]); 317 CGRect rect = CGRectMake(0, 0, 1, 1); 318 HIThemeMenuDrawInfo drawInfo; 319 drawInfo.version = 0; 320 drawInfo.menuType = kThemeMenuTypePopUp; 321 HIThemeDrawMenuBackground(&rect, &drawInfo, context, kHIThemeOrientationInverted); 322 323 NSUInteger pixel[4]; 324 [offscreenRep getPixel:pixel atX:0 y:0]; 325 326 [offscreenRep release]; 327 328 return makeRGB(pixel[0], pixel[1], pixel[2]); 329 } 330 331 void RenderThemeMac::platformColorsDidChange() 332 { 333 m_systemColorCache.clear(); 334 RenderTheme::platformColorsDidChange(); 335 } 336 337 Color RenderThemeMac::systemColor(int cssValueId) const 338 { 339 if (m_systemColorCache.contains(cssValueId)) 340 return m_systemColorCache.get(cssValueId); 341 342 Color color; 343 switch (cssValueId) { 344 case CSSValueActiveborder: 345 color = convertNSColorToColor([NSColor keyboardFocusIndicatorColor]); 346 break; 347 case CSSValueActivecaption: 348 color = convertNSColorToColor([NSColor windowFrameTextColor]); 349 break; 350 case CSSValueAppworkspace: 351 color = convertNSColorToColor([NSColor headerColor]); 352 break; 353 case CSSValueBackground: 354 // Use theme independent default 355 break; 356 case CSSValueButtonface: 357 // We use this value instead of NSColor's controlColor to avoid website incompatibilities. 358 // We may want to change this to use the NSColor in future. 359 color = 0xFFC0C0C0; 360 break; 361 case CSSValueButtonhighlight: 362 color = convertNSColorToColor([NSColor controlHighlightColor]); 363 break; 364 case CSSValueButtonshadow: 365 color = convertNSColorToColor([NSColor controlShadowColor]); 366 break; 367 case CSSValueButtontext: 368 color = convertNSColorToColor([NSColor controlTextColor]); 369 break; 370 case CSSValueCaptiontext: 371 color = convertNSColorToColor([NSColor textColor]); 372 break; 373 case CSSValueGraytext: 374 color = convertNSColorToColor([NSColor disabledControlTextColor]); 375 break; 376 case CSSValueHighlight: 377 color = convertNSColorToColor([NSColor selectedTextBackgroundColor]); 378 break; 379 case CSSValueHighlighttext: 380 color = convertNSColorToColor([NSColor selectedTextColor]); 381 break; 382 case CSSValueInactiveborder: 383 color = convertNSColorToColor([NSColor controlBackgroundColor]); 384 break; 385 case CSSValueInactivecaption: 386 color = convertNSColorToColor([NSColor controlBackgroundColor]); 387 break; 388 case CSSValueInactivecaptiontext: 389 color = convertNSColorToColor([NSColor textColor]); 390 break; 391 case CSSValueInfobackground: 392 // There is no corresponding NSColor for this so we use a hard coded value. 393 color = 0xFFFBFCC5; 394 break; 395 case CSSValueInfotext: 396 color = convertNSColorToColor([NSColor textColor]); 397 break; 398 case CSSValueMenu: 399 color = menuBackgroundColor(); 400 break; 401 case CSSValueMenutext: 402 color = convertNSColorToColor([NSColor selectedMenuItemTextColor]); 403 break; 404 case CSSValueScrollbar: 405 color = convertNSColorToColor([NSColor scrollBarColor]); 406 break; 407 case CSSValueText: 408 color = convertNSColorToColor([NSColor textColor]); 409 break; 410 case CSSValueThreeddarkshadow: 411 color = convertNSColorToColor([NSColor controlDarkShadowColor]); 412 break; 413 case CSSValueThreedshadow: 414 color = convertNSColorToColor([NSColor shadowColor]); 415 break; 416 case CSSValueThreedface: 417 // We use this value instead of NSColor's controlColor to avoid website incompatibilities. 418 // We may want to change this to use the NSColor in future. 419 color = 0xFFC0C0C0; 420 break; 421 case CSSValueThreedhighlight: 422 color = convertNSColorToColor([NSColor highlightColor]); 423 break; 424 case CSSValueThreedlightshadow: 425 color = convertNSColorToColor([NSColor controlLightHighlightColor]); 426 break; 427 case CSSValueWebkitFocusRingColor: 428 color = convertNSColorToColor([NSColor keyboardFocusIndicatorColor]); 429 break; 430 case CSSValueWindow: 431 color = convertNSColorToColor([NSColor windowBackgroundColor]); 432 break; 433 case CSSValueWindowframe: 434 color = convertNSColorToColor([NSColor windowFrameColor]); 435 break; 436 case CSSValueWindowtext: 437 color = convertNSColorToColor([NSColor windowFrameTextColor]); 438 break; 439 } 440 441 if (!color.isValid()) 442 color = RenderTheme::systemColor(cssValueId); 443 444 if (color.isValid()) 445 m_systemColorCache.set(cssValueId, color.rgb()); 446 447 return color; 448 } 449 450 bool RenderThemeMac::isControlStyled(const RenderStyle* style, const BorderData& border, 451 const FillLayer& background, const Color& backgroundColor) const 452 { 453 if (style->appearance() == TextFieldPart || style->appearance() == TextAreaPart || style->appearance() == ListboxPart) 454 return style->border() != border; 455 456 // FIXME: This is horrible, but there is not much else that can be done. Menu lists cannot draw properly when 457 // scaled. They can't really draw properly when transformed either. We can't detect the transform case at style 458 // adjustment time so that will just have to stay broken. We can however detect that we're zooming. If zooming 459 // is in effect we treat it like the control is styled. 460 if (style->appearance() == MenulistPart && style->effectiveZoom() != 1.0f) 461 return true; 462 463 return RenderTheme::isControlStyled(style, border, background, backgroundColor); 464 } 465 466 void RenderThemeMac::adjustRepaintRect(const RenderObject* o, IntRect& r) 467 { 468 ControlPart part = o->style()->appearance(); 469 470 #if USE(NEW_THEME) 471 switch (part) { 472 case CheckboxPart: 473 case RadioPart: 474 case PushButtonPart: 475 case SquareButtonPart: 476 case ListButtonPart: 477 case DefaultButtonPart: 478 case ButtonPart: 479 return RenderTheme::adjustRepaintRect(o, r); 480 default: 481 break; 482 } 483 #endif 484 485 float zoomLevel = o->style()->effectiveZoom(); 486 487 if (part == MenulistPart) { 488 setPopupButtonCellState(o, r); 489 IntSize size = popupButtonSizes()[[popupButton() controlSize]]; 490 size.setHeight(size.height() * zoomLevel); 491 size.setWidth(r.width()); 492 r = inflateRect(r, size, popupButtonMargins(), zoomLevel); 493 } 494 } 495 496 IntRect RenderThemeMac::inflateRect(const IntRect& r, const IntSize& size, const int* margins, float zoomLevel) const 497 { 498 // Only do the inflation if the available width/height are too small. Otherwise try to 499 // fit the glow/check space into the available box's width/height. 500 int widthDelta = r.width() - (size.width() + margins[leftMargin] * zoomLevel + margins[rightMargin] * zoomLevel); 501 int heightDelta = r.height() - (size.height() + margins[topMargin] * zoomLevel + margins[bottomMargin] * zoomLevel); 502 IntRect result(r); 503 if (widthDelta < 0) { 504 result.setX(result.x() - margins[leftMargin] * zoomLevel); 505 result.setWidth(result.width() - widthDelta); 506 } 507 if (heightDelta < 0) { 508 result.setY(result.y() - margins[topMargin] * zoomLevel); 509 result.setHeight(result.height() - heightDelta); 510 } 511 return result; 512 } 513 514 FloatRect RenderThemeMac::convertToPaintingRect(const RenderObject* inputRenderer, const RenderObject* partRenderer, const FloatRect& inputRect, const IntRect& r) const 515 { 516 FloatRect partRect(inputRect); 517 518 // Compute an offset between the part renderer and the input renderer 519 FloatSize offsetFromInputRenderer; 520 const RenderObject* renderer = partRenderer; 521 while (renderer && renderer != inputRenderer) { 522 RenderObject* containingRenderer = renderer->container(); 523 offsetFromInputRenderer -= renderer->offsetFromContainer(containingRenderer); 524 renderer = containingRenderer; 525 } 526 // If the input renderer was not a container, something went wrong 527 ASSERT(renderer == inputRenderer); 528 // Move the rect into partRenderer's coords 529 partRect.move(offsetFromInputRenderer); 530 // Account for the local drawing offset (tx, ty) 531 partRect.move(r.x(), r.y()); 532 533 return partRect; 534 } 535 536 void RenderThemeMac::updateCheckedState(NSCell* cell, const RenderObject* o) 537 { 538 bool oldIndeterminate = [cell state] == NSMixedState; 539 bool indeterminate = isIndeterminate(o); 540 bool checked = isChecked(o); 541 542 if (oldIndeterminate != indeterminate) { 543 [cell setState:indeterminate ? NSMixedState : (checked ? NSOnState : NSOffState)]; 544 return; 545 } 546 547 bool oldChecked = [cell state] == NSOnState; 548 if (checked != oldChecked) 549 [cell setState:checked ? NSOnState : NSOffState]; 550 } 551 552 void RenderThemeMac::updateEnabledState(NSCell* cell, const RenderObject* o) 553 { 554 bool oldEnabled = [cell isEnabled]; 555 bool enabled = isEnabled(o); 556 if (enabled != oldEnabled) 557 [cell setEnabled:enabled]; 558 } 559 560 void RenderThemeMac::updateFocusedState(NSCell* cell, const RenderObject* o) 561 { 562 bool oldFocused = [cell showsFirstResponder]; 563 bool focused = isFocused(o) && o->style()->outlineStyleIsAuto(); 564 if (focused != oldFocused) 565 [cell setShowsFirstResponder:focused]; 566 } 567 568 void RenderThemeMac::updatePressedState(NSCell* cell, const RenderObject* o) 569 { 570 bool oldPressed = [cell isHighlighted]; 571 bool pressed = (o->node() && o->node()->active()); 572 if (pressed != oldPressed) 573 [cell setHighlighted:pressed]; 574 } 575 576 bool RenderThemeMac::controlSupportsTints(const RenderObject* o) const 577 { 578 // An alternate way to implement this would be to get the appropriate cell object 579 // and call the private _needRedrawOnWindowChangedKeyState method. An advantage of 580 // that would be that we would match AppKit behavior more closely, but a disadvantage 581 // would be that we would rely on an AppKit SPI method. 582 583 if (!isEnabled(o)) 584 return false; 585 586 // Checkboxes only have tint when checked. 587 if (o->style()->appearance() == CheckboxPart) 588 return isChecked(o); 589 590 // For now assume other controls have tint if enabled. 591 return true; 592 } 593 594 NSControlSize RenderThemeMac::controlSizeForFont(RenderStyle* style) const 595 { 596 int fontSize = style->fontSize(); 597 if (fontSize >= 16) 598 return NSRegularControlSize; 599 if (fontSize >= 11) 600 return NSSmallControlSize; 601 return NSMiniControlSize; 602 } 603 604 void RenderThemeMac::setControlSize(NSCell* cell, const IntSize* sizes, const IntSize& minSize, float zoomLevel) 605 { 606 NSControlSize size; 607 if (minSize.width() >= static_cast<int>(sizes[NSRegularControlSize].width() * zoomLevel) && 608 minSize.height() >= static_cast<int>(sizes[NSRegularControlSize].height() * zoomLevel)) 609 size = NSRegularControlSize; 610 else if (minSize.width() >= static_cast<int>(sizes[NSSmallControlSize].width() * zoomLevel) && 611 minSize.height() >= static_cast<int>(sizes[NSSmallControlSize].height() * zoomLevel)) 612 size = NSSmallControlSize; 613 else 614 size = NSMiniControlSize; 615 if (size != [cell controlSize]) // Only update if we have to, since AppKit does work even if the size is the same. 616 [cell setControlSize:size]; 617 } 618 619 IntSize RenderThemeMac::sizeForFont(RenderStyle* style, const IntSize* sizes) const 620 { 621 if (style->effectiveZoom() != 1.0f) { 622 IntSize result = sizes[controlSizeForFont(style)]; 623 return IntSize(result.width() * style->effectiveZoom(), result.height() * style->effectiveZoom()); 624 } 625 return sizes[controlSizeForFont(style)]; 626 } 627 628 IntSize RenderThemeMac::sizeForSystemFont(RenderStyle* style, const IntSize* sizes) const 629 { 630 if (style->effectiveZoom() != 1.0f) { 631 IntSize result = sizes[controlSizeForSystemFont(style)]; 632 return IntSize(result.width() * style->effectiveZoom(), result.height() * style->effectiveZoom()); 633 } 634 return sizes[controlSizeForSystemFont(style)]; 635 } 636 637 void RenderThemeMac::setSizeFromFont(RenderStyle* style, const IntSize* sizes) const 638 { 639 // FIXME: Check is flawed, since it doesn't take min-width/max-width into account. 640 IntSize size = sizeForFont(style, sizes); 641 if (style->width().isIntrinsicOrAuto() && size.width() > 0) 642 style->setWidth(Length(size.width(), Fixed)); 643 if (style->height().isAuto() && size.height() > 0) 644 style->setHeight(Length(size.height(), Fixed)); 645 } 646 647 void RenderThemeMac::setFontFromControlSize(CSSStyleSelector*, RenderStyle* style, NSControlSize controlSize) const 648 { 649 FontDescription fontDescription; 650 fontDescription.setIsAbsoluteSize(true); 651 fontDescription.setGenericFamily(FontDescription::SerifFamily); 652 653 NSFont* font = [NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:controlSize]]; 654 fontDescription.firstFamily().setFamily([font familyName]); 655 fontDescription.setComputedSize([font pointSize] * style->effectiveZoom()); 656 fontDescription.setSpecifiedSize([font pointSize] * style->effectiveZoom()); 657 658 // Reset line height 659 style->setLineHeight(RenderStyle::initialLineHeight()); 660 661 if (style->setFontDescription(fontDescription)) 662 style->font().update(0); 663 } 664 665 NSControlSize RenderThemeMac::controlSizeForSystemFont(RenderStyle* style) const 666 { 667 int fontSize = style->fontSize(); 668 if (fontSize >= [NSFont systemFontSizeForControlSize:NSRegularControlSize]) 669 return NSRegularControlSize; 670 if (fontSize >= [NSFont systemFontSizeForControlSize:NSSmallControlSize]) 671 return NSSmallControlSize; 672 return NSMiniControlSize; 673 } 674 675 bool RenderThemeMac::paintTextField(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r) 676 { 677 LocalCurrentGraphicsContext localContext(paintInfo.context); 678 wkDrawBezeledTextFieldCell(r, isEnabled(o) && !isReadOnlyControl(o)); 679 return false; 680 } 681 682 void RenderThemeMac::adjustTextFieldStyle(CSSStyleSelector*, RenderStyle*, Element*) const 683 { 684 } 685 686 bool RenderThemeMac::paintCapsLockIndicator(RenderObject*, const RenderObject::PaintInfo& paintInfo, const IntRect& r) 687 { 688 if (paintInfo.context->paintingDisabled()) 689 return true; 690 691 LocalCurrentGraphicsContext localContext(paintInfo.context); 692 wkDrawCapsLockIndicator(paintInfo.context->platformContext(), r); 693 694 return false; 695 } 696 697 bool RenderThemeMac::paintTextArea(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r) 698 { 699 LocalCurrentGraphicsContext localContext(paintInfo.context); 700 wkDrawBezeledTextArea(r, isEnabled(o) && !isReadOnlyControl(o)); 701 return false; 702 } 703 704 void RenderThemeMac::adjustTextAreaStyle(CSSStyleSelector*, RenderStyle*, Element*) const 705 { 706 } 707 708 const int* RenderThemeMac::popupButtonMargins() const 709 { 710 static const int margins[3][4] = 711 { 712 { 0, 3, 1, 3 }, 713 { 0, 3, 2, 3 }, 714 { 0, 1, 0, 1 } 715 }; 716 return margins[[popupButton() controlSize]]; 717 } 718 719 const IntSize* RenderThemeMac::popupButtonSizes() const 720 { 721 static const IntSize sizes[3] = { IntSize(0, 21), IntSize(0, 18), IntSize(0, 15) }; 722 return sizes; 723 } 724 725 const int* RenderThemeMac::popupButtonPadding(NSControlSize size) const 726 { 727 static const int padding[3][4] = 728 { 729 { 2, 26, 3, 8 }, 730 { 2, 23, 3, 8 }, 731 { 2, 22, 3, 10 } 732 }; 733 return padding[size]; 734 } 735 736 bool RenderThemeMac::paintMenuList(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r) 737 { 738 setPopupButtonCellState(o, r); 739 740 NSPopUpButtonCell* popupButton = this->popupButton(); 741 742 float zoomLevel = o->style()->effectiveZoom(); 743 IntSize size = popupButtonSizes()[[popupButton controlSize]]; 744 size.setHeight(size.height() * zoomLevel); 745 size.setWidth(r.width()); 746 747 // Now inflate it to account for the shadow. 748 IntRect inflatedRect = r; 749 if (r.width() >= minimumMenuListSize(o->style())) 750 inflatedRect = inflateRect(inflatedRect, size, popupButtonMargins(), zoomLevel); 751 752 paintInfo.context->save(); 753 754 #ifndef BUILDING_ON_TIGER 755 // On Leopard, the cell will draw outside of the given rect, so we have to clip to the rect 756 paintInfo.context->clip(inflatedRect); 757 #endif 758 759 if (zoomLevel != 1.0f) { 760 inflatedRect.setWidth(inflatedRect.width() / zoomLevel); 761 inflatedRect.setHeight(inflatedRect.height() / zoomLevel); 762 paintInfo.context->translate(inflatedRect.x(), inflatedRect.y()); 763 paintInfo.context->scale(FloatSize(zoomLevel, zoomLevel)); 764 paintInfo.context->translate(-inflatedRect.x(), -inflatedRect.y()); 765 } 766 767 [popupButton drawWithFrame:inflatedRect inView:o->view()->frameView()->documentView()]; 768 [popupButton setControlView:nil]; 769 770 paintInfo.context->restore(); 771 772 return false; 773 } 774 775 const float baseFontSize = 11.0f; 776 const float baseArrowHeight = 4.0f; 777 const float baseArrowWidth = 5.0f; 778 const float baseSpaceBetweenArrows = 2.0f; 779 const int arrowPaddingLeft = 6; 780 const int arrowPaddingRight = 6; 781 const int paddingBeforeSeparator = 4; 782 const int baseBorderRadius = 5; 783 const int styledPopupPaddingLeft = 8; 784 const int styledPopupPaddingTop = 1; 785 const int styledPopupPaddingBottom = 2; 786 787 static void TopGradientInterpolate(void*, const CGFloat* inData, CGFloat* outData) 788 { 789 static float dark[4] = { 1.0f, 1.0f, 1.0f, 0.4f }; 790 static float light[4] = { 1.0f, 1.0f, 1.0f, 0.15f }; 791 float a = inData[0]; 792 int i = 0; 793 for (i = 0; i < 4; i++) 794 outData[i] = (1.0f - a) * dark[i] + a * light[i]; 795 } 796 797 static void BottomGradientInterpolate(void*, const CGFloat* inData, CGFloat* outData) 798 { 799 static float dark[4] = { 1.0f, 1.0f, 1.0f, 0.0f }; 800 static float light[4] = { 1.0f, 1.0f, 1.0f, 0.3f }; 801 float a = inData[0]; 802 int i = 0; 803 for (i = 0; i < 4; i++) 804 outData[i] = (1.0f - a) * dark[i] + a * light[i]; 805 } 806 807 static void MainGradientInterpolate(void*, const CGFloat* inData, CGFloat* outData) 808 { 809 static float dark[4] = { 0.0f, 0.0f, 0.0f, 0.15f }; 810 static float light[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; 811 float a = inData[0]; 812 int i = 0; 813 for (i = 0; i < 4; i++) 814 outData[i] = (1.0f - a) * dark[i] + a * light[i]; 815 } 816 817 static void TrackGradientInterpolate(void*, const CGFloat* inData, CGFloat* outData) 818 { 819 static float dark[4] = { 0.0f, 0.0f, 0.0f, 0.678f }; 820 static float light[4] = { 0.0f, 0.0f, 0.0f, 0.13f }; 821 float a = inData[0]; 822 int i = 0; 823 for (i = 0; i < 4; i++) 824 outData[i] = (1.0f - a) * dark[i] + a * light[i]; 825 } 826 827 void RenderThemeMac::paintMenuListButtonGradients(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r) 828 { 829 if (r.isEmpty()) 830 return; 831 832 CGContextRef context = paintInfo.context->platformContext(); 833 834 paintInfo.context->save(); 835 836 IntSize topLeftRadius; 837 IntSize topRightRadius; 838 IntSize bottomLeftRadius; 839 IntSize bottomRightRadius; 840 841 o->style()->getBorderRadiiForRect(r, topLeftRadius, topRightRadius, bottomLeftRadius, bottomRightRadius); 842 843 int radius = topLeftRadius.width(); 844 845 RetainPtr<CGColorSpaceRef> cspace(AdoptCF, CGColorSpaceCreateDeviceRGB()); 846 847 FloatRect topGradient(r.x(), r.y(), r.width(), r.height() / 2.0f); 848 struct CGFunctionCallbacks topCallbacks = { 0, TopGradientInterpolate, NULL }; 849 RetainPtr<CGFunctionRef> topFunction(AdoptCF, CGFunctionCreate(NULL, 1, NULL, 4, NULL, &topCallbacks)); 850 RetainPtr<CGShadingRef> topShading(AdoptCF, CGShadingCreateAxial(cspace.get(), CGPointMake(topGradient.x(), topGradient.y()), CGPointMake(topGradient.x(), topGradient.bottom()), topFunction.get(), false, false)); 851 852 FloatRect bottomGradient(r.x() + radius, r.y() + r.height() / 2.0f, r.width() - 2.0f * radius, r.height() / 2.0f); 853 struct CGFunctionCallbacks bottomCallbacks = { 0, BottomGradientInterpolate, NULL }; 854 RetainPtr<CGFunctionRef> bottomFunction(AdoptCF, CGFunctionCreate(NULL, 1, NULL, 4, NULL, &bottomCallbacks)); 855 RetainPtr<CGShadingRef> bottomShading(AdoptCF, CGShadingCreateAxial(cspace.get(), CGPointMake(bottomGradient.x(), bottomGradient.y()), CGPointMake(bottomGradient.x(), bottomGradient.bottom()), bottomFunction.get(), false, false)); 856 857 struct CGFunctionCallbacks mainCallbacks = { 0, MainGradientInterpolate, NULL }; 858 RetainPtr<CGFunctionRef> mainFunction(AdoptCF, CGFunctionCreate(NULL, 1, NULL, 4, NULL, &mainCallbacks)); 859 RetainPtr<CGShadingRef> mainShading(AdoptCF, CGShadingCreateAxial(cspace.get(), CGPointMake(r.x(), r.y()), CGPointMake(r.x(), r.bottom()), mainFunction.get(), false, false)); 860 861 RetainPtr<CGShadingRef> leftShading(AdoptCF, CGShadingCreateAxial(cspace.get(), CGPointMake(r.x(), r.y()), CGPointMake(r.x() + radius, r.y()), mainFunction.get(), false, false)); 862 863 RetainPtr<CGShadingRef> rightShading(AdoptCF, CGShadingCreateAxial(cspace.get(), CGPointMake(r.right(), r.y()), CGPointMake(r.right() - radius, r.y()), mainFunction.get(), false, false)); 864 paintInfo.context->save(); 865 CGContextClipToRect(context, r); 866 paintInfo.context->addRoundedRectClip(r, topLeftRadius, topRightRadius, bottomLeftRadius, bottomRightRadius); 867 CGContextDrawShading(context, mainShading.get()); 868 paintInfo.context->restore(); 869 870 paintInfo.context->save(); 871 CGContextClipToRect(context, topGradient); 872 paintInfo.context->addRoundedRectClip(enclosingIntRect(topGradient), topLeftRadius, topRightRadius, IntSize(), IntSize()); 873 CGContextDrawShading(context, topShading.get()); 874 paintInfo.context->restore(); 875 876 if (!bottomGradient.isEmpty()) { 877 paintInfo.context->save(); 878 CGContextClipToRect(context, bottomGradient); 879 paintInfo.context->addRoundedRectClip(enclosingIntRect(bottomGradient), IntSize(), IntSize(), bottomLeftRadius, bottomRightRadius); 880 CGContextDrawShading(context, bottomShading.get()); 881 paintInfo.context->restore(); 882 } 883 884 paintInfo.context->save(); 885 CGContextClipToRect(context, r); 886 paintInfo.context->addRoundedRectClip(r, topLeftRadius, topRightRadius, bottomLeftRadius, bottomRightRadius); 887 CGContextDrawShading(context, leftShading.get()); 888 CGContextDrawShading(context, rightShading.get()); 889 paintInfo.context->restore(); 890 891 paintInfo.context->restore(); 892 } 893 894 bool RenderThemeMac::paintMenuListButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r) 895 { 896 IntRect bounds = IntRect(r.x() + o->style()->borderLeftWidth(), 897 r.y() + o->style()->borderTopWidth(), 898 r.width() - o->style()->borderLeftWidth() - o->style()->borderRightWidth(), 899 r.height() - o->style()->borderTopWidth() - o->style()->borderBottomWidth()); 900 // Draw the gradients to give the styled popup menu a button appearance 901 paintMenuListButtonGradients(o, paintInfo, bounds); 902 903 // Since we actually know the size of the control here, we restrict the font scale to make sure the arrows will fit vertically in the bounds 904 float fontScale = min(o->style()->fontSize() / baseFontSize, bounds.height() / (baseArrowHeight * 2 + baseSpaceBetweenArrows)); 905 float centerY = bounds.y() + bounds.height() / 2.0f; 906 float arrowHeight = baseArrowHeight * fontScale; 907 float arrowWidth = baseArrowWidth * fontScale; 908 float leftEdge = bounds.right() - arrowPaddingRight * o->style()->effectiveZoom() - arrowWidth; 909 float spaceBetweenArrows = baseSpaceBetweenArrows * fontScale; 910 911 if (bounds.width() < arrowWidth + arrowPaddingLeft * o->style()->effectiveZoom()) 912 return false; 913 914 paintInfo.context->save(); 915 916 paintInfo.context->setFillColor(o->style()->color(), o->style()->colorSpace()); 917 paintInfo.context->setStrokeStyle(NoStroke); 918 919 FloatPoint arrow1[3]; 920 arrow1[0] = FloatPoint(leftEdge, centerY - spaceBetweenArrows / 2.0f); 921 arrow1[1] = FloatPoint(leftEdge + arrowWidth, centerY - spaceBetweenArrows / 2.0f); 922 arrow1[2] = FloatPoint(leftEdge + arrowWidth / 2.0f, centerY - spaceBetweenArrows / 2.0f - arrowHeight); 923 924 // Draw the top arrow 925 paintInfo.context->drawConvexPolygon(3, arrow1, true); 926 927 FloatPoint arrow2[3]; 928 arrow2[0] = FloatPoint(leftEdge, centerY + spaceBetweenArrows / 2.0f); 929 arrow2[1] = FloatPoint(leftEdge + arrowWidth, centerY + spaceBetweenArrows / 2.0f); 930 arrow2[2] = FloatPoint(leftEdge + arrowWidth / 2.0f, centerY + spaceBetweenArrows / 2.0f + arrowHeight); 931 932 // Draw the bottom arrow 933 paintInfo.context->drawConvexPolygon(3, arrow2, true); 934 935 Color leftSeparatorColor(0, 0, 0, 40); 936 Color rightSeparatorColor(255, 255, 255, 40); 937 938 // FIXME: Should the separator thickness and space be scaled up by fontScale? 939 int separatorSpace = 2; // Deliberately ignores zoom since it looks nicer if it stays thin. 940 int leftEdgeOfSeparator = static_cast<int>(leftEdge - arrowPaddingLeft * o->style()->effectiveZoom()); // FIXME: Round? 941 942 // Draw the separator to the left of the arrows 943 paintInfo.context->setStrokeThickness(1.0f); // Deliberately ignores zoom since it looks nicer if it stays thin. 944 paintInfo.context->setStrokeStyle(SolidStroke); 945 paintInfo.context->setStrokeColor(leftSeparatorColor, DeviceColorSpace); 946 paintInfo.context->drawLine(IntPoint(leftEdgeOfSeparator, bounds.y()), 947 IntPoint(leftEdgeOfSeparator, bounds.bottom())); 948 949 paintInfo.context->setStrokeColor(rightSeparatorColor, DeviceColorSpace); 950 paintInfo.context->drawLine(IntPoint(leftEdgeOfSeparator + separatorSpace, bounds.y()), 951 IntPoint(leftEdgeOfSeparator + separatorSpace, bounds.bottom())); 952 953 paintInfo.context->restore(); 954 return false; 955 } 956 957 static const IntSize* menuListButtonSizes() 958 { 959 static const IntSize sizes[3] = { IntSize(0, 21), IntSize(0, 18), IntSize(0, 15) }; 960 return sizes; 961 } 962 963 void RenderThemeMac::adjustMenuListStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const 964 { 965 NSControlSize controlSize = controlSizeForFont(style); 966 967 style->resetBorder(); 968 style->resetPadding(); 969 970 // Height is locked to auto. 971 style->setHeight(Length(Auto)); 972 973 // White-space is locked to pre 974 style->setWhiteSpace(PRE); 975 976 // Set the foreground color to black or gray when we have the aqua look. 977 // Cast to RGB32 is to work around a compiler bug. 978 style->setColor(e && e->isEnabledFormControl() ? static_cast<RGBA32>(Color::black) : Color::darkGray); 979 980 // Set the button's vertical size. 981 setSizeFromFont(style, menuListButtonSizes()); 982 983 // Our font is locked to the appropriate system font size for the control. To clarify, we first use the CSS-specified font to figure out 984 // a reasonable control size, but once that control size is determined, we throw that font away and use the appropriate 985 // system font for the control size instead. 986 setFontFromControlSize(selector, style, controlSize); 987 988 style->setBoxShadow(0); 989 } 990 991 int RenderThemeMac::popupInternalPaddingLeft(RenderStyle* style) const 992 { 993 if (style->appearance() == MenulistPart) 994 return popupButtonPadding(controlSizeForFont(style))[leftPadding] * style->effectiveZoom(); 995 if (style->appearance() == MenulistButtonPart) 996 return styledPopupPaddingLeft * style->effectiveZoom(); 997 return 0; 998 } 999 1000 int RenderThemeMac::popupInternalPaddingRight(RenderStyle* style) const 1001 { 1002 if (style->appearance() == MenulistPart) 1003 return popupButtonPadding(controlSizeForFont(style))[rightPadding] * style->effectiveZoom(); 1004 if (style->appearance() == MenulistButtonPart) { 1005 float fontScale = style->fontSize() / baseFontSize; 1006 float arrowWidth = baseArrowWidth * fontScale; 1007 return static_cast<int>(ceilf(arrowWidth + (arrowPaddingLeft + arrowPaddingRight + paddingBeforeSeparator) * style->effectiveZoom())); 1008 } 1009 return 0; 1010 } 1011 1012 int RenderThemeMac::popupInternalPaddingTop(RenderStyle* style) const 1013 { 1014 if (style->appearance() == MenulistPart) 1015 return popupButtonPadding(controlSizeForFont(style))[topPadding] * style->effectiveZoom(); 1016 if (style->appearance() == MenulistButtonPart) 1017 return styledPopupPaddingTop * style->effectiveZoom(); 1018 return 0; 1019 } 1020 1021 int RenderThemeMac::popupInternalPaddingBottom(RenderStyle* style) const 1022 { 1023 if (style->appearance() == MenulistPart) 1024 return popupButtonPadding(controlSizeForFont(style))[bottomPadding] * style->effectiveZoom(); 1025 if (style->appearance() == MenulistButtonPart) 1026 return styledPopupPaddingBottom * style->effectiveZoom(); 1027 return 0; 1028 } 1029 1030 void RenderThemeMac::adjustMenuListButtonStyle(CSSStyleSelector*, RenderStyle* style, Element*) const 1031 { 1032 float fontScale = style->fontSize() / baseFontSize; 1033 1034 style->resetPadding(); 1035 style->setBorderRadius(IntSize(int(baseBorderRadius + fontScale - 1), int(baseBorderRadius + fontScale - 1))); // FIXME: Round up? 1036 1037 const int minHeight = 15; 1038 style->setMinHeight(Length(minHeight, Fixed)); 1039 1040 style->setLineHeight(RenderStyle::initialLineHeight()); 1041 } 1042 1043 void RenderThemeMac::setPopupButtonCellState(const RenderObject* o, const IntRect& r) 1044 { 1045 NSPopUpButtonCell* popupButton = this->popupButton(); 1046 1047 // Set the control size based off the rectangle we're painting into. 1048 setControlSize(popupButton, popupButtonSizes(), r.size(), o->style()->effectiveZoom()); 1049 1050 // Update the various states we respond to. 1051 updateCheckedState(popupButton, o); 1052 updateEnabledState(popupButton, o); 1053 updatePressedState(popupButton, o); 1054 updateFocusedState(popupButton, o); 1055 } 1056 1057 const IntSize* RenderThemeMac::menuListSizes() const 1058 { 1059 static const IntSize sizes[3] = { IntSize(9, 0), IntSize(5, 0), IntSize(0, 0) }; 1060 return sizes; 1061 } 1062 1063 int RenderThemeMac::minimumMenuListSize(RenderStyle* style) const 1064 { 1065 return sizeForSystemFont(style, menuListSizes()).width(); 1066 } 1067 1068 const int trackWidth = 5; 1069 const int trackRadius = 2; 1070 1071 void RenderThemeMac::adjustSliderTrackStyle(CSSStyleSelector*, RenderStyle* style, Element*) const 1072 { 1073 style->setBoxShadow(0); 1074 } 1075 1076 bool RenderThemeMac::paintSliderTrack(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r) 1077 { 1078 IntRect bounds = r; 1079 float zoomLevel = o->style()->effectiveZoom(); 1080 float zoomedTrackWidth = trackWidth * zoomLevel; 1081 1082 if (o->style()->appearance() == SliderHorizontalPart || o->style()->appearance() == MediaSliderPart) { 1083 bounds.setHeight(zoomedTrackWidth); 1084 bounds.setY(r.y() + r.height() / 2 - zoomedTrackWidth / 2); 1085 } else if (o->style()->appearance() == SliderVerticalPart) { 1086 bounds.setWidth(zoomedTrackWidth); 1087 bounds.setX(r.x() + r.width() / 2 - zoomedTrackWidth / 2); 1088 } 1089 1090 LocalCurrentGraphicsContext localContext(paintInfo.context); 1091 CGContextRef context = paintInfo.context->platformContext(); 1092 RetainPtr<CGColorSpaceRef> cspace(AdoptCF, CGColorSpaceCreateDeviceRGB()); 1093 1094 paintInfo.context->save(); 1095 CGContextClipToRect(context, bounds); 1096 1097 struct CGFunctionCallbacks mainCallbacks = { 0, TrackGradientInterpolate, NULL }; 1098 RetainPtr<CGFunctionRef> mainFunction(AdoptCF, CGFunctionCreate(NULL, 1, NULL, 4, NULL, &mainCallbacks)); 1099 RetainPtr<CGShadingRef> mainShading; 1100 if (o->style()->appearance() == SliderVerticalPart) 1101 mainShading.adoptCF(CGShadingCreateAxial(cspace.get(), CGPointMake(bounds.x(), bounds.bottom()), CGPointMake(bounds.right(), bounds.bottom()), mainFunction.get(), false, false)); 1102 else 1103 mainShading.adoptCF(CGShadingCreateAxial(cspace.get(), CGPointMake(bounds.x(), bounds.y()), CGPointMake(bounds.x(), bounds.bottom()), mainFunction.get(), false, false)); 1104 1105 IntSize radius(trackRadius, trackRadius); 1106 paintInfo.context->addRoundedRectClip(bounds, 1107 radius, radius, 1108 radius, radius); 1109 CGContextDrawShading(context, mainShading.get()); 1110 paintInfo.context->restore(); 1111 1112 return false; 1113 } 1114 1115 void RenderThemeMac::adjustSliderThumbStyle(CSSStyleSelector*, RenderStyle* style, Element*) const 1116 { 1117 style->setBoxShadow(0); 1118 } 1119 1120 const float verticalSliderHeightPadding = 0.1f; 1121 1122 bool RenderThemeMac::paintSliderThumb(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r) 1123 { 1124 ASSERT(o->parent()->isSlider()); 1125 1126 NSSliderCell* sliderThumbCell = o->style()->appearance() == SliderThumbVerticalPart 1127 ? sliderThumbVertical() 1128 : sliderThumbHorizontal(); 1129 1130 LocalCurrentGraphicsContext localContext(paintInfo.context); 1131 1132 // Update the various states we respond to. 1133 updateEnabledState(sliderThumbCell, o->parent()); 1134 updateFocusedState(sliderThumbCell, o->parent()); 1135 1136 // Update the pressed state using the NSCell tracking methods, since that's how NSSliderCell keeps track of it. 1137 bool oldPressed; 1138 if (o->style()->appearance() == SliderThumbVerticalPart) 1139 oldPressed = m_isSliderThumbVerticalPressed; 1140 else 1141 oldPressed = m_isSliderThumbHorizontalPressed; 1142 1143 bool pressed = toRenderSlider(o->parent())->inDragMode(); 1144 1145 if (o->style()->appearance() == SliderThumbVerticalPart) 1146 m_isSliderThumbVerticalPressed = pressed; 1147 else 1148 m_isSliderThumbHorizontalPressed = pressed; 1149 1150 if (pressed != oldPressed) { 1151 if (pressed) 1152 [sliderThumbCell startTrackingAt:NSPoint() inView:nil]; 1153 else 1154 [sliderThumbCell stopTracking:NSPoint() at:NSPoint() inView:nil mouseIsUp:YES]; 1155 } 1156 1157 FloatRect bounds = r; 1158 // Make the height of the vertical slider slightly larger so NSSliderCell will draw a vertical slider. 1159 if (o->style()->appearance() == SliderThumbVerticalPart) 1160 bounds.setHeight(bounds.height() + verticalSliderHeightPadding * o->style()->effectiveZoom()); 1161 1162 paintInfo.context->save(); 1163 float zoomLevel = o->style()->effectiveZoom(); 1164 1165 FloatRect unzoomedRect = bounds; 1166 if (zoomLevel != 1.0f) { 1167 unzoomedRect.setWidth(unzoomedRect.width() / zoomLevel); 1168 unzoomedRect.setHeight(unzoomedRect.height() / zoomLevel); 1169 paintInfo.context->translate(unzoomedRect.x(), unzoomedRect.y()); 1170 paintInfo.context->scale(FloatSize(zoomLevel, zoomLevel)); 1171 paintInfo.context->translate(-unzoomedRect.x(), -unzoomedRect.y()); 1172 } 1173 1174 [sliderThumbCell drawWithFrame:unzoomedRect inView:o->view()->frameView()->documentView()]; 1175 [sliderThumbCell setControlView:nil]; 1176 1177 paintInfo.context->restore(); 1178 1179 return false; 1180 } 1181 1182 bool RenderThemeMac::paintSearchField(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r) 1183 { 1184 NSSearchFieldCell* search = this->search(); 1185 LocalCurrentGraphicsContext localContext(paintInfo.context); 1186 1187 setSearchCellState(o, r); 1188 1189 paintInfo.context->save(); 1190 1191 float zoomLevel = o->style()->effectiveZoom(); 1192 1193 IntRect unzoomedRect = r; 1194 1195 if (zoomLevel != 1.0f) { 1196 unzoomedRect.setWidth(unzoomedRect.width() / zoomLevel); 1197 unzoomedRect.setHeight(unzoomedRect.height() / zoomLevel); 1198 paintInfo.context->translate(unzoomedRect.x(), unzoomedRect.y()); 1199 paintInfo.context->scale(FloatSize(zoomLevel, zoomLevel)); 1200 paintInfo.context->translate(-unzoomedRect.x(), -unzoomedRect.y()); 1201 } 1202 1203 // Set the search button to nil before drawing. Then reset it so we can draw it later. 1204 [search setSearchButtonCell:nil]; 1205 1206 [search drawWithFrame:NSRect(unzoomedRect) inView:o->view()->frameView()->documentView()]; 1207 #ifdef BUILDING_ON_TIGER 1208 if ([search showsFirstResponder]) 1209 wkDrawTextFieldCellFocusRing(search, NSRect(unzoomedRect)); 1210 #endif 1211 1212 [search setControlView:nil]; 1213 [search resetSearchButtonCell]; 1214 1215 paintInfo.context->restore(); 1216 1217 return false; 1218 } 1219 1220 void RenderThemeMac::setSearchCellState(RenderObject* o, const IntRect&) 1221 { 1222 NSSearchFieldCell* search = this->search(); 1223 1224 [search setControlSize:controlSizeForFont(o->style())]; 1225 1226 // Update the various states we respond to. 1227 updateEnabledState(search, o); 1228 updateFocusedState(search, o); 1229 } 1230 1231 const IntSize* RenderThemeMac::searchFieldSizes() const 1232 { 1233 static const IntSize sizes[3] = { IntSize(0, 22), IntSize(0, 19), IntSize(0, 17) }; 1234 return sizes; 1235 } 1236 1237 void RenderThemeMac::setSearchFieldSize(RenderStyle* style) const 1238 { 1239 // If the width and height are both specified, then we have nothing to do. 1240 if (!style->width().isIntrinsicOrAuto() && !style->height().isAuto()) 1241 return; 1242 1243 // Use the font size to determine the intrinsic width of the control. 1244 setSizeFromFont(style, searchFieldSizes()); 1245 } 1246 1247 void RenderThemeMac::adjustSearchFieldStyle(CSSStyleSelector* selector, RenderStyle* style, Element*) const 1248 { 1249 // Override border. 1250 style->resetBorder(); 1251 const short borderWidth = 2 * style->effectiveZoom(); 1252 style->setBorderLeftWidth(borderWidth); 1253 style->setBorderLeftStyle(INSET); 1254 style->setBorderRightWidth(borderWidth); 1255 style->setBorderRightStyle(INSET); 1256 style->setBorderBottomWidth(borderWidth); 1257 style->setBorderBottomStyle(INSET); 1258 style->setBorderTopWidth(borderWidth); 1259 style->setBorderTopStyle(INSET); 1260 1261 // Override height. 1262 style->setHeight(Length(Auto)); 1263 setSearchFieldSize(style); 1264 1265 // Override padding size to match AppKit text positioning. 1266 const int padding = 1 * style->effectiveZoom(); 1267 style->setPaddingLeft(Length(padding, Fixed)); 1268 style->setPaddingRight(Length(padding, Fixed)); 1269 style->setPaddingTop(Length(padding, Fixed)); 1270 style->setPaddingBottom(Length(padding, Fixed)); 1271 1272 NSControlSize controlSize = controlSizeForFont(style); 1273 setFontFromControlSize(selector, style, controlSize); 1274 1275 style->setBoxShadow(0); 1276 } 1277 1278 bool RenderThemeMac::paintSearchFieldCancelButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r) 1279 { 1280 Node* input = o->node()->shadowAncestorNode(); 1281 if (!input->renderer()->isBox()) 1282 return false; 1283 1284 setSearchCellState(input->renderer(), r); 1285 1286 NSSearchFieldCell* search = this->search(); 1287 1288 updatePressedState([search cancelButtonCell], o); 1289 1290 paintInfo.context->save(); 1291 1292 float zoomLevel = o->style()->effectiveZoom(); 1293 1294 FloatRect localBounds = [search cancelButtonRectForBounds:NSRect(input->renderBox()->borderBoxRect())]; 1295 localBounds = convertToPaintingRect(input->renderer(), o, localBounds, r); 1296 1297 FloatRect unzoomedRect(localBounds); 1298 if (zoomLevel != 1.0f) { 1299 unzoomedRect.setWidth(unzoomedRect.width() / zoomLevel); 1300 unzoomedRect.setHeight(unzoomedRect.height() / zoomLevel); 1301 paintInfo.context->translate(unzoomedRect.x(), unzoomedRect.y()); 1302 paintInfo.context->scale(FloatSize(zoomLevel, zoomLevel)); 1303 paintInfo.context->translate(-unzoomedRect.x(), -unzoomedRect.y()); 1304 } 1305 1306 [[search cancelButtonCell] drawWithFrame:unzoomedRect inView:o->view()->frameView()->documentView()]; 1307 [[search cancelButtonCell] setControlView:nil]; 1308 1309 paintInfo.context->restore(); 1310 return false; 1311 } 1312 1313 const IntSize* RenderThemeMac::cancelButtonSizes() const 1314 { 1315 static const IntSize sizes[3] = { IntSize(16, 13), IntSize(13, 11), IntSize(13, 9) }; 1316 return sizes; 1317 } 1318 1319 void RenderThemeMac::adjustSearchFieldCancelButtonStyle(CSSStyleSelector*, RenderStyle* style, Element*) const 1320 { 1321 IntSize size = sizeForSystemFont(style, cancelButtonSizes()); 1322 style->setWidth(Length(size.width(), Fixed)); 1323 style->setHeight(Length(size.height(), Fixed)); 1324 style->setBoxShadow(0); 1325 } 1326 1327 const IntSize* RenderThemeMac::resultsButtonSizes() const 1328 { 1329 static const IntSize sizes[3] = { IntSize(19, 13), IntSize(17, 11), IntSize(17, 9) }; 1330 return sizes; 1331 } 1332 1333 const int emptyResultsOffset = 9; 1334 void RenderThemeMac::adjustSearchFieldDecorationStyle(CSSStyleSelector*, RenderStyle* style, Element*) const 1335 { 1336 IntSize size = sizeForSystemFont(style, resultsButtonSizes()); 1337 style->setWidth(Length(size.width() - emptyResultsOffset, Fixed)); 1338 style->setHeight(Length(size.height(), Fixed)); 1339 style->setBoxShadow(0); 1340 } 1341 1342 bool RenderThemeMac::paintSearchFieldDecoration(RenderObject*, const RenderObject::PaintInfo&, const IntRect&) 1343 { 1344 return false; 1345 } 1346 1347 void RenderThemeMac::adjustSearchFieldResultsDecorationStyle(CSSStyleSelector*, RenderStyle* style, Element*) const 1348 { 1349 IntSize size = sizeForSystemFont(style, resultsButtonSizes()); 1350 style->setWidth(Length(size.width(), Fixed)); 1351 style->setHeight(Length(size.height(), Fixed)); 1352 style->setBoxShadow(0); 1353 } 1354 1355 bool RenderThemeMac::paintSearchFieldResultsDecoration(RenderObject* o, const RenderObject::PaintInfo&, const IntRect& r) 1356 { 1357 Node* input = o->node()->shadowAncestorNode(); 1358 if (!input->renderer()->isBox()) 1359 return false; 1360 1361 setSearchCellState(input->renderer(), r); 1362 1363 NSSearchFieldCell* search = this->search(); 1364 1365 if ([search searchMenuTemplate] != nil) 1366 [search setSearchMenuTemplate:nil]; 1367 1368 FloatRect localBounds = [search searchButtonRectForBounds:NSRect(input->renderBox()->borderBoxRect())]; 1369 localBounds = convertToPaintingRect(input->renderer(), o, localBounds, r); 1370 1371 [[search searchButtonCell] drawWithFrame:localBounds inView:o->view()->frameView()->documentView()]; 1372 [[search searchButtonCell] setControlView:nil]; 1373 return false; 1374 } 1375 1376 const int resultsArrowWidth = 5; 1377 void RenderThemeMac::adjustSearchFieldResultsButtonStyle(CSSStyleSelector*, RenderStyle* style, Element*) const 1378 { 1379 IntSize size = sizeForSystemFont(style, resultsButtonSizes()); 1380 style->setWidth(Length(size.width() + resultsArrowWidth, Fixed)); 1381 style->setHeight(Length(size.height(), Fixed)); 1382 style->setBoxShadow(0); 1383 } 1384 1385 bool RenderThemeMac::paintSearchFieldResultsButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r) 1386 { 1387 Node* input = o->node()->shadowAncestorNode(); 1388 if (!input->renderer()->isBox()) 1389 return false; 1390 1391 setSearchCellState(input->renderer(), r); 1392 1393 NSSearchFieldCell* search = this->search(); 1394 1395 if (![search searchMenuTemplate]) 1396 [search setSearchMenuTemplate:searchMenuTemplate()]; 1397 1398 paintInfo.context->save(); 1399 1400 float zoomLevel = o->style()->effectiveZoom(); 1401 1402 FloatRect localBounds = [search searchButtonRectForBounds:NSRect(input->renderBox()->borderBoxRect())]; 1403 localBounds = convertToPaintingRect(input->renderer(), o, localBounds, r); 1404 1405 IntRect unzoomedRect(localBounds); 1406 if (zoomLevel != 1.0f) { 1407 unzoomedRect.setWidth(unzoomedRect.width() / zoomLevel); 1408 unzoomedRect.setHeight(unzoomedRect.height() / zoomLevel); 1409 paintInfo.context->translate(unzoomedRect.x(), unzoomedRect.y()); 1410 paintInfo.context->scale(FloatSize(zoomLevel, zoomLevel)); 1411 paintInfo.context->translate(-unzoomedRect.x(), -unzoomedRect.y()); 1412 } 1413 1414 [[search searchButtonCell] drawWithFrame:unzoomedRect inView:o->view()->frameView()->documentView()]; 1415 [[search searchButtonCell] setControlView:nil]; 1416 1417 paintInfo.context->restore(); 1418 1419 return false; 1420 } 1421 1422 #if ENABLE(VIDEO) 1423 typedef enum { 1424 MediaControllerThemeClassic = 1, 1425 MediaControllerThemeQuickTime = 2 1426 } MediaControllerThemeStyle; 1427 1428 static int mediaControllerTheme() 1429 { 1430 static int controllerTheme = -1; 1431 1432 if (controllerTheme != -1) 1433 return controllerTheme; 1434 1435 controllerTheme = MediaControllerThemeClassic; 1436 1437 Boolean validKey; 1438 Boolean useQTMediaUIPref = CFPreferencesGetAppBooleanValue(CFSTR("UseQuickTimeMediaUI"), CFSTR("com.apple.WebCore"), &validKey); 1439 1440 #if !defined(BUILDING_ON_TIGER) 1441 if (validKey && !useQTMediaUIPref) 1442 return controllerTheme; 1443 #else 1444 if (!validKey || !useQTMediaUIPref) 1445 return controllerTheme; 1446 #endif 1447 1448 controllerTheme = MediaControllerThemeQuickTime; 1449 return controllerTheme; 1450 } 1451 #endif 1452 1453 const int sliderThumbWidth = 15; 1454 const int sliderThumbHeight = 15; 1455 const int mediaSliderThumbWidth = 13; 1456 const int mediaSliderThumbHeight = 14; 1457 1458 void RenderThemeMac::adjustSliderThumbSize(RenderObject* o) const 1459 { 1460 float zoomLevel = o->style()->effectiveZoom(); 1461 if (o->style()->appearance() == SliderThumbHorizontalPart || o->style()->appearance() == SliderThumbVerticalPart) { 1462 o->style()->setWidth(Length(static_cast<int>(sliderThumbWidth * zoomLevel), Fixed)); 1463 o->style()->setHeight(Length(static_cast<int>(sliderThumbHeight * zoomLevel), Fixed)); 1464 } 1465 1466 #if ENABLE(VIDEO) 1467 else if (o->style()->appearance() == MediaSliderThumbPart) { 1468 int width = mediaSliderThumbWidth; 1469 int height = mediaSliderThumbHeight; 1470 1471 if (mediaControllerTheme() == MediaControllerThemeQuickTime) { 1472 CGSize size; 1473 1474 wkMeasureMediaUIPart(MediaSliderThumb, MediaControllerThemeQuickTime, NULL, &size); 1475 width = size.width; 1476 height = size.height; 1477 } 1478 1479 o->style()->setWidth(Length(static_cast<int>(width * zoomLevel), Fixed)); 1480 o->style()->setHeight(Length(static_cast<int>(height * zoomLevel), Fixed)); 1481 } 1482 #endif 1483 } 1484 1485 1486 #if ENABLE(VIDEO) 1487 1488 enum WKMediaControllerThemeState { 1489 MediaUIPartDisabledFlag = 1 << 0, 1490 MediaUIPartPressedFlag = 1 << 1, 1491 MediaUIPartDrawEndCapsFlag = 1 << 3, 1492 }; 1493 1494 static unsigned getMediaUIPartStateFlags(Node* node) 1495 { 1496 unsigned flags = 0; 1497 1498 if (node->disabled()) 1499 flags |= MediaUIPartDisabledFlag; 1500 else if (node->active()) 1501 flags |= MediaUIPartPressedFlag; 1502 return flags; 1503 } 1504 1505 // Utility to scale when the UI part are not scaled by wkDrawMediaUIPart 1506 static FloatRect getUnzoomedRectAndAdjustCurrentContext(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect &originalRect) 1507 { 1508 float zoomLevel = o->style()->effectiveZoom(); 1509 FloatRect unzoomedRect(originalRect); 1510 if (zoomLevel != 1.0f && mediaControllerTheme() == MediaControllerThemeQuickTime) { 1511 unzoomedRect.setWidth(unzoomedRect.width() / zoomLevel); 1512 unzoomedRect.setHeight(unzoomedRect.height() / zoomLevel); 1513 paintInfo.context->translate(unzoomedRect.x(), unzoomedRect.y()); 1514 paintInfo.context->scale(FloatSize(zoomLevel, zoomLevel)); 1515 paintInfo.context->translate(-unzoomedRect.x(), -unzoomedRect.y()); 1516 } 1517 return unzoomedRect; 1518 } 1519 1520 1521 bool RenderThemeMac::paintMediaFullscreenButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r) 1522 { 1523 Node* node = o->node(); 1524 if (!node) 1525 return false; 1526 1527 LocalCurrentGraphicsContext localContext(paintInfo.context); 1528 wkDrawMediaUIPart(MediaFullscreenButton, mediaControllerTheme(), paintInfo.context->platformContext(), r, getMediaUIPartStateFlags(node)); 1529 return false; 1530 } 1531 1532 bool RenderThemeMac::paintMediaMuteButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r) 1533 { 1534 Node* node = o->node(); 1535 Node* mediaNode = node ? node->shadowAncestorNode() : 0; 1536 if (!mediaNode || (!mediaNode->hasTagName(videoTag) && !mediaNode->hasTagName(audioTag))) 1537 return false; 1538 1539 if (MediaControlMuteButtonElement* btn = static_cast<MediaControlMuteButtonElement*>(node)) { 1540 LocalCurrentGraphicsContext localContext(paintInfo.context); 1541 wkDrawMediaUIPart(btn->displayType(), mediaControllerTheme(), paintInfo.context->platformContext(), r, getMediaUIPartStateFlags(node)); 1542 1543 } 1544 return false; 1545 } 1546 1547 bool RenderThemeMac::paintMediaPlayButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r) 1548 { 1549 Node* node = o->node(); 1550 Node* mediaNode = node ? node->shadowAncestorNode() : 0; 1551 if (!mediaNode || (!mediaNode->hasTagName(videoTag) && !mediaNode->hasTagName(audioTag))) 1552 return false; 1553 1554 if (MediaControlPlayButtonElement* btn = static_cast<MediaControlPlayButtonElement*>(node)) { 1555 LocalCurrentGraphicsContext localContext(paintInfo.context); 1556 wkDrawMediaUIPart(btn->displayType(), mediaControllerTheme(), paintInfo.context->platformContext(), r, getMediaUIPartStateFlags(node)); 1557 } 1558 return false; 1559 } 1560 1561 bool RenderThemeMac::paintMediaSeekBackButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r) 1562 { 1563 Node* node = o->node(); 1564 if (!node) 1565 return false; 1566 1567 LocalCurrentGraphicsContext localContext(paintInfo.context); 1568 wkDrawMediaUIPart(MediaSeekBackButton, mediaControllerTheme(), paintInfo.context->platformContext(), r, getMediaUIPartStateFlags(node)); 1569 return false; 1570 } 1571 1572 bool RenderThemeMac::paintMediaSeekForwardButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r) 1573 { 1574 Node* node = o->node(); 1575 if (!node) 1576 return false; 1577 1578 LocalCurrentGraphicsContext localContext(paintInfo.context); 1579 wkDrawMediaUIPart(MediaSeekForwardButton, mediaControllerTheme(), paintInfo.context->platformContext(), r, getMediaUIPartStateFlags(node)); 1580 return false; 1581 } 1582 1583 bool RenderThemeMac::paintMediaSliderTrack(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r) 1584 { 1585 Node* node = o->node(); 1586 Node* mediaNode = node ? node->shadowAncestorNode() : 0; 1587 if (!mediaNode || (!mediaNode->hasTagName(videoTag) && !mediaNode->hasTagName(audioTag))) 1588 return false; 1589 1590 HTMLMediaElement* mediaElement = static_cast<HTMLMediaElement*>(mediaNode); 1591 if (!mediaElement) 1592 return false; 1593 1594 RefPtr<TimeRanges> timeRanges = mediaElement->buffered(); 1595 ExceptionCode ignoredException; 1596 float timeLoaded = timeRanges->length() ? timeRanges->end(0, ignoredException) : 0; 1597 float currentTime = mediaElement->currentTime(); 1598 float duration = mediaElement->duration(); 1599 if (isnan(duration)) 1600 duration = 0; 1601 1602 paintInfo.context->save(); 1603 FloatRect unzoomedRect = getUnzoomedRectAndAdjustCurrentContext(o, paintInfo, r); 1604 wkDrawMediaSliderTrack(mediaControllerTheme(), paintInfo.context->platformContext(), unzoomedRect, 1605 timeLoaded, currentTime, duration, getMediaUIPartStateFlags(node)); 1606 1607 paintInfo.context->restore(); 1608 return false; 1609 } 1610 1611 bool RenderThemeMac::paintMediaSliderThumb(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r) 1612 { 1613 Node* node = o->node(); 1614 if (!node) 1615 return false; 1616 1617 LocalCurrentGraphicsContext localContext(paintInfo.context); 1618 wkDrawMediaUIPart(MediaSliderThumb, mediaControllerTheme(), paintInfo.context->platformContext(), r, getMediaUIPartStateFlags(node)); 1619 return false; 1620 } 1621 1622 bool RenderThemeMac::paintMediaRewindButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r) 1623 { 1624 Node* node = o->node(); 1625 if (!node) 1626 return false; 1627 1628 LocalCurrentGraphicsContext localContext(paintInfo.context); 1629 wkDrawMediaUIPart(MediaRewindButton, mediaControllerTheme(), paintInfo.context->platformContext(), r, getMediaUIPartStateFlags(node)); 1630 return false; 1631 } 1632 1633 bool RenderThemeMac::paintMediaReturnToRealtimeButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r) 1634 { 1635 Node* node = o->node(); 1636 if (!node) 1637 return false; 1638 1639 LocalCurrentGraphicsContext localContext(paintInfo.context); 1640 wkDrawMediaUIPart(MediaReturnToRealtimeButton, mediaControllerTheme(), paintInfo.context->platformContext(), r, getMediaUIPartStateFlags(node)); 1641 return false; 1642 } 1643 1644 bool RenderThemeMac::paintMediaToggleClosedCaptionsButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r) 1645 { 1646 HTMLInputElement* node = static_cast<HTMLInputElement*>(o->node()); 1647 if (!node) 1648 return false; 1649 1650 MediaControlToggleClosedCaptionsButtonElement* btn = static_cast<MediaControlToggleClosedCaptionsButtonElement*>(node); 1651 if (!btn) 1652 return false; 1653 1654 LocalCurrentGraphicsContext localContext(paintInfo.context); 1655 wkDrawMediaUIPart(btn->displayType(), mediaControllerTheme(), paintInfo.context->platformContext(), r, getMediaUIPartStateFlags(node)); 1656 1657 return false; 1658 } 1659 1660 bool RenderThemeMac::paintMediaControlsBackground(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r) 1661 { 1662 Node* node = o->node(); 1663 if (!node) 1664 return false; 1665 1666 LocalCurrentGraphicsContext localContext(paintInfo.context); 1667 wkDrawMediaUIPart(MediaTimelineContainer, mediaControllerTheme(), paintInfo.context->platformContext(), r, getMediaUIPartStateFlags(node)); 1668 return false; 1669 } 1670 1671 bool RenderThemeMac::paintMediaCurrentTime(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r) 1672 { 1673 Node* node = o->node(); 1674 if (!node) 1675 return false; 1676 1677 paintInfo.context->save(); 1678 FloatRect unzoomedRect = getUnzoomedRectAndAdjustCurrentContext(o, paintInfo, r); 1679 wkDrawMediaUIPart(MediaCurrentTimeDisplay, mediaControllerTheme(), paintInfo.context->platformContext(), unzoomedRect, getMediaUIPartStateFlags(node)); 1680 paintInfo.context->restore(); 1681 return false; 1682 } 1683 1684 bool RenderThemeMac::paintMediaTimeRemaining(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r) 1685 { 1686 Node* node = o->node(); 1687 if (!node) 1688 return false; 1689 1690 paintInfo.context->save(); 1691 FloatRect unzoomedRect = getUnzoomedRectAndAdjustCurrentContext(o, paintInfo, r); 1692 wkDrawMediaUIPart(MediaTimeRemainingDisplay, mediaControllerTheme(), paintInfo.context->platformContext(), unzoomedRect, getMediaUIPartStateFlags(node)); 1693 paintInfo.context->restore(); 1694 return false; 1695 } 1696 1697 String RenderThemeMac::extraMediaControlsStyleSheet() 1698 { 1699 if (mediaControllerTheme() == MediaControllerThemeQuickTime) 1700 return String(mediaControlsQuickTimeUserAgentStyleSheet, sizeof(mediaControlsQuickTimeUserAgentStyleSheet)); 1701 else 1702 return String(); 1703 } 1704 1705 bool RenderThemeMac::shouldRenderMediaControlPart(ControlPart part, Element* element) 1706 { 1707 if (part == MediaToggleClosedCaptionsButtonPart) { 1708 1709 // We rely on QTKit to render captions so don't enable the button unless it will be able to do so. 1710 if (!element->hasTagName(videoTag)) 1711 return false; 1712 } 1713 1714 return RenderTheme::shouldRenderMediaControlPart(part, element); 1715 } 1716 1717 #endif // ENABLE(VIDEO) 1718 1719 NSPopUpButtonCell* RenderThemeMac::popupButton() const 1720 { 1721 if (!m_popupButton) { 1722 m_popupButton.adoptNS([[NSPopUpButtonCell alloc] initTextCell:@"" pullsDown:NO]); 1723 [m_popupButton.get() setUsesItemFromMenu:NO]; 1724 [m_popupButton.get() setFocusRingType:NSFocusRingTypeExterior]; 1725 } 1726 1727 return m_popupButton.get(); 1728 } 1729 1730 NSSearchFieldCell* RenderThemeMac::search() const 1731 { 1732 if (!m_search) { 1733 m_search.adoptNS([[NSSearchFieldCell alloc] initTextCell:@""]); 1734 [m_search.get() setBezelStyle:NSTextFieldRoundedBezel]; 1735 [m_search.get() setBezeled:YES]; 1736 [m_search.get() setEditable:YES]; 1737 [m_search.get() setFocusRingType:NSFocusRingTypeExterior]; 1738 } 1739 1740 return m_search.get(); 1741 } 1742 1743 NSMenu* RenderThemeMac::searchMenuTemplate() const 1744 { 1745 if (!m_searchMenuTemplate) 1746 m_searchMenuTemplate.adoptNS([[NSMenu alloc] initWithTitle:@""]); 1747 1748 return m_searchMenuTemplate.get(); 1749 } 1750 1751 NSSliderCell* RenderThemeMac::sliderThumbHorizontal() const 1752 { 1753 if (!m_sliderThumbHorizontal) { 1754 m_sliderThumbHorizontal.adoptNS([[NSSliderCell alloc] init]); 1755 [m_sliderThumbHorizontal.get() setTitle:nil]; 1756 [m_sliderThumbHorizontal.get() setSliderType:NSLinearSlider]; 1757 [m_sliderThumbHorizontal.get() setControlSize:NSSmallControlSize]; 1758 [m_sliderThumbHorizontal.get() setFocusRingType:NSFocusRingTypeExterior]; 1759 } 1760 1761 return m_sliderThumbHorizontal.get(); 1762 } 1763 1764 NSSliderCell* RenderThemeMac::sliderThumbVertical() const 1765 { 1766 if (!m_sliderThumbVertical) { 1767 m_sliderThumbVertical.adoptNS([[NSSliderCell alloc] init]); 1768 [m_sliderThumbVertical.get() setTitle:nil]; 1769 [m_sliderThumbVertical.get() setSliderType:NSLinearSlider]; 1770 [m_sliderThumbVertical.get() setControlSize:NSSmallControlSize]; 1771 [m_sliderThumbVertical.get() setFocusRingType:NSFocusRingTypeExterior]; 1772 } 1773 1774 return m_sliderThumbVertical.get(); 1775 } 1776 1777 } // namespace WebCore 1778