/*
 * Copyright (C) 2007 Apple Inc.
 * Copyright (C) 2007 Alp Toker <alp@atoker.com>
 * Copyright (C) 2008 Collabora Ltd.
 * Copyright (C) 2009 Kenneth Rohde Christiansen
 * Copyright (C) 2010 Igalia S.L.
 *
 * 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 "config.h"
#include "RenderThemeGtk.h"

#include "CSSValueKeywords.h"
#include "FileList.h"
#include "FloatRoundedRect.h"
#include "FontDescription.h"
#include "GRefPtrGtk.h"
#include "GUniquePtrGtk.h"
#include "Gradient.h"
#include "GraphicsContext.h"
#include "HTMLInputElement.h"
#include "HTMLMediaElement.h"
#include "LocalizedStrings.h"
#include "MediaControlElements.h"
#include "Page.h"
#include "PaintInfo.h"
#include "PlatformContextCairo.h"
#include "RenderBox.h"
#include "RenderObject.h"
#include "RenderProgress.h"
#include "RenderThemeWidget.h"
#include "ScrollbarThemeGtk.h"
#include "StringTruncator.h"
#include "TimeRanges.h"
#include "UserAgentScripts.h"
#include "UserAgentStyleSheets.h"
#include <cmath>
#include <gdk/gdk.h>
#include <glib.h>
#include <gtk/gtk.h>
#include <wtf/FileSystem.h>
#include <wtf/glib/GRefPtr.h>
#include <wtf/glib/GUniquePtr.h>
#include <wtf/text/CString.h>
#include <wtf/text/StringBuilder.h>

namespace WebCore {

RenderTheme& RenderTheme::singleton()
{
    static NeverDestroyed<RenderThemeGtk> theme;
    return theme;
}

static double getScreenDPI()
{
    // FIXME: Really this should be the widget's screen.
    GdkScreen* screen = gdk_screen_get_default();
    if (!screen)
        return 96; // Default to 96 DPI.

    float dpi = gdk_screen_get_resolution(screen);
    if (dpi <= 0)
        return 96;
    return dpi;
}

void RenderThemeGtk::updateCachedSystemFontDescription(CSSValueID, FontCascadeDescription& fontDescription) const
{
    GtkSettings* settings = gtk_settings_get_default();
    if (!settings)
        return;

    // This will be a font selection string like "Sans 10" so we cannot use it as the family name.
    GUniqueOutPtr<gchar> fontName;
    g_object_get(settings, "gtk-font-name", &fontName.outPtr(), nullptr);
    if (!fontName || !fontName.get()[0])
        return;

    PangoFontDescription* pangoDescription = pango_font_description_from_string(fontName.get());
    if (!pangoDescription)
        return;

    fontDescription.setOneFamily(pango_font_description_get_family(pangoDescription));

    int size = pango_font_description_get_size(pangoDescription) / PANGO_SCALE;
    // If the size of the font is in points, we need to convert it to pixels.
    if (!pango_font_description_get_size_is_absolute(pangoDescription))
        size = size * (getScreenDPI() / 72.0);

    fontDescription.setSpecifiedSize(size);
    fontDescription.setIsAbsoluteSize(true);
    fontDescription.setWeight(normalWeightValue());
    fontDescription.setItalic(FontSelectionValue());
    pango_font_description_free(pangoDescription);
}

#if ENABLE(DATALIST_ELEMENT)
IntSize RenderThemeGtk::sliderTickSize() const
{
    // FIXME: We need to set this to the size of one tick mark.
    return IntSize(0, 0);
}

int RenderThemeGtk::sliderTickOffsetFromTrackCenter() const
{
    // FIXME: We need to set this to the position of the tick marks.
    return 0;
}
#endif

static void themeChangedCallback()
{
    Page::updateStyleForAllPagesAfterGlobalChangeInEnvironment();
}

RenderThemeGtk::RenderThemeGtk()
{
    static bool themeMonitorInitialized = false;
    if (!themeMonitorInitialized) {
        GtkSettings* settings = gtk_settings_get_default();
        g_signal_connect(settings, "notify::gtk-theme-name", G_CALLBACK(themeChangedCallback), nullptr);
        g_signal_connect(settings, "notify::gtk-color-scheme", G_CALLBACK(themeChangedCallback), nullptr);
        themeMonitorInitialized = true;
    }
}

enum RenderThemePart {
    Entry,
    EntrySelection,
    EntryIconLeft,
    EntryIconRight,
    Button,
    CheckButton,
    RadioButton,
    ComboBox,
    ComboBoxButton,
    ComboBoxArrow,
    Scale,
    ScaleTrough,
    ScaleSlider,
    ProgressBar,
    ProgressBarTrough,
    ProgressBarProgress,
    ListBox,
    SpinButton,
    SpinButtonUpButton,
    SpinButtonDownButton,
#if ENABLE(VIDEO)
    MediaButton,
#endif
    Window,
};

#if ENABLE(VIDEO)
static bool nodeHasPseudo(Node& node, const char* pseudo)
{
    return is<Element>(node) && downcast<Element>(node).pseudo() == pseudo;
}

static bool nodeHasClass(Node* node, const char* className)
{
    if (!is<Element>(*node))
        return false;

    Element& element = downcast<Element>(*node);

    if (!element.hasClass())
        return false;

    return element.classNames().contains(className);
}
#endif // ENABLE(VIDEO)

RenderThemeGtk::~RenderThemeGtk() = default;

static bool supportsFocus(ControlPart appearance)
{
    switch (appearance) {
    case PushButtonPart:
    case ButtonPart:
    case TextFieldPart:
    case TextAreaPart:
    case SearchFieldPart:
    case MenulistPart:
    case RadioPart:
    case CheckboxPart:
    case SliderHorizontalPart:
    case SliderVerticalPart:
        return true;
    default:
        return false;
    }
}

bool RenderThemeGtk::supportsFocusRing(const RenderStyle& style) const
{
    return supportsFocus(style.appearance());
}

bool RenderThemeGtk::controlSupportsTints(const RenderObject& o) const
{
    return isEnabled(o);
}

int RenderThemeGtk::baselinePosition(const RenderBox& box) const
{
    // FIXME: This strategy is possibly incorrect for the GTK+ port.
    if (box.style().appearance() == CheckboxPart || box.style().appearance() == RadioPart)
        return box.marginTop() + box.height() - 2;
    return RenderTheme::baselinePosition(box);
}

void RenderThemeGtk::adjustRepaintRect(const RenderObject&, FloatRect&)
{
}
static GtkStateFlags themePartStateFlags(const RenderThemeGtk& theme, RenderThemePart themePart, const RenderObject& renderObject)
{
    unsigned stateFlags = 0;
    switch (renderObject.style().direction()) {
    case TextDirection::RTL:
        stateFlags |= GTK_STATE_FLAG_DIR_RTL;
        break;
    case TextDirection::LTR:
        stateFlags |= GTK_STATE_FLAG_DIR_LTR;
        break;
    }

    if (!theme.isEnabled(renderObject) || (themePart == Entry && theme.isReadOnlyControl(renderObject)))
        stateFlags |= GTK_STATE_FLAG_INSENSITIVE;
    else {
        if (theme.isHovered(renderObject))
            stateFlags |= GTK_STATE_FLAG_PRELIGHT;
        if (theme.isFocused(renderObject))
            stateFlags |= GTK_STATE_FLAG_FOCUSED;
    }

    switch (themePart) {
    case CheckButton:
    case RadioButton:
        if (theme.isChecked(renderObject))
            stateFlags |= GTK_STATE_FLAG_CHECKED;
        if (theme.isIndeterminate(renderObject))
            stateFlags |= GTK_STATE_FLAG_INCONSISTENT;
        if (theme.isPressed(renderObject))
            stateFlags |= GTK_STATE_FLAG_SELECTED;
        break;
    case Button:
    case ComboBoxButton:
    case ScaleSlider:
    case EntryIconLeft:
    case EntryIconRight:
#if ENABLE(VIDEO)
    case MediaButton:
#endif
        if (theme.isPressed(renderObject))
            stateFlags |= GTK_STATE_FLAG_ACTIVE;
        break;
    case SpinButtonUpButton:
        if (theme.isPressed(renderObject) && theme.isSpinUpButtonPartPressed(renderObject))
            stateFlags |= GTK_STATE_FLAG_ACTIVE;
        if (theme.isHovered(renderObject) && !theme.isSpinUpButtonPartHovered(renderObject))
            stateFlags &= ~GTK_STATE_FLAG_PRELIGHT;
        break;
    case SpinButtonDownButton:
        if (theme.isPressed(renderObject) && !theme.isSpinUpButtonPartPressed(renderObject))
            stateFlags |= GTK_STATE_FLAG_ACTIVE;
        if (theme.isHovered(renderObject) && theme.isSpinUpButtonPartHovered(renderObject))
            stateFlags &= ~GTK_STATE_FLAG_PRELIGHT;
        break;
    default:
        break;
    }

    return static_cast<GtkStateFlags>(stateFlags);
}

void RenderThemeGtk::adjustButtonStyle(StyleResolver&, RenderStyle& style, const Element*) const
{
    // Some layout tests check explicitly that buttons ignore line-height.
    if (style.appearance() == PushButtonPart)
        style.setLineHeight(RenderStyle::initialLineHeight());
}

static void shrinkToMinimumSizeAndCenterRectangle(FloatRect& rect, const IntSize& minSize)
{
    if (rect.width() > minSize.width()) {
        rect.inflateX(-(rect.width() - minSize.width()) / 2);
        rect.setWidth(minSize.width()); // In case rect.width() was equal to minSize.width() + 1.
    }

    if (rect.height() > minSize.height()) {
        rect.inflateY(-(rect.height() - minSize.height()) / 2);
        rect.setHeight(minSize.height()); // In case rect.height() was equal to minSize.height() + 1.
    }
}

static void setToggleSize(RenderThemePart themePart, RenderStyle& style)
{
    ASSERT(themePart == CheckButton || themePart == RadioButton);

    // The width and height are both specified, so we shouldn't change them.
    if (!style.width().isIntrinsicOrAuto() && !style.height().isAuto())
        return;

    auto& toggleWidget = static_cast<RenderThemeToggleButton&>(RenderThemeWidget::getOrCreate(themePart == CheckButton ? RenderThemeWidget::Type::CheckButton : RenderThemeWidget::Type::RadioButton));
    toggleWidget.button().setState(GTK_STATE_FLAG_NORMAL);
    toggleWidget.toggle().setState(GTK_STATE_FLAG_NORMAL);
    IntSize preferredSize = toggleWidget.button().preferredSize();
    preferredSize = preferredSize.expandedTo(toggleWidget.toggle().preferredSize());

    if (style.width().isIntrinsicOrAuto())
        style.setWidth(Length(preferredSize.width(), Fixed));

    if (style.height().isAuto())
        style.setHeight(Length(preferredSize.height(), Fixed));
}

static void paintToggle(const RenderThemeGtk* theme, RenderThemePart themePart, const RenderObject& renderObject, const PaintInfo& paintInfo, const IntRect& fullRect)
{
    ASSERT(themePart == CheckButton || themePart == RadioButton);

    auto& toggleWidget = static_cast<RenderThemeToggleButton&>(RenderThemeWidget::getOrCreate(themePart == CheckButton ? RenderThemeWidget::Type::CheckButton : RenderThemeWidget::Type::RadioButton));
    auto toggleState = themePartStateFlags(*theme, themePart, renderObject);
    toggleWidget.button().setState(toggleState);
    toggleWidget.toggle().setState(toggleState);

    FloatRect rect = fullRect;
    // Some themes do not render large toggle buttons properly, so we simply
    // shrink the rectangle back down to the default size and then center it
    // in the full toggle button region. The reason for not simply forcing toggle
    // buttons to be a smaller size is that we don't want to break site layouts.
    IntSize preferredSize = toggleWidget.button().preferredSize();
    preferredSize = preferredSize.expandedTo(toggleWidget.toggle().preferredSize());
    shrinkToMinimumSizeAndCenterRectangle(rect, preferredSize);
    toggleWidget.button().render(paintInfo.context().platformContext()->cr(), rect);
    toggleWidget.toggle().render(paintInfo.context().platformContext()->cr(), rect);

    if (theme->isFocused(renderObject))
        toggleWidget.button().renderFocus(paintInfo.context().platformContext()->cr(), rect);
}

void RenderThemeGtk::setCheckboxSize(RenderStyle& style) const
{
    setToggleSize(CheckButton, style);
}

bool RenderThemeGtk::paintCheckbox(const RenderObject& renderObject, const PaintInfo& paintInfo, const IntRect& rect)
{
    paintToggle(this, CheckButton, renderObject, paintInfo, rect);
    return false;
}

void RenderThemeGtk::setRadioSize(RenderStyle& style) const
{
    setToggleSize(RadioButton, style);
}

bool RenderThemeGtk::paintRadio(const RenderObject& renderObject, const PaintInfo& paintInfo, const IntRect& rect)
{
    paintToggle(this, RadioButton, renderObject, paintInfo, rect);
    return false;
}

bool RenderThemeGtk::paintButton(const RenderObject& renderObject, const PaintInfo& paintInfo, const IntRect& rect)
{
    auto& buttonWidget = static_cast<RenderThemeButton&>(RenderThemeWidget::getOrCreate(isDefault(renderObject) ? RenderThemeWidget::Type::ButtonDefault : RenderThemeWidget::Type::Button));
    buttonWidget.button().setState(themePartStateFlags(*this, Button, renderObject));
    buttonWidget.button().render(paintInfo.context().platformContext()->cr(), rect);
    if (isFocused(renderObject))
        buttonWidget.button().renderFocus(paintInfo.context().platformContext()->cr(), rect);
    return false;
}

static Color menuListColor(const Element* element)
{
    auto& comboWidget = static_cast<RenderThemeComboBox&>(RenderThemeWidget::getOrCreate(RenderThemeWidget::Type::ComboBox));
    GtkStateFlags state = element->isDisabledFormControl() ? GTK_STATE_FLAG_INSENSITIVE : GTK_STATE_FLAG_NORMAL;
    comboWidget.comboBox().setState(state);
    comboWidget.button().setState(state);
    return comboWidget.button().color();
}

void RenderThemeGtk::adjustMenuListStyle(StyleResolver&, RenderStyle& style, const Element* element) const
{
    // The tests check explicitly that select menu buttons ignore line height.
    style.setLineHeight(RenderStyle::initialLineHeight());

    // We cannot give a proper rendering when border radius is active, unfortunately.
    style.resetBorderRadius();

    if (element)
        style.setColor(menuListColor(element));
}

void RenderThemeGtk::adjustMenuListButtonStyle(StyleResolver& styleResolver, RenderStyle& style, const Element* e) const
{
    adjustMenuListStyle(styleResolver, style, e);
}

/*
 * GtkComboBox gadgets tree
 *
 * combobox
 * ├── box.linked
 * │   ╰── button.combo
 * │       ╰── box
 * │           ├── cellview
 * │           ╰── arrow
 * ╰── window.popup
 */
