<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[199477] releases/WebKitGTK/webkit-2.12/Source/WebCore</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/199477">199477</a></dd>
<dt>Author</dt> <dd>carlosgc@webkit.org</dd>
<dt>Date</dt> <dd>2016-04-13 06:40:51 -0700 (Wed, 13 Apr 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>Merge <a href="http://trac.webkit.org/projects/webkit/changeset/199344">r199344</a> - [GTK] Rework scrollbars theming code for GTK+ 3.20
https://bugs.webkit.org/show_bug.cgi?id=156462

Reviewed by Michael Catanzaro.

In <a href="http://trac.webkit.org/projects/webkit/changeset/199292">r199292</a>, we reworked the theming code to ensure it works with the new GTK+ CSS theming system. The same is
needed for scrollbars, this patch uses the RenderThemeGadget classes introduced in <a href="http://trac.webkit.org/projects/webkit/changeset/199292">r199292</a> to render the native
scrollbars. The code is now split in 3 parts: stub methods for GTK+2 (since this file is compiled for
WebCoreGTK, but not used), the implementation for GTK+ &lt; 3.20 and the implementation for GTK+ &gt;= 3.20. This
reduces the amount of ifdefed code, and ensures that changes in new code don't break the rendering with older
versions of GTK+. I noticed that we were overriding both, the specific paint methods to render scrollbars
parts and the global paint method that renders all the scrollbar parts. We don't really need the specific paint
methods, so I've removed the implemention leaving only the paint method. This also allows us to get rid of the
GtkStyleContext cache.

* platform/gtk/RenderThemeGadget.cpp:
(WebCore::RenderThemeGadget::create): Handle scrollbars gadgets.
(WebCore::appendElementToPath): In case of scrollbar gadget, use the scrollbar GType when creating the path to
be able to get non-CSS style properties.
(WebCore::RenderThemeGadget::opacity): Add method to get the opacity CSS style property.
(WebCore::RenderThemeScrollbarGadget::RenderThemeScrollbarGadget): Initialize m_steppers option set with the
steppers used by the theme.
* platform/gtk/RenderThemeGadget.h:
* platform/gtk/ScrollbarThemeGtk.cpp:
(WebCore::themeChangedCallback):
(WebCore::ScrollbarThemeGtk::ScrollbarThemeGtk):
(WebCore::createStyleContext):
(WebCore::createChildStyleContext):
(WebCore::ScrollbarThemeGtk::themeChanged):
(WebCore::ScrollbarThemeGtk::updateThemeProperties):
(WebCore::scrollbarPartStateFlags):
(WebCore::scrollbarGadgetForLayout):
(WebCore::contentsGadgetForLayout):
(WebCore::ScrollbarThemeGtk::trackRect):
(WebCore::ScrollbarThemeGtk::hasThumb):
(WebCore::ScrollbarThemeGtk::backButtonRect):
(WebCore::ScrollbarThemeGtk::forwardButtonRect):
(WebCore::ScrollbarThemeGtk::paint):
(WebCore::paintStepper):
(WebCore::adjustRectAccordingToMargin):
(WebCore::ScrollbarThemeGtk::scrollbarThickness):
(WebCore::ScrollbarThemeGtk::minimumThumbLength):
* platform/gtk/ScrollbarThemeGtk.h:</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#releasesWebKitGTKwebkit212SourceWebCoreChangeLog">releases/WebKitGTK/webkit-2.12/Source/WebCore/ChangeLog</a></li>
<li><a href="#releasesWebKitGTKwebkit212SourceWebCoreplatformgtkRenderThemeGadgetcpp">releases/WebKitGTK/webkit-2.12/Source/WebCore/platform/gtk/RenderThemeGadget.cpp</a></li>
<li><a href="#releasesWebKitGTKwebkit212SourceWebCoreplatformgtkRenderThemeGadgeth">releases/WebKitGTK/webkit-2.12/Source/WebCore/platform/gtk/RenderThemeGadget.h</a></li>
<li><a href="#releasesWebKitGTKwebkit212SourceWebCoreplatformgtkScrollbarThemeGtkcpp">releases/WebKitGTK/webkit-2.12/Source/WebCore/platform/gtk/ScrollbarThemeGtk.cpp</a></li>
<li><a href="#releasesWebKitGTKwebkit212SourceWebCoreplatformgtkScrollbarThemeGtkh">releases/WebKitGTK/webkit-2.12/Source/WebCore/platform/gtk/ScrollbarThemeGtk.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="releasesWebKitGTKwebkit212SourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: releases/WebKitGTK/webkit-2.12/Source/WebCore/ChangeLog (199476 => 199477)</h4>
<pre class="diff"><span>
<span class="info">--- releases/WebKitGTK/webkit-2.12/Source/WebCore/ChangeLog        2016-04-13 13:40:36 UTC (rev 199476)
+++ releases/WebKitGTK/webkit-2.12/Source/WebCore/ChangeLog        2016-04-13 13:40:51 UTC (rev 199477)
</span><span class="lines">@@ -1,3 +1,49 @@
</span><ins>+2016-04-12  Carlos Garcia Campos  &lt;cgarcia@igalia.com&gt;
+
+        [GTK] Rework scrollbars theming code for GTK+ 3.20
+        https://bugs.webkit.org/show_bug.cgi?id=156462
+
+        Reviewed by Michael Catanzaro.
+
+        In r199292, we reworked the theming code to ensure it works with the new GTK+ CSS theming system. The same is
+        needed for scrollbars, this patch uses the RenderThemeGadget classes introduced in r199292 to render the native
+        scrollbars. The code is now split in 3 parts: stub methods for GTK+2 (since this file is compiled for
+        WebCoreGTK, but not used), the implementation for GTK+ &lt; 3.20 and the implementation for GTK+ &gt;= 3.20. This
+        reduces the amount of ifdefed code, and ensures that changes in new code don't break the rendering with older
+        versions of GTK+. I noticed that we were overriding both, the specific paint methods to render scrollbars
+        parts and the global paint method that renders all the scrollbar parts. We don't really need the specific paint
+        methods, so I've removed the implemention leaving only the paint method. This also allows us to get rid of the
+        GtkStyleContext cache.
+
+        * platform/gtk/RenderThemeGadget.cpp:
+        (WebCore::RenderThemeGadget::create): Handle scrollbars gadgets.
+        (WebCore::appendElementToPath): In case of scrollbar gadget, use the scrollbar GType when creating the path to
+        be able to get non-CSS style properties.
+        (WebCore::RenderThemeGadget::opacity): Add method to get the opacity CSS style property.
+        (WebCore::RenderThemeScrollbarGadget::RenderThemeScrollbarGadget): Initialize m_steppers option set with the
+        steppers used by the theme.
+        * platform/gtk/RenderThemeGadget.h:
+        * platform/gtk/ScrollbarThemeGtk.cpp:
+        (WebCore::themeChangedCallback):
+        (WebCore::ScrollbarThemeGtk::ScrollbarThemeGtk):
+        (WebCore::createStyleContext):
+        (WebCore::createChildStyleContext):
+        (WebCore::ScrollbarThemeGtk::themeChanged):
+        (WebCore::ScrollbarThemeGtk::updateThemeProperties):
+        (WebCore::scrollbarPartStateFlags):
+        (WebCore::scrollbarGadgetForLayout):
+        (WebCore::contentsGadgetForLayout):
+        (WebCore::ScrollbarThemeGtk::trackRect):
+        (WebCore::ScrollbarThemeGtk::hasThumb):
+        (WebCore::ScrollbarThemeGtk::backButtonRect):
+        (WebCore::ScrollbarThemeGtk::forwardButtonRect):
+        (WebCore::ScrollbarThemeGtk::paint):
+        (WebCore::paintStepper):
+        (WebCore::adjustRectAccordingToMargin):
+        (WebCore::ScrollbarThemeGtk::scrollbarThickness):
+        (WebCore::ScrollbarThemeGtk::minimumThumbLength):
+        * platform/gtk/ScrollbarThemeGtk.h:
+
</ins><span class="cx"> 2016-04-07  Carlos Garcia Campos  &lt;cgarcia@igalia.com&gt;
</span><span class="cx"> 
</span><span class="cx">         [GTK] Rework the theming code for GTK+ 3.20
</span></span></pre></div>
<a id="releasesWebKitGTKwebkit212SourceWebCoreplatformgtkRenderThemeGadgetcpp"></a>
<div class="modfile"><h4>Modified: releases/WebKitGTK/webkit-2.12/Source/WebCore/platform/gtk/RenderThemeGadget.cpp (199476 => 199477)</h4>
<pre class="diff"><span>
<span class="info">--- releases/WebKitGTK/webkit-2.12/Source/WebCore/platform/gtk/RenderThemeGadget.cpp        2016-04-13 13:40:36 UTC (rev 199476)
+++ releases/WebKitGTK/webkit-2.12/Source/WebCore/platform/gtk/RenderThemeGadget.cpp        2016-04-13 13:40:51 UTC (rev 199477)
</span><span class="lines">@@ -47,6 +47,8 @@
</span><span class="cx">         return std::make_unique&lt;RenderThemeArrowGadget&gt;(info, parent, siblings, position);
</span><span class="cx">     case RenderThemeGadget::Type::Icon:
</span><span class="cx">         return std::make_unique&lt;RenderThemeIconGadget&gt;(info, parent, siblings, position);
</span><ins>+    case RenderThemeGadget::Type::Scrollbar:
+        return std::make_unique&lt;RenderThemeScrollbarGadget&gt;(info, parent, siblings, position);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     ASSERT_NOT_REACHED();
</span><span class="lines">@@ -65,7 +67,8 @@
</span><span class="cx"> 
</span><span class="cx"> static void appendElementToPath(GtkWidgetPath* path, const RenderThemeGadget::Info&amp; info)
</span><span class="cx"> {
</span><del>-    gtk_widget_path_append_type(path, G_TYPE_NONE);
</del><ins>+    // Scrollbars need to use its GType to be able to get non-CSS style properties.
+    gtk_widget_path_append_type(path, info.type == RenderThemeGadget::Type::Scrollbar ? GTK_TYPE_SCROLLBAR : G_TYPE_NONE);
</ins><span class="cx">     gtk_widget_path_iter_set_object_name(path, -1, info.name);
</span><span class="cx">     for (const auto* className : info.classList)
</span><span class="cx">         gtk_widget_path_iter_add_class(path, -1, className);
</span><span class="lines">@@ -136,6 +139,13 @@
</span><span class="cx">     return returnValue;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+double RenderThemeGadget::opacity() const
+{
+    double returnValue;
+    gtk_style_context_get(m_context.get(), gtk_style_context_get_state(m_context.get()), &quot;opacity&quot;, &amp;returnValue, nullptr);
+    return returnValue;
+}
+
</ins><span class="cx"> IntSize RenderThemeGadget::minimumSize() const
</span><span class="cx"> {
</span><span class="cx">     int width, height;
</span><span class="lines">@@ -322,6 +332,22 @@
</span><span class="cx">     return IntSize(m_iconSize, m_iconSize);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+RenderThemeScrollbarGadget::RenderThemeScrollbarGadget(const RenderThemeGadget::Info&amp; info, RenderThemeGadget* parent, const Vector&lt;RenderThemeGadget::Info&gt; siblings, unsigned position)
+    : RenderThemeGadget(info, parent, siblings, position)
+{
+    gboolean hasBackward, hasForward, hasSecondaryBackward, hasSecondaryForward;
+    gtk_style_context_get_style(m_context.get(), &quot;has-backward-stepper&quot;, &amp;hasBackward, &quot;has-forward-stepper&quot;, &amp;hasForward,
+        &quot;has-secondary-backward-stepper&quot;, &amp;hasSecondaryBackward, &quot;has-secondary-forward-stepper&quot;, &amp;hasSecondaryForward, nullptr);
+    if (hasBackward)
+        m_steppers |= Steppers::Backward;
+    if (hasForward)
+        m_steppers |= Steppers::Forward;
+    if (hasSecondaryBackward)
+        m_steppers |= Steppers::SecondaryBackward;
+    if (hasSecondaryForward)
+        m_steppers |= Steppers::SecondaryForward;
+}
+
</ins><span class="cx"> } // namespace WebCore
</span><span class="cx"> 
</span><span class="cx"> #endif // GTK_CHECK_VERSION(3, 20, 0)
</span></span></pre></div>
<a id="releasesWebKitGTKwebkit212SourceWebCoreplatformgtkRenderThemeGadgeth"></a>
<div class="modfile"><h4>Modified: releases/WebKitGTK/webkit-2.12/Source/WebCore/platform/gtk/RenderThemeGadget.h (199476 => 199477)</h4>
<pre class="diff"><span>
<span class="info">--- releases/WebKitGTK/webkit-2.12/Source/WebCore/platform/gtk/RenderThemeGadget.h        2016-04-13 13:40:36 UTC (rev 199476)
+++ releases/WebKitGTK/webkit-2.12/Source/WebCore/platform/gtk/RenderThemeGadget.h        2016-04-13 13:40:51 UTC (rev 199477)
</span><span class="lines">@@ -31,6 +31,7 @@
</span><span class="cx"> 
</span><span class="cx"> #include &quot;Color.h&quot;
</span><span class="cx"> #include &quot;IntSize.h&quot;
</span><ins>+#include &lt;wtf/OptionSet.h&gt;
</ins><span class="cx"> #include &lt;wtf/Vector.h&gt;
</span><span class="cx"> #include &lt;wtf/glib/GRefPtr.h&gt;
</span><span class="cx"> #include &lt;wtf/text/CString.h&gt;
</span><span class="lines">@@ -48,7 +49,8 @@
</span><span class="cx">         Check,
</span><span class="cx">         Radio,
</span><span class="cx">         Arrow,
</span><del>-        Icon
</del><ins>+        Icon,
+        Scrollbar
</ins><span class="cx">     };
</span><span class="cx"> 
</span><span class="cx">     struct Info {
</span><span class="lines">@@ -71,6 +73,7 @@
</span><span class="cx">     GtkBorder contentsBox() const;
</span><span class="cx">     Color color() const;
</span><span class="cx">     Color backgroundColor() const;
</span><ins>+    double opacity() const;
</ins><span class="cx"> 
</span><span class="cx"> protected:
</span><span class="cx">     GtkStyleContext* context() const { return m_context.get(); }
</span><span class="lines">@@ -144,6 +147,22 @@
</span><span class="cx">     unsigned m_iconSize { 0 };
</span><span class="cx"> };
</span><span class="cx"> 
</span><ins>+class RenderThemeScrollbarGadget final : public RenderThemeGadget {
+public:
+    RenderThemeScrollbarGadget(const Info&amp;, RenderThemeGadget* parent, const Vector&lt;RenderThemeGadget::Info&gt; siblings, unsigned position);
+
+    enum class Steppers {
+        Backward = 1 &lt;&lt; 0,
+        Forward = 1 &lt;&lt; 1,
+        SecondaryBackward = 1 &lt;&lt; 2,
+        SecondaryForward = 1 &lt;&lt; 3
+    };
+    OptionSet&lt;Steppers&gt; steppers() const { return m_steppers; };
+
+private:
+    OptionSet&lt;Steppers&gt; m_steppers;
+};
+
</ins><span class="cx"> } // namespace WebCore
</span><span class="cx"> 
</span><span class="cx"> #endif // GTK_CHECK_VERSION(3, 20, 0)
</span></span></pre></div>
<a id="releasesWebKitGTKwebkit212SourceWebCoreplatformgtkScrollbarThemeGtkcpp"></a>
<div class="modfile"><h4>Modified: releases/WebKitGTK/webkit-2.12/Source/WebCore/platform/gtk/ScrollbarThemeGtk.cpp (199476 => 199477)</h4>
<pre class="diff"><span>
<span class="info">--- releases/WebKitGTK/webkit-2.12/Source/WebCore/platform/gtk/ScrollbarThemeGtk.cpp        2016-04-13 13:40:36 UTC (rev 199476)
+++ releases/WebKitGTK/webkit-2.12/Source/WebCore/platform/gtk/ScrollbarThemeGtk.cpp        2016-04-13 13:40:51 UTC (rev 199477)
</span><span class="lines">@@ -1,4 +1,5 @@
</span><span class="cx"> /*
</span><ins>+ * Copyright (C) 2016 Igalia S.L.
</ins><span class="cx">  * Copyright (C) 2008 Apple Inc. All Rights Reserved.
</span><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="lines">@@ -29,11 +30,11 @@
</span><span class="cx"> #include &quot;GRefPtrGtk.h&quot;
</span><span class="cx"> #include &quot;PlatformContextCairo.h&quot;
</span><span class="cx"> #include &quot;PlatformMouseEvent.h&quot;
</span><ins>+#include &quot;RenderThemeGadget.h&quot;
</ins><span class="cx"> #include &quot;ScrollView.h&quot;
</span><span class="cx"> #include &quot;Scrollbar.h&quot;
</span><span class="cx"> #include &lt;gtk/gtk.h&gt;
</span><span class="cx"> #include &lt;wtf/NeverDestroyed.h&gt;
</span><del>-#include &lt;wtf/TemporaryChange.h&gt;
</del><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><span class="lines">@@ -47,332 +48,546 @@
</span><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-bool ScrollbarThemeGtk::hasThumb(Scrollbar&amp; scrollbar)
</del><ins>+#ifndef GTK_API_VERSION_2
+static void themeChangedCallback()
</ins><span class="cx"> {
</span><del>-#ifndef GTK_API_VERSION_2
-    // This method is just called as a paint-time optimization to see if
-    // painting the thumb can be skipped.  We don't have to be exact here.
-    return thumbLength(scrollbar) &gt; 0;
</del><ins>+    ScrollbarTheme::theme().themeChanged();
+}
+
+ScrollbarThemeGtk::ScrollbarThemeGtk()
+{
+#if GTK_CHECK_VERSION(3, 20, 0)
+#if USE(COORDINATED_GRAPHICS_THREADED)
+    m_usesOverlayScrollbars = true;
</ins><span class="cx"> #else
</span><del>-    UNUSED_PARAM(scrollbar);
-    return false;
</del><ins>+    m_usesOverlayScrollbars = g_strcmp0(g_getenv(&quot;GTK_OVERLAY_SCROLLING&quot;), &quot;0&quot;);
</ins><span class="cx"> #endif
</span><ins>+#endif
+    static bool themeMonitorInitialized = false;
+    if (!themeMonitorInitialized) {
+        g_signal_connect(gtk_settings_get_default(), &quot;notify::gtk-theme-name&quot;, G_CALLBACK(themeChangedCallback), nullptr);
+        themeMonitorInitialized = true;
+        updateThemeProperties();
+    }
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-IntRect ScrollbarThemeGtk::backButtonRect(Scrollbar&amp; scrollbar, ScrollbarPart part, bool painting)
</del><ins>+#if !GTK_CHECK_VERSION(3, 20, 0)
+static GRefPtr&lt;GtkStyleContext&gt; createStyleContext(Scrollbar* scrollbar = nullptr)
</ins><span class="cx"> {
</span><del>-#ifndef GTK_API_VERSION_2
-    if (part == BackButtonEndPart &amp;&amp; !m_hasBackButtonEndPart)
-        return IntRect();
-    if (part == BackButtonStartPart &amp;&amp; !m_hasBackButtonStartPart)
-        return IntRect();
</del><ins>+    GRefPtr&lt;GtkStyleContext&gt; styleContext = adoptGRef(gtk_style_context_new());
+    GRefPtr&lt;GtkWidgetPath&gt; path = adoptGRef(gtk_widget_path_new());
+    gtk_widget_path_append_type(path.get(), GTK_TYPE_SCROLLBAR);
+    gtk_widget_path_iter_add_class(path.get(), -1, GTK_STYLE_CLASS_SCROLLBAR);
+    gtk_widget_path_iter_add_class(path.get(), -1, scrollbar &amp;&amp; scrollbar-&gt;orientation() == HorizontalScrollbar ? &quot;horizontal&quot; : &quot;vertical&quot;);
+    gtk_style_context_set_path(styleContext.get(), path.get());
+    return styleContext;
+}
</ins><span class="cx"> 
</span><del>-    GRefPtr&lt;GtkStyleContext&gt; styleContext = getOrCreateStyleContext(&amp;scrollbar, painting ? StyleContextMode::Paint : StyleContextMode::Layout);
-    GtkBorder troughBorder;
-    getTroughBorder(scrollbar, &amp;troughBorder);
-    int x = scrollbar.x() + troughBorder.left;
-    int y = scrollbar.y() + troughBorder.top;
-    IntSize size = buttonSize(scrollbar, part);
-    if (part == BackButtonStartPart)
-        return IntRect(x, y, size.width(), size.height());
</del><ins>+static GRefPtr&lt;GtkStyleContext&gt; createChildStyleContext(GtkStyleContext* parent, const char* className)
+{
+    ASSERT(parent);
+    GRefPtr&lt;GtkWidgetPath&gt; path = adoptGRef(gtk_widget_path_copy(gtk_style_context_get_path(parent)));
+    gtk_widget_path_append_type(path.get(), GTK_TYPE_SCROLLBAR);
+    gtk_widget_path_iter_add_class(path.get(), -1, GTK_STYLE_CLASS_SCROLLBAR);
+    gtk_widget_path_iter_add_class(path.get(), -1, className);
</ins><span class="cx"> 
</span><del>-    // BackButtonEndPart (alternate button)
-    if (scrollbar.orientation() == HorizontalScrollbar)
-        return IntRect(scrollbar.x() + scrollbar.width() - troughBorder.left - (2 * size.width()), y, size.width(), size.height());
</del><ins>+    GRefPtr&lt;GtkStyleContext&gt; styleContext = adoptGRef(gtk_style_context_new());
+    gtk_style_context_set_path(styleContext.get(), path.get());
+    gtk_style_context_set_parent(styleContext.get(), parent);
+    return styleContext;
+}
+#endif // GTK_CHECK_VERSION(3, 20, 0)
</ins><span class="cx"> 
</span><del>-    // VerticalScrollbar alternate button
-    return IntRect(x, scrollbar.y() + scrollbar.height() - troughBorder.top - (2 * size.height()), size.width(), size.height());
</del><ins>+void ScrollbarThemeGtk::themeChanged()
+{
+    updateThemeProperties();
+}
+
+#if GTK_CHECK_VERSION(3, 20, 0)
+void ScrollbarThemeGtk::updateThemeProperties()
+{
+    auto steppers = static_cast&lt;RenderThemeScrollbarGadget*&gt;(RenderThemeGadget::create({ RenderThemeGadget::Type::Scrollbar, &quot;scrollbar&quot;, GTK_STATE_FLAG_NORMAL, { } }).get())-&gt;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);
+}
</ins><span class="cx"> #else
</span><del>-    UNUSED_PARAM(scrollbar);
-    UNUSED_PARAM(part);
-    UNUSED_PARAM(painting);
-    return IntRect();
-#endif
</del><ins>+void ScrollbarThemeGtk::updateThemeProperties()
+{
+    gboolean hasBackButtonStartPart, hasForwardButtonEndPart, hasBackButtonEndPart, hasForwardButtonStartPart;
+    gtk_style_context_get_style(createStyleContext().get(),
+        &quot;has-backward-stepper&quot;, &amp;hasBackButtonStartPart,
+        &quot;has-forward-stepper&quot;, &amp;hasForwardButtonEndPart,
+        &quot;has-secondary-backward-stepper&quot;, &amp;hasBackButtonEndPart,
+        &quot;has-secondary-forward-stepper&quot;, &amp;hasForwardButtonStartPart,
+        nullptr);
+    m_hasBackButtonStartPart = hasBackButtonStartPart;
+    m_hasForwardButtonEndPart = hasForwardButtonEndPart;
+    m_hasBackButtonEndPart = hasBackButtonEndPart;
+    m_hasForwardButtonStartPart = hasForwardButtonStartPart;
</ins><span class="cx"> }
</span><ins>+#endif // GTK_CHECK_VERSION(3, 20, 0)
</ins><span class="cx"> 
</span><del>-IntRect ScrollbarThemeGtk::forwardButtonRect(Scrollbar&amp; scrollbar, ScrollbarPart part, bool painting)
</del><ins>+#if GTK_CHECK_VERSION(3, 20, 0)
+static GtkStateFlags scrollbarPartStateFlags(Scrollbar&amp; scrollbar, ScrollbarPart part, bool painting = false)
</ins><span class="cx"> {
</span><del>-#ifndef GTK_API_VERSION_2
-    if (part == ForwardButtonStartPart &amp;&amp; !m_hasForwardButtonStartPart)
-        return IntRect();
-    if (part == ForwardButtonEndPart &amp;&amp; !m_hasForwardButtonEndPart)
-        return IntRect();
</del><ins>+    unsigned stateFlags = 0;
+    switch (part) {
+    case AllParts:
+        if (!painting || scrollbar.hoveredPart() != NoPart)
+            stateFlags |= GTK_STATE_FLAG_PRELIGHT;
+        break;
+    case BackTrackPart:
+    case ForwardTrackPart:
+        if (scrollbar.hoveredPart() == BackTrackPart || scrollbar.hoveredPart() == ForwardTrackPart)
+            stateFlags |= GTK_STATE_FLAG_PRELIGHT;
+        if (scrollbar.pressedPart() == BackTrackPart || scrollbar.pressedPart() == ForwardTrackPart)
+            stateFlags |= GTK_STATE_FLAG_ACTIVE;
+        break;
+    case BackButtonStartPart:
+    case ForwardButtonStartPart:
+    case BackButtonEndPart:
+    case ForwardButtonEndPart:
+        if (((part == BackButtonStartPart || part == BackButtonEndPart) &amp;&amp; !scrollbar.currentPos())
+            || ((part == ForwardButtonEndPart || part == ForwardButtonStartPart) &amp;&amp; scrollbar.currentPos() == scrollbar.maximum())) {
+            stateFlags |= GTK_STATE_FLAG_INSENSITIVE;
+            break;
+        }
+        FALLTHROUGH;
+    default:
+        if (scrollbar.hoveredPart() == part)
+            stateFlags |= GTK_STATE_FLAG_PRELIGHT;
</ins><span class="cx"> 
</span><del>-    GRefPtr&lt;GtkStyleContext&gt; styleContext = getOrCreateStyleContext(&amp;scrollbar, painting ? StyleContextMode::Paint : StyleContextMode::Layout);
-    GtkBorder troughBorder;
-    getTroughBorder(scrollbar, &amp;troughBorder);
-    IntSize size = buttonSize(scrollbar, part);
-    if (scrollbar.orientation() == HorizontalScrollbar) {
-        int y = scrollbar.y() + troughBorder.top;
-        if (part == ForwardButtonEndPart)
-            return IntRect(scrollbar.x() + scrollbar.width() - size.width() - troughBorder.left, y, size.width(), size.height());
</del><ins>+        if (scrollbar.pressedPart() == part)
+            stateFlags |= GTK_STATE_FLAG_ACTIVE;
+        break;
+    }
</ins><span class="cx"> 
</span><del>-        // ForwardButtonStartPart (alternate button)
-        return IntRect(scrollbar.x() + troughBorder.left + size.width(), y, size.width(), size.height());
</del><ins>+    return static_cast&lt;GtkStateFlags&gt;(stateFlags);
+}
+
+static std::unique_ptr&lt;RenderThemeGadget&gt; scrollbarGadgetForLayout(Scrollbar&amp; scrollbar)
+{
+    RenderThemeGadget::Info info = { RenderThemeGadget::Type::Scrollbar, &quot;scrollbar&quot;, scrollbarPartStateFlags(scrollbar, AllParts), { } };
+    if (scrollbar.orientation() == VerticalScrollbar) {
+        info.classList.append(&quot;vertical&quot;);
+        info.classList.append(&quot;right&quot;);
+    } else {
+        info.classList.append(&quot;horizontal&quot;);
+        info.classList.append(&quot;bottom&quot;);
</ins><span class="cx">     }
</span><ins>+    if (scrollbar.isOverlayScrollbar())
+        info.classList.append(&quot;overlay-indicator&quot;);
+    if (info.state &amp; GTK_STATE_FLAG_PRELIGHT)
+        info.classList.append(&quot;hovering&quot;);
</ins><span class="cx"> 
</span><del>-    // VerticalScrollbar
-    int x = scrollbar.x() + troughBorder.left;
-    if (part == ForwardButtonEndPart)
-        return IntRect(x, scrollbar.y() + scrollbar.height() - size.height() - troughBorder.top, size.width(), size.height());
</del><ins>+    return RenderThemeGadget::create(info);
+}
</ins><span class="cx"> 
</span><del>-    // ForwardButtonStartPart (alternate button)
-    return IntRect(x, scrollbar.y() + troughBorder.top + size.height(), size.width(), size.height());
-#else
-    UNUSED_PARAM(scrollbar);
-    UNUSED_PARAM(part);
-    UNUSED_PARAM(painting);
-    return IntRect();
-#endif
</del><ins>+static std::unique_ptr&lt;RenderThemeBoxGadget&gt; contentsGadgetForLayout(Scrollbar&amp; scrollbar, RenderThemeGadget* parent, IntRect&amp; contentsRect, Vector&lt;int, 4&gt; steppersPosition)
+{
+    Vector&lt;RenderThemeGadget::Info&gt; children;
+    auto steppers = static_cast&lt;RenderThemeScrollbarGadget*&gt;(parent)-&gt;steppers();
+    if (steppers.contains(RenderThemeScrollbarGadget::Steppers::Backward)) {
+        steppersPosition[0] = 0;
+        children.append({ RenderThemeGadget::Type::Generic, &quot;button&quot;, scrollbarPartStateFlags(scrollbar, BackButtonStartPart), { &quot;up&quot; } });
+    }
+    if (steppers.contains(RenderThemeScrollbarGadget::Steppers::SecondaryForward)) {
+        steppersPosition[1] = children.size();
+        children.append({ RenderThemeGadget::Type::Generic, &quot;button&quot;, scrollbarPartStateFlags(scrollbar, ForwardButtonStartPart), { &quot;down&quot; } });
+    }
+    children.append({ RenderThemeGadget::Type::Generic, &quot;trough&quot;, scrollbarPartStateFlags(scrollbar, BackTrackPart), { } });
+    if (steppers.contains(RenderThemeScrollbarGadget::Steppers::SecondaryBackward)) {
+        steppersPosition[2] = children.size();
+        children.append({ RenderThemeGadget::Type::Generic, &quot;button&quot;, scrollbarPartStateFlags(scrollbar, BackButtonEndPart), { &quot;up&quot; } });
+    }
+    if (steppers.contains(RenderThemeScrollbarGadget::Steppers::Forward)) {
+        steppersPosition[3] = children.size();
+        children.append({ RenderThemeGadget::Type::Generic, &quot;button&quot;, scrollbarPartStateFlags(scrollbar, ForwardButtonEndPart), { &quot;down&quot; } });
+    }
+    RenderThemeGadget::Info info = { RenderThemeGadget::Type::Generic, &quot;contents&quot;, GTK_STATE_FLAG_NORMAL, { } };
+    auto contentsGadget = std::make_unique&lt;RenderThemeBoxGadget&gt;(info, children, parent);
+
+    GtkBorder scrollbarContentsBox = parent-&gt;contentsBox();
+    GtkBorder contentsContentsBox = contentsGadget-&gt;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();
+    contentsRect.move(padding.left, padding.top);
+    contentsRect.contract(padding.left + padding.right, padding.top + padding.bottom);
+    return contentsGadget;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-IntRect ScrollbarThemeGtk::trackRect(Scrollbar&amp; scrollbar, bool painting)
</del><ins>+IntRect ScrollbarThemeGtk::trackRect(Scrollbar&amp; scrollbar, bool /*painting*/)
</ins><span class="cx"> {
</span><del>-#ifndef GTK_API_VERSION_2
-    GRefPtr&lt;GtkStyleContext&gt; styleContext = getOrCreateStyleContext(&amp;scrollbar, painting ? StyleContextMode::Paint : StyleContextMode::Layout);
</del><ins>+    auto scrollbarGadget = scrollbarGadgetForLayout(scrollbar);
+    IntRect rect;
+    Vector&lt;int, 4&gt; steppersPosition(4, -1);
+    auto contentsGadget = contentsGadgetForLayout(scrollbar, scrollbarGadget.get(), rect, steppersPosition);
+
+    if (steppersPosition[0] != -1) {
+        if (scrollbar.orientation() == VerticalScrollbar)
+            rect.move(0, contentsGadget-&gt;child(steppersPosition[0])-&gt;preferredSize().height());
+        else
+            rect.move(contentsGadget-&gt;child(steppersPosition[0])-&gt;preferredSize().width(), 0);
+    }
+    if (steppersPosition[1] != -1) {
+        if (scrollbar.orientation() == VerticalScrollbar)
+            rect.move(0, contentsGadget-&gt;child(steppersPosition[1])-&gt;preferredSize().height());
+        else
+            rect.move(contentsGadget-&gt;child(steppersPosition[1])-&gt;preferredSize().width(), 0);
+    }
+    if (steppersPosition[2] != -1) {
+        if (scrollbar.orientation() == VerticalScrollbar)
+            rect.contract(0, contentsGadget-&gt;child(steppersPosition[2])-&gt;preferredSize().height());
+        else
+            rect.contract(contentsGadget-&gt;child(steppersPosition[2])-&gt;preferredSize().width(), 0);
+    }
+    if (steppersPosition[3] != -1) {
+        if (scrollbar.orientation() == VerticalScrollbar)
+            rect.contract(0, contentsGadget-&gt;child(steppersPosition[3])-&gt;preferredSize().height());
+        else
+            rect.contract(contentsGadget-&gt;child(steppersPosition[3])-&gt;preferredSize().width(), 0);
+    }
+
+    if (scrollbar.orientation() == VerticalScrollbar)
+        return scrollbar.height() &lt; rect.height() ? IntRect() : rect;
+
+    return scrollbar.width() &lt; rect.width() ? IntRect() : rect;
+}
+#else
+IntRect ScrollbarThemeGtk::trackRect(Scrollbar&amp; scrollbar, bool /*painting*/)
+{
+    GRefPtr&lt;GtkStyleContext&gt; styleContext = createStyleContext(&amp;scrollbar);
</ins><span class="cx">     // The padding along the thumb movement axis includes the trough border
</span><span class="cx">     // plus the size of stepper spacing (the space between the stepper and
</span><span class="cx">     // the place where the thumb stops). There is often no stepper spacing.
</span><del>-    GtkBorder troughBorder;
-    getTroughBorder(scrollbar, &amp;troughBorder);
-    GtkBorder stepperSpacing = { 0, 0, 0, 0 };
</del><ins>+    int stepperSpacing, stepperSize, troughBorderWidth, thumbFat;
+    gtk_style_context_get_style(styleContext.get(), &quot;stepper-spacing&quot;, &amp;stepperSpacing, &quot;stepper-size&quot;, &amp;stepperSize, &quot;trough-border&quot;,
+        &amp;troughBorderWidth, &quot;slider-width&quot;, &amp;thumbFat, nullptr);
</ins><span class="cx"> 
</span><span class="cx">     // The fatness of the scrollbar on the non-movement axis.
</span><del>-    int thickness = scrollbarThickness(styleContext.get(), scrollbar.orientation());
</del><ins>+    int thickness = thumbFat + 2 * troughBorderWidth;
</ins><span class="cx"> 
</span><span class="cx">     int startButtonsOffset = 0;
</span><span class="cx">     int buttonsWidth = 0;
</span><span class="cx">     if (m_hasForwardButtonStartPart) {
</span><del>-        int buttonSize = stepperSize(scrollbar, ForwardButtonStartPart);
-        startButtonsOffset += buttonSize;
-        buttonsWidth += buttonSize;
</del><ins>+        startButtonsOffset += stepperSize;
+        buttonsWidth += stepperSize;
</ins><span class="cx">     }
</span><span class="cx">     if (m_hasBackButtonStartPart) {
</span><del>-        int buttonSize = stepperSize(scrollbar, BackButtonStartPart);
-        startButtonsOffset += buttonSize;
-        buttonsWidth += buttonSize;
-        GtkBorder margin;
-        getStepperSpacing(scrollbar, BackButtonStartPart, &amp;margin);
-        stepperSpacing.left += margin.left;
-        stepperSpacing.right += margin.right;
-        stepperSpacing.top += margin.top;
-        stepperSpacing.bottom += margin.bottom;
</del><ins>+        startButtonsOffset += stepperSize;
+        buttonsWidth += stepperSize;
</ins><span class="cx">     }
</span><span class="cx">     if (m_hasBackButtonEndPart)
</span><del>-        buttonsWidth += stepperSize(scrollbar, BackButtonEndPart);
-    if (m_hasForwardButtonEndPart) {
-        buttonsWidth += stepperSize(scrollbar, ForwardButtonEndPart);
-        GtkBorder margin;
-        getStepperSpacing(scrollbar, BackButtonStartPart, &amp;margin);
-        stepperSpacing.left += margin.left;
-        stepperSpacing.right += margin.right;
-        stepperSpacing.top += margin.top;
-        stepperSpacing.bottom += margin.bottom;
-    }
</del><ins>+        buttonsWidth += stepperSize;
+    if (m_hasForwardButtonEndPart)
+        buttonsWidth += stepperSize;
</ins><span class="cx"> 
</span><span class="cx">     if (scrollbar.orientation() == HorizontalScrollbar) {
</span><span class="cx">         // Once the scrollbar becomes smaller than the natural size of the two buttons and the thumb, the track disappears.
</span><span class="cx">         if (scrollbar.width() &lt; buttonsWidth + minimumThumbLength(scrollbar))
</span><span class="cx">             return IntRect();
</span><del>-        return IntRect(scrollbar.x() + troughBorder.left + stepperSpacing.left + startButtonsOffset, scrollbar.y(),
-            scrollbar.width() - (troughBorder.left + troughBorder.right) - (stepperSpacing.left + stepperSpacing.right) - buttonsWidth, thickness);
</del><ins>+        return IntRect(scrollbar.x() + troughBorderWidth + stepperSpacing + startButtonsOffset, scrollbar.y(),
+            scrollbar.width() - (2 * troughBorderWidth) - (2 * stepperSpacing) - buttonsWidth, thickness);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     if (scrollbar.height() &lt; buttonsWidth + minimumThumbLength(scrollbar))
</span><span class="cx">         return IntRect();
</span><del>-    return IntRect(scrollbar.x(), scrollbar.y() + troughBorder.top + stepperSpacing.top + startButtonsOffset,
-        thickness, scrollbar.height() - (troughBorder.top + troughBorder.bottom) - (stepperSpacing.top + stepperSpacing.bottom) - buttonsWidth);
-#else
-    UNUSED_PARAM(scrollbar);
-    UNUSED_PARAM(painting);
-    return IntRect();
</del><ins>+    return IntRect(scrollbar.x(), scrollbar.y() + troughBorderWidth + stepperSpacing + startButtonsOffset,
+        thickness, scrollbar.height() - (2 * troughBorderWidth) - (2 * stepperSpacing) - buttonsWidth);
+}
</ins><span class="cx"> #endif
</span><ins>+
+bool ScrollbarThemeGtk::hasThumb(Scrollbar&amp; scrollbar)
+{
+    // This method is just called as a paint-time optimization to see if
+    // painting the thumb can be skipped. We don't have to be exact here.
+    return thumbLength(scrollbar) &gt; 0;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-#ifndef GTK_API_VERSION_2
-// The GtkStyleContext returned by this function is cached by ScrollbarThemeGtk::paint for the
-// duration of its scope, so a different GtkStyleContext with updated theme properties will be
-// used for each call to paint.
-GRefPtr&lt;GtkStyleContext&gt; ScrollbarThemeGtk::getOrCreateStyleContext(Scrollbar* scrollbar, StyleContextMode mode)
</del><ins>+#if GTK_CHECK_VERSION(3, 20, 0)
+IntRect ScrollbarThemeGtk::backButtonRect(Scrollbar&amp; scrollbar, ScrollbarPart part, bool /*painting*/)
</ins><span class="cx"> {
</span><del>-    ASSERT(scrollbar || mode == StyleContextMode::Layout);
-    if (m_cachedStyleContext)
-        return m_cachedStyleContext;
</del><ins>+    ASSERT(part == BackButtonStartPart || part == BackButtonEndPart);
+    if ((part == BackButtonEndPart &amp;&amp; !m_hasBackButtonEndPart) || (part == BackButtonStartPart &amp;&amp; !m_hasBackButtonStartPart))
+        return IntRect();
</ins><span class="cx"> 
</span><del>-    GRefPtr&lt;GtkStyleContext&gt; styleContext = adoptGRef(gtk_style_context_new());
-    GRefPtr&lt;GtkWidgetPath&gt; path = adoptGRef(gtk_widget_path_new());
-    gtk_widget_path_append_type(path.get(), GTK_TYPE_SCROLLBAR);
-#if GTK_CHECK_VERSION(3, 19, 2)
-    gtk_widget_path_iter_set_object_name(path.get(), -1, &quot;scrollbar&quot;);
-    if (m_usesOverlayScrollbars) {
-        gtk_widget_path_iter_add_class(path.get(), -1, &quot;overlay-indicator&quot;);
-        if (mode == StyleContextMode::Layout || scrollbar-&gt;hoveredPart() != NoPart)
-            gtk_widget_path_iter_add_class(path.get(), -1, &quot;hovering&quot;);
</del><ins>+    auto scrollbarGadget = scrollbarGadgetForLayout(scrollbar);
+    IntRect rect;
+    Vector&lt;int, 4&gt; steppersPosition(4, -1);
+    auto contentsGadget = contentsGadgetForLayout(scrollbar, scrollbarGadget.get(), rect, steppersPosition);
+
+    if (part == BackButtonStartPart)
+        return IntRect(rect.location(), contentsGadget-&gt;child(0)-&gt;preferredSize());
+
+    // Secondary back.
+    if (steppersPosition[1] != -1) {
+        if (scrollbar.orientation() == VerticalScrollbar)
+            rect.move(0, contentsGadget-&gt;child(steppersPosition[1])-&gt;preferredSize().height());
+        else
+            rect.move(contentsGadget-&gt;child(steppersPosition[1])-&gt;preferredSize().width(), 0);
</ins><span class="cx">     }
</span><del>-#else
-    gtk_widget_path_iter_add_class(path.get(), -1, &quot;scrollbar&quot;);
-#endif
-    ScrollbarOrientation orientation = scrollbar ? scrollbar-&gt;orientation() : VerticalScrollbar;
-    gtk_widget_path_iter_add_class(path.get(), -1, orientation == VerticalScrollbar ? &quot;vertical&quot; : &quot;horizontal&quot;);
-    gtk_widget_path_iter_add_class(path.get(), -1, orientation == VerticalScrollbar ? &quot;right&quot; : &quot;bottom&quot;);
-    gtk_style_context_set_path(styleContext.get(), path.get());
</del><span class="cx"> 
</span><del>-    return styleContext;
-}
</del><ins>+    IntSize preferredSize = contentsGadget-&gt;child(steppersPosition[2])-&gt;preferredSize();
+    if (scrollbar.orientation() == VerticalScrollbar)
+        rect.contract(0, preferredSize.height());
+    else
+        rect.contract(preferredSize.width(), 0);
</ins><span class="cx"> 
</span><del>-static GRefPtr&lt;GtkStyleContext&gt; createChildStyleContext(GtkStyleContext* parent, const char* name)
-{
-    ASSERT(parent);
-    GRefPtr&lt;GtkWidgetPath&gt; path = adoptGRef(gtk_widget_path_copy(gtk_style_context_get_path(parent)));
-    gtk_widget_path_append_type(path.get(), GTK_TYPE_SCROLLBAR);
-#if GTK_CHECK_VERSION(3, 19, 2)
-    gtk_widget_path_iter_set_object_name(path.get(), -1, name);
-#else
-    gtk_widget_path_iter_add_class(path.get(), -1, GTK_STYLE_CLASS_SCROLLBAR);
-    gtk_widget_path_iter_add_class(path.get(), -1, name);
-#endif
</del><ins>+    if (steppersPosition[3] != -1) {
+        if (scrollbar.orientation() == VerticalScrollbar)
+            rect.contract(0, contentsGadget-&gt;child(steppersPosition[3])-&gt;preferredSize().height());
+        else
+            rect.contract(contentsGadget-&gt;child(steppersPosition[3])-&gt;preferredSize().width(), 0);
+    }
</ins><span class="cx"> 
</span><del>-    GRefPtr&lt;GtkStyleContext&gt; styleContext = adoptGRef(gtk_style_context_new());
-    gtk_style_context_set_path(styleContext.get(), path.get());
-    gtk_style_context_set_parent(styleContext.get(), parent);
-    return styleContext;
</del><ins>+    if (scrollbar.orientation() == VerticalScrollbar)
+        rect.move(0, rect.height());
+    else
+        rect.move(rect.width(), 0);
+
+    return IntRect(rect.location(), preferredSize);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-static void themeChangedCallback()
</del><ins>+IntRect ScrollbarThemeGtk::forwardButtonRect(Scrollbar&amp; scrollbar, ScrollbarPart part, bool /*painting*/)
</ins><span class="cx"> {
</span><del>-    ScrollbarTheme::theme().themeChanged();
-}
</del><ins>+    ASSERT(part == ForwardButtonStartPart || part == ForwardButtonEndPart);
+    if ((part == ForwardButtonStartPart &amp;&amp; !m_hasForwardButtonStartPart) || (part == ForwardButtonEndPart &amp;&amp; !m_hasForwardButtonEndPart))
+        return IntRect();
</ins><span class="cx"> 
</span><del>-ScrollbarThemeGtk::ScrollbarThemeGtk()
-{
-#if GTK_CHECK_VERSION(3, 19, 2)
-#if USE(COORDINATED_GRAPHICS_THREADED)
-    m_usesOverlayScrollbars = true;
-#else
-    m_usesOverlayScrollbars = g_strcmp0(g_getenv(&quot;GTK_OVERLAY_SCROLLING&quot;), &quot;0&quot;);
-#endif
-#endif
-    static bool themeMonitorInitialized = false;
-    if (!themeMonitorInitialized) {
-        g_signal_connect_swapped(gtk_settings_get_default(), &quot;notify::gtk-theme-name&quot;, G_CALLBACK(themeChangedCallback), nullptr);
-        themeMonitorInitialized = true;
</del><ins>+    auto scrollbarGadget = scrollbarGadgetForLayout(scrollbar);
+    IntRect rect;
+    Vector&lt;int, 4&gt; steppersPosition(4, -1);
+    auto contentsGadget = contentsGadgetForLayout(scrollbar, scrollbarGadget.get(), rect, steppersPosition);
+
+    if (steppersPosition[0] != -1) {
+        if (scrollbar.orientation() == VerticalScrollbar)
+            rect.move(0, contentsGadget-&gt;child(steppersPosition[0])-&gt;preferredSize().height());
+        else
+            rect.move(contentsGadget-&gt;child(steppersPosition[0])-&gt;preferredSize().width(), 0);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    updateThemeProperties();
-}
</del><ins>+    if (part == ForwardButtonStartPart)
+        return IntRect(rect.location(), contentsGadget-&gt;child(1)-&gt;preferredSize());
</ins><span class="cx"> 
</span><del>-void ScrollbarThemeGtk::themeChanged()
-{
-    updateThemeProperties();
-}
</del><ins>+    // Forward button.
+    IntSize preferredSize = contentsGadget-&gt;child(steppersPosition[3])-&gt;preferredSize();
+    if (scrollbar.orientation() == VerticalScrollbar)
+        rect.move(0, rect.height() - preferredSize.height());
+    else
+        rect.move(rect.width() - preferredSize.width(), 0);
</ins><span class="cx"> 
</span><del>-void ScrollbarThemeGtk::updateThemeProperties()
-{
-    GRefPtr&lt;GtkStyleContext&gt; styleContext = getOrCreateStyleContext();
-    gtk_style_context_get_style(
-        styleContext.get(),
-        &quot;has-backward-stepper&quot;, &amp;m_hasBackButtonStartPart,
-        &quot;has-forward-stepper&quot;, &amp;m_hasForwardButtonEndPart,
-        &quot;has-secondary-backward-stepper&quot;, &amp;m_hasBackButtonEndPart,
-        &quot;has-secondary-forward-stepper&quot;, &amp;m_hasForwardButtonStartPart,
-        nullptr);
</del><ins>+    return IntRect(rect.location(), preferredSize);
</ins><span class="cx"> }
</span><del>-
-IntRect ScrollbarThemeGtk::thumbRect(Scrollbar&amp; scrollbar, const IntRect&amp; unconstrainedTrackRect)
</del><ins>+#else
+IntRect ScrollbarThemeGtk::backButtonRect(Scrollbar&amp; scrollbar, ScrollbarPart part, bool /*painting*/)
</ins><span class="cx"> {
</span><del>-    GRefPtr&lt;GtkStyleContext&gt; styleContext = getOrCreateStyleContext(&amp;scrollbar);
-    IntRect trackRect = constrainTrackRectToTrackPieces(scrollbar, unconstrainedTrackRect);
-    int thumbPos = thumbPosition(scrollbar);
-    int thumbFat = thumbFatness(scrollbar);
-    GtkBorder troughBorder = { 0, 0, 0, 0 };
-#if GTK_CHECK_VERSION(3, 19, 11)
-    getTroughBorder(scrollbar, &amp;troughBorder);
-#endif
</del><ins>+    if ((part == BackButtonEndPart &amp;&amp; !m_hasBackButtonEndPart) || (part == BackButtonStartPart &amp;&amp; !m_hasBackButtonStartPart))
+        return IntRect();
</ins><span class="cx"> 
</span><ins>+    GRefPtr&lt;GtkStyleContext&gt; styleContext = createStyleContext(&amp;scrollbar);
+    int troughBorderWidth, stepperSize, thumbFat;
+    gtk_style_context_get_style(styleContext.get(), &quot;trough-border&quot;, &amp;troughBorderWidth, &quot;stepper-size&quot;, &amp;stepperSize, &quot;slider-width&quot;, &amp;thumbFat, nullptr);
+    int x = scrollbar.x() + troughBorderWidth;
+    int y = scrollbar.y() + troughBorderWidth;
+    if (part == BackButtonStartPart) {
+        if (scrollbar.orientation() == HorizontalScrollbar)
+            return IntRect(x, y, stepperSize, thumbFat);
+        return IntRect(x, y, thumbFat, stepperSize);
+    }
+
+    // BackButtonEndPart (alternate button)
</ins><span class="cx">     if (scrollbar.orientation() == HorizontalScrollbar)
</span><del>-        return IntRect(trackRect.x() + thumbPos, trackRect.y() + troughBorder.top + (trackRect.height() - thumbFat) / 2, thumbLength(scrollbar), thumbFat);
</del><ins>+        return IntRect(scrollbar.x() + scrollbar.width() - troughBorderWidth - (2 * stepperSize), y, stepperSize, thumbFat);
</ins><span class="cx"> 
</span><del>-    // VerticalScrollbar
-    return IntRect(trackRect.x() + troughBorder.left + (trackRect.width() - thumbFat) / 2, trackRect.y() + thumbPos, thumbFat, thumbLength(scrollbar));
</del><ins>+    // VerticalScrollbar alternate button
+    return IntRect(x, scrollbar.y() + scrollbar.height() - troughBorderWidth - (2 * stepperSize), thumbFat, stepperSize);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-static void adjustRectAccordingToMargin(GtkStyleContext* context, IntRect&amp; rect)
</del><ins>+IntRect ScrollbarThemeGtk::forwardButtonRect(Scrollbar&amp; scrollbar, ScrollbarPart part, bool /*painting*/)
</ins><span class="cx"> {
</span><del>-    GtkBorder margin;
-    gtk_style_context_get_margin(context, gtk_style_context_get_state(context), &amp;margin);
-    rect.move(margin.left, margin.top);
-    rect.contract(margin.left + margin.right, margin.top + margin.bottom);
-}
</del><ins>+    if ((part == ForwardButtonStartPart &amp;&amp; !m_hasForwardButtonStartPart) || (part == ForwardButtonEndPart &amp;&amp; !m_hasForwardButtonEndPart))
+        return IntRect();
</ins><span class="cx"> 
</span><del>-void ScrollbarThemeGtk::paintTrackBackground(GraphicsContext&amp; context, Scrollbar&amp; scrollbar, const IntRect&amp; rect)
-{
-    GRefPtr&lt;GtkStyleContext&gt; parentStyleContext = getOrCreateStyleContext(&amp;scrollbar, StyleContextMode::Paint);
-    // Paint the track background. If the trough-under-steppers property is true, this
-    // should be the full size of the scrollbar, but if is false, it should only be the
-    // track rect.
-    IntRect fullScrollbarRect(rect);
-    if (troughUnderSteppers(scrollbar))
-        fullScrollbarRect = IntRect(scrollbar.x(), scrollbar.y(), scrollbar.width(), scrollbar.height());
</del><ins>+    GRefPtr&lt;GtkStyleContext&gt; styleContext = createStyleContext(&amp;scrollbar);
+    int troughBorderWidth, stepperSize, thumbFat;
+    gtk_style_context_get_style(styleContext.get(), &quot;trough-border&quot;, &amp;troughBorderWidth, &quot;stepper-size&quot;, &amp;stepperSize, &quot;slider-width&quot;, &amp;thumbFat, nullptr);
+    if (scrollbar.orientation() == HorizontalScrollbar) {
+        int y = scrollbar.y() + troughBorderWidth;
+        if (part == ForwardButtonEndPart)
+            return IntRect(scrollbar.x() + scrollbar.width() - stepperSize - troughBorderWidth, y, stepperSize, thumbFat);
</ins><span class="cx"> 
</span><del>-    IntRect adjustedRect = fullScrollbarRect;
-    adjustRectAccordingToMargin(parentStyleContext.get(), adjustedRect);
-    gtk_render_background(parentStyleContext.get(), context.platformContext()-&gt;cr(), adjustedRect.x(), adjustedRect.y(), adjustedRect.width(), adjustedRect.height());
-    gtk_render_frame(parentStyleContext.get(), context.platformContext()-&gt;cr(), adjustedRect.x(), adjustedRect.y(), adjustedRect.width(), adjustedRect.height());
</del><ins>+        // ForwardButtonStartPart (alternate button)
+        return IntRect(scrollbar.x() + troughBorderWidth + stepperSize, y, stepperSize, thumbFat);
+    }
</ins><span class="cx"> 
</span><del>-    GRefPtr&lt;GtkStyleContext&gt; contentsStyleContext = createChildStyleContext(parentStyleContext.get(), &quot;contents&quot;);
-    adjustedRect = fullScrollbarRect;
-    adjustRectAccordingToMargin(contentsStyleContext.get(), adjustedRect);
-    gtk_render_background(contentsStyleContext.get(), context.platformContext()-&gt;cr(), adjustedRect.x(), adjustedRect.y(), adjustedRect.width(), adjustedRect.height());
-    gtk_render_frame(contentsStyleContext.get(), context.platformContext()-&gt;cr(), adjustedRect.x(), adjustedRect.y(), adjustedRect.width(), adjustedRect.height());
</del><ins>+    // VerticalScrollbar
+    int x = scrollbar.x() + troughBorderWidth;
+    if (part == ForwardButtonEndPart)
+        return IntRect(x, scrollbar.y() + scrollbar.height() - stepperSize - troughBorderWidth, thumbFat, stepperSize);
</ins><span class="cx"> 
</span><del>-    GRefPtr&lt;GtkStyleContext&gt; troughStyleContext = createChildStyleContext(contentsStyleContext.get(), &quot;trough&quot;);
-    adjustedRect = fullScrollbarRect;
-    adjustRectAccordingToMargin(troughStyleContext.get(), adjustedRect);
-    gtk_render_background(troughStyleContext.get(), context.platformContext()-&gt;cr(), adjustedRect.x(), adjustedRect.y(), adjustedRect.width(), adjustedRect.height());
-    gtk_render_frame(troughStyleContext.get(), context.platformContext()-&gt;cr(), adjustedRect.x(), adjustedRect.y(), adjustedRect.width(), adjustedRect.height());
</del><ins>+    // ForwardButtonStartPart (alternate button)
+    return IntRect(x, scrollbar.y() + troughBorderWidth + stepperSize, thumbFat, stepperSize);
</ins><span class="cx"> }
</span><ins>+#endif // GTK_CHECK_VERSION(3, 20, 0)
</ins><span class="cx"> 
</span><del>-void ScrollbarThemeGtk::paintScrollbarBackground(GraphicsContext&amp; context, Scrollbar&amp; scrollbar)
</del><ins>+#if GTK_CHECK_VERSION(3, 20, 0)
+bool ScrollbarThemeGtk::paint(Scrollbar&amp; scrollbar, GraphicsContext&amp; graphicsContext, const IntRect&amp; damageRect)
</ins><span class="cx"> {
</span><del>-    GRefPtr&lt;GtkStyleContext&gt; styleContext = getOrCreateStyleContext(&amp;scrollbar, StyleContextMode::Paint);
-    gtk_render_frame(styleContext.get(), context.platformContext()-&gt;cr(), scrollbar.x(), scrollbar.y(), scrollbar.width(), scrollbar.height());
-}
</del><ins>+    if (graphicsContext.paintingDisabled())
+        return false;
</ins><span class="cx"> 
</span><del>-void ScrollbarThemeGtk::paintThumb(GraphicsContext&amp; context, Scrollbar&amp; scrollbar, const IntRect&amp; rect)
-{
-    ScrollbarOrientation orientation = scrollbar.orientation();
-    GRefPtr&lt;GtkStyleContext&gt; parentStyleContext = getOrCreateStyleContext(&amp;scrollbar, StyleContextMode::Paint);
-    GRefPtr&lt;GtkStyleContext&gt; contentsStyleContext = createChildStyleContext(parentStyleContext.get(), &quot;contents&quot;);
-    GRefPtr&lt;GtkStyleContext&gt; troughStyleContext = createChildStyleContext(contentsStyleContext.get(), &quot;trough&quot;);
-    GRefPtr&lt;GtkStyleContext&gt; styleContext = createChildStyleContext(troughStyleContext.get(), &quot;slider&quot;);
</del><ins>+    double opacity = scrollbar.hoveredPart() == NoPart ? scrollbar.opacity() : 1;
+    if (!opacity)
+        return true;
</ins><span class="cx"> 
</span><del>-    unsigned flags = 0;
-    if (scrollbar.pressedPart() == ThumbPart)
-        flags |= GTK_STATE_FLAG_ACTIVE;
-    if (scrollbar.hoveredPart() == ThumbPart)
-        flags |= GTK_STATE_FLAG_PRELIGHT;
-    gtk_style_context_set_state(styleContext.get(), static_cast&lt;GtkStateFlags&gt;(flags));
</del><ins>+    IntRect rect = scrollbar.frameRect();
+    if (!rect.intersects(damageRect))
+        return true;
</ins><span class="cx"> 
</span><del>-    IntRect thumbRect(rect);
-    if (m_usesOverlayScrollbars &amp;&amp; scrollbar.hoveredPart() == NoPart) {
</del><ins>+    RenderThemeGadget::Info info = { RenderThemeGadget::Type::Scrollbar, &quot;scrollbar&quot;, scrollbarPartStateFlags(scrollbar, AllParts, true), { } };
+    if (scrollbar.orientation() == VerticalScrollbar) {
+        info.classList.append(&quot;vertical&quot;);
+        info.classList.append(&quot;right&quot;);
+    } else {
+        info.classList.append(&quot;horizontal&quot;);
+        info.classList.append(&quot;bottom&quot;);
+    }
+    if (m_usesOverlayScrollbars)
+        info.classList.append(&quot;overlay-indicator&quot;);
+    if (info.state &amp; GTK_STATE_FLAG_PRELIGHT)
+        info.classList.append(&quot;hovering&quot;);
+    if (scrollbar.pressedPart() != NoPart)
+        info.classList.append(&quot;dragging&quot;);
+    auto scrollbarGadget = RenderThemeGadget::create(info);
+    if (m_usesOverlayScrollbars)
+        opacity *= scrollbarGadget-&gt;opacity();
+    if (!opacity)
+        return true;
+
+    info.type = RenderThemeGadget::Type::Generic;
+    info.name = &quot;contents&quot;;
+    info.state = GTK_STATE_FLAG_NORMAL;
+    info.classList.clear();
+    Vector&lt;RenderThemeGadget::Info&gt; children;
+    auto steppers = static_cast&lt;RenderThemeScrollbarGadget*&gt;(scrollbarGadget.get())-&gt;steppers();
+    unsigned steppersPosition[4] = { 0, 0, 0, 0 };
+    if (steppers.contains(RenderThemeScrollbarGadget::Steppers::Backward)) {
+        steppersPosition[0] = children.size();
+        children.append({ RenderThemeGadget::Type::Generic, &quot;button&quot;, scrollbarPartStateFlags(scrollbar, BackButtonStartPart), { &quot;up&quot; } });
+    }
+    if (steppers.contains(RenderThemeScrollbarGadget::Steppers::SecondaryForward)) {
+        steppersPosition[1] = children.size();
+        children.append({ RenderThemeGadget::Type::Generic, &quot;button&quot;, scrollbarPartStateFlags(scrollbar, ForwardButtonStartPart), { &quot;down&quot; } });
+    }
+    unsigned troughPosition = children.size();
+    children.append({ RenderThemeGadget::Type::Generic, &quot;trough&quot;, scrollbarPartStateFlags(scrollbar, BackTrackPart), { } });
+    if (steppers.contains(RenderThemeScrollbarGadget::Steppers::SecondaryBackward)) {
+        steppersPosition[2] = children.size();
+        children.append({ RenderThemeGadget::Type::Generic, &quot;button&quot;, scrollbarPartStateFlags(scrollbar, BackButtonEndPart), { &quot;up&quot; } });
+    }
+    if (steppers.contains(RenderThemeScrollbarGadget::Steppers::Forward)) {
+        steppersPosition[3] = children.size();
+        children.append({ RenderThemeGadget::Type::Generic, &quot;button&quot;, scrollbarPartStateFlags(scrollbar, ForwardButtonEndPart), { &quot;down&quot; } });
+    }
+    auto contentsGadget = std::make_unique&lt;RenderThemeBoxGadget&gt;(info, children, scrollbarGadget.get());
+    RenderThemeGadget* troughGadget = contentsGadget-&gt;child(troughPosition);
+
+    if (opacity != 1) {
+        graphicsContext.save();
+        graphicsContext.clip(damageRect);
+        graphicsContext.beginTransparencyLayer(opacity);
+    }
+
+    FloatRect contentsRect;
+    scrollbarGadget-&gt;render(graphicsContext.platformContext()-&gt;cr(), rect, &amp;contentsRect);
+    contentsGadget-&gt;render(graphicsContext.platformContext()-&gt;cr(), contentsRect, &amp;contentsRect);
+    troughGadget-&gt;render(graphicsContext.platformContext()-&gt;cr(), contentsRect, &amp;contentsRect);
+    FloatRect buttonRect = contentsRect;
+    if (steppers.contains(RenderThemeScrollbarGadget::Steppers::Backward)) {
+        RenderThemeGadget* buttonGadget = contentsGadget-&gt;child(steppersPosition[0]);
+        if (scrollbar.orientation() == VerticalScrollbar)
+            buttonRect.setHeight(buttonGadget-&gt;preferredSize().height());
+        else
+            buttonRect.setWidth(buttonGadget-&gt;preferredSize().width());
+        buttonGadget-&gt;render(graphicsContext.platformContext()-&gt;cr(), buttonRect);
+        if (scrollbar.orientation() == VerticalScrollbar)
+            buttonRect.move(0, buttonRect.height());
+        else
+            buttonRect.move(buttonRect.width(), 0);
+    }
+    if (steppers.contains(RenderThemeScrollbarGadget::Steppers::SecondaryForward)) {
+        RenderThemeGadget* buttonGadget = contentsGadget-&gt;child(steppersPosition[1]);
+        if (scrollbar.orientation() == VerticalScrollbar)
+            buttonRect.setHeight(buttonGadget-&gt;preferredSize().height());
+        else
+            buttonRect.setWidth(buttonGadget-&gt;preferredSize().width());
+        buttonGadget-&gt;render(graphicsContext.platformContext()-&gt;cr(), buttonRect);
+        if (scrollbar.orientation() == VerticalScrollbar)
+            buttonRect.move(0, contentsRect.height());
+        else
+            buttonRect.move(contentsRect.width(), 0);
+    }
+    if (steppers.contains(RenderThemeScrollbarGadget::Steppers::SecondaryBackward)) {
+        RenderThemeGadget* buttonGadget = contentsGadget-&gt;child(steppersPosition[2]);
+        if (scrollbar.orientation() == VerticalScrollbar)
+            buttonRect.setHeight(buttonGadget-&gt;preferredSize().height());
+        else
+            buttonRect.setWidth(buttonGadget-&gt;preferredSize().width());
+        buttonGadget-&gt;render(graphicsContext.platformContext()-&gt;cr(), buttonRect);
+        if (scrollbar.orientation() == VerticalScrollbar)
+            buttonRect.move(0, buttonRect.height());
+        else
+            buttonRect.move(buttonRect.width(), 0);
+    }
+    if (steppers.contains(RenderThemeScrollbarGadget::Steppers::Forward)) {
+        RenderThemeGadget* buttonGadget = contentsGadget-&gt;child(steppersPosition[3]);
+        if (scrollbar.orientation() == VerticalScrollbar)
+            buttonRect.setHeight(buttonGadget-&gt;preferredSize().height());
+        else
+            buttonRect.setWidth(buttonGadget-&gt;preferredSize().width());
+        buttonGadget-&gt;render(graphicsContext.platformContext()-&gt;cr(), buttonRect);
+    }
+    if (int thumbSize = thumbLength(scrollbar)) {
+        info.name = &quot;slider&quot;;
+        info.state = scrollbarPartStateFlags(scrollbar, ThumbPart);
+        auto sliderGadget = RenderThemeGadget::create(info, troughGadget);
+
</ins><span class="cx">         // When using overlay scrollbars we always claim the size of the scrollbar when hovered, so when
</span><span class="cx">         // drawing the indicator we need to adjust the rectangle to its actual size in indicator mode.
</span><del>-        if (orientation == VerticalScrollbar)
-            thumbRect.move(scrollbar.width() - scrollbarThickness(parentStyleContext.get(), orientation), 0);
-        else
-            thumbRect.move(0, scrollbar.height() - scrollbarThickness(parentStyleContext.get(), orientation));
</del><ins>+        bool isIndicator = m_usesOverlayScrollbars &amp;&amp; scrollbar.hoveredPart() == NoPart;
+        if (scrollbar.orientation() == VerticalScrollbar) {
+            int sliderWidth = sliderGadget-&gt;preferredSize().width();
+            contentsRect.move(isIndicator ? contentsRect.width() - sliderWidth : 0, thumbPosition(scrollbar));
+            contentsRect.setWidth(sliderWidth);
+            contentsRect.setHeight(thumbSize);
+        } else {
+            int sliderHeight = sliderGadget-&gt;preferredSize().height();
+            contentsRect.move(thumbPosition(scrollbar), isIndicator ? contentsRect.height() - sliderHeight : 0);
+            contentsRect.setWidth(thumbSize);
+            contentsRect.setHeight(sliderHeight);
+        }
+        if (contentsRect.intersects(damageRect))
+            sliderGadget-&gt;render(graphicsContext.platformContext()-&gt;cr(), contentsRect);
</ins><span class="cx">     }
</span><del>-    adjustRectAccordingToMargin(styleContext.get(), thumbRect);
-    gtk_render_slider(styleContext.get(), context.platformContext()-&gt;cr(), thumbRect.x(), thumbRect.y(), thumbRect.width(), thumbRect.height(),
-        orientation == VerticalScrollbar ? GTK_ORIENTATION_VERTICAL : GTK_ORIENTATION_HORIZONTAL);
</del><ins>+
+    if (opacity != 1) {
+        graphicsContext.endTransparencyLayer();
+        graphicsContext.restore();
+    }
+
+    return true;
</ins><span class="cx"> }
</span><del>-
-void ScrollbarThemeGtk::paintButton(GraphicsContext&amp; context, Scrollbar&amp; scrollbar, const IntRect&amp; rect, ScrollbarPart part)
</del><ins>+#else
+static void paintStepper(GtkStyleContext* parentContext, GraphicsContext&amp; context, Scrollbar&amp; scrollbar, const IntRect&amp; rect, ScrollbarPart part)
</ins><span class="cx"> {
</span><span class="cx">     ScrollbarOrientation orientation = scrollbar.orientation();
</span><del>-    GRefPtr&lt;GtkStyleContext&gt; parentStyleContext = getOrCreateStyleContext(&amp;scrollbar, StyleContextMode::Paint);
-    GRefPtr&lt;GtkStyleContext&gt; contentsStyleContext = createChildStyleContext(parentStyleContext.get(), &quot;contents&quot;);
-    GRefPtr&lt;GtkStyleContext&gt; styleContext = createChildStyleContext(contentsStyleContext.get(), &quot;button&quot;);
</del><ins>+    GRefPtr&lt;GtkStyleContext&gt; styleContext = createChildStyleContext(parentContext, &quot;button&quot;);
</ins><span class="cx"> 
</span><span class="cx">     unsigned flags = 0;
</span><span class="cx">     if ((BackButtonStartPart == part &amp;&amp; scrollbar.currentPos())
</span><span class="lines">@@ -394,9 +609,7 @@
</span><span class="cx">     gtk_style_context_get_style(styleContext.get(), &quot;arrow-scaling&quot;, &amp;arrowScaling, nullptr);
</span><span class="cx"> 
</span><span class="cx">     double arrowSize = std::min(rect.width(), rect.height()) * arrowScaling;
</span><del>-    FloatPoint arrowPoint(
-        rect.x() + (rect.width() - arrowSize) / 2,
-        rect.y() + (rect.height() - arrowSize) / 2);
</del><ins>+    FloatPoint arrowPoint(rect.x() + (rect.width() - arrowSize) / 2, rect.y() + (rect.height() - arrowSize) / 2);
</ins><span class="cx"> 
</span><span class="cx">     if (flags &amp; GTK_STATE_FLAG_ACTIVE) {
</span><span class="cx">         gint arrowDisplacementX, arrowDisplacementY;
</span><span class="lines">@@ -413,18 +626,21 @@
</span><span class="cx">     gtk_render_arrow(styleContext.get(), context.platformContext()-&gt;cr(), angle, arrowPoint.x(), arrowPoint.y(), arrowSize);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+static void adjustRectAccordingToMargin(GtkStyleContext* context, IntRect&amp; rect)
+{
+    GtkBorder margin;
+    gtk_style_context_get_margin(context, gtk_style_context_get_state(context), &amp;margin);
+    rect.move(margin.left, margin.top);
+    rect.contract(margin.left + margin.right, margin.top + margin.bottom);
+}
+
</ins><span class="cx"> bool ScrollbarThemeGtk::paint(Scrollbar&amp; scrollbar, GraphicsContext&amp; graphicsContext, const IntRect&amp; damageRect)
</span><span class="cx"> {
</span><span class="cx">     if (graphicsContext.paintingDisabled())
</span><span class="cx">         return false;
</span><span class="cx"> 
</span><del>-    double opacity = scrollbar.hoveredPart() == NoPart ? scrollbar.opacity() : 1;
-    if (!opacity)
-        return true;
</del><ins>+    GRefPtr&lt;GtkStyleContext&gt; styleContext = createStyleContext(&amp;scrollbar);
</ins><span class="cx"> 
</span><del>-    // Cache a new GtkStyleContext for the duration of this scope.
-    TemporaryChange&lt;GRefPtr&lt;GtkStyleContext&gt;&gt; tempStyleContext(m_cachedStyleContext, getOrCreateStyleContext(&amp;scrollbar, StyleContextMode::Paint));
-
</del><span class="cx">     // Create the ScrollbarControlPartMask based on the damageRect
</span><span class="cx">     ScrollbarControlPartMask scrollMask = NoPart;
</span><span class="cx"> 
</span><span class="lines">@@ -451,7 +667,9 @@
</span><span class="cx">     if (damageRect.intersects(trackPaintRect))
</span><span class="cx">         scrollMask |= TrackBGPart;
</span><span class="cx"> 
</span><del>-    if (troughUnderSteppers(scrollbar) &amp;&amp; (scrollMask &amp; BackButtonStartPart
</del><ins>+    gboolean troughUnderSteppers;
+    gtk_style_context_get_style(styleContext.get(), &quot;trough-under-steppers&quot;, &amp;troughUnderSteppers, nullptr);
+    if (troughUnderSteppers &amp;&amp; (scrollMask &amp; BackButtonStartPart
</ins><span class="cx">             || scrollMask &amp; BackButtonEndPart
</span><span class="cx">             || scrollMask &amp; ForwardButtonStartPart
</span><span class="cx">             || scrollMask &amp; ForwardButtonEndPart))
</span><span class="lines">@@ -460,63 +678,71 @@
</span><span class="cx">     IntRect currentThumbRect;
</span><span class="cx">     if (hasThumb(scrollbar)) {
</span><span class="cx">         IntRect track = trackRect(scrollbar, false);
</span><del>-        currentThumbRect = thumbRect(scrollbar, track);
</del><ins>+        IntRect trackRect = constrainTrackRectToTrackPieces(scrollbar, track);
+        int thumbFat;
+        gtk_style_context_get_style(styleContext.get(), &quot;slider-width&quot;, &amp;thumbFat, nullptr);
+        if (scrollbar.orientation() == HorizontalScrollbar)
+            currentThumbRect = IntRect(trackRect.x() + thumbPosition(scrollbar), trackRect.y() + (trackRect.height() - thumbFat) / 2, thumbLength(scrollbar), thumbFat);
+        else
+            currentThumbRect = IntRect(trackRect.x() + (trackRect.width() - thumbFat) / 2, trackRect.y() + thumbPosition(scrollbar), thumbFat, thumbLength(scrollbar));
</ins><span class="cx">         if (damageRect.intersects(currentThumbRect))
</span><span class="cx">             scrollMask |= ThumbPart;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    if (m_usesOverlayScrollbars) {
-        // FIXME: Remove this check once 3.20 is released.
-#if GTK_CHECK_VERSION(3, 19, 8)
-        unsigned flags = 0;
-        if (scrollbar.hoveredPart() != NoPart)
-            flags |= GTK_STATE_FLAG_PRELIGHT;
-        if (scrollbar.pressedPart() != NoPart)
-            flags |= GTK_STATE_FLAG_ACTIVE;
-        double styleOpacity;
-        gtk_style_context_set_state(m_cachedStyleContext.get(), static_cast&lt;GtkStateFlags&gt;(flags));
-        gtk_style_context_get(m_cachedStyleContext.get(), gtk_style_context_get_state(m_cachedStyleContext.get()), &quot;opacity&quot;, &amp;styleOpacity, nullptr);
-        opacity *= styleOpacity;
-#else
-        opacity *= scrollbar.hoveredPart() == NoPart ? 0.4 : 0.7;
-#endif
-    }
-    if (!opacity || scrollMask == NoPart)
</del><ins>+    if (scrollMask == NoPart)
</ins><span class="cx">         return true;
</span><span class="cx"> 
</span><del>-    if (opacity != 1) {
-        graphicsContext.save();
-        graphicsContext.clip(damageRect);
-        graphicsContext.beginTransparencyLayer(opacity);
-    }
</del><ins>+    ScrollbarControlPartMask allButtons = BackButtonStartPart | BackButtonEndPart | ForwardButtonStartPart | ForwardButtonEndPart;
</ins><span class="cx"> 
</span><del>-    ScrollbarControlPartMask allButtons = BackButtonStartPart | BackButtonEndPart | ForwardButtonStartPart | ForwardButtonEndPart;
</del><ins>+    // Paint the track background. If the trough-under-steppers property is true, this
+    // should be the full size of the scrollbar, but if is false, it should only be the
+    // track rect.
+    GRefPtr&lt;GtkStyleContext&gt; troughStyleContext = createChildStyleContext(styleContext.get(), &quot;trough&quot;);
</ins><span class="cx">     if (scrollMask &amp; TrackBGPart || scrollMask &amp; ThumbPart || scrollMask &amp; allButtons) {
</span><del>-        paintScrollbarBackground(graphicsContext, scrollbar);
-        paintTrackBackground(graphicsContext, scrollbar, trackPaintRect);
</del><ins>+        IntRect fullScrollbarRect = trackPaintRect;
+        if (troughUnderSteppers)
+            fullScrollbarRect = scrollbar.frameRect();
+
+        IntRect adjustedRect = fullScrollbarRect;
+        adjustRectAccordingToMargin(styleContext.get(), adjustedRect);
+        gtk_render_background(styleContext.get(), graphicsContext.platformContext()-&gt;cr(), adjustedRect.x(), adjustedRect.y(), adjustedRect.width(), adjustedRect.height());
+        gtk_render_frame(styleContext.get(), graphicsContext.platformContext()-&gt;cr(), adjustedRect.x(), adjustedRect.y(), adjustedRect.width(), adjustedRect.height());
+
+        adjustedRect = fullScrollbarRect;
+        adjustRectAccordingToMargin(troughStyleContext.get(), adjustedRect);
+        gtk_render_background(troughStyleContext.get(), graphicsContext.platformContext()-&gt;cr(), adjustedRect.x(), adjustedRect.y(), adjustedRect.width(), adjustedRect.height());
+        gtk_render_frame(troughStyleContext.get(), graphicsContext.platformContext()-&gt;cr(), adjustedRect.x(), adjustedRect.y(), adjustedRect.width(), adjustedRect.height());
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     // Paint the back and forward buttons.
</span><span class="cx">     if (scrollMask &amp; BackButtonStartPart)
</span><del>-        paintButton(graphicsContext, scrollbar, backButtonStartPaintRect, BackButtonStartPart);
</del><ins>+        paintStepper(styleContext.get(), graphicsContext, scrollbar, backButtonStartPaintRect, BackButtonStartPart);
</ins><span class="cx">     if (scrollMask &amp; BackButtonEndPart)
</span><del>-        paintButton(graphicsContext, scrollbar, backButtonEndPaintRect, BackButtonEndPart);
</del><ins>+        paintStepper(styleContext.get(), graphicsContext, scrollbar, backButtonEndPaintRect, BackButtonEndPart);
</ins><span class="cx">     if (scrollMask &amp; ForwardButtonStartPart)
</span><del>-        paintButton(graphicsContext, scrollbar, forwardButtonStartPaintRect, ForwardButtonStartPart);
</del><ins>+        paintStepper(styleContext.get(), graphicsContext, scrollbar, forwardButtonStartPaintRect, ForwardButtonStartPart);
</ins><span class="cx">     if (scrollMask &amp; ForwardButtonEndPart)
</span><del>-        paintButton(graphicsContext, scrollbar, forwardButtonEndPaintRect, ForwardButtonEndPart);
</del><ins>+        paintStepper(styleContext.get(), graphicsContext, scrollbar, forwardButtonEndPaintRect, ForwardButtonEndPart);
</ins><span class="cx"> 
</span><span class="cx">     // Paint the thumb.
</span><del>-    if (scrollMask &amp; ThumbPart)
-        paintThumb(graphicsContext, scrollbar, currentThumbRect);
</del><ins>+    if (scrollMask &amp; ThumbPart) {
+        GRefPtr&lt;GtkStyleContext&gt; thumbStyleContext = createChildStyleContext(troughStyleContext.get(), &quot;slider&quot;);
+        unsigned flags = 0;
+        if (scrollbar.pressedPart() == ThumbPart)
+            flags |= GTK_STATE_FLAG_ACTIVE;
+        if (scrollbar.hoveredPart() == ThumbPart)
+            flags |= GTK_STATE_FLAG_PRELIGHT;
+        gtk_style_context_set_state(thumbStyleContext.get(), static_cast&lt;GtkStateFlags&gt;(flags));
</ins><span class="cx"> 
</span><del>-    if (opacity != 1) {
-        graphicsContext.endTransparencyLayer();
-        graphicsContext.restore();
</del><ins>+        IntRect thumbRect(currentThumbRect);
+        adjustRectAccordingToMargin(thumbStyleContext.get(), thumbRect);
+        gtk_render_slider(thumbStyleContext.get(), graphicsContext.platformContext()-&gt;cr(), thumbRect.x(), thumbRect.y(), thumbRect.width(), thumbRect.height(),
+            scrollbar.orientation() == VerticalScrollbar ? GTK_ORIENTATION_VERTICAL : GTK_ORIENTATION_HORIZONTAL);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     return true;
</span><span class="cx"> }
</span><ins>+#endif // GTK_CHECK_VERSION(3, 20, 0)
</ins><span class="cx"> 
</span><span class="cx"> ScrollbarButtonPressAction ScrollbarThemeGtk::handleMousePressEvent(Scrollbar&amp;, const PlatformMouseEvent&amp; event, ScrollbarPart pressedPart)
</span><span class="cx"> {
</span><span class="lines">@@ -539,197 +765,93 @@
</span><span class="cx">     return ScrollbarButtonPressAction::None;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-int ScrollbarThemeGtk::scrollbarThickness(GtkStyleContext* styleContext, ScrollbarOrientation orientation)
</del><ins>+#if GTK_CHECK_VERSION(3, 20, 0)
+int ScrollbarThemeGtk::scrollbarThickness(ScrollbarControlSize)
</ins><span class="cx"> {
</span><del>-    GtkBorder troughBorder;
-#if GTK_CHECK_VERSION(3, 19, 11)
-    GRefPtr&lt;GtkStyleContext&gt; contentsStyleContext = createChildStyleContext(styleContext, &quot;contents&quot;);
-    GRefPtr&lt;GtkStyleContext&gt; troughStyleContext = createChildStyleContext(contentsStyleContext.get(), &quot;trough&quot;);
-    GRefPtr&lt;GtkStyleContext&gt; sliderStyleContext = createChildStyleContext(troughStyleContext.get(), &quot;slider&quot;);
-    int thumbFat = thumbFatness(sliderStyleContext.get(), orientation);
-    getTroughBorder(troughStyleContext.get(), &amp;troughBorder);
-    // Since GTK+ 3.19 the scrollbar can have its own border too.
-    GtkBorder border;
-    gtk_style_context_get_border(styleContext, gtk_style_context_get_state(styleContext), &amp;border);
-    troughBorder.left += border.left;
-    troughBorder.right += border.right;
-    troughBorder.top += border.top;
-    troughBorder.bottom += border.bottom;
-#else
-    int thumbFat = thumbFatness(styleContext, orientation);
-    getTroughBorder(styleContext, &amp;troughBorder);
-#endif
-    if (orientation == VerticalScrollbar)
-        return thumbFat + troughBorder.left + troughBorder.right;
-    return thumbFat + troughBorder.top + troughBorder.bottom;
-}
</del><ins>+    RenderThemeGadget::Info info = { RenderThemeGadget::Type::Scrollbar, &quot;scrollbar&quot;, GTK_STATE_FLAG_PRELIGHT, { &quot;vertical&quot;, &quot;right&quot;, &quot;hovering&quot; } };
+    if (m_usesOverlayScrollbars)
+        info.classList.append(&quot;overlay-indicator&quot;);
+    auto scrollbarGadget = RenderThemeGadget::create(info);
+    info.type = RenderThemeGadget::Type::Generic;
+    info.name = &quot;contents&quot;;
+    info.state = GTK_STATE_FLAG_NORMAL;
+    info.classList.clear();
+    Vector&lt;RenderThemeGadget::Info&gt; children;
+    auto steppers = static_cast&lt;RenderThemeScrollbarGadget*&gt;(scrollbarGadget.get())-&gt;steppers();
+    if (steppers.contains(RenderThemeScrollbarGadget::Steppers::Backward))
+        children.append({ RenderThemeGadget::Type::Generic, &quot;button&quot;, GTK_STATE_FLAG_NORMAL, { &quot;up&quot; } });
+    if (steppers.contains(RenderThemeScrollbarGadget::Steppers::SecondaryForward))
+        children.append({ RenderThemeGadget::Type::Generic, &quot;button&quot;, GTK_STATE_FLAG_NORMAL, { &quot;down&quot; } });
+    unsigned troughPositon = children.size();
+    children.append({ RenderThemeGadget::Type::Generic, &quot;trough&quot;, GTK_STATE_FLAG_PRELIGHT, { } });
+    if (steppers.contains(RenderThemeScrollbarGadget::Steppers::SecondaryBackward))
+        children.append({ RenderThemeGadget::Type::Generic, &quot;button&quot;, GTK_STATE_FLAG_NORMAL, { &quot;up&quot; } });
+    if (steppers.contains(RenderThemeScrollbarGadget::Steppers::Forward))
+        children.append({ RenderThemeGadget::Type::Generic, &quot;button&quot;, GTK_STATE_FLAG_NORMAL, { &quot;down&quot; } });
+    auto contentsGadget = std::make_unique&lt;RenderThemeBoxGadget&gt;(info, children, scrollbarGadget.get());
+    info.name = &quot;slider&quot;;
+    auto sliderGadget = RenderThemeGadget::create(info, contentsGadget-&gt;child(troughPositon));
+    IntSize preferredSize = scrollbarGadget-&gt;preferredSize();
+    preferredSize += contentsGadget-&gt;preferredSize();
+    preferredSize += sliderGadget-&gt;preferredSize();
</ins><span class="cx"> 
</span><del>-int ScrollbarThemeGtk::scrollbarThickness(ScrollbarControlSize)
-{
-    GRefPtr&lt;GtkStyleContext&gt; styleContext = getOrCreateStyleContext();
-    return scrollbarThickness(styleContext.get());
</del><ins>+    return preferredSize.width();
</ins><span class="cx"> }
</span><del>-
-IntSize ScrollbarThemeGtk::buttonSize(Scrollbar&amp; scrollbar, ScrollbarPart buttonPart)
-{
-    GRefPtr&lt;GtkStyleContext&gt; styleContext = getOrCreateStyleContext(&amp;scrollbar);
-#if GTK_CHECK_VERSION(3, 19, 11)
-    GRefPtr&lt;GtkStyleContext&gt; contentsStyleContext = createChildStyleContext(styleContext.get(), &quot;contents&quot;);
-    GRefPtr&lt;GtkStyleContext&gt; buttonStyleContext = createChildStyleContext(contentsStyleContext.get(), &quot;button&quot;);
-    switch (buttonPart) {
-    case BackButtonStartPart:
-    case ForwardButtonStartPart:
-        gtk_style_context_add_class(buttonStyleContext.get(), &quot;up&quot;);
-        break;
-    case BackButtonEndPart:
-    case ForwardButtonEndPart:
-        gtk_style_context_add_class(buttonStyleContext.get(), &quot;down&quot;);
-        break;
-    default:
-        ASSERT_NOT_REACHED();
-    }
-    int minWidth = 0, minHeight = 0;
-    gtk_style_context_get(buttonStyleContext.get(), gtk_style_context_get_state(buttonStyleContext.get()),
-        &quot;min-width&quot;, &amp;minWidth, &quot;min-height&quot;, &amp;minHeight, nullptr);
-    return IntSize(minWidth, minHeight);
</del><span class="cx"> #else
</span><del>-    UNUSED_PARAM(buttonPart);
-    int stepperSize;
-    gtk_style_context_get_style(styleContext.get(), &quot;stepper-size&quot;, &amp;stepperSize, nullptr);
-    if (scrollbar.orientation() == VerticalScrollbar)
-        return IntSize(thumbFatness(scrollbar), stepperSize);
-
-    // HorizontalScrollbar
-    return IntSize(stepperSize, thumbFatness(scrollbar));
-#endif
-}
-
-int ScrollbarThemeGtk::stepperSize(Scrollbar&amp; scrollbar, ScrollbarPart buttonPart)
</del><ins>+int ScrollbarThemeGtk::scrollbarThickness(ScrollbarControlSize)
</ins><span class="cx"> {
</span><del>-    IntSize size = buttonSize(scrollbar, buttonPart);
-    return scrollbar.orientation() == VerticalScrollbar ? size.height() : size.width();
</del><ins>+    int thumbFat, troughBorderWidth;
+    gtk_style_context_get_style(createStyleContext().get(), &quot;slider-width&quot;, &amp;thumbFat, &quot;trough-border&quot;, &amp;troughBorderWidth, nullptr);
+    return thumbFat + 2 * troughBorderWidth;
</ins><span class="cx"> }
</span><ins>+#endif // GTK_CHECK_VERSION(3, 20, 0)
</ins><span class="cx"> 
</span><del>-void ScrollbarThemeGtk::getStepperSpacing(Scrollbar&amp; scrollbar, ScrollbarPart buttonPart, GtkBorder* margin)
</del><ins>+#if GTK_CHECK_VERSION(3, 20, 0)
+int ScrollbarThemeGtk::minimumThumbLength(Scrollbar&amp; scrollbar)
</ins><span class="cx"> {
</span><del>-    GRefPtr&lt;GtkStyleContext&gt; styleContext = getOrCreateStyleContext(&amp;scrollbar);
-#if GTK_CHECK_VERSION(3, 19, 11)
-    GRefPtr&lt;GtkStyleContext&gt; contentsStyleContext = createChildStyleContext(styleContext.get(), &quot;contents&quot;);
-    GRefPtr&lt;GtkStyleContext&gt; buttonStyleContext = createChildStyleContext(contentsStyleContext.get(), &quot;button&quot;);
-    switch (buttonPart) {
-    case BackButtonStartPart:
-    case ForwardButtonStartPart:
-        gtk_style_context_add_class(buttonStyleContext.get(), &quot;up&quot;);
-        break;
-    case BackButtonEndPart:
-    case ForwardButtonEndPart:
-        gtk_style_context_add_class(buttonStyleContext.get(), &quot;down&quot;);
-        break;
-    default:
-        ASSERT_NOT_REACHED();
-    }
-    gtk_style_context_get_margin(buttonStyleContext.get(), gtk_style_context_get_state(buttonStyleContext.get()), margin);
-#else
-    UNUSED_PARAM(buttonPart);
-    int stepperSpacing = 0;
-    gtk_style_context_get_style(styleContext.get(), &quot;stepper-spacing&quot;, &amp;stepperSpacing, nullptr);
-    margin-&gt;left = margin-&gt;right = margin-&gt;top = margin-&gt;bottom = stepperSpacing;
-#endif
</del><ins>+    RenderThemeGadget::Info info = { RenderThemeGadget::Type::Scrollbar, &quot;scrollbar&quot;, GTK_STATE_FLAG_PRELIGHT, { &quot;vertical&quot;, &quot;right&quot;, &quot;hovering&quot; } };
+    if (m_usesOverlayScrollbars)
+        info.classList.append(&quot;overlay-indicator&quot;);
+    auto scrollbarGadget = RenderThemeGadget::create(info);
+    info.type = RenderThemeGadget::Type::Generic;
+    info.name = &quot;contents&quot;;
+    info.state = GTK_STATE_FLAG_NORMAL;
+    info.classList.clear();
+    Vector&lt;RenderThemeGadget::Info&gt; children = {{ RenderThemeGadget::Type::Generic, &quot;trough&quot;, GTK_STATE_FLAG_PRELIGHT, { } } };
+    auto contentsGadget = std::make_unique&lt;RenderThemeBoxGadget&gt;(info, children, scrollbarGadget.get());
+    info.name = &quot;slider&quot;;
+    IntSize minSize = RenderThemeGadget::create(info, contentsGadget-&gt;child(0))-&gt;minimumSize();
+    return scrollbar.orientation() == VerticalScrollbar ? minSize.height() : minSize.width();
</ins><span class="cx"> }
</span><del>-
-bool ScrollbarThemeGtk::troughUnderSteppers(Scrollbar&amp; scrollbar)
-{
-#if !GTK_CHECK_VERSION(3, 19, 11)
-    GRefPtr&lt;GtkStyleContext&gt; styleContext = getOrCreateStyleContext(&amp;scrollbar);
-    gboolean underSteppers;
-    gtk_style_context_get_style(styleContext.get(), &quot;trough-under-steppers&quot;, &amp;underSteppers, nullptr);
-    return underSteppers;
</del><span class="cx"> #else
</span><del>-    UNUSED_PARAM(scrollbar);
-    // This is now ignored by GTK+ and considered always true.
-    return true;
-#endif
-}
</del><span class="cx"> int ScrollbarThemeGtk::minimumThumbLength(Scrollbar&amp; scrollbar)
</span><span class="cx"> {
</span><del>-    GRefPtr&lt;GtkStyleContext&gt; styleContext = getOrCreateStyleContext(&amp;scrollbar);
</del><span class="cx">     int minThumbLength = 0;
</span><del>-#if GTK_CHECK_VERSION(3, 19, 11)
-    GRefPtr&lt;GtkStyleContext&gt; contentsStyleContext = createChildStyleContext(styleContext.get(), &quot;contents&quot;);
-    GRefPtr&lt;GtkStyleContext&gt; troughStyleContext = createChildStyleContext(contentsStyleContext.get(), &quot;trough&quot;);
-    GRefPtr&lt;GtkStyleContext&gt; sliderStyleContext = createChildStyleContext(troughStyleContext.get(), &quot;slider&quot;);
-    gtk_style_context_get(sliderStyleContext.get(), gtk_style_context_get_state(sliderStyleContext.get()),
-        scrollbar.orientation() == VerticalScrollbar ? &quot;min-height&quot; : &quot;min-width&quot;, &amp;minThumbLength, nullptr);
-#else
-    gtk_style_context_get_style(styleContext.get(), &quot;min-slider-length&quot;, &amp;minThumbLength, nullptr);
-#endif
</del><ins>+    gtk_style_context_get_style(createStyleContext(&amp;scrollbar).get(), &quot;min-slider-length&quot;, &amp;minThumbLength, nullptr);
</ins><span class="cx">     return minThumbLength;
</span><span class="cx"> }
</span><ins>+#endif
</ins><span class="cx"> 
</span><del>-int ScrollbarThemeGtk::thumbFatness(GtkStyleContext* styleContext, ScrollbarOrientation orientation)
</del><ins>+#else // GTK_API_VERSION_2
+bool ScrollbarThemeGtk::hasThumb(Scrollbar&amp;)
</ins><span class="cx"> {
</span><del>-    int thumbFat = 0;
-#if GTK_CHECK_VERSION(3, 19, 11)
-    gtk_style_context_get(styleContext, gtk_style_context_get_state(styleContext),
-        orientation == VerticalScrollbar ? &quot;min-width&quot; : &quot;min-height&quot;, &amp;thumbFat, nullptr);
-    GtkBorder margin;
-    gtk_style_context_get_margin(styleContext, gtk_style_context_get_state(styleContext), &amp;margin);
-    GtkBorder border;
-    gtk_style_context_get_border(styleContext, gtk_style_context_get_state(styleContext), &amp;border);
-    if (orientation == VerticalScrollbar)
-        thumbFat += margin.left + margin.right + border.left + border.right;
-    else
-        thumbFat += margin.top + margin.bottom + border.top + border.bottom;
-#else
-    UNUSED_PARAM(orientation);
-    gtk_style_context_get_style(styleContext, &quot;slider-width&quot;, &amp;thumbFat, nullptr);
-#endif
-    return thumbFat;
</del><ins>+    return false;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-int ScrollbarThemeGtk::thumbFatness(Scrollbar&amp; scrollbar)
</del><ins>+IntRect ScrollbarThemeGtk::backButtonRect(Scrollbar&amp;, ScrollbarPart, bool)
</ins><span class="cx"> {
</span><del>-    GRefPtr&lt;GtkStyleContext&gt; styleContext = getOrCreateStyleContext(&amp;scrollbar);
-#if GTK_CHECK_VERSION(3, 19, 11)
-    GRefPtr&lt;GtkStyleContext&gt; contentsStyleContext = createChildStyleContext(styleContext.get(), &quot;contents&quot;);
-    GRefPtr&lt;GtkStyleContext&gt; troughStyleContext = createChildStyleContext(contentsStyleContext.get(), &quot;trough&quot;);
-    GRefPtr&lt;GtkStyleContext&gt; sliderStyleContext = createChildStyleContext(troughStyleContext.get(), &quot;slider&quot;);
-    return thumbFatness(sliderStyleContext.get(), scrollbar.orientation());
-#else
-    return thumbFatness(styleContext.get(), scrollbar.orientation());
-#endif
</del><ins>+    return IntRect();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void ScrollbarThemeGtk::getTroughBorder(GtkStyleContext* styleContext, GtkBorder* border)
</del><ins>+IntRect ScrollbarThemeGtk::forwardButtonRect(Scrollbar&amp;, ScrollbarPart, bool)
</ins><span class="cx"> {
</span><del>-#if GTK_CHECK_VERSION(3, 19, 11)
-    gtk_style_context_get_border(styleContext, gtk_style_context_get_state(styleContext), border);
-#else
-    int troughBorderWidth = 0;
-    gtk_style_context_get_style(styleContext, &quot;trough-border&quot;, &amp;troughBorderWidth, nullptr);
-    border-&gt;top = border-&gt;bottom = border-&gt;left = border-&gt;right = troughBorderWidth;
-#endif
</del><ins>+    return IntRect();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void ScrollbarThemeGtk::getTroughBorder(Scrollbar&amp; scrollbar, GtkBorder* border)
</del><ins>+IntRect ScrollbarThemeGtk::trackRect(Scrollbar&amp;, bool)
</ins><span class="cx"> {
</span><del>-    GRefPtr&lt;GtkStyleContext&gt; styleContext = getOrCreateStyleContext(&amp;scrollbar);
-#if GTK_CHECK_VERSION(3, 19, 11)
-    GRefPtr&lt;GtkStyleContext&gt; contentsStyleContext = createChildStyleContext(styleContext.get(), &quot;contents&quot;);
-    GRefPtr&lt;GtkStyleContext&gt; troughStyleContext = createChildStyleContext(contentsStyleContext.get(), &quot;trough&quot;);
-    getTroughBorder(troughStyleContext.get(), border);
-    // Since GTK+ 3.19 the scrollbar can have its own border too.
-    GtkBorder scrollbarBorder;
-    gtk_style_context_get_border(styleContext.get(), gtk_style_context_get_state(styleContext.get()), &amp;scrollbarBorder);
-    border-&gt;left += scrollbarBorder.left;
-    border-&gt;right += scrollbarBorder.right;
-    border-&gt;top += scrollbarBorder.top;
-    border-&gt;bottom += scrollbarBorder.bottom;
-#else
-    getTroughBorder(styleContext.get(), border);
-#endif
</del><ins>+    return IntRect();
</ins><span class="cx"> }
</span><del>-
</del><span class="cx"> #endif // GTK_API_VERSION_2
</span><span class="cx"> 
</span><span class="cx"> }
</span></span></pre></div>
<a id="releasesWebKitGTKwebkit212SourceWebCoreplatformgtkScrollbarThemeGtkh"></a>
<div class="modfile"><h4>Modified: releases/WebKitGTK/webkit-2.12/Source/WebCore/platform/gtk/ScrollbarThemeGtk.h (199476 => 199477)</h4>
<pre class="diff"><span>
<span class="info">--- releases/WebKitGTK/webkit-2.12/Source/WebCore/platform/gtk/ScrollbarThemeGtk.h        2016-04-13 13:40:36 UTC (rev 199476)
+++ releases/WebKitGTK/webkit-2.12/Source/WebCore/platform/gtk/ScrollbarThemeGtk.h        2016-04-13 13:40:51 UTC (rev 199477)
</span><span class="lines">@@ -46,16 +46,10 @@
</span><span class="cx"> #ifndef GTK_API_VERSION_2
</span><span class="cx">     ScrollbarThemeGtk();
</span><span class="cx"> 
</span><del>-    using ScrollbarThemeComposite::thumbRect;
-    IntRect thumbRect(Scrollbar&amp;, const IntRect&amp; unconstrainedTrackRect);
-    virtual bool paint(Scrollbar&amp;, GraphicsContext&amp;, const IntRect&amp; damageRect) override;
-    virtual void paintScrollbarBackground(GraphicsContext&amp;, Scrollbar&amp;) override;
-    virtual void paintTrackBackground(GraphicsContext&amp;, Scrollbar&amp;, const IntRect&amp;) override;
-    virtual void paintThumb(GraphicsContext&amp;, Scrollbar&amp;, const IntRect&amp;) override;
-    virtual void paintButton(GraphicsContext&amp;, Scrollbar&amp;, const IntRect&amp;, ScrollbarPart) override;
-    virtual ScrollbarButtonPressAction handleMousePressEvent(Scrollbar&amp;, const PlatformMouseEvent&amp;, ScrollbarPart) override;
-    virtual int scrollbarThickness(ScrollbarControlSize) override;
-    virtual int minimumThumbLength(Scrollbar&amp;) override;
</del><ins>+    bool paint(Scrollbar&amp;, GraphicsContext&amp;, const IntRect&amp; damageRect) override;
+    ScrollbarButtonPressAction handleMousePressEvent(Scrollbar&amp;, const PlatformMouseEvent&amp;, ScrollbarPart) override;
+    int scrollbarThickness(ScrollbarControlSize) override;
+    int minimumThumbLength(Scrollbar&amp;) override;
</ins><span class="cx"> 
</span><span class="cx">     // TODO: These are the default GTK+ values. At some point we should pull these from the theme itself.
</span><span class="cx">     virtual double initialAutoscrollTimerDelay() override { return 0.20; }
</span><span class="lines">@@ -67,24 +61,11 @@
</span><span class="cx"> 
</span><span class="cx"> private:
</span><span class="cx">     void updateThemeProperties();
</span><del>-    enum class StyleContextMode { Layout, Paint };
-    GRefPtr&lt;GtkStyleContext&gt; getOrCreateStyleContext(Scrollbar* = nullptr, StyleContextMode = StyleContextMode::Layout);
</del><span class="cx"> 
</span><del>-    IntSize buttonSize(Scrollbar&amp;, ScrollbarPart);
-    int stepperSize(Scrollbar&amp;, ScrollbarPart);
-    int thumbFatness(Scrollbar&amp;);
-    int thumbFatness(GtkStyleContext*, ScrollbarOrientation = VerticalScrollbar);
-    void getTroughBorder(Scrollbar&amp;, GtkBorder*);
-    void getTroughBorder(GtkStyleContext*, GtkBorder*);
-    int scrollbarThickness(GtkStyleContext*, ScrollbarOrientation = VerticalScrollbar);
-    void getStepperSpacing(Scrollbar&amp;, ScrollbarPart, GtkBorder*);
-    bool troughUnderSteppers(Scrollbar&amp;);
-
-    GRefPtr&lt;GtkStyleContext&gt; m_cachedStyleContext;
-    gboolean m_hasForwardButtonStartPart;
-    gboolean m_hasForwardButtonEndPart;
-    gboolean m_hasBackButtonStartPart;
-    gboolean m_hasBackButtonEndPart;
</del><ins>+    bool m_hasForwardButtonStartPart : 1;
+    bool m_hasForwardButtonEndPart : 1;
+    bool m_hasBackButtonStartPart : 1;
+    bool m_hasBackButtonEndPart : 1;
</ins><span class="cx">     bool m_usesOverlayScrollbars { false };
</span><span class="cx"> #endif // GTK_API_VERSION_2
</span><span class="cx"> };
</span></span></pre>
</div>
</div>

</body>
</html>