2011-02-08 Martin Robinson <mrobinson@igalia.com>
authormrobinson@webkit.org <mrobinson@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 8 Feb 2011 19:15:32 +0000 (19:15 +0000)
committermrobinson@webkit.org <mrobinson@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 8 Feb 2011 19:15:32 +0000 (19:15 +0000)
        Reviewed by Gustavo Noronha Silva.

        [GTK] Move scrollbar rendering out of gtk2drawing.c
        https://bugs.webkit.org/show_bug.cgi?id=52836

        Replace gtk2drawing.c scrollbar rendering with our own version. This
        is the last use of the Mozilla theme drawing code.

        No new tests. This should not change the rendering of the default
        theme.

        * platform/gtk/GtkVersioning.h: Add some more backported allocation setters.
        * platform/gtk/RenderThemeGtk.h: Add a getter for the scrollbar widgets.
        * platform/gtk/RenderThemeGtk2.cpp:  Initialize and add getters for scrollbar widgets.
        (WebCore::RenderThemeGtk::platformInit): Ditto.
        (WebCore::RenderThemeGtk::gtkHScrollbar): Ditto.
        (WebCore::RenderThemeGtk::gtkVScrollbar): Ditto.
        * platform/gtk/ScrollbarThemeGtk.cpp:
        (WebCore::ScrollbarThemeGtk::paint): We only repaint the scrolled
        window background if we are repainting a button or the thumb. In that
        case also repaint the track rect.
        * platform/gtk/ScrollbarThemeGtk2.cpp: Port to WidgetRenderingContext.
        (WebCore::ScrollbarThemeGtk::ScrollbarThemeGtk): Ditto.
        (WebCore::ScrollbarThemeGtk::updateThemeProperties): Ditto.
        (WebCore::getWidgetForScrollbar): Ditto.
        (WebCore::ScrollbarThemeGtk::paintTrackBackground): Ditto.
        (WebCore::ScrollbarThemeGtk::paintScrollbarBackground): Ditto.
        (WebCore::ScrollbarThemeGtk::paintThumb): Ditto.
        (WebCore::ScrollbarThemeGtk::paintButton): Ditto.
        * platform/gtk/WidgetRenderingContext.cpp: Ditto.
        (WebCore::WidgetRenderingContext::gtkPaintBox): Added an option which
        also adjusts a widget allocation according to the paint rect. This is
        necessary to properly draw scrollbar buttons.
        * platform/gtk/WidgetRenderingContext.h: Ditto.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@77960 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WebCore/ChangeLog
Source/WebCore/platform/gtk/GtkVersioning.h
Source/WebCore/platform/gtk/RenderThemeGtk.h
Source/WebCore/platform/gtk/RenderThemeGtk2.cpp
Source/WebCore/platform/gtk/ScrollbarThemeGtk.cpp
Source/WebCore/platform/gtk/ScrollbarThemeGtk2.cpp
Source/WebCore/platform/gtk/WidgetRenderingContext.cpp