LengthBox RenderThemeGtk::popupInternalPaddingBox(const RenderStyle& style) const
{
    if (style.appearance() == NoControlPart)
        return LengthBox(0);

    auto& comboWidget = static_cast<RenderThemeComboBox&>(RenderThemeWidget::getOrCreate(RenderThemeWidget::Type::ComboBox));
    comboWidget.comboBox().setState(GTK_STATE_FLAG_NORMAL);
    comboWidget.button().setState(GTK_STATE_FLAG_NORMAL);
    comboWidget.arrow().setState(GTK_STATE_FLAG_NORMAL);
    GtkBorder comboContentsBox = comboWidget.comboBox().contentsBox();
    GtkBorder boxContentsBox = comboWidget.box().contentsBox();
    GtkBorder buttonContentsBox = comboWidget.button().contentsBox();
    GtkBorder buttonBoxContentsBox = comboWidget.buttonBox().contentsBox();
    GtkBorder padding;
    padding.left = comboContentsBox.left + boxContentsBox.left + buttonContentsBox.left + buttonBoxContentsBox.left;
    padding.right = comboContentsBox.right + boxContentsBox.right + buttonContentsBox.right + buttonBoxContentsBox.right;
    padding.top = comboContentsBox.top + boxContentsBox.top + buttonContentsBox.top + buttonBoxContentsBox.top;
    padding.bottom = comboContentsBox.bottom + boxContentsBox.bottom + buttonContentsBox.bottom + buttonBoxContentsBox.bottom;

    auto arrowSize = comboWidget.arrow().preferredSize();
    return LengthBox(padding.top, padding.right + (style.direction() == TextDirection::LTR ? arrowSize.width() : 0),
        padding.bottom, padding.left + (style.direction() == TextDirection::RTL ? arrowSize.width() : 0));
}

