| /* |
| * Copyright (C) 2007 Apple Inc. |
| * Copyright (C) 2007 Alp Toker <alp@atoker.com> |
| * 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/LayoutThemeFontProvider.h" |
| #include "core/paint/MediaControlsPainter.h" |
| #include "core/style/ComputedStyle.h" |
| #include "platform/DataResourceHelper.h" |
| #include "platform/LayoutTestSupport.h" |
| #include "platform/PlatformChromeClient.h" |
| #include "platform/graphics/Color.h" |
| #include "platform/wtf/text/StringBuilder.h" |
| #include "public/platform/Platform.h" |
| #include "public/platform/WebThemeEngine.h" |
| |
| namespace blink { |
| |
| // These values all match Safari/Win. |
| static const float kDefaultControlFontPixelSize = 13; |
| static const float kDefaultCancelButtonSize = 9; |
| static const float kMinCancelButtonSize = 5; |
| static const float kMaxCancelButtonSize = 21; |
| |
| static bool UseMockTheme() { |
| return LayoutTestSupport::IsMockThemeEnabledForTest(); |
| } |
| |
| unsigned LayoutThemeDefault::active_selection_background_color_ = 0xff1e90ff; |
| unsigned LayoutThemeDefault::active_selection_foreground_color_ = Color::kBlack; |
| unsigned LayoutThemeDefault::inactive_selection_background_color_ = 0xffc8c8c8; |
| unsigned LayoutThemeDefault::inactive_selection_foreground_color_ = 0xff323232; |
| |
| double LayoutThemeDefault::caret_blink_interval_; |
| |
| LayoutThemeDefault::LayoutThemeDefault() |
| : LayoutTheme(nullptr), painter_(*this) { |
| caret_blink_interval_ = 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() == kButtonPart || |
| style.Appearance() == kPushButtonPart || |
| style.Appearance() == kSquareButtonPart; |
| } |
| |
| // This causes Blink to draw the focus rings for us. |
| return false; |
| } |
| |
| Color LayoutThemeDefault::SystemColor(CSSValueID css_value_id) const { |
| static const Color kDefaultButtonGrayColor(0xffdddddd); |
| static const Color kDefaultMenuColor(0xfff7f7f7); |
| |
| if (css_value_id == CSSValueButtonface) { |
| if (UseMockTheme()) |
| return Color(0xc0, 0xc0, 0xc0); |
| return kDefaultButtonGrayColor; |
| } |
| if (css_value_id == CSSValueMenu) |
| return kDefaultMenuColor; |
| return LayoutTheme::SystemColor(css_value_id); |
| } |
| |
| // Use the Windows style sheets to match their metrics. |
| String LayoutThemeDefault::ExtraDefaultStyleSheet() { |
| String extra_style_sheet = LayoutTheme::ExtraDefaultStyleSheet(); |
| String multiple_fields_style_sheet = |
| RuntimeEnabledFeatures::inputMultipleFieldsUIEnabled() |
| ? GetDataResourceAsASCIIString("themeInputMultipleFields.css") |
| : String(); |
| String windows_style_sheet = GetDataResourceAsASCIIString("themeWin.css"); |
| StringBuilder builder; |
| builder.ReserveCapacity(extra_style_sheet.length() + |
| multiple_fields_style_sheet.length() + |
| windows_style_sheet.length()); |
| builder.Append(extra_style_sheet); |
| builder.Append(multiple_fields_style_sheet); |
| builder.Append(windows_style_sheet); |
| return builder.ToString(); |
| } |
| |
| String LayoutThemeDefault::ExtraQuirksStyleSheet() { |
| return GetDataResourceAsASCIIString("themeWinQuirks.css"); |
| } |
| |
| Color LayoutThemeDefault::ActiveListBoxSelectionBackgroundColor() const { |
| return Color(0x28, 0x28, 0x28); |
| } |
| |
| Color LayoutThemeDefault::ActiveListBoxSelectionForegroundColor() const { |
| return Color::kBlack; |
| } |
| |
| 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 active_selection_background_color_; |
| } |
| |
| Color LayoutThemeDefault::PlatformInactiveSelectionBackgroundColor() const { |
| if (UseMockTheme()) |
| return Color(0x99, 0x99, 0x99); // Medium gray. |
| return inactive_selection_background_color_; |
| } |
| |
| Color LayoutThemeDefault::PlatformActiveSelectionForegroundColor() const { |
| if (UseMockTheme()) |
| return Color(0xff, 0xff, 0xcc); // Pale yellow. |
| return active_selection_foreground_color_; |
| } |
| |
| Color LayoutThemeDefault::PlatformInactiveSelectionForegroundColor() const { |
| if (UseMockTheme()) |
| return Color::kWhite; |
| return inactive_selection_foreground_color_; |
| } |
| |
| 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::kPartSliderThumb); |
| |
| // FIXME: Mock theme doesn't handle zoomed sliders. |
| float zoom_level = UseMockTheme() ? 1 : style.EffectiveZoom(); |
| if (style.Appearance() == kSliderThumbHorizontalPart) { |
| style.SetWidth(Length(size.Width() * zoom_level, kFixed)); |
| style.SetHeight(Length(size.Height() * zoom_level, kFixed)); |
| } else if (style.Appearance() == kSliderThumbVerticalPart) { |
| style.SetWidth(Length(size.Height() * zoom_level, kFixed)); |
| style.SetHeight(Length(size.Width() * zoom_level, kFixed)); |
| } else { |
| MediaControlsPainter::AdjustMediaSliderThumbSize(style); |
| } |
| } |
| |
| void LayoutThemeDefault::SetSelectionColors( |
| unsigned active_background_color, |
| unsigned active_foreground_color, |
| unsigned inactive_background_color, |
| unsigned inactive_foreground_color) { |
| active_selection_background_color_ = active_background_color; |
| active_selection_foreground_color_ = active_foreground_color; |
| inactive_selection_background_color_ = inactive_background_color; |
| inactive_selection_foreground_color_ = inactive_foreground_color; |
| } |
| |
| 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::kPartCheckbox); |
| float zoom_level = style.EffectiveZoom(); |
| size.SetWidth(size.Width() * zoom_level); |
| size.SetHeight(size.Height() * zoom_level); |
| 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::kPartRadio); |
| float zoom_level = style.EffectiveZoom(); |
| size.SetWidth(size.Width() * zoom_level); |
| size.SetHeight(size.Height() * zoom_level); |
| SetSizeIfAuto(style, size); |
| } |
| |
| void LayoutThemeDefault::AdjustInnerSpinButtonStyle( |
| ComputedStyle& style) const { |
| IntSize size = Platform::Current()->ThemeEngine()->GetSize( |
| WebThemeEngine::kPartInnerSpinButton); |
| |
| float zoom_level = style.EffectiveZoom(); |
| style.SetWidth(Length(size.Width() * zoom_level, kFixed)); |
| style.SetMinWidth(Length(size.Width() * zoom_level, kFixed)); |
| } |
| |
| 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 == kCheckboxPart || part == kRadioPart) |
| return style.EffectiveZoom() != 1; |
| } |
| return LayoutTheme::ShouldUseFallbackTheme(style); |
| } |
| |
| bool LayoutThemeDefault::SupportsHover(const ComputedStyle& style) const { |
| return true; |
| } |
| |
| Color LayoutThemeDefault::PlatformFocusRingColor() const { |
| static Color focus_ring_color(229, 151, 0, 255); |
| return focus_ring_color; |
| } |
| |
| void LayoutThemeDefault::SystemFont(CSSValueID system_font_id, |
| FontStyle& font_style, |
| FontWeight& font_weight, |
| float& font_size, |
| AtomicString& font_family) const { |
| LayoutThemeFontProvider::SystemFont(system_font_id, font_style, font_weight, |
| font_size, font_family); |
| } |
| |
| 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() == kPushButtonPart) { |
| // 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 font_scale = style.FontSize() / kDefaultControlFontPixelSize; |
| int cancel_button_size = lroundf(std::min( |
| std::max(kMinCancelButtonSize, kDefaultCancelButtonSize * font_scale), |
| kMaxCancelButtonSize)); |
| style.SetWidth(Length(cancel_button_size, kFixed)); |
| style.SetHeight(Length(cancel_button_size, kFixed)); |
| } |
| |
| 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); |
| } |
| |
| // The following internal paddings are in addition to the user-supplied padding. |
| // Matches the Firefox behavior. |
| |
| int LayoutThemeDefault::PopupInternalPaddingStart( |
| const ComputedStyle& style) const { |
| return MenuListInternalPadding(style, 4); |
| } |
| |
| int LayoutThemeDefault::PopupInternalPaddingEnd( |
| const PlatformChromeClient* client, |
| const ComputedStyle& style) const { |
| if (style.Appearance() == kNoControlPart) |
| return 0; |
| return 1 * style.EffectiveZoom() + |
| ClampedMenuListArrowPaddingSize(client, style); |
| } |
| |
| int LayoutThemeDefault::PopupInternalPaddingTop( |
| const ComputedStyle& style) const { |
| return MenuListInternalPadding(style, 1); |
| } |
| |
| int LayoutThemeDefault::PopupInternalPaddingBottom( |
| const ComputedStyle& style) const { |
| return MenuListInternalPadding(style, 1); |
| } |
| |
| int LayoutThemeDefault::MenuListArrowWidthInDIP() const { |
| int width = Platform::Current() |
| ->ThemeEngine() |
| ->GetSize(WebThemeEngine::kPartScrollbarUpArrow) |
| .width; |
| return width > 0 ? width : 15; |
| } |
| |
| float LayoutThemeDefault::ClampedMenuListArrowPaddingSize( |
| const PlatformChromeClient* client, |
| const ComputedStyle& style) const { |
| if (cached_menu_list_arrow_padding_size_ > 0 && |
| style.EffectiveZoom() == cached_menu_list_arrow_zoom_level_) |
| return cached_menu_list_arrow_padding_size_; |
| cached_menu_list_arrow_zoom_level_ = style.EffectiveZoom(); |
| int original_size = MenuListArrowWidthInDIP(); |
| int scaled_size = |
| client ? client->WindowToViewportScalar(original_size) : original_size; |
| // The result should not be samller than the scrollbar thickness in order to |
| // secure space for scrollbar in popup. |
| float device_scale = 1.0f * scaled_size / original_size; |
| float size; |
| if (cached_menu_list_arrow_zoom_level_ < device_scale) { |
| size = scaled_size; |
| } else { |
| // The value should be zoomed though scrollbars aren't scaled by zoom. |
| // crbug.com/432795. |
| size = original_size * cached_menu_list_arrow_zoom_level_; |
| } |
| cached_menu_list_arrow_padding_size_ = size; |
| return size; |
| } |
| |
| void LayoutThemeDefault::DidChangeThemeEngine() { |
| cached_menu_list_arrow_zoom_level_ = 0; |
| cached_menu_list_arrow_padding_size_ = 0; |
| } |
| |
| // static |
| void LayoutThemeDefault::SetDefaultFontSize(int font_size) { |
| LayoutThemeFontProvider::SetDefaultFontSize(font_size); |
| } |
| |
| int LayoutThemeDefault::MenuListInternalPadding(const ComputedStyle& style, |
| int padding) const { |
| if (style.Appearance() == kNoControlPart) |
| return 0; |
| return padding * style.EffectiveZoom(); |
| } |
| |
| // |
| // Following values are come from default of GTK+ |
| // |
| static const int kProgressAnimationFrames = 10; |
| static const double kProgressAnimationInterval = 0.125; |
| |
| double LayoutThemeDefault::AnimationRepeatIntervalForProgressBar() const { |
| return kProgressAnimationInterval; |
| } |
| |
| double LayoutThemeDefault::AnimationDurationForProgressBar() const { |
| return kProgressAnimationInterval * kProgressAnimationFrames * |
| 2; // "2" for back and forth |
| } |
| |
| } // namespace blink |