2011-01-12 Martin Robinson <mrobinson@igalia.com>
authormrobinson@webkit.org <mrobinson@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 20 Jan 2011 01:03:18 +0000 (01:03 +0000)
committermrobinson@webkit.org <mrobinson@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 20 Jan 2011 01:03:18 +0000 (01:03 +0000)
        Reviewed by Gustavo Noronha Silva.

        [GTK] Move text field painting out of gtk2drawing.c
        https://bugs.webkit.org/show_bug.cgi?id=52327

        No new tests. This should not change behavior.

        * platform/gtk/RenderThemeGtk2.cpp:
        (WebCore::RenderThemeGtk::paintButton): Use the setWidgetHasFocus helper.
        (WebCore::RenderThemeGtk::paintTextField): Do this manually now instead
        of calling into the Mozilla code.
        * platform/gtk/WidgetRenderingContext.cpp: Added a couple more wrappers
        for GTK+ theme functions.
        (WebCore::WidgetRenderingContext::gtkPaintFlatBox):
        (WebCore::WidgetRenderingContext::gtkPaintShadow):
        * platform/gtk/WidgetRenderingContext.h: Added new method declarations.
        * platform/gtk/gtk2drawing.c: Remove unused code.
        (moz_gtk_get_widget_border):
        (moz_gtk_widget_paint):
        * platform/gtk/gtkdrawing.h:

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

Source/WebCore/ChangeLog
Source/WebCore/platform/gtk/RenderThemeGtk2.cpp
Source/WebCore/platform/gtk/WidgetRenderingContext.cpp
Source/WebCore/platform/gtk/WidgetRenderingContext.h
Source/WebCore/platform/gtk/gtk2drawing.c
Source/WebCore/platform/gtk/gtkdrawing.h

index 4e57c72..b9e45a6 100644 (file)
@@ -1,3 +1,26 @@
+2011-01-12  Martin Robinson  <mrobinson@igalia.com>
+
+        Reviewed by Gustavo Noronha Silva.
+
+        [GTK] Move text field painting out of gtk2drawing.c
+        https://bugs.webkit.org/show_bug.cgi?id=52327
+
+        No new tests. This should not change behavior.
+
+        * platform/gtk/RenderThemeGtk2.cpp:
+        (WebCore::RenderThemeGtk::paintButton): Use the setWidgetHasFocus helper.
+        (WebCore::RenderThemeGtk::paintTextField): Do this manually now instead
+        of calling into the Mozilla code.
+        * platform/gtk/WidgetRenderingContext.cpp: Added a couple more wrappers
+        for GTK+ theme functions.
+        (WebCore::WidgetRenderingContext::gtkPaintFlatBox):
+        (WebCore::WidgetRenderingContext::gtkPaintShadow):
+        * platform/gtk/WidgetRenderingContext.h: Added new method declarations.
+        * platform/gtk/gtk2drawing.c: Remove unused code.
+        (moz_gtk_get_widget_border):
+        (moz_gtk_widget_paint):
+        * platform/gtk/gtkdrawing.h:
+
 2011-01-19  Antti Koivisto  <antti@apple.com>
 
         Reviewed by Oliver Hunt.
index e917816..97b4f78 100644 (file)
 
 #ifdef GTK_API_VERSION_2
 
+// We need this to allow building while using GTK_WIDGET_SET_FLAGS. It's deprecated
+// but some theme engines require it to ensure proper rendering of focus indicators.
+#undef GTK_DISABLE_DEPRECATED
+
 #include "CSSValueKeywords.h"
 #include "GraphicsContext.h"
 #include "GtkVersioning.h"
@@ -243,6 +247,18 @@ bool RenderThemeGtk::paintRadio(RenderObject* renderObject, const PaintInfo& inf
     return false;
 }
 