index f65d3b9..86b065d 100644 (file)
@@ -1,3 +1,40 @@
+2011-02-08  Martin Robinson  <mrobinson@igalia.com>
+
+        Reviewed by Gustavo Noronha Silva.
+
+        [GTK] Move scrollbar rendering out of gtk2drawing.c
+        https://bugs.webkit.org/show_bug.cgi?id=52836
+
+        Replace gtk2drawing.c scrollbar rendering with our own version. This
+        is the last use of the Mozilla theme drawing code.
+
+        No new tests. This should not change the rendering of the default
+        theme.
+
+        * platform/gtk/GtkVersioning.h: Add some more backported allocation setters.
+        * platform/gtk/RenderThemeGtk.h: Add a getter for the scrollbar widgets.
+        * platform/gtk/RenderThemeGtk2.cpp:  Initialize and add getters for scrollbar widgets.
+        (WebCore::RenderThemeGtk::platformInit): Ditto.
+        (WebCore::RenderThemeGtk::gtkHScrollbar): Ditto.
+        (WebCore::RenderThemeGtk::gtkVScrollbar): Ditto.
+        * platform/gtk/ScrollbarThemeGtk.cpp: 
+        (WebCore::ScrollbarThemeGtk::paint): We only repaint the scrolled
+        window background if we are repainting a button or the thumb. In that
+        case also repaint the track rect.
+        * platform/gtk/ScrollbarThemeGtk2.cpp: Port to WidgetRenderingContext.
+        (WebCore::ScrollbarThemeGtk::ScrollbarThemeGtk): Ditto.
+        (WebCore::ScrollbarThemeGtk::updateThemeProperties): Ditto.
+        (WebCore::getWidgetForScrollbar): Ditto.
+        (WebCore::ScrollbarThemeGtk::paintTrackBackground): Ditto.
+        (WebCore::ScrollbarThemeGtk::paintScrollbarBackground): Ditto.
+        (WebCore::ScrollbarThemeGtk::paintThumb): Ditto.
+        (WebCore::ScrollbarThemeGtk::paintButton): Ditto.
+        * platform/gtk/WidgetRenderingContext.cpp: Ditto.
+        (WebCore::WidgetRenderingContext::gtkPaintBox): Added an option which
+        also adjusts a widget allocation according to the paint rect. This is
+        necessary to properly draw scrollbar buttons.
+        * platform/gtk/WidgetRenderingContext.h: Ditto.
+
 2011-02-08  Simon Fraser  <simon.fraser@apple.com>
 
         Reviewed by Dan Bernstein.
index 7e9fcd1..70e1bbe 100644 (file)
@@ -94,7 +94,10 @@ const gchar* gtk_menu_item_get_label(GtkMenuItem*);
 #define gtk_selection_data_get_length(data) (data)->length
 #define gtk_selection_data_get_data(data) (data)->data
 #define gtk_selection_data_get_target(data) (data)->target
-#define gtk_adjustment_set_page_size(adj, value) (adj)->page_size = value
+#define gtk_adjustment_set_page_size(adj, newValue) ((adj)->page_size = newValue)
+#define gtk_adjustment_set_value(adj, newValue) ((adj)->value = newValue)
+#define gtk_adjustment_set_lower(adj, newValue) ((adj)->lower = newValue)
+#define gtk_adjustment_set_upper(adj, newValue) ((adj)->upper = newValue)
 
 void gtk_adjustment_configure(GtkAdjustment* adjustment, gdouble value, gdouble lower, gdouble upper,
                               gdouble stepIncrement, gdouble pageIncrement, gdouble pageSize);
index 6581df9..8620127 100644 (file)
@@ -92,7 +92,8 @@ public:
 #endif
 
 #ifdef GTK_API_VERSION_2
-    GtkWidget* gtkScrollbar();
+    GtkWidget* gtkVScrollbar() const;
+    GtkWidget* gtkHScrollbar() const;
     static void getIndicatorMetrics(ControlPart, int& indicatorSize, int& indicatorSpacing);
 #else
     GtkStyleContext* gtkScrollbarStyle();
@@ -233,6 +234,8 @@ private:
     mutable GtkWidget* m_gtkComboBoxButton;
     mutable GtkWidget* m_gtkComboBoxArrow;
     mutable GtkWidget* m_gtkComboBoxSeparator;
+    mutable GtkWidget* m_gtkVScrollbar;
+    mutable GtkWidget* m_gtkHScrollbar;
     bool m_themePartsHaveRGBAColormap;
     friend class WidgetRenderingContext;
 #endif
index cb79287..b370251 100644 (file)
@@ -68,6 +68,8 @@ void RenderThemeGtk::platformInit()
     m_gtkComboBoxButton = 0;
     m_gtkComboBoxArrow = 0;
     m_gtkComboBoxSeparator = 0;
+    m_gtkVScrollbar = 0;
+    m_gtkHScrollbar = 0;
 
     memset(&m_themeParts, 0, sizeof(GtkThemeParts));
     GdkColormap* colormap = gdk_screen_get_rgba_colormap(gdk_screen_get_default());