bool RenderThemeGtk::paintMenuList(const RenderObject& renderObject, const PaintInfo& paintInfo, const FloatRect& rect)
{
    auto& comboWidget = static_cast<RenderThemeComboBox&>(RenderThemeWidget::getOrCreate(RenderThemeWidget::Type::ComboBox));
    auto comboState = themePartStateFlags(*this, ComboBoxButton, renderObject);
    comboWidget.comboBox().setState(comboState);
    comboWidget.button().setState(comboState);
    comboWidget.arrow().setState(comboState);

    cairo_t* cr = paintInfo.context().platformContext()->cr();
    comboWidget.comboBox().render(cr, rect);
    comboWidget.box().render(cr, rect);
    FloatRect contentsRect;
    comboWidget.button().render(cr, rect, &contentsRect);
    comboWidget.buttonBox().render(cr, contentsRect);
    comboWidget.arrow().render(cr, contentsRect);
    if (isFocused(renderObject))
        comboWidget.button().renderFocus(cr, rect);

    return false;
}

bool RenderThemeGtk::paintMenuListButtonDecorations(const RenderBox& object, const PaintInfo& info, const FloatRect& rect)
{
    return paintMenuList(object, info, rect);
}

static IntSize spinButtonSize()
{
    auto& spinButtonWidget = static_cast<RenderThemeSpinButton&>(RenderThemeWidget::getOrCreate(RenderThemeWidget::Type::SpinButton));
    spinButtonWidget.spinButton().setState(GTK_STATE_FLAG_NORMAL);
    spinButtonWidget.entry().setState(GTK_STATE_FLAG_NORMAL);
    spinButtonWidget.up().setState(GTK_STATE_FLAG_NORMAL);
    spinButtonWidget.down().setState(GTK_STATE_FLAG_NORMAL);

    IntSize preferredSize = spinButtonWidget.spinButton().preferredSize();
    preferredSize = preferredSize.expandedTo(spinButtonWidget.entry().preferredSize());
    IntSize upPreferredSize = preferredSize.expandedTo(spinButtonWidget.up().preferredSize());
    IntSize downPreferredSize = preferredSize.expandedTo(spinButtonWidget.down().preferredSize());

    return IntSize(upPreferredSize.width() + downPreferredSize.width(), std::max(upPreferredSize.height(), downPreferredSize.height()));
}


void RenderThemeGtk::adjustTextFieldStyle(StyleResolver&, RenderStyle& style, const Element* element) const
{
    if (!is<HTMLInputElement>(element) || !shouldHaveSpinButton(downcast<HTMLInputElement>(*element)))
        return;

    style.setMinHeight(Length(spinButtonSize().height(), Fixed));

    // The default theme for the GTK+ port uses very wide spin buttons (66px) compared to what other
    // browsers use (~13 px). And unfortunately, most of the web developers won't test how their site
    // renders on WebKitGTK. To ensure that spin buttons don't end up covering the values of the input
    // field, we override the width of the input element and always increment it with the width needed
    // for the spinbutton (when drawing the spinbutton).
    int minimumWidth = style.width().intValue() + spinButtonSize().width();
    style.setMinWidth(Length(minimumWidth, Fixed));
}

