1/* 2 * Copyright (C) 2006, 2007, 2013 Apple Inc. 3 * Copyright (C) 2009 Kenneth Rohde Christiansen 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., 59 Temple Place - Suite 330, 18 * Boston, MA 02111-1307, USA. 19 * 20 */ 21 22#include "config.h" 23#include "RenderThemeWin.h" 24 25#include "CSSValueKeywords.h" 26#include "Element.h" 27#include "FontMetrics.h" 28#include "Frame.h" 29#include "FrameSelection.h" 30#include "GraphicsContext.h" 31#include "HTMLMeterElement.h" 32#include "LocalWindowsContext.h" 33#include "PaintInfo.h" 34#include "RenderMeter.h" 35#include "RenderSlider.h" 36#include "Settings.h" 37#include "SoftLinking.h" 38#include "SystemInfo.h" 39#include "UserAgentStyleSheets.h" 40#include "WebCoreBundleWin.h" 41#include <wtf/win/GDIObject.h> 42 43#if ENABLE(VIDEO) 44#include "RenderMediaControls.h" 45#endif 46 47#include <tchar.h> 48 49/* 50 * The following constants are used to determine how a widget is drawn using 51 * Windows' Theme API. For more information on theme parts and states see 52 * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/shellcc/platform/commctls/userex/topics/partsandstates.asp 53 */ 54 55// Generic state constants 56#define TS_NORMAL 1 57#define TS_HOVER 2 58#define TS_ACTIVE 3 59#define TS_DISABLED 4 60#define TS_FOCUSED 5 61 62// Button constants 63#define BP_BUTTON 1 64#define BP_RADIO 2 65#define BP_CHECKBOX 3 66 67// Textfield constants 68#define TFP_TEXTFIELD 1 69#define EP_EDITBORDER_NOSCROLL 6 70#define TFS_READONLY 6 71 72// ComboBox constants (from vsstyle.h) 73#define CP_DROPDOWNBUTTON 1 74#define CP_BORDER 4 75#define CP_READONLY 5 76#define CP_DROPDOWNBUTTONRIGHT 6 77 78// TrackBar (slider) parts 79#define TKP_TRACK 1 80#define TKP_TRACKVERT 2 81 82// TrackBar (slider) thumb parts 83#define TKP_THUMBBOTTOM 4 84#define TKP_THUMBTOP 5 85#define TKP_THUMBLEFT 7 86#define TKP_THUMBRIGHT 8 87 88// Trackbar (slider) thumb states 89#define TUS_NORMAL 1 90#define TUS_HOT 2 91#define TUS_PRESSED 3 92#define TUS_FOCUSED 4 93#define TUS_DISABLED 5 94 95// button states 96#define PBS_NORMAL 1 97#define PBS_HOT 2 98#define PBS_PRESSED 3 99#define PBS_DISABLED 4 100#define PBS_DEFAULTED 5 101 102// Spin button parts 103#define SPNP_UP 1 104#define SPNP_DOWN 2 105 106// Spin button states 107#define DNS_NORMAL 1 108#define DNS_HOT 2 109#define DNS_PRESSED 3 110#define DNS_DISABLED 4 111#define UPS_NORMAL 1 112#define UPS_HOT 2 113#define UPS_PRESSED 3 114#define UPS_DISABLED 4 115 116// Progress bar parts 117#define PP_BAR 1 118#define PP_BARVERT 2 119#define PP_CHUNK 3 120#define PP_CHUNKVERT 4 121#define PP_FILL 5 122#define PP_FILLVERT 6 123#define PP_PULSEOVERLAY 7 124#define PP_MOVEOVERLAY 8 125#define PP_PULSEOVERLAYVERT 9 126#define PP_MOVEOVERLAYVERT 10 127#define PP_TRANSPARENTBAR 11 128#define PP_TRANSPARENTBARVERT 12 129 130// Progress bar states 131#define PBBS_NORMAL 1 132#define PBBS_PARTIAL 2 133#define PBBVS_NORMAL 1 // Vertical 134#define PBBVS_PARTIAL 2 135 136// Progress bar fill states 137#define PBFS_NORMAL 1 138#define PBFS_ERROR 2 139#define PBFS_PAUSED 3 140#define PBFS_PARTIAL 4 141#define PBFVS_NORMAL 1 // Vertical 142#define PBFVS_ERROR 2 143#define PBFVS_PAUSED 3 144#define PBFVS_PARTIAL 4 145 146 147SOFT_LINK_LIBRARY(uxtheme) 148SOFT_LINK(uxtheme, OpenThemeData, HANDLE, WINAPI, (HWND hwnd, LPCWSTR pszClassList), (hwnd, pszClassList)) 149SOFT_LINK(uxtheme, CloseThemeData, HRESULT, WINAPI, (HANDLE hTheme), (hTheme)) 150SOFT_LINK(uxtheme, DrawThemeBackground, HRESULT, WINAPI, (HANDLE hTheme, HDC hdc, int iPartId, int iStateId, const RECT* pRect, const RECT* pClipRect), (hTheme, hdc, iPartId, iStateId, pRect, pClipRect)) 151SOFT_LINK(uxtheme, IsThemeActive, BOOL, WINAPI, (), ()) 152SOFT_LINK(uxtheme, IsThemeBackgroundPartiallyTransparent, BOOL, WINAPI, (HANDLE hTheme, int iPartId, int iStateId), (hTheme, iPartId, iStateId)) 153 154static bool haveTheme; 155 156static const unsigned vistaMenuListButtonOutset = 1; 157 158using namespace std; 159 160namespace WebCore { 161 162// This is the fixed width IE and Firefox use for buttons on dropdown menus 163static const int dropDownButtonWidth = 17; 164 165static const int shell32MagnifierIconIndex = 22; 166 167// Default font size to match Firefox. 168static const float defaultControlFontPixelSize = 13; 169 170static const float defaultCancelButtonSize = 9; 171static const float minCancelButtonSize = 5; 172static const float maxCancelButtonSize = 21; 173static const float defaultSearchFieldResultsDecorationSize = 13; 174static const float minSearchFieldResultsDecorationSize = 9; 175static const float maxSearchFieldResultsDecorationSize = 30; 176static const float defaultSearchFieldResultsButtonWidth = 18; 177 178static bool gWebKitIsBeingUnloaded; 179 180void RenderThemeWin::setWebKitIsBeingUnloaded() 181{ 182 gWebKitIsBeingUnloaded = true; 183} 184 185PassRefPtr<RenderTheme> RenderThemeWin::create() 186{ 187 return adoptRef(new RenderThemeWin); 188} 189 190#if !USE(SAFARI_THEME) 191PassRefPtr<RenderTheme> RenderTheme::themeForPage(Page* page) 192{ 193 static RenderTheme* winTheme = RenderThemeWin::create().leakRef(); 194 return winTheme; 195} 196#endif 197 198RenderThemeWin::RenderThemeWin() 199 : m_buttonTheme(0) 200 , m_textFieldTheme(0) 201 , m_menuListTheme(0) 202 , m_sliderTheme(0) 203 , m_spinButtonTheme(0) 204 , m_progressBarTheme(0) 205{ 206 haveTheme = uxthemeLibrary() && IsThemeActive(); 207} 208 209RenderThemeWin::~RenderThemeWin() 210{ 211 // If WebKit is being unloaded, then uxtheme.dll is no longer available. 212 if (gWebKitIsBeingUnloaded || !uxthemeLibrary()) 213 return; 214 close(); 215} 216 217HANDLE RenderThemeWin::buttonTheme() const 218{ 219 if (haveTheme && !m_buttonTheme) 220 m_buttonTheme = OpenThemeData(0, L"Button"); 221 return m_buttonTheme; 222} 223 224HANDLE RenderThemeWin::textFieldTheme() const 225{ 226 if (haveTheme && !m_textFieldTheme) 227 m_textFieldTheme = OpenThemeData(0, L"Edit"); 228 return m_textFieldTheme; 229} 230 231HANDLE RenderThemeWin::menuListTheme() const 232{ 233 if (haveTheme && !m_menuListTheme) 234 m_menuListTheme = OpenThemeData(0, L"ComboBox"); 235 return m_menuListTheme; 236} 237 238HANDLE RenderThemeWin::sliderTheme() const 239{ 240 if (haveTheme && !m_sliderTheme) 241 m_sliderTheme = OpenThemeData(0, L"TrackBar"); 242 return m_sliderTheme; 243} 244 245HANDLE RenderThemeWin::spinButtonTheme() const 246{ 247 if (haveTheme && !m_spinButtonTheme) 248 m_spinButtonTheme = OpenThemeData(0, L"Spin"); 249 return m_spinButtonTheme; 250} 251 252HANDLE RenderThemeWin::progressBarTheme() const 253{ 254 if (haveTheme && !m_progressBarTheme) 255 m_progressBarTheme = OpenThemeData(0, L"Progress"); 256 return m_progressBarTheme; 257} 258 259void RenderThemeWin::close() 260{ 261 // This method will need to be called when the OS theme changes to flush our cached themes. 262 if (m_buttonTheme) 263 CloseThemeData(m_buttonTheme); 264 if (m_textFieldTheme) 265 CloseThemeData(m_textFieldTheme); 266 if (m_menuListTheme) 267 CloseThemeData(m_menuListTheme); 268 if (m_sliderTheme) 269 CloseThemeData(m_sliderTheme); 270 if (m_spinButtonTheme) 271 CloseThemeData(m_spinButtonTheme); 272 if (m_progressBarTheme) 273 CloseThemeData(m_progressBarTheme); 274 m_buttonTheme = m_textFieldTheme = m_menuListTheme = m_sliderTheme = m_spinButtonTheme = m_progressBarTheme = 0; 275 276 haveTheme = uxthemeLibrary() && IsThemeActive(); 277} 278 279void RenderThemeWin::themeChanged() 280{ 281 close(); 282} 283 284String RenderThemeWin::extraDefaultStyleSheet() 285{ 286 return String(themeWinUserAgentStyleSheet, sizeof(themeWinUserAgentStyleSheet)); 287} 288 289String RenderThemeWin::extraQuirksStyleSheet() 290{ 291 return String(themeWinQuirksUserAgentStyleSheet, sizeof(themeWinQuirksUserAgentStyleSheet)); 292} 293 294bool RenderThemeWin::supportsHover(const RenderStyle&) const 295{ 296 // The Classic/2k look has no hover effects. 297 return haveTheme; 298} 299 300Color RenderThemeWin::platformActiveSelectionBackgroundColor() const 301{ 302 COLORREF color = GetSysColor(COLOR_HIGHLIGHT); 303 return Color(GetRValue(color), GetGValue(color), GetBValue(color)); 304} 305 306Color RenderThemeWin::platformInactiveSelectionBackgroundColor() const 307{ 308 // This color matches Firefox. 309 return Color(176, 176, 176); 310} 311 312Color RenderThemeWin::platformActiveSelectionForegroundColor() const 313{ 314 COLORREF color = GetSysColor(COLOR_HIGHLIGHTTEXT); 315 return Color(GetRValue(color), GetGValue(color), GetBValue(color)); 316} 317 318Color RenderThemeWin::platformInactiveSelectionForegroundColor() const 319{ 320 return platformActiveSelectionForegroundColor(); 321} 322 323static void fillFontDescription(FontDescription& fontDescription, LOGFONT& logFont, float fontSize) 324{ 325 fontDescription.setIsAbsoluteSize(true); 326 fontDescription.setGenericFamily(FontDescription::NoFamily); 327 fontDescription.setOneFamily(String(logFont.lfFaceName)); 328 fontDescription.setSpecifiedSize(fontSize); 329 fontDescription.setWeight(logFont.lfWeight >= 700 ? FontWeightBold : FontWeightNormal); // FIXME: Use real weight. 330 fontDescription.setItalic(logFont.lfItalic); 331} 332 333static void fillFontDescription(FontDescription& fontDescription, LOGFONT& logFont) 334{ 335 fillFontDescription(fontDescription, logFont, abs(logFont.lfHeight)); 336} 337 338void RenderThemeWin::systemFont(CSSValueID valueID, FontDescription& fontDescription) const 339{ 340 static FontDescription captionFont; 341 static FontDescription controlFont; 342 static FontDescription smallCaptionFont; 343 static FontDescription menuFont; 344 static FontDescription iconFont; 345 static FontDescription messageBoxFont; 346 static FontDescription statusBarFont; 347 static FontDescription systemFont; 348 349 static bool initialized; 350 static NONCLIENTMETRICS ncm; 351 352 if (!initialized) { 353 initialized = true; 354 ncm.cbSize = sizeof(NONCLIENTMETRICS); 355 ::SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(ncm), &ncm, 0); 356 } 357 358 switch (valueID) { 359 case CSSValueIcon: { 360 if (!iconFont.isAbsoluteSize()) { 361 LOGFONT logFont; 362 ::SystemParametersInfo(SPI_GETICONTITLELOGFONT, sizeof(logFont), &logFont, 0); 363 fillFontDescription(iconFont, logFont); 364 } 365 fontDescription = iconFont; 366 break; 367 } 368 case CSSValueMenu: 369 if (!menuFont.isAbsoluteSize()) 370 fillFontDescription(menuFont, ncm.lfMenuFont); 371 fontDescription = menuFont; 372 break; 373 case CSSValueMessageBox: 374 if (!messageBoxFont.isAbsoluteSize()) 375 fillFontDescription(messageBoxFont, ncm.lfMessageFont); 376 fontDescription = messageBoxFont; 377 break; 378 case CSSValueStatusBar: 379 if (!statusBarFont.isAbsoluteSize()) 380 fillFontDescription(statusBarFont, ncm.lfStatusFont); 381 fontDescription = statusBarFont; 382 break; 383 case CSSValueCaption: 384 if (!captionFont.isAbsoluteSize()) 385 fillFontDescription(captionFont, ncm.lfCaptionFont); 386 fontDescription = captionFont; 387 break; 388 case CSSValueSmallCaption: 389 if (!smallCaptionFont.isAbsoluteSize()) 390 fillFontDescription(smallCaptionFont, ncm.lfSmCaptionFont); 391 fontDescription = smallCaptionFont; 392 break; 393 case CSSValueWebkitSmallControl: 394 case CSSValueWebkitMiniControl: // Just map to small. 395 case CSSValueWebkitControl: // Just map to small. 396 if (!controlFont.isAbsoluteSize()) { 397 HGDIOBJ hGDI = ::GetStockObject(DEFAULT_GUI_FONT); 398 if (hGDI) { 399 LOGFONT logFont; 400 if (::GetObject(hGDI, sizeof(logFont), &logFont) > 0) 401 fillFontDescription(controlFont, logFont, defaultControlFontPixelSize); 402 } 403 } 404 fontDescription = controlFont; 405 break; 406 default: { // Everything else uses the stock GUI font. 407 if (!systemFont.isAbsoluteSize()) { 408 HGDIOBJ hGDI = ::GetStockObject(DEFAULT_GUI_FONT); 409 if (hGDI) { 410 LOGFONT logFont; 411 if (::GetObject(hGDI, sizeof(logFont), &logFont) > 0) 412 fillFontDescription(systemFont, logFont); 413 } 414 } 415 fontDescription = systemFont; 416 } 417 } 418} 419 420bool RenderThemeWin::supportsFocus(ControlPart appearance) const 421{ 422 switch (appearance) { 423 case PushButtonPart: 424 case ButtonPart: 425 case DefaultButtonPart: 426 return true; 427 default: 428 return false; 429 } 430} 431 432bool RenderThemeWin::supportsFocusRing(const RenderStyle& style) const 433{ 434 return supportsFocus(style.appearance()); 435} 436 437unsigned RenderThemeWin::determineClassicState(const RenderObject& o, ControlSubPart subPart) 438{ 439 unsigned state = 0; 440 switch (o.style().appearance()) { 441 case PushButtonPart: 442 case ButtonPart: 443 case DefaultButtonPart: 444 state = DFCS_BUTTONPUSH; 445 if (!isEnabled(o)) 446 state |= DFCS_INACTIVE; 447 else if (isPressed(o)) 448 state |= DFCS_PUSHED; 449 break; 450 case RadioPart: 451 case CheckboxPart: 452 state = (o.style().appearance() == RadioPart) ? DFCS_BUTTONRADIO : DFCS_BUTTONCHECK; 453 if (isChecked(o)) 454 state |= DFCS_CHECKED; 455 if (!isEnabled(o)) 456 state |= DFCS_INACTIVE; 457 else if (isPressed(o)) 458 state |= DFCS_PUSHED; 459 break; 460 case MenulistPart: 461 state = DFCS_SCROLLCOMBOBOX; 462 if (!isEnabled(o)) 463 state |= DFCS_INACTIVE; 464 else if (isPressed(o)) 465 state |= DFCS_PUSHED; 466 break; 467 case InnerSpinButtonPart: { 468 bool isUpButton = subPart == SpinButtonUp; 469 state = isUpButton ? DFCS_SCROLLUP : DFCS_SCROLLDOWN; 470 if (!isEnabled(o) || isReadOnlyControl(o)) 471 state |= DFCS_INACTIVE; 472 else if (isPressed(o) && isUpButton == isSpinUpButtonPartPressed(o)) 473 state |= DFCS_PUSHED; 474 else if (isHovered(o) && isUpButton == isSpinUpButtonPartHovered(o)) 475 state |= DFCS_HOT; 476 break; 477 } 478 default: 479 break; 480 } 481 return state; 482} 483 484unsigned RenderThemeWin::determineState(const RenderObject& o) 485{ 486 unsigned result = TS_NORMAL; 487 ControlPart appearance = o.style().appearance(); 488 if (!isEnabled(o)) 489 result = TS_DISABLED; 490 else if (isReadOnlyControl(o) && (TextFieldPart == appearance || TextAreaPart == appearance || SearchFieldPart == appearance)) 491 result = TFS_READONLY; // Readonly is supported on textfields. 492 else if (isPressed(o)) // Active overrides hover and focused. 493 result = TS_ACTIVE; 494 else if (supportsFocus(appearance) && isFocused(o)) 495 result = TS_FOCUSED; 496 else if (isHovered(o)) 497 result = TS_HOVER; 498 if (isChecked(o)) 499 result += 4; // 4 unchecked states, 4 checked states. 500 else if (isIndeterminate(o) && appearance == CheckboxPart) 501 result += 8; 502 return result; 503} 504 505unsigned RenderThemeWin::determineSliderThumbState(const RenderObject& o) 506{ 507 unsigned result = TUS_NORMAL; 508 if (!isEnabled(o)) 509 result = TUS_DISABLED; 510 else if (supportsFocus(o.style().appearance()) && isFocused(o)) 511 result = TUS_FOCUSED; 512 else if (isPressed(o)) 513 result = TUS_PRESSED; 514 else if (isHovered(o)) 515 result = TUS_HOT; 516 return result; 517} 518 519unsigned RenderThemeWin::determineButtonState(const RenderObject& o) 520{ 521 unsigned result = PBS_NORMAL; 522 if (!isEnabled(o)) 523 result = PBS_DISABLED; 524 else if (isPressed(o)) 525 result = PBS_PRESSED; 526 else if (supportsFocus(o.style().appearance()) && isFocused(o)) 527 result = PBS_DEFAULTED; 528 else if (isHovered(o)) 529 result = PBS_HOT; 530 else if (isDefault(o)) 531 result = PBS_DEFAULTED; 532 return result; 533} 534 535unsigned RenderThemeWin::determineSpinButtonState(const RenderObject& o, ControlSubPart subPart) 536{ 537 bool isUpButton = subPart == SpinButtonUp; 538 unsigned result = isUpButton ? UPS_NORMAL : DNS_NORMAL; 539 if (!isEnabled(o) || isReadOnlyControl(o)) 540 result = isUpButton ? UPS_DISABLED : DNS_DISABLED; 541 else if (isPressed(o) && isUpButton == isSpinUpButtonPartPressed(o)) 542 result = isUpButton ? UPS_PRESSED : DNS_PRESSED; 543 else if (isHovered(o) && isUpButton == isSpinUpButtonPartHovered(o)) 544 result = isUpButton ? UPS_HOT : DNS_HOT; 545 return result; 546} 547 548ThemeData RenderThemeWin::getClassicThemeData(const RenderObject& o, ControlSubPart subPart) 549{ 550 ThemeData result; 551 switch (o.style().appearance()) { 552 case PushButtonPart: 553 case ButtonPart: 554 case DefaultButtonPart: 555 case CheckboxPart: 556 case RadioPart: 557 result.m_part = DFC_BUTTON; 558 result.m_state = determineClassicState(o); 559 break; 560 case MenulistPart: 561 result.m_part = DFC_SCROLL; 562 result.m_state = determineClassicState(o); 563 break; 564 case MeterPart: 565 result.m_part = PP_BAR; 566 result.m_state = determineState(o); 567 break; 568 case SearchFieldPart: 569 case TextFieldPart: 570 case TextAreaPart: 571 result.m_part = TFP_TEXTFIELD; 572 result.m_state = determineState(o); 573 break; 574 case SliderHorizontalPart: 575 result.m_part = TKP_TRACK; 576 result.m_state = TS_NORMAL; 577 break; 578 case SliderVerticalPart: 579 result.m_part = TKP_TRACKVERT; 580 result.m_state = TS_NORMAL; 581 break; 582 case SliderThumbHorizontalPart: 583 result.m_part = TKP_THUMBBOTTOM; 584 result.m_state = determineSliderThumbState(o); 585 break; 586 case SliderThumbVerticalPart: 587 result.m_part = TKP_THUMBRIGHT; 588 result.m_state = determineSliderThumbState(o); 589 break; 590 case InnerSpinButtonPart: 591 result.m_part = DFC_SCROLL; 592 result.m_state = determineClassicState(o, subPart); 593 break; 594 default: 595 break; 596 } 597 return result; 598} 599 600ThemeData RenderThemeWin::getThemeData(const RenderObject& o, ControlSubPart subPart) 601{ 602 if (!haveTheme) 603 return getClassicThemeData(o, subPart); 604 605 ThemeData result; 606 switch (o.style().appearance()) { 607 case PushButtonPart: 608 case ButtonPart: 609 case DefaultButtonPart: 610 result.m_part = BP_BUTTON; 611 result.m_state = determineButtonState(o); 612 break; 613 case CheckboxPart: 614 result.m_part = BP_CHECKBOX; 615 result.m_state = determineState(o); 616 break; 617 case MenulistPart: 618 case MenulistButtonPart: { 619 const bool isVistaOrLater = (windowsVersion() >= WindowsVista); 620 result.m_part = isVistaOrLater ? CP_DROPDOWNBUTTONRIGHT : CP_DROPDOWNBUTTON; 621 if (isVistaOrLater && o.frame().settings().applicationChromeMode()) { 622 // The "readonly" look we use in application chrome mode 623 // only uses a "normal" look for the drop down button. 624 result.m_state = TS_NORMAL; 625 } else 626 result.m_state = determineState(o); 627 break; 628 } 629 case MeterPart: 630 result.m_part = PP_BAR; 631 result.m_state = determineState(o); 632 break; 633 case RadioPart: 634 result.m_part = BP_RADIO; 635 result.m_state = determineState(o); 636 break; 637 case SearchFieldPart: 638 case TextFieldPart: 639 case TextAreaPart: 640 result.m_part = (windowsVersion() >= WindowsVista) ? EP_EDITBORDER_NOSCROLL : TFP_TEXTFIELD; 641 result.m_state = determineState(o); 642 break; 643 case SliderHorizontalPart: 644 result.m_part = TKP_TRACK; 645 result.m_state = TS_NORMAL; 646 break; 647 case SliderVerticalPart: 648 result.m_part = TKP_TRACKVERT; 649 result.m_state = TS_NORMAL; 650 break; 651 case SliderThumbHorizontalPart: 652 result.m_part = TKP_THUMBBOTTOM; 653 result.m_state = determineSliderThumbState(o); 654 break; 655 case SliderThumbVerticalPart: 656 result.m_part = TKP_THUMBRIGHT; 657 result.m_state = determineSliderThumbState(o); 658 break; 659 case InnerSpinButtonPart: 660 result.m_part = subPart == SpinButtonUp ? SPNP_UP : SPNP_DOWN; 661 result.m_state = determineSpinButtonState(o, subPart); 662 break; 663 } 664 665 return result; 666} 667 668static void drawControl(GraphicsContext* context, const RenderObject& o, HANDLE theme, const ThemeData& themeData, const IntRect& r) 669{ 670 bool alphaBlend = false; 671 if (theme) 672 alphaBlend = IsThemeBackgroundPartiallyTransparent(theme, themeData.m_part, themeData.m_state); 673 LocalWindowsContext windowsContext(context, r, alphaBlend); 674 RECT widgetRect = r; 675 if (theme) 676 DrawThemeBackground(theme, windowsContext.hdc(), themeData.m_part, themeData.m_state, &widgetRect, 0); 677 else { 678 HDC hdc = windowsContext.hdc(); 679 if (themeData.m_part == TFP_TEXTFIELD) { 680 ::DrawEdge(hdc, &widgetRect, EDGE_SUNKEN, BF_RECT | BF_ADJUST); 681 if (themeData.m_state == TS_DISABLED || themeData.m_state == TFS_READONLY) 682 ::FillRect(hdc, &widgetRect, (HBRUSH)(COLOR_BTNFACE+1)); 683 else 684 ::FillRect(hdc, &widgetRect, (HBRUSH)(COLOR_WINDOW+1)); 685 } else if (themeData.m_part == TKP_TRACK || themeData.m_part == TKP_TRACKVERT) { 686 ::DrawEdge(hdc, &widgetRect, EDGE_SUNKEN, BF_RECT | BF_ADJUST); 687 ::FillRect(hdc, &widgetRect, (HBRUSH)GetStockObject(GRAY_BRUSH)); 688 } else if ((o.style().appearance() == SliderThumbHorizontalPart 689 || o.style().appearance() == SliderThumbVerticalPart) 690 && (themeData.m_part == TKP_THUMBBOTTOM || themeData.m_part == TKP_THUMBTOP 691 || themeData.m_part == TKP_THUMBLEFT || themeData.m_part == TKP_THUMBRIGHT)) { 692 ::DrawEdge(hdc, &widgetRect, EDGE_RAISED, BF_RECT | BF_SOFT | BF_MIDDLE | BF_ADJUST); 693 if (themeData.m_state == TUS_DISABLED) { 694 static WORD patternBits[8] = {0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55}; 695 auto patternBmp = adoptGDIObject(::CreateBitmap(8, 8, 1, 1, patternBits)); 696 if (patternBmp) { 697 auto brush = adoptGDIObject(::CreatePatternBrush(patternBmp.get())); 698 COLORREF oldForeColor = ::SetTextColor(hdc, ::GetSysColor(COLOR_3DFACE)); 699 COLORREF oldBackColor = ::SetBkColor(hdc, ::GetSysColor(COLOR_3DHILIGHT)); 700 POINT p; 701 ::GetViewportOrgEx(hdc, &p); 702 ::SetBrushOrgEx(hdc, p.x + widgetRect.left, p.y + widgetRect.top, NULL); 703 HGDIOBJ oldBrush = ::SelectObject(hdc, brush.get()); 704 ::FillRect(hdc, &widgetRect, brush.get()); 705 ::SetTextColor(hdc, oldForeColor); 706 ::SetBkColor(hdc, oldBackColor); 707 ::SelectObject(hdc, oldBrush); 708 } else 709 ::FillRect(hdc, &widgetRect, (HBRUSH)COLOR_3DHILIGHT); 710 } 711 } else { 712 // Push buttons, buttons, checkboxes and radios, and the dropdown arrow in menulists. 713 if (o.style().appearance() == DefaultButtonPart) { 714 HBRUSH brush = ::GetSysColorBrush(COLOR_3DDKSHADOW); 715 ::FrameRect(hdc, &widgetRect, brush); 716 ::InflateRect(&widgetRect, -1, -1); 717 ::DrawEdge(hdc, &widgetRect, BDR_RAISEDOUTER, BF_RECT | BF_MIDDLE); 718 } 719 ::DrawFrameControl(hdc, &widgetRect, themeData.m_part, themeData.m_state); 720 } 721 } 722 723 if (!alphaBlend && !context->isInTransparencyLayer()) 724 DIBPixelData::setRGBABitmapAlpha(windowsContext.hdc(), r, 255); 725} 726 727bool RenderThemeWin::paintButton(const RenderObject& o, const PaintInfo& i, const IntRect& r) 728{ 729 drawControl(i.context, o, buttonTheme(), getThemeData(o), r); 730 return false; 731} 732 733void RenderThemeWin::adjustInnerSpinButtonStyle(StyleResolver& styleResolver, RenderStyle& style, Element& e) const 734{ 735 int width = ::GetSystemMetrics(SM_CXVSCROLL); 736 if (width <= 0) 737 width = 17; // Vista's default. 738 style.setWidth(Length(width, Fixed)); 739 style.setMinWidth(Length(width, Fixed)); 740} 741 742bool RenderThemeWin::paintInnerSpinButton(const RenderObject& o, const PaintInfo& i, const IntRect& r) 743{ 744 // We split the specified rectangle into two vertically. We can't draw a 745 // spin button of which height is less than 2px. 746 if (r.height() < 2) 747 return false; 748 IntRect upRect(r); 749 upRect.setHeight(r.height() / 2); 750 IntRect downRect(r); 751 downRect.setY(upRect.maxY()); 752 downRect.setHeight(r.height() - upRect.height()); 753 drawControl(i.context, o, spinButtonTheme(), getThemeData(o, SpinButtonUp), upRect); 754 drawControl(i.context, o, spinButtonTheme(), getThemeData(o, SpinButtonDown), downRect); 755 return false; 756} 757 758void RenderThemeWin::setCheckboxSize(RenderStyle& style) const 759{ 760 // If the width and height are both specified, then we have nothing to do. 761 if (!style.width().isIntrinsicOrAuto() && !style.height().isAuto()) 762 return; 763 764 // FIXME: A hard-coded size of 13 is used. This is wrong but necessary for now. It matches Firefox. 765 // At different DPI settings on Windows, querying the theme gives you a larger size that accounts for 766 // the higher DPI. Until our entire engine honors a DPI setting other than 96, we can't rely on the theme's 767 // metrics. 768 if (style.width().isIntrinsicOrAuto()) 769 style.setWidth(Length(13, Fixed)); 770 if (style.height().isAuto()) 771 style.setHeight(Length(13, Fixed)); 772} 773 774bool RenderThemeWin::paintTextField(const RenderObject& o, const PaintInfo& i, const FloatRect& r) 775{ 776 drawControl(i.context, o, textFieldTheme(), getThemeData(o), IntRect(r)); 777 return false; 778} 779 780bool RenderThemeWin::paintMenuList(const RenderObject& renderer, const PaintInfo& paintInfo, const FloatRect& rect) 781{ 782 HANDLE theme; 783 int part; 784 if (haveTheme && (windowsVersion() >= WindowsVista)) { 785 theme = menuListTheme(); 786 if (renderer.frame().settings().applicationChromeMode()) 787 part = CP_READONLY; 788 else 789 part = CP_BORDER; 790 } else { 791 theme = textFieldTheme(); 792 part = TFP_TEXTFIELD; 793 } 794 795 drawControl(paintInfo.context, renderer, theme, ThemeData(part, determineState(renderer)), IntRect(rect)); 796 797 return paintMenuListButtonDecorations(renderer, paintInfo, FloatRect(rect)); 798} 799 800void RenderThemeWin::adjustMenuListStyle(StyleResolver& styleResolver, RenderStyle& style, Element& e) const 801{ 802 style.resetBorder(); 803 adjustMenuListButtonStyle(styleResolver, style, e); 804} 805 806void RenderThemeWin::adjustMenuListButtonStyle(StyleResolver& styleResolver, RenderStyle& style, Element& e) const 807{ 808 // These are the paddings needed to place the text correctly in the <select> box 809 const int dropDownBoxPaddingTop = 2; 810 const int dropDownBoxPaddingRight = style.direction() == LTR ? 4 + dropDownButtonWidth : 4; 811 const int dropDownBoxPaddingBottom = 2; 812 const int dropDownBoxPaddingLeft = style.direction() == LTR ? 4 : 4 + dropDownButtonWidth; 813 // The <select> box must be at least 12px high for the button to render nicely on Windows 814 const int dropDownBoxMinHeight = 12; 815 816 // Position the text correctly within the select box and make the box wide enough to fit the dropdown button 817 style.setPaddingTop(Length(dropDownBoxPaddingTop, Fixed)); 818 style.setPaddingRight(Length(dropDownBoxPaddingRight, Fixed)); 819 style.setPaddingBottom(Length(dropDownBoxPaddingBottom, Fixed)); 820 style.setPaddingLeft(Length(dropDownBoxPaddingLeft, Fixed)); 821 822 // Height is locked to auto 823 style.setHeight(Length(Auto)); 824 825 // Calculate our min-height 826 int minHeight = style.fontMetrics().height(); 827 minHeight = max(minHeight, dropDownBoxMinHeight); 828 829 style.setMinHeight(Length(minHeight, Fixed)); 830 831 style.setLineHeight(RenderStyle::initialLineHeight()); 832 833 // White-space is locked to pre 834 style.setWhiteSpace(PRE); 835} 836 837bool RenderThemeWin::paintMenuListButtonDecorations(const RenderObject& renderer, const PaintInfo& paintInfo, const FloatRect& rect) 838{ 839 // FIXME: Don't make hardcoded assumptions about the thickness of the textfield border. 840 int borderThickness = haveTheme ? 1 : 2; 841 842 // Paint the dropdown button on the inner edge of the text field, 843 // leaving space for the text field's 1px border 844 IntRect buttonRect(rect); 845 buttonRect.inflate(-borderThickness); 846 if (renderer.style().direction() == LTR) 847 buttonRect.setX(buttonRect.maxX() - dropDownButtonWidth); 848 buttonRect.setWidth(dropDownButtonWidth); 849 850 if ((windowsVersion() >= WindowsVista)) { 851 // Outset the top, right, and bottom borders of the button so that they coincide with the <select>'s border. 852 buttonRect.setY(buttonRect.y() - vistaMenuListButtonOutset); 853 buttonRect.setHeight(buttonRect.height() + 2 * vistaMenuListButtonOutset); 854 buttonRect.setWidth(buttonRect.width() + vistaMenuListButtonOutset); 855 } 856 857 drawControl(paintInfo.context, renderer, menuListTheme(), getThemeData(renderer), buttonRect); 858 859 return false; 860} 861 862const int trackWidth = 4; 863 864bool RenderThemeWin::paintSliderTrack(const RenderObject& o, const PaintInfo& i, const IntRect& r) 865{ 866 IntRect bounds = r; 867 868 if (o.style().appearance() == SliderHorizontalPart) { 869 bounds.setHeight(trackWidth); 870 bounds.setY(r.y() + r.height() / 2 - trackWidth / 2); 871 } else if (o.style().appearance() == SliderVerticalPart) { 872 bounds.setWidth(trackWidth); 873 bounds.setX(r.x() + r.width() / 2 - trackWidth / 2); 874 } 875 876 drawControl(i.context, o, sliderTheme(), getThemeData(o), bounds); 877 return false; 878} 879 880bool RenderThemeWin::paintSliderThumb(const RenderObject& o, const PaintInfo& i, const IntRect& r) 881{ 882 drawControl(i.context, o, sliderTheme(), getThemeData(o), r); 883 return false; 884} 885 886const int sliderThumbWidth = 7; 887const int sliderThumbHeight = 15; 888 889void RenderThemeWin::adjustSliderThumbSize(RenderStyle& style, Element&) const 890{ 891 ControlPart part = style.appearance(); 892 if (part == SliderThumbVerticalPart) { 893 style.setWidth(Length(sliderThumbHeight, Fixed)); 894 style.setHeight(Length(sliderThumbWidth, Fixed)); 895 } else if (part == SliderThumbHorizontalPart) { 896 style.setWidth(Length(sliderThumbWidth, Fixed)); 897 style.setHeight(Length(sliderThumbHeight, Fixed)); 898 } 899#if ENABLE(VIDEO) && USE(CG) 900 else if (part == MediaSliderThumbPart || part == MediaVolumeSliderThumbPart) 901 RenderMediaControls::adjustMediaSliderThumbSize(style); 902#endif 903} 904 905bool RenderThemeWin::paintSearchField(const RenderObject& o, const PaintInfo& i, const IntRect& r) 906{ 907 return paintTextField(o, i, r); 908} 909 910void RenderThemeWin::adjustSearchFieldStyle(StyleResolver& styleResolver, RenderStyle& style, Element& e) const 911{ 912 // Override paddingSize to match AppKit text positioning. 913 const int padding = 1; 914 style.setPaddingLeft(Length(padding, Fixed)); 915 style.setPaddingRight(Length(padding, Fixed)); 916 style.setPaddingTop(Length(padding, Fixed)); 917 style.setPaddingBottom(Length(padding, Fixed)); 918 if (e.focused() && e.document().frame()->selection().isFocusedAndActive()) 919 style.setOutlineOffset(-2); 920} 921 922bool RenderThemeWin::paintSearchFieldCancelButton(const RenderObject& o, const PaintInfo& paintInfo, const IntRect& r) 923{ 924 IntRect bounds = r; 925 ASSERT(o.parent()); 926 if (!o.parent() || !o.parent()->isBox()) 927 return false; 928 929 RenderBox* parentRenderBox = toRenderBox(o.parent()); 930 931 IntRect parentBox = parentRenderBox->absoluteContentBox(); 932 933 // Make sure the scaled button stays square and will fit in its parent's box 934 bounds.setHeight(min(parentBox.width(), min(parentBox.height(), bounds.height()))); 935 bounds.setWidth(bounds.height()); 936 937 // Center the button vertically. Round up though, so if it has to be one pixel off-center, it will 938 // be one pixel closer to the bottom of the field. This tends to look better with the text. 939 bounds.setY(parentBox.y() + (parentBox.height() - bounds.height() + 1) / 2); 940 941 static Image* cancelImage = Image::loadPlatformResource("searchCancel").leakRef(); 942 static Image* cancelPressedImage = Image::loadPlatformResource("searchCancelPressed").leakRef(); 943 paintInfo.context->drawImage(isPressed(o) ? cancelPressedImage : cancelImage, o.style().colorSpace(), bounds); 944 return false; 945} 946 947void RenderThemeWin::adjustSearchFieldCancelButtonStyle(StyleResolver&, RenderStyle& style, Element&) const 948{ 949 // Scale the button size based on the font size 950 float fontScale = style.fontSize() / defaultControlFontPixelSize; 951 int cancelButtonSize = lroundf(min(max(minCancelButtonSize, defaultCancelButtonSize * fontScale), maxCancelButtonSize)); 952 style.setWidth(Length(cancelButtonSize, Fixed)); 953 style.setHeight(Length(cancelButtonSize, Fixed)); 954} 955 956void RenderThemeWin::adjustSearchFieldDecorationPartStyle(StyleResolver&, RenderStyle& style, Element&) const 957{ 958 IntSize emptySize(1, 11); 959 style.setWidth(Length(emptySize.width(), Fixed)); 960 style.setHeight(Length(emptySize.height(), Fixed)); 961} 962 963void RenderThemeWin::adjustSearchFieldResultsDecorationPartStyle(StyleResolver&, RenderStyle& style, Element&) const 964{ 965 // Scale the decoration size based on the font size 966 float fontScale = style.fontSize() / defaultControlFontPixelSize; 967 int magnifierSize = lroundf(min(max(minSearchFieldResultsDecorationSize, defaultSearchFieldResultsDecorationSize * fontScale), 968 maxSearchFieldResultsDecorationSize)); 969 style.setWidth(Length(magnifierSize, Fixed)); 970 style.setHeight(Length(magnifierSize, Fixed)); 971} 972 973bool RenderThemeWin::paintSearchFieldResultsDecorationPart(const RenderObject& o, const PaintInfo& paintInfo, const IntRect& r) 974{ 975 IntRect bounds = r; 976 ASSERT(o.parent()); 977 if (!o.parent() || !o.parent()->isBox()) 978 return false; 979 980 RenderBox* parentRenderBox = toRenderBox(o.parent()); 981 IntRect parentBox = parentRenderBox->absoluteContentBox(); 982 983 // Make sure the scaled decoration stays square and will fit in its parent's box 984 bounds.setHeight(min(parentBox.width(), min(parentBox.height(), bounds.height()))); 985 bounds.setWidth(bounds.height()); 986 987 // Center the decoration vertically. Round up though, so if it has to be one pixel off-center, it will 988 // be one pixel closer to the bottom of the field. This tends to look better with the text. 989 bounds.setY(parentBox.y() + (parentBox.height() - bounds.height() + 1) / 2); 990 991 static Image* magnifierImage = Image::loadPlatformResource("searchMagnifier").leakRef(); 992 paintInfo.context->drawImage(magnifierImage, o.style().colorSpace(), bounds); 993 return false; 994} 995 996void RenderThemeWin::adjustSearchFieldResultsButtonStyle(StyleResolver&, RenderStyle& style, Element&) const 997{ 998 // Scale the button size based on the font size 999 float fontScale = style.fontSize() / defaultControlFontPixelSize; 1000 int magnifierHeight = lroundf(min(max(minSearchFieldResultsDecorationSize, defaultSearchFieldResultsDecorationSize * fontScale), 1001 maxSearchFieldResultsDecorationSize)); 1002 int magnifierWidth = lroundf(magnifierHeight * defaultSearchFieldResultsButtonWidth / defaultSearchFieldResultsDecorationSize); 1003 style.setWidth(Length(magnifierWidth, Fixed)); 1004 style.setHeight(Length(magnifierHeight, Fixed)); 1005} 1006 1007bool RenderThemeWin::paintSearchFieldResultsButton(const RenderObject& o, const PaintInfo& paintInfo, const IntRect& r) 1008{ 1009 IntRect bounds = r; 1010 ASSERT(o.parent()); 1011 if (!o.parent()) 1012 return false; 1013 if (!o.parent() || !o.parent()->isBox()) 1014 return false; 1015 1016 RenderBox* parentRenderBox = toRenderBox(o.parent()); 1017 IntRect parentBox = parentRenderBox->absoluteContentBox(); 1018 1019 // Make sure the scaled decoration will fit in its parent's box 1020 bounds.setHeight(min(parentBox.height(), bounds.height())); 1021 bounds.setWidth(min<int>(parentBox.width(), bounds.height() * defaultSearchFieldResultsButtonWidth / defaultSearchFieldResultsDecorationSize)); 1022 1023 // Center the button vertically. Round up though, so if it has to be one pixel off-center, it will 1024 // be one pixel closer to the bottom of the field. This tends to look better with the text. 1025 bounds.setY(parentBox.y() + (parentBox.height() - bounds.height() + 1) / 2); 1026 1027 static Image* magnifierImage = Image::loadPlatformResource("searchMagnifierResults").leakRef(); 1028 paintInfo.context->drawImage(magnifierImage, o.style().colorSpace(), bounds); 1029 return false; 1030} 1031 1032// Map a CSSValue* system color to an index understood by GetSysColor 1033static int cssValueIdToSysColorIndex(CSSValueID cssValueId) 1034{ 1035 switch (cssValueId) { 1036 case CSSValueActiveborder: return COLOR_ACTIVEBORDER; 1037 case CSSValueActivecaption: return COLOR_ACTIVECAPTION; 1038 case CSSValueAppworkspace: return COLOR_APPWORKSPACE; 1039 case CSSValueBackground: return COLOR_BACKGROUND; 1040 case CSSValueButtonface: return COLOR_BTNFACE; 1041 case CSSValueButtonhighlight: return COLOR_BTNHIGHLIGHT; 1042 case CSSValueButtonshadow: return COLOR_BTNSHADOW; 1043 case CSSValueButtontext: return COLOR_BTNTEXT; 1044 case CSSValueCaptiontext: return COLOR_CAPTIONTEXT; 1045 case CSSValueGraytext: return COLOR_GRAYTEXT; 1046 case CSSValueHighlight: return COLOR_HIGHLIGHT; 1047 case CSSValueHighlighttext: return COLOR_HIGHLIGHTTEXT; 1048 case CSSValueInactiveborder: return COLOR_INACTIVEBORDER; 1049 case CSSValueInactivecaption: return COLOR_INACTIVECAPTION; 1050 case CSSValueInactivecaptiontext: return COLOR_INACTIVECAPTIONTEXT; 1051 case CSSValueInfobackground: return COLOR_INFOBK; 1052 case CSSValueInfotext: return COLOR_INFOTEXT; 1053 case CSSValueMenu: return COLOR_MENU; 1054 case CSSValueMenutext: return COLOR_MENUTEXT; 1055 case CSSValueScrollbar: return COLOR_SCROLLBAR; 1056 case CSSValueThreeddarkshadow: return COLOR_3DDKSHADOW; 1057 case CSSValueThreedface: return COLOR_3DFACE; 1058 case CSSValueThreedhighlight: return COLOR_3DHIGHLIGHT; 1059 case CSSValueThreedlightshadow: return COLOR_3DLIGHT; 1060 case CSSValueThreedshadow: return COLOR_3DSHADOW; 1061 case CSSValueWindow: return COLOR_WINDOW; 1062 case CSSValueWindowframe: return COLOR_WINDOWFRAME; 1063 case CSSValueWindowtext: return COLOR_WINDOWTEXT; 1064 default: return -1; // Unsupported CSSValue 1065 } 1066} 1067 1068Color RenderThemeWin::systemColor(CSSValueID cssValueId) const 1069{ 1070 int sysColorIndex = cssValueIdToSysColorIndex(cssValueId); 1071 if (sysColorIndex == -1) 1072 return RenderTheme::systemColor(cssValueId); 1073 1074 COLORREF color = GetSysColor(sysColorIndex); 1075 return Color(GetRValue(color), GetGValue(color), GetBValue(color)); 1076} 1077 1078#if ENABLE(VIDEO) 1079static const size_t maximumReasonableBufferSize = 32768; 1080 1081static void fillBufferWithContentsOfFile(PlatformFileHandle file, long long filesize, Vector<char>& buffer) 1082{ 1083 // Load the file content into buffer 1084 buffer.resize(filesize + 1); 1085 1086 int bufferPosition = 0; 1087 int bufferReadSize = 4096; 1088 int bytesRead = 0; 1089 while (filesize > bufferPosition) { 1090 if (filesize - bufferPosition < bufferReadSize) 1091 bufferReadSize = filesize - bufferPosition; 1092 1093 bytesRead = readFromFile(file, buffer.data() + bufferPosition, bufferReadSize); 1094 if (bytesRead != bufferReadSize) { 1095 buffer.clear(); 1096 return; 1097 } 1098 1099 bufferPosition += bufferReadSize; 1100 } 1101 1102 buffer[filesize] = 0; 1103} 1104 1105String RenderThemeWin::stringWithContentsOfFile(CFStringRef name, CFStringRef type) 1106{ 1107 RetainPtr<CFURLRef> requestedURLRef = adoptCF(CFBundleCopyResourceURL(webKitBundle(), name, type, 0)); 1108 if (!requestedURLRef) 1109 return String(); 1110 1111 UInt8 requestedFilePath[MAX_PATH]; 1112 if (!CFURLGetFileSystemRepresentation(requestedURLRef.get(), false, requestedFilePath, MAX_PATH)) 1113 return String(); 1114 1115 PlatformFileHandle requestedFileHandle = openFile(requestedFilePath, OpenForRead); 1116 if (!isHandleValid(requestedFileHandle)) 1117 return String(); 1118 1119 long long filesize = -1; 1120 if (!getFileSize(requestedFilePath, filesize)) { 1121 closeFile(requestedFileHandle); 1122 return String(); 1123 } 1124 1125 Vector<char> fileContents; 1126 fillBufferWithContentsOfFile(requestedFileHandle, filesize, fileContents); 1127 closeFile(requestedFileHandle); 1128 1129 return String(fileContents.data(), static_cast<size_t>(filesize)); 1130} 1131 1132String RenderThemeWin::mediaControlsStyleSheet() 1133{ 1134#if ENABLE(MEDIA_CONTROLS_SCRIPT) 1135 if (m_mediaControlsStyleSheet.isEmpty()) 1136 m_mediaControlsStyleSheet = stringWithContentsOfFile(CFSTR("mediaControlsApple"), CFSTR("css")); 1137 return m_mediaControlsStyleSheet; 1138#else 1139 return emptyString(); 1140#endif 1141} 1142 1143String RenderThemeWin::mediaControlsScript() 1144{ 1145#if ENABLE(MEDIA_CONTROLS_SCRIPT) 1146 if (m_mediaControlsScript.isEmpty()) { 1147 StringBuilder scriptBuilder; 1148 scriptBuilder.append(stringWithContentsOfFile(CFSTR("mediaControlsLocalizedStrings"), CFSTR("js"))); 1149 scriptBuilder.append(stringWithContentsOfFile(CFSTR("mediaControlsApple"), CFSTR("js"))); 1150 m_mediaControlsScript = scriptBuilder.toString(); 1151 } 1152 return m_mediaControlsScript; 1153#else 1154 return emptyString(); 1155#endif 1156} 1157#endif 1158 1159#if ENABLE(METER_ELEMENT) 1160void RenderThemeWin::adjustMeterStyle(StyleResolver&, RenderStyle& style, Element&) const 1161{ 1162 style.setBoxShadow(nullptr); 1163} 1164 1165bool RenderThemeWin::supportsMeter(ControlPart part) const 1166{ 1167 switch (part) { 1168 case MeterPart: 1169 return true; 1170 default: 1171 return false; 1172 } 1173} 1174 1175IntSize RenderThemeWin::meterSizeForBounds(const RenderMeter&, const IntRect& bounds) const 1176{ 1177 return bounds.size(); 1178} 1179 1180bool RenderThemeWin::paintMeter(const RenderObject& renderObject, const PaintInfo& paintInfo, const IntRect& rect) 1181{ 1182 if (!renderObject.isMeter()) 1183 return true; 1184 1185 HTMLMeterElement* element = toRenderMeter(renderObject).meterElement(); 1186 1187 ThemeData theme = getThemeData(renderObject); 1188 1189 int remaining = static_cast<int>((1.0 - element->valueRatio()) * static_cast<double>(rect.size().width())); 1190 1191 // Draw the background 1192 drawControl(paintInfo.context, renderObject, progressBarTheme(), theme, rect); 1193 1194 // Draw the progress portion 1195 IntRect completedRect(rect); 1196 completedRect.contract(remaining, 0); 1197 1198 theme.m_part = PP_FILL; 1199 drawControl(paintInfo.context, renderObject, progressBarTheme(), theme, completedRect); 1200 1201 return true; 1202} 1203 1204#endif 1205 1206 1207} 1208