Title: [217702] trunk/Source/WebCore
Revision
217702
Author
[email protected]
Date
2017-06-01 23:40:36 -0700 (Thu, 01 Jun 2017)

Log 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):

Modified Paths

Added Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (217701 => 217702)


--- trunk/Source/WebCore/ChangeLog	2017-06-02 05:55:28 UTC (rev 217701)
+++ trunk/Source/WebCore/ChangeLog	2017-06-02 06:40:36 UTC (rev 217702)
@@ -1,3 +1,89 @@
+2017-06-01  Carlos Garcia Campos  <[email protected]>
+
+        [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):
+
 2017-06-01  Andreas Kling  <[email protected]>
 
         [Mac] Remove backing store for layers that are outside the viewport

Modified: trunk/Source/WebCore/PlatformGTK.cmake (217701 => 217702)


--- trunk/Source/WebCore/PlatformGTK.cmake	2017-06-02 05:55:28 UTC (rev 217701)
+++ trunk/Source/WebCore/PlatformGTK.cmake	2017-06-02 06:40:36 UTC (rev 217702)
@@ -173,6 +173,7 @@
     platform/gtk/PlatformScreenGtk.cpp
     platform/gtk/PlatformWheelEventGtk.cpp
     platform/gtk/RenderThemeGadget.cpp
+    platform/gtk/RenderThemeWidget.cpp
     platform/gtk/ScrollbarThemeGtk.cpp
     platform/gtk/SoundGtk.cpp
     platform/gtk/WidgetGtk.cpp

Modified: trunk/Source/WebCore/platform/gtk/RenderThemeGadget.cpp (217701 => 217702)


--- trunk/Source/WebCore/platform/gtk/RenderThemeGadget.cpp	2017-06-02 05:55:28 UTC (rev 217701)
+++ trunk/Source/WebCore/platform/gtk/RenderThemeGadget.cpp	2017-06-02 06:40:36 UTC (rev 217702)
@@ -60,8 +60,6 @@
     GRefPtr<GtkStyleContext> context = adoptGRef(gtk_style_context_new());
     gtk_style_context_set_path(context.get(), path);
     gtk_style_context_set_parent(context.get(), parent);
-    // Unfortunately, we have to explicitly set the state again here for it to take effect.
-    gtk_style_context_set_state(context.get(), gtk_widget_path_iter_get_state(path, -1));
     return context;
 }
 
@@ -72,7 +70,6 @@
     gtk_widget_path_iter_set_object_name(path, -1, info.name);
     for (const auto* className : info.classList)
         gtk_widget_path_iter_add_class(path, -1, className);
-    gtk_widget_path_iter_set_state(path, -1, static_cast<GtkStateFlags>(gtk_widget_path_iter_get_state(path, -1) | info.state));
 }
 
 RenderThemeGadget::RenderThemeGadget(const RenderThemeGadget::Info& info, RenderThemeGadget* parent, const Vector<RenderThemeGadget::Info> siblings, unsigned position)
@@ -146,6 +143,16 @@
     return returnValue;
 }
 
