/* * Copyright (C) 2007 Apple Inc. * Copyright (C) 2007 Alp Toker * Copyright (C) 2008 Collabora Ltd. * Copyright (C) 2008, 2009 Google Inc. * Copyright (C) 2009 Kenneth Rohde Christiansen * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * */ #include "core/layout/LayoutThemeDefault.h" #include "core/CSSValueKeywords.h" #include "core/layout/LayoutObject.h" #include "core/layout/LayoutProgress.h" #include "core/layout/LayoutThemeFontProvider.h" #include "core/paint/MediaControlsPainter.h" #include "platform/LayoutTestSupport.h" #include "platform/PlatformResourceLoader.h" #include "platform/graphics/Color.h" #include "platform/scroll/ScrollbarTheme.h" #include "public/platform/Platform.h" #include "public/platform/WebThemeEngine.h" namespace blink { enum PaddingType { TopPadding, RightPadding, BottomPadding, LeftPadding }; static const int styledMenuListInternalPadding[4] = { 1, 4, 1, 4 }; // These values all match Safari/Win. static const float defaultControlFontPixelSize = 13; static const float defaultCancelButtonSize = 9; static const float minCancelButtonSize = 5; static const float maxCancelButtonSize = 21; static const float defaultSearchFieldResultsDecorationSize = 13; static const float minSearchFieldResultsDecorationSize = 9; static const float maxSearchFieldResultsDecorationSize = 30; static const int menuListArrowPaddingSize = 14; static bool useMockTheme() { return LayoutTestSupport::isMockThemeEnabledForTest(); } unsigned LayoutThemeDefault::m_activeSelectionBackgroundColor = 0xff1e90ff; unsigned LayoutThemeDefault::m_activeSelectionForegroundColor = Color::black; unsigned LayoutThemeDefault::m_inactiveSelectionBackgroundColor = 0xffc8c8c8; unsigned LayoutThemeDefault::m_inactiveSelectionForegroundColor = 0xff323232; double LayoutThemeDefault::m_caretBlinkInterval; LayoutThemeDefault::LayoutThemeDefault() : LayoutTheme(nullptr) { m_caretBlinkInterval = LayoutTheme::caretBlinkInterval(); } LayoutThemeDefault::~LayoutThemeDefault() { } bool LayoutThemeDefault::themeDrawsFocusRing(const ComputedStyle& style) const { if (useMockTheme()) { // Don't use focus rings for buttons when mocking controls. return style.appearance() == ButtonPart || style.appearance() == PushButtonPart || style.appearance() == SquareButtonPart; } // This causes Blink to draw the focus rings for us. return false; } Color LayoutThemeDefault::systemColor(CSSValueID cssValueId) const { static const Color defaultButtonGrayColor(0xffdddddd); static const Color defaultMenuColor(0xfff7f7f7); if (cssValueId == CSSValueButtonface) { if (useMockTheme()) return Color(0xc0, 0xc0, 0xc0); return defaultButtonGrayColor; } if (cssValueId == CSSValueMenu) return defaultMenuColor; return LayoutTheme::systemColor(cssValueId); } // Use the Windows style sheets to match their metrics. String LayoutThemeDefault::extraDefaultStyleSheet() { return LayoutTheme::extraDefaultStyleSheet() #if ENABLE(INPUT_MULTIPLE_FIELDS_UI) + loadResourceAsASCIIString("themeInputMultipleFields.css") #endif + loadResourceAsASCIIString("themeWin.css"); } String LayoutThemeDefault::extraQuirksStyleSheet() { return loadResourceAsASCIIString("themeWinQuirks.css"); } Color LayoutThemeDefault::activeListBoxSelectionBackgroundColor() const { return Color(0x28, 0x28, 0x28); } Color LayoutThemeDefault::activeListBoxSelectionForegroundColor() const { return Color::black; } Color LayoutThemeDefault::inactiveListBoxSelectionBackgroundColor() const { return Color(0xc8, 0xc8, 0xc8); } Color LayoutThemeDefault::inactiveListBoxSelectionForegroundColor() const { return Color(0x32, 0x32, 0x32); } Color LayoutThemeDefault::platformActiveSelectionBackgroundColor() const { if (useMockTheme()) return Color(0x00, 0x00, 0xff); // Royal blue. return m_activeSelectionBackgroundColor; } Color LayoutThemeDefault::platformInactiveSelectionBackgroundColor() const { if (useMockTheme()) return Color(0x99, 0x99, 0x99); // Medium gray. return m_inactiveSelectionBackgroundColor; } Color LayoutThemeDefault::platformActiveSelectionForegroundColor() const { if (useMockTheme()) return Color(0xff, 0xff, 0xcc); // Pale yellow. return m_activeSelectionForegroundColor; } Color LayoutThemeDefault::platformInactiveSelectionForegroundColor() const { if (useMockTheme()) return Color::white; return m_inactiveSelectionForegroundColor; } IntSize LayoutThemeDefault::sliderTickSize() const { if (useMockTheme()) return IntSize(1, 3); return IntSize(1, 6); } int LayoutThemeDefault::sliderTickOffsetFromTrackCenter() const { if (useMockTheme()) return 11; return -16; } void LayoutThemeDefault::adjustSliderThumbSize(ComputedStyle& style) const { IntSize size = Platform::current()->themeEngine()->getSize(WebThemeEngine::PartSliderThumb); // FIXME: Mock theme doesn't handle zoomed sliders. float zoomLevel = useMockTheme() ? 1 : style.effectiveZoom(); if (style.appearance() == SliderThumbHorizontalPart) { style.setWidth(Length(size.width() * zoomLevel, Fixed)); style.setHeight(Length(size.height() * zoomLevel, Fixed)); } else if (style.appearance() == SliderThumbVerticalPart) { style.setWidth(Length(size.height() * zoomLevel, Fixed)); style.setHeight(Length(size.width() * zoomLevel, Fixed)); } else { MediaControlsPainter::adjustMediaSliderThumbSize(style); } } void LayoutThemeDefault::setCaretBlinkInterval(double interval) { m_caretBlinkInterval = interval; } void LayoutThemeDefault::setSelectionColors( unsigned activeBackgroundColor, unsigned activeForegroundColor, unsigned inactiveBackgroundColor, unsigned inactiveForegroundColor) { m_activeSelectionBackgroundColor = activeBackgroundColor; m_activeSelectionForegroundColor = activeForegroundColor; m_inactiveSelectionBackgroundColor = inactiveBackgroundColor; m_inactiveSelectionForegroundColor = inactiveForegroundColor; } void LayoutThemeDefault::setCheckboxSize(ComputedStyle& style) const { // If the width and height are both specified, then we have nothing to do. if (!style.width().isIntrinsicOrAuto() && !style.height().isAuto()) return; IntSize size = Platform::current()->themeEngine()->getSize(WebThemeEngine::PartCheckbox); float zoomLevel = style.effectiveZoom(); size.setWidth(size.width() * zoomLevel); size.setHeight(size.height() * zoomLevel); setSizeIfAuto(style, size); } void LayoutThemeDefault::setRadioSize(ComputedStyle& style) const { // If the width and height are both specified, then we have nothing to do. if (!style.width().isIntrinsicOrAuto() && !style.height().isAuto()) return; IntSize size = Platform::current()->themeEngine()->getSize(WebThemeEngine::PartRadio); float zoomLevel = style.effectiveZoom(); size.setWidth(size.width() * zoomLevel); size.setHeight(size.height() * zoomLevel); setSizeIfAuto(style, size); } void LayoutThemeDefault::adjustInnerSpinButtonStyle(ComputedStyle& style) const { IntSize size = Platform::current()->themeEngine()->getSize(WebThemeEngine::PartInnerSpinButton); style.setWidth(Length(size.width(), Fixed)); style.setMinWidth(Length(size.width(), Fixed)); } bool LayoutThemeDefault::shouldOpenPickerWithF4Key() const { return true; } bool LayoutThemeDefault::shouldUseFallbackTheme(const ComputedStyle& style) const { if (useMockTheme()) { // The mock theme can't handle zoomed controls, so we fall back to the "fallback" theme. ControlPart part = style.appearance(); if (part == CheckboxPart || part == RadioPart) return style.effectiveZoom() != 1; } return LayoutTheme::shouldUseFallbackTheme(style); } bool LayoutThemeDefault::supportsHover(const ComputedStyle& style) const { return true; } Color LayoutThemeDefault::platformFocusRingColor() const { static Color focusRingColor(229, 151, 0, 255); return focusRingColor; } double LayoutThemeDefault::caretBlinkInterval() const { // Disable the blinking caret in layout test mode, as it introduces // a race condition for the pixel tests. http://b/1198440 if (LayoutTestSupport::isRunningLayoutTest()) return 0; return m_caretBlinkInterval; } void LayoutThemeDefault::systemFont(CSSValueID systemFontID, FontStyle& fontStyle, FontWeight& fontWeight, float& fontSize, AtomicString& fontFamily) const { LayoutThemeFontProvider::systemFont(systemFontID, fontStyle, fontWeight, fontSize, fontFamily); } int LayoutThemeDefault::minimumMenuListSize(const ComputedStyle& style) const { return 0; } // Return a rectangle that has the same center point as |original|, but with a // size capped at |width| by |height|. IntRect center(const IntRect& original, int width, int height) { width = std::min(original.width(), width); height = std::min(original.height(), height); int x = original.x() + (original.width() - width) / 2; int y = original.y() + (original.height() - height) / 2; return IntRect(x, y, width, height); } void LayoutThemeDefault::adjustButtonStyle(ComputedStyle& style) const { if (style.appearance() == PushButtonPart) { // Ignore line-height. style.setLineHeight(ComputedStyle::initialLineHeight()); } } void LayoutThemeDefault::adjustSearchFieldStyle(ComputedStyle& style) const { // Ignore line-height. style.setLineHeight(ComputedStyle::initialLineHeight()); } void LayoutThemeDefault::adjustSearchFieldCancelButtonStyle(ComputedStyle& style) const { // Scale the button size based on the font size float fontScale = style.fontSize() / defaultControlFontPixelSize; int cancelButtonSize = lroundf(std::min(std::max(minCancelButtonSize, defaultCancelButtonSize * fontScale), maxCancelButtonSize)); style.setWidth(Length(cancelButtonSize, Fixed)); style.setHeight(Length(cancelButtonSize, Fixed)); } void LayoutThemeDefault::adjustSearchFieldDecorationStyle(ComputedStyle& style) const { IntSize emptySize(1, 11); style.setWidth(Length(emptySize.width(), Fixed)); style.setHeight(Length(emptySize.height(), Fixed)); } void LayoutThemeDefault::adjustSearchFieldResultsDecorationStyle(ComputedStyle& style) const { // Scale the decoration size based on the font size float fontScale = style.fontSize() / defaultControlFontPixelSize; int magnifierSize = lroundf(std::min(std::max(minSearchFieldResultsDecorationSize, defaultSearchFieldResultsDecorationSize * fontScale), maxSearchFieldResultsDecorationSize)); style.setWidth(Length(magnifierSize, Fixed)); style.setHeight(Length(magnifierSize, Fixed)); } void LayoutThemeDefault::adjustMenuListStyle(ComputedStyle& style, Element*) const { // Height is locked to auto on all browsers. style.setLineHeight(ComputedStyle::initialLineHeight()); } void LayoutThemeDefault::adjustMenuListButtonStyle(ComputedStyle& style, Element* e) const { adjustMenuListStyle(style, e); } int LayoutThemeDefault::popupInternalPaddingLeft(const ComputedStyle& style) const { return menuListInternalPadding(style, LeftPadding); } int LayoutThemeDefault::popupInternalPaddingRight(const ComputedStyle& style) const { return menuListInternalPadding(style, RightPadding); } int LayoutThemeDefault::popupInternalPaddingTop(const ComputedStyle& style) const { return menuListInternalPadding(style, TopPadding); } int LayoutThemeDefault::popupInternalPaddingBottom(const ComputedStyle& style) const { return menuListInternalPadding(style, BottomPadding); } // static void LayoutThemeDefault::setDefaultFontSize(int fontSize) { LayoutThemeFontProvider::setDefaultFontSize(fontSize); } int LayoutThemeDefault::menuListInternalPadding(const ComputedStyle& style, int paddingType) const { if (style.appearance() == NoControlPart) return 0; // This internal padding is in addition to the user-supplied padding. // Matches the FF behavior. int padding = styledMenuListInternalPadding[paddingType]; // Reserve the space for right arrow here. The rest of the padding is // set by adjustMenuListStyle, since PopMenuWin.cpp uses the padding from // LayoutMenuList to lay out the individual items in the popup. const int barType = style.direction() == LTR ? RightPadding : LeftPadding; if (paddingType == barType) padding += menuListArrowPaddingSize; return padding * style.effectiveZoom(); } // // Following values are come from default of GTK+ // static const int progressAnimationFrames = 10; static const double progressAnimationInterval = 0.125; double LayoutThemeDefault::animationRepeatIntervalForProgressBar() const { return progressAnimationInterval; } double LayoutThemeDefault::animationDurationForProgressBar() const { return progressAnimationInterval * progressAnimationFrames * 2; // "2" for back and forth } } // namespace blink