+static void setWidgetHasFocus(GtkWidget* widget, gboolean hasFocus)
+{
+    g_object_set(widget, "has-focus", hasFocus, NULL);
+
+    // These functions are deprecated in GTK+ 2.22, yet theme engines still look
+    // at these flags when determining if a widget has focus, so we must use them.
+    if (hasFocus)
+        GTK_WIDGET_SET_FLAGS(widget, GTK_HAS_FOCUS);
+    else
+        GTK_WIDGET_UNSET_FLAGS(widget, GTK_HAS_FOCUS);
+}
+
 bool RenderThemeGtk::paintButton(RenderObject* object, const PaintInfo& info, const IntRect& rect)
 {
     if (info.context->paintingDisabled())
@@ -257,12 +273,7 @@ bool RenderThemeGtk::paintButton(RenderObject* object, const PaintInfo& info, co
     gtk_widget_set_direction(widget, gtkTextDirection(object->style()->direction()));
 
     if (isFocused(object)) {
-        if (isEnabled(object)) {
-#if !GTK_CHECK_VERSION(2, 22, 0)
-            GTK_WIDGET_SET_FLAGS(widget, GTK_HAS_FOCUS);
-#endif
-            g_object_set(widget, "has-focus", TRUE, NULL);
-        }
+        setWidgetHasFocus(widget, TRUE);
 
         gboolean interiorFocus = 0, focusWidth = 0, focusPadding = 0;
         gtk_widget_style_get(widget,
@@ -288,10 +299,7 @@ bool RenderThemeGtk::paintButton(RenderObject* object, const PaintInfo& info, co
     if (isFocused(object))
         widgetContext.gtkPaintFocus(focusRect, widget, state, "button");
 
-#if !GTK_CHECK_VERSION(2, 22, 0)
-    GTK_WIDGET_UNSET_FLAGS(widget, GTK_HAS_FOCUS);
-#endif
-    g_object_set(widget, "has-focus", FALSE, NULL);
+    setWidgetHasFocus(widget, FALSE);
     return false;
 }
 
@@ -338,9 +346,47 @@ bool RenderThemeGtk::paintMenuList(RenderObject* object, const PaintInfo& info,
     return paintRenderObject(MOZ_GTK_DROPDOWN, object, info.context, rect);
 }
 
-bool RenderThemeGtk::paintTextField(RenderObject* object, const PaintInfo& info, const IntRect& rect)
+bool RenderThemeGtk::paintTextField(RenderObject* renderObject, const PaintInfo& info, const IntRect& rect)
 {
-    return paintRenderObject(MOZ_GTK_ENTRY, object, info.context, rect);
+    GtkWidget* widget = gtkEntry();
+
+    bool enabled = isEnabled(renderObject) && !isReadOnlyControl(renderObject);
+    GtkStateType backgroundState = enabled ? GTK_STATE_NORMAL : GTK_STATE_INSENSITIVE;
+    gtk_widget_set_sensitive(widget, enabled);
+    gtk_widget_set_direction(widget, gtkTextDirection(renderObject->style()->direction()));
+    setWidgetHasFocus(widget, isFocused(renderObject));
+
+    WidgetRenderingContext widgetContext(info.context, rect);
+    IntRect textFieldRect(IntPoint(), rect.size());
+
+    // The entry background is only painted over the interior part of the GTK+ entry, not
+    // the entire frame. This happens in the Mozilla theme drawing code as well.
+    IntRect interiorRect(textFieldRect);
+    GtkStyle* style = gtk_widget_get_style(widget);
+    interiorRect.inflateX(-style->xthickness);
+    interiorRect.inflateY(-style->ythickness);
+    widgetContext.gtkPaintFlatBox(interiorRect, widget, backgroundState, GTK_SHADOW_NONE, "entry_bg");
+
+    // This is responsible for drawing the actual frame.
+    widgetContext.gtkPaintShadow(textFieldRect, widget, GTK_STATE_NORMAL, GTK_SHADOW_IN, "entry");
+
+    gboolean interiorFocus;
+    gint focusWidth;
+    gtk_widget_style_get(widget,
+                         "interior-focus", &interiorFocus,
+                         "focus-line-width", &focusWidth,  NULL);
+    if (isFocused(renderObject) && !interiorFocus) {
+        // When GTK+ paints a text entry with focus, it shrinks the size of the frame area by the
+        // focus width and paints over the previously unfocused text entry. We need to emulate that
+        // by drawing both the unfocused frame above and the focused frame here.
+        IntRect shadowRect(textFieldRect);
+        shadowRect.inflate(-focusWidth);
+        widgetContext.gtkPaintShadow(shadowRect, widget, GTK_STATE_NORMAL, GTK_SHADOW_IN, "entry");
+
+        widgetContext.gtkPaintFocus(textFieldRect, widget, GTK_STATE_NORMAL, "entry");
+    }
+
+    return false;
 }
 
 bool RenderThemeGtk::paintSliderTrack(RenderObject* object, const PaintInfo& info, const IntRect& rect)
index 1f1437a..29f5ada 100644 (file)
@@ -159,6 +159,13 @@ void WidgetRenderingContext::gtkPaintBox(const IntRect& rect, GtkWidget* widget,
                   widget, detail, paintRect.x, paintRect.y, paintRect.width, paintRect.height);
 }
 
+void WidgetRenderingContext::gtkPaintFlatBox(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_flat_box(gtk_widget_get_style(widget), m_target, stateType, shadowType, &paintRect,
+                       widget, detail, paintRect.x, paintRect.y, paintRect.width, paintRect.height);
+}
+
 void WidgetRenderingContext::gtkPaintFocus(const IntRect& rect, GtkWidget* widget, GtkStateType stateType, const gchar* detail)
 {
     GdkRectangle paintRect = { m_paintRect.x + rect.x(), m_paintRect.y + rect.y(), rect.width(), rect.height() };
@@ -187,6 +194,14 @@ void WidgetRenderingContext::gtkPaintOption(const IntRect& rect, GtkWidget* widg
                      detail, paintRect.x, paintRect.y, paintRect.width, paintRect.height);
 }
 
+void WidgetRenderingContext::gtkPaintShadow(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_shadow(gtk_widget_get_style(widget), m_target, stateType, shadowType, &paintRect, widget,
+                     detail, paintRect.x, paintRect.y, paintRect.width, paintRect.height);
+}
+
+
 }
 
 #endif // GTK_API_VERSION_2
index 90c3269..69e1eb7 100644 (file)
@@ -39,10 +39,12 @@ public:
 
     bool paintMozillaWidget(GtkThemeWidgetType, GtkWidgetState*, int flags, GtkTextDirection = GTK_TEXT_DIR_NONE);
     void gtkPaintBox(const IntRect&, GtkWidget*, GtkStateType, GtkShadowType, const gchar*);
+    void gtkPaintFlatBox(const IntRect&, GtkWidget*, GtkStateType, GtkShadowType, const gchar*);
     void gtkPaintFocus(const IntRect&, GtkWidget*, GtkStateType, const gchar*);
     void gtkPaintSlider(const IntRect&, GtkWidget*, GtkStateType, GtkShadowType, const gchar*, GtkOrientation);
     void gtkPaintCheck(const IntRect&, GtkWidget*, GtkStateType, GtkShadowType, const gchar*);
     void gtkPaintOption(const IntRect&, GtkWidget*, GtkStateType, GtkShadowType, const gchar*);
+    void gtkPaintShadow(const IntRect&, GtkWidget*, GtkStateType, GtkShadowType, const gchar*);
 
 private:
     GraphicsContext* m_graphicsContext;
index 8dc601a..0c11aeb 100644 (file)
@@ -164,16 +164,6 @@ ensure_scrollbar_widget()
     return MOZ_GTK_SUCCESS;
 }
 
-static gint
-ensure_entry_widget()
-{
-    if (!gParts->entryWidget) {
-        gParts->entryWidget = gtk_entry_new();
-        setup_widget_prototype(gParts->entryWidget);
-    }
-    return MOZ_GTK_SUCCESS;
-}
-
 /* We need to have pointers to the inner widgets (button, separator, arrow)
  * of the ComboBox to get the correct rendering from theme engines which
  * special cases their look. Since the inner layout can change, we ask GTK
@@ -778,107 +768,6 @@ moz_gtk_scrollbar_thumb_paint(GtkThemeWidgetType widget,
 }
 
 static gint
-moz_gtk_entry_paint(GdkDrawable* drawable, GdkRectangle* rect,
-                    GdkRectangle* cliprect, GtkWidgetState* state,
-                    GtkWidget* widget, GtkTextDirection direction)
-{
-    GtkStateType bg_state = state->disabled ?
-                                GTK_STATE_INSENSITIVE : GTK_STATE_NORMAL;
-    gint x, y, width = rect->width, height = rect->height;
-    GtkStyle* style;
-    gboolean interior_focus;
-    gboolean theme_honors_transparency = FALSE;
-    gint focus_width;
-
-    gtk_widget_set_direction(widget, direction);
-
-    style = gtk_widget_get_style(widget);
-
-    gtk_widget_style_get(widget,
-                         "interior-focus", &interior_focus,
-                         "focus-line-width", &focus_width,
-                         "honors-transparent-bg-hint", &theme_honors_transparency,
-                         NULL);
-
-    /* gtkentry.c uses two windows, one for the entire widget and one for the
-     * text area inside it. The background of both windows is set to the "base"
-     * color of the new state in gtk_entry_state_changed, but only the inner
-     * textarea window uses gtk_paint_flat_box when exposed */
-
-    TSOffsetStyleGCs(style, rect->x, rect->y);
-
-    /* This gets us a lovely greyish disabledish look */
-    gtk_widget_set_sensitive(widget, !state->disabled);
-
-    /* GTK fills the outer widget window with the base color before drawing the widget.
-     * Some older themes rely on this behavior, but many themes nowadays use rounded
-     * corners on their widgets. While most GTK apps are blissfully unaware of this
-     * problem due to their use of the default window background, we render widgets on
-     * many kinds of backgrounds on the web.
-     * If the theme is able to cope with transparency, then we can skip pre-filling
-     * and notify the theme it will paint directly on the canvas. */
-    if (theme_honors_transparency) {
-        g_object_set_data(G_OBJECT(widget), "transparent-bg-hint", GINT_TO_POINTER(TRUE));
-    } else {
-        gdk_draw_rectangle(drawable, style->base_gc[bg_state], TRUE,
-                           cliprect->x, cliprect->y, cliprect->width, cliprect->height);
-        g_object_set_data(G_OBJECT(widget), "transparent-bg-hint", GINT_TO_POINTER(FALSE));
-    }
-
-    /* Get the position of the inner window, see _gtk_entry_get_borders */
-    x = XTHICKNESS(style);
-    y = YTHICKNESS(style);
-
-    if (!interior_focus) {
-        x += focus_width;
-        y += focus_width;
-    }
-
-    /* Simulate an expose of the inner window */
-    gtk_paint_flat_box(style, drawable, bg_state, GTK_SHADOW_NONE,
-                       cliprect, widget, "entry_bg",  rect->x + x,
-                       rect->y + y, rect->width - 2*x, rect->height - 2*y);
-
-    /* Now paint the shadow and focus border.
-     * We do like in gtk_entry_draw_frame, we first draw the shadow, a tad
-     * smaller when focused if the focus is not interior, then the focus. */
-    x = rect->x;
-    y = rect->y;
-
-    if (state->focused && !state->disabled) {
-        /* This will get us the lit borders that focused textboxes enjoy on
-         * some themes. */
-        GTK_WIDGET_SET_FLAGS(widget, GTK_HAS_FOCUS);
-
-        if (!interior_focus) {
-            /* Indent the border a little bit if we have exterior focus 
-               (this is what GTK does to draw native entries) */
-            x += focus_width;
-            y += focus_width;
-            width -= 2 * focus_width;
-            height -= 2 * focus_width;
-        }
-    }
-
-    gtk_paint_shadow(style, drawable, GTK_STATE_NORMAL, GTK_SHADOW_IN,
-                     cliprect, widget, "entry", x, y, width, height);
-
-    if (state->focused && !state->disabled) {
-        if (!interior_focus) {
-            gtk_paint_focus(style, drawable,  GTK_STATE_NORMAL, cliprect,
-                            widget, "entry",
-                            rect->x, rect->y, rect->width, rect->height);
-        }
-
-        /* Now unset the focus flag. We don't want other entries to look
-         * like they're focused too! */
-        GTK_WIDGET_UNSET_FLAGS(widget, GTK_HAS_FOCUS);
-    }
-
-    return MOZ_GTK_SUCCESS;
-}
-
-static gint
 moz_gtk_combo_box_paint(GdkDrawable* drawable, GdkRectangle* rect,
                         GdkRectangle* cliprect, GtkWidgetState* state,
                         gboolean ishtml, GtkTextDirection direction)