bool RenderThemeGtk::paintTextField(const RenderObject& renderObject, const PaintInfo& paintInfo, const FloatRect& rect)
{
    if (is<HTMLInputElement>(renderObject.node()) && shouldHaveSpinButton(downcast<HTMLInputElement>(*renderObject.node()))) {
        auto& spinButtonWidget = static_cast<RenderThemeSpinButton&>(RenderThemeWidget::getOrCreate(RenderThemeWidget::Type::SpinButton));
        auto spinButtonState = themePartStateFlags(*this, Entry, renderObject);
        spinButtonWidget.spinButton().setState(spinButtonState);
        spinButtonWidget.entry().setState(spinButtonState);
        spinButtonWidget.spinButton().render(paintInfo.context().platformContext()->cr(), rect);
        spinButtonWidget.entry().render(paintInfo.context().platformContext()->cr(), rect);
    } else {
        auto& entryWidget = static_cast<RenderThemeEntry&>(RenderThemeWidget::getOrCreate(RenderThemeWidget::Type::Entry));
        entryWidget.entry().setState(themePartStateFlags(*this, Entry, renderObject));
        entryWidget.entry().render(paintInfo.context().platformContext()->cr(), rect);

#if ENABLE(DATALIST_ELEMENT)
        if (is<HTMLInputElement>(renderObject.generatingNode())) {
            const auto& input = downcast<HTMLInputElement>(*(renderObject.generatingNode()));
            if (input.list())
                paintListButtonForInput(renderObject, paintInfo, rect);
        }
#endif
    }
    return false;
}

static void adjustSearchFieldIconStyle(RenderThemePart themePart, RenderStyle& style)
{
    ASSERT(themePart == EntryIconLeft || themePart == EntryIconRight);
    auto& searchEntryWidget = static_cast<RenderThemeSearchEntry&>(RenderThemeWidget::getOrCreate(RenderThemeWidget::Type::SearchEntry));
    searchEntryWidget.entry().setState(GTK_STATE_FLAG_NORMAL);
    searchEntryWidget.leftIcon().setState(GTK_STATE_FLAG_NORMAL);
    searchEntryWidget.rightIcon().setState(GTK_STATE_FLAG_NORMAL);

    // Get the icon size based on the font size.
    auto& icon = static_cast<RenderThemeIconGadget&>(themePart == EntryIconLeft ? searchEntryWidget.leftIcon() : searchEntryWidget.rightIcon());
    icon.setIconSize(style.computedFontPixelSize());
    IntSize preferredSize = icon.preferredSize();
    GtkBorder contentsBox = searchEntryWidget.entry().contentsBox();
    if (themePart == EntryIconLeft)
        preferredSize.expand(contentsBox.left, contentsBox.top + contentsBox.bottom);
    else
        preferredSize.expand(contentsBox.right, contentsBox.top + contentsBox.bottom);
    style.setWidth(Length(preferredSize.width(), Fixed));
    style.setHeight(Length(preferredSize.height(), Fixed));
}

bool RenderThemeGtk::paintTextArea(const RenderObject& o, const PaintInfo& i, const FloatRect& r)
{
    return paintTextField(o, i, r);
}

void RenderThemeGtk::adjustSearchFieldResultsButtonStyle(StyleResolver& styleResolver, RenderStyle& style, const Element* e) const
{
    adjustSearchFieldCancelButtonStyle(styleResolver, style, e);
}

bool RenderThemeGtk::paintSearchFieldResultsButton(const RenderBox& o, const PaintInfo& i, const IntRect& rect)
{
    return paintSearchFieldResultsDecorationPart(o, i, rect);
}

void RenderThemeGtk::adjustSearchFieldResultsDecorationPartStyle(StyleResolver&, RenderStyle& style, const Element*) const
{
    adjustSearchFieldIconStyle(EntryIconLeft, style);
}

void RenderThemeGtk::adjustSearchFieldCancelButtonStyle(StyleResolver&, RenderStyle& style, const Element*) const
{
    adjustSearchFieldIconStyle(EntryIconRight, style);
}

static bool paintSearchFieldIcon(RenderThemeGtk* theme, RenderThemePart themePart, const RenderBox& renderObject, const PaintInfo& paintInfo, const IntRect& rect)
{
    ASSERT(themePart == EntryIconLeft || themePart == EntryIconRight);
    auto& searchEntryWidget = static_cast<RenderThemeSearchEntry&>(RenderThemeWidget::getOrCreate(RenderThemeWidget::Type::SearchEntry));
    searchEntryWidget.entry().setState(themePartStateFlags(*theme, Entry, renderObject));
    auto& icon = static_cast<RenderThemeIconGadget&>(themePart == EntryIconLeft ? searchEntryWidget.leftIcon() : searchEntryWidget.rightIcon());
    icon.setState(themePartStateFlags(*theme, themePart, renderObject));
    icon.setIconSize(renderObject.style().computedFontPixelSize());
    GtkBorder contentsBox = searchEntryWidget.entry().contentsBox();
    IntRect iconRect = rect;
    if (themePart == EntryIconLeft) {
        iconRect.move(contentsBox.left, contentsBox.top);
        iconRect.contract(contentsBox.left, contentsBox.top + contentsBox.bottom);
    } else
        iconRect.contract(contentsBox.right, contentsBox.top + contentsBox.bottom);
    return !icon.render(paintInfo.context().platformContext()->cr(), iconRect);
}
bool RenderThemeGtk::paintSearchFieldResultsDecorationPart(const RenderBox& renderObject, const PaintInfo& paintInfo, const IntRect& rect)
{
    return paintSearchFieldIcon(this, EntryIconLeft, renderObject, paintInfo, rect);
}

bool RenderThemeGtk::paintSearchFieldCancelButton(const RenderBox& renderObject, const PaintInfo& paintInfo, const IntRect& rect)
{
    return paintSearchFieldIcon(this, EntryIconRight, renderObject, paintInfo, rect);
}

#if ENABLE(DATALIST_ELEMENT)
void RenderThemeGtk::adjustListButtonStyle(StyleResolver&, RenderStyle& style, const Element*) const
{
    // Add a margin to place the button at end of the input field.
    if (style.isLeftToRightDirection())
        style.setMarginRight(Length(-4, Fixed));
    else
        style.setMarginLeft(Length(-4, Fixed));
}

void RenderThemeGtk::paintListButtonForInput(const RenderObject& renderObject, const PaintInfo& paintInfo, const FloatRect& rect)
{
    // Use a combo box widget to render its arrow.
    auto& comboWidget = static_cast<RenderThemeComboBox&>(RenderThemeWidget::getOrCreate(RenderThemeWidget::Type::ComboBox));
    comboWidget.arrow().setState(themePartStateFlags(*this, ComboBoxButton, renderObject));

    // But a search entry widget to get the contents rect, since this is a text input field.
    auto& searchEntryWidget = static_cast<RenderThemeSearchEntry&>(RenderThemeWidget::getOrCreate(RenderThemeWidget::Type::SearchEntry));
    auto& icon = static_cast<RenderThemeIconGadget&>(searchEntryWidget.rightIcon());
    icon.setIconSize(comboWidget.arrow().preferredSize().width());
    GtkBorder contentsBox = searchEntryWidget.entry().contentsBox();
    FloatRect adjustedRect(rect);
    adjustedRect.move(contentsBox.left, contentsBox.top);
    adjustedRect.contract(contentsBox.right + 1, contentsBox.top + contentsBox.bottom);
    comboWidget.arrow().render(paintInfo.context().platformContext()->cr(), adjustedRect);
}
#endif

