/*
 * Copyright (C) 2014, 2020 Igalia S.L.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 * THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "config.h"
#include "RenderThemeAdwaita.h"

#include "Color.h"
#include "FloatRoundedRect.h"
#include "GraphicsContext.h"
#include "HTMLInputElement.h"
#include "HTMLMediaElement.h"
#include "MediaControlTextTrackContainerElement.h"
#include "PaintInfo.h"
#include "RenderBox.h"
#include "RenderObject.h"
#include "RenderProgress.h"
#include "RenderStyle.h"
#include "ThemeAdwaita.h"
#include "TimeRanges.h"
#include "UserAgentScripts.h"
#include "UserAgentStyleSheets.h"

namespace WebCore {

static const int textFieldBorderSize = 1;
static constexpr auto textFieldBorderColor = SRGBA<uint8_t> { 205, 199, 194 };
static constexpr auto textFieldBorderDisabledColor = SRGBA<uint8_t> { 213, 208, 204 };
static constexpr auto textFieldBackgroundColor = Color::white;
static constexpr auto textFieldBackgroundDisabledColor = SRGBA<uint8_t> { 252, 252, 252 };
static const unsigned menuListButtonArrowSize = 16;
static const int menuListButtonFocusOffset = -3;
static const unsigned menuListButtonPadding = 5;
static const int menuListButtonBorderSize = 1; // Keep in sync with buttonBorderSize in ThemeAdwaita.
static const unsigned progressActivityBlocks = 5;
static const unsigned progressAnimationFrameCount = 75;
static const Seconds progressAnimationFrameRate = 33_ms; // 30fps.
static const unsigned progressBarSize = 6;
static constexpr auto progressBarBorderColor = SRGBA<uint8_t> { 205, 199, 194 };
static constexpr auto progressBarBackgroundColor = SRGBA<uint8_t> { 225, 222, 219 };
static const unsigned sliderTrackSize = 6;
static const int sliderTrackBorderSize = 1;
static constexpr auto sliderTrackBorderColor = SRGBA<uint8_t> { 205, 199, 194 };
static constexpr auto sliderTrackBackgroundColor = SRGBA<uint8_t> { 225, 222, 219 };
static const int sliderTrackFocusOffset = 2;
static const int sliderThumbSize = 20;
static const int sliderThumbBorderSize = 1;
static constexpr auto sliderThumbBorderColor = SRGBA<uint8_t> { 205, 199, 194 };
static constexpr auto sliderThumbBackgroundColor = SRGBA<uint8_t> { 244, 242, 241 };
static constexpr auto sliderThumbBackgroundHoveredColor = SRGBA<uint8_t> { 248, 248, 247 };
static constexpr auto sliderThumbBackgroundDisabledColor = SRGBA<uint8_t> { 244, 242, 241 };
#if ENABLE(VIDEO)
static constexpr auto mediaSliderTrackBackgroundcolor = SRGBA<uint8_t> { 77, 77, 77 };
static constexpr auto mediaSliderTrackBufferedColor = SRGBA<uint8_t> { 173, 173, 173 };
static constexpr auto mediaSliderTrackActiveColor = SRGBA<uint8_t> { 252, 252, 252 };
#endif

#if !PLATFORM(GTK)
RenderTheme& RenderTheme::singleton()
{
    static MainThreadNeverDestroyed<RenderThemeAdwaita> theme;
    return theme;
}
#endif

bool RenderThemeAdwaita::supportsFocusRing(const RenderStyle& style) const
{
    switch (style.appearance()) {
    case PushButtonPart:
    case ButtonPart:
    case TextFieldPart:
    case TextAreaPart:
    case SearchFieldPart:
    case MenulistPart:
    case RadioPart:
    case CheckboxPart:
    case SliderHorizontalPart:
    case SliderVerticalPart:
        return true;
    default:
        break;
    }

    return false;
}

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

Color RenderThemeAdwaita::platformActiveSelectionBackgroundColor(OptionSet<StyleColor::Options>) const
{
    return static_cast<ThemeAdwaita&>(Theme::singleton()).activeSelectionBackgroundColor();
}

Color RenderThemeAdwaita::platformInactiveSelectionBackgroundColor(OptionSet<StyleColor::Options>) const
{
    return static_cast<ThemeAdwaita&>(Theme::singleton()).inactiveSelectionBackgroundColor();
}

Color RenderThemeAdwaita::platformActiveSelectionForegroundColor(OptionSet<StyleColor::Options>) const
{
    return static_cast<ThemeAdwaita&>(Theme::singleton()).activeSelectionForegroundColor();
}

Color RenderThemeAdwaita::platformInactiveSelectionForegroundColor(OptionSet<StyleColor::Options>) const
{
    return static_cast<ThemeAdwaita&>(Theme::singleton()).inactiveSelectionForegroundColor();
}

Color RenderThemeAdwaita::platformActiveListBoxSelectionBackgroundColor(OptionSet<StyleColor::Options>) const
{
    return static_cast<ThemeAdwaita&>(Theme::singleton()).activeSelectionBackgroundColor();
}

Color RenderThemeAdwaita::platformInactiveListBoxSelectionBackgroundColor(OptionSet<StyleColor::Options>) const
{
    return static_cast<ThemeAdwaita&>(Theme::singleton()).inactiveSelectionBackgroundColor();
}

Color RenderThemeAdwaita::platformActiveListBoxSelectionForegroundColor(OptionSet<StyleColor::Options>) const
{
    return static_cast<ThemeAdwaita&>(Theme::singleton()).activeSelectionForegroundColor();
}

Color RenderThemeAdwaita::platformInactiveListBoxSelectionForegroundColor(OptionSet<StyleColor::Options>) const
{
    return static_cast<ThemeAdwaita&>(Theme::singleton()).inactiveSelectionForegroundColor();
}

Color RenderThemeAdwaita::platformFocusRingColor(OptionSet<StyleColor::Options>) const
{
    return ThemeAdwaita::focusColor();
}

void RenderThemeAdwaita::platformColorsDidChange()
{
    static_cast<ThemeAdwaita&>(Theme::singleton()).platformColorsDidChange();
    RenderTheme::platformColorsDidChange();
}

String RenderThemeAdwaita::extraDefaultStyleSheet()
{
    return String(themeAdwaitaUserAgentStyleSheet, sizeof(themeAdwaitaUserAgentStyleSheet));
}

#if ENABLE(VIDEO)
String RenderThemeAdwaita::extraMediaControlsStyleSheet()
{
    return String(mediaControlsAdwaitaUserAgentStyleSheet, sizeof(mediaControlsAdwaitaUserAgentStyleSheet));
}

String RenderThemeAdwaita::mediaControlsScript()
{
    return String(mediaControlsAdwaitaJavaScript, sizeof(mediaControlsAdwaitaJavaScript));
}
#endif

bool RenderThemeAdwaita::paintTextField(const RenderObject& renderObject, const PaintInfo& paintInfo, const FloatRect& rect)
{
    auto& graphicsContext = paintInfo.context();
    GraphicsContextStateSaver stateSaver(graphicsContext);

    int borderSize = textFieldBorderSize;
    if (isEnabled(renderObject) && !isReadOnlyControl(renderObject) && isFocused(renderObject))
        borderSize *= 2;

    FloatRect fieldRect = rect;
    FloatSize corner(5, 5);
    Path path;
    path.addRoundedRect(fieldRect, corner);
    fieldRect.inflate(-borderSize);
    corner.expand(-borderSize, -borderSize);
    path.addRoundedRect(fieldRect, corner);
    graphicsContext.setFillRule(WindRule::EvenOdd);
    if (!isEnabled(renderObject) || isReadOnlyControl(renderObject))
        graphicsContext.setFillColor(textFieldBorderDisabledColor);
    else if (isFocused(renderObject))
        graphicsContext.setFillColor(activeSelectionBackgroundColor({ }));
    else
        graphicsContext.setFillColor(textFieldBorderColor);
    graphicsContext.fillPath(path);
    path.clear();

    path.addRoundedRect(fieldRect, corner);
    graphicsContext.setFillRule(WindRule::NonZero);
    if (!isEnabled(renderObject) || isReadOnlyControl(renderObject))
        graphicsContext.setFillColor(textFieldBackgroundDisabledColor);
    else
        graphicsContext.setFillColor(textFieldBackgroundColor);
    graphicsContext.fillPath(path);

#if ENABLE(DATALIST_ELEMENT)
    if (is<HTMLInputElement>(renderObject.generatingNode()) && downcast<HTMLInputElement>(*(renderObject.generatingNode())).list()) {
        FloatRect arrowRect = rect;
        if (renderObject.style().direction() == TextDirection::LTR)
            arrowRect.move(arrowRect.width() - (menuListButtonArrowSize + textFieldBorderSize * 2), (arrowRect.height() / 2.) - (menuListButtonArrowSize / 2.));
        else
            fieldRect.move(textFieldBorderSize * 2, (arrowRect.height() / 2.) - (menuListButtonArrowSize / 2.));
        arrowRect.setWidth(menuListButtonArrowSize);
        arrowRect.setHeight(menuListButtonArrowSize);
        {
            GraphicsContextStateSaver arrowStateSaver(graphicsContext);
            graphicsContext.translate(arrowRect.x(), arrowRect.y());
            ThemeAdwaita::paintArrow(graphicsContext, ThemeAdwaita::ArrowDirection::Down);
        }
    }
#endif

    return false;
}

bool RenderThemeAdwaita::paintTextArea(const RenderObject& renderObject, const PaintInfo& paintInfo, const FloatRect& rect)
{
    return paintTextField(renderObject, paintInfo, rect);
}

bool RenderThemeAdwaita::paintSearchField(const RenderObject& renderObject, const PaintInfo& paintInfo, const IntRect& rect)
{
    return paintTextField(renderObject, paintInfo, rect);
}

void RenderThemeAdwaita::adjustMenuListStyle(RenderStyle& style, const Element*) const
{
    style.setLineHeight(RenderStyle::initialLineHeight());
}

void RenderThemeAdwaita::adjustMenuListButtonStyle(RenderStyle& style, const Element* element) const
{
    adjustMenuListStyle(style, element);
}

LengthBox RenderThemeAdwaita::popupInternalPaddingBox(const RenderStyle& style, const Settings&) const
{
    if (style.appearance() == NoControlPart)
        return { };

    int leftPadding = menuListButtonPadding + (style.direction() == TextDirection::RTL ? menuListButtonArrowSize : 0);
    int rightPadding = menuListButtonPadding + (style.direction() == TextDirection::LTR ? menuListButtonArrowSize : 0);

    return { menuListButtonPadding, rightPadding, menuListButtonPadding, leftPadding };
}

bool RenderThemeAdwaita::paintMenuList(const RenderObject& renderObject, const PaintInfo& paintInfo, const FloatRect& rect)
{
    auto& graphicsContext = paintInfo.context();
    GraphicsContextStateSaver stateSaver(graphicsContext);

    ControlStates::States states = 0;
    if (isEnabled(renderObject))
        states |= ControlStates::EnabledState;
    if (isPressed(renderObject))
        states |= ControlStates::PressedState;
    if (isHovered(renderObject))
        states |= ControlStates::HoverState;
    ControlStates controlStates(states);
    Theme::singleton().paint(ButtonPart, controlStates, graphicsContext, rect, 1., nullptr, 1., 1., false, false);

    FloatRect fieldRect = rect;
    fieldRect.inflate(menuListButtonBorderSize);
    if (renderObject.style().direction() == TextDirection::LTR)
        fieldRect.move(fieldRect.width() - (menuListButtonArrowSize + menuListButtonPadding), (fieldRect.height() / 2.) - (menuListButtonArrowSize / 2));
    else
        fieldRect.move(menuListButtonPadding, (fieldRect.height() / 2.) - (menuListButtonArrowSize / 2));
    fieldRect.setWidth(menuListButtonArrowSize);
    fieldRect.setHeight(menuListButtonArrowSize);
    {
        GraphicsContextStateSaver arrowStateSaver(graphicsContext);
        graphicsContext.translate(fieldRect.x(), fieldRect.y());
        ThemeAdwaita::paintArrow(graphicsContext, ThemeAdwaita::ArrowDirection::Down);
    }

    if (isFocused(renderObject))
        ThemeAdwaita::paintFocus(graphicsContext, rect, menuListButtonFocusOffset);

    return false;
}

void RenderThemeAdwaita::paintMenuListButtonDecorations(const RenderBox& renderObject, const PaintInfo& paintInfo, const FloatRect& rect)
{
    paintMenuList(renderObject, paintInfo, rect);
}

Seconds RenderThemeAdwaita::animationRepeatIntervalForProgressBar(const RenderProgress&) const
{
    return progressAnimationFrameRate;
}

Seconds RenderThemeAdwaita::animationDurationForProgressBar(const RenderProgress&) const
{
    return progressAnimationFrameRate * progressAnimationFrameCount;
}

IntRect RenderThemeAdwaita::progressBarRectForBounds(const RenderObject&, const IntRect& bounds) const
{
    return { bounds.x(), bounds.y(), bounds.width(), progressBarSize };
}

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

    auto& graphicsContext = paintInfo.context();
    GraphicsContextStateSaver stateSaver(graphicsContext);

    FloatRect fieldRect = rect;
    FloatSize corner(3, 3);
    Path path;
    path.addRoundedRect(fieldRect, corner);
    fieldRect.inflate(-1);
    corner.expand(-1, -1);
    path.addRoundedRect(fieldRect, corner);
    graphicsContext.setFillRule(WindRule::EvenOdd);
    graphicsContext.setFillColor(progressBarBorderColor);
    graphicsContext.fillPath(path);
    path.clear();

    path.addRoundedRect(fieldRect, corner);
    graphicsContext.setFillRule(WindRule::NonZero);
    graphicsContext.setFillColor(progressBarBackgroundColor);
    graphicsContext.fillPath(path);
    path.clear();

    fieldRect = rect;
    const auto& renderProgress = downcast<RenderProgress>(renderObject);
    if (renderProgress.isDeterminate()) {
        auto progressWidth = fieldRect.width() * renderProgress.position();
        if (renderObject.style().direction() == TextDirection::RTL)
            fieldRect.move(fieldRect.width() - progressWidth, 0);
        fieldRect.setWidth(progressWidth);
    } else {
        double animationProgress = renderProgress.animationProgress();

        // Never let the progress rect shrink smaller than 2 pixels.
        fieldRect.setWidth(std::max<float>(2, fieldRect.width() / progressActivityBlocks));
        auto movableWidth = rect.width() - fieldRect.width();

        // 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)
            fieldRect.move(animationProgress * 2 * movableWidth, 0);
        else
            fieldRect.move((1.0 - animationProgress) * 2 * movableWidth, 0);
    }

    path.addRoundedRect(fieldRect, corner);
    graphicsContext.setFillRule(WindRule::NonZero);
    graphicsContext.setFillColor(activeSelectionBackgroundColor({ }));
    graphicsContext.fillPath(path);

    return false;
}

bool RenderThemeAdwaita::paintSliderTrack(const RenderObject& renderObject, const PaintInfo& paintInfo, const IntRect& rect)
{
    auto& graphicsContext = paintInfo.context();
    GraphicsContextStateSaver stateSaver(graphicsContext);

    ControlPart part = renderObject.style().appearance();
    ASSERT(part == SliderHorizontalPart || part == SliderVerticalPart);

    FloatRect fieldRect = rect;
    if (part == SliderHorizontalPart) {
        fieldRect.move(0, rect.height() / 2 - (sliderTrackSize / 2));
        fieldRect.setHeight(6);
    } else {
        fieldRect.move(rect.width() / 2 - (sliderTrackSize / 2), 0);
        fieldRect.setWidth(6);
    }

    FloatSize corner(3, 3);
    Path path;
    path.addRoundedRect(fieldRect, corner);
    fieldRect.inflate(-sliderTrackBorderSize);
    corner.expand(-sliderTrackBorderSize, -sliderTrackBorderSize);
    path.addRoundedRect(fieldRect, corner);
    graphicsContext.setFillRule(WindRule::EvenOdd);
    graphicsContext.setFillColor(sliderTrackBorderColor);
    graphicsContext.fillPath(path);
    path.clear();

    path.addRoundedRect(fieldRect, corner);
    graphicsContext.setFillRule(WindRule::NonZero);
    graphicsContext.setFillColor(sliderTrackBackgroundColor);
    graphicsContext.fillPath(path);
    path.clear();

    fieldRect.inflate(sliderTrackBorderSize);
    LayoutPoint thumbLocation;
    if (is<HTMLInputElement>(renderObject.node())) {
        auto& input = downcast<HTMLInputElement>(*renderObject.node());
        if (auto* element = input.sliderThumbElement())
            thumbLocation = element->renderBox()->location();
    }
    FloatRect rangeRect = fieldRect;
    FloatRoundedRect::Radii corners;
    if (part == SliderHorizontalPart) {
        if (renderObject.style().direction() == TextDirection::RTL) {
            rangeRect.move(thumbLocation.x(), 0);
            rangeRect.setWidth(rangeRect.width() - thumbLocation.x());
            corners.setTopRight(corner);
            corners.setBottomRight(corner);
        } else {
            rangeRect.setWidth(thumbLocation.x());
            corners.setTopLeft(corner);
            corners.setBottomLeft(corner);
        }
    } else {
        rangeRect.setHeight(thumbLocation.y());
        corners.setTopLeft(corner);
        corners.setTopRight(corner);
    }

    path.addRoundedRect(FloatRoundedRect(rangeRect, corners));
    graphicsContext.setFillRule(WindRule::NonZero);
    graphicsContext.setFillColor(activeSelectionBackgroundColor({ }));
    graphicsContext.fillPath(path);

#if ENABLE(DATALIST_ELEMENT)
    paintSliderTicks(renderObject, paintInfo, rect);
#endif

    if (isFocused(renderObject))
        ThemeAdwaita::paintFocus(graphicsContext, fieldRect, sliderTrackFocusOffset);

    return false;
}

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

    style.setWidth(Length(sliderThumbSize, LengthType::Fixed));
    style.setHeight(Length(sliderThumbSize, LengthType::Fixed));
}

bool RenderThemeAdwaita::paintSliderThumb(const RenderObject& renderObject, const PaintInfo& paintInfo, const IntRect& rect)
{
    auto& graphicsContext = paintInfo.context();
    GraphicsContextStateSaver stateSaver(graphicsContext);

    ASSERT(renderObject.style().appearance() == SliderThumbHorizontalPart || renderObject.style().appearance() == SliderThumbVerticalPart);

    FloatRect fieldRect = rect;
    Path path;
    path.addEllipse(fieldRect);
    fieldRect.inflate(-sliderThumbBorderSize);
    path.addEllipse(fieldRect);
    graphicsContext.setFillRule(WindRule::EvenOdd);
    if (isEnabled(renderObject) && isPressed(renderObject))
        graphicsContext.setFillColor(activeSelectionBackgroundColor({ }));
    else
        graphicsContext.setFillColor(sliderThumbBorderColor);
    graphicsContext.fillPath(path);
    path.clear();

    path.addEllipse(fieldRect);
    graphicsContext.setFillRule(WindRule::NonZero);
    if (!isEnabled(renderObject))
        graphicsContext.setFillColor(sliderThumbBackgroundDisabledColor);
    else if (isHovered(renderObject))
        graphicsContext.setFillColor(sliderThumbBackgroundHoveredColor);
    else
        graphicsContext.setFillColor(sliderThumbBackgroundColor);
    graphicsContext.fillPath(path);

    return false;
}

#if ENABLE(VIDEO)
static RefPtr<HTMLMediaElement> parentMediaElement(const Node* node)
{
    if (!node)
        return nullptr;
    RefPtr<Node> mediaNode = node->shadowHost();
    if (!mediaNode)
        mediaNode = const_cast<Node*>(node);
    if (!is<HTMLMediaElement>(*mediaNode))
        return nullptr;
    return downcast<HTMLMediaElement>(mediaNode.get());
}

bool RenderThemeAdwaita::paintMediaSliderTrack(const RenderObject& renderObject, const PaintInfo& paintInfo, const IntRect& rect)
{
    auto mediaElement = parentMediaElement(renderObject.node());
    if (!mediaElement)
        return false;

    auto& graphicsContext = paintInfo.context();
    GraphicsContextStateSaver stateSaver(graphicsContext);

    FloatRect trackRect = rect;
    FloatSize corner(2, 2);
    Path path;
    path.addRoundedRect(trackRect, corner);
    graphicsContext.setFillColor(mediaSliderTrackBackgroundcolor);
    graphicsContext.fillPath(path);
    path.clear();

    graphicsContext.setFillColor(mediaSliderTrackBufferedColor);

    float mediaDuration = mediaElement->duration();
    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;

        FloatRect rangeRect = rect;
        rangeRect.setWidth(lengthRatio * rect.width());
        if (index)
            rangeRect.move(startRatio * rect.width(), 0);

        path.addRoundedRect(rangeRect, corner);
        graphicsContext.fillPath(path);
        path.clear();
    }

    FloatRect playedRect = rect;
    playedRect.setWidth((mediaElement->currentTime() / mediaDuration) * rect.width());
    graphicsContext.setFillColor(mediaSliderTrackActiveColor);
    path.addRoundedRect(playedRect, corner);
    graphicsContext.fillPath(path);

    return false;
}

bool RenderThemeAdwaita::paintMediaVolumeSliderTrack(const RenderObject& renderObject, const PaintInfo& paintInfo, const IntRect& rect)
{
    auto mediaElement = parentMediaElement(renderObject.node());
    if (!mediaElement)
        return false;

    auto& graphicsContext = paintInfo.context();
    GraphicsContextStateSaver stateSaver(graphicsContext);

    FloatRect trackRect = rect;
    FloatSize corner(2, 2);
    Path path;
    path.addRoundedRect(trackRect, corner);
    graphicsContext.setFillColor(mediaSliderTrackBackgroundcolor);
    graphicsContext.fillPath(path);
    path.clear();

    float volume = mediaElement->muted() ? 0.0f : mediaElement->volume();
    if (volume) {
        FloatRect volumeRect = rect;
        volumeRect.setHeight(volumeRect.height() * volume);
        volumeRect.move(0, rect.height() - volumeRect.height());
        path.addRoundedRect(volumeRect, corner);
        graphicsContext.setFillColor(mediaSliderTrackActiveColor);
        graphicsContext.fillPath(path);
    }

    return false;
}
#endif // ENABLE(VIDEO)

#if ENABLE(DATALIST_ELEMENT)
IntSize RenderThemeAdwaita::sliderTickSize() const
{
    return { 1, 7 };
}

int RenderThemeAdwaita::sliderTickOffsetFromTrackCenter() const
{
    return -16;
}

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

} // namespace WebCore