@@ -1034,10 +923,6 @@ moz_gtk_get_widget_border(GtkThemeWidgetType widget, gint* left, gint* top,
             *bottom += style->ythickness;
             return MOZ_GTK_SUCCESS;
         }
-    case MOZ_GTK_ENTRY:
-        ensure_entry_widget();
-        w = gParts->entryWidget;
-        break;
     case MOZ_GTK_DROPDOWN:
         {
             /* We need to account for the arrow on the dropdown, so text
@@ -1168,11 +1053,6 @@ moz_gtk_widget_paint(GtkThemeWidgetType widget, GdkDrawable* drawable,
     case MOZ_GTK_SCROLLED_WINDOW:
         return moz_gtk_scrolled_window_paint(drawable, rect, cliprect, state);
         break;
-    case MOZ_GTK_ENTRY:
-        ensure_entry_widget();
-        return moz_gtk_entry_paint(drawable, rect, cliprect, state,
-                                   gParts->entryWidget, direction);
-        break;
     case MOZ_GTK_DROPDOWN:
         return moz_gtk_combo_box_paint(drawable, rect, cliprect, state,
                                        (gboolean) flags, direction);
index a261de5..238a293 100644 (file)
@@ -48,6 +48,8 @@
 #ifndef _GTK_DRAWING_H_
 #define _GTK_DRAWING_H_
 
+#undef GTK_DISABLE_DEPRECATED
+
 #include <gtk/gtk.h>
 
 #ifdef __cplusplus
@@ -89,7 +91,6 @@ typedef struct _GtkThemeParts {
     GtkWidget* buttonArrowWidget;
     GtkWidget* horizScrollbarWidget;
     GtkWidget* vertScrollbarWidget;
-    GtkWidget* entryWidget;
     GtkWidget* comboBoxWidget;
     GtkWidget* comboBoxButtonWidget;
     GtkWidget* comboBoxArrowWidget;
@@ -133,7 +134,6 @@ typedef enum {
   MOZ_GTK_SCROLLBAR_THUMB_VERTICAL,
   /* Paints the background of a scrolled window */
   MOZ_GTK_SCROLLED_WINDOW,
-  MOZ_GTK_ENTRY,
   /* Paints a GtkOptionMenu. */
   MOZ_GTK_DROPDOWN,
   /* Paints a GtkProgressBar. */