void RenderThemeGtk::adjustSearchFieldStyle(StyleResolver&, RenderStyle& style, const Element*) const
{
    // We cannot give a proper rendering when border radius is active, unfortunately.
    style.resetBorderRadius();
    style.setLineHeight(RenderStyle::initialLineHeight());
}

bool RenderThemeGtk::paintSearchField(const RenderObject& o, const PaintInfo& i, const IntRect& rect)
{
    return paintTextField(o, i, rect);
}

bool RenderThemeGtk::shouldHaveCapsLockIndicator(const HTMLInputElement& element) const
{
    return element.isPasswordField();
}

void RenderThemeGtk::adjustSliderTrackStyle(StyleResolver&, RenderStyle& style, const Element*) const
{
    style.setBoxShadow(nullptr);
}

void RenderThemeGtk::adjustSliderThumbStyle(StyleResolver& styleResolver, RenderStyle& style, const Element* element) const
{
    RenderTheme::adjustSliderThumbStyle(styleResolver, style, element);
    style.setBoxShadow(nullptr);
}

/*
 * GtkScale
 *
 * scale
 * ╰── contents
 *     ╰── trough
 *         ├── slider
 *         ╰── [highlight]
 */
bool RenderThemeGtk::paintSliderTrack(const RenderObject& renderObject, const PaintInfo& paintInfo, const IntRect& rect)
{
    ControlPart part = renderObject.style().appearance();
    ASSERT(part == SliderHorizontalPart || part == SliderVerticalPart);

    auto& sliderWidget = static_cast<RenderThemeSlider&>(RenderThemeWidget::getOrCreate(part == SliderHorizontalPart ? RenderThemeWidget::Type::HorizontalSlider : RenderThemeWidget::Type::VerticalSlider));
    auto scaleState = themePartStateFlags(*this, Scale, renderObject);
    auto& scale = sliderWidget.scale();
    scale.setState(scaleState);
    auto& contents = sliderWidget.contents();
    auto& trough = sliderWidget.trough();
    trough.setState(scaleState);
    auto& slider = sliderWidget.slider();
    auto& highlight = sliderWidget.highlight();

    // The given rectangle is not calculated based on the scale size, but all the margins and paddings are based on it.
    IntSize preferredSize = scale.preferredSize();
    preferredSize = preferredSize.expandedTo(contents.preferredSize());
    preferredSize = preferredSize.expandedTo(trough.preferredSize());
    FloatRect trackRect = rect;
    if (part == SliderHorizontalPart) {
        trackRect.move(0, rect.height() / 2 - (preferredSize.height() / 2));
        trackRect.setHeight(preferredSize.height());
    } else {
        trackRect.move(rect.width() / 2 - (preferredSize.width() / 2), 0);
        trackRect.setWidth(preferredSize.width());
    }

    FloatRect contentsRect;
    scale.render(paintInfo.context().platformContext()->cr(), trackRect, &contentsRect);
    contents.render(paintInfo.context().platformContext()->cr(), contentsRect, &contentsRect);
    // Scale trough defines its size querying slider and highlight.
    if (part == SliderHorizontalPart)
        contentsRect.setHeight(trough.preferredSize().height() + std::max(slider.preferredSize().height(), highlight.preferredSize().height()));
    else
        contentsRect.setWidth(trough.preferredSize().width() + std::max(slider.preferredSize().width(), highlight.preferredSize().width()));
    FloatRect troughRect = contentsRect;
    trough.render(paintInfo.context().platformContext()->cr(), troughRect, &contentsRect);
    if (isFocused(renderObject))
        trough.renderFocus(paintInfo.context().platformContext()->cr(), troughRect);

    LayoutPoint thumbLocation;
    if (is<HTMLInputElement>(renderObject.node())) {
        auto& input = downcast<HTMLInputElement>(*renderObject.node());
        if (auto* element = input.sliderThumbElement())
            thumbLocation = element->renderBox()->location();
    }

    if (part == SliderHorizontalPart) {
        if (renderObject.style().direction() == TextDirection::RTL) {
            contentsRect.move(thumbLocation.x(), 0);
            contentsRect.setWidth(contentsRect.width() - thumbLocation.x());
        } else
            contentsRect.setWidth(thumbLocation.x());
    } else
        contentsRect.setHeight(thumbLocation.y());
    highlight.render(paintInfo.context().platformContext()->cr(), contentsRect);

    return false;
}

void RenderThemeGtk::adjustSliderThumbSize(RenderStyle& style, const Element*) const
{
    ControlPart part = style.appearance();
    if (part != SliderThumbHorizontalPart && part != SliderThumbVerticalPart)
        return;

    auto& sliderWidget = static_cast<RenderThemeSlider&>(RenderThemeWidget::getOrCreate(part == SliderThumbHorizontalPart ? RenderThemeWidget::Type::HorizontalSlider : RenderThemeWidget::Type::VerticalSlider));
    sliderWidget.scale().setState(GTK_STATE_FLAG_NORMAL);
    sliderWidget.trough().setState(GTK_STATE_FLAG_NORMAL);

    IntSize preferredSize = sliderWidget.scale().preferredSize();
    preferredSize = preferredSize.expandedTo(sliderWidget.contents().preferredSize());
    preferredSize = preferredSize.expandedTo(sliderWidget.trough().preferredSize());
    preferredSize = preferredSize.expandedTo(sliderWidget.slider().preferredSize());
    if (part == SliderThumbHorizontalPart) {
        style.setWidth(Length(preferredSize.width(), Fixed));
        style.setHeight(Length(preferredSize.height(), Fixed));
        return;
    }
    ASSERT(part == SliderThumbVerticalPart);
    style.setWidth(Length(preferredSize.height(), Fixed));
    style.setHeight(Length(preferredSize.width(), Fixed));
}

bool RenderThemeGtk::paintSliderThumb(const RenderObject& renderObject, const PaintInfo& paintInfo, const IntRect& rect)
{
    ControlPart part = renderObject.style().appearance();
    ASSERT(part == SliderThumbHorizontalPart || part == SliderThumbVerticalPart);

    auto& sliderWidget = static_cast<RenderThemeSlider&>(RenderThemeWidget::getOrCreate(part == SliderThumbHorizontalPart ? RenderThemeWidget::Type::HorizontalSlider : RenderThemeWidget::Type::VerticalSlider));
    auto scaleState = themePartStateFlags(*this, Scale, renderObject);
    auto& scale = sliderWidget.scale();
    scale.setState(scaleState);
    auto& contents = sliderWidget.contents();
    auto& trough = sliderWidget.trough();
    trough.setState(scaleState);
    auto& slider = sliderWidget.slider();
    slider.setState(themePartStateFlags(*this, ScaleSlider, renderObject));
    auto& highlight = sliderWidget.highlight();

    GtkBorder scaleContentsBox = scale.contentsBox();
    GtkBorder contentsContentsBox = contents.contentsBox();
    GtkBorder troughContentsBox = trough.contentsBox();
    GtkBorder padding;
    padding.left = scaleContentsBox.left + contentsContentsBox.left + troughContentsBox.left;
    padding.right = scaleContentsBox.right + contentsContentsBox.right + troughContentsBox.right;
    padding.top = scaleContentsBox.top + contentsContentsBox.top + troughContentsBox.top;
    padding.bottom = scaleContentsBox.bottom + contentsContentsBox.bottom + troughContentsBox.bottom;

    // Scale trough defines its size querying slider and highlight.
    int troughHeight = trough.preferredSize().height() + std::max(slider.preferredSize().height(), highlight.preferredSize().height());
    IntRect sliderRect(rect.location(), IntSize(troughHeight, troughHeight));
    sliderRect.move(padding.left, padding.top);
    sliderRect.contract(padding.left + padding.right, padding.top + padding.bottom);
    slider.render(paintInfo.context().platformContext()->cr(), sliderRect);
    return false;
}

