Changeset 217702 in webkit


Ignore:
Timestamp:
Jun 1, 2017 11:40:36 PM (7 years ago)
Author:
Carlos Garcia Campos
Message:

[GTK] Cache RenderThemeGadget hierarchies for rendering themed elements with GTK+ 3.20+
https://bugs.webkit.org/show_bug.cgi?id=162673

Reviewed by Michael Catanzaro.

Because of the way the new theming system works in GTK+ >= 3.20 we are currently creating a gadget hierarchy
every time we need to render a styled element or get layout information about it. That's happening on every
repaint, and it's specially problematic for overlay scrollbar indicators that fade in/out when shown/hidden. We
need to cache the gadgets and simply apply the state before every paint or layout query. When using GtkWidgetPath,
calling gtk_style_context_save() breaks the gadget hierarchy, and style classes need to be set when building the
GtkWidgetPath. That means we can't cache RenderThemeGadgets, call save, apply style classes and state, and then
call restore. We need to cache gadget hierarchies with fixed style classes. Fortunately, setting the state does
work, so we don't need to also cache a different hierarchy for every possible state. For example, for the
particular case of scrollbars we would cache VerticalScrollbarRight, VerticalScrollbarLeft, HorizontalScrollbar,
VerticalScrollIndicatorRight, VerticalScrollIndicatorLeft and HorizontalScrollIndicator. In practice, we will
only have 4 of those at the same time in the cache.
This patch adds RenderThemeWidget to represent a hierarchy of gadgets with fixed style classes that can be
cached and reused to render or query style of those "widgets". It also simplifies the RenderThemeGtk and
ScrollbarThemeGtk code by removing a lot of duplicated code to build the gadget hierarchies.

  • PlatformGTK.cmake:
  • platform/gtk/RenderThemeGadget.cpp:

(WebCore::createStyleContext):
(WebCore::appendElementToPath):
(WebCore::RenderThemeGadget::state):
(WebCore::RenderThemeGadget::setState):

  • platform/gtk/RenderThemeGadget.h:
  • platform/gtk/RenderThemeWidget.cpp: Added.

(WebCore::widgetMap):
(WebCore::RenderThemeWidget::getOrCreate):
(WebCore::RenderThemeWidget::clearCache):
(WebCore::RenderThemeWidget::~RenderThemeWidget):
(WebCore::RenderThemeScrollbar::RenderThemeScrollbar):
(WebCore::RenderThemeScrollbar::stepper):
(WebCore::RenderThemeToggleButton::RenderThemeToggleButton):
(WebCore::RenderThemeButton::RenderThemeButton):
(WebCore::RenderThemeComboBox::RenderThemeComboBox):
(WebCore::RenderThemeEntry::RenderThemeEntry):
(WebCore::RenderThemeSearchEntry::RenderThemeSearchEntry):
(WebCore::RenderThemeSpinButton::RenderThemeSpinButton):
(WebCore::RenderThemeSlider::RenderThemeSlider):
(WebCore::RenderThemeProgressBar::RenderThemeProgressBar):
(WebCore::RenderThemeListView::RenderThemeListView):
(WebCore::RenderThemeIcon::RenderThemeIcon):

  • platform/gtk/RenderThemeWidget.h: Added.

(WebCore::RenderThemeEntry::entry):
(WebCore::RenderThemeEntry::selection):

  • platform/gtk/ScrollbarThemeGtk.cpp:

(WebCore::ScrollbarThemeGtk::themeChanged):
(WebCore::ScrollbarThemeGtk::updateThemeProperties):
(WebCore::widgetTypeForScrollbar):
(WebCore::contentsRectangle):
(WebCore::ScrollbarThemeGtk::trackRect):
(WebCore::ScrollbarThemeGtk::backButtonRect):
(WebCore::ScrollbarThemeGtk::forwardButtonRect):
(WebCore::ScrollbarThemeGtk::paint):
(WebCore::ScrollbarThemeGtk::scrollbarThickness):
(WebCore::ScrollbarThemeGtk::minimumThumbLength):

  • rendering/RenderThemeGtk.cpp:

(WebCore::createStyleContext):
(WebCore::setToggleSize):
(WebCore::paintToggle):
(WebCore::RenderThemeGtk::paintButton):
(WebCore::menuListColor):
(WebCore::RenderThemeGtk::popupInternalPaddingBox):
(WebCore::RenderThemeGtk::paintMenuList):
(WebCore::RenderThemeGtk::adjustTextFieldStyle):
(WebCore::RenderThemeGtk::paintTextField):
(WebCore::adjustSearchFieldIconStyle):
(WebCore::paintSearchFieldIcon):
(WebCore::RenderThemeGtk::paintSliderTrack):
(WebCore::RenderThemeGtk::adjustSliderThumbSize):
(WebCore::RenderThemeGtk::paintSliderThumb):
(WebCore::RenderThemeGtk::progressBarRectForBounds):
(WebCore::RenderThemeGtk::paintProgressBar):
(WebCore::RenderThemeGtk::adjustInnerSpinButtonStyle):
(WebCore::RenderThemeGtk::paintInnerSpinButton):
(WebCore::styleColor):
(WebCore::RenderThemeGtk::platformActiveSelectionBackgroundColor):
(WebCore::RenderThemeGtk::platformInactiveSelectionBackgroundColor):
(WebCore::RenderThemeGtk::platformActiveSelectionForegroundColor):
(WebCore::RenderThemeGtk::platformInactiveSelectionForegroundColor):
(WebCore::RenderThemeGtk::paintMediaButton):