@@ -891,9 +893,22 @@ GtkWidget* RenderThemeGtk::gtkComboBoxSeparator() const
     return m_gtkComboBoxSeparator;
 }
 
-GtkWidget* RenderThemeGtk::gtkScrollbar()
+GtkWidget* RenderThemeGtk::gtkHScrollbar() const
 {
-    return moz_gtk_get_scrollbar_widget();
+    if (m_gtkHScrollbar)
+        return m_gtkHScrollbar;
+    m_gtkHScrollbar = gtk_hscrollbar_new(0);
+    setupWidgetAndAddToContainer(m_gtkHScrollbar, gtkContainer());
+    return m_gtkHScrollbar;
+}
+
+GtkWidget* RenderThemeGtk::gtkVScrollbar() const
+{
+    if (m_gtkVScrollbar)
+        return m_gtkVScrollbar;
+    m_gtkVScrollbar = gtk_vscrollbar_new(0);
+    setupWidgetAndAddToContainer(m_gtkVScrollbar, gtkContainer());
+    return m_gtkVScrollbar;
 }
 
 } // namespace WebCore
index cb9b0f8..7f7c269 100644 (file)
@@ -228,9 +228,10 @@ bool ScrollbarThemeGtk::paint(Scrollbar* scrollbar, GraphicsContext* graphicsCon
             scrollMask |= ThumbPart;
     }
 
-    paintScrollbarBackground(graphicsContext, scrollbar);
-
-    if (scrollMask & TrackBGPart)
+    ScrollbarControlPartMask allButtons = BackButtonStartPart | BackButtonEndPart
+                                         | ForwardButtonStartPart | ForwardButtonEndPart;
+    if (scrollMask & TrackBGPart || scrollMask & ThumbPart || scrollMask & allButtons)
+        paintScrollbarBackground(graphicsContext, scrollbar);
         paintTrackBackground(graphicsContext, scrollbar, trackPaintRect);
 
     // Paint the back and forward buttons.