IntRect RenderThemeGtk::progressBarRectForBounds(const RenderObject& renderObject, const IntRect& bounds) const
{
    const auto& renderProgress = downcast<RenderProgress>(renderObject);
    auto& progressBarWidget = static_cast<RenderThemeProgressBar&>(RenderThemeWidget::getOrCreate(renderProgress.isDeterminate() ? RenderThemeProgressBar::Type::ProgressBar : RenderThemeProgressBar::Type::IndeterminateProgressBar));
    IntSize preferredSize = progressBarWidget.progressBar().preferredSize();
    preferredSize = preferredSize.expandedTo(progressBarWidget.trough().preferredSize());
    preferredSize = preferredSize.expandedTo(progressBarWidget.progress().preferredSize());
    return IntRect(bounds.x(), bounds.y(), bounds.width(), preferredSize.height());
}

bool RenderThemeGtk::paintProgressBar(const RenderObject& renderObject, const PaintInfo& paintInfo, const IntRect& rect)
{
    if (!renderObject.isProgress())
        return true;

    const auto& renderProgress = downcast<RenderProgress>(renderObject);
    auto& progressBarWidget = static_cast<RenderThemeProgressBar&>(RenderThemeWidget::getOrCreate(renderProgress.isDeterminate() ? RenderThemeProgressBar::Type::ProgressBar : RenderThemeProgressBar::Type::IndeterminateProgressBar));
    progressBarWidget.progressBar().render(paintInfo.context().platformContext()->cr(), rect);
    progressBarWidget.trough().render(paintInfo.context().platformContext()->cr(), rect);
    progressBarWidget.progress().render(paintInfo.context().platformContext()->cr(), calculateProgressRect(renderObject, rect));
    return false;
}

RenderTheme::InnerSpinButtonLayout RenderThemeGtk::innerSpinButtonLayout(const RenderObject& renderObject) const
{
    return renderObject.style().direction() == TextDirection::RTL ? InnerSpinButtonLayout::HorizontalUpLeft : InnerSpinButtonLayout::HorizontalUpRight;
}

void RenderThemeGtk::adjustInnerSpinButtonStyle(StyleResolver&, RenderStyle& style, const Element*) const
{
    style.setWidth(Length(spinButtonSize().width(), Fixed));
    style.setHeight(Length(spinButtonSize().height(), Fixed));
}

bool RenderThemeGtk::paintInnerSpinButton(const RenderObject& renderObject, const PaintInfo& paintInfo, const IntRect& rect)
{
    auto& spinButtonWidget = static_cast<RenderThemeSpinButton&>(RenderThemeWidget::getOrCreate(RenderThemeWidget::Type::SpinButton));
    auto spinButtonState = themePartStateFlags(*this, SpinButton, renderObject);
    spinButtonWidget.spinButton().setState(spinButtonState);
    spinButtonWidget.entry().setState(spinButtonState);
    auto& up = spinButtonWidget.up();
    up.setState(themePartStateFlags(*this, SpinButtonUpButton, renderObject));
    auto& down = spinButtonWidget.down();
    down.setState(themePartStateFlags(*this, SpinButtonDownButton, renderObject));

    IntRect iconRect = rect;
    iconRect.setWidth(iconRect.width() / 2);
    if (renderObject.style().direction() == TextDirection::RTL)
        up.render(paintInfo.context().platformContext()->cr(), iconRect);
    else
        down.render(paintInfo.context().platformContext()->cr(), iconRect);
    iconRect.move(iconRect.width(), 0);
    if (renderObject.style().direction() == TextDirection::RTL)
        down.render(paintInfo.context().platformContext()->cr(), iconRect);
    else
        up.render(paintInfo.context().platformContext()->cr(), iconRect);

    return false;
}

Seconds RenderThemeGtk::caretBlinkInterval() const
{
    GtkSettings* settings = gtk_settings_get_default();

    gboolean shouldBlink;
    gint time;

    g_object_get(settings, "gtk-cursor-blink", &shouldBlink, "gtk-cursor-blink-time", &time, nullptr);

    if (!shouldBlink)
        return 0_s;

    return 500_us * time;
}

enum StyleColorType { StyleColorBackground, StyleColorForeground };

static Color styleColor(RenderThemePart themePart, GtkStateFlags state, StyleColorType colorType)
{
    RenderThemeGadget* gadget = nullptr;
    switch (themePart) {
    default:
        ASSERT_NOT_REACHED();
        FALLTHROUGH;
    case Entry:
        gadget = &static_cast<RenderThemeEntry&>(RenderThemeWidget::getOrCreate(RenderThemeWidget::Type::Entry)).entry();
        break;
    case EntrySelection:
        gadget = static_cast<RenderThemeEntry&>(RenderThemeWidget::getOrCreate(RenderThemeWidget::Type::SelectedEntry)).selection();
        break;
    case ListBox:
        gadget = &static_cast<RenderThemeListView&>(RenderThemeWidget::getOrCreate(RenderThemeWidget::Type::ListView)).treeview();
        break;
    case Button:
        gadget = &static_cast<RenderThemeButton&>(RenderThemeWidget::getOrCreate(RenderThemeWidget::Type::Button)).button();
        break;
    case Window:
        gadget = &static_cast<RenderThemeWindow&>(RenderThemeWidget::getOrCreate(RenderThemeWidget::Type::Window)).window();
        break;
    }

    ASSERT(gadget);
    gadget->setState(state);
    return colorType == StyleColorBackground ? gadget->backgroundColor() : gadget->color();
}

Color RenderThemeGtk::platformActiveSelectionBackgroundColor(OptionSet<StyleColor::Options>) const
{
    return styleColor(EntrySelection, static_cast<GtkStateFlags>(GTK_STATE_FLAG_SELECTED | GTK_STATE_FLAG_FOCUSED), StyleColorBackground);
}

Color RenderThemeGtk::platformInactiveSelectionBackgroundColor(OptionSet<StyleColor::Options>) const
{
    return styleColor(EntrySelection, GTK_STATE_FLAG_SELECTED, StyleColorBackground);
}

Color RenderThemeGtk::platformActiveSelectionForegroundColor(OptionSet<StyleColor::Options>) const
{
    return styleColor(EntrySelection, static_cast<GtkStateFlags>(GTK_STATE_FLAG_SELECTED | GTK_STATE_FLAG_FOCUSED), StyleColorForeground);
}

Color RenderThemeGtk::platformInactiveSelectionForegroundColor(OptionSet<StyleColor::Options>) const
{
    return styleColor(EntrySelection, GTK_STATE_FLAG_SELECTED, StyleColorForeground);
}

Color RenderThemeGtk::platformActiveListBoxSelectionBackgroundColor(OptionSet<StyleColor::Options>) const
{
    return styleColor(ListBox, static_cast<GtkStateFlags>(GTK_STATE_FLAG_SELECTED | GTK_STATE_FLAG_FOCUSED), StyleColorBackground);
}

Color RenderThemeGtk::platformInactiveListBoxSelectionBackgroundColor(OptionSet<StyleColor::Options>) const
{
    return styleColor(ListBox, GTK_STATE_FLAG_SELECTED, StyleColorBackground);
}

Color RenderThemeGtk::platformActiveListBoxSelectionForegroundColor(OptionSet<StyleColor::Options>) const
{
    return styleColor(ListBox, static_cast<GtkStateFlags>(GTK_STATE_FLAG_SELECTED | GTK_STATE_FLAG_FOCUSED), StyleColorForeground);
}

Color RenderThemeGtk::platformInactiveListBoxSelectionForegroundColor(OptionSet<StyleColor::Options>) const
{
    return styleColor(ListBox, GTK_STATE_FLAG_SELECTED, StyleColorForeground);
}

Color RenderThemeGtk::disabledTextColor(const Color&, const Color&) const
{
    return styleColor(Entry, GTK_STATE_FLAG_INSENSITIVE, StyleColorForeground);
}

Color RenderThemeGtk::systemColor(CSSValueID cssValueId, OptionSet<StyleColor::Options> options) const
{
    switch (cssValueId) {
    case CSSValueButtontext:
        return styleColor(Button, GTK_STATE_FLAG_ACTIVE, StyleColorForeground);
    case CSSValueCaptiontext:
        return styleColor(Entry, GTK_STATE_FLAG_ACTIVE, StyleColorForeground);
    case CSSValueText:
        return styleColor(Entry, GTK_STATE_FLAG_ACTIVE, StyleColorForeground);
    case CSSValueGraytext:
        return styleColor(Entry, GTK_STATE_FLAG_INSENSITIVE, StyleColorForeground);
    case CSSValueWebkitControlBackground:
        return styleColor(Entry, GTK_STATE_FLAG_ACTIVE, StyleColorBackground);
    case CSSValueWindow: {
        // Only get window color from the theme in dark mode.
        gboolean preferDarkTheme = FALSE;
        if (auto* settings = gtk_settings_get_default())
            g_object_get(settings, "gtk-application-prefer-dark-theme", &preferDarkTheme, nullptr);
        if (preferDarkTheme)
            return styleColor(Window, GTK_STATE_FLAG_ACTIVE, StyleColorBackground);
        break;
    }
    default:
        break;
    }

    return RenderTheme::systemColor(cssValueId, options);
}

void RenderThemeGtk::platformColorsDidChange()
{
    RenderTheme::platformColorsDidChange();
}

#if ENABLE(VIDEO)
String RenderThemeGtk::extraMediaControlsStyleSheet()
{
    return String(mediaControlsGtkUserAgentStyleSheet, sizeof(mediaControlsGtkUserAgentStyleSheet));
}

#if ENABLE(FULLSCREEN_API)
String RenderThemeGtk::extraFullScreenStyleSheet()
{
    return String();
}
#endif

bool RenderThemeGtk::paintMediaButton(const RenderObject& renderObject, GraphicsContext& graphicsContext, const IntRect& rect, const char* iconName)
{
    auto& iconWidget = static_cast<RenderThemeIcon&>(RenderThemeWidget::getOrCreate(RenderThemeWidget::Type::Icon));
    auto& icon = static_cast<RenderThemeIconGadget&>(iconWidget.icon());
    icon.setState(themePartStateFlags(*this, MediaButton, renderObject));
    icon.setIconSize(RenderThemeIconGadget::IconSizeGtk::Menu);
    icon.setIconName(iconName);
    return !icon.render(graphicsContext.platformContext()->cr(), rect);
}

bool RenderThemeGtk::hasOwnDisabledStateHandlingFor(ControlPart part) const
{
    return (part != MediaMuteButtonPart);
}

bool RenderThemeGtk::paintMediaFullscreenButton(const RenderObject& renderObject, const PaintInfo& paintInfo, const IntRect& rect)
{
    return paintMediaButton(renderObject, paintInfo.context(), rect, "view-fullscreen-symbolic");
}

bool RenderThemeGtk::paintMediaMuteButton(const RenderObject& renderObject, const PaintInfo& paintInfo, const IntRect& rect)
{
    Node* node = renderObject.node();
    if (!node)
        return true;
    Node* mediaNode = node->shadowHost();
    if (!is<HTMLMediaElement>(mediaNode))
        return true;

    HTMLMediaElement* mediaElement = downcast<HTMLMediaElement>(mediaNode);
    return paintMediaButton(renderObject, paintInfo.context(), rect, mediaElement->muted() ? "audio-volume-muted-symbolic" : "audio-volume-high-symbolic");
}

bool RenderThemeGtk::paintMediaPlayButton(const RenderObject& renderObject, const PaintInfo& paintInfo, const IntRect& rect)
{
    Node* node = renderObject.node();
    if (!node)
        return true;
    if (!nodeHasPseudo(*node, "-webkit-media-controls-play-button"))
        return true;

    return paintMediaButton(renderObject, paintInfo.context(), rect, nodeHasClass(node, "paused") ? "media-playback-start-symbolic" : "media-playback-pause-symbolic");
}

bool RenderThemeGtk::paintMediaSeekBackButton(const RenderObject& renderObject, const PaintInfo& paintInfo, const IntRect& rect)
{
    return paintMediaButton(renderObject, paintInfo.context(), rect, "media-seek-backward-symbolic");
}

bool RenderThemeGtk::paintMediaSeekForwardButton(const RenderObject& renderObject, const PaintInfo& paintInfo, const IntRect& rect)
{
    return paintMediaButton(renderObject, paintInfo.context(), rect, "media-seek-forward-symbolic");
}

#if ENABLE(VIDEO_TRACK)
bool RenderThemeGtk::paintMediaToggleClosedCaptionsButton(const RenderObject& renderObject, const PaintInfo& paintInfo, const IntRect& rect)
{
    return paintMediaButton(renderObject, paintInfo.context(), rect, "media-view-subtitles-symbolic");
}
#endif