Location:
trunk/Source/WebCore
Files:
2 added
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r217696 r217702  
     12017-06-01  Carlos Garcia Campos  <cgarcia@igalia.com>
     2
     3        [GTK] Cache RenderThemeGadget hierarchies for rendering themed elements with GTK+ 3.20+
     4        https://bugs.webkit.org/show_bug.cgi?id=162673
     5
     6        Reviewed by Michael Catanzaro.
     7
     8        Because of the way the new theming system works in GTK+ >= 3.20 we are currently creating a gadget hierarchy
     9        every time we need to render a styled element or get layout information about it. That's happening on every
     10        repaint, and it's specially problematic for overlay scrollbar indicators that fade in/out when shown/hidden. We
     11        need to cache the gadgets and simply apply the state before every paint or layout query. When using GtkWidgetPath,
     12        calling gtk_style_context_save() breaks the gadget hierarchy, and style classes need to be set when building the
     13        GtkWidgetPath. That means we can't cache RenderThemeGadgets, call save, apply style classes and state, and then
     14        call restore. We need to cache gadget hierarchies with fixed style classes. Fortunately, setting the state does
     15        work, so we don't need to also cache a different hierarchy for every possible state. For example, for the
     16        particular case of scrollbars we would cache VerticalScrollbarRight, VerticalScrollbarLeft, HorizontalScrollbar,
     17        VerticalScrollIndicatorRight, VerticalScrollIndicatorLeft and HorizontalScrollIndicator. In practice, we will
     18        only have 4 of those at the same time in the cache.
     19        This patch adds RenderThemeWidget to represent a hierarchy of gadgets with fixed style classes that can be
     20        cached and reused to render or query style of those "widgets". It also simplifies the RenderThemeGtk and
     21        ScrollbarThemeGtk code by removing a lot of duplicated code to build the gadget hierarchies.
     22
     23        * PlatformGTK.cmake:
     24        * platform/gtk/RenderThemeGadget.cpp:
     25        (WebCore::createStyleContext):
     26        (WebCore::appendElementToPath):
     27        (WebCore::RenderThemeGadget::state):
     28        (WebCore::RenderThemeGadget::setState):
     29        * platform/gtk/RenderThemeGadget.h:
     30        * platform/gtk/RenderThemeWidget.cpp: Added.
     31        (WebCore::widgetMap):
     32        (WebCore::RenderThemeWidget::getOrCreate):
     33        (WebCore::RenderThemeWidget::clearCache):
     34        (WebCore::RenderThemeWidget::~RenderThemeWidget):
     35        (WebCore::RenderThemeScrollbar::RenderThemeScrollbar):
     36        (WebCore::RenderThemeScrollbar::stepper):
     37        (WebCore::RenderThemeToggleButton::RenderThemeToggleButton):
     38        (WebCore::RenderThemeButton::RenderThemeButton):
     39        (WebCore::RenderThemeComboBox::RenderThemeComboBox):
     40        (WebCore::RenderThemeEntry::RenderThemeEntry):
     41        (WebCore::RenderThemeSearchEntry::RenderThemeSearchEntry):
     42        (WebCore::RenderThemeSpinButton::RenderThemeSpinButton):
     43        (WebCore::RenderThemeSlider::RenderThemeSlider):
     44        (WebCore::RenderThemeProgressBar::RenderThemeProgressBar):
     45        (WebCore::RenderThemeListView::RenderThemeListView):
     46        (WebCore::RenderThemeIcon::RenderThemeIcon):
     47        * platform/gtk/RenderThemeWidget.h: Added.
     48        (WebCore::RenderThemeEntry::entry):
     49        (WebCore::RenderThemeEntry::selection):
     50        * platform/gtk/ScrollbarThemeGtk.cpp:
     51        (WebCore::ScrollbarThemeGtk::themeChanged):
     52        (WebCore::ScrollbarThemeGtk::updateThemeProperties):
     53        (WebCore::widgetTypeForScrollbar):
     54        (WebCore::contentsRectangle):
     55        (WebCore::ScrollbarThemeGtk::trackRect):
     56        (WebCore::ScrollbarThemeGtk::backButtonRect):
     57        (WebCore::ScrollbarThemeGtk::forwardButtonRect):
     58        (WebCore::ScrollbarThemeGtk::paint):
     59        (WebCore::ScrollbarThemeGtk::scrollbarThickness):
     60        (WebCore::ScrollbarThemeGtk::minimumThumbLength):
     61        * rendering/RenderThemeGtk.cpp:
     62        (WebCore::createStyleContext):
     63        (WebCore::setToggleSize):
     64        (WebCore::paintToggle):
     65        (WebCore::RenderThemeGtk::paintButton):
     66        (WebCore::menuListColor):
     67        (WebCore::RenderThemeGtk::popupInternalPaddingBox):
     68        (WebCore::RenderThemeGtk::paintMenuList):
     69        (WebCore::RenderThemeGtk::adjustTextFieldStyle):
     70        (WebCore::RenderThemeGtk::paintTextField):
     71        (WebCore::adjustSearchFieldIconStyle):
     72        (WebCore::paintSearchFieldIcon):
     73        (WebCore::RenderThemeGtk::paintSliderTrack):
     74        (WebCore::RenderThemeGtk::adjustSliderThumbSize):
     75        (WebCore::RenderThemeGtk::paintSliderThumb):
     76        (WebCore::RenderThemeGtk::progressBarRectForBounds):
     77        (WebCore::RenderThemeGtk::paintProgressBar):
     78        (WebCore::RenderThemeGtk::adjustInnerSpinButtonStyle):
     79        (WebCore::RenderThemeGtk::paintInnerSpinButton):
     80        (WebCore::styleColor):
     81        (WebCore::RenderThemeGtk::platformActiveSelectionBackgroundColor):
     82        (WebCore::RenderThemeGtk::platformInactiveSelectionBackgroundColor):
     83        (WebCore::RenderThemeGtk::platformActiveSelectionForegroundColor):
     84        (WebCore::RenderThemeGtk::platformInactiveSelectionForegroundColor):
     85        (WebCore::RenderThemeGtk::paintMediaButton):
     86
    1872017-06-01  Andreas Kling  <akling@apple.com>
    288
  • trunk/Source/WebCore/PlatformGTK.cmake

    r217508 r217702  
    174174    platform/gtk/PlatformWheelEventGtk.cpp
    175175    platform/gtk/RenderThemeGadget.cpp
     176    platform/gtk/RenderThemeWidget.cpp
    176177    platform/gtk/ScrollbarThemeGtk.cpp
    177178    platform/gtk/SoundGtk.cpp
  • trunk/Source/WebCore/platform/gtk/RenderThemeGadget.cpp

    r200173 r217702  
    6161    gtk_style_context_set_path(context.get(), path);
    6262    gtk_style_context_set_parent(context.get(), parent);
    63     // Unfortunately, we have to explicitly set the state again here for it to take effect.
    64     gtk_style_context_set_state(context.get(), gtk_widget_path_iter_get_state(path, -1));
    6563    return context;
    6664}
     
    7371    for (const auto* className : info.classList)
    7472        gtk_widget_path_iter_add_class(path, -1, className);
    75     gtk_widget_path_iter_set_state(path, -1, static_cast<GtkStateFlags>(gtk_widget_path_iter_get_state(path, -1) | info.state));
    7673}
    7774
     
    145142    gtk_style_context_get(m_context.get(), gtk_style_context_get_state(m_context.get()), "opacity", &returnValue, nullptr);
    146143    return returnValue;
     144}
     145
     146GtkStateFlags RenderThemeGadget::state() const
     147{
     148    return gtk_style_context_get_state(m_context.get());
     149}
     150
     151void RenderThemeGadget::setState(GtkStateFlags state)
     152{
     153    gtk_style_context_set_state(m_context.get(), state);
    147154}
    148155
  • trunk/Source/WebCore/platform/gtk/RenderThemeGadget.h

    r200173 r217702  
    5757        Type type;
    5858        const char* name;
    59         GtkStateFlags state;
    6059        Vector<const char*> classList;
    6160    };
     
    7776
    7877    GtkStyleContext* context() const { return m_context.get(); }
     78
     79    GtkStateFlags state() const;
     80    void setState(GtkStateFlags);
    7981
    8082protected:
  • trunk/Source/WebCore/platform/gtk/ScrollbarThemeGtk.cpp

    r215566 r217702  
    3131#include "PlatformContextCairo.h"
    3232#include "PlatformMouseEvent.h"
    33 #include "RenderThemeGadget.h"
     33#include "RenderThemeWidget.h"
    3434#include "ScrollView.h"
    3535#include "Scrollbar.h"
     
    9797void ScrollbarThemeGtk::themeChanged()
    9898{
     99#if GTK_CHECK_VERSION(3, 20, 0)
     100    RenderThemeWidget::clearCache();
     101#endif
    99102    updateThemeProperties();
    100103}
     
    103106void ScrollbarThemeGtk::updateThemeProperties()
    104107{
    105     auto steppers = static_cast<RenderThemeScrollbarGadget*>(RenderThemeGadget::create({ RenderThemeGadget::Type::Scrollbar, "scrollbar", GTK_STATE_FLAG_NORMAL, { } }).get())->steppers();
    106     m_hasBackButtonStartPart = steppers.contains(RenderThemeScrollbarGadget::Steppers::Backward);
    107     m_hasForwardButtonEndPart = steppers.contains(RenderThemeScrollbarGadget::Steppers::Forward);
    108     m_hasBackButtonEndPart = steppers.contains(RenderThemeScrollbarGadget::Steppers::SecondaryBackward);
    109     m_hasForwardButtonStartPart = steppers.contains(RenderThemeScrollbarGadget::Steppers::SecondaryForward);
     108    auto& scrollbar = static_cast<RenderThemeScrollbar&>(RenderThemeWidget::getOrCreate(RenderThemeWidget::Type::VerticalScrollbarRight));
     109    m_hasBackButtonStartPart = scrollbar.stepper(RenderThemeScrollbarGadget::Steppers::Backward);
     110    m_hasForwardButtonEndPart = scrollbar.stepper(RenderThemeScrollbarGadget::Steppers::Forward);
     111    m_hasBackButtonEndPart = scrollbar.stepper(RenderThemeScrollbarGadget::Steppers::SecondaryBackward);
     112    m_hasForwardButtonStartPart = scrollbar.stepper(RenderThemeScrollbarGadget::Steppers::SecondaryForward);
    110113}
    111114#else
     
    169172}
    170173
    171 static std::unique_ptr<RenderThemeGadget> scrollbarGadgetForLayout(Scrollbar& scrollbar)
    172 {
    173     RenderThemeGadget::Info info = { RenderThemeGadget::Type::Scrollbar, "scrollbar", scrollbarPartStateFlags(scrollbar, AllParts), { } };
     174static RenderThemeWidget::Type widgetTypeForScrollbar(Scrollbar& scrollbar, GtkStateFlags scrollbarState)
     175{
    174176    if (scrollbar.orientation() == VerticalScrollbar) {
    175         info.classList.append("vertical");
    176         info.classList.append("right");
    177     } else {
    178         info.classList.append("horizontal");
    179         info.classList.append("bottom");
    180     }
    181     if (scrollbar.isOverlayScrollbar())
    182         info.classList.append("overlay-indicator");
    183     if (info.state & GTK_STATE_FLAG_PRELIGHT)
    184         info.classList.append("hovering");
    185 
    186     return RenderThemeGadget::create(info);
    187 }
    188 
    189 static std::unique_ptr<RenderThemeBoxGadget> contentsGadgetForLayout(Scrollbar& scrollbar, RenderThemeGadget* parent, IntRect& contentsRect, Vector<int, 4>& steppersPosition)
    190 {
    191     Vector<RenderThemeGadget::Info> children;
    192     auto steppers = static_cast<RenderThemeScrollbarGadget*>(parent)->steppers();
    193     if (steppers.contains(RenderThemeScrollbarGadget::Steppers::Backward)) {
    194         steppersPosition[0] = 0;
    195         children.append({ RenderThemeGadget::Type::Generic, "button", scrollbarPartStateFlags(scrollbar, BackButtonStartPart), { "up" } });
    196     }
    197     if (steppers.contains(RenderThemeScrollbarGadget::Steppers::SecondaryForward)) {
    198         steppersPosition[1] = children.size();
    199         children.append({ RenderThemeGadget::Type::Generic, "button", scrollbarPartStateFlags(scrollbar, ForwardButtonStartPart), { "down" } });
    200     }
    201     children.append({ RenderThemeGadget::Type::Generic, "trough", scrollbarPartStateFlags(scrollbar, BackTrackPart), { } });
    202     if (steppers.contains(RenderThemeScrollbarGadget::Steppers::SecondaryBackward)) {
    203         steppersPosition[2] = children.size();
    204         children.append({ RenderThemeGadget::Type::Generic, "button", scrollbarPartStateFlags(scrollbar, BackButtonEndPart), { "up" } });
    205     }
    206     if (steppers.contains(RenderThemeScrollbarGadget::Steppers::Forward)) {
    207         steppersPosition[3] = children.size();
    208         children.append({ RenderThemeGadget::Type::Generic, "button", scrollbarPartStateFlags(scrollbar, ForwardButtonEndPart), { "down" } });
    209     }
    210     RenderThemeGadget::Info info = { RenderThemeGadget::Type::Generic, "contents", GTK_STATE_FLAG_NORMAL, { } };
    211     auto contentsGadget = std::make_unique<RenderThemeBoxGadget>(info, scrollbar.orientation() == VerticalScrollbar ? GTK_ORIENTATION_VERTICAL : GTK_ORIENTATION_HORIZONTAL,
    212         children, parent);
    213 
    214     GtkBorder scrollbarContentsBox = parent->contentsBox();
    215     GtkBorder contentsContentsBox = contentsGadget->contentsBox();
     177        if (scrollbar.scrollableArea().shouldPlaceBlockDirectionScrollbarOnLeft())
     178            return scrollbarState & GTK_STATE_FLAG_PRELIGHT ? RenderThemeWidget::Type::VerticalScrollbarLeft : RenderThemeWidget::Type::VerticalScrollIndicatorLeft;
     179        return scrollbarState & GTK_STATE_FLAG_PRELIGHT ? RenderThemeWidget::Type::VerticalScrollbarRight : RenderThemeWidget::Type::VerticalScrollIndicatorRight;
     180    }
     181    return scrollbarState & GTK_STATE_FLAG_PRELIGHT ? RenderThemeWidget::Type::HorizontalScrollbar : RenderThemeWidget::Type::HorizontalScrollIndicator;
     182}
     183
     184static IntRect contentsRectangle(Scrollbar& scrollbar, RenderThemeScrollbar& scrollbarWidget)
     185{
     186    GtkBorder scrollbarContentsBox = scrollbarWidget.scrollbar().contentsBox();
     187    GtkBorder contentsContentsBox = scrollbarWidget.contents().contentsBox();
    216188    GtkBorder padding;
    217189    padding.left = scrollbarContentsBox.left + contentsContentsBox.left;
     
    219191    padding.top = scrollbarContentsBox.top + contentsContentsBox.top;
    220192    padding.bottom = scrollbarContentsBox.bottom + contentsContentsBox.bottom;
    221     contentsRect = scrollbar.frameRect();
     193    IntRect contentsRect = scrollbar.frameRect();
    222194    contentsRect.move(padding.left, padding.top);
    223195    contentsRect.contract(padding.left + padding.right, padding.top + padding.bottom);
    224     return contentsGadget;
     196    return contentsRect;
    225197}
    226198
    227199IntRect ScrollbarThemeGtk::trackRect(Scrollbar& scrollbar, bool /*painting*/)
    228200{
    229     auto scrollbarGadget = scrollbarGadgetForLayout(scrollbar);
    230     IntRect rect;
    231     Vector<int, 4> steppersPosition(4, -1);
    232     auto contentsGadget = contentsGadgetForLayout(scrollbar, scrollbarGadget.get(), rect, steppersPosition);
    233 
    234     if (steppersPosition[0] != -1) {
    235         IntSize stepperSize = contentsGadget->child(steppersPosition[0])->preferredSize();
     201    auto scrollbarState = scrollbarPartStateFlags(scrollbar, AllParts);
     202    auto& scrollbarWidget = static_cast<RenderThemeScrollbar&>(RenderThemeWidget::getOrCreate(widgetTypeForScrollbar(scrollbar, scrollbarState)));
     203    scrollbarWidget.scrollbar().setState(scrollbarState);
     204
     205    IntRect rect = contentsRectangle(scrollbar, scrollbarWidget);
     206    if (auto* backwardStepper = scrollbarWidget.stepper(RenderThemeScrollbarGadget::Steppers::Backward)) {
     207        backwardStepper->setState(scrollbarPartStateFlags(scrollbar, BackButtonStartPart));
     208        IntSize stepperSize = backwardStepper->preferredSize();
    236209        if (scrollbar.orientation() == VerticalScrollbar) {
    237210            rect.move(0, stepperSize.height());
     
    242215        }
    243216    }
    244     if (steppersPosition[1] != -1) {
    245         IntSize stepperSize = contentsGadget->child(steppersPosition[1])->preferredSize();
     217    if (auto* secondaryForwardStepper = scrollbarWidget.stepper(RenderThemeScrollbarGadget::Steppers::SecondaryForward)) {
     218        secondaryForwardStepper->setState(scrollbarPartStateFlags(scrollbar, ForwardButtonStartPart));
     219        IntSize stepperSize = secondaryForwardStepper->preferredSize();
    246220        if (scrollbar.orientation() == VerticalScrollbar) {
    247221            rect.move(0, stepperSize.height());
     
    252226        }
    253227    }
    254     if (steppersPosition[2] != -1) {
     228    if (auto* secondaryBackwardStepper = scrollbarWidget.stepper(RenderThemeScrollbarGadget::Steppers::SecondaryBackward)) {
     229        secondaryBackwardStepper->setState(scrollbarPartStateFlags(scrollbar, BackButtonEndPart));
    255230        if (scrollbar.orientation() == VerticalScrollbar)
    256             rect.contract(0, contentsGadget->child(steppersPosition[2])->preferredSize().height());
     231            rect.contract(0, secondaryBackwardStepper->preferredSize().height());
    257232        else
    258             rect.contract(contentsGadget->child(steppersPosition[2])->preferredSize().width(), 0);
    259     }
    260     if (steppersPosition[3] != -1) {
     233            rect.contract(secondaryBackwardStepper->preferredSize().width(), 0);
     234    }
     235    if (auto* forwardStepper = scrollbarWidget.stepper(RenderThemeScrollbarGadget::Steppers::Forward)) {
     236        forwardStepper->setState(scrollbarPartStateFlags(scrollbar, ForwardButtonEndPart));
    261237        if (scrollbar.orientation() == VerticalScrollbar)
    262             rect.contract(0, contentsGadget->child(steppersPosition[3])->preferredSize().height());
     238            rect.contract(0, forwardStepper->preferredSize().height());
    263239        else
    264             rect.contract(contentsGadget->child(steppersPosition[3])->preferredSize().width(), 0);
     240            rect.contract(forwardStepper->preferredSize().width(), 0);
    265241    }
    266242
     
    328304        return IntRect();
    329305
    330     auto scrollbarGadget = scrollbarGadgetForLayout(scrollbar);
    331     IntRect rect;
    332     Vector<int, 4> steppersPosition(4, -1);
    333     auto contentsGadget = contentsGadgetForLayout(scrollbar, scrollbarGadget.get(), rect, steppersPosition);
    334 
    335     if (part == BackButtonStartPart)
    336         return IntRect(rect.location(), contentsGadget->child(0)->preferredSize());
    337 
    338     // Secondary back.
    339     if (steppersPosition[1] != -1) {
    340         IntSize preferredSize = contentsGadget->child(steppersPosition[1])->preferredSize();
     306    auto scrollbarState = scrollbarPartStateFlags(scrollbar, AllParts);
     307    auto& scrollbarWidget = static_cast<RenderThemeScrollbar&>(RenderThemeWidget::getOrCreate(widgetTypeForScrollbar(scrollbar, scrollbarState)));
     308    scrollbarWidget.scrollbar().setState(scrollbarState);
     309
     310    IntRect rect = contentsRectangle(scrollbar, scrollbarWidget);
     311    if (part == BackButtonStartPart) {
     312        auto* backwardStepper = scrollbarWidget.stepper(RenderThemeScrollbarGadget::Steppers::Backward);
     313        ASSERT(backwardStepper);
     314        backwardStepper->setState(scrollbarPartStateFlags(scrollbar, BackButtonStartPart));
     315        return IntRect(rect.location(), backwardStepper->preferredSize());
     316    }
     317
     318    if (auto* secondaryForwardStepper = scrollbarWidget.stepper(RenderThemeScrollbarGadget::Steppers::SecondaryForward)) {
     319        secondaryForwardStepper->setState(scrollbarPartStateFlags(scrollbar, ForwardButtonStartPart));
     320        IntSize preferredSize = secondaryForwardStepper->preferredSize();
    341321        if (scrollbar.orientation() == VerticalScrollbar) {
    342322            rect.move(0, preferredSize.height());
     
    348328    }
    349329
    350     if (steppersPosition[3] != -1) {
     330    if (auto* secondaryBackwardStepper = scrollbarWidget.stepper(RenderThemeScrollbarGadget::Steppers::SecondaryBackward)) {
     331        secondaryBackwardStepper->setState(scrollbarPartStateFlags(scrollbar, BackButtonEndPart));
    351332        if (scrollbar.orientation() == VerticalScrollbar)
    352             rect.contract(0, contentsGadget->child(steppersPosition[3])->preferredSize().height());
     333            rect.contract(0, secondaryBackwardStepper->preferredSize().height());
    353334        else
    354             rect.contract(contentsGadget->child(steppersPosition[3])->preferredSize().width(), 0);
    355     }
    356 
    357     IntSize preferredSize = contentsGadget->child(steppersPosition[2])->preferredSize();
     335            rect.contract(secondaryBackwardStepper->preferredSize().width(), 0);
     336    }
     337
     338    auto* forwardStepper = scrollbarWidget.stepper(RenderThemeScrollbarGadget::Steppers::Forward);
     339    ASSERT(forwardStepper);
     340    forwardStepper->setState(scrollbarPartStateFlags(scrollbar, ForwardButtonEndPart));
     341    IntSize preferredSize = forwardStepper->preferredSize();
    358342    if (scrollbar.orientation() == VerticalScrollbar)
    359343        rect.move(0, rect.height() - preferredSize.height());
     
    370354        return IntRect();
    371355
    372     auto scrollbarGadget = scrollbarGadgetForLayout(scrollbar);
    373     IntRect rect;
    374     Vector<int, 4> steppersPosition(4, -1);
    375     auto contentsGadget = contentsGadgetForLayout(scrollbar, scrollbarGadget.get(), rect, steppersPosition);
    376 
    377     if (steppersPosition[0] != -1) {
    378         IntSize preferredSize = contentsGadget->child(steppersPosition[0])->preferredSize();
     356    auto scrollbarState = scrollbarPartStateFlags(scrollbar, AllParts);
     357    auto& scrollbarWidget = static_cast<RenderThemeScrollbar&>(RenderThemeWidget::getOrCreate(widgetTypeForScrollbar(scrollbar, scrollbarState)));
     358    scrollbarWidget.scrollbar().setState(scrollbarState);
     359
     360    IntRect rect = contentsRectangle(scrollbar, scrollbarWidget);
     361    if (auto* backwardStepper = scrollbarWidget.stepper(RenderThemeScrollbarGadget::Steppers::Backward)) {
     362        backwardStepper->setState(scrollbarPartStateFlags(scrollbar, BackButtonStartPart));
     363        IntSize preferredSize = backwardStepper->preferredSize();
    379364        if (scrollbar.orientation() == VerticalScrollbar) {
    380365            rect.move(0, preferredSize.height());
     
    386371    }
    387372
    388     if (steppersPosition[1] != -1) {
    389         IntSize preferredSize = contentsGadget->child(steppersPosition[1])->preferredSize();
     373    if (auto* secondaryForwardStepper = scrollbarWidget.stepper(RenderThemeScrollbarGadget::Steppers::SecondaryForward)) {
     374        secondaryForwardStepper->setState(scrollbarPartStateFlags(scrollbar, ForwardButtonStartPart));
     375        IntSize preferredSize = secondaryForwardStepper->preferredSize();
    390376        if (part == ForwardButtonStartPart)
    391377            return IntRect(rect.location(), preferredSize);
     
    400386    }
    401387
    402     // Forward button.
    403     IntSize preferredSize = contentsGadget->child(steppersPosition[3])->preferredSize();
     388    auto* forwardStepper = scrollbarWidget.stepper(RenderThemeScrollbarGadget::Steppers::Forward);
     389    ASSERT(forwardStepper);
     390    forwardStepper->setState(scrollbarPartStateFlags(scrollbar, ForwardButtonEndPart));
     391    IntSize preferredSize = forwardStepper->preferredSize();
    404392    if (scrollbar.orientation() == VerticalScrollbar)
    405393        rect.move(0, rect.height() - preferredSize.height());
     
    478466        return true;
    479467
    480     bool scrollbarOnLeft = scrollbar.scrollableArea().shouldPlaceBlockDirectionScrollbarOnLeft();
    481 
    482     RenderThemeGadget::Info info = { RenderThemeGadget::Type::Scrollbar, "scrollbar", scrollbarPartStateFlags(scrollbar, AllParts, true), { } };
    483     if (scrollbar.orientation() == VerticalScrollbar) {
    484         info.classList.append("vertical");
    485         info.classList.append(scrollbarOnLeft ? "left" : "right");
    486     } else {
    487         info.classList.append("horizontal");
    488         info.classList.append("bottom");
    489     }
     468    auto scrollbarState = scrollbarPartStateFlags(scrollbar, AllParts, true);
     469    auto& scrollbarWidget = static_cast<RenderThemeScrollbar&>(RenderThemeWidget::getOrCreate(widgetTypeForScrollbar(scrollbar, scrollbarState)));
     470    auto& scrollbarGadget = scrollbarWidget.scrollbar();
     471    scrollbarGadget.setState(scrollbarState);
    490472    if (m_usesOverlayScrollbars)
    491         info.classList.append("overlay-indicator");
    492     if (info.state & GTK_STATE_FLAG_PRELIGHT)
    493         info.classList.append("hovering");
    494     if (scrollbar.pressedPart() != NoPart)
    495         info.classList.append("dragging");
    496     auto scrollbarGadget = RenderThemeGadget::create(info);
    497     if (m_usesOverlayScrollbars)
    498         opacity *= scrollbarGadget->opacity();
     473        opacity *= scrollbarGadget.opacity();
    499474    if (!opacity)
    500475        return true;
    501476
    502     info.type = RenderThemeGadget::Type::Generic;
    503     info.name = "contents";
    504     info.state = GTK_STATE_FLAG_NORMAL;
    505     info.classList.clear();
    506     Vector<RenderThemeGadget::Info> children;
    507     auto steppers = static_cast<RenderThemeScrollbarGadget*>(scrollbarGadget.get())->steppers();
    508     unsigned steppersPosition[4] = { 0, 0, 0, 0 };
    509     if (steppers.contains(RenderThemeScrollbarGadget::Steppers::Backward)) {
    510         steppersPosition[0] = children.size();
    511         children.append({ RenderThemeGadget::Type::Generic, "button", scrollbarPartStateFlags(scrollbar, BackButtonStartPart), { "up" } });
    512     }
    513     if (steppers.contains(RenderThemeScrollbarGadget::Steppers::SecondaryForward)) {
    514         steppersPosition[1] = children.size();
    515         children.append({ RenderThemeGadget::Type::Generic, "button", scrollbarPartStateFlags(scrollbar, ForwardButtonStartPart), { "down" } });
    516     }
    517     unsigned troughPosition = children.size();
    518     children.append({ RenderThemeGadget::Type::Generic, "trough", scrollbarPartStateFlags(scrollbar, BackTrackPart), { } });
    519     if (steppers.contains(RenderThemeScrollbarGadget::Steppers::SecondaryBackward)) {
    520         steppersPosition[2] = children.size();
    521         children.append({ RenderThemeGadget::Type::Generic, "button", scrollbarPartStateFlags(scrollbar, BackButtonEndPart), { "up" } });
    522     }
    523     if (steppers.contains(RenderThemeScrollbarGadget::Steppers::Forward)) {
    524         steppersPosition[3] = children.size();
    525         children.append({ RenderThemeGadget::Type::Generic, "button", scrollbarPartStateFlags(scrollbar, ForwardButtonEndPart), { "down" } });
    526     }
    527     auto contentsGadget = std::make_unique<RenderThemeBoxGadget>(info, scrollbar.orientation() == VerticalScrollbar ? GTK_ORIENTATION_VERTICAL : GTK_ORIENTATION_HORIZONTAL,
    528         children, scrollbarGadget.get());
    529     RenderThemeGadget* troughGadget = contentsGadget->child(troughPosition);
    530 
    531     IntSize preferredSize = contentsGadget->preferredSize();
    532     std::unique_ptr<RenderThemeGadget> sliderGadget;
     477    auto& trough = scrollbarWidget.trough();
     478    trough.setState(scrollbarPartStateFlags(scrollbar, BackTrackPart));
     479
     480    auto* backwardStepper = scrollbarWidget.stepper(RenderThemeScrollbarGadget::Steppers::Backward);
     481    if (backwardStepper)
     482        backwardStepper->setState(scrollbarPartStateFlags(scrollbar, BackButtonStartPart));
     483    auto* secondaryForwardStepper = scrollbarWidget.stepper(RenderThemeScrollbarGadget::Steppers::SecondaryForward);
     484    if (secondaryForwardStepper)
     485        secondaryForwardStepper->setState(scrollbarPartStateFlags(scrollbar, ForwardButtonStartPart));
     486    auto* secondaryBackwardStepper = scrollbarWidget.stepper(RenderThemeScrollbarGadget::Steppers::SecondaryBackward);
     487    if (secondaryBackwardStepper)
     488        secondaryBackwardStepper->setState(scrollbarPartStateFlags(scrollbar, BackButtonEndPart));
     489    auto* forwardStepper = scrollbarWidget.stepper(RenderThemeScrollbarGadget::Steppers::Forward);
     490    if (forwardStepper)
     491        forwardStepper->setState(scrollbarPartStateFlags(scrollbar, ForwardButtonEndPart));
     492
     493    IntSize preferredSize = scrollbarWidget.contents().preferredSize();
    533494    int thumbSize = thumbLength(scrollbar);
    534495    if (thumbSize) {
    535         info.name = "slider";
    536         info.state = scrollbarPartStateFlags(scrollbar, ThumbPart);
    537         sliderGadget = RenderThemeGadget::create(info, troughGadget);
    538         preferredSize = preferredSize.expandedTo(sliderGadget->preferredSize());
    539     }
    540     preferredSize += scrollbarGadget->preferredSize() - scrollbarGadget->minimumSize();
     496        scrollbarWidget.slider().setState(scrollbarPartStateFlags(scrollbar, ThumbPart));
     497        preferredSize = preferredSize.expandedTo(scrollbarWidget.slider().preferredSize());
     498    }
     499    preferredSize += scrollbarGadget.preferredSize() - scrollbarGadget.minimumSize();
    541500
    542501    FloatRect contentsRect(rect);
     
    545504    if (scrollbar.orientation() == VerticalScrollbar) {
    546505        if (rect.width() != preferredSize.width()) {
    547             if (!scrollbarOnLeft)
     506            if (!scrollbar.scrollableArea().shouldPlaceBlockDirectionScrollbarOnLeft())
    548507                contentsRect.move(std::abs(rect.width() - preferredSize.width()), 0);
    549508            contentsRect.setWidth(preferredSize.width());
     
    562521    }
    563522
    564     scrollbarGadget->render(graphicsContext.platformContext()->cr(), contentsRect, &contentsRect);
    565     contentsGadget->render(graphicsContext.platformContext()->cr(), contentsRect, &contentsRect);
    566 
    567     if (steppers.contains(RenderThemeScrollbarGadget::Steppers::Backward)) {
    568         RenderThemeGadget* buttonGadget = contentsGadget->child(steppersPosition[0]);
     523    scrollbarGadget.render(graphicsContext.platformContext()->cr(), contentsRect, &contentsRect);
     524    scrollbarWidget.contents().render(graphicsContext.platformContext()->cr(), contentsRect, &contentsRect);
     525
     526    if (backwardStepper) {
    569527        FloatRect buttonRect = contentsRect;
    570528        if (scrollbar.orientation() == VerticalScrollbar)
    571             buttonRect.setHeight(buttonGadget->preferredSize().height());
     529            buttonRect.setHeight(backwardStepper->preferredSize().height());
    572530        else
    573             buttonRect.setWidth(buttonGadget->preferredSize().width());
    574         static_cast<RenderThemeScrollbarGadget*>(scrollbarGadget.get())->renderStepper(graphicsContext.platformContext()->cr(), buttonRect, buttonGadget,
     531            buttonRect.setWidth(backwardStepper->preferredSize().width());
     532        static_cast<RenderThemeScrollbarGadget&>(scrollbarGadget).renderStepper(graphicsContext.platformContext()->cr(), buttonRect, backwardStepper,
    575533            scrollbar.orientation() == VerticalScrollbar ? GTK_ORIENTATION_VERTICAL : GTK_ORIENTATION_HORIZONTAL, RenderThemeScrollbarGadget::Steppers::Backward);
    576534        if (scrollbar.orientation() == VerticalScrollbar) {
     
    582540        }
    583541    }
    584     if (steppers.contains(RenderThemeScrollbarGadget::Steppers::SecondaryForward)) {
    585         RenderThemeGadget* buttonGadget = contentsGadget->child(steppersPosition[1]);
     542    if (secondaryForwardStepper) {
    586543        FloatRect buttonRect = contentsRect;
    587544        if (scrollbar.orientation() == VerticalScrollbar)
    588             buttonRect.setHeight(buttonGadget->preferredSize().height());
     545            buttonRect.setHeight(secondaryForwardStepper->preferredSize().height());
    589546        else
    590             buttonRect.setWidth(buttonGadget->preferredSize().width());
    591         static_cast<RenderThemeScrollbarGadget*>(scrollbarGadget.get())->renderStepper(graphicsContext.platformContext()->cr(), buttonRect, buttonGadget,
     547            buttonRect.setWidth(secondaryForwardStepper->preferredSize().width());
     548        static_cast<RenderThemeScrollbarGadget&>(scrollbarGadget).renderStepper(graphicsContext.platformContext()->cr(), buttonRect, secondaryForwardStepper,
    592549            scrollbar.orientation() == VerticalScrollbar ? GTK_ORIENTATION_VERTICAL : GTK_ORIENTATION_HORIZONTAL, RenderThemeScrollbarGadget::Steppers::SecondaryForward);
    593550        if (scrollbar.orientation() == VerticalScrollbar) {
     
    599556        }
    600557    }
    601 
    602     if (steppers.contains(RenderThemeScrollbarGadget::Steppers::Forward)) {
    603         RenderThemeGadget* buttonGadget = contentsGadget->child(steppersPosition[3]);
     558    if (secondaryBackwardStepper) {
    604559        FloatRect buttonRect = contentsRect;
    605560        if (scrollbar.orientation() == VerticalScrollbar) {
    606             buttonRect.setHeight(buttonGadget->preferredSize().height());
     561            buttonRect.setHeight(secondaryBackwardStepper->preferredSize().height());
    607562            buttonRect.move(0, contentsRect.height() - buttonRect.height());
    608563        } else {
    609             buttonRect.setWidth(buttonGadget->preferredSize().width());
     564            buttonRect.setWidth(secondaryBackwardStepper->preferredSize().width());
    610565            buttonRect.move(contentsRect.width() - buttonRect.width(), 0);
    611566        }
    612         static_cast<RenderThemeScrollbarGadget*>(scrollbarGadget.get())->renderStepper(graphicsContext.platformContext()->cr(), buttonRect, buttonGadget,
     567        static_cast<RenderThemeScrollbarGadget&>(scrollbarGadget).renderStepper(graphicsContext.platformContext()->cr(), buttonRect, secondaryBackwardStepper,
     568            scrollbar.orientation() == VerticalScrollbar ? GTK_ORIENTATION_VERTICAL : GTK_ORIENTATION_HORIZONTAL, RenderThemeScrollbarGadget::Steppers::SecondaryBackward);
     569        if (scrollbar.orientation() == VerticalScrollbar)
     570            contentsRect.contract(0, buttonRect.height());
     571        else
     572            contentsRect.contract(buttonRect.width(), 0);
     573    }
     574    if (forwardStepper) {
     575        FloatRect buttonRect = contentsRect;
     576        if (scrollbar.orientation() == VerticalScrollbar) {
     577            buttonRect.setHeight(forwardStepper->preferredSize().height());
     578            buttonRect.move(0, contentsRect.height() - buttonRect.height());
     579        } else {
     580            buttonRect.setWidth(forwardStepper->preferredSize().width());
     581            buttonRect.move(contentsRect.width() - buttonRect.width(), 0);
     582        }
     583        static_cast<RenderThemeScrollbarGadget&>(scrollbarGadget).renderStepper(graphicsContext.platformContext()->cr(), buttonRect, forwardStepper,
    613584            scrollbar.orientation() == VerticalScrollbar ? GTK_ORIENTATION_VERTICAL : GTK_ORIENTATION_HORIZONTAL, RenderThemeScrollbarGadget::Steppers::Forward);
    614585        if (scrollbar.orientation() == VerticalScrollbar)
     
    617588            contentsRect.contract(buttonRect.width(), 0);
    618589    }
    619     if (steppers.contains(RenderThemeScrollbarGadget::Steppers::SecondaryBackward)) {
    620         RenderThemeGadget* buttonGadget = contentsGadget->child(steppersPosition[2]);
    621         FloatRect buttonRect = contentsRect;
    622         if (scrollbar.orientation() == VerticalScrollbar) {
    623             buttonRect.setHeight(buttonGadget->preferredSize().height());
    624             buttonRect.move(0, contentsRect.height() - buttonRect.height());
    625         } else {
    626             buttonRect.setWidth(buttonGadget->preferredSize().width());
    627             buttonRect.move(contentsRect.width() - buttonRect.width(), 0);
    628         }
    629         static_cast<RenderThemeScrollbarGadget*>(scrollbarGadget.get())->renderStepper(graphicsContext.platformContext()->cr(), buttonRect, buttonGadget,
    630             scrollbar.orientation() == VerticalScrollbar ? GTK_ORIENTATION_VERTICAL : GTK_ORIENTATION_HORIZONTAL, RenderThemeScrollbarGadget::Steppers::SecondaryBackward);
    631         if (scrollbar.orientation() == VerticalScrollbar)
    632             contentsRect.contract(0, buttonRect.height());
    633         else
    634             contentsRect.contract(buttonRect.width(), 0);
    635     }
    636 
    637     troughGadget->render(graphicsContext.platformContext()->cr(), contentsRect, &contentsRect);
    638     if (sliderGadget) {
     590
     591    trough.render(graphicsContext.platformContext()->cr(), contentsRect, &contentsRect);
     592
     593    if (thumbSize) {
    639594        if (scrollbar.orientation() == VerticalScrollbar) {
    640595            contentsRect.move(0, thumbPosition(scrollbar));
    641             contentsRect.setWidth(sliderGadget->preferredSize().width());
     596            contentsRect.setWidth(scrollbarWidget.slider().preferredSize().width());
    642597            contentsRect.setHeight(thumbSize);
    643598        } else {
    644599            contentsRect.move(thumbPosition(scrollbar), 0);
    645600            contentsRect.setWidth(thumbSize);
    646             contentsRect.setHeight(sliderGadget->preferredSize().height());
     601            contentsRect.setHeight(scrollbarWidget.slider().preferredSize().height());
    647602        }
    648603        if (contentsRect.intersects(damageRect))
    649             sliderGadget->render(graphicsContext.platformContext()->cr(), contentsRect);
     604            scrollbarWidget.slider().render(graphicsContext.platformContext()->cr(), contentsRect);
    650605    }
    651606
     
    847802int ScrollbarThemeGtk::scrollbarThickness(ScrollbarControlSize, ScrollbarExpansionState)
    848803{
    849     RenderThemeGadget::Info info = { RenderThemeGadget::Type::Scrollbar, "scrollbar", GTK_STATE_FLAG_PRELIGHT, { "vertical", "right", "hovering" } };
    850     if (m_usesOverlayScrollbars)
    851         info.classList.append("overlay-indicator");
    852     auto scrollbarGadget = RenderThemeGadget::create(info);
    853     info.type = RenderThemeGadget::Type::Generic;
    854     info.name = "contents";
    855     info.state = GTK_STATE_FLAG_NORMAL;
    856     info.classList.clear();
    857     Vector<RenderThemeGadget::Info> children;
    858     auto steppers = static_cast<RenderThemeScrollbarGadget*>(scrollbarGadget.get())->steppers();
    859     if (steppers.contains(RenderThemeScrollbarGadget::Steppers::Backward))
    860         children.append({ RenderThemeGadget::Type::Generic, "button", GTK_STATE_FLAG_NORMAL, { "up" } });
    861     if (steppers.contains(RenderThemeScrollbarGadget::Steppers::SecondaryForward))
    862         children.append({ RenderThemeGadget::Type::Generic, "button", GTK_STATE_FLAG_NORMAL, { "down" } });
    863     unsigned troughPositon = children.size();
    864     children.append({ RenderThemeGadget::Type::Generic, "trough", GTK_STATE_FLAG_PRELIGHT, { } });
    865     if (steppers.contains(RenderThemeScrollbarGadget::Steppers::SecondaryBackward))
    866         children.append({ RenderThemeGadget::Type::Generic, "button", GTK_STATE_FLAG_NORMAL, { "up" } });
    867     if (steppers.contains(RenderThemeScrollbarGadget::Steppers::Forward))
    868         children.append({ RenderThemeGadget::Type::Generic, "button", GTK_STATE_FLAG_NORMAL, { "down" } });
    869     auto contentsGadget = std::make_unique<RenderThemeBoxGadget>(info, GTK_ORIENTATION_VERTICAL, children, scrollbarGadget.get());
    870     info.name = "slider";
    871     auto sliderGadget = RenderThemeGadget::create(info, contentsGadget->child(troughPositon));
    872     IntSize contentsPreferredSize = contentsGadget->preferredSize();
    873     contentsPreferredSize = contentsPreferredSize.expandedTo(sliderGadget->preferredSize());
    874     IntSize preferredSize = contentsPreferredSize + scrollbarGadget->preferredSize() - scrollbarGadget->minimumSize();
    875 
     804    auto& scrollbarWidget = static_cast<RenderThemeScrollbar&>(RenderThemeWidget::getOrCreate(RenderThemeWidget::Type::VerticalScrollbarRight));
     805    scrollbarWidget.scrollbar().setState(GTK_STATE_FLAG_PRELIGHT);
     806    IntSize contentsPreferredSize = scrollbarWidget.contents().preferredSize();
     807    contentsPreferredSize = contentsPreferredSize.expandedTo(scrollbarWidget.slider().preferredSize());
     808    IntSize preferredSize = contentsPreferredSize + scrollbarWidget.scrollbar().preferredSize() - scrollbarWidget.scrollbar().minimumSize();
    876809    return preferredSize.width();
    877810}
     
    888821int ScrollbarThemeGtk::minimumThumbLength(Scrollbar& scrollbar)
    889822{
    890     RenderThemeGadget::Info info = { RenderThemeGadget::Type::Scrollbar, "scrollbar", GTK_STATE_FLAG_PRELIGHT, { "vertical", "right", "hovering" } };
    891     if (m_usesOverlayScrollbars)
    892         info.classList.append("overlay-indicator");
    893     auto scrollbarGadget = RenderThemeGadget::create(info);
    894     info.type = RenderThemeGadget::Type::Generic;
    895     info.name = "contents";
    896     info.state = GTK_STATE_FLAG_NORMAL;
    897     info.classList.clear();
    898     Vector<RenderThemeGadget::Info> children = {{ RenderThemeGadget::Type::Generic, "trough", GTK_STATE_FLAG_PRELIGHT, { } } };
    899     auto contentsGadget = std::make_unique<RenderThemeBoxGadget>(info, GTK_ORIENTATION_VERTICAL, children, scrollbarGadget.get());
    900     info.name = "slider";
    901     IntSize minSize = RenderThemeGadget::create(info, contentsGadget->child(0))->minimumSize();
     823    auto& scrollbarWidget = static_cast<RenderThemeScrollbar&>(RenderThemeWidget::getOrCreate(RenderThemeWidget::Type::VerticalScrollbarRight));
     824    scrollbarWidget.scrollbar().setState(GTK_STATE_FLAG_PRELIGHT);
     825    IntSize minSize = scrollbarWidget.slider().minimumSize();
    902826    return scrollbar.orientation() == VerticalScrollbar ? minSize.height() : minSize.width();
    903827}
  • trunk/Source/WebCore/rendering/RenderThemeGtk.cpp

    r216902 r217702  
    4545#include "RenderObject.h"
    4646#include "RenderProgress.h"
    47 #include "RenderThemeGadget.h"
     47#include "RenderThemeWidget.h"
    4848#include "ScrollbarThemeGtk.h"
    4949#include "StringTruncator.h"
     
    186186    switch (themePart) {
    187187    case Entry:
     188    case EntrySelection:
    188189        gtk_widget_path_append_type(path.get(), GTK_TYPE_ENTRY);
    189190        gtk_widget_path_iter_add_class(path.get(), -1, GTK_STYLE_CLASS_ENTRY);
     
    528529        return;
    529530
    530     RenderThemeGadget::Info info = {
    531         .type = RenderThemeGadget::Type::Generic,
    532         .name = themePart == CheckButton ? "checkbutton" : "radiobutton",
    533         .state = GTK_STATE_FLAG_NORMAL,
    534         .classList = { }
    535     };
    536     auto parentGadget = RenderThemeGadget::create(info);
    537     if (themePart == CheckButton) {
    538         info.type = RenderThemeGadget::Type::Check;
    539         info.name = "check";
    540     } else {
    541         info.type = RenderThemeGadget::Type::Radio;
    542         info.name = "radio";
    543     }
    544     auto gadget = RenderThemeToggleGadget::create(info);
    545     IntSize preferredSize = parentGadget->preferredSize();
    546     preferredSize = preferredSize.expandedTo(gadget->preferredSize());
     531    auto& toggleWidget = static_cast<RenderThemeToggleButton&>(RenderThemeWidget::getOrCreate(themePart == CheckButton ? RenderThemeWidget::Type::CheckButton : RenderThemeWidget::Type::RadioButton));
     532    toggleWidget.button().setState(GTK_STATE_FLAG_NORMAL);
     533    toggleWidget.toggle().setState(GTK_STATE_FLAG_NORMAL);
     534    IntSize preferredSize = toggleWidget.button().preferredSize();
     535    preferredSize = preferredSize.expandedTo(toggleWidget.toggle().preferredSize());
    547536
    548537    if (style.width().isIntrinsicOrAuto())
     
    557546    ASSERT(themePart == CheckButton || themePart == RadioButton);
    558547
    559     RenderThemeGadget::Info parentInfo = {
    560         .type = RenderThemeGadget::Type::Generic,
    561         .name = themePart == CheckButton ? "checkbutton" : "radiobutton",
    562         .state = themePartStateFlags(*theme, themePart, renderObject),
    563         .classList = { "text-button" }
    564     };
    565     auto parentGadget = RenderThemeGadget::create(parentInfo);
    566     RenderThemeGadget::Info info;
    567     info.state = parentInfo.state;
    568     if (themePart == CheckButton) {
    569         info.type = RenderThemeGadget::Type::Check;
    570         info.name = "check";
    571     } else {
    572         info.type = RenderThemeGadget::Type::Radio;
    573         info.name = "radio";
    574     }
    575     auto gadget = RenderThemeGadget::create(info, parentGadget.get());
     548    auto& toggleWidget = static_cast<RenderThemeToggleButton&>(RenderThemeWidget::getOrCreate(themePart == CheckButton ? RenderThemeWidget::Type::CheckButton : RenderThemeWidget::Type::RadioButton));
     549    auto toggleState = themePartStateFlags(*theme, themePart, renderObject);
     550    toggleWidget.button().setState(toggleState);
     551    toggleWidget.toggle().setState(toggleState);
    576552
    577553    FloatRect rect = fullRect;
     
    580556    // in the full toggle button region. The reason for not simply forcing toggle
    581557    // buttons to be a smaller size is that we don't want to break site layouts.
    582     IntSize preferredSize = parentGadget->preferredSize();
    583     preferredSize = preferredSize.expandedTo(gadget->preferredSize());
     558    IntSize preferredSize = toggleWidget.button().preferredSize();
     559    preferredSize = preferredSize.expandedTo(toggleWidget.toggle().preferredSize());
    584560    shrinkToMinimumSizeAndCenterRectangle(rect, preferredSize);
    585     parentGadget->render(paintInfo.context().platformContext()->cr(), rect);
    586     gadget->render(paintInfo.context().platformContext()->cr(), rect);
     561    toggleWidget.button().render(paintInfo.context().platformContext()->cr(), rect);
     562    toggleWidget.toggle().render(paintInfo.context().platformContext()->cr(), rect);
    587563
    588564    if (theme->isFocused(renderObject))
    589         parentGadget->renderFocus(paintInfo.context().platformContext()->cr(), rect);
     565        toggleWidget.button().renderFocus(paintInfo.context().platformContext()->cr(), rect);
    590566}
    591567#else
     
    684660bool RenderThemeGtk::paintButton(const RenderObject& renderObject, const PaintInfo& paintInfo, const IntRect& rect)
    685661{
    686     RenderThemeGadget::Info info = { RenderThemeGadget::Type::Generic, "button", themePartStateFlags(*this, Button, renderObject), { "text-button" } };
    687     if (isDefault(renderObject))
    688         info.classList.append("default");
    689     auto gadget = RenderThemeGadget::create(info);
    690     gadget->render(paintInfo.context().platformContext()->cr(), rect);
     662    auto& buttonWidget = static_cast<RenderThemeButton&>(RenderThemeWidget::getOrCreate(isDefault(renderObject) ? RenderThemeWidget::Type::ButtonDefault : RenderThemeWidget::Type::Button));
     663    buttonWidget.button().setState(themePartStateFlags(*this, Button, renderObject));
     664    buttonWidget.button().render(paintInfo.context().platformContext()->cr(), rect);
    691665    if (isFocused(renderObject))
    692         gadget->renderFocus(paintInfo.context().platformContext()->cr(), rect);
     666        buttonWidget.button().renderFocus(paintInfo.context().platformContext()->cr(), rect);
    693667    return false;
    694668}
     
    772746{
    773747#if GTK_CHECK_VERSION(3, 20, 0)
    774     RenderThemeGadget::Info info { RenderThemeGadget::Type::Generic, "combobox", element->isDisabledFormControl() ? GTK_STATE_FLAG_INSENSITIVE : GTK_STATE_FLAG_NORMAL, { } };
    775     auto comboGadget = RenderThemeGadget::create(info);
    776     Vector<RenderThemeGadget::Info> children {
    777         { RenderThemeGadget::Type::Generic, "button", info.state, { "combo" } }
    778     };
    779     info.name = "box";
    780     info.classList = { "horizontal", "linked" };
    781     return RenderThemeBoxGadget(info, GTK_ORIENTATION_HORIZONTAL, children, comboGadget.get()).child(0)->color();
     748    auto& comboWidget = static_cast<RenderThemeComboBox&>(RenderThemeWidget::getOrCreate(RenderThemeWidget::Type::ComboBox));
     749    GtkStateFlags state = element->isDisabledFormControl() ? GTK_STATE_FLAG_INSENSITIVE : GTK_STATE_FLAG_NORMAL;
     750    comboWidget.comboBox().setState(state);
     751    comboWidget.button().setState(state);
     752    return comboWidget.button().color();
    782753#else
    783754    GRefPtr<GtkStyleContext> parentStyleContext = createStyleContext(ComboBox);
     
    825796        return LengthBox(0);
    826797
    827     RenderThemeGadget::Info info = { RenderThemeGadget::Type::Generic, "combobox", GTK_STATE_FLAG_NORMAL, { } };
    828     auto comboGadget = RenderThemeGadget::create(info);
    829     Vector<RenderThemeGadget::Info> children = {
    830         { RenderThemeGadget::Type::Generic, "button", GTK_STATE_FLAG_NORMAL, { "combo" } }
    831     };
    832     info.name = "box";
    833     info.classList = { "horizontal", "linked" };
    834     auto boxGadget = std::make_unique<RenderThemeBoxGadget>(info, GTK_ORIENTATION_HORIZONTAL, children, comboGadget.get());
    835     RenderThemeGadget* buttonGadget = boxGadget->child(0);
    836     info.classList.removeLast();
    837     auto buttonBoxGadget = RenderThemeGadget::create(info, buttonGadget);
    838     info.name = "arrow";
    839     info.classList = { };
    840     auto arrowGadget = RenderThemeGadget::create(info, buttonBoxGadget.get());
    841     GtkBorder comboContentsBox = comboGadget->contentsBox();
    842     GtkBorder boxContentsBox = boxGadget->contentsBox();
    843     GtkBorder buttonContentsBox = buttonGadget->contentsBox();
    844     GtkBorder buttonBoxContentsBox = buttonBoxGadget->contentsBox();
     798    auto& comboWidget = static_cast<RenderThemeComboBox&>(RenderThemeWidget::getOrCreate(RenderThemeWidget::Type::ComboBox));
     799    comboWidget.comboBox().setState(GTK_STATE_FLAG_NORMAL);
     800    comboWidget.button().setState(GTK_STATE_FLAG_NORMAL);
     801    comboWidget.arrow().setState(GTK_STATE_FLAG_NORMAL);
     802    GtkBorder comboContentsBox = comboWidget.comboBox().contentsBox();
     803    GtkBorder boxContentsBox = comboWidget.box().contentsBox();
     804    GtkBorder buttonContentsBox = comboWidget.button().contentsBox();
     805    GtkBorder buttonBoxContentsBox = comboWidget.buttonBox().contentsBox();
    845806    GtkBorder padding;
    846807    padding.left = comboContentsBox.left + boxContentsBox.left + buttonContentsBox.left + buttonBoxContentsBox.left;
     
    849810    padding.bottom = comboContentsBox.bottom + boxContentsBox.bottom + buttonContentsBox.bottom + buttonBoxContentsBox.bottom;
    850811
    851     auto arrowSize = arrowGadget->preferredSize();
     812    auto arrowSize = comboWidget.arrow().preferredSize();
    852813    return LengthBox(padding.top, padding.right + (style.direction() == LTR ? arrowSize.width() : 0),
    853814        padding.bottom, padding.left + (style.direction() == RTL ? arrowSize.width() : 0));
     
    856817bool RenderThemeGtk::paintMenuList(const RenderObject& renderObject, const PaintInfo& paintInfo, const FloatRect& rect)
    857818{
    858     RenderThemeGadget::Info info = { RenderThemeGadget::Type::Generic, "combobox", themePartStateFlags(*this, ComboBoxButton, renderObject), { } };
    859     auto comboGadget = RenderThemeGadget::create(info);
    860     Vector<RenderThemeGadget::Info> children = {
    861         { RenderThemeGadget::Type::Generic, "button", info.state, { "combo" } }
    862     };
    863     info.name = "box";
    864     info.classList = { "horizontal", "linked" };
    865     auto boxGadget = std::make_unique<RenderThemeBoxGadget>(info, GTK_ORIENTATION_HORIZONTAL, children, comboGadget.get());
    866     RenderThemeGadget* buttonGadget = boxGadget->child(0);
    867     info.classList.removeLast();
    868     auto buttonBoxGadget = RenderThemeGadget::create(info, buttonGadget);
    869     info.type = RenderThemeGadget::Type::Arrow;
    870     info.name = "arrow";
    871     info.classList = { };
    872     auto arrowGadget = RenderThemeGadget::create(info, buttonBoxGadget.get());
     819    auto& comboWidget = static_cast<RenderThemeComboBox&>(RenderThemeWidget::getOrCreate(RenderThemeWidget::Type::ComboBox));
     820    auto comboState = themePartStateFlags(*this, ComboBoxButton, renderObject);
     821    comboWidget.comboBox().setState(comboState);
     822    comboWidget.button().setState(comboState);
     823    comboWidget.arrow().setState(comboState);
    873824
    874825    cairo_t* cr = paintInfo.context().platformContext()->cr();
    875     comboGadget->render(cr, rect);
    876     boxGadget->render(cr, rect);
     826    comboWidget.comboBox().render(cr, rect);
     827    comboWidget.box().render(cr, rect);
    877828    FloatRect contentsRect;
    878     buttonGadget->render(cr, rect, &contentsRect);
    879     buttonBoxGadget->render(cr, contentsRect);
    880     arrowGadget->render(cr, contentsRect);
     829    comboWidget.button().render(cr, rect, &contentsRect);
     830    comboWidget.buttonBox().render(cr, contentsRect);
     831    comboWidget.arrow().render(cr, contentsRect);
    881832    if (isFocused(renderObject))
    882         buttonGadget->renderFocus(cr, rect);
     833        comboWidget.button().renderFocus(cr, rect);
    883834
    884835    return false;
     
    987938
    988939    // Spinbuttons need a minimum height to be rendered correctly.
    989     RenderThemeGadget::Info info = { RenderThemeGadget::Type::Generic, "spinbutton", GTK_STATE_FLAG_NORMAL, { "horizontal" } };
    990     auto spinbuttonGadget = RenderThemeGadget::create(info);
    991     info.type = RenderThemeGadget::Type::TextField;
    992     info.name = "entry";
    993     info.classList.clear();
    994     auto entryGadget = RenderThemeGadget::create(info, spinbuttonGadget.get());
    995     info.type = RenderThemeGadget::Type::Icon;
    996     info.name = "button";
    997     info.classList.append("up");
    998     auto buttonUpGadget = RenderThemeGadget::create(info, spinbuttonGadget.get());
    999     static_cast<RenderThemeIconGadget*>(buttonUpGadget.get())->setIconSize(RenderThemeIconGadget::IconSizeGtk::Menu);
    1000     info.classList[0] = "down";
    1001     auto buttonDownGadget = RenderThemeGadget::create(info, spinbuttonGadget.get());
    1002     static_cast<RenderThemeIconGadget*>(buttonDownGadget.get())->setIconSize(RenderThemeIconGadget::IconSizeGtk::Menu);
    1003     IntSize preferredSize = spinbuttonGadget->preferredSize();
    1004     preferredSize = preferredSize.expandedTo(entryGadget->preferredSize());
    1005     IntSize upPreferredSize = preferredSize.expandedTo(buttonUpGadget->preferredSize());
    1006     IntSize downPreferredSize = preferredSize.expandedTo(buttonDownGadget->preferredSize());
     940    auto& spinButtonWidget = static_cast<RenderThemeSpinButton&>(RenderThemeWidget::getOrCreate(RenderThemeWidget::Type::SpinButton));
     941    spinButtonWidget.spinButton().setState(GTK_STATE_FLAG_NORMAL);
     942    spinButtonWidget.entry().setState(GTK_STATE_FLAG_NORMAL);
     943    spinButtonWidget.up().setState(GTK_STATE_FLAG_NORMAL);
     944    spinButtonWidget.down().setState(GTK_STATE_FLAG_NORMAL);
     945
     946    IntSize preferredSize = spinButtonWidget.spinButton().preferredSize();
     947    preferredSize = preferredSize.expandedTo(spinButtonWidget.entry().preferredSize());
     948    IntSize upPreferredSize = preferredSize.expandedTo(spinButtonWidget.up().preferredSize());
     949    IntSize downPreferredSize = preferredSize.expandedTo(spinButtonWidget.down().preferredSize());
    1007950    int height = std::max(upPreferredSize.height(), downPreferredSize.height());
    1008951    style.setMinHeight(Length(height, Fixed));
     
    1011954bool RenderThemeGtk::paintTextField(const RenderObject& renderObject, const PaintInfo& paintInfo, const FloatRect& rect)
    1012955{
    1013     RenderThemeGadget::Info info = { RenderThemeGadget::Type::TextField, "entry", themePartStateFlags(*this, Entry, renderObject), { } };
    1014     std::unique_ptr<RenderThemeGadget> parentGadget;
    1015956    if (is<HTMLInputElement>(renderObject.node()) && shouldHaveSpinButton(downcast<HTMLInputElement>(*renderObject.node()))) {
    1016         info.name = "spinbutton";
    1017         info.classList.append("horizontal");
    1018         parentGadget = RenderThemeTextFieldGadget::create(info);
    1019         info.name = "entry";
    1020         info.classList.clear();
    1021     }
    1022 
    1023     auto entryGadget = RenderThemeTextFieldGadget::create(info, parentGadget.get());
    1024     if (parentGadget)
    1025         parentGadget->render(paintInfo.context().platformContext()->cr(), rect);
    1026     entryGadget->render(paintInfo.context().platformContext()->cr(), rect);
     957        auto& spinButtonWidget = static_cast<RenderThemeSpinButton&>(RenderThemeWidget::getOrCreate(RenderThemeWidget::Type::SpinButton));
     958        auto spinButtonState = themePartStateFlags(*this, Entry, renderObject);
     959        spinButtonWidget.spinButton().setState(spinButtonState);
     960        spinButtonWidget.entry().setState(spinButtonState);
     961        spinButtonWidget.spinButton().render(paintInfo.context().platformContext()->cr(), rect);
     962        spinButtonWidget.entry().render(paintInfo.context().platformContext()->cr(), rect);
     963    } else {
     964        auto& entryWidget = static_cast<RenderThemeEntry&>(RenderThemeWidget::getOrCreate(RenderThemeWidget::Type::Entry));
     965        entryWidget.entry().setState(themePartStateFlags(*this, Entry, renderObject));
     966        entryWidget.entry().render(paintInfo.context().platformContext()->cr(), rect);
     967    }
    1027968    return false;
    1028969}
     
    10661007{
    10671008    ASSERT(themePart == EntryIconLeft || themePart == EntryIconRight);
    1068     RenderThemeGadget::Info info = { RenderThemeGadget::Type::TextField, "entry", GTK_STATE_FLAG_NORMAL, { } };
    1069     auto parentGadget = RenderThemeGadget::create(info);
    1070     info.type = RenderThemeGadget::Type::Icon;
    1071     info.name = "image";
    1072     if (themePart == EntryIconLeft)
    1073         info.classList.append("left");
    1074     else
    1075         info.classList.append("right");
    1076     auto gadget = RenderThemeIconGadget::create(info, parentGadget.get());
     1009    auto& searchEntryWidget = static_cast<RenderThemeSearchEntry&>(RenderThemeWidget::getOrCreate(RenderThemeWidget::Type::SearchEntry));
     1010    searchEntryWidget.entry().setState(GTK_STATE_FLAG_NORMAL);
     1011    searchEntryWidget.leftIcon().setState(GTK_STATE_FLAG_NORMAL);
     1012    searchEntryWidget.rightIcon().setState(GTK_STATE_FLAG_NORMAL);
    10771013
    10781014    // Get the icon size based on the font size.
    1079     static_cast<RenderThemeIconGadget*>(gadget.get())->setIconSize(style.fontSize());
    1080     IntSize preferredSize = gadget->preferredSize();
    1081     GtkBorder contentsBox = parentGadget->contentsBox();
     1015    auto& icon = static_cast<RenderThemeIconGadget&>(themePart == EntryIconLeft ? searchEntryWidget.leftIcon() : searchEntryWidget.rightIcon());
     1016    icon.setIconSize(style.fontSize());
     1017    IntSize preferredSize = icon.preferredSize();
     1018    GtkBorder contentsBox = searchEntryWidget.entry().contentsBox();
    10821019    if (themePart == EntryIconLeft)
    10831020        preferredSize.expand(contentsBox.left, contentsBox.top + contentsBox.bottom);
     
    11661103{
    11671104    ASSERT(themePart == EntryIconLeft || themePart == EntryIconRight);
    1168     RenderThemeGadget::Info info = { RenderThemeGadget::Type::TextField, "entry", themePartStateFlags(*theme, Entry, renderObject), { } };
    1169     auto parentGadget = RenderThemeGadget::create(info);
    1170     info.type = RenderThemeGadget::Type::Icon;
    1171     info.state = themePartStateFlags(*theme, themePart, renderObject);
    1172     info.name = "image";
    1173     if (themePart == EntryIconLeft)
    1174         info.classList.append("left");
    1175     else
    1176         info.classList.append("right");
    1177     auto gadget = RenderThemeGadget::create(info, parentGadget.get());
    1178     auto* gadgetIcon = static_cast<RenderThemeIconGadget*>(gadget.get());
    1179     gadgetIcon->setIconSize(renderObject.style().fontSize());
    1180     if (themePart == EntryIconLeft)
    1181         gadgetIcon->setIconName("edit-find-symbolic");
    1182     else
    1183         gadgetIcon->setIconName("edit-clear-symbolic");
    1184     GtkBorder contentsBox = parentGadget->contentsBox();
     1105    auto& searchEntryWidget = static_cast<RenderThemeSearchEntry&>(RenderThemeWidget::getOrCreate(RenderThemeWidget::Type::SearchEntry));
     1106    searchEntryWidget.entry().setState(themePartStateFlags(*theme, Entry, renderObject));
     1107    auto& icon = static_cast<RenderThemeIconGadget&>(themePart == EntryIconLeft ? searchEntryWidget.leftIcon() : searchEntryWidget.rightIcon());
     1108    icon.setState(themePartStateFlags(*theme, themePart, renderObject));
     1109    icon.setIconSize(renderObject.style().fontSize());
     1110    GtkBorder contentsBox = searchEntryWidget.entry().contentsBox();
    11851111    IntRect iconRect = rect;
    11861112    if (themePart == EntryIconLeft) {
     
    11891115    } else
    11901116        iconRect.contract(contentsBox.right, contentsBox.top + contentsBox.bottom);
    1191     return !gadget->render(paintInfo.context().platformContext()->cr(), iconRect);
     1117    return !icon.render(paintInfo.context().platformContext()->cr(), iconRect);
    11921118}
    11931119bool RenderThemeGtk::paintSearchFieldResultsDecorationPart(const RenderBox& renderObject, const PaintInfo& paintInfo, const IntRect& rect)
     
    13101236    ASSERT(part == SliderHorizontalPart || part == SliderVerticalPart);
    13111237
    1312     RenderThemeGadget::Info info = { RenderThemeGadget::Type::Generic, "scale", themePartStateFlags(*this, Scale, renderObject), { } };
    1313     if (part == SliderHorizontalPart)
    1314         info.classList.append("horizontal");
    1315     else
    1316         info.classList.append("vertical");
    1317     auto scaleGadget = RenderThemeGadget::create(info);
    1318     info.name = "contents";
    1319     info.classList.clear();
    1320     auto contentsGadget = RenderThemeGadget::create(info, scaleGadget.get());
    1321     info.name = "trough";
    1322     auto troughGadget = RenderThemeGadget::create(info, contentsGadget.get());
    1323     info.name = "slider";
    1324     auto sliderGadget = RenderThemeGadget::create(info, troughGadget.get());
    1325     info.name = "highlight";
    1326     auto highlightGadget = RenderThemeGadget::create(info, troughGadget.get());
     1238    auto& sliderWidget = static_cast<RenderThemeSlider&>(RenderThemeWidget::getOrCreate(part == SliderHorizontalPart ? RenderThemeWidget::Type::HorizontalSlider : RenderThemeWidget::Type::VerticalSlider));
     1239    auto scaleState = themePartStateFlags(*this, Scale, renderObject);
     1240    auto& scale = sliderWidget.scale();
     1241    scale.setState(scaleState);
     1242    auto& contents = sliderWidget.contents();
     1243    auto& trough = sliderWidget.trough();
     1244    trough.setState(scaleState);
     1245    auto& slider = sliderWidget.slider();
     1246    auto& highlight = sliderWidget.highlight();
    13271247
    13281248    // The given rectangle is not calculated based on the scale size, but all the margins and paddings are based on it.
    1329     IntSize preferredSize = scaleGadget->preferredSize();
    1330     preferredSize = preferredSize.expandedTo(contentsGadget->preferredSize());
    1331     preferredSize = preferredSize.expandedTo(troughGadget->preferredSize());
     1249    IntSize preferredSize = scale.preferredSize();
     1250    preferredSize = preferredSize.expandedTo(contents.preferredSize());
     1251    preferredSize = preferredSize.expandedTo(trough.preferredSize());
    13321252    FloatRect trackRect = rect;
    13331253    if (part == SliderHorizontalPart) {
     
    13401260
    13411261    FloatRect contentsRect;
    1342     scaleGadget->render(paintInfo.context().platformContext()->cr(), trackRect, &contentsRect);
    1343     contentsGadget->render(paintInfo.context().platformContext()->cr(), contentsRect, &contentsRect);
     1262    scale.render(paintInfo.context().platformContext()->cr(), trackRect, &contentsRect);
     1263    contents.render(paintInfo.context().platformContext()->cr(), contentsRect, &contentsRect);
    13441264    // Scale trough defines its size querying slider and highlight.
    13451265    if (part == SliderHorizontalPart)
    1346         contentsRect.setHeight(troughGadget->preferredSize().height() + std::max(sliderGadget->preferredSize().height(), highlightGadget->preferredSize().height()));
     1266        contentsRect.setHeight(trough.preferredSize().height() + std::max(slider.preferredSize().height(), highlight.preferredSize().height()));
    13471267    else
    1348         contentsRect.setWidth(troughGadget->preferredSize().width() + std::max(sliderGadget->preferredSize().width(), highlightGadget->preferredSize().width()));
     1268        contentsRect.setWidth(trough.preferredSize().width() + std::max(slider.preferredSize().width(), highlight.preferredSize().width()));
    13491269    FloatRect troughRect = contentsRect;
    1350     troughGadget->render(paintInfo.context().platformContext()->cr(), troughRect, &contentsRect);
     1270    trough.render(paintInfo.context().platformContext()->cr(), troughRect, &contentsRect);
    13511271    if (isFocused(renderObject))
    1352         troughGadget->renderFocus(paintInfo.context().platformContext()->cr(), troughRect);
     1272        trough.renderFocus(paintInfo.context().platformContext()->cr(), troughRect);
    13531273
    13541274    LayoutPoint thumbLocation;
     
    13671287    } else
    13681288        contentsRect.setHeight(thumbLocation.y());
    1369     highlightGadget->render(paintInfo.context().platformContext()->cr(), contentsRect);
     1289    highlight.render(paintInfo.context().platformContext()->cr(), contentsRect);
    13701290
    13711291    return false;
     
    13781298        return;
    13791299
    1380     RenderThemeGadget::Info info = { RenderThemeGadget::Type::Generic, "scale", GTK_STATE_FLAG_NORMAL, { } };
    1381     if (part == SliderHorizontalPart)
    1382         info.classList.append("horizontal");
    1383     else
    1384         info.classList.append("vertical");
    1385     auto scaleGadget = RenderThemeGadget::create(info);
    1386     info.name = "contents";
    1387     info.classList.clear();
    1388     auto contentsGadget = RenderThemeGadget::create(info, scaleGadget.get());
    1389     info.name = "trough";
    1390     auto troughGadget = RenderThemeGadget::create(info, contentsGadget.get());
    1391     info.name = "slider";
    1392     auto sliderGadget = RenderThemeGadget::create(info, troughGadget.get());
    1393     info.name = "highlight";
    1394     auto highlightGadget = RenderThemeGadget::create(info, troughGadget.get());
    1395 
    1396     IntSize preferredSize = scaleGadget->preferredSize();
    1397     preferredSize = preferredSize.expandedTo(contentsGadget->preferredSize());
    1398     preferredSize = preferredSize.expandedTo(troughGadget->preferredSize());
    1399     preferredSize = preferredSize.expandedTo(sliderGadget->preferredSize());
     1300    auto& sliderWidget = static_cast<RenderThemeSlider&>(RenderThemeWidget::getOrCreate(part == SliderHorizontalPart ? RenderThemeWidget::Type::HorizontalSlider : RenderThemeWidget::Type::VerticalSlider));
     1301    sliderWidget.scale().setState(GTK_STATE_FLAG_NORMAL);
     1302    sliderWidget.trough().setState(GTK_STATE_FLAG_NORMAL);
     1303
     1304    IntSize preferredSize = sliderWidget.scale().preferredSize();
     1305    preferredSize = preferredSize.expandedTo(sliderWidget.contents().preferredSize());
     1306    preferredSize = preferredSize.expandedTo(sliderWidget.trough().preferredSize());
     1307    preferredSize = preferredSize.expandedTo(sliderWidget.slider().preferredSize());
    14001308    if (part == SliderThumbHorizontalPart) {
    14011309        style.setWidth(Length(preferredSize.width(), Fixed));
     
    14131321    ASSERT(part == SliderThumbHorizontalPart || part == SliderThumbVerticalPart);
    14141322
    1415     RenderThemeGadget::Info info = { RenderThemeGadget::Type::Generic, "scale", themePartStateFlags(*this, Scale, renderObject), { } };
    1416     if (part == SliderHorizontalPart)
    1417         info.classList.append("horizontal");
    1418     else
    1419         info.classList.append("vertical");
    1420     auto scaleGadget = RenderThemeGadget::create(info);
    1421     info.name = "contents";
    1422     info.classList.clear();
    1423     auto contentsGadget = RenderThemeGadget::create(info, scaleGadget.get());
    1424     info.name = "trough";
    1425     auto troughGadget = RenderThemeGadget::create(info, contentsGadget.get());
    1426     info.name = "slider";
    1427     info.state = themePartStateFlags(*this, ScaleSlider, renderObject);
    1428     auto sliderGadget = RenderThemeGadget::create(info, troughGadget.get());
    1429     info.name = "highlight";
    1430     auto highlightGadget = RenderThemeGadget::create(info, troughGadget.get());
    1431 
    1432     GtkBorder scaleContentsBox = scaleGadget->contentsBox();
    1433     GtkBorder contentsContentsBox = contentsGadget->contentsBox();
    1434     GtkBorder troughContentsBox = troughGadget->contentsBox();
     1323    auto& sliderWidget = static_cast<RenderThemeSlider&>(RenderThemeWidget::getOrCreate(part == SliderThumbHorizontalPart ? RenderThemeWidget::Type::HorizontalSlider : RenderThemeWidget::Type::VerticalSlider));
     1324    auto scaleState = themePartStateFlags(*this, Scale, renderObject);
     1325    auto& scale = sliderWidget.scale();
     1326    scale.setState(scaleState);
     1327    auto& contents = sliderWidget.contents();
     1328    auto& trough = sliderWidget.trough();
     1329    trough.setState(scaleState);
     1330    auto& slider = sliderWidget.slider();
     1331    slider.setState(themePartStateFlags(*this, ScaleSlider, renderObject));
     1332    auto& highlight = sliderWidget.highlight();
     1333
     1334    GtkBorder scaleContentsBox = scale.contentsBox();
     1335    GtkBorder contentsContentsBox = contents.contentsBox();
     1336    GtkBorder troughContentsBox = trough.contentsBox();
    14351337    GtkBorder padding;
    14361338    padding.left = scaleContentsBox.left + contentsContentsBox.left + troughContentsBox.left;
     
    14401342
    14411343    // Scale trough defines its size querying slider and highlight.
    1442     int troughHeight = troughGadget->preferredSize().height() + std::max(sliderGadget->preferredSize().height(), highlightGadget->preferredSize().height());
     1344    int troughHeight = trough.preferredSize().height() + std::max(slider.preferredSize().height(), highlight.preferredSize().height());
    14431345    IntRect sliderRect(rect.location(), IntSize(troughHeight, troughHeight));
    14441346    sliderRect.move(padding.left, padding.top);
    14451347    sliderRect.contract(padding.left + padding.right, padding.top + padding.bottom);
    1446     sliderGadget->render(paintInfo.context().platformContext()->cr(), sliderRect);
     1348    slider.render(paintInfo.context().platformContext()->cr(), sliderRect);
    14471349    return false;
    14481350}
     
    15411443IntRect RenderThemeGtk::progressBarRectForBounds(const RenderObject& renderObject, const IntRect& bounds) const
    15421444{
    1543     RenderThemeGadget::Info info = { RenderThemeGadget::Type::Generic, "progressbar", GTK_STATE_FLAG_NORMAL, { "horizontal" } };
    1544     auto progressBarGadget = RenderThemeGadget::create(info);
    1545     info.name = "trough";
    1546     info.classList.clear();
    1547     auto troughGadget = RenderThemeGadget::create(info, progressBarGadget.get());
    1548     info.name = "progress";
    1549     if (renderObject.style().direction() == RTL)
    1550         info.classList.append("right");
    1551     else
    1552         info.classList.append("left");
    15531445    const auto& renderProgress = downcast<RenderProgress>(renderObject);
    1554     if (renderProgress.isDeterminate())
    1555         info.classList.append("pulse");
    1556     auto progressGadget = RenderThemeGadget::create(info, troughGadget.get());
    1557     IntSize preferredSize = progressBarGadget->preferredSize();
    1558     preferredSize = preferredSize.expandedTo(troughGadget->preferredSize());
    1559     preferredSize = preferredSize.expandedTo(progressGadget->preferredSize());
     1446    auto& progressBarWidget = static_cast<RenderThemeProgressBar&>(RenderThemeWidget::getOrCreate(renderProgress.isDeterminate() ? RenderThemeProgressBar::Type::ProgressBar : RenderThemeProgressBar::Type::IndeterminateProgressBar));
     1447    IntSize preferredSize = progressBarWidget.progressBar().preferredSize();
     1448    preferredSize = preferredSize.expandedTo(progressBarWidget.trough().preferredSize());
     1449    preferredSize = preferredSize.expandedTo(progressBarWidget.progress().preferredSize());
    15601450    return IntRect(bounds.x(), bounds.y(), bounds.width(), preferredSize.height());
    15611451}
     
    15661456        return true;
    15671457
    1568     RenderThemeGadget::Info info = { RenderThemeGadget::Type::Generic, "progressbar", GTK_STATE_FLAG_NORMAL, { "horizontal" } };
    1569     auto progressBarGadget = RenderThemeGadget::create(info);
    1570     info.name = "trough";
    1571     info.classList.clear();
    1572     auto troughGadget = RenderThemeGadget::create(info, progressBarGadget.get());
    1573     info.name = "progress";
    1574     if (renderObject.style().direction() == RTL)
    1575         info.classList.append("right");
    1576     else
    1577         info.classList.append("left");
    15781458    const auto& renderProgress = downcast<RenderProgress>(renderObject);
    1579     if (renderProgress.isDeterminate())
    1580         info.classList.append("pulse");
    1581     auto progressGadget = RenderThemeGadget::create(info, troughGadget.get());
    1582 
    1583     progressBarGadget->render(paintInfo.context().platformContext()->cr(), rect);
    1584     troughGadget->render(paintInfo.context().platformContext()->cr(), rect);
    1585     progressGadget->render(paintInfo.context().platformContext()->cr(), calculateProgressRect(renderObject, rect));
     1459    auto& progressBarWidget = static_cast<RenderThemeProgressBar&>(RenderThemeWidget::getOrCreate(renderProgress.isDeterminate() ? RenderThemeProgressBar::Type::ProgressBar : RenderThemeProgressBar::Type::IndeterminateProgressBar));
     1460    progressBarWidget.progressBar().render(paintInfo.context().platformContext()->cr(), rect);
     1461    progressBarWidget.trough().render(paintInfo.context().platformContext()->cr(), rect);
     1462    progressBarWidget.progress().render(paintInfo.context().platformContext()->cr(), calculateProgressRect(renderObject, rect));
    15861463    return false;
    15871464}
     
    16361513void RenderThemeGtk::adjustInnerSpinButtonStyle(StyleResolver&, RenderStyle& style, const Element*) const
    16371514{
    1638     RenderThemeGadget::Info info = { RenderThemeGadget::Type::Generic, "spinbutton", GTK_STATE_FLAG_NORMAL, { "horizontal" } };
    1639     auto spinbuttonGadget = RenderThemeGadget::create(info);
    1640     info.type = RenderThemeGadget::Type::TextField;
    1641     info.name = "entry";
    1642     info.classList.clear();
    1643     auto entryGadget = RenderThemeGadget::create(info, spinbuttonGadget.get());
    1644     info.type = RenderThemeGadget::Type::Icon;
    1645     info.name = "button";
    1646     info.classList.append("up");
    1647     auto buttonUpGadget = RenderThemeGadget::create(info, spinbuttonGadget.get());
    1648     static_cast<RenderThemeIconGadget*>(buttonUpGadget.get())->setIconSize(RenderThemeIconGadget::IconSizeGtk::Menu);
    1649     info.classList[0] = "down";
    1650     auto buttonDownGadget = RenderThemeGadget::create(info, spinbuttonGadget.get());
    1651     static_cast<RenderThemeIconGadget*>(buttonDownGadget.get())->setIconSize(RenderThemeIconGadget::IconSizeGtk::Menu);
    1652     IntSize upPreferredSize = buttonUpGadget->preferredSize();
    1653     IntSize downPreferredSize = buttonDownGadget->preferredSize();
     1515    auto& spinButtonWidget = static_cast<RenderThemeSpinButton&>(RenderThemeWidget::getOrCreate(RenderThemeWidget::Type::SpinButton));
     1516    spinButtonWidget.spinButton().setState(GTK_STATE_FLAG_NORMAL);
     1517    spinButtonWidget.entry().setState(GTK_STATE_FLAG_NORMAL);
     1518    spinButtonWidget.up().setState(GTK_STATE_FLAG_NORMAL);
     1519    spinButtonWidget.down().setState(GTK_STATE_FLAG_NORMAL);
     1520
     1521    IntSize upPreferredSize = spinButtonWidget.up().preferredSize();
     1522    IntSize downPreferredSize = spinButtonWidget.down().preferredSize();
    16541523    int buttonSize = std::max(std::max(upPreferredSize.width(), downPreferredSize.width()), std::max(upPreferredSize.height(), downPreferredSize.height()));
    16551524    style.setWidth(Length(buttonSize * 2, Fixed));
     
    16591528bool RenderThemeGtk::paintInnerSpinButton(const RenderObject& renderObject, const PaintInfo& paintInfo, const IntRect& rect)
    16601529{
    1661     RenderThemeGadget::Info info = { RenderThemeGadget::Type::Generic, "spinbutton", themePartStateFlags(*this, SpinButton, renderObject), { } };
    1662     auto spinbuttonGadget = RenderThemeGadget::create(info);
    1663     info.type = RenderThemeGadget::Type::TextField;
    1664     info.name = "entry";
    1665     info.classList.clear();
    1666     auto entryGadget = RenderThemeGadget::create(info, spinbuttonGadget.get());
    1667     info.type = RenderThemeGadget::Type::Icon;
    1668     info.name = "button";
    1669     info.classList.append("up");
    1670     info.state = themePartStateFlags(*this, SpinButtonUpButton, renderObject);
    1671     auto buttonUpGadget = RenderThemeGadget::create(info, spinbuttonGadget.get());
    1672     auto* gadgetIcon = static_cast<RenderThemeIconGadget*>(buttonUpGadget.get());
    1673     gadgetIcon->setIconSize(RenderThemeIconGadget::IconSizeGtk::Menu);
    1674     gadgetIcon->setIconName("list-add-symbolic");
    1675     info.classList[0] = "down";
    1676     info.state = themePartStateFlags(*this, SpinButtonDownButton, renderObject);
    1677     auto buttonDownGadget = RenderThemeGadget::create(info, spinbuttonGadget.get());
    1678     gadgetIcon = static_cast<RenderThemeIconGadget*>(buttonDownGadget.get());
    1679     gadgetIcon->setIconSize(RenderThemeIconGadget::IconSizeGtk::Menu);
    1680     gadgetIcon->setIconName("list-remove-symbolic");
     1530    auto& spinButtonWidget = static_cast<RenderThemeSpinButton&>(RenderThemeWidget::getOrCreate(RenderThemeWidget::Type::SpinButton));
     1531    auto spinButtonState = themePartStateFlags(*this, SpinButton, renderObject);
     1532    spinButtonWidget.spinButton().setState(spinButtonState);
     1533    spinButtonWidget.entry().setState(spinButtonState);
     1534    auto& up = spinButtonWidget.up();
     1535    up.setState(themePartStateFlags(*this, SpinButtonUpButton, renderObject));
     1536    auto& down = spinButtonWidget.down();
     1537    down.setState(themePartStateFlags(*this, SpinButtonDownButton, renderObject));
    16811538
    16821539    IntRect iconRect = rect;
    16831540    iconRect.setWidth(iconRect.width() / 2);
    16841541    if (renderObject.style().direction() == RTL)
    1685         buttonUpGadget->render(paintInfo.context().platformContext()->cr(), iconRect);
     1542        up.render(paintInfo.context().platformContext()->cr(), iconRect);
    16861543    else
    1687         buttonDownGadget->render(paintInfo.context().platformContext()->cr(), iconRect);
     1544        down.render(paintInfo.context().platformContext()->cr(), iconRect);
    16881545    iconRect.move(iconRect.width(), 0);
    16891546    if (renderObject.style().direction() == RTL)
    1690         buttonDownGadget->render(paintInfo.context().platformContext()->cr(), iconRect);
     1547        down.render(paintInfo.context().platformContext()->cr(), iconRect);
    16911548    else
    1692         buttonUpGadget->render(paintInfo.context().platformContext()->cr(), iconRect);
     1549        up.render(paintInfo.context().platformContext()->cr(), iconRect);
    16931550
    16941551    return false;
     
    18231680static Color styleColor(RenderThemePart themePart, GtkStateFlags state, StyleColorType colorType)
    18241681{
    1825     RenderThemeGadget::Info info = { RenderThemeGadget::Type::Generic, nullptr, state, { } };
    1826     std::unique_ptr<RenderThemeGadget> parentGadget;
    1827     RenderThemePart part = themePart;
    1828     if (themePart == Entry && (state & GTK_STATE_FLAG_SELECTED)) {
    1829         info.name = "entry";
    1830         parentGadget = RenderThemeGadget::create(info);
    1831         part = EntrySelection;
    1832     }
    1833 
    1834     switch (part) {
    1835     case Entry:
    1836         info.name = "entry";
    1837         break;
    1838     case EntrySelection:
    1839         info.name = "selection";
    1840         break;
    1841     case ListBox:
    1842         info.name = "treeview";
    1843         info.classList.append("view");
    1844         break;
    1845     case Button:
    1846         info.name = "button";
    1847         break;
     1682    RenderThemeGadget* gadget = nullptr;
     1683    switch (themePart) {
    18481684    default:
    18491685        ASSERT_NOT_REACHED();
    1850         info.name = "entry";
    1851     }
    1852 
    1853     auto gadget = RenderThemeGadget::create(info, parentGadget.get());
     1686        FALLTHROUGH;
     1687    case Entry:
     1688        gadget = &static_cast<RenderThemeEntry&>(RenderThemeWidget::getOrCreate(RenderThemeWidget::Type::Entry)).entry();
     1689        break;
     1690    case EntrySelection:
     1691        gadget = static_cast<RenderThemeEntry&>(RenderThemeWidget::getOrCreate(RenderThemeWidget::Type::SelectedEntry)).selection();
     1692        break;
     1693    case ListBox:
     1694        gadget = &static_cast<RenderThemeListView&>(RenderThemeWidget::getOrCreate(RenderThemeWidget::Type::ListView)).treeview();
     1695        break;
     1696    case Button:
     1697        gadget = &static_cast<RenderThemeButton&>(RenderThemeWidget::getOrCreate(RenderThemeWidget::Type::Button)).button();
     1698        break;
     1699    }
     1700
     1701    ASSERT(gadget);
     1702    gadget->setState(state);
    18541703    return colorType == StyleColorBackground ? gadget->backgroundColor() : gadget->color();
    18551704}
     
    18711720Color RenderThemeGtk::platformActiveSelectionBackgroundColor() const
    18721721{
    1873     return styleColor(Entry, static_cast<GtkStateFlags>(GTK_STATE_FLAG_SELECTED | GTK_STATE_FLAG_FOCUSED), StyleColorBackground);
     1722    return styleColor(EntrySelection, static_cast<GtkStateFlags>(GTK_STATE_FLAG_SELECTED | GTK_STATE_FLAG_FOCUSED), StyleColorBackground);
    18741723}
    18751724
    18761725Color RenderThemeGtk::platformInactiveSelectionBackgroundColor() const
    18771726{
    1878     return styleColor(Entry, GTK_STATE_FLAG_SELECTED, StyleColorBackground);
     1727    return styleColor(EntrySelection, GTK_STATE_FLAG_SELECTED, StyleColorBackground);
    18791728}
    18801729
    18811730Color RenderThemeGtk::platformActiveSelectionForegroundColor() const
    18821731{
    1883     return styleColor(Entry, static_cast<GtkStateFlags>(GTK_STATE_FLAG_SELECTED | GTK_STATE_FLAG_FOCUSED), StyleColorForeground);
     1732    return styleColor(EntrySelection, static_cast<GtkStateFlags>(GTK_STATE_FLAG_SELECTED | GTK_STATE_FLAG_FOCUSED), StyleColorForeground);
    18841733}
    18851734
    18861735Color RenderThemeGtk::platformInactiveSelectionForegroundColor() const
    18871736{
    1888     return styleColor(Entry, GTK_STATE_FLAG_SELECTED, StyleColorForeground);
     1737    return styleColor(EntrySelection, GTK_STATE_FLAG_SELECTED, StyleColorForeground);
    18891738}
    18901739
     
    19421791bool RenderThemeGtk::paintMediaButton(const RenderObject& renderObject, GraphicsContext& graphicsContext, const IntRect& rect, const char* iconName)
    19431792{
    1944     RenderThemeGadget::Info info = { RenderThemeGadget::Type::Icon, "image", themePartStateFlags(*this, MediaButton, renderObject), { } };
    1945     auto gadget = RenderThemeGadget::create(info);
    1946     auto* gadgetIcon = static_cast<RenderThemeIconGadget*>(gadget.get());
    1947     gadgetIcon->setIconSize(RenderThemeIconGadget::IconSizeGtk::Menu);
    1948     gadgetIcon->setIconName(iconName);
    1949     return !gadget->render(graphicsContext.platformContext()->cr(), rect);
     1793    auto& iconWidget = static_cast<RenderThemeIcon&>(RenderThemeWidget::getOrCreate(RenderThemeWidget::Type::Icon));
     1794    auto& icon = static_cast<RenderThemeIconGadget&>(iconWidget.icon());
     1795    icon.setState(themePartStateFlags(*this, MediaButton, renderObject));
     1796    icon.setIconSize(RenderThemeIconGadget::IconSizeGtk::Menu);
     1797    icon.setIconName(iconName);
     1798    return !icon.render(graphicsContext.platformContext()->cr(), rect);
    19501799}
    19511800#else
Note: See TracChangeset for help on using the changeset viewer.