index 79295c1..7a0cdcd 100644 (file)
@@ -46,107 +46,169 @@ static void gtkStyleSetCallback(GtkWidget* widget, GtkStyle* previous, Scrollbar
 ScrollbarThemeGtk::ScrollbarThemeGtk()
 {
     updateThemeProperties();
-    g_signal_connect(static_cast<RenderThemeGtk*>(RenderTheme::defaultTheme().get())->gtkScrollbar(),
+    g_signal_connect(static_cast<RenderThemeGtk*>(RenderTheme::defaultTheme().get())->gtkHScrollbar(),
          "style-set", G_CALLBACK(gtkStyleSetCallback), this);
 }
 
 void ScrollbarThemeGtk::updateThemeProperties()
 {
-    MozGtkScrollbarMetrics metrics;
-    moz_gtk_get_scrollbar_metrics(&metrics);
-
-    m_thumbFatness = metrics.slider_width;
-    m_troughBorderWidth = metrics.trough_border;
-    m_stepperSize = metrics.stepper_size;
-    m_stepperSpacing = metrics.stepper_spacing;
-    m_minThumbLength = metrics.min_slider_size;
-    m_troughUnderSteppers = metrics.trough_under_steppers;
-    m_hasForwardButtonStartPart = metrics.has_secondary_forward_stepper;
-    m_hasBackButtonEndPart = metrics.has_secondary_backward_stepper;
-
+    GtkWidget* scrollbar = static_cast<RenderThemeGtk*>(RenderTheme::defaultTheme().get())->gtkHScrollbar();
+    gtk_widget_style_get(scrollbar,
+                         "slider_width", &m_thumbFatness,
+                         "trough_border", &m_troughBorderWidth,
+                         "stepper-size", &m_stepperSize,
+                         "trough-under-steppers", &m_troughUnderSteppers,
+                         "has-secondary-forward-stepper", &m_hasForwardButtonStartPart,
+                         "has-secondary-backward-stepper", &m_hasBackButtonEndPart, NULL);
+    m_minThumbLength = gtk_range_get_min_slider_size(GTK_RANGE(scrollbar));
     updateScrollbarsFrameThickness();
 }
 
-void ScrollbarThemeGtk::paintTrackBackground(GraphicsContext* context, Scrollbar* scrollbar, const IntRect& rect)
+static GtkWidget* getWidgetForScrollbar(Scrollbar* scrollbar)
 {
-    GtkWidgetState state;
-    state.focused = FALSE;
-    state.isDefault = FALSE;
-    state.canDefault = FALSE;
-    state.disabled = FALSE;
-    state.active = FALSE;
-    state.inHover = FALSE;
+    RenderThemeGtk* theme = static_cast<RenderThemeGtk*>(RenderTheme::defaultTheme().get());
+    return scrollbar->orientation() == VerticalScrollbar ? theme->gtkVScrollbar() : theme->gtkHScrollbar();
+}
 
+void ScrollbarThemeGtk::paintTrackBackground(GraphicsContext* context, Scrollbar* scrollbar, const IntRect& rect)
+{
     // 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;
+    IntRect fullScrollbarRect(rect);
     if (m_troughUnderSteppers)
         fullScrollbarRect = IntRect(scrollbar->x(), scrollbar->y(), scrollbar->width(), scrollbar->height());
 
-    GtkThemeWidgetType type = scrollbar->orientation() == VerticalScrollbar ? MOZ_GTK_SCROLLBAR_TRACK_VERTICAL : MOZ_GTK_SCROLLBAR_TRACK_HORIZONTAL;
     WidgetRenderingContext widgetContext(context, fullScrollbarRect);
-    widgetContext.paintMozillaWidget(type, &state, 0);
+    IntRect paintRect(IntPoint(), fullScrollbarRect.size());
+    widgetContext.gtkPaintBox(paintRect, getWidgetForScrollbar(scrollbar),
+                              GTK_STATE_ACTIVE, GTK_SHADOW_IN, "trough");
 }
 
 void ScrollbarThemeGtk::paintScrollbarBackground(GraphicsContext* context, Scrollbar* scrollbar)
 {
-    // This is unused by the moz_gtk_scrollecd_window_paint.
-    GtkWidgetState state;
     IntRect fullScrollbarRect = IntRect(scrollbar->x(), scrollbar->y(), scrollbar->width(), scrollbar->height());
+
     WidgetRenderingContext widgetContext(context, fullScrollbarRect);
-    widgetContext.paintMozillaWidget(MOZ_GTK_SCROLLED_WINDOW, &state, 0);
+    widgetContext.gtkPaintBox(fullScrollbarRect, getWidgetForScrollbar(scrollbar),
+                              GTK_STATE_NORMAL, GTK_SHADOW_IN, "scrolled_window");
 }
 
 void ScrollbarThemeGtk::paintThumb(GraphicsContext* context, Scrollbar* scrollbar, const IntRect& rect)
 {
-    GtkWidgetState state;
-    state.focused = FALSE;
-    state.isDefault = FALSE;
-    state.canDefault = FALSE;
-    state.disabled = FALSE;
-    state.active = scrollbar->pressedPart() == ThumbPart;
-    state.inHover = scrollbar->hoveredPart() == ThumbPart;
-    state.maxpos = scrollbar->maximum();
-    state.curpos = scrollbar->currentPos();
-
-    GtkThemeWidgetType type = scrollbar->orientation() == VerticalScrollbar ? MOZ_GTK_SCROLLBAR_THUMB_VERTICAL : MOZ_GTK_SCROLLBAR_THUMB_HORIZONTAL;
+    GtkWidget* widget = getWidgetForScrollbar(scrollbar);
+    gboolean activateSlider;
+    gtk_widget_style_get(widget, "activate-slider", &activateSlider, NULL);
+
+    GtkStateType stateType = GTK_STATE_NORMAL;
+    GtkShadowType shadowType = GTK_SHADOW_OUT;
+    if (activateSlider && scrollbar->pressedPart() == ThumbPart) {
+        stateType = GTK_STATE_ACTIVE;
+        shadowType = GTK_SHADOW_IN;
+    } else if (scrollbar->pressedPart() == ThumbPart || scrollbar->hoveredPart() == ThumbPart)
+        stateType = GTK_STATE_PRELIGHT;
+
+    // The adjustment controls the rendering of the scrollbar thumb. If it's not set
+    // properly the theme may not draw the thumb borders properly.
+    GtkAdjustment* adjustment = gtk_range_get_adjustment(GTK_RANGE(widget));
+    gtk_adjustment_set_value(adjustment, scrollbar->currentPos());
+    gtk_adjustment_set_lower(adjustment, 0);
+    gtk_adjustment_set_upper(adjustment, scrollbar->maximum());
+
+    GtkOrientation orientation = GTK_ORIENTATION_HORIZONTAL;
+    if (scrollbar->orientation() == VerticalScrollbar) {
+        gtk_adjustment_set_page_size(adjustment, rect.height());
+        orientation = GTK_ORIENTATION_VERTICAL;
+    } else
+        gtk_adjustment_set_page_size(adjustment, rect.width());
+
     WidgetRenderingContext widgetContext(context, rect);
-    widgetContext.paintMozillaWidget(type, &state, 0);
+    IntRect sliderRect(IntPoint(), rect.size());
+    widgetContext.gtkPaintSlider(sliderRect, widget, stateType, shadowType, "slider", orientation);
 }
 
 void ScrollbarThemeGtk::paintButton(GraphicsContext* context, Scrollbar* scrollbar, const IntRect& rect, ScrollbarPart part)
 {
-    int flags = 0;
-    if (scrollbar->orientation() == VerticalScrollbar)
-        flags |= MOZ_GTK_STEPPER_VERTICAL;
-
-    if (part == ForwardButtonEndPart)
-        flags |= (MOZ_GTK_STEPPER_DOWN | MOZ_GTK_STEPPER_BOTTOM);
-    if (part == ForwardButtonStartPart)
-        flags |= MOZ_GTK_STEPPER_DOWN;
-
-    GtkWidgetState state;
-    state.focused = TRUE;
-    state.isDefault = TRUE;
-    state.canDefault = TRUE;
-    state.depressed = FALSE;
+    // The buttons will be disabled if the thumb is as the appropriate extreme.
+    GtkShadowType shadowType = GTK_SHADOW_OUT;
+    GtkStateType stateType = GTK_STATE_INSENSITIVE;
+    bool pressed = (part == scrollbar->pressedPart());
 
     if ((BackButtonStartPart == part && scrollbar->currentPos())
         || (BackButtonEndPart == part && scrollbar->currentPos())
         || (ForwardButtonEndPart == part && scrollbar->currentPos() != scrollbar->maximum())
         || (ForwardButtonStartPart == part && scrollbar->currentPos() != scrollbar->maximum())) {
-        state.disabled = FALSE;
-        state.active = part == scrollbar->pressedPart();
-        state.inHover = part == scrollbar->hoveredPart();
+        stateType = GTK_STATE_NORMAL;
+        if (pressed) {
+            stateType = GTK_STATE_ACTIVE;
+            shadowType = GTK_SHADOW_IN;
+        } else if (part == scrollbar->hoveredPart())
+            stateType = GTK_STATE_PRELIGHT;
+    }
+
+    // Themes determine how to draw the button (which button to draw) based on the allocation
+    // of the widget. Where the target rect is in relation to the total widget allocation
+    // determines the button.
+    ScrollbarOrientation orientation = scrollbar->orientation();
+    int buttonSize = (orientation == VerticalScrollbar) ? rect.height() : rect.width();
+    int totalAllocation = buttonSize * 5; // One space for each button and one extra.
+    int buttonOffset = 0;
+    if (ForwardButtonStartPart == part)
+        buttonOffset = buttonSize;
+    else if (BackButtonEndPart == part)
+        buttonOffset = 3 * buttonSize;
+    else if (ForwardButtonEndPart == part)
+        buttonOffset = 4 * buttonSize;
+
+    // Now we want the allocation to be relative to the origin of the painted rect.
+    GtkWidget* widget = getWidgetForScrollbar(scrollbar);
+    GtkAllocation allocation;
+    gtk_widget_get_allocation(widget, &allocation);
+    allocation.x = allocation.y = 0;
+    allocation.width = rect.width();
+    allocation.height = rect.height();
+
+    if (orientation == VerticalScrollbar) {
+        allocation.height = totalAllocation;
+        allocation.y -= buttonOffset;
     } else {
-        state.disabled = TRUE;
-        state.active = FALSE;
-        state.inHover = FALSE;
+        allocation.width = totalAllocation;
+        allocation.x -= buttonOffset;
     }
+    gtk_widget_set_allocation(widget, &allocation);
 
+    const char* detail = orientation == VerticalScrollbar ? "vscrollbar" : "hscrollbar";
     WidgetRenderingContext widgetContext(context, rect);
-    widgetContext.paintMozillaWidget(MOZ_GTK_SCROLLBAR_BUTTON, &state, flags);
+
+    IntRect buttonRect(IntPoint(), rect.size());
+    widgetContext.gtkPaintBox(buttonRect, widget, stateType, shadowType, detail);
+
+    float arrowScaling;
+    gtk_widget_style_get(widget, "arrow-scaling", &arrowScaling, NULL);
+    IntSize arrowSize = rect.size();
+    arrowSize.scale(arrowScaling);
+    IntRect arrowRect(IntPoint(buttonRect.x() + (buttonRect.width() - arrowSize.width()) / 2,
+                               buttonRect.y() + (buttonRect.height() - arrowSize.height()) / 2),
+                      arrowSize);
+    if (pressed) {
+        int arrowDisplacementX, arrowDisplacementY;
+        gtk_widget_style_get(widget,
+                             "arrow-displacement-x", &arrowDisplacementX,
+                             "arrow-displacement-y", &arrowDisplacementY,
+                             NULL);
+        arrowRect.move(arrowDisplacementX, arrowDisplacementY);
+    }
+
+    GtkArrowType arrowType = GTK_ARROW_DOWN;
+    if (orientation == VerticalScrollbar) {
+        if (part == BackButtonEndPart || part == BackButtonStartPart)
+            arrowType = GTK_ARROW_UP;
+    } else if (orientation == HorizontalScrollbar) {
+        arrowType = GTK_ARROW_RIGHT;
+        if (part == BackButtonEndPart || part == BackButtonStartPart)
+            arrowType = GTK_ARROW_LEFT;
+    }
+    widgetContext.gtkPaintArrow(arrowRect, widget, stateType, shadowType, arrowType, detail);
 }
 
 } // namespace WebCore
index 51b32ea..0632273 100644 (file)
@@ -155,7 +155,16 @@ bool WidgetRenderingContext::paintMozillaWidget(GtkThemeWidgetType type, GtkWidg
 void WidgetRenderingContext::gtkPaintBox(const IntRect& rect, GtkWidget* widget, GtkStateType stateType, GtkShadowType shadowType, const gchar* detail)
 {
     GdkRectangle paintRect = { m_paintRect.x + rect.x(), m_paintRect.y + rect.y(), rect.width(), rect.height() };
-    gtk_paint_box(gtk_widget_get_style(widget), m_target, stateType, shadowType, &m_paintRect,
+
+    // Some widgets also need their allocation adjusted to account for extra space.
+    // Right now only scrollbar buttons have significant allocations.
+    GtkAllocation allocation;
+    gtk_widget_get_allocation(widget, &allocation);
+    allocation.x += m_paintRect.x;
+    allocation.y += m_paintRect.y;
+    gtk_widget_set_allocation(widget, &allocation);
+
+    gtk_paint_box(gtk_widget_get_style(widget), m_target, stateType, shadowType, &paintRect,
                   widget, detail, paintRect.x, paintRect.y, paintRect.width, paintRect.height);
 }