static FloatRoundedRect::Radii borderRadiiFromStyle(const RenderStyle& style)
{
    return FloatRoundedRect::Radii(
        IntSize(style.borderTopLeftRadius().width.intValue(), style.borderTopLeftRadius().height.intValue()),
        IntSize(style.borderTopRightRadius().width.intValue(), style.borderTopRightRadius().height.intValue()),
        IntSize(style.borderBottomLeftRadius().width.intValue(), style.borderBottomLeftRadius().height.intValue()),
        IntSize(style.borderBottomRightRadius().width.intValue(), style.borderBottomRightRadius().height.intValue()));
}

bool RenderThemeGtk::paintMediaSliderTrack(const RenderObject& o, const PaintInfo& paintInfo, const IntRect& r)
{
    auto mediaElement = parentMediaElement(o);
    if (!mediaElement)
        return true;

    GraphicsContext& context = paintInfo.context();
    context.save();
    context.setStrokeStyle(NoStroke);

    float mediaDuration = mediaElement->duration();
    float totalTrackWidth = r.width();
    auto& style = o.style();
    RefPtr<TimeRanges> timeRanges = mediaElement->buffered();
    for (unsigned index = 0; index < timeRanges->length(); ++index) {
        float start = timeRanges->start(index).releaseReturnValue();
        float end = timeRanges->end(index).releaseReturnValue();
        float startRatio = start / mediaDuration;
        float lengthRatio = (end - start) / mediaDuration;
        if (!lengthRatio)
            continue;

        IntRect rangeRect(r);
        rangeRect.setWidth(lengthRatio * totalTrackWidth);
        if (index)
            rangeRect.move(startRatio * totalTrackWidth, 0);
        context.fillRoundedRect(FloatRoundedRect(rangeRect, borderRadiiFromStyle(style)), style.visitedDependentColor(CSSPropertyColor));
    }

    context.restore();
    return false;
}

bool RenderThemeGtk::paintMediaSliderThumb(const RenderObject& o, const PaintInfo& paintInfo, const IntRect& r)
{
    auto& style = o.style();
    paintInfo.context().fillRoundedRect(FloatRoundedRect(r, borderRadiiFromStyle(style)), style.visitedDependentColor(CSSPropertyColor));
    return false;
}

bool RenderThemeGtk::paintMediaVolumeSliderTrack(const RenderObject& renderObject, const PaintInfo& paintInfo, const IntRect& rect)
{
    auto mediaElement = parentMediaElement(renderObject);
    if (!mediaElement)
        return true;

    float volume = mediaElement->muted() ? 0.0f : mediaElement->volume();
    if (!volume)
        return true;

    GraphicsContext& context = paintInfo.context();
    context.save();
    context.setStrokeStyle(NoStroke);

    int rectHeight = rect.height();
    float trackHeight = rectHeight * volume;
    auto& style = renderObject.style();
    IntRect volumeRect(rect);
    volumeRect.move(0, rectHeight - trackHeight);
    volumeRect.setHeight(ceil(trackHeight));

    context.fillRoundedRect(FloatRoundedRect(volumeRect, borderRadiiFromStyle(style)), style.visitedDependentColor(CSSPropertyColor));
    context.restore();

    return false;
}

bool RenderThemeGtk::paintMediaVolumeSliderThumb(const RenderObject& renderObject, const PaintInfo& paintInfo, const IntRect& rect)
{
    return paintMediaSliderThumb(renderObject, paintInfo, rect);
}

String RenderThemeGtk::formatMediaControlsCurrentTime(float currentTime, float duration) const
{
    return formatMediaControlsTime(currentTime) + " / " + formatMediaControlsTime(duration);
}

bool RenderThemeGtk::paintMediaCurrentTime(const RenderObject&, const PaintInfo&, const IntRect&)
{
    return false;
}
#endif

void RenderThemeGtk::adjustProgressBarStyle(StyleResolver&, RenderStyle& style, const Element*) const
{
    style.setBoxShadow(nullptr);
}

// These values have been copied from RenderThemeChromiumSkia.cpp
static const int progressActivityBlocks = 5;
static const int progressAnimationFrames = 10;
static const Seconds progressAnimationInterval { 125_ms };
Seconds RenderThemeGtk::animationRepeatIntervalForProgressBar(RenderProgress&) const
{
    return progressAnimationInterval;
}

Seconds RenderThemeGtk::animationDurationForProgressBar(RenderProgress&) const
{
    return progressAnimationInterval * progressAnimationFrames * 2; // "2" for back and forth;
}

IntRect RenderThemeGtk::calculateProgressRect(const RenderObject& renderObject, const IntRect& fullBarRect)
{
    IntRect progressRect(fullBarRect);
    const auto& renderProgress = downcast<RenderProgress>(renderObject);
    if (renderProgress.isDeterminate()) {
        int progressWidth = progressRect.width() * renderProgress.position();
        if (renderObject.style().direction() == TextDirection::RTL)
            progressRect.setX(progressRect.x() + progressRect.width() - progressWidth);
        progressRect.setWidth(progressWidth);
        return progressRect;
    }

    double animationProgress = renderProgress.animationProgress();

    // Never let the progress rect shrink smaller than 2 pixels.
    int newWidth = std::max(2, progressRect.width() / progressActivityBlocks);
    int movableWidth = progressRect.width() - newWidth;
    progressRect.setWidth(newWidth);

    // We want the first 0.5 units of the animation progress to represent the
    // forward motion and the second 0.5 units to represent the backward motion,
    // thus we multiply by two here to get the full sweep of the progress bar with
    // each direction.
    if (animationProgress < 0.5)
        progressRect.setX(progressRect.x() + (animationProgress * 2 * movableWidth));
    else
        progressRect.setX(progressRect.x() + ((1.0 - animationProgress) * 2 * movableWidth));
    return progressRect;
}

String RenderThemeGtk::fileListNameForWidth(const FileList* fileList, const FontCascade& font, int width, bool multipleFilesAllowed) const
{
    if (width <= 0)
        return String();

    if (fileList->length() > 1)
        return StringTruncator::rightTruncate(multipleFileUploadText(fileList->length()), width, font);

    String string;
    if (fileList->length())
        string = FileSystem::pathGetFileName(fileList->item(0)->path());
    else if (multipleFilesAllowed)
        string = fileButtonNoFilesSelectedLabel();
    else
        string = fileButtonNoFileSelectedLabel();

    return StringTruncator::centerTruncate(string, width, font);
}

#if ENABLE(VIDEO)
String RenderThemeGtk::mediaControlsScript()
{
    StringBuilder scriptBuilder;
    scriptBuilder.appendCharacters(mediaControlsLocalizedStringsJavaScript, sizeof(mediaControlsLocalizedStringsJavaScript));
    scriptBuilder.appendCharacters(mediaControlsBaseJavaScript, sizeof(mediaControlsBaseJavaScript));
    scriptBuilder.appendCharacters(mediaControlsGtkJavaScript, sizeof(mediaControlsGtkJavaScript));
    return scriptBuilder.toString();
}
#endif // ENABLE(VIDEO)
}