+GtkStateFlags RenderThemeGadget::state() const
+{
+    return gtk_style_context_get_state(m_context.get());
+}
+
+void RenderThemeGadget::setState(GtkStateFlags state)
+{
+    gtk_style_context_set_state(m_context.get(), state);
+}
+
 IntSize RenderThemeGadget::minimumSize() const
 {
     int width, height;

Modified: trunk/Source/WebCore/platform/gtk/RenderThemeGadget.h (217701 => 217702)


--- trunk/Source/WebCore/platform/gtk/RenderThemeGadget.h	2017-06-02 05:55:28 UTC (rev 217701)
+++ trunk/Source/WebCore/platform/gtk/RenderThemeGadget.h	2017-06-02 06:40:36 UTC (rev 217702)
@@ -56,7 +56,6 @@
     struct Info {
         Type type;
         const char* name;
-        GtkStateFlags state;
         Vector<const char*> classList;
     };
 
@@ -77,6 +76,9 @@
 
     GtkStyleContext* context() const { return m_context.get(); }
 
+    GtkStateFlags state() const;
+    void setState(GtkStateFlags);
+
 protected:
     GtkBorder marginBox() const;
     GtkBorder borderBox() const;

Added: trunk/Source/WebCore/platform/gtk/RenderThemeWidget.cpp (0 => 217702)


--- trunk/Source/WebCore/platform/gtk/RenderThemeWidget.cpp	                        (rev 0)
+++ trunk/Source/WebCore/platform/gtk/RenderThemeWidget.cpp	2017-06-02 06:40:36 UTC (rev 217702)
@@ -0,0 +1,300 @@
+/*
+ * Copyright (C) 2017 Igalia S.L.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "RenderThemeWidget.h"
+
+#if GTK_CHECK_VERSION(3, 20, 0)
+
+#include <wtf/HashMap.h>
+#include <wtf/NeverDestroyed.h>
+
+namespace WebCore {
+
+static HashMap<unsigned, std::unique_ptr<RenderThemeWidget>>& widgetMap()
+{
+    static NeverDestroyed<HashMap<unsigned, std::unique_ptr<RenderThemeWidget>>> map;
+    return map;
+}
+
+RenderThemeWidget& RenderThemeWidget::getOrCreate(Type widgetType)
+{
+    auto addResult = widgetMap().ensure(static_cast<unsigned>(widgetType), [widgetType]() -> std::unique_ptr<RenderThemeWidget> {
+        switch (widgetType) {
+        case RenderThemeWidget::Type::VerticalScrollbarRight:
+            return std::make_unique<RenderThemeScrollbar>(GTK_ORIENTATION_VERTICAL, RenderThemeScrollbar::Mode::Full);
+        case RenderThemeWidget::Type::VerticalScrollbarLeft:
+            return std::make_unique<RenderThemeScrollbar>(GTK_ORIENTATION_VERTICAL, RenderThemeScrollbar::Mode::Full, RenderThemeScrollbar::VerticalPosition::Left);
+        case RenderThemeWidget::Type::HorizontalScrollbar:
+            return std::make_unique<RenderThemeScrollbar>(GTK_ORIENTATION_HORIZONTAL, RenderThemeScrollbar::Mode::Full);
+        case RenderThemeWidget::Type::VerticalScrollIndicatorRight:
+            return std::make_unique<RenderThemeScrollbar>(GTK_ORIENTATION_VERTICAL, RenderThemeScrollbar::Mode::Indicator);
+        case RenderThemeWidget::Type::VerticalScrollIndicatorLeft:
+            return std::make_unique<RenderThemeScrollbar>(GTK_ORIENTATION_VERTICAL, RenderThemeScrollbar::Mode::Indicator, RenderThemeScrollbar::VerticalPosition::Left);
+        case RenderThemeWidget::Type::HorizontalScrollIndicator:
+            return std::make_unique<RenderThemeScrollbar>(GTK_ORIENTATION_HORIZONTAL, RenderThemeScrollbar::Mode::Indicator);
+        case RenderThemeWidget::Type::CheckButton:
+            return std::make_unique<RenderThemeToggleButton>(RenderThemeToggleButton::Type::Check);
+        case RenderThemeWidget::Type::RadioButton:
+            return std::make_unique<RenderThemeToggleButton>(RenderThemeToggleButton::Type::Radio);
+        case RenderThemeWidget::Type::Button:
+            return std::make_unique<RenderThemeButton>(RenderThemeButton::Default::No);
+        case RenderThemeWidget::Type::ButtonDefault:
+            return std::make_unique<RenderThemeButton>(RenderThemeButton::Default::Yes);
+        case RenderThemeWidget::Type::ComboBox:
+            return std::make_unique<RenderThemeComboBox>();
+        case RenderThemeWidget::Type::Entry:
+            return std::make_unique<RenderThemeEntry>();
+        case RenderThemeWidget::Type::SelectedEntry:
+            return std::make_unique<RenderThemeEntry>(RenderThemeEntry::Selected::Yes);
+        case RenderThemeWidget::Type::SearchEntry:
+            return std::make_unique<RenderThemeSearchEntry>();
+        case RenderThemeWidget::Type::SpinButton:
+            return std::make_unique<RenderThemeSpinButton>();
+        case RenderThemeWidget::Type::VerticalSlider:
+            return std::make_unique<RenderThemeSlider>(GTK_ORIENTATION_VERTICAL);
+        case RenderThemeWidget::Type::HorizontalSlider:
+            return std::make_unique<RenderThemeSlider>(GTK_ORIENTATION_HORIZONTAL);
+        case RenderThemeWidget::Type::ProgressBar:
+            return std::make_unique<RenderThemeProgressBar>(RenderThemeProgressBar::Mode::Determinate);
+        case RenderThemeWidget::Type::IndeterminateProgressBar:
+            return std::make_unique<RenderThemeProgressBar>(RenderThemeProgressBar::Mode::Indeterminate);
+        case RenderThemeWidget::Type::ListView:
+            return std::make_unique<RenderThemeListView>();
+        case RenderThemeWidget::Type::Icon:
+            return std::make_unique<RenderThemeIcon>();
+        }
+        ASSERT_NOT_REACHED();
+        return nullptr;
+    });
+    return *addResult.iterator->value;
+}
+
+void RenderThemeWidget::clearCache()
+{
+    widgetMap().clear();
+}
+
+RenderThemeWidget::~RenderThemeWidget()
+{
+}
+
+RenderThemeScrollbar::RenderThemeScrollbar(GtkOrientation orientation, Mode mode, VerticalPosition verticalPosition)
+{
+    RenderThemeGadget::Info info = { RenderThemeGadget::Type::Scrollbar, "scrollbar", { } };
+    if (orientation == GTK_ORIENTATION_VERTICAL) {
+        info.classList.append("vertical");
+        info.classList.append(verticalPosition == VerticalPosition::Right ? "right" : "left");
+    } else {
+        info.classList.append("horizontal");
+        info.classList.append("bottom");
+    }
+    static bool usesOverlayScrollbars = g_strcmp0(g_getenv("GTK_OVERLAY_SCROLLING"), "0");
+    if (usesOverlayScrollbars)
+        info.classList.append("overlay-indicator");
+    if (mode == Mode::Full)
+        info.classList.append("hovering");
+    m_scrollbar = RenderThemeGadget::create(info);
+
+    Vector<RenderThemeGadget::Info> children;
+    auto steppers = static_cast<RenderThemeScrollbarGadget*>(m_scrollbar.get())->steppers();
+    if (steppers.contains(RenderThemeScrollbarGadget::Steppers::Backward)) {
+        m_steppersPosition[0] = children.size();
+        children.append({ RenderThemeGadget::Type::Generic, "button", { "up" } });
+    }
+    if (steppers.contains(RenderThemeScrollbarGadget::Steppers::SecondaryForward)) {
+        m_steppersPosition[1] = children.size();
+        children.append({ RenderThemeGadget::Type::Generic, "button", { "down" } });
+    }
+    m_troughPosition = children.size();
+    children.append({ RenderThemeGadget::Type::Generic, "trough", { } });
+    if (steppers.contains(RenderThemeScrollbarGadget::Steppers::SecondaryBackward)) {
+        m_steppersPosition[2] = children.size();
+        children.append({ RenderThemeGadget::Type::Generic, "button", { "up" } });
+    }
+    if (steppers.contains(RenderThemeScrollbarGadget::Steppers::Forward)) {
+        m_steppersPosition[3] = children.size();
+        children.append({ RenderThemeGadget::Type::Generic, "button", { "down" } });
+    }
+    info.type = RenderThemeGadget::Type::Generic;
+    info.name = "contents";
+    info.classList.clear();
+    m_contents = std::make_unique<RenderThemeBoxGadget>(info, GTK_ORIENTATION_VERTICAL, children, m_scrollbar.get());
+    info.name = "slider";
+    m_slider = RenderThemeGadget::create(info, m_contents->child(m_troughPosition));
+}
+
+RenderThemeGadget* RenderThemeScrollbar::stepper(RenderThemeScrollbarGadget::Steppers scrollbarStepper)
+{
+    if (!static_cast<RenderThemeScrollbarGadget*>(m_scrollbar.get())->steppers().contains(scrollbarStepper))
+        return nullptr;
+
+    switch (scrollbarStepper) {
+    case RenderThemeScrollbarGadget::Steppers::Backward:
+        return m_contents->child(m_steppersPosition[0]);
+    case RenderThemeScrollbarGadget::Steppers::SecondaryForward:
+        return m_contents->child(m_steppersPosition[1]);
+    case RenderThemeScrollbarGadget::Steppers::SecondaryBackward:
+        return m_contents->child(m_steppersPosition[2]);
+    case RenderThemeScrollbarGadget::Steppers::Forward:
+        return m_contents->child(m_steppersPosition[3]);
+    default:
+        break;
+    }
+
+    return nullptr;
+}
+
+RenderThemeToggleButton::RenderThemeToggleButton(Type toggleType)
+{
+    RenderThemeGadget::Info info = { RenderThemeGadget::Type::Generic, toggleType == Type::Check ? "checkbutton" : "radiobutton", { "text-button" } };
+    m_button = RenderThemeGadget::create(info);
+    if (toggleType == Type::Check) {
+        info.type = RenderThemeGadget::Type::Check;
+        info.name = "check";
+    } else {
+        info.type = RenderThemeGadget::Type::Radio;
+        info.name = "radio";
+    }
+    info.classList.clear();
+    m_toggle = RenderThemeGadget::create(info, m_button.get());
+}
+
+RenderThemeButton::RenderThemeButton(Default isDefault)
+{
+    RenderThemeGadget::Info info = { RenderThemeGadget::Type::Generic, "button", { "text-button" } };
+    if (isDefault == Default::Yes)
+        info.classList.append("default");
+    m_button = RenderThemeGadget::create(info);
+}
+
+RenderThemeComboBox::RenderThemeComboBox()
+{
+    RenderThemeGadget::Info info = { RenderThemeGadget::Type::Generic, "combobox", { } };
+    m_comboBox = RenderThemeGadget::create(info);
+    Vector<RenderThemeGadget::Info> children = {
+        { RenderThemeGadget::Type::Generic, "button", { "combo" } }
+    };
+    info.name = "box";
+    info.classList = { "horizontal", "linked" };
+    m_box = std::make_unique<RenderThemeBoxGadget>(info, GTK_ORIENTATION_HORIZONTAL, children, m_comboBox.get());
+    RenderThemeGadget* button = m_box->child(0);
+    info.classList.removeLast();
+    m_buttonBox = RenderThemeGadget::create(info, button);
+    info.type = RenderThemeGadget::Type::Arrow;
+    info.name = "arrow";
+    info.classList = { };
+    m_arrow = RenderThemeGadget::create(info, m_buttonBox.get());
+}
+
+RenderThemeEntry::RenderThemeEntry(Selected isSelected)
+{
+    RenderThemeGadget::Info info = { RenderThemeGadget::Type::TextField, "entry", { } };
+    m_entry = RenderThemeGadget::create(info);
+    if (isSelected == Selected::Yes) {
+        info.type = RenderThemeGadget::Type::Generic;
+        info.name = "selection";
+        m_selection = RenderThemeGadget::create(info, m_entry.get());
+    }
+}
+
+RenderThemeSearchEntry::RenderThemeSearchEntry()
+{
+    RenderThemeGadget::Info info = { RenderThemeGadget::Type::Icon, "image", { "left" } };
+    m_leftIcon = RenderThemeGadget::create(info, m_entry.get());
+    static_cast<RenderThemeIconGadget*>(m_leftIcon.get())->setIconName("edit-find-symbolic");
+    info.classList.clear();
+    info.classList.append("right");
+    m_rightIcon = RenderThemeGadget::create(info, m_entry.get());
+    static_cast<RenderThemeIconGadget*>(m_rightIcon.get())->setIconName("edit-clear-symbolic");
+}
+
+RenderThemeSpinButton::RenderThemeSpinButton()
+{
+    RenderThemeGadget::Info info = { RenderThemeGadget::Type::Generic, "spinbutton", { "horizontal" } };
+    m_spinButton = RenderThemeGadget::create(info);
+    info.type = RenderThemeGadget::Type::TextField;
+    info.name = "entry";
+    info.classList.clear();
+    m_entry = RenderThemeGadget::create(info, m_spinButton.get());
+    info.type = RenderThemeGadget::Type::Icon;
+    info.name = "button";
+    info.classList.append("up");
+    m_up = RenderThemeGadget::create(info, m_spinButton.get());
+    auto* upIcon = static_cast<RenderThemeIconGadget*>(m_up.get());
+    upIcon->setIconSize(RenderThemeIconGadget::IconSizeGtk::Menu);
+    upIcon->setIconName("list-add-symbolic");
+    info.classList[0] = "down";
+    m_down = RenderThemeGadget::create(info, m_spinButton.get());
+    auto* downIcon = static_cast<RenderThemeIconGadget*>(m_down.get());
+    downIcon->setIconSize(RenderThemeIconGadget::IconSizeGtk::Menu);
+    downIcon->setIconName("list-remove-symbolic");
+}
+
+RenderThemeSlider::RenderThemeSlider(GtkOrientation orientation)
+{
+    RenderThemeGadget::Info info = { RenderThemeGadget::Type::Generic, "scale", { } };
+    if (orientation == GTK_ORIENTATION_VERTICAL)
+        info.classList.append("vertical");
+    else
+        info.classList.append("horizontal");
+    m_scale = RenderThemeGadget::create(info);
+    info.name = "contents";
+    info.classList.clear();
+    m_contents = RenderThemeGadget::create(info, m_scale.get());
+    info.name = "trough";
+    m_trough = RenderThemeGadget::create(info, m_contents.get());
+    info.name = "slider";
+    m_slider = RenderThemeGadget::create(info, m_trough.get());
+    info.name = "highlight";
+    m_highlight = RenderThemeGadget::create(info, m_trough.get());
+}
+
+RenderThemeProgressBar::RenderThemeProgressBar(Mode mode)
+{
+    RenderThemeGadget::Info info = { RenderThemeGadget::Type::Generic, "progressbar", { "horizontal" } };
+    m_progressBar = RenderThemeGadget::create(info);
+    info.name = "trough";
+    info.classList.clear();
+    m_trough = RenderThemeGadget::create(info, m_progressBar.get());
+    info.name = "progress";
+    if (mode == Mode::Determinate)
+        info.classList.append("pulse");
+    m_progress = RenderThemeGadget::create(info, m_trough.get());
+}
+
+RenderThemeListView::RenderThemeListView()
+    : m_treeview(RenderThemeGadget::create({ RenderThemeGadget::Type::Generic, "treeview", { "view" } }))
+{
+}
+
+RenderThemeIcon::RenderThemeIcon()
+    : m_icon(RenderThemeGadget::create({ RenderThemeGadget::Type::Icon, "image", { } }))
+{
+}
+
+} // namepsace WebCore
+
+#endif // GTK_CHECK_VERSION(3, 20, 0)

Added: trunk/Source/WebCore/platform/gtk/RenderThemeWidget.h (0 => 217702)


--- trunk/Source/WebCore/platform/gtk/RenderThemeWidget.h	                        (rev 0)
+++ trunk/Source/WebCore/platform/gtk/RenderThemeWidget.h	2017-06-02 06:40:36 UTC (rev 217702)
@@ -0,0 +1,238 @@
+/*
+ * Copyright (C) 2017 Igalia S.L.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+
+#if GTK_CHECK_VERSION(3, 20, 0)
+
+#include "RenderThemeGadget.h"
+
+namespace WebCore {
+
+class RenderThemeWidget {
+    WTF_MAKE_FAST_ALLOCATED;
+    WTF_MAKE_NONCOPYABLE(RenderThemeWidget);
+public:
+    enum class Type {
+        VerticalScrollbarRight = 1,
+        VerticalScrollbarLeft,
+        HorizontalScrollbar,
+        VerticalScrollIndicatorRight,
+        VerticalScrollIndicatorLeft,
+        HorizontalScrollIndicator,
+        CheckButton,
+        RadioButton,
+        Button,
+        ButtonDefault,
+        ComboBox,
+        Entry,
+        SelectedEntry,
+        SearchEntry,
+        SpinButton,
+        VerticalSlider,
+        HorizontalSlider,
+        ProgressBar,
+        IndeterminateProgressBar,
+        ListView,
+        Icon,
+    };
+    static RenderThemeWidget& getOrCreate(Type);
+    static void clearCache();
+
+    RenderThemeWidget() = default;
+    virtual ~RenderThemeWidget();
+};
+
+class RenderThemeScrollbar final : public RenderThemeWidget {
+public:
+    enum class Mode { Full, Indicator };
+    enum class VerticalPosition { Right, Left };
+    RenderThemeScrollbar(GtkOrientation, Mode, VerticalPosition = VerticalPosition::Right);
+    ~RenderThemeScrollbar() = default;
+
+    RenderThemeGadget& scrollbar() const { return *m_scrollbar; }
+    RenderThemeGadget& contents() const { return *m_contents; }
+    RenderThemeGadget& slider() const { return *m_slider; }
+    RenderThemeGadget& trough() const { return *m_contents->child(m_troughPosition); }
+    RenderThemeGadget* stepper(RenderThemeScrollbarGadget::Steppers);
+
+private:
+    std::unique_ptr<RenderThemeGadget> m_scrollbar;
+    std::unique_ptr<RenderThemeBoxGadget> m_contents;
+    std::unique_ptr<RenderThemeGadget> m_slider;
+    unsigned m_troughPosition;
+    unsigned m_steppersPosition[4];
+};
+
+class RenderThemeToggleButton final : public RenderThemeWidget {
+public:
+    enum class Type { Check, Radio };
+    explicit RenderThemeToggleButton(Type);
+    ~RenderThemeToggleButton() = default;
+
+    RenderThemeGadget& button() const { return *m_button; }
+    RenderThemeGadget& toggle() const { return *m_toggle; }
+
+private:
+    std::unique_ptr<RenderThemeGadget> m_button;
+    std::unique_ptr<RenderThemeGadget> m_toggle;
+};
+
+class RenderThemeButton final : public RenderThemeWidget {
+public:
+    enum class Default { No, Yes };
+    explicit RenderThemeButton(Default);
+    ~RenderThemeButton() = default;
+
+    RenderThemeGadget& button() const { return *m_button; }
+
+private:
+    std::unique_ptr<RenderThemeGadget> m_button;
+};
+
+class RenderThemeComboBox final : public RenderThemeWidget {
+public:
+    RenderThemeComboBox();
+    ~RenderThemeComboBox() = default;
+
+    RenderThemeGadget& comboBox() const { return *m_comboBox; }
+    RenderThemeGadget& box() const { return *m_box; }
+    RenderThemeGadget& button() const { return *m_box->child(0); }
+    RenderThemeGadget& buttonBox() const { return *m_buttonBox; }
+    RenderThemeGadget& arrow() const { return *m_arrow; }
+
+private:
+    std::unique_ptr<RenderThemeGadget> m_comboBox;
+    std::unique_ptr<RenderThemeBoxGadget> m_box;
+    std::unique_ptr<RenderThemeGadget> m_buttonBox;
+    std::unique_ptr<RenderThemeGadget> m_arrow;
+};
+
+class RenderThemeEntry : public RenderThemeWidget {
+public:
+    enum class Selected { No, Yes };
+    explicit RenderThemeEntry(Selected = Selected::No);
+    ~RenderThemeEntry() = default;
+
+    RenderThemeGadget& entry() const { return *m_entry; }
+    RenderThemeGadget* selection() const { return m_selection.get(); }
+
+protected:
+    std::unique_ptr<RenderThemeGadget> m_entry;
+    std::unique_ptr<RenderThemeGadget> m_selection;
+};
+
+class RenderThemeSearchEntry final : public RenderThemeEntry {
+public:
+    RenderThemeSearchEntry();
+    ~RenderThemeSearchEntry() = default;
+
+    RenderThemeGadget& leftIcon() const { return *m_leftIcon; }
+    RenderThemeGadget& rightIcon() const { return *m_rightIcon; }
+
+private:
+    std::unique_ptr<RenderThemeGadget> m_leftIcon;
+    std::unique_ptr<RenderThemeGadget> m_rightIcon;
+};
+
+class RenderThemeSpinButton final : public RenderThemeWidget {
+public:
+    RenderThemeSpinButton();
+    ~RenderThemeSpinButton() = default;
+
+    RenderThemeGadget& spinButton() const { return *m_spinButton; }
+    RenderThemeGadget& entry() const { return *m_entry; }
+    RenderThemeGadget& up() const { return *m_up; }
+    RenderThemeGadget& down() const { return *m_down; }
+
+private:
+    std::unique_ptr<RenderThemeGadget> m_spinButton;
+    std::unique_ptr<RenderThemeGadget> m_entry;
+    std::unique_ptr<RenderThemeGadget> m_up;
+    std::unique_ptr<RenderThemeGadget> m_down;
+};
+
+class RenderThemeSlider final : public RenderThemeWidget {
+public:
+    explicit RenderThemeSlider(GtkOrientation);
+    ~RenderThemeSlider() = default;
+
+    RenderThemeGadget& scale() const { return *m_scale; }
+    RenderThemeGadget& contents() const { return *m_contents; }
+    RenderThemeGadget& trough() const { return *m_trough; }
+    RenderThemeGadget& slider() const { return *m_slider; }
+    RenderThemeGadget& highlight() const { return *m_highlight; }
+
+private:
+    std::unique_ptr<RenderThemeGadget> m_scale;
+    std::unique_ptr<RenderThemeGadget> m_contents;
+    std::unique_ptr<RenderThemeGadget> m_trough;
+    std::unique_ptr<RenderThemeGadget> m_slider;
+    std::unique_ptr<RenderThemeGadget> m_highlight;
+};
+
+class RenderThemeProgressBar final : public RenderThemeWidget {
+public:
+    enum class Mode { Determinate, Indeterminate };
+    explicit RenderThemeProgressBar(Mode);
+    ~RenderThemeProgressBar() = default;
+
+    RenderThemeGadget& progressBar() const { return *m_progressBar; }
+    RenderThemeGadget& trough() const { return *m_trough; }
+    RenderThemeGadget& progress() const { return *m_progress; }
+
+private:
+    std::unique_ptr<RenderThemeGadget> m_progressBar;
+    std::unique_ptr<RenderThemeGadget> m_trough;
+    std::unique_ptr<RenderThemeGadget> m_progress;
+};
+
+class RenderThemeListView final : public RenderThemeWidget {
+public:
+    RenderThemeListView();
+    ~RenderThemeListView() = default;
+
+    RenderThemeGadget& treeview() const { return *m_treeview; }
+
+private:
+    std::unique_ptr<RenderThemeGadget> m_treeview;
+};
+
+class RenderThemeIcon final : public RenderThemeWidget {
+public:
+    RenderThemeIcon();
+    ~RenderThemeIcon() = default;
+
+    RenderThemeGadget& icon() const { return *m_icon; }
+
+private:
+    std::unique_ptr<RenderThemeGadget> m_icon;
+};
+
+} // namespace WebCore
+
+#endif // GTK_CHECK_VERSION(3, 20, 0)

Modified: trunk/Source/WebCore/platform/gtk/ScrollbarThemeGtk.cpp (217701 => 217702)


--- trunk/Source/WebCore/platform/gtk/ScrollbarThemeGtk.cpp	2017-06-02 05:55:28 UTC (rev 217701)
+++ trunk/Source/WebCore/platform/gtk/ScrollbarThemeGtk.cpp	2017-06-02 06:40:36 UTC (rev 217702)
@@ -30,7 +30,7 @@
 #include "GRefPtrGtk.h"
 #include "PlatformContextCairo.h"
 #include "PlatformMouseEvent.h"
-#include "RenderThemeGadget.h"
+#include "RenderThemeWidget.h"
 #include "ScrollView.h"
 #include "Scrollbar.h"
 #include <cstdlib>
@@ -96,6 +96,9 @@
 
 void ScrollbarThemeGtk::themeChanged()
 {
+#if GTK_CHECK_VERSION(3, 20, 0)
+    RenderThemeWidget::clearCache();
+#endif
     updateThemeProperties();
 }
 
@@ -102,11 +105,11 @@
 #if GTK_CHECK_VERSION(3, 20, 0)
 void ScrollbarThemeGtk::updateThemeProperties()
 {
-    auto steppers = static_cast<RenderThemeScrollbarGadget*>(RenderThemeGadget::create({ RenderThemeGadget::Type::Scrollbar, "scrollbar", GTK_STATE_FLAG_NORMAL, { } }).get())->steppers();
-    m_hasBackButtonStartPart = steppers.contains(RenderThemeScrollbarGadget::Steppers::Backward);
-    m_hasForwardButtonEndPart = steppers.contains(RenderThemeScrollbarGadget::Steppers::Forward);
-    m_hasBackButtonEndPart = steppers.contains(RenderThemeScrollbarGadget::Steppers::SecondaryBackward);
-    m_hasForwardButtonStartPart = steppers.contains(RenderThemeScrollbarGadget::Steppers::SecondaryForward);
+    auto& scrollbar = static_cast<RenderThemeScrollbar&>(RenderThemeWidget::getOrCreate(RenderThemeWidget::Type::VerticalScrollbarRight));
+    m_hasBackButtonStartPart = scrollbar.stepper(RenderThemeScrollbarGadget::Steppers::Backward);
+    m_hasForwardButtonEndPart = scrollbar.stepper(RenderThemeScrollbarGadget::Steppers::Forward);
+    m_hasBackButtonEndPart = scrollbar.stepper(RenderThemeScrollbarGadget::Steppers::SecondaryBackward);
+    m_hasForwardButtonStartPart = scrollbar.stepper(RenderThemeScrollbarGadget::Steppers::SecondaryForward);
 }
 #else
 void ScrollbarThemeGtk::updateThemeProperties()
@@ -168,71 +171,41 @@
     return static_cast<GtkStateFlags>(stateFlags);
 }
 
-static std::unique_ptr<RenderThemeGadget> scrollbarGadgetForLayout(Scrollbar& scrollbar)
+static RenderThemeWidget::Type widgetTypeForScrollbar(Scrollbar& scrollbar, GtkStateFlags scrollbarState)
 {
-    RenderThemeGadget::Info info = { RenderThemeGadget::Type::Scrollbar, "scrollbar", scrollbarPartStateFlags(scrollbar, AllParts), { } };
     if (scrollbar.orientation() == VerticalScrollbar) {
-        info.classList.append("vertical");
-        info.classList.append("right");
-    } else {
-        info.classList.append("horizontal");
-        info.classList.append("bottom");
+        if (scrollbar.scrollableArea().shouldPlaceBlockDirectionScrollbarOnLeft())
+            return scrollbarState & GTK_STATE_FLAG_PRELIGHT ? RenderThemeWidget::Type::VerticalScrollbarLeft : RenderThemeWidget::Type::VerticalScrollIndicatorLeft;
+        return scrollbarState & GTK_STATE_FLAG_PRELIGHT ? RenderThemeWidget::Type::VerticalScrollbarRight : RenderThemeWidget::Type::VerticalScrollIndicatorRight;
     }
-    if (scrollbar.isOverlayScrollbar())
-        info.classList.append("overlay-indicator");
-    if (info.state & GTK_STATE_FLAG_PRELIGHT)
-        info.classList.append("hovering");
-
-    return RenderThemeGadget::create(info);
+    return scrollbarState & GTK_STATE_FLAG_PRELIGHT ? RenderThemeWidget::Type::HorizontalScrollbar : RenderThemeWidget::Type::HorizontalScrollIndicator;
 }
 
-static std::unique_ptr<RenderThemeBoxGadget> contentsGadgetForLayout(Scrollbar& scrollbar, RenderThemeGadget* parent, IntRect& contentsRect, Vector<int, 4>& steppersPosition)
+static IntRect contentsRectangle(Scrollbar& scrollbar, RenderThemeScrollbar& scrollbarWidget)
 {
-    Vector<RenderThemeGadget::Info> children;
-    auto steppers = static_cast<RenderThemeScrollbarGadget*>(parent)->steppers();
-    if (steppers.contains(RenderThemeScrollbarGadget::Steppers::Backward)) {
-        steppersPosition[0] = 0;
-        children.append({ RenderThemeGadget::Type::Generic, "button", scrollbarPartStateFlags(scrollbar, BackButtonStartPart), { "up" } });
-    }
-    if (steppers.contains(RenderThemeScrollbarGadget::Steppers::SecondaryForward)) {
-        steppersPosition[1] = children.size();
-        children.append({ RenderThemeGadget::Type::Generic, "button", scrollbarPartStateFlags(scrollbar, ForwardButtonStartPart), { "down" } });
-    }
-    children.append({ RenderThemeGadget::Type::Generic, "trough", scrollbarPartStateFlags(scrollbar, BackTrackPart), { } });
-    if (steppers.contains(RenderThemeScrollbarGadget::Steppers::SecondaryBackward)) {
-        steppersPosition[2] = children.size();
-        children.append({ RenderThemeGadget::Type::Generic, "button", scrollbarPartStateFlags(scrollbar, BackButtonEndPart), { "up" } });
-    }
-    if (steppers.contains(RenderThemeScrollbarGadget::Steppers::Forward)) {
-        steppersPosition[3] = children.size();
-        children.append({ RenderThemeGadget::Type::Generic, "button", scrollbarPartStateFlags(scrollbar, ForwardButtonEndPart), { "down" } });
-    }
-    RenderThemeGadget::Info info = { RenderThemeGadget::Type::Generic, "contents", GTK_STATE_FLAG_NORMAL, { } };
-    auto contentsGadget = std::make_unique<RenderThemeBoxGadget>(info, scrollbar.orientation() == VerticalScrollbar ? GTK_ORIENTATION_VERTICAL : GTK_ORIENTATION_HORIZONTAL,
-        children, parent);
-
-    GtkBorder scrollbarContentsBox = parent->contentsBox();
-    GtkBorder contentsContentsBox = contentsGadget->contentsBox();
+    GtkBorder scrollbarContentsBox = scrollbarWidget.scrollbar().contentsBox();
+    GtkBorder contentsContentsBox = scrollbarWidget.contents().contentsBox();
     GtkBorder padding;
     padding.left = scrollbarContentsBox.left + contentsContentsBox.left;
     padding.right = scrollbarContentsBox.right + contentsContentsBox.right;
     padding.top = scrollbarContentsBox.top + contentsContentsBox.top;
     padding.bottom = scrollbarContentsBox.bottom + contentsContentsBox.bottom;
-    contentsRect = scrollbar.frameRect();
+    IntRect contentsRect = scrollbar.frameRect();
     contentsRect.move(padding.left, padding.top);
     contentsRect.contract(padding.left + padding.right, padding.top + padding.bottom);
-    return contentsGadget;
+    return contentsRect;
 }
 
 IntRect ScrollbarThemeGtk::trackRect(Scrollbar& scrollbar, bool /*painting*/)
 {
-    auto scrollbarGadget = scrollbarGadgetForLayout(scrollbar);
-    IntRect rect;
-    Vector<int, 4> steppersPosition(4, -1);
-    auto contentsGadget = contentsGadgetForLayout(scrollbar, scrollbarGadget.get(), rect, steppersPosition);
+    auto scrollbarState = scrollbarPartStateFlags(scrollbar, AllParts);
+    auto& scrollbarWidget = static_cast<RenderThemeScrollbar&>(RenderThemeWidget::getOrCreate(widgetTypeForScrollbar(scrollbar, scrollbarState)));
+    scrollbarWidget.scrollbar().setState(scrollbarState);
 
-    if (steppersPosition[0] != -1) {
-        IntSize stepperSize = contentsGadget->child(steppersPosition[0])->preferredSize();
+    IntRect rect = contentsRectangle(scrollbar, scrollbarWidget);
+    if (auto* backwardStepper = scrollbarWidget.stepper(RenderThemeScrollbarGadget::Steppers::Backward)) {
+        backwardStepper->setState(scrollbarPartStateFlags(scrollbar, BackButtonStartPart));
+        IntSize stepperSize = backwardStepper->preferredSize();
         if (scrollbar.orientation() == VerticalScrollbar) {
             rect.move(0, stepperSize.height());
             rect.contract(0, stepperSize.height());
@@ -241,8 +214,9 @@
             rect.contract(stepperSize.width(), 0);
         }
     }
-    if (steppersPosition[1] != -1) {
-        IntSize stepperSize = contentsGadget->child(steppersPosition[1])->preferredSize();
+    if (auto* secondaryForwardStepper = scrollbarWidget.stepper(RenderThemeScrollbarGadget::Steppers::SecondaryForward)) {
+        secondaryForwardStepper->setState(scrollbarPartStateFlags(scrollbar, ForwardButtonStartPart));
+        IntSize stepperSize = secondaryForwardStepper->preferredSize();
         if (scrollbar.orientation() == VerticalScrollbar) {
             rect.move(0, stepperSize.height());
             rect.contract(0, stepperSize.height());
@@ -251,17 +225,19 @@
             rect.contract(stepperSize.width(), 0);
         }
     }
-    if (steppersPosition[2] != -1) {
+    if (auto* secondaryBackwardStepper = scrollbarWidget.stepper(RenderThemeScrollbarGadget::Steppers::SecondaryBackward)) {
+        secondaryBackwardStepper->setState(scrollbarPartStateFlags(scrollbar, BackButtonEndPart));
         if (scrollbar.orientation() == VerticalScrollbar)
-            rect.contract(0, contentsGadget->child(steppersPosition[2])->preferredSize().height());
+            rect.contract(0, secondaryBackwardStepper->preferredSize().height());
         else
-            rect.contract(contentsGadget->child(steppersPosition[2])->preferredSize().width(), 0);
+            rect.contract(secondaryBackwardStepper->preferredSize().width(), 0);
     }
-    if (steppersPosition[3] != -1) {
+    if (auto* forwardStepper = scrollbarWidget.stepper(RenderThemeScrollbarGadget::Steppers::Forward)) {
+        forwardStepper->setState(scrollbarPartStateFlags(scrollbar, ForwardButtonEndPart));
         if (scrollbar.orientation() == VerticalScrollbar)
-            rect.contract(0, contentsGadget->child(steppersPosition[3])->preferredSize().height());
+            rect.contract(0, forwardStepper->preferredSize().height());
         else
-            rect.contract(contentsGadget->child(steppersPosition[3])->preferredSize().width(), 0);
+            rect.contract(forwardStepper->preferredSize().width(), 0);
     }
 
     if (scrollbar.orientation() == VerticalScrollbar)
@@ -327,17 +303,21 @@
     if ((part == BackButtonEndPart && !m_hasBackButtonEndPart) || (part == BackButtonStartPart && !m_hasBackButtonStartPart))
         return IntRect();
 
-    auto scrollbarGadget = scrollbarGadgetForLayout(scrollbar);
-    IntRect rect;
-    Vector<int, 4> steppersPosition(4, -1);
-    auto contentsGadget = contentsGadgetForLayout(scrollbar, scrollbarGadget.get(), rect, steppersPosition);
+    auto scrollbarState = scrollbarPartStateFlags(scrollbar, AllParts);
+    auto& scrollbarWidget = static_cast<RenderThemeScrollbar&>(RenderThemeWidget::getOrCreate(widgetTypeForScrollbar(scrollbar, scrollbarState)));
+    scrollbarWidget.scrollbar().setState(scrollbarState);
 
-    if (part == BackButtonStartPart)
-        return IntRect(rect.location(), contentsGadget->child(0)->preferredSize());
+    IntRect rect = contentsRectangle(scrollbar, scrollbarWidget);
+    if (part == BackButtonStartPart) {
+        auto* backwardStepper = scrollbarWidget.stepper(RenderThemeScrollbarGadget::Steppers::Backward);
+        ASSERT(backwardStepper);
+        backwardStepper->setState(scrollbarPartStateFlags(scrollbar, BackButtonStartPart));
+        return IntRect(rect.location(), backwardStepper->preferredSize());
+    }
 
-    // Secondary back.
-    if (steppersPosition[1] != -1) {
-        IntSize preferredSize = contentsGadget->child(steppersPosition[1])->preferredSize();
+    if (auto* secondaryForwardStepper = scrollbarWidget.stepper(RenderThemeScrollbarGadget::Steppers::SecondaryForward)) {
+        secondaryForwardStepper->setState(scrollbarPartStateFlags(scrollbar, ForwardButtonStartPart));
+        IntSize preferredSize = secondaryForwardStepper->preferredSize();
         if (scrollbar.orientation() == VerticalScrollbar) {
             rect.move(0, preferredSize.height());
             rect.contract(0, preferredSize.height());
@@ -347,14 +327,18 @@
         }
     }
 
-    if (steppersPosition[3] != -1) {
+    if (auto* secondaryBackwardStepper = scrollbarWidget.stepper(RenderThemeScrollbarGadget::Steppers::SecondaryBackward)) {
+        secondaryBackwardStepper->setState(scrollbarPartStateFlags(scrollbar, BackButtonEndPart));
         if (scrollbar.orientation() == VerticalScrollbar)
-            rect.contract(0, contentsGadget->child(steppersPosition[3])->preferredSize().height());
+            rect.contract(0, secondaryBackwardStepper->preferredSize().height());
         else
-            rect.contract(contentsGadget->child(steppersPosition[3])->preferredSize().width(), 0);
+            rect.contract(secondaryBackwardStepper->preferredSize().width(), 0);
     }
 
-    IntSize preferredSize = contentsGadget->child(steppersPosition[2])->preferredSize();
+    auto* forwardStepper = scrollbarWidget.stepper(RenderThemeScrollbarGadget::Steppers::Forward);
+    ASSERT(forwardStepper);
+    forwardStepper->setState(scrollbarPartStateFlags(scrollbar, ForwardButtonEndPart));
+    IntSize preferredSize = forwardStepper->preferredSize();
     if (scrollbar.orientation() == VerticalScrollbar)
         rect.move(0, rect.height() - preferredSize.height());
     else
@@ -369,13 +353,14 @@
     if ((part == ForwardButtonStartPart && !m_hasForwardButtonStartPart) || (part == ForwardButtonEndPart && !m_hasForwardButtonEndPart))
         return IntRect();
 
-    auto scrollbarGadget = scrollbarGadgetForLayout(scrollbar);
-    IntRect rect;
-    Vector<int, 4> steppersPosition(4, -1);
-    auto contentsGadget = contentsGadgetForLayout(scrollbar, scrollbarGadget.get(), rect, steppersPosition);
+    auto scrollbarState = scrollbarPartStateFlags(scrollbar, AllParts);
+    auto& scrollbarWidget = static_cast<RenderThemeScrollbar&>(RenderThemeWidget::getOrCreate(widgetTypeForScrollbar(scrollbar, scrollbarState)));
+    scrollbarWidget.scrollbar().setState(scrollbarState);
 
-    if (steppersPosition[0] != -1) {
-        IntSize preferredSize = contentsGadget->child(steppersPosition[0])->preferredSize();
+    IntRect rect = contentsRectangle(scrollbar, scrollbarWidget);
+    if (auto* backwardStepper = scrollbarWidget.stepper(RenderThemeScrollbarGadget::Steppers::Backward)) {
+        backwardStepper->setState(scrollbarPartStateFlags(scrollbar, BackButtonStartPart));
+        IntSize preferredSize = backwardStepper->preferredSize();
         if (scrollbar.orientation() == VerticalScrollbar) {
             rect.move(0, preferredSize.height());
             rect.contract(0, preferredSize.height());
@@ -385,8 +370,9 @@
         }
     }
 
-    if (steppersPosition[1] != -1) {
-        IntSize preferredSize = contentsGadget->child(steppersPosition[1])->preferredSize();
+    if (auto* secondaryForwardStepper = scrollbarWidget.stepper(RenderThemeScrollbarGadget::Steppers::SecondaryForward)) {
+        secondaryForwardStepper->setState(scrollbarPartStateFlags(scrollbar, ForwardButtonStartPart));
+        IntSize preferredSize = secondaryForwardStepper->preferredSize();
         if (part == ForwardButtonStartPart)
             return IntRect(rect.location(), preferredSize);
 
@@ -399,8 +385,10 @@
         }
     }
 
-    // Forward button.
-    IntSize preferredSize = contentsGadget->child(steppersPosition[3])->preferredSize();
+    auto* forwardStepper = scrollbarWidget.stepper(RenderThemeScrollbarGadget::Steppers::Forward);
+    ASSERT(forwardStepper);
+    forwardStepper->setState(scrollbarPartStateFlags(scrollbar, ForwardButtonEndPart));
+    IntSize preferredSize = forwardStepper->preferredSize();
     if (scrollbar.orientation() == VerticalScrollbar)
         rect.move(0, rect.height() - preferredSize.height());
     else
@@ -477,67 +465,38 @@
     if (!rect.intersects(damageRect))
         return true;
 
-    bool scrollbarOnLeft = scrollbar.scrollableArea().shouldPlaceBlockDirectionScrollbarOnLeft();
-
-    RenderThemeGadget::Info info = { RenderThemeGadget::Type::Scrollbar, "scrollbar", scrollbarPartStateFlags(scrollbar, AllParts, true), { } };
-    if (scrollbar.orientation() == VerticalScrollbar) {
-        info.classList.append("vertical");
-        info.classList.append(scrollbarOnLeft ? "left" : "right");
-    } else {
-        info.classList.append("horizontal");
-        info.classList.append("bottom");
-    }
+    auto scrollbarState = scrollbarPartStateFlags(scrollbar, AllParts, true);
+    auto& scrollbarWidget = static_cast<RenderThemeScrollbar&>(RenderThemeWidget::getOrCreate(widgetTypeForScrollbar(scrollbar, scrollbarState)));
+    auto& scrollbarGadget = scrollbarWidget.scrollbar();
+    scrollbarGadget.setState(scrollbarState);
     if (m_usesOverlayScrollbars)
-        info.classList.append("overlay-indicator");
-    if (info.state & GTK_STATE_FLAG_PRELIGHT)
-        info.classList.append("hovering");
-    if (scrollbar.pressedPart() != NoPart)
-        info.classList.append("dragging");
-    auto scrollbarGadget = RenderThemeGadget::create(info);
-    if (m_usesOverlayScrollbars)
-        opacity *= scrollbarGadget->opacity();
+        opacity *= scrollbarGadget.opacity();
     if (!opacity)
         return true;
 
-    info.type = RenderThemeGadget::Type::Generic;
-    info.name = "contents";
-    info.state = GTK_STATE_FLAG_NORMAL;
-    info.classList.clear();
-    Vector<RenderThemeGadget::Info> children;
-    auto steppers = static_cast<RenderThemeScrollbarGadget*>(scrollbarGadget.get())->steppers();
-    unsigned steppersPosition[4] = { 0, 0, 0, 0 };
-    if (steppers.contains(RenderThemeScrollbarGadget::Steppers::Backward)) {
-        steppersPosition[0] = children.size();
-        children.append({ RenderThemeGadget::Type::Generic, "button", scrollbarPartStateFlags(scrollbar, BackButtonStartPart), { "up" } });
-    }
-    if (steppers.contains(RenderThemeScrollbarGadget::Steppers::SecondaryForward)) {
-        steppersPosition[1] = children.size();
-        children.append({ RenderThemeGadget::Type::Generic, "button", scrollbarPartStateFlags(scrollbar, ForwardButtonStartPart), { "down" } });
-    }
-    unsigned troughPosition = children.size();
-    children.append({ RenderThemeGadget::Type::Generic, "trough", scrollbarPartStateFlags(scrollbar, BackTrackPart), { } });
-    if (steppers.contains(RenderThemeScrollbarGadget::Steppers::SecondaryBackward)) {
-        steppersPosition[2] = children.size();
-        children.append({ RenderThemeGadget::Type::Generic, "button", scrollbarPartStateFlags(scrollbar, BackButtonEndPart), { "up" } });
-    }
-    if (steppers.contains(RenderThemeScrollbarGadget::Steppers::Forward)) {
-        steppersPosition[3] = children.size();
-        children.append({ RenderThemeGadget::Type::Generic, "button", scrollbarPartStateFlags(scrollbar, ForwardButtonEndPart), { "down" } });
-    }
-    auto contentsGadget = std::make_unique<RenderThemeBoxGadget>(info, scrollbar.orientation() == VerticalScrollbar ? GTK_ORIENTATION_VERTICAL : GTK_ORIENTATION_HORIZONTAL,
-        children, scrollbarGadget.get());
-    RenderThemeGadget* troughGadget = contentsGadget->child(troughPosition);
+    auto& trough = scrollbarWidget.trough();
+    trough.setState(scrollbarPartStateFlags(scrollbar, BackTrackPart));
 
-    IntSize preferredSize = contentsGadget->preferredSize();
-    std::unique_ptr<RenderThemeGadget> sliderGadget;
+    auto* backwardStepper = scrollbarWidget.stepper(RenderThemeScrollbarGadget::Steppers::Backward);
+    if (backwardStepper)
+        backwardStepper->setState(scrollbarPartStateFlags(scrollbar, BackButtonStartPart));
+    auto* secondaryForwardStepper = scrollbarWidget.stepper(RenderThemeScrollbarGadget::Steppers::SecondaryForward);
+    if (secondaryForwardStepper)
+        secondaryForwardStepper->setState(scrollbarPartStateFlags(scrollbar, ForwardButtonStartPart));
+    auto* secondaryBackwardStepper = scrollbarWidget.stepper(RenderThemeScrollbarGadget::Steppers::SecondaryBackward);
+    if (secondaryBackwardStepper)
+        secondaryBackwardStepper->setState(scrollbarPartStateFlags(scrollbar, BackButtonEndPart));
+    auto* forwardStepper = scrollbarWidget.stepper(RenderThemeScrollbarGadget::Steppers::Forward);
+    if (forwardStepper)
+        forwardStepper->setState(scrollbarPartStateFlags(scrollbar, ForwardButtonEndPart));
+
+    IntSize preferredSize = scrollbarWidget.contents().preferredSize();
     int thumbSize = thumbLength(scrollbar);
     if (thumbSize) {
-        info.name = "slider";
-        info.state = scrollbarPartStateFlags(scrollbar, ThumbPart);
-        sliderGadget = RenderThemeGadget::create(info, troughGadget);
-        preferredSize = preferredSize.expandedTo(sliderGadget->preferredSize());
+        scrollbarWidget.slider().setState(scrollbarPartStateFlags(scrollbar, ThumbPart));
+        preferredSize = preferredSize.expandedTo(scrollbarWidget.slider().preferredSize());
     }
-    preferredSize += scrollbarGadget->preferredSize() - scrollbarGadget->minimumSize();
+    preferredSize += scrollbarGadget.preferredSize() - scrollbarGadget.minimumSize();
 
     FloatRect contentsRect(rect);
     // When using overlay scrollbars we always claim the size of the scrollbar when hovered, so when
@@ -544,7 +503,7 @@
     // drawing the indicator we need to adjust the rectangle to its actual size in indicator mode.
     if (scrollbar.orientation() == VerticalScrollbar) {
         if (rect.width() != preferredSize.width()) {
-            if (!scrollbarOnLeft)
+            if (!scrollbar.scrollableArea().shouldPlaceBlockDirectionScrollbarOnLeft())
                 contentsRect.move(std::abs(rect.width() - preferredSize.width()), 0);
             contentsRect.setWidth(preferredSize.width());
         }
@@ -561,17 +520,16 @@
         graphicsContext.beginTransparencyLayer(opacity);
     }
 
-    scrollbarGadget->render(graphicsContext.platformContext()->cr(), contentsRect, &contentsRect);
-    contentsGadget->render(graphicsContext.platformContext()->cr(), contentsRect, &contentsRect);
+    scrollbarGadget.render(graphicsContext.platformContext()->cr(), contentsRect, &contentsRect);
+    scrollbarWidget.contents().render(graphicsContext.platformContext()->cr(), contentsRect, &contentsRect);
 
-    if (steppers.contains(RenderThemeScrollbarGadget::Steppers::Backward)) {
-        RenderThemeGadget* buttonGadget = contentsGadget->child(steppersPosition[0]);
+    if (backwardStepper) {
         FloatRect buttonRect = contentsRect;
         if (scrollbar.orientation() == VerticalScrollbar)
-            buttonRect.setHeight(buttonGadget->preferredSize().height());
+            buttonRect.setHeight(backwardStepper->preferredSize().height());
         else
-            buttonRect.setWidth(buttonGadget->preferredSize().width());
-        static_cast<RenderThemeScrollbarGadget*>(scrollbarGadget.get())->renderStepper(graphicsContext.platformContext()->cr(), buttonRect, buttonGadget,
+            buttonRect.setWidth(backwardStepper->preferredSize().width());
+        static_cast<RenderThemeScrollbarGadget&>(scrollbarGadget).renderStepper(graphicsContext.platformContext()->cr(), buttonRect, backwardStepper,
             scrollbar.orientation() == VerticalScrollbar ? GTK_ORIENTATION_VERTICAL : GTK_ORIENTATION_HORIZONTAL, RenderThemeScrollbarGadget::Steppers::Backward);
         if (scrollbar.orientation() == VerticalScrollbar) {
             contentsRect.move(0, buttonRect.height());
@@ -581,14 +539,13 @@
             contentsRect.contract(buttonRect.width(), 0);
         }
     }
-    if (steppers.contains(RenderThemeScrollbarGadget::Steppers::SecondaryForward)) {
-        RenderThemeGadget* buttonGadget = contentsGadget->child(steppersPosition[1]);
+    if (secondaryForwardStepper) {
         FloatRect buttonRect = contentsRect;
         if (scrollbar.orientation() == VerticalScrollbar)
-            buttonRect.setHeight(buttonGadget->preferredSize().height());
+            buttonRect.setHeight(secondaryForwardStepper->preferredSize().height());
         else
-            buttonRect.setWidth(buttonGadget->preferredSize().width());
-        static_cast<RenderThemeScrollbarGadget*>(scrollbarGadget.get())->renderStepper(graphicsContext.platformContext()->cr(), buttonRect, buttonGadget,
+            buttonRect.setWidth(secondaryForwardStepper->preferredSize().width());
+        static_cast<RenderThemeScrollbarGadget&>(scrollbarGadget).renderStepper(graphicsContext.platformContext()->cr(), buttonRect, secondaryForwardStepper,
             scrollbar.orientation() == VerticalScrollbar ? GTK_ORIENTATION_VERTICAL : GTK_ORIENTATION_HORIZONTAL, RenderThemeScrollbarGadget::Steppers::SecondaryForward);
         if (scrollbar.orientation() == VerticalScrollbar) {
             contentsRect.move(0, buttonRect.height());
@@ -598,36 +555,33 @@
             contentsRect.contract(buttonRect.width(), 0);
         }
     }
-
-    if (steppers.contains(RenderThemeScrollbarGadget::Steppers::Forward)) {
-        RenderThemeGadget* buttonGadget = contentsGadget->child(steppersPosition[3]);
+    if (secondaryBackwardStepper) {
         FloatRect buttonRect = contentsRect;
         if (scrollbar.orientation() == VerticalScrollbar) {
-            buttonRect.setHeight(buttonGadget->preferredSize().height());
+            buttonRect.setHeight(secondaryBackwardStepper->preferredSize().height());
             buttonRect.move(0, contentsRect.height() - buttonRect.height());
         } else {
-            buttonRect.setWidth(buttonGadget->preferredSize().width());
+            buttonRect.setWidth(secondaryBackwardStepper->preferredSize().width());
             buttonRect.move(contentsRect.width() - buttonRect.width(), 0);
         }
-        static_cast<RenderThemeScrollbarGadget*>(scrollbarGadget.get())->renderStepper(graphicsContext.platformContext()->cr(), buttonRect, buttonGadget,
-            scrollbar.orientation() == VerticalScrollbar ? GTK_ORIENTATION_VERTICAL : GTK_ORIENTATION_HORIZONTAL, RenderThemeScrollbarGadget::Steppers::Forward);
+        static_cast<RenderThemeScrollbarGadget&>(scrollbarGadget).renderStepper(graphicsContext.platformContext()->cr(), buttonRect, secondaryBackwardStepper,
+            scrollbar.orientation() == VerticalScrollbar ? GTK_ORIENTATION_VERTICAL : GTK_ORIENTATION_HORIZONTAL, RenderThemeScrollbarGadget::Steppers::SecondaryBackward);
         if (scrollbar.orientation() == VerticalScrollbar)
             contentsRect.contract(0, buttonRect.height());
         else
             contentsRect.contract(buttonRect.width(), 0);
     }
-    if (steppers.contains(RenderThemeScrollbarGadget::Steppers::SecondaryBackward)) {
-        RenderThemeGadget* buttonGadget = contentsGadget->child(steppersPosition[2]);
+    if (forwardStepper) {
         FloatRect buttonRect = contentsRect;
         if (scrollbar.orientation() == VerticalScrollbar) {
-            buttonRect.setHeight(buttonGadget->preferredSize().height());
+            buttonRect.setHeight(forwardStepper->preferredSize().height());
             buttonRect.move(0, contentsRect.height() - buttonRect.height());
         } else {
-            buttonRect.setWidth(buttonGadget->preferredSize().width());
+            buttonRect.setWidth(forwardStepper->preferredSize().width());
             buttonRect.move(contentsRect.width() - buttonRect.width(), 0);
         }
-        static_cast<RenderThemeScrollbarGadget*>(scrollbarGadget.get())->renderStepper(graphicsContext.platformContext()->cr(), buttonRect, buttonGadget,
-            scrollbar.orientation() == VerticalScrollbar ? GTK_ORIENTATION_VERTICAL : GTK_ORIENTATION_HORIZONTAL, RenderThemeScrollbarGadget::Steppers::SecondaryBackward);
+        static_cast<RenderThemeScrollbarGadget&>(scrollbarGadget).renderStepper(graphicsContext.platformContext()->cr(), buttonRect, forwardStepper,
+            scrollbar.orientation() == VerticalScrollbar ? GTK_ORIENTATION_VERTICAL : GTK_ORIENTATION_HORIZONTAL, RenderThemeScrollbarGadget::Steppers::Forward);
         if (scrollbar.orientation() == VerticalScrollbar)
             contentsRect.contract(0, buttonRect.height());
         else
@@ -634,19 +588,20 @@
             contentsRect.contract(buttonRect.width(), 0);
     }
 
-    troughGadget->render(graphicsContext.platformContext()->cr(), contentsRect, &contentsRect);
-    if (sliderGadget) {
+    trough.render(graphicsContext.platformContext()->cr(), contentsRect, &contentsRect);
+
+    if (thumbSize) {
         if (scrollbar.orientation() == VerticalScrollbar) {
             contentsRect.move(0, thumbPosition(scrollbar));
-            contentsRect.setWidth(sliderGadget->preferredSize().width());
+            contentsRect.setWidth(scrollbarWidget.slider().preferredSize().width());
             contentsRect.setHeight(thumbSize);
         } else {
             contentsRect.move(thumbPosition(scrollbar), 0);
             contentsRect.setWidth(thumbSize);
-            contentsRect.setHeight(sliderGadget->preferredSize().height());
+            contentsRect.setHeight(scrollbarWidget.slider().preferredSize().height());
         }
         if (contentsRect.intersects(damageRect))
-            sliderGadget->render(graphicsContext.platformContext()->cr(), contentsRect);
+            scrollbarWidget.slider().render(graphicsContext.platformContext()->cr(), contentsRect);
     }
 
     if (opacity != 1) {
@@ -846,33 +801,11 @@
 #if GTK_CHECK_VERSION(3, 20, 0)
 int ScrollbarThemeGtk::scrollbarThickness(ScrollbarControlSize, ScrollbarExpansionState)
 {
-    RenderThemeGadget::Info info = { RenderThemeGadget::Type::Scrollbar, "scrollbar", GTK_STATE_FLAG_PRELIGHT, { "vertical", "right", "hovering" } };
-    if (m_usesOverlayScrollbars)
-        info.classList.append("overlay-indicator");
-    auto scrollbarGadget = RenderThemeGadget::create(info);
-    info.type = RenderThemeGadget::Type::Generic;
-    info.name = "contents";
-    info.state = GTK_STATE_FLAG_NORMAL;
-    info.classList.clear();
-    Vector<RenderThemeGadget::Info> children;
-    auto steppers = static_cast<RenderThemeScrollbarGadget*>(scrollbarGadget.get())->steppers();
-    if (steppers.contains(RenderThemeScrollbarGadget::Steppers::Backward))
-        children.append({ RenderThemeGadget::Type::Generic, "button", GTK_STATE_FLAG_NORMAL, { "up" } });
-    if (steppers.contains(RenderThemeScrollbarGadget::Steppers::SecondaryForward))
-        children.append({ RenderThemeGadget::Type::Generic, "button", GTK_STATE_FLAG_NORMAL, { "down" } });
-    unsigned troughPositon = children.size();
-    children.append({ RenderThemeGadget::Type::Generic, "trough", GTK_STATE_FLAG_PRELIGHT, { } });
-    if (steppers.contains(RenderThemeScrollbarGadget::Steppers::SecondaryBackward))
-        children.append({ RenderThemeGadget::Type::Generic, "button", GTK_STATE_FLAG_NORMAL, { "up" } });
-    if (steppers.contains(RenderThemeScrollbarGadget::Steppers::Forward))
-        children.append({ RenderThemeGadget::Type::Generic, "button", GTK_STATE_FLAG_NORMAL, { "down" } });
-    auto contentsGadget = std::make_unique<RenderThemeBoxGadget>(info, GTK_ORIENTATION_VERTICAL, children, scrollbarGadget.get());
-    info.name = "slider";
-    auto sliderGadget = RenderThemeGadget::create(info, contentsGadget->child(troughPositon));
-    IntSize contentsPreferredSize = contentsGadget->preferredSize();
-    contentsPreferredSize = contentsPreferredSize.expandedTo(sliderGadget->preferredSize());
-    IntSize preferredSize = contentsPreferredSize + scrollbarGadget->preferredSize() - scrollbarGadget->minimumSize();
-
+    auto& scrollbarWidget = static_cast<RenderThemeScrollbar&>(RenderThemeWidget::getOrCreate(RenderThemeWidget::Type::VerticalScrollbarRight));
+    scrollbarWidget.scrollbar().setState(GTK_STATE_FLAG_PRELIGHT);
+    IntSize contentsPreferredSize = scrollbarWidget.contents().preferredSize();
+    contentsPreferredSize = contentsPreferredSize.expandedTo(scrollbarWidget.slider().preferredSize());
+    IntSize preferredSize = contentsPreferredSize + scrollbarWidget.scrollbar().preferredSize() - scrollbarWidget.scrollbar().minimumSize();
     return preferredSize.width();
 }
 #else
@@ -887,18 +820,9 @@
 #if GTK_CHECK_VERSION(3, 20, 0)
 int ScrollbarThemeGtk::minimumThumbLength(Scrollbar& scrollbar)
 {
-    RenderThemeGadget::Info info = { RenderThemeGadget::Type::Scrollbar, "scrollbar", GTK_STATE_FLAG_PRELIGHT, { "vertical", "right", "hovering" } };
-    if (m_usesOverlayScrollbars)
-        info.classList.append("overlay-indicator");
-    auto scrollbarGadget = RenderThemeGadget::create(info);
-    info.type = RenderThemeGadget::Type::Generic;
-    info.name = "contents";
-    info.state = GTK_STATE_FLAG_NORMAL;
-    info.classList.clear();
-    Vector<RenderThemeGadget::Info> children = {{ RenderThemeGadget::Type::Generic, "trough", GTK_STATE_FLAG_PRELIGHT, { } } };
-    auto contentsGadget = std::make_unique<RenderThemeBoxGadget>(info, GTK_ORIENTATION_VERTICAL, children, scrollbarGadget.get());
-    info.name = "slider";
-    IntSize minSize = RenderThemeGadget::create(info, contentsGadget->child(0))->minimumSize();
+    auto& scrollbarWidget = static_cast<RenderThemeScrollbar&>(RenderThemeWidget::getOrCreate(RenderThemeWidget::Type::VerticalScrollbarRight));
+    scrollbarWidget.scrollbar().setState(GTK_STATE_FLAG_PRELIGHT);
+    IntSize minSize = scrollbarWidget.slider().minimumSize();
     return scrollbar.orientation() == VerticalScrollbar ? minSize.height() : minSize.width();
 }
 #else

Modified: trunk/Source/WebCore/rendering/RenderThemeGtk.cpp (217701 => 217702)


--- trunk/Source/WebCore/rendering/RenderThemeGtk.cpp	2017-06-02 05:55:28 UTC (rev 217701)
+++ trunk/Source/WebCore/rendering/RenderThemeGtk.cpp	2017-06-02 06:40:36 UTC (rev 217702)
@@ -44,7 +44,7 @@
 #include "RenderBox.h"
 #include "RenderObject.h"
 #include "RenderProgress.h"
-#include "RenderThemeGadget.h"
+#include "RenderThemeWidget.h"
 #include "ScrollbarThemeGtk.h"
 #include "StringTruncator.h"
 #include "TimeRanges.h"
@@ -185,6 +185,7 @@
 
     switch (themePart) {
     case Entry:
+    case EntrySelection:
         gtk_widget_path_append_type(path.get(), GTK_TYPE_ENTRY);
         gtk_widget_path_iter_add_class(path.get(), -1, GTK_STYLE_CLASS_ENTRY);
         break;
@@ -527,23 +528,11 @@
     if (!style.width().isIntrinsicOrAuto() && !style.height().isAuto())
         return;
 
-    RenderThemeGadget::Info info = {
-        .type = RenderThemeGadget::Type::Generic,
-        .name = themePart == CheckButton ? "checkbutton" : "radiobutton",
-        .state = GTK_STATE_FLAG_NORMAL,
-        .classList = { }
-    };
-    auto parentGadget = RenderThemeGadget::create(info);
-    if (themePart == CheckButton) {
-        info.type = RenderThemeGadget::Type::Check;
-        info.name = "check";
-    } else {
-        info.type = RenderThemeGadget::Type::Radio;
-        info.name = "radio";
-    }
-    auto gadget = RenderThemeToggleGadget::create(info);
-    IntSize preferredSize = parentGadget->preferredSize();
-    preferredSize = preferredSize.expandedTo(gadget->preferredSize());
+    auto& toggleWidget = static_cast<RenderThemeToggleButton&>(RenderThemeWidget::getOrCreate(themePart == CheckButton ? RenderThemeWidget::Type::CheckButton : RenderThemeWidget::Type::RadioButton));
+    toggleWidget.button().setState(GTK_STATE_FLAG_NORMAL);
+    toggleWidget.toggle().setState(GTK_STATE_FLAG_NORMAL);
+    IntSize preferredSize = toggleWidget.button().preferredSize();
+    preferredSize = preferredSize.expandedTo(toggleWidget.toggle().preferredSize());
 
     if (style.width().isIntrinsicOrAuto())
         style.setWidth(Length(preferredSize.width(), Fixed));
@@ -556,23 +545,10 @@
 {
     ASSERT(themePart == CheckButton || themePart == RadioButton);
 
-    RenderThemeGadget::Info parentInfo = {
-        .type = RenderThemeGadget::Type::Generic,
-        .name = themePart == CheckButton ? "checkbutton" : "radiobutton",
-        .state = themePartStateFlags(*theme, themePart, renderObject),
-        .classList = { "text-button" }
-    };
-    auto parentGadget = RenderThemeGadget::create(parentInfo);
-    RenderThemeGadget::Info info;
-    info.state = parentInfo.state;
-    if (themePart == CheckButton) {
-        info.type = RenderThemeGadget::Type::Check;
-        info.name = "check";
-    } else {
-        info.type = RenderThemeGadget::Type::Radio;
-        info.name = "radio";
-    }
-    auto gadget = RenderThemeGadget::create(info, parentGadget.get());
+    auto& toggleWidget = static_cast<RenderThemeToggleButton&>(RenderThemeWidget::getOrCreate(themePart == CheckButton ? RenderThemeWidget::Type::CheckButton : RenderThemeWidget::Type::RadioButton));
+    auto toggleState = themePartStateFlags(*theme, themePart, renderObject);
+    toggleWidget.button().setState(toggleState);
+    toggleWidget.toggle().setState(toggleState);
 
     FloatRect rect = fullRect;
     // Some themes do not render large toggle buttons properly, so we simply
@@ -579,14 +555,14 @@
     // shrink the rectangle back down to the default size and then center it
     // in the full toggle button region. The reason for not simply forcing toggle
     // buttons to be a smaller size is that we don't want to break site layouts.
-    IntSize preferredSize = parentGadget->preferredSize();
-    preferredSize = preferredSize.expandedTo(gadget->preferredSize());
+    IntSize preferredSize = toggleWidget.button().preferredSize();
+    preferredSize = preferredSize.expandedTo(toggleWidget.toggle().preferredSize());
     shrinkToMinimumSizeAndCenterRectangle(rect, preferredSize);
-    parentGadget->render(paintInfo.context().platformContext()->cr(), rect);
-    gadget->render(paintInfo.context().platformContext()->cr(), rect);
+    toggleWidget.button().render(paintInfo.context().platformContext()->cr(), rect);
+    toggleWidget.toggle().render(paintInfo.context().platformContext()->cr(), rect);
 
     if (theme->isFocused(renderObject))
-        parentGadget->renderFocus(paintInfo.context().platformContext()->cr(), rect);
+        toggleWidget.button().renderFocus(paintInfo.context().platformContext()->cr(), rect);
 }
 #else
 static void setToggleSize(RenderThemePart themePart, RenderStyle& style)
@@ -683,13 +659,11 @@
 #if GTK_CHECK_VERSION(3, 20, 0)
 bool RenderThemeGtk::paintButton(const RenderObject& renderObject, const PaintInfo& paintInfo, const IntRect& rect)
 {
-    RenderThemeGadget::Info info = { RenderThemeGadget::Type::Generic, "button", themePartStateFlags(*this, Button, renderObject), { "text-button" } };
-    if (isDefault(renderObject))
-        info.classList.append("default");
-    auto gadget = RenderThemeGadget::create(info);
-    gadget->render(paintInfo.context().platformContext()->cr(), rect);
+    auto& buttonWidget = static_cast<RenderThemeButton&>(RenderThemeWidget::getOrCreate(isDefault(renderObject) ? RenderThemeWidget::Type::ButtonDefault : RenderThemeWidget::Type::Button));
+    buttonWidget.button().setState(themePartStateFlags(*this, Button, renderObject));
+    buttonWidget.button().render(paintInfo.context().platformContext()->cr(), rect);
     if (isFocused(renderObject))
-        gadget->renderFocus(paintInfo.context().platformContext()->cr(), rect);
+        buttonWidget.button().renderFocus(paintInfo.context().platformContext()->cr(), rect);
     return false;
 }
 #else
@@ -771,14 +745,11 @@
 static Color menuListColor(const Element* element)
 {
 #if GTK_CHECK_VERSION(3, 20, 0)
-    RenderThemeGadget::Info info { RenderThemeGadget::Type::Generic, "combobox", element->isDisabledFormControl() ? GTK_STATE_FLAG_INSENSITIVE : GTK_STATE_FLAG_NORMAL, { } };
-    auto comboGadget = RenderThemeGadget::create(info);
-    Vector<RenderThemeGadget::Info> children {
-        { RenderThemeGadget::Type::Generic, "button", info.state, { "combo" } }
-    };
-    info.name = "box";
-    info.classList = { "horizontal", "linked" };
-    return RenderThemeBoxGadget(info, GTK_ORIENTATION_HORIZONTAL, children, comboGadget.get()).child(0)->color();
+    auto& comboWidget = static_cast<RenderThemeComboBox&>(RenderThemeWidget::getOrCreate(RenderThemeWidget::Type::ComboBox));
+    GtkStateFlags state = element->isDisabledFormControl() ? GTK_STATE_FLAG_INSENSITIVE : GTK_STATE_FLAG_NORMAL;
+    comboWidget.comboBox().setState(state);
+    comboWidget.button().setState(state);
+    return comboWidget.button().color();
 #else
     GRefPtr<GtkStyleContext> parentStyleContext = createStyleContext(ComboBox);
     GRefPtr<GtkStyleContext> buttonStyleContext = createStyleContext(ComboBoxButton, parentStyleContext.get());
@@ -824,24 +795,14 @@
     if (style.appearance() == NoControlPart)
         return LengthBox(0);
 
-    RenderThemeGadget::Info info = { RenderThemeGadget::Type::Generic, "combobox", GTK_STATE_FLAG_NORMAL, { } };
-    auto comboGadget = RenderThemeGadget::create(info);
-    Vector<RenderThemeGadget::Info> children = {
-        { RenderThemeGadget::Type::Generic, "button", GTK_STATE_FLAG_NORMAL, { "combo" } }
-    };
-    info.name = "box";
-    info.classList = { "horizontal", "linked" };
-    auto boxGadget = std::make_unique<RenderThemeBoxGadget>(info, GTK_ORIENTATION_HORIZONTAL, children, comboGadget.get());
-    RenderThemeGadget* buttonGadget = boxGadget->child(0);
-    info.classList.removeLast();
-    auto buttonBoxGadget = RenderThemeGadget::create(info, buttonGadget);
-    info.name = "arrow";
-    info.classList = { };
-    auto arrowGadget = RenderThemeGadget::create(info, buttonBoxGadget.get());
-    GtkBorder comboContentsBox = comboGadget->contentsBox();
-    GtkBorder boxContentsBox = boxGadget->contentsBox();
-    GtkBorder buttonContentsBox = buttonGadget->contentsBox();
-    GtkBorder buttonBoxContentsBox = buttonBoxGadget->contentsBox();
+    auto& comboWidget = static_cast<RenderThemeComboBox&>(RenderThemeWidget::getOrCreate(RenderThemeWidget::Type::ComboBox));
+    comboWidget.comboBox().setState(GTK_STATE_FLAG_NORMAL);
+    comboWidget.button().setState(GTK_STATE_FLAG_NORMAL);
+    comboWidget.arrow().setState(GTK_STATE_FLAG_NORMAL);
+    GtkBorder comboContentsBox = comboWidget.comboBox().contentsBox();
+    GtkBorder boxContentsBox = comboWidget.box().contentsBox();
+    GtkBorder buttonContentsBox = comboWidget.button().contentsBox();
+    GtkBorder buttonBoxContentsBox = comboWidget.buttonBox().contentsBox();
     GtkBorder padding;
     padding.left = comboContentsBox.left + boxContentsBox.left + buttonContentsBox.left + buttonBoxContentsBox.left;
     padding.right = comboContentsBox.right + boxContentsBox.right + buttonContentsBox.right + buttonBoxContentsBox.right;
@@ -848,7 +809,7 @@
     padding.top = comboContentsBox.top + boxContentsBox.top + buttonContentsBox.top + buttonBoxContentsBox.top;
     padding.bottom = comboContentsBox.bottom + boxContentsBox.bottom + buttonContentsBox.bottom + buttonBoxContentsBox.bottom;
 
-    auto arrowSize = arrowGadget->preferredSize();
+    auto arrowSize = comboWidget.arrow().preferredSize();
     return LengthBox(padding.top, padding.right + (style.direction() == LTR ? arrowSize.width() : 0),
         padding.bottom, padding.left + (style.direction() == RTL ? arrowSize.width() : 0));
 }
@@ -855,31 +816,21 @@
 
 bool RenderThemeGtk::paintMenuList(const RenderObject& renderObject, const PaintInfo& paintInfo, const FloatRect& rect)
 {
-    RenderThemeGadget::Info info = { RenderThemeGadget::Type::Generic, "combobox", themePartStateFlags(*this, ComboBoxButton, renderObject), { } };
-    auto comboGadget = RenderThemeGadget::create(info);
-    Vector<RenderThemeGadget::Info> children = {
-        { RenderThemeGadget::Type::Generic, "button", info.state, { "combo" } }
-    };
-    info.name = "box";
-    info.classList = { "horizontal", "linked" };
-    auto boxGadget = std::make_unique<RenderThemeBoxGadget>(info, GTK_ORIENTATION_HORIZONTAL, children, comboGadget.get());
-    RenderThemeGadget* buttonGadget = boxGadget->child(0);
-    info.classList.removeLast();
-    auto buttonBoxGadget = RenderThemeGadget::create(info, buttonGadget);
-    info.type = RenderThemeGadget::Type::Arrow;
-    info.name = "arrow";
-    info.classList = { };
-    auto arrowGadget = RenderThemeGadget::create(info, buttonBoxGadget.get());
+    auto& comboWidget = static_cast<RenderThemeComboBox&>(RenderThemeWidget::getOrCreate(RenderThemeWidget::Type::ComboBox));
+    auto comboState = themePartStateFlags(*this, ComboBoxButton, renderObject);
+    comboWidget.comboBox().setState(comboState);
+    comboWidget.button().setState(comboState);
+    comboWidget.arrow().setState(comboState);
 
     cairo_t* cr = paintInfo.context().platformContext()->cr();
-    comboGadget->render(cr, rect);
-    boxGadget->render(cr, rect);
+    comboWidget.comboBox().render(cr, rect);
+    comboWidget.box().render(cr, rect);
     FloatRect contentsRect;
-    buttonGadget->render(cr, rect, &contentsRect);
-    buttonBoxGadget->render(cr, contentsRect);
-    arrowGadget->render(cr, contentsRect);
+    comboWidget.button().render(cr, rect, &contentsRect);
+    comboWidget.buttonBox().render(cr, contentsRect);
+    comboWidget.arrow().render(cr, contentsRect);
     if (isFocused(renderObject))
-        buttonGadget->renderFocus(cr, rect);
+        comboWidget.button().renderFocus(cr, rect);
 
     return false;
 }
@@ -986,24 +937,16 @@
         return;
 
     // Spinbuttons need a minimum height to be rendered correctly.
-    RenderThemeGadget::Info info = { RenderThemeGadget::Type::Generic, "spinbutton", GTK_STATE_FLAG_NORMAL, { "horizontal" } };
-    auto spinbuttonGadget = RenderThemeGadget::create(info);
-    info.type = RenderThemeGadget::Type::TextField;
-    info.name = "entry";
-    info.classList.clear();
-    auto entryGadget = RenderThemeGadget::create(info, spinbuttonGadget.get());
-    info.type = RenderThemeGadget::Type::Icon;
-    info.name = "button";
-    info.classList.append("up");
-    auto buttonUpGadget = RenderThemeGadget::create(info, spinbuttonGadget.get());
-    static_cast<RenderThemeIconGadget*>(buttonUpGadget.get())->setIconSize(RenderThemeIconGadget::IconSizeGtk::Menu);
-    info.classList[0] = "down";
-    auto buttonDownGadget = RenderThemeGadget::create(info, spinbuttonGadget.get());
-    static_cast<RenderThemeIconGadget*>(buttonDownGadget.get())->setIconSize(RenderThemeIconGadget::IconSizeGtk::Menu);
-    IntSize preferredSize = spinbuttonGadget->preferredSize();
-    preferredSize = preferredSize.expandedTo(entryGadget->preferredSize());
-    IntSize upPreferredSize = preferredSize.expandedTo(buttonUpGadget->preferredSize());
-    IntSize downPreferredSize = preferredSize.expandedTo(buttonDownGadget->preferredSize());
+    auto& spinButtonWidget = static_cast<RenderThemeSpinButton&>(RenderThemeWidget::getOrCreate(RenderThemeWidget::Type::SpinButton));
+    spinButtonWidget.spinButton().setState(GTK_STATE_FLAG_NORMAL);
+    spinButtonWidget.entry().setState(GTK_STATE_FLAG_NORMAL);
+    spinButtonWidget.up().setState(GTK_STATE_FLAG_NORMAL);
+    spinButtonWidget.down().setState(GTK_STATE_FLAG_NORMAL);
+
+    IntSize preferredSize = spinButtonWidget.spinButton().preferredSize();
+    preferredSize = preferredSize.expandedTo(spinButtonWidget.entry().preferredSize());
+    IntSize upPreferredSize = preferredSize.expandedTo(spinButtonWidget.up().preferredSize());
+    IntSize downPreferredSize = preferredSize.expandedTo(spinButtonWidget.down().preferredSize());
     int height = std::max(upPreferredSize.height(), downPreferredSize.height());
     style.setMinHeight(Length(height, Fixed));
 }
@@ -1010,20 +953,18 @@
 
 bool RenderThemeGtk::paintTextField(const RenderObject& renderObject, const PaintInfo& paintInfo, const FloatRect& rect)
 {
-    RenderThemeGadget::Info info = { RenderThemeGadget::Type::TextField, "entry", themePartStateFlags(*this, Entry, renderObject), { } };
-    std::unique_ptr<RenderThemeGadget> parentGadget;
     if (is<HTMLInputElement>(renderObject.node()) && shouldHaveSpinButton(downcast<HTMLInputElement>(*renderObject.node()))) {
-        info.name = "spinbutton";
-        info.classList.append("horizontal");
-        parentGadget = RenderThemeTextFieldGadget::create(info);
-        info.name = "entry";
-        info.classList.clear();
+        auto& spinButtonWidget = static_cast<RenderThemeSpinButton&>(RenderThemeWidget::getOrCreate(RenderThemeWidget::Type::SpinButton));
+        auto spinButtonState = themePartStateFlags(*this, Entry, renderObject);
+        spinButtonWidget.spinButton().setState(spinButtonState);
+        spinButtonWidget.entry().setState(spinButtonState);
+        spinButtonWidget.spinButton().render(paintInfo.context().platformContext()->cr(), rect);
+        spinButtonWidget.entry().render(paintInfo.context().platformContext()->cr(), rect);
+    } else {
+        auto& entryWidget = static_cast<RenderThemeEntry&>(RenderThemeWidget::getOrCreate(RenderThemeWidget::Type::Entry));
+        entryWidget.entry().setState(themePartStateFlags(*this, Entry, renderObject));
+        entryWidget.entry().render(paintInfo.context().platformContext()->cr(), rect);
     }
-
-    auto entryGadget = RenderThemeTextFieldGadget::create(info, parentGadget.get());
-    if (parentGadget)
-        parentGadget->render(paintInfo.context().platformContext()->cr(), rect);
-    entryGadget->render(paintInfo.context().platformContext()->cr(), rect);
     return false;
 }
 #else
@@ -1065,20 +1006,16 @@
 static void adjustSearchFieldIconStyle(RenderThemePart themePart, RenderStyle& style)
 {
     ASSERT(themePart == EntryIconLeft || themePart == EntryIconRight);
-    RenderThemeGadget::Info info = { RenderThemeGadget::Type::TextField, "entry", GTK_STATE_FLAG_NORMAL, { } };
-    auto parentGadget = RenderThemeGadget::create(info);
-    info.type = RenderThemeGadget::Type::Icon;
-    info.name = "image";
-    if (themePart == EntryIconLeft)
-        info.classList.append("left");
-    else
-        info.classList.append("right");
-    auto gadget = RenderThemeIconGadget::create(info, parentGadget.get());
+    auto& searchEntryWidget = static_cast<RenderThemeSearchEntry&>(RenderThemeWidget::getOrCreate(RenderThemeWidget::Type::SearchEntry));
+    searchEntryWidget.entry().setState(GTK_STATE_FLAG_NORMAL);
+    searchEntryWidget.leftIcon().setState(GTK_STATE_FLAG_NORMAL);
+    searchEntryWidget.rightIcon().setState(GTK_STATE_FLAG_NORMAL);
 
     // Get the icon size based on the font size.
-    static_cast<RenderThemeIconGadget*>(gadget.get())->setIconSize(style.fontSize());
-    IntSize preferredSize = gadget->preferredSize();
-    GtkBorder contentsBox = parentGadget->contentsBox();
+    auto& icon = static_cast<RenderThemeIconGadget&>(themePart == EntryIconLeft ? searchEntryWidget.leftIcon() : searchEntryWidget.rightIcon());
+    icon.setIconSize(style.fontSize());
+    IntSize preferredSize = icon.preferredSize();
+    GtkBorder contentsBox = searchEntryWidget.entry().contentsBox();
     if (themePart == EntryIconLeft)
         preferredSize.expand(contentsBox.left, contentsBox.top + contentsBox.bottom);
     else
@@ -1165,23 +1102,12 @@
 static bool paintSearchFieldIcon(RenderThemeGtk* theme, RenderThemePart themePart, const RenderBox& renderObject, const PaintInfo& paintInfo, const IntRect& rect)
 {
     ASSERT(themePart == EntryIconLeft || themePart == EntryIconRight);
-    RenderThemeGadget::Info info = { RenderThemeGadget::Type::TextField, "entry", themePartStateFlags(*theme, Entry, renderObject), { } };
-    auto parentGadget = RenderThemeGadget::create(info);
-    info.type = RenderThemeGadget::Type::Icon;
-    info.state = themePartStateFlags(*theme, themePart, renderObject);
-    info.name = "image";
-    if (themePart == EntryIconLeft)
-        info.classList.append("left");
-    else
-        info.classList.append("right");
-    auto gadget = RenderThemeGadget::create(info, parentGadget.get());
-    auto* gadgetIcon = static_cast<RenderThemeIconGadget*>(gadget.get());
-    gadgetIcon->setIconSize(renderObject.style().fontSize());
-    if (themePart == EntryIconLeft)
-        gadgetIcon->setIconName("edit-find-symbolic");
-    else
-        gadgetIcon->setIconName("edit-clear-symbolic");
-    GtkBorder contentsBox = parentGadget->contentsBox();
+    auto& searchEntryWidget = static_cast<RenderThemeSearchEntry&>(RenderThemeWidget::getOrCreate(RenderThemeWidget::Type::SearchEntry));
+    searchEntryWidget.entry().setState(themePartStateFlags(*theme, Entry, renderObject));
+    auto& icon = static_cast<RenderThemeIconGadget&>(themePart == EntryIconLeft ? searchEntryWidget.leftIcon() : searchEntryWidget.rightIcon());
+    icon.setState(themePartStateFlags(*theme, themePart, renderObject));
+    icon.setIconSize(renderObject.style().fontSize());
+    GtkBorder contentsBox = searchEntryWidget.entry().contentsBox();
     IntRect iconRect = rect;
     if (themePart == EntryIconLeft) {
         iconRect.move(contentsBox.left, contentsBox.top);
@@ -1188,7 +1114,7 @@
         iconRect.contract(contentsBox.left, contentsBox.top + contentsBox.bottom);
     } else
         iconRect.contract(contentsBox.right, contentsBox.top + contentsBox.bottom);
-    return !gadget->render(paintInfo.context().platformContext()->cr(), iconRect);
+    return !icon.render(paintInfo.context().platformContext()->cr(), iconRect);
 }
 bool RenderThemeGtk::paintSearchFieldResultsDecorationPart(const RenderBox& renderObject, const PaintInfo& paintInfo, const IntRect& rect)
 {
@@ -1309,26 +1235,20 @@
     ControlPart part = renderObject.style().appearance();
     ASSERT(part == SliderHorizontalPart || part == SliderVerticalPart);
 
-    RenderThemeGadget::Info info = { RenderThemeGadget::Type::Generic, "scale", themePartStateFlags(*this, Scale, renderObject), { } };
-    if (part == SliderHorizontalPart)
-        info.classList.append("horizontal");
-    else
-        info.classList.append("vertical");
-    auto scaleGadget = RenderThemeGadget::create(info);
-    info.name = "contents";
-    info.classList.clear();
-    auto contentsGadget = RenderThemeGadget::create(info, scaleGadget.get());
-    info.name = "trough";
-    auto troughGadget = RenderThemeGadget::create(info, contentsGadget.get());
-    info.name = "slider";
-    auto sliderGadget = RenderThemeGadget::create(info, troughGadget.get());
-    info.name = "highlight";
-    auto highlightGadget = RenderThemeGadget::create(info, troughGadget.get());
+    auto& sliderWidget = static_cast<RenderThemeSlider&>(RenderThemeWidget::getOrCreate(part == SliderHorizontalPart ? RenderThemeWidget::Type::HorizontalSlider : RenderThemeWidget::Type::VerticalSlider));
+    auto scaleState = themePartStateFlags(*this, Scale, renderObject);
+    auto& scale = sliderWidget.scale();
+    scale.setState(scaleState);
+    auto& contents = sliderWidget.contents();
+    auto& trough = sliderWidget.trough();
+    trough.setState(scaleState);
+    auto& slider = sliderWidget.slider();
+    auto& highlight = sliderWidget.highlight();
 
     // The given rectangle is not calculated based on the scale size, but all the margins and paddings are based on it.
-    IntSize preferredSize = scaleGadget->preferredSize();
-    preferredSize = preferredSize.expandedTo(contentsGadget->preferredSize());
-    preferredSize = preferredSize.expandedTo(troughGadget->preferredSize());
+    IntSize preferredSize = scale.preferredSize();
+    preferredSize = preferredSize.expandedTo(contents.preferredSize());
+    preferredSize = preferredSize.expandedTo(trough.preferredSize());
     FloatRect trackRect = rect;
     if (part == SliderHorizontalPart) {
         trackRect.move(0, rect.height() / 2 - (preferredSize.height() / 2));
@@ -1339,17 +1259,17 @@
     }
 
     FloatRect contentsRect;
-    scaleGadget->render(paintInfo.context().platformContext()->cr(), trackRect, &contentsRect);
-    contentsGadget->render(paintInfo.context().platformContext()->cr(), contentsRect, &contentsRect);
+    scale.render(paintInfo.context().platformContext()->cr(), trackRect, &contentsRect);
+    contents.render(paintInfo.context().platformContext()->cr(), contentsRect, &contentsRect);
     // Scale trough defines its size querying slider and highlight.
     if (part == SliderHorizontalPart)
-        contentsRect.setHeight(troughGadget->preferredSize().height() + std::max(sliderGadget->preferredSize().height(), highlightGadget->preferredSize().height()));
+        contentsRect.setHeight(trough.preferredSize().height() + std::max(slider.preferredSize().height(), highlight.preferredSize().height()));
     else
-        contentsRect.setWidth(troughGadget->preferredSize().width() + std::max(sliderGadget->preferredSize().width(), highlightGadget->preferredSize().width()));
+        contentsRect.setWidth(trough.preferredSize().width() + std::max(slider.preferredSize().width(), highlight.preferredSize().width()));
     FloatRect troughRect = contentsRect;
-    troughGadget->render(paintInfo.context().platformContext()->cr(), troughRect, &contentsRect);
+    trough.render(paintInfo.context().platformContext()->cr(), troughRect, &contentsRect);
     if (isFocused(renderObject))
-        troughGadget->renderFocus(paintInfo.context().platformContext()->cr(), troughRect);
+        trough.renderFocus(paintInfo.context().platformContext()->cr(), troughRect);
 
     LayoutPoint thumbLocation;
     if (is<HTMLInputElement>(renderObject.node())) {
@@ -1366,7 +1286,7 @@
             contentsRect.setWidth(thumbLocation.x());
     } else
         contentsRect.setHeight(thumbLocation.y());
-    highlightGadget->render(paintInfo.context().platformContext()->cr(), contentsRect);
+    highlight.render(paintInfo.context().platformContext()->cr(), contentsRect);
 
     return false;
 }
@@ -1377,26 +1297,14 @@
     if (part != SliderThumbHorizontalPart && part != SliderThumbVerticalPart)
         return;
 
-    RenderThemeGadget::Info info = { RenderThemeGadget::Type::Generic, "scale", GTK_STATE_FLAG_NORMAL, { } };
-    if (part == SliderHorizontalPart)
-        info.classList.append("horizontal");
-    else
-        info.classList.append("vertical");
-    auto scaleGadget = RenderThemeGadget::create(info);
-    info.name = "contents";
-    info.classList.clear();
-    auto contentsGadget = RenderThemeGadget::create(info, scaleGadget.get());
-    info.name = "trough";
-    auto troughGadget = RenderThemeGadget::create(info, contentsGadget.get());
-    info.name = "slider";
-    auto sliderGadget = RenderThemeGadget::create(info, troughGadget.get());
-    info.name = "highlight";
-    auto highlightGadget = RenderThemeGadget::create(info, troughGadget.get());
+    auto& sliderWidget = static_cast<RenderThemeSlider&>(RenderThemeWidget::getOrCreate(part == SliderHorizontalPart ? RenderThemeWidget::Type::HorizontalSlider : RenderThemeWidget::Type::VerticalSlider));
+    sliderWidget.scale().setState(GTK_STATE_FLAG_NORMAL);
+    sliderWidget.trough().setState(GTK_STATE_FLAG_NORMAL);
 
-    IntSize preferredSize = scaleGadget->preferredSize();
-    preferredSize = preferredSize.expandedTo(contentsGadget->preferredSize());
-    preferredSize = preferredSize.expandedTo(troughGadget->preferredSize());
-    preferredSize = preferredSize.expandedTo(sliderGadget->preferredSize());
+    IntSize preferredSize = sliderWidget.scale().preferredSize();
+    preferredSize = preferredSize.expandedTo(sliderWidget.contents().preferredSize());
+    preferredSize = preferredSize.expandedTo(sliderWidget.trough().preferredSize());
+    preferredSize = preferredSize.expandedTo(sliderWidget.slider().preferredSize());
     if (part == SliderThumbHorizontalPart) {
         style.setWidth(Length(preferredSize.width(), Fixed));
         style.setHeight(Length(preferredSize.height(), Fixed));
@@ -1412,26 +1320,20 @@
     ControlPart part = renderObject.style().appearance();
     ASSERT(part == SliderThumbHorizontalPart || part == SliderThumbVerticalPart);
 
-    RenderThemeGadget::Info info = { RenderThemeGadget::Type::Generic, "scale", themePartStateFlags(*this, Scale, renderObject), { } };
-    if (part == SliderHorizontalPart)
-        info.classList.append("horizontal");
-    else
-        info.classList.append("vertical");
-    auto scaleGadget = RenderThemeGadget::create(info);
-    info.name = "contents";
-    info.classList.clear();
-    auto contentsGadget = RenderThemeGadget::create(info, scaleGadget.get());
-    info.name = "trough";
-    auto troughGadget = RenderThemeGadget::create(info, contentsGadget.get());
-    info.name = "slider";
-    info.state = themePartStateFlags(*this, ScaleSlider, renderObject);
-    auto sliderGadget = RenderThemeGadget::create(info, troughGadget.get());
-    info.name = "highlight";
-    auto highlightGadget = RenderThemeGadget::create(info, troughGadget.get());
+    auto& sliderWidget = static_cast<RenderThemeSlider&>(RenderThemeWidget::getOrCreate(part == SliderThumbHorizontalPart ? RenderThemeWidget::Type::HorizontalSlider : RenderThemeWidget::Type::VerticalSlider));
+    auto scaleState = themePartStateFlags(*this, Scale, renderObject);
+    auto& scale = sliderWidget.scale();
+    scale.setState(scaleState);
+    auto& contents = sliderWidget.contents();
+    auto& trough = sliderWidget.trough();
+    trough.setState(scaleState);
+    auto& slider = sliderWidget.slider();
+    slider.setState(themePartStateFlags(*this, ScaleSlider, renderObject));
+    auto& highlight = sliderWidget.highlight();
 
-    GtkBorder scaleContentsBox = scaleGadget->contentsBox();
-    GtkBorder contentsContentsBox = contentsGadget->contentsBox();
-    GtkBorder troughContentsBox = troughGadget->contentsBox();
+    GtkBorder scaleContentsBox = scale.contentsBox();
+    GtkBorder contentsContentsBox = contents.contentsBox();
+    GtkBorder troughContentsBox = trough.contentsBox();
     GtkBorder padding;
     padding.left = scaleContentsBox.left + contentsContentsBox.left + troughContentsBox.left;
     padding.right = scaleContentsBox.right + contentsContentsBox.right + troughContentsBox.right;
@@ -1439,11 +1341,11 @@
     padding.bottom = scaleContentsBox.bottom + contentsContentsBox.bottom + troughContentsBox.bottom;
 
     // Scale trough defines its size querying slider and highlight.
-    int troughHeight = troughGadget->preferredSize().height() + std::max(sliderGadget->preferredSize().height(), highlightGadget->preferredSize().height());
+    int troughHeight = trough.preferredSize().height() + std::max(slider.preferredSize().height(), highlight.preferredSize().height());
     IntRect sliderRect(rect.location(), IntSize(troughHeight, troughHeight));
     sliderRect.move(padding.left, padding.top);
     sliderRect.contract(padding.left + padding.right, padding.top + padding.bottom);
-    sliderGadget->render(paintInfo.context().platformContext()->cr(), sliderRect);
+    slider.render(paintInfo.context().platformContext()->cr(), sliderRect);
     return false;
 }
 #else
@@ -1540,23 +1442,11 @@
 #if GTK_CHECK_VERSION(3, 20, 0)
 IntRect RenderThemeGtk::progressBarRectForBounds(const RenderObject& renderObject, const IntRect& bounds) const
 {
-    RenderThemeGadget::Info info = { RenderThemeGadget::Type::Generic, "progressbar", GTK_STATE_FLAG_NORMAL, { "horizontal" } };
-    auto progressBarGadget = RenderThemeGadget::create(info);
-    info.name = "trough";
-    info.classList.clear();
-    auto troughGadget = RenderThemeGadget::create(info, progressBarGadget.get());
-    info.name = "progress";
-    if (renderObject.style().direction() == RTL)
-        info.classList.append("right");
-    else
-        info.classList.append("left");
     const auto& renderProgress = downcast<RenderProgress>(renderObject);
-    if (renderProgress.isDeterminate())
-        info.classList.append("pulse");
-    auto progressGadget = RenderThemeGadget::create(info, troughGadget.get());
-    IntSize preferredSize = progressBarGadget->preferredSize();
-    preferredSize = preferredSize.expandedTo(troughGadget->preferredSize());
-    preferredSize = preferredSize.expandedTo(progressGadget->preferredSize());
+    auto& progressBarWidget = static_cast<RenderThemeProgressBar&>(RenderThemeWidget::getOrCreate(renderProgress.isDeterminate() ? RenderThemeProgressBar::Type::ProgressBar : RenderThemeProgressBar::Type::IndeterminateProgressBar));
+    IntSize preferredSize = progressBarWidget.progressBar().preferredSize();
+    preferredSize = preferredSize.expandedTo(progressBarWidget.trough().preferredSize());
+    preferredSize = preferredSize.expandedTo(progressBarWidget.progress().preferredSize());
     return IntRect(bounds.x(), bounds.y(), bounds.width(), preferredSize.height());
 }
 
@@ -1565,24 +1455,11 @@
     if (!renderObject.isProgress())
         return true;
 
-    RenderThemeGadget::Info info = { RenderThemeGadget::Type::Generic, "progressbar", GTK_STATE_FLAG_NORMAL, { "horizontal" } };
-    auto progressBarGadget = RenderThemeGadget::create(info);
-    info.name = "trough";
-    info.classList.clear();
-    auto troughGadget = RenderThemeGadget::create(info, progressBarGadget.get());
-    info.name = "progress";
-    if (renderObject.style().direction() == RTL)
-        info.classList.append("right");
-    else
-        info.classList.append("left");
     const auto& renderProgress = downcast<RenderProgress>(renderObject);
-    if (renderProgress.isDeterminate())
-        info.classList.append("pulse");
-    auto progressGadget = RenderThemeGadget::create(info, troughGadget.get());
-
-    progressBarGadget->render(paintInfo.context().platformContext()->cr(), rect);
-    troughGadget->render(paintInfo.context().platformContext()->cr(), rect);
-    progressGadget->render(paintInfo.context().platformContext()->cr(), calculateProgressRect(renderObject, rect));
+    auto& progressBarWidget = static_cast<RenderThemeProgressBar&>(RenderThemeWidget::getOrCreate(renderProgress.isDeterminate() ? RenderThemeProgressBar::Type::ProgressBar : RenderThemeProgressBar::Type::IndeterminateProgressBar));
+    progressBarWidget.progressBar().render(paintInfo.context().platformContext()->cr(), rect);
+    progressBarWidget.trough().render(paintInfo.context().platformContext()->cr(), rect);
+    progressBarWidget.progress().render(paintInfo.context().platformContext()->cr(), calculateProgressRect(renderObject, rect));
     return false;
 }
 #else
@@ -1635,22 +1512,14 @@
 
 void RenderThemeGtk::adjustInnerSpinButtonStyle(StyleResolver&, RenderStyle& style, const Element*) const
 {
-    RenderThemeGadget::Info info = { RenderThemeGadget::Type::Generic, "spinbutton", GTK_STATE_FLAG_NORMAL, { "horizontal" } };
-    auto spinbuttonGadget = RenderThemeGadget::create(info);
-    info.type = RenderThemeGadget::Type::TextField;
-    info.name = "entry";
-    info.classList.clear();
-    auto entryGadget = RenderThemeGadget::create(info, spinbuttonGadget.get());
-    info.type = RenderThemeGadget::Type::Icon;
-    info.name = "button";
-    info.classList.append("up");
-    auto buttonUpGadget = RenderThemeGadget::create(info, spinbuttonGadget.get());
-    static_cast<RenderThemeIconGadget*>(buttonUpGadget.get())->setIconSize(RenderThemeIconGadget::IconSizeGtk::Menu);
-    info.classList[0] = "down";
-    auto buttonDownGadget = RenderThemeGadget::create(info, spinbuttonGadget.get());
-    static_cast<RenderThemeIconGadget*>(buttonDownGadget.get())->setIconSize(RenderThemeIconGadget::IconSizeGtk::Menu);
-    IntSize upPreferredSize = buttonUpGadget->preferredSize();
-    IntSize downPreferredSize = buttonDownGadget->preferredSize();
+    auto& spinButtonWidget = static_cast<RenderThemeSpinButton&>(RenderThemeWidget::getOrCreate(RenderThemeWidget::Type::SpinButton));
+    spinButtonWidget.spinButton().setState(GTK_STATE_FLAG_NORMAL);
+    spinButtonWidget.entry().setState(GTK_STATE_FLAG_NORMAL);
+    spinButtonWidget.up().setState(GTK_STATE_FLAG_NORMAL);
+    spinButtonWidget.down().setState(GTK_STATE_FLAG_NORMAL);
+
+    IntSize upPreferredSize = spinButtonWidget.up().preferredSize();
+    IntSize downPreferredSize = spinButtonWidget.down().preferredSize();
     int buttonSize = std::max(std::max(upPreferredSize.width(), downPreferredSize.width()), std::max(upPreferredSize.height(), downPreferredSize.height()));
     style.setWidth(Length(buttonSize * 2, Fixed));
     style.setHeight(Length(buttonSize, Fixed));
@@ -1658,38 +1527,26 @@
 
 bool RenderThemeGtk::paintInnerSpinButton(const RenderObject& renderObject, const PaintInfo& paintInfo, const IntRect& rect)
 {
-    RenderThemeGadget::Info info = { RenderThemeGadget::Type::Generic, "spinbutton", themePartStateFlags(*this, SpinButton, renderObject), { } };
-    auto spinbuttonGadget = RenderThemeGadget::create(info);
-    info.type = RenderThemeGadget::Type::TextField;
-    info.name = "entry";
-    info.classList.clear();
-    auto entryGadget = RenderThemeGadget::create(info, spinbuttonGadget.get());
-    info.type = RenderThemeGadget::Type::Icon;
-    info.name = "button";
-    info.classList.append("up");
-    info.state = themePartStateFlags(*this, SpinButtonUpButton, renderObject);
-    auto buttonUpGadget = RenderThemeGadget::create(info, spinbuttonGadget.get());
-    auto* gadgetIcon = static_cast<RenderThemeIconGadget*>(buttonUpGadget.get());
-    gadgetIcon->setIconSize(RenderThemeIconGadget::IconSizeGtk::Menu);
-    gadgetIcon->setIconName("list-add-symbolic");
-    info.classList[0] = "down";
-    info.state = themePartStateFlags(*this, SpinButtonDownButton, renderObject);
-    auto buttonDownGadget = RenderThemeGadget::create(info, spinbuttonGadget.get());
-    gadgetIcon = static_cast<RenderThemeIconGadget*>(buttonDownGadget.get());
-    gadgetIcon->setIconSize(RenderThemeIconGadget::IconSizeGtk::Menu);
-    gadgetIcon->setIconName("list-remove-symbolic");
+    auto& spinButtonWidget = static_cast<RenderThemeSpinButton&>(RenderThemeWidget::getOrCreate(RenderThemeWidget::Type::SpinButton));
+    auto spinButtonState = themePartStateFlags(*this, SpinButton, renderObject);
+    spinButtonWidget.spinButton().setState(spinButtonState);
+    spinButtonWidget.entry().setState(spinButtonState);
+    auto& up = spinButtonWidget.up();
+    up.setState(themePartStateFlags(*this, SpinButtonUpButton, renderObject));
+    auto& down = spinButtonWidget.down();
+    down.setState(themePartStateFlags(*this, SpinButtonDownButton, renderObject));
 
     IntRect iconRect = rect;
     iconRect.setWidth(iconRect.width() / 2);
     if (renderObject.style().direction() == RTL)
-        buttonUpGadget->render(paintInfo.context().platformContext()->cr(), iconRect);
+        up.render(paintInfo.context().platformContext()->cr(), iconRect);
     else
-        buttonDownGadget->render(paintInfo.context().platformContext()->cr(), iconRect);
+        down.render(paintInfo.context().platformContext()->cr(), iconRect);
     iconRect.move(iconRect.width(), 0);
     if (renderObject.style().direction() == RTL)
-        buttonDownGadget->render(paintInfo.context().platformContext()->cr(), iconRect);
+        down.render(paintInfo.context().platformContext()->cr(), iconRect);
     else
-        buttonUpGadget->render(paintInfo.context().platformContext()->cr(), iconRect);
+        up.render(paintInfo.context().platformContext()->cr(), iconRect);
 
     return false;
 }
@@ -1822,35 +1679,27 @@
 #if GTK_CHECK_VERSION(3, 20, 0)
 static Color styleColor(RenderThemePart themePart, GtkStateFlags state, StyleColorType colorType)
 {
-    RenderThemeGadget::Info info = { RenderThemeGadget::Type::Generic, nullptr, state, { } };
-    std::unique_ptr<RenderThemeGadget> parentGadget;
-    RenderThemePart part = themePart;
-    if (themePart == Entry && (state & GTK_STATE_FLAG_SELECTED)) {
-        info.name = "entry";
-        parentGadget = RenderThemeGadget::create(info);
-        part = EntrySelection;
-    }
-
-    switch (part) {
+    RenderThemeGadget* gadget = nullptr;
+    switch (themePart) {
+    default:
+        ASSERT_NOT_REACHED();
+        FALLTHROUGH;
     case Entry:
-        info.name = "entry";
+        gadget = &static_cast<RenderThemeEntry&>(RenderThemeWidget::getOrCreate(RenderThemeWidget::Type::Entry)).entry();
         break;
     case EntrySelection:
-        info.name = "selection";
+        gadget = static_cast<RenderThemeEntry&>(RenderThemeWidget::getOrCreate(RenderThemeWidget::Type::SelectedEntry)).selection();
         break;
     case ListBox:
-        info.name = "treeview";
-        info.classList.append("view");
+        gadget = &static_cast<RenderThemeListView&>(RenderThemeWidget::getOrCreate(RenderThemeWidget::Type::ListView)).treeview();
         break;
     case Button:
-        info.name = "button";
+        gadget = &static_cast<RenderThemeButton&>(RenderThemeWidget::getOrCreate(RenderThemeWidget::Type::Button)).button();
         break;
-    default:
-        ASSERT_NOT_REACHED();
-        info.name = "entry";
     }
 
-    auto gadget = RenderThemeGadget::create(info, parentGadget.get());
+    ASSERT(gadget);
+    gadget->setState(state);
     return colorType == StyleColorBackground ? gadget->backgroundColor() : gadget->color();
 }
 #else
@@ -1870,22 +1719,22 @@
 
 Color RenderThemeGtk::platformActiveSelectionBackgroundColor() const
 {
-    return styleColor(Entry, static_cast<GtkStateFlags>(GTK_STATE_FLAG_SELECTED | GTK_STATE_FLAG_FOCUSED), StyleColorBackground);
+    return styleColor(EntrySelection, static_cast<GtkStateFlags>(GTK_STATE_FLAG_SELECTED | GTK_STATE_FLAG_FOCUSED), StyleColorBackground);
 }
 
 Color RenderThemeGtk::platformInactiveSelectionBackgroundColor() const
 {
-    return styleColor(Entry, GTK_STATE_FLAG_SELECTED, StyleColorBackground);
+    return styleColor(EntrySelection, GTK_STATE_FLAG_SELECTED, StyleColorBackground);
 }
 
 Color RenderThemeGtk::platformActiveSelectionForegroundColor() const
 {
-    return styleColor(Entry, static_cast<GtkStateFlags>(GTK_STATE_FLAG_SELECTED | GTK_STATE_FLAG_FOCUSED), StyleColorForeground);
+    return styleColor(EntrySelection, static_cast<GtkStateFlags>(GTK_STATE_FLAG_SELECTED | GTK_STATE_FLAG_FOCUSED), StyleColorForeground);
 }
 
 Color RenderThemeGtk::platformInactiveSelectionForegroundColor() const
 {
-    return styleColor(Entry, GTK_STATE_FLAG_SELECTED, StyleColorForeground);
+    return styleColor(EntrySelection, GTK_STATE_FLAG_SELECTED, StyleColorForeground);
 }
 
 Color RenderThemeGtk::platformActiveListBoxSelectionBackgroundColor() const
@@ -1941,12 +1790,12 @@
 #if GTK_CHECK_VERSION(3, 20, 0)
 bool RenderThemeGtk::paintMediaButton(const RenderObject& renderObject, GraphicsContext& graphicsContext, const IntRect& rect, const char* iconName)
 {
-    RenderThemeGadget::Info info = { RenderThemeGadget::Type::Icon, "image", themePartStateFlags(*this, MediaButton, renderObject), { } };
-    auto gadget = RenderThemeGadget::create(info);
-    auto* gadgetIcon = static_cast<RenderThemeIconGadget*>(gadget.get());
-    gadgetIcon->setIconSize(RenderThemeIconGadget::IconSizeGtk::Menu);
-    gadgetIcon->setIconName(iconName);
-    return !gadget->render(graphicsContext.platformContext()->cr(), rect);
+    auto& iconWidget = static_cast<RenderThemeIcon&>(RenderThemeWidget::getOrCreate(RenderThemeWidget::Type::Icon));
+    auto& icon = static_cast<RenderThemeIconGadget&>(iconWidget.icon());
+    icon.setState(themePartStateFlags(*this, MediaButton, renderObject));
+    icon.setIconSize(RenderThemeIconGadget::IconSizeGtk::Menu);
+    icon.setIconName(iconName);
+    return !icon.render(graphicsContext.platformContext()->cr(), rect);
 }
 #else
 bool RenderThemeGtk::paintMediaButton(const RenderObject& renderObject, GraphicsContext& graphicsContext, const IntRect& rect, const char* iconName)
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to