widget/gtk/gtk2drawing.c

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/widget/gtk/gtk2drawing.c	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,3418 @@
     1.4 +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
     1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.8 +
     1.9 +/*
    1.10 + * This file contains painting functions for each of the gtk2 widgets.
    1.11 + * Adapted from the gtkdrawing.c, and gtk+2.0 source.
    1.12 + */
    1.13 +
    1.14 +#include <gtk/gtk.h>
    1.15 +#include <gdk/gdkprivate.h>
    1.16 +#include <string.h>
    1.17 +#include "gtkdrawing.h"
    1.18 +#include "nsDebug.h"
    1.19 +#include "prinrval.h"
    1.20 +
    1.21 +#include <math.h>
    1.22 +
    1.23 +#define XTHICKNESS(style) (style->xthickness)
    1.24 +#define YTHICKNESS(style) (style->ythickness)
    1.25 +#define WINDOW_IS_MAPPED(window) ((window) && GDK_IS_WINDOW(window) && gdk_window_is_visible(window))
    1.26 +
    1.27 +static GtkWidget* gProtoWindow;
    1.28 +static GtkWidget* gProtoLayout;
    1.29 +static GtkWidget* gButtonWidget;
    1.30 +static GtkWidget* gToggleButtonWidget;
    1.31 +static GtkWidget* gButtonArrowWidget;
    1.32 +static GtkWidget* gCheckboxWidget;
    1.33 +static GtkWidget* gRadiobuttonWidget;
    1.34 +static GtkWidget* gHorizScrollbarWidget;
    1.35 +static GtkWidget* gVertScrollbarWidget;
    1.36 +static GtkWidget* gSpinWidget;
    1.37 +static GtkWidget* gHScaleWidget;
    1.38 +static GtkWidget* gVScaleWidget;
    1.39 +static GtkWidget* gEntryWidget;
    1.40 +static GtkWidget* gComboBoxWidget;
    1.41 +static GtkWidget* gComboBoxButtonWidget;
    1.42 +static GtkWidget* gComboBoxArrowWidget;
    1.43 +static GtkWidget* gComboBoxSeparatorWidget;
    1.44 +static GtkWidget* gComboBoxEntryWidget;
    1.45 +static GtkWidget* gComboBoxEntryTextareaWidget;
    1.46 +static GtkWidget* gComboBoxEntryButtonWidget;
    1.47 +static GtkWidget* gComboBoxEntryArrowWidget;
    1.48 +static GtkWidget* gHandleBoxWidget;
    1.49 +static GtkWidget* gToolbarWidget;
    1.50 +static GtkWidget* gFrameWidget;
    1.51 +static GtkWidget* gStatusbarWidget;
    1.52 +static GtkWidget* gProgressWidget;
    1.53 +static GtkWidget* gTabWidget;
    1.54 +static GtkWidget* gTooltipWidget;
    1.55 +static GtkWidget* gMenuBarWidget;
    1.56 +static GtkWidget* gMenuBarItemWidget;
    1.57 +static GtkWidget* gMenuPopupWidget;
    1.58 +static GtkWidget* gMenuItemWidget;
    1.59 +static GtkWidget* gImageMenuItemWidget;
    1.60 +static GtkWidget* gCheckMenuItemWidget;
    1.61 +static GtkWidget* gTreeViewWidget;
    1.62 +static GtkTreeViewColumn* gMiddleTreeViewColumn;
    1.63 +static GtkWidget* gTreeHeaderCellWidget;
    1.64 +static GtkWidget* gTreeHeaderSortArrowWidget;
    1.65 +static GtkWidget* gExpanderWidget;
    1.66 +static GtkWidget* gToolbarSeparatorWidget;
    1.67 +static GtkWidget* gMenuSeparatorWidget;
    1.68 +static GtkWidget* gHPanedWidget;
    1.69 +static GtkWidget* gVPanedWidget;
    1.70 +static GtkWidget* gScrolledWindowWidget;
    1.71 +
    1.72 +static style_prop_t style_prop_func;
    1.73 +static gboolean have_arrow_scaling;
    1.74 +static gboolean is_initialized;
    1.75 +
    1.76 +/* Because we have such an unconventional way of drawing widgets, signal to the GTK theme engine
    1.77 +   that they are drawing for Mozilla instead of a conventional GTK app so they can do any specific
    1.78 +   things they may want to do. */
    1.79 +static void
    1.80 +moz_gtk_set_widget_name(GtkWidget* widget)
    1.81 +{
    1.82 +    gtk_widget_set_name(widget, "MozillaGtkWidget");
    1.83 +}
    1.84 +
    1.85 +gint
    1.86 +moz_gtk_enable_style_props(style_prop_t styleGetProp)
    1.87 +{
    1.88 +    style_prop_func = styleGetProp;
    1.89 +    return MOZ_GTK_SUCCESS;
    1.90 +}
    1.91 +
    1.92 +static gint
    1.93 +ensure_window_widget()
    1.94 +{
    1.95 +    if (!gProtoWindow) {
    1.96 +        gProtoWindow = gtk_window_new(GTK_WINDOW_POPUP);
    1.97 +        gtk_widget_realize(gProtoWindow);
    1.98 +        moz_gtk_set_widget_name(gProtoWindow);
    1.99 +    }
   1.100 +    return MOZ_GTK_SUCCESS;
   1.101 +}
   1.102 +
   1.103 +static gint
   1.104 +setup_widget_prototype(GtkWidget* widget)
   1.105 +{
   1.106 +    ensure_window_widget();
   1.107 +    if (!gProtoLayout) {
   1.108 +        gProtoLayout = gtk_fixed_new();
   1.109 +        gtk_container_add(GTK_CONTAINER(gProtoWindow), gProtoLayout);
   1.110 +    }
   1.111 +
   1.112 +    gtk_container_add(GTK_CONTAINER(gProtoLayout), widget);
   1.113 +    gtk_widget_realize(widget);
   1.114 +    g_object_set_data(G_OBJECT(widget), "transparent-bg-hint", GINT_TO_POINTER(TRUE));
   1.115 +    return MOZ_GTK_SUCCESS;
   1.116 +}
   1.117 +
   1.118 +static gint
   1.119 +ensure_button_widget()
   1.120 +{
   1.121 +    if (!gButtonWidget) {
   1.122 +        gButtonWidget = gtk_button_new_with_label("M");
   1.123 +        setup_widget_prototype(gButtonWidget);
   1.124 +    }
   1.125 +    return MOZ_GTK_SUCCESS;
   1.126 +}
   1.127 +
   1.128 +static gint
   1.129 +ensure_hpaned_widget()
   1.130 +{
   1.131 +    if (!gHPanedWidget) {
   1.132 +        gHPanedWidget = gtk_hpaned_new();
   1.133 +        setup_widget_prototype(gHPanedWidget);
   1.134 +    }
   1.135 +    return MOZ_GTK_SUCCESS;
   1.136 +}
   1.137 +
   1.138 +static gint
   1.139 +ensure_vpaned_widget()
   1.140 +{
   1.141 +    if (!gVPanedWidget) {
   1.142 +        gVPanedWidget = gtk_vpaned_new();
   1.143 +        setup_widget_prototype(gVPanedWidget);
   1.144 +    }
   1.145 +    return MOZ_GTK_SUCCESS;
   1.146 +}
   1.147 +
   1.148 +static gint
   1.149 +ensure_toggle_button_widget()
   1.150 +{
   1.151 +    if (!gToggleButtonWidget) {
   1.152 +        gToggleButtonWidget = gtk_toggle_button_new();
   1.153 +        setup_widget_prototype(gToggleButtonWidget);
   1.154 +        /* toggle button must be set active to get the right style on hover. */
   1.155 +        GTK_TOGGLE_BUTTON(gToggleButtonWidget)->active = TRUE;
   1.156 +  }
   1.157 +  return MOZ_GTK_SUCCESS;
   1.158 +}
   1.159 +
   1.160 +static gint
   1.161 +ensure_button_arrow_widget()
   1.162 +{
   1.163 +    if (!gButtonArrowWidget) {
   1.164 +        ensure_toggle_button_widget();
   1.165 +
   1.166 +        gButtonArrowWidget = gtk_arrow_new(GTK_ARROW_DOWN, GTK_SHADOW_OUT);
   1.167 +        gtk_container_add(GTK_CONTAINER(gToggleButtonWidget), gButtonArrowWidget);
   1.168 +        gtk_widget_realize(gButtonArrowWidget);
   1.169 +    }
   1.170 +    return MOZ_GTK_SUCCESS;
   1.171 +}
   1.172 +
   1.173 +static gint
   1.174 +ensure_checkbox_widget()
   1.175 +{
   1.176 +    if (!gCheckboxWidget) {
   1.177 +        gCheckboxWidget = gtk_check_button_new_with_label("M");
   1.178 +        setup_widget_prototype(gCheckboxWidget);
   1.179 +    }
   1.180 +    return MOZ_GTK_SUCCESS;
   1.181 +}
   1.182 +
   1.183 +static gint
   1.184 +ensure_radiobutton_widget()
   1.185 +{
   1.186 +    if (!gRadiobuttonWidget) {
   1.187 +        gRadiobuttonWidget = gtk_radio_button_new_with_label(NULL, "M");
   1.188 +        setup_widget_prototype(gRadiobuttonWidget);
   1.189 +    }
   1.190 +    return MOZ_GTK_SUCCESS;
   1.191 +}
   1.192 +
   1.193 +static gint
   1.194 +ensure_scrollbar_widget()
   1.195 +{
   1.196 +    if (!gVertScrollbarWidget) {
   1.197 +        gVertScrollbarWidget = gtk_vscrollbar_new(NULL);
   1.198 +        setup_widget_prototype(gVertScrollbarWidget);
   1.199 +    }
   1.200 +    if (!gHorizScrollbarWidget) {
   1.201 +        gHorizScrollbarWidget = gtk_hscrollbar_new(NULL);
   1.202 +        setup_widget_prototype(gHorizScrollbarWidget);
   1.203 +    }
   1.204 +    return MOZ_GTK_SUCCESS;
   1.205 +}
   1.206 +
   1.207 +static gint
   1.208 +ensure_spin_widget()
   1.209 +{
   1.210 +  if (!gSpinWidget) {
   1.211 +    gSpinWidget = gtk_spin_button_new(NULL, 1, 0);
   1.212 +    setup_widget_prototype(gSpinWidget);
   1.213 +  }
   1.214 +  return MOZ_GTK_SUCCESS;
   1.215 +}
   1.216 +
   1.217 +static gint
   1.218 +ensure_scale_widget()
   1.219 +{
   1.220 +  if (!gHScaleWidget) {
   1.221 +    gHScaleWidget = gtk_hscale_new(NULL);
   1.222 +    setup_widget_prototype(gHScaleWidget);
   1.223 +  }
   1.224 +  if (!gVScaleWidget) {
   1.225 +    gVScaleWidget = gtk_vscale_new(NULL);
   1.226 +    setup_widget_prototype(gVScaleWidget);
   1.227 +  }
   1.228 +  return MOZ_GTK_SUCCESS;
   1.229 +}
   1.230 +
   1.231 +static gint
   1.232 +ensure_entry_widget()
   1.233 +{
   1.234 +    if (!gEntryWidget) {
   1.235 +        gEntryWidget = gtk_entry_new();
   1.236 +        setup_widget_prototype(gEntryWidget);
   1.237 +    }
   1.238 +    return MOZ_GTK_SUCCESS;
   1.239 +}
   1.240 +
   1.241 +/* We need to have pointers to the inner widgets (button, separator, arrow)
   1.242 + * of the ComboBox to get the correct rendering from theme engines which
   1.243 + * special cases their look. Since the inner layout can change, we ask GTK
   1.244 + * to NULL our pointers when they are about to become invalid because the
   1.245 + * corresponding widgets don't exist anymore. It's the role of
   1.246 + * g_object_add_weak_pointer().
   1.247 + * Note that if we don't find the inner widgets (which shouldn't happen), we
   1.248 + * fallback to use generic "non-inner" widgets, and they don't need that kind
   1.249 + * of weak pointer since they are explicit children of gProtoWindow and as
   1.250 + * such GTK holds a strong reference to them. */
   1.251 +static void
   1.252 +moz_gtk_get_combo_box_inner_button(GtkWidget *widget, gpointer client_data)
   1.253 +{
   1.254 +    if (GTK_IS_TOGGLE_BUTTON(widget)) {
   1.255 +        gComboBoxButtonWidget = widget;
   1.256 +        g_object_add_weak_pointer(G_OBJECT(widget),
   1.257 +                                  (gpointer) &gComboBoxButtonWidget);
   1.258 +        gtk_widget_realize(widget);
   1.259 +        g_object_set_data(G_OBJECT(widget), "transparent-bg-hint", GINT_TO_POINTER(TRUE));
   1.260 +    }
   1.261 +}
   1.262 +
   1.263 +static void
   1.264 +moz_gtk_get_combo_box_button_inner_widgets(GtkWidget *widget,
   1.265 +                                           gpointer client_data)
   1.266 +{
   1.267 +    if (GTK_IS_SEPARATOR(widget)) {
   1.268 +        gComboBoxSeparatorWidget = widget;
   1.269 +        g_object_add_weak_pointer(G_OBJECT(widget),
   1.270 +                                  (gpointer) &gComboBoxSeparatorWidget);
   1.271 +    } else if (GTK_IS_ARROW(widget)) {
   1.272 +        gComboBoxArrowWidget = widget;
   1.273 +        g_object_add_weak_pointer(G_OBJECT(widget),
   1.274 +                                  (gpointer) &gComboBoxArrowWidget);
   1.275 +    } else
   1.276 +        return;
   1.277 +    gtk_widget_realize(widget);
   1.278 +    g_object_set_data(G_OBJECT(widget), "transparent-bg-hint", GINT_TO_POINTER(TRUE));
   1.279 +}
   1.280 +
   1.281 +static gint
   1.282 +ensure_combo_box_widgets()
   1.283 +{
   1.284 +    GtkWidget* buttonChild;
   1.285 +
   1.286 +    if (gComboBoxButtonWidget && gComboBoxArrowWidget)
   1.287 +        return MOZ_GTK_SUCCESS;
   1.288 +
   1.289 +    /* Create a ComboBox if needed */
   1.290 +    if (!gComboBoxWidget) {
   1.291 +        gComboBoxWidget = gtk_combo_box_new();
   1.292 +        setup_widget_prototype(gComboBoxWidget);
   1.293 +    }
   1.294 +
   1.295 +    /* Get its inner Button */
   1.296 +    gtk_container_forall(GTK_CONTAINER(gComboBoxWidget),
   1.297 +                         moz_gtk_get_combo_box_inner_button,
   1.298 +                         NULL);
   1.299 +
   1.300 +    if (gComboBoxButtonWidget) {
   1.301 +        /* Get the widgets inside the Button */
   1.302 +        buttonChild = GTK_BIN(gComboBoxButtonWidget)->child;
   1.303 +        if (GTK_IS_HBOX(buttonChild)) {
   1.304 +            /* appears-as-list = FALSE, cell-view = TRUE; the button
   1.305 +             * contains an hbox. This hbox is there because the ComboBox
   1.306 +             * needs to place a cell renderer, a separator, and an arrow in
   1.307 +             * the button when appears-as-list is FALSE. */
   1.308 +            gtk_container_forall(GTK_CONTAINER(buttonChild),
   1.309 +                                 moz_gtk_get_combo_box_button_inner_widgets,
   1.310 +                                 NULL);
   1.311 +        } else if(GTK_IS_ARROW(buttonChild)) {
   1.312 +            /* appears-as-list = TRUE, or cell-view = FALSE;
   1.313 +             * the button only contains an arrow */
   1.314 +            gComboBoxArrowWidget = buttonChild;
   1.315 +            g_object_add_weak_pointer(G_OBJECT(buttonChild), (gpointer)
   1.316 +                                      &gComboBoxArrowWidget);
   1.317 +            gtk_widget_realize(gComboBoxArrowWidget);
   1.318 +            g_object_set_data(G_OBJECT(gComboBoxArrowWidget),
   1.319 +                              "transparent-bg-hint", GINT_TO_POINTER(TRUE));
   1.320 +        }
   1.321 +    } else {
   1.322 +        /* Shouldn't be reached with current internal gtk implementation; we
   1.323 +         * use a generic toggle button as last resort fallback to avoid
   1.324 +         * crashing. */
   1.325 +        ensure_toggle_button_widget();
   1.326 +        gComboBoxButtonWidget = gToggleButtonWidget;
   1.327 +    }
   1.328 +
   1.329 +    if (!gComboBoxArrowWidget) {
   1.330 +        /* Shouldn't be reached with current internal gtk implementation;
   1.331 +         * we gButtonArrowWidget as last resort fallback to avoid
   1.332 +         * crashing. */
   1.333 +        ensure_button_arrow_widget();
   1.334 +        gComboBoxArrowWidget = gButtonArrowWidget;
   1.335 +    }
   1.336 +
   1.337 +    /* We don't test the validity of gComboBoxSeparatorWidget since there
   1.338 +     * is none when "appears-as-list" = TRUE or "cell-view" = FALSE; if it
   1.339 +     * is invalid we just won't paint it. */
   1.340 +
   1.341 +    return MOZ_GTK_SUCCESS;
   1.342 +}
   1.343 +
   1.344 +/* We need to have pointers to the inner widgets (entry, button, arrow) of
   1.345 + * the ComboBoxEntry to get the correct rendering from theme engines which
   1.346 + * special cases their look. Since the inner layout can change, we ask GTK
   1.347 + * to NULL our pointers when they are about to become invalid because the
   1.348 + * corresponding widgets don't exist anymore. It's the role of
   1.349 + * g_object_add_weak_pointer().
   1.350 + * Note that if we don't find the inner widgets (which shouldn't happen), we
   1.351 + * fallback to use generic "non-inner" widgets, and they don't need that kind
   1.352 + * of weak pointer since they are explicit children of gProtoWindow and as
   1.353 + * such GTK holds a strong reference to them. */
   1.354 +static void
   1.355 +moz_gtk_get_combo_box_entry_inner_widgets(GtkWidget *widget,
   1.356 +                                          gpointer client_data)
   1.357 +{
   1.358 +    if (GTK_IS_TOGGLE_BUTTON(widget)) {
   1.359 +        gComboBoxEntryButtonWidget = widget;
   1.360 +        g_object_add_weak_pointer(G_OBJECT(widget),
   1.361 +                                  (gpointer) &gComboBoxEntryButtonWidget);
   1.362 +    } else if (GTK_IS_ENTRY(widget)) {
   1.363 +        gComboBoxEntryTextareaWidget = widget;
   1.364 +        g_object_add_weak_pointer(G_OBJECT(widget),
   1.365 +                                  (gpointer) &gComboBoxEntryTextareaWidget);
   1.366 +    } else
   1.367 +        return;
   1.368 +    gtk_widget_realize(widget);
   1.369 +    g_object_set_data(G_OBJECT(widget), "transparent-bg-hint", GINT_TO_POINTER(TRUE));
   1.370 +}
   1.371 +
   1.372 +static void
   1.373 +moz_gtk_get_combo_box_entry_arrow(GtkWidget *widget, gpointer client_data)
   1.374 +{
   1.375 +    if (GTK_IS_ARROW(widget)) {
   1.376 +        gComboBoxEntryArrowWidget = widget;
   1.377 +        g_object_add_weak_pointer(G_OBJECT(widget),
   1.378 +                                  (gpointer) &gComboBoxEntryArrowWidget);
   1.379 +        gtk_widget_realize(widget);
   1.380 +        g_object_set_data(G_OBJECT(widget), "transparent-bg-hint", GINT_TO_POINTER(TRUE));
   1.381 +    }
   1.382 +}
   1.383 +
   1.384 +static gint
   1.385 +ensure_combo_box_entry_widgets()
   1.386 +{
   1.387 +    GtkWidget* buttonChild;
   1.388 +
   1.389 +    if (gComboBoxEntryTextareaWidget &&
   1.390 +            gComboBoxEntryButtonWidget &&
   1.391 +            gComboBoxEntryArrowWidget)
   1.392 +        return MOZ_GTK_SUCCESS;
   1.393 +
   1.394 +    /* Create a ComboBoxEntry if needed */
   1.395 +    if (!gComboBoxEntryWidget) {
   1.396 +        gComboBoxEntryWidget = gtk_combo_box_entry_new();
   1.397 +        setup_widget_prototype(gComboBoxEntryWidget);
   1.398 +    }
   1.399 +
   1.400 +    /* Get its inner Entry and Button */
   1.401 +    gtk_container_forall(GTK_CONTAINER(gComboBoxEntryWidget),
   1.402 +                         moz_gtk_get_combo_box_entry_inner_widgets,
   1.403 +                         NULL);
   1.404 +
   1.405 +    if (!gComboBoxEntryTextareaWidget) {
   1.406 +        ensure_entry_widget();
   1.407 +        gComboBoxEntryTextareaWidget = gEntryWidget;
   1.408 +    }
   1.409 +
   1.410 +    if (gComboBoxEntryButtonWidget) {
   1.411 +        /* Get the Arrow inside the Button */
   1.412 +        buttonChild = GTK_BIN(gComboBoxEntryButtonWidget)->child;
   1.413 +        if (GTK_IS_HBOX(buttonChild)) {
   1.414 +            /* appears-as-list = FALSE, cell-view = TRUE; the button
   1.415 +             * contains an hbox. This hbox is there because ComboBoxEntry
   1.416 +             * inherits from ComboBox which needs to place a cell renderer,
   1.417 +             * a separator, and an arrow in the button when appears-as-list
   1.418 +             * is FALSE. Here the hbox should only contain an arrow, since
   1.419 +             * a ComboBoxEntry doesn't need all those widgets in the
   1.420 +             * button. */
   1.421 +            gtk_container_forall(GTK_CONTAINER(buttonChild),
   1.422 +                                 moz_gtk_get_combo_box_entry_arrow,
   1.423 +                                 NULL);
   1.424 +        } else if(GTK_IS_ARROW(buttonChild)) {
   1.425 +            /* appears-as-list = TRUE, or cell-view = FALSE;
   1.426 +             * the button only contains an arrow */
   1.427 +            gComboBoxEntryArrowWidget = buttonChild;
   1.428 +            g_object_add_weak_pointer(G_OBJECT(buttonChild), (gpointer)
   1.429 +                                      &gComboBoxEntryArrowWidget);
   1.430 +            gtk_widget_realize(gComboBoxEntryArrowWidget);
   1.431 +            g_object_set_data(G_OBJECT(gComboBoxEntryArrowWidget),
   1.432 +                              "transparent-bg-hint", GINT_TO_POINTER(TRUE));
   1.433 +        }
   1.434 +    } else {
   1.435 +        /* Shouldn't be reached with current internal gtk implementation;
   1.436 +         * we use a generic toggle button as last resort fallback to avoid
   1.437 +         * crashing. */
   1.438 +        ensure_toggle_button_widget();
   1.439 +        gComboBoxEntryButtonWidget = gToggleButtonWidget;
   1.440 +    }
   1.441 +
   1.442 +    if (!gComboBoxEntryArrowWidget) {
   1.443 +        /* Shouldn't be reached with current internal gtk implementation;
   1.444 +         * we gButtonArrowWidget as last resort fallback to avoid
   1.445 +         * crashing. */
   1.446 +        ensure_button_arrow_widget();
   1.447 +        gComboBoxEntryArrowWidget = gButtonArrowWidget;
   1.448 +    }
   1.449 +
   1.450 +    return MOZ_GTK_SUCCESS;
   1.451 +}
   1.452 +
   1.453 +
   1.454 +static gint
   1.455 +ensure_handlebox_widget()
   1.456 +{
   1.457 +    if (!gHandleBoxWidget) {
   1.458 +        gHandleBoxWidget = gtk_handle_box_new();
   1.459 +        setup_widget_prototype(gHandleBoxWidget);
   1.460 +    }
   1.461 +    return MOZ_GTK_SUCCESS;
   1.462 +}
   1.463 +
   1.464 +static gint
   1.465 +ensure_toolbar_widget()
   1.466 +{
   1.467 +    if (!gToolbarWidget) {
   1.468 +        ensure_handlebox_widget();
   1.469 +        gToolbarWidget = gtk_toolbar_new();
   1.470 +        gtk_container_add(GTK_CONTAINER(gHandleBoxWidget), gToolbarWidget);
   1.471 +        gtk_widget_realize(gToolbarWidget);
   1.472 +        g_object_set_data(G_OBJECT(gToolbarWidget), "transparent-bg-hint", GINT_TO_POINTER(TRUE));
   1.473 +    }
   1.474 +    return MOZ_GTK_SUCCESS;
   1.475 +}
   1.476 +
   1.477 +static gint
   1.478 +ensure_toolbar_separator_widget()
   1.479 +{
   1.480 +    if (!gToolbarSeparatorWidget) {
   1.481 +        ensure_toolbar_widget();
   1.482 +        gToolbarSeparatorWidget = GTK_WIDGET(gtk_separator_tool_item_new());
   1.483 +        setup_widget_prototype(gToolbarSeparatorWidget);
   1.484 +    }
   1.485 +    return MOZ_GTK_SUCCESS;
   1.486 +}
   1.487 +
   1.488 +static gint
   1.489 +ensure_tooltip_widget()
   1.490 +{
   1.491 +    if (!gTooltipWidget) {
   1.492 +        gTooltipWidget = gtk_window_new(GTK_WINDOW_POPUP);
   1.493 +        gtk_widget_realize(gTooltipWidget);
   1.494 +        moz_gtk_set_widget_name(gTooltipWidget);
   1.495 +    }
   1.496 +    return MOZ_GTK_SUCCESS;
   1.497 +}
   1.498 +
   1.499 +static gint
   1.500 +ensure_tab_widget()
   1.501 +{
   1.502 +    if (!gTabWidget) {
   1.503 +        gTabWidget = gtk_notebook_new();
   1.504 +        setup_widget_prototype(gTabWidget);
   1.505 +    }
   1.506 +    return MOZ_GTK_SUCCESS;
   1.507 +}
   1.508 +
   1.509 +static gint
   1.510 +ensure_progress_widget()
   1.511 +{
   1.512 +    if (!gProgressWidget) {
   1.513 +        gProgressWidget = gtk_progress_bar_new();
   1.514 +        setup_widget_prototype(gProgressWidget);
   1.515 +    }
   1.516 +    return MOZ_GTK_SUCCESS;
   1.517 +}
   1.518 +
   1.519 +static gint
   1.520 +ensure_statusbar_widget()
   1.521 +{
   1.522 +    if (!gStatusbarWidget) {
   1.523 +      gStatusbarWidget = gtk_statusbar_new();
   1.524 +      setup_widget_prototype(gStatusbarWidget);
   1.525 +    }
   1.526 +    return MOZ_GTK_SUCCESS;
   1.527 +}
   1.528 +
   1.529 +static gint
   1.530 +ensure_frame_widget()
   1.531 +{
   1.532 +    if (!gFrameWidget) {
   1.533 +        ensure_statusbar_widget();
   1.534 +        gFrameWidget = gtk_frame_new(NULL);
   1.535 +        gtk_container_add(GTK_CONTAINER(gStatusbarWidget), gFrameWidget);
   1.536 +        gtk_widget_realize(gFrameWidget);
   1.537 +    }
   1.538 +    return MOZ_GTK_SUCCESS;
   1.539 +}
   1.540 +
   1.541 +static gint
   1.542 +ensure_menu_bar_widget()
   1.543 +{
   1.544 +    if (!gMenuBarWidget) {
   1.545 +        gMenuBarWidget = gtk_menu_bar_new();
   1.546 +        setup_widget_prototype(gMenuBarWidget);
   1.547 +    }
   1.548 +    return MOZ_GTK_SUCCESS;
   1.549 +}
   1.550 +
   1.551 +static gint
   1.552 +ensure_menu_bar_item_widget()
   1.553 +{
   1.554 +    if (!gMenuBarItemWidget) {
   1.555 +        ensure_menu_bar_widget();
   1.556 +        gMenuBarItemWidget = gtk_menu_item_new();
   1.557 +        gtk_menu_shell_append(GTK_MENU_SHELL(gMenuBarWidget),
   1.558 +                              gMenuBarItemWidget);
   1.559 +        gtk_widget_realize(gMenuBarItemWidget);
   1.560 +        g_object_set_data(G_OBJECT(gMenuBarItemWidget),
   1.561 +                          "transparent-bg-hint", GINT_TO_POINTER(TRUE));
   1.562 +    }
   1.563 +    return MOZ_GTK_SUCCESS;
   1.564 +}
   1.565 +
   1.566 +static gint
   1.567 +ensure_menu_popup_widget()
   1.568 +{
   1.569 +    if (!gMenuPopupWidget) {
   1.570 +        ensure_menu_bar_item_widget();
   1.571 +        gMenuPopupWidget = gtk_menu_new();
   1.572 +        gtk_menu_item_set_submenu(GTK_MENU_ITEM(gMenuBarItemWidget),
   1.573 +                                  gMenuPopupWidget);
   1.574 +        gtk_widget_realize(gMenuPopupWidget);
   1.575 +        g_object_set_data(G_OBJECT(gMenuPopupWidget),
   1.576 +                          "transparent-bg-hint", GINT_TO_POINTER(TRUE));
   1.577 +    }
   1.578 +    return MOZ_GTK_SUCCESS;
   1.579 +}
   1.580 +
   1.581 +static gint
   1.582 +ensure_menu_item_widget()
   1.583 +{
   1.584 +    if (!gMenuItemWidget) {
   1.585 +        ensure_menu_popup_widget();
   1.586 +        gMenuItemWidget = gtk_menu_item_new_with_label("M");
   1.587 +        gtk_menu_shell_append(GTK_MENU_SHELL(gMenuPopupWidget),
   1.588 +                              gMenuItemWidget);
   1.589 +        gtk_widget_realize(gMenuItemWidget);
   1.590 +        g_object_set_data(G_OBJECT(gMenuItemWidget),
   1.591 +                          "transparent-bg-hint", GINT_TO_POINTER(TRUE));
   1.592 +    }
   1.593 +    return MOZ_GTK_SUCCESS;
   1.594 +}
   1.595 +
   1.596 +static gint
   1.597 +ensure_image_menu_item_widget()
   1.598 +{
   1.599 +    if (!gImageMenuItemWidget) {
   1.600 +        ensure_menu_popup_widget();
   1.601 +        gImageMenuItemWidget = gtk_image_menu_item_new();
   1.602 +        gtk_menu_shell_append(GTK_MENU_SHELL(gMenuPopupWidget),
   1.603 +                              gImageMenuItemWidget);
   1.604 +        gtk_widget_realize(gImageMenuItemWidget);
   1.605 +        g_object_set_data(G_OBJECT(gImageMenuItemWidget),
   1.606 +                          "transparent-bg-hint", GINT_TO_POINTER(TRUE));
   1.607 +    }
   1.608 +    return MOZ_GTK_SUCCESS;
   1.609 +}
   1.610 +
   1.611 +static gint
   1.612 +ensure_menu_separator_widget()
   1.613 +{
   1.614 +    if (!gMenuSeparatorWidget) {
   1.615 +        ensure_menu_popup_widget();
   1.616 +        gMenuSeparatorWidget = gtk_separator_menu_item_new();
   1.617 +        gtk_menu_shell_append(GTK_MENU_SHELL(gMenuPopupWidget),
   1.618 +                              gMenuSeparatorWidget);
   1.619 +        gtk_widget_realize(gMenuSeparatorWidget);
   1.620 +        g_object_set_data(G_OBJECT(gMenuSeparatorWidget),
   1.621 +                          "transparent-bg-hint", GINT_TO_POINTER(TRUE));
   1.622 +    }
   1.623 +    return MOZ_GTK_SUCCESS;
   1.624 +}
   1.625 +
   1.626 +static gint
   1.627 +ensure_check_menu_item_widget()
   1.628 +{
   1.629 +    if (!gCheckMenuItemWidget) {
   1.630 +        ensure_menu_popup_widget();
   1.631 +        gCheckMenuItemWidget = gtk_check_menu_item_new_with_label("M");
   1.632 +        gtk_menu_shell_append(GTK_MENU_SHELL(gMenuPopupWidget),
   1.633 +                              gCheckMenuItemWidget);
   1.634 +        gtk_widget_realize(gCheckMenuItemWidget);
   1.635 +        g_object_set_data(G_OBJECT(gCheckMenuItemWidget),
   1.636 +                          "transparent-bg-hint", GINT_TO_POINTER(TRUE));
   1.637 +    }
   1.638 +    return MOZ_GTK_SUCCESS;
   1.639 +}
   1.640 +
   1.641 +static gint
   1.642 +ensure_tree_view_widget()
   1.643 +{
   1.644 +    if (!gTreeViewWidget) {
   1.645 +        gTreeViewWidget = gtk_tree_view_new();
   1.646 +        setup_widget_prototype(gTreeViewWidget);
   1.647 +    }
   1.648 +    return MOZ_GTK_SUCCESS;
   1.649 +}
   1.650 +
   1.651 +static gint
   1.652 +ensure_tree_header_cell_widget()
   1.653 +{
   1.654 +    if(!gTreeHeaderCellWidget) {
   1.655 +        /*
   1.656 +         * Some GTK engines paint the first and last cell
   1.657 +         * of a TreeView header with a highlight.
   1.658 +         * Since we do not know where our widget will be relative
   1.659 +         * to the other buttons in the TreeView header, we must
   1.660 +         * paint it as a button that is between two others,
   1.661 +         * thus ensuring it is neither the first or last button
   1.662 +         * in the header.
   1.663 +         * GTK doesn't give us a way to do this explicitly,
   1.664 +         * so we must paint with a button that is between two
   1.665 +         * others.
   1.666 +         */
   1.667 +
   1.668 +        GtkTreeViewColumn* firstTreeViewColumn;
   1.669 +        GtkTreeViewColumn* lastTreeViewColumn;
   1.670 +
   1.671 +        ensure_tree_view_widget();
   1.672 +
   1.673 +        /* Create and append our three columns */
   1.674 +        firstTreeViewColumn = gtk_tree_view_column_new();
   1.675 +        gtk_tree_view_column_set_title(firstTreeViewColumn, "M");
   1.676 +        gtk_tree_view_append_column(GTK_TREE_VIEW(gTreeViewWidget), firstTreeViewColumn);
   1.677 +
   1.678 +        gMiddleTreeViewColumn = gtk_tree_view_column_new();
   1.679 +        gtk_tree_view_column_set_title(gMiddleTreeViewColumn, "M");
   1.680 +        gtk_tree_view_append_column(GTK_TREE_VIEW(gTreeViewWidget),
   1.681 +                                    gMiddleTreeViewColumn);
   1.682 +
   1.683 +        lastTreeViewColumn = gtk_tree_view_column_new();
   1.684 +        gtk_tree_view_column_set_title(lastTreeViewColumn, "M");
   1.685 +        gtk_tree_view_append_column(GTK_TREE_VIEW(gTreeViewWidget), lastTreeViewColumn);
   1.686 +
   1.687 +        /* Use the middle column's header for our button */
   1.688 +        gTreeHeaderCellWidget = gMiddleTreeViewColumn->button;
   1.689 +        gTreeHeaderSortArrowWidget = gMiddleTreeViewColumn->arrow;
   1.690 +        g_object_set_data(G_OBJECT(gTreeHeaderCellWidget),
   1.691 +                          "transparent-bg-hint", GINT_TO_POINTER(TRUE));
   1.692 +        g_object_set_data(G_OBJECT(gTreeHeaderSortArrowWidget),
   1.693 +                          "transparent-bg-hint", GINT_TO_POINTER(TRUE));
   1.694 +    }
   1.695 +    return MOZ_GTK_SUCCESS;
   1.696 +}
   1.697 +
   1.698 +static gint
   1.699 +ensure_expander_widget()
   1.700 +{
   1.701 +    if (!gExpanderWidget) {
   1.702 +        gExpanderWidget = gtk_expander_new("M");
   1.703 +        setup_widget_prototype(gExpanderWidget);
   1.704 +    }
   1.705 +    return MOZ_GTK_SUCCESS;
   1.706 +}
   1.707 +
   1.708 +static gint
   1.709 +ensure_scrolled_window_widget()
   1.710 +{
   1.711 +    if (!gScrolledWindowWidget) {
   1.712 +        gScrolledWindowWidget = gtk_scrolled_window_new(NULL, NULL);
   1.713 +        setup_widget_prototype(gScrolledWindowWidget);
   1.714 +    }
   1.715 +    return MOZ_GTK_SUCCESS;
   1.716 +}
   1.717 +
   1.718 +static GtkStateType
   1.719 +ConvertGtkState(GtkWidgetState* state)
   1.720 +{
   1.721 +    if (state->disabled)
   1.722 +        return GTK_STATE_INSENSITIVE;
   1.723 +    else if (state->depressed)
   1.724 +        return (state->inHover ? GTK_STATE_PRELIGHT : GTK_STATE_ACTIVE);
   1.725 +    else if (state->inHover)
   1.726 +        return (state->active ? GTK_STATE_ACTIVE : GTK_STATE_PRELIGHT);
   1.727 +    else
   1.728 +        return GTK_STATE_NORMAL;
   1.729 +}
   1.730 +
   1.731 +static gint
   1.732 +TSOffsetStyleGCArray(GdkGC** gcs, gint xorigin, gint yorigin)
   1.733 +{
   1.734 +    int i;
   1.735 +    /* there are 5 gc's in each array, for each of the widget states */
   1.736 +    for (i = 0; i < 5; ++i)
   1.737 +        gdk_gc_set_ts_origin(gcs[i], xorigin, yorigin);
   1.738 +    return MOZ_GTK_SUCCESS;
   1.739 +}
   1.740 +
   1.741 +static gint
   1.742 +TSOffsetStyleGCs(GtkStyle* style, gint xorigin, gint yorigin)
   1.743 +{
   1.744 +    TSOffsetStyleGCArray(style->fg_gc, xorigin, yorigin);
   1.745 +    TSOffsetStyleGCArray(style->bg_gc, xorigin, yorigin);
   1.746 +    TSOffsetStyleGCArray(style->light_gc, xorigin, yorigin);
   1.747 +    TSOffsetStyleGCArray(style->dark_gc, xorigin, yorigin);
   1.748 +    TSOffsetStyleGCArray(style->mid_gc, xorigin, yorigin);
   1.749 +    TSOffsetStyleGCArray(style->text_gc, xorigin, yorigin);
   1.750 +    TSOffsetStyleGCArray(style->base_gc, xorigin, yorigin);
   1.751 +    gdk_gc_set_ts_origin(style->black_gc, xorigin, yorigin);
   1.752 +    gdk_gc_set_ts_origin(style->white_gc, xorigin, yorigin);
   1.753 +    return MOZ_GTK_SUCCESS;
   1.754 +}
   1.755 +
   1.756 +gint
   1.757 +moz_gtk_init()
   1.758 +{
   1.759 +    GtkWidgetClass *entry_class;
   1.760 +
   1.761 +    if (is_initialized)
   1.762 +        return MOZ_GTK_SUCCESS;
   1.763 +
   1.764 +    is_initialized = TRUE;
   1.765 +    have_arrow_scaling = (gtk_major_version > 2 ||
   1.766 +                          (gtk_major_version == 2 && gtk_minor_version >= 12));
   1.767 +
   1.768 +    /* Add style property to GtkEntry.
   1.769 +     * Adding the style property to the normal GtkEntry class means that it
   1.770 +     * will work without issues inside GtkComboBox and for Spinbuttons. */
   1.771 +    entry_class = g_type_class_ref(GTK_TYPE_ENTRY);
   1.772 +    gtk_widget_class_install_style_property(entry_class,
   1.773 +        g_param_spec_boolean("honors-transparent-bg-hint",
   1.774 +                             "Transparent BG enabling flag",
   1.775 +                             "If TRUE, the theme is able to draw the GtkEntry on non-prefilled background.",
   1.776 +                             FALSE,
   1.777 +                             G_PARAM_READWRITE));
   1.778 +
   1.779 +    return MOZ_GTK_SUCCESS;
   1.780 +}
   1.781 +
   1.782 +GdkColormap*
   1.783 +moz_gtk_widget_get_colormap()
   1.784 +{
   1.785 +    /* Child widgets inherit the colormap from the GtkWindow. */
   1.786 +    ensure_window_widget();
   1.787 +    return gtk_widget_get_colormap(gProtoWindow);
   1.788 +}
   1.789 +
   1.790 +gint
   1.791 +moz_gtk_checkbox_get_metrics(gint* indicator_size, gint* indicator_spacing)
   1.792 +{
   1.793 +    ensure_checkbox_widget();
   1.794 +
   1.795 +    gtk_widget_style_get (gCheckboxWidget,
   1.796 +                          "indicator_size", indicator_size,
   1.797 +                          "indicator_spacing", indicator_spacing,
   1.798 +                          NULL);
   1.799 +
   1.800 +    return MOZ_GTK_SUCCESS;
   1.801 +}
   1.802 +
   1.803 +gint
   1.804 +moz_gtk_radio_get_metrics(gint* indicator_size, gint* indicator_spacing)
   1.805 +{
   1.806 +    ensure_radiobutton_widget();
   1.807 +
   1.808 +    gtk_widget_style_get (gRadiobuttonWidget,
   1.809 +                          "indicator_size", indicator_size,
   1.810 +                          "indicator_spacing", indicator_spacing,
   1.811 +                          NULL);
   1.812 +
   1.813 +    return MOZ_GTK_SUCCESS;
   1.814 +}
   1.815 +
   1.816 +gint
   1.817 +moz_gtk_widget_get_focus(GtkWidget* widget, gboolean* interior_focus,
   1.818 +                         gint* focus_width, gint* focus_pad) 
   1.819 +{
   1.820 +    gtk_widget_style_get (widget,
   1.821 +                          "interior-focus", interior_focus,
   1.822 +                          "focus-line-width", focus_width,
   1.823 +                          "focus-padding", focus_pad,
   1.824 +                          NULL);
   1.825 +
   1.826 +    return MOZ_GTK_SUCCESS;
   1.827 +}
   1.828 +
   1.829 +gint
   1.830 +moz_gtk_menuitem_get_horizontal_padding(gint* horizontal_padding)
   1.831 +{
   1.832 +    ensure_menu_item_widget();
   1.833 +
   1.834 +    gtk_widget_style_get (gMenuItemWidget,
   1.835 +                          "horizontal-padding", horizontal_padding,
   1.836 +                          NULL);
   1.837 +
   1.838 +    return MOZ_GTK_SUCCESS;
   1.839 +}
   1.840 +
   1.841 +gint
   1.842 +moz_gtk_checkmenuitem_get_horizontal_padding(gint* horizontal_padding)
   1.843 +{
   1.844 +    ensure_check_menu_item_widget();
   1.845 +
   1.846 +    gtk_widget_style_get (gCheckMenuItemWidget,
   1.847 +                          "horizontal-padding", horizontal_padding,
   1.848 +                          NULL);
   1.849 +
   1.850 +    return MOZ_GTK_SUCCESS;
   1.851 +}
   1.852 +
   1.853 +gint
   1.854 +moz_gtk_button_get_default_overflow(gint* border_top, gint* border_left,
   1.855 +                                    gint* border_bottom, gint* border_right)
   1.856 +{
   1.857 +    GtkBorder* default_outside_border;
   1.858 +
   1.859 +    ensure_button_widget();
   1.860 +    gtk_widget_style_get(gButtonWidget,
   1.861 +                         "default-outside-border", &default_outside_border,
   1.862 +                         NULL);
   1.863 +
   1.864 +    if (default_outside_border) {
   1.865 +        *border_top = default_outside_border->top;
   1.866 +        *border_left = default_outside_border->left;
   1.867 +        *border_bottom = default_outside_border->bottom;
   1.868 +        *border_right = default_outside_border->right;
   1.869 +        gtk_border_free(default_outside_border);
   1.870 +    } else {
   1.871 +        *border_top = *border_left = *border_bottom = *border_right = 0;
   1.872 +    }
   1.873 +    return MOZ_GTK_SUCCESS;
   1.874 +}
   1.875 +
   1.876 +static gint
   1.877 +moz_gtk_button_get_default_border(gint* border_top, gint* border_left,
   1.878 +                                  gint* border_bottom, gint* border_right)
   1.879 +{
   1.880 +    GtkBorder* default_border;
   1.881 +
   1.882 +    ensure_button_widget();
   1.883 +    gtk_widget_style_get(gButtonWidget,
   1.884 +                         "default-border", &default_border,
   1.885 +                         NULL);
   1.886 +
   1.887 +    if (default_border) {
   1.888 +        *border_top = default_border->top;
   1.889 +        *border_left = default_border->left;
   1.890 +        *border_bottom = default_border->bottom;
   1.891 +        *border_right = default_border->right;
   1.892 +        gtk_border_free(default_border);
   1.893 +    } else {
   1.894 +        /* see gtkbutton.c */
   1.895 +        *border_top = *border_left = *border_bottom = *border_right = 1;
   1.896 +    }
   1.897 +    return MOZ_GTK_SUCCESS;
   1.898 +}
   1.899 +
   1.900 +gint
   1.901 +moz_gtk_splitter_get_metrics(gint orientation, gint* size)
   1.902 +{
   1.903 +    if (orientation == GTK_ORIENTATION_HORIZONTAL) {
   1.904 +        ensure_hpaned_widget();
   1.905 +        gtk_widget_style_get(gHPanedWidget, "handle_size", size, NULL);
   1.906 +    } else {
   1.907 +        ensure_vpaned_widget();
   1.908 +        gtk_widget_style_get(gVPanedWidget, "handle_size", size, NULL);
   1.909 +    }
   1.910 +    return MOZ_GTK_SUCCESS;
   1.911 +}
   1.912 +
   1.913 +gint
   1.914 +moz_gtk_button_get_inner_border(GtkWidget* widget, GtkBorder* inner_border)
   1.915 +{
   1.916 +    static const GtkBorder default_inner_border = { 1, 1, 1, 1 };
   1.917 +    GtkBorder *tmp_border;
   1.918 +
   1.919 +    gtk_widget_style_get (widget, "inner-border", &tmp_border, NULL);
   1.920 +
   1.921 +    if (tmp_border) {
   1.922 +        *inner_border = *tmp_border;
   1.923 +        gtk_border_free(tmp_border);
   1.924 +    }
   1.925 +    else
   1.926 +        *inner_border = default_inner_border;
   1.927 +
   1.928 +    return MOZ_GTK_SUCCESS;
   1.929 +}
   1.930 +
   1.931 +static gint
   1.932 +moz_gtk_button_paint(GdkDrawable* drawable, GdkRectangle* rect,
   1.933 +                     GdkRectangle* cliprect, GtkWidgetState* state,
   1.934 +                     GtkReliefStyle relief, GtkWidget* widget,
   1.935 +                     GtkTextDirection direction)
   1.936 +{
   1.937 +    GtkShadowType shadow_type;
   1.938 +    GtkStyle* style = widget->style;
   1.939 +    GtkStateType button_state = ConvertGtkState(state);
   1.940 +    gint x = rect->x, y=rect->y, width=rect->width, height=rect->height;
   1.941 +
   1.942 +    gboolean interior_focus;
   1.943 +    gint focus_width, focus_pad;
   1.944 +
   1.945 +    moz_gtk_widget_get_focus(widget, &interior_focus, &focus_width, &focus_pad);
   1.946 +
   1.947 +    if (WINDOW_IS_MAPPED(drawable)) {
   1.948 +        gdk_window_set_back_pixmap(drawable, NULL, TRUE);
   1.949 +        gdk_window_clear_area(drawable, cliprect->x, cliprect->y,
   1.950 +                              cliprect->width, cliprect->height);
   1.951 +    }
   1.952 +
   1.953 +    gtk_widget_set_state(widget, button_state);
   1.954 +    gtk_widget_set_direction(widget, direction);
   1.955 +
   1.956 +    if (state->isDefault)
   1.957 +        GTK_WIDGET_SET_FLAGS(widget, GTK_HAS_DEFAULT);
   1.958 +
   1.959 +    GTK_BUTTON(widget)->relief = relief;
   1.960 +
   1.961 +    /* Some theme engines love to cause us pain in that gtk_paint_focus is a
   1.962 +       no-op on buttons and button-like widgets. They only listen to this flag. */
   1.963 +    if (state->focused && !state->disabled)
   1.964 +        GTK_WIDGET_SET_FLAGS(widget, GTK_HAS_FOCUS);
   1.965 +
   1.966 +    if (!interior_focus && state->focused) {
   1.967 +        x += focus_width + focus_pad;
   1.968 +        y += focus_width + focus_pad;
   1.969 +        width -= 2 * (focus_width + focus_pad);
   1.970 +        height -= 2 * (focus_width + focus_pad);
   1.971 +    }
   1.972 +
   1.973 +    shadow_type = button_state == GTK_STATE_ACTIVE ||
   1.974 +                      state->depressed ? GTK_SHADOW_IN : GTK_SHADOW_OUT;
   1.975 + 
   1.976 +    if (state->isDefault && relief == GTK_RELIEF_NORMAL) {
   1.977 +        /* handle default borders both outside and inside the button */
   1.978 +        gint default_top, default_left, default_bottom, default_right;
   1.979 +        moz_gtk_button_get_default_overflow(&default_top, &default_left,
   1.980 +                                            &default_bottom, &default_right);
   1.981 +        x -= default_left;
   1.982 +        y -= default_top;
   1.983 +        width += default_left + default_right;
   1.984 +        height += default_top + default_bottom;
   1.985 +        gtk_paint_box(style, drawable, GTK_STATE_NORMAL, GTK_SHADOW_IN, cliprect,
   1.986 +                      widget, "buttondefault", x, y, width, height);
   1.987 +
   1.988 +        moz_gtk_button_get_default_border(&default_top, &default_left,
   1.989 +                                          &default_bottom, &default_right);
   1.990 +        x += default_left;
   1.991 +        y += default_top;
   1.992 +        width -= (default_left + default_right);
   1.993 +        height -= (default_top + default_bottom);
   1.994 +    }
   1.995 + 
   1.996 +    if (relief != GTK_RELIEF_NONE || state->depressed ||
   1.997 +        (button_state != GTK_STATE_NORMAL &&
   1.998 +         button_state != GTK_STATE_INSENSITIVE)) {
   1.999 +        TSOffsetStyleGCs(style, x, y);
  1.1000 +        /* the following line can trigger an assertion (Crux theme)
  1.1001 +           file ../../gdk/gdkwindow.c: line 1846 (gdk_window_clear_area):
  1.1002 +           assertion `GDK_IS_WINDOW (window)' failed */
  1.1003 +        gtk_paint_box(style, drawable, button_state, shadow_type, cliprect,
  1.1004 +                      widget, "button", x, y, width, height);
  1.1005 +    }
  1.1006 +
  1.1007 +    if (state->focused) {
  1.1008 +        if (interior_focus) {
  1.1009 +            x += widget->style->xthickness + focus_pad;
  1.1010 +            y += widget->style->ythickness + focus_pad;
  1.1011 +            width -= 2 * (widget->style->xthickness + focus_pad);
  1.1012 +            height -= 2 * (widget->style->ythickness + focus_pad);
  1.1013 +        } else {
  1.1014 +            x -= focus_width + focus_pad;
  1.1015 +            y -= focus_width + focus_pad;
  1.1016 +            width += 2 * (focus_width + focus_pad);
  1.1017 +            height += 2 * (focus_width + focus_pad);
  1.1018 +        }
  1.1019 +
  1.1020 +        TSOffsetStyleGCs(style, x, y);
  1.1021 +        gtk_paint_focus(style, drawable, button_state, cliprect,
  1.1022 +                        widget, "button", x, y, width, height);
  1.1023 +    }
  1.1024 +
  1.1025 +    GTK_WIDGET_UNSET_FLAGS(widget, GTK_HAS_DEFAULT);
  1.1026 +    GTK_WIDGET_UNSET_FLAGS(widget, GTK_HAS_FOCUS);
  1.1027 +    return MOZ_GTK_SUCCESS;
  1.1028 +}
  1.1029 +
  1.1030 +static gint
  1.1031 +moz_gtk_toggle_paint(GdkDrawable* drawable, GdkRectangle* rect,
  1.1032 +                     GdkRectangle* cliprect, GtkWidgetState* state,
  1.1033 +                     gboolean selected, gboolean inconsistent,
  1.1034 +                     gboolean isradio, GtkTextDirection direction)
  1.1035 +{
  1.1036 +    GtkStateType state_type = ConvertGtkState(state);
  1.1037 +    GtkShadowType shadow_type = (selected)?GTK_SHADOW_IN:GTK_SHADOW_OUT;
  1.1038 +    gint indicator_size, indicator_spacing;
  1.1039 +    gint x, y, width, height;
  1.1040 +    gint focus_x, focus_y, focus_width, focus_height;
  1.1041 +    GtkWidget *w;
  1.1042 +    GtkStyle *style;
  1.1043 +
  1.1044 +    if (isradio) {
  1.1045 +        moz_gtk_radio_get_metrics(&indicator_size, &indicator_spacing);
  1.1046 +        w = gRadiobuttonWidget;
  1.1047 +    } else {
  1.1048 +        moz_gtk_checkbox_get_metrics(&indicator_size, &indicator_spacing);
  1.1049 +        w = gCheckboxWidget;
  1.1050 +    }
  1.1051 +
  1.1052 +    // XXX we should assert rect->height >= indicator_size too
  1.1053 +    // after bug 369581 is fixed.
  1.1054 +    NS_ASSERTION(rect->width >= indicator_size,
  1.1055 +                 "GetMinimumWidgetSize was ignored");
  1.1056 +
  1.1057 +    // Paint it center aligned in the rect.
  1.1058 +    x = rect->x + (rect->width - indicator_size) / 2;
  1.1059 +    y = rect->y + (rect->height - indicator_size) / 2;
  1.1060 +    width = indicator_size;
  1.1061 +    height = indicator_size;
  1.1062 +
  1.1063 +    focus_x = x - indicator_spacing;
  1.1064 +    focus_y = y - indicator_spacing;
  1.1065 +    focus_width = width + 2 * indicator_spacing;
  1.1066 +    focus_height = height + 2 * indicator_spacing;
  1.1067 +  
  1.1068 +    style = w->style;
  1.1069 +    TSOffsetStyleGCs(style, x, y);
  1.1070 +
  1.1071 +    gtk_widget_set_sensitive(w, !state->disabled);
  1.1072 +    gtk_widget_set_direction(w, direction);
  1.1073 +    GTK_TOGGLE_BUTTON(w)->active = selected;
  1.1074 +      
  1.1075 +    if (isradio) {
  1.1076 +        gtk_paint_option(style, drawable, state_type, shadow_type, cliprect,
  1.1077 +                         gRadiobuttonWidget, "radiobutton", x, y,
  1.1078 +                         width, height);
  1.1079 +        if (state->focused) {
  1.1080 +            gtk_paint_focus(style, drawable, GTK_STATE_ACTIVE, cliprect,
  1.1081 +                            gRadiobuttonWidget, "radiobutton", focus_x, focus_y,
  1.1082 +                            focus_width, focus_height);
  1.1083 +        }
  1.1084 +    }
  1.1085 +    else {
  1.1086 +       /*
  1.1087 +        * 'indeterminate' type on checkboxes. In GTK, the shadow type
  1.1088 +        * must also be changed for the state to be drawn.
  1.1089 +        */
  1.1090 +        if (inconsistent) {
  1.1091 +            gtk_toggle_button_set_inconsistent(GTK_TOGGLE_BUTTON(gCheckboxWidget), TRUE);
  1.1092 +            shadow_type = GTK_SHADOW_ETCHED_IN;
  1.1093 +        } else {
  1.1094 +            gtk_toggle_button_set_inconsistent(GTK_TOGGLE_BUTTON(gCheckboxWidget), FALSE);
  1.1095 +        }
  1.1096 +
  1.1097 +        gtk_paint_check(style, drawable, state_type, shadow_type, cliprect, 
  1.1098 +                        gCheckboxWidget, "checkbutton", x, y, width, height);
  1.1099 +        if (state->focused) {
  1.1100 +            gtk_paint_focus(style, drawable, GTK_STATE_ACTIVE, cliprect,
  1.1101 +                            gCheckboxWidget, "checkbutton", focus_x, focus_y,
  1.1102 +                            focus_width, focus_height);
  1.1103 +        }
  1.1104 +    }
  1.1105 +
  1.1106 +    return MOZ_GTK_SUCCESS;
  1.1107 +}
  1.1108 +
  1.1109 +static gint
  1.1110 +calculate_button_inner_rect(GtkWidget* button, GdkRectangle* rect,
  1.1111 +                            GdkRectangle* inner_rect,
  1.1112 +                            GtkTextDirection direction,
  1.1113 +                            gboolean ignore_focus)
  1.1114 +{
  1.1115 +    GtkBorder inner_border;
  1.1116 +    gboolean interior_focus;
  1.1117 +    gint focus_width, focus_pad;
  1.1118 +    GtkStyle* style;
  1.1119 +
  1.1120 +    style = button->style;
  1.1121 +
  1.1122 +    /* This mirrors gtkbutton's child positioning */
  1.1123 +    moz_gtk_button_get_inner_border(button, &inner_border);
  1.1124 +    moz_gtk_widget_get_focus(button, &interior_focus,
  1.1125 +                             &focus_width, &focus_pad);
  1.1126 +
  1.1127 +    if (ignore_focus)
  1.1128 +        focus_width = focus_pad = 0;
  1.1129 +
  1.1130 +    inner_rect->x = rect->x + XTHICKNESS(style) + focus_width + focus_pad;
  1.1131 +    inner_rect->x += direction == GTK_TEXT_DIR_LTR ?
  1.1132 +                        inner_border.left : inner_border.right;
  1.1133 +    inner_rect->y = rect->y + inner_border.top + YTHICKNESS(style) +
  1.1134 +                    focus_width + focus_pad;
  1.1135 +    inner_rect->width = MAX(1, rect->width - inner_border.left -
  1.1136 +       inner_border.right - (XTHICKNESS(style) + focus_pad + focus_width) * 2);
  1.1137 +    inner_rect->height = MAX(1, rect->height - inner_border.top -
  1.1138 +       inner_border.bottom - (YTHICKNESS(style) + focus_pad + focus_width) * 2);
  1.1139 +
  1.1140 +    return MOZ_GTK_SUCCESS;
  1.1141 +}
  1.1142 +
  1.1143 +
  1.1144 +static gint
  1.1145 +calculate_arrow_rect(GtkWidget* arrow, GdkRectangle* rect,
  1.1146 +                     GdkRectangle* arrow_rect, GtkTextDirection direction)
  1.1147 +{
  1.1148 +    /* defined in gtkarrow.c */
  1.1149 +    gfloat arrow_scaling = 0.7;
  1.1150 +    gfloat xalign, xpad;
  1.1151 +    gint extent;
  1.1152 +    GtkMisc* misc = GTK_MISC(arrow);
  1.1153 +
  1.1154 +    if (have_arrow_scaling)
  1.1155 +        gtk_widget_style_get(arrow, "arrow_scaling", &arrow_scaling, NULL);
  1.1156 +
  1.1157 +    extent = MIN((rect->width - misc->xpad * 2),
  1.1158 +                 (rect->height - misc->ypad * 2)) * arrow_scaling;
  1.1159 +
  1.1160 +    xalign = direction == GTK_TEXT_DIR_LTR ? misc->xalign : 1.0 - misc->xalign;
  1.1161 +    xpad = misc->xpad + (rect->width - extent) * xalign;
  1.1162 +
  1.1163 +    arrow_rect->x = direction == GTK_TEXT_DIR_LTR ?
  1.1164 +                        floor(rect->x + xpad) : ceil(rect->x + xpad);
  1.1165 +    arrow_rect->y = floor(rect->y + misc->ypad +
  1.1166 +                          ((rect->height - extent) * misc->yalign));
  1.1167 +
  1.1168 +    arrow_rect->width = arrow_rect->height = extent;
  1.1169 +
  1.1170 +    return MOZ_GTK_SUCCESS;
  1.1171 +}
  1.1172 +
  1.1173 +static gint
  1.1174 +moz_gtk_scrollbar_button_paint(GdkDrawable* drawable, GdkRectangle* rect,
  1.1175 +                               GdkRectangle* cliprect, GtkWidgetState* state,
  1.1176 +                               GtkScrollbarButtonFlags flags,
  1.1177 +                               GtkTextDirection direction)
  1.1178 +{
  1.1179 +    GtkStateType state_type = ConvertGtkState(state);
  1.1180 +    GtkShadowType shadow_type = (state->active) ?
  1.1181 +        GTK_SHADOW_IN : GTK_SHADOW_OUT;
  1.1182 +    GdkRectangle arrow_rect;
  1.1183 +    GtkStyle* style;
  1.1184 +    GtkWidget *scrollbar;
  1.1185 +    GtkArrowType arrow_type;
  1.1186 +    gint arrow_displacement_x, arrow_displacement_y;
  1.1187 +    const char* detail = (flags & MOZ_GTK_STEPPER_VERTICAL) ?
  1.1188 +                           "vscrollbar" : "hscrollbar";
  1.1189 +
  1.1190 +    ensure_scrollbar_widget();
  1.1191 +
  1.1192 +    if (flags & MOZ_GTK_STEPPER_VERTICAL)
  1.1193 +        scrollbar = gVertScrollbarWidget;
  1.1194 +    else
  1.1195 +        scrollbar = gHorizScrollbarWidget;
  1.1196 +
  1.1197 +    gtk_widget_set_direction(scrollbar, direction);
  1.1198 +
  1.1199 +    /* Some theme engines (i.e., ClearLooks) check the scrollbar's allocation
  1.1200 +       to determine where it should paint rounded corners on the buttons.
  1.1201 +       We need to trick them into drawing the buttons the way we want them. */
  1.1202 +
  1.1203 +    scrollbar->allocation.x = rect->x;
  1.1204 +    scrollbar->allocation.y = rect->y;
  1.1205 +    scrollbar->allocation.width = rect->width;
  1.1206 +    scrollbar->allocation.height = rect->height;
  1.1207 +
  1.1208 +    if (flags & MOZ_GTK_STEPPER_VERTICAL) {
  1.1209 +        scrollbar->allocation.height *= 5;
  1.1210 +        if (flags & MOZ_GTK_STEPPER_DOWN) {
  1.1211 +            arrow_type = GTK_ARROW_DOWN;
  1.1212 +            if (flags & MOZ_GTK_STEPPER_BOTTOM)
  1.1213 +                scrollbar->allocation.y -= 4 * rect->height;
  1.1214 +            else
  1.1215 +                scrollbar->allocation.y -= rect->height;
  1.1216 +
  1.1217 +        } else {
  1.1218 +            arrow_type = GTK_ARROW_UP;
  1.1219 +            if (flags & MOZ_GTK_STEPPER_BOTTOM)
  1.1220 +                scrollbar->allocation.y -= 3 * rect->height;
  1.1221 +        }
  1.1222 +    } else {
  1.1223 +        scrollbar->allocation.width *= 5;
  1.1224 +        if (flags & MOZ_GTK_STEPPER_DOWN) {
  1.1225 +            arrow_type = GTK_ARROW_RIGHT;
  1.1226 +            if (flags & MOZ_GTK_STEPPER_BOTTOM)
  1.1227 +                scrollbar->allocation.x -= 4 * rect->width;
  1.1228 +            else
  1.1229 +                scrollbar->allocation.x -= rect->width;
  1.1230 +        } else {
  1.1231 +            arrow_type = GTK_ARROW_LEFT;
  1.1232 +            if (flags & MOZ_GTK_STEPPER_BOTTOM)
  1.1233 +                scrollbar->allocation.x -= 3 * rect->width;
  1.1234 +        }
  1.1235 +    }
  1.1236 +
  1.1237 +    style = scrollbar->style;
  1.1238 +
  1.1239 +    TSOffsetStyleGCs(style, rect->x, rect->y);
  1.1240 +
  1.1241 +    gtk_paint_box(style, drawable, state_type, shadow_type, cliprect,
  1.1242 +                  scrollbar, detail, rect->x, rect->y,
  1.1243 +                  rect->width, rect->height);
  1.1244 +
  1.1245 +    arrow_rect.width = rect->width / 2;
  1.1246 +    arrow_rect.height = rect->height / 2;
  1.1247 +    arrow_rect.x = rect->x + (rect->width - arrow_rect.width) / 2;
  1.1248 +    arrow_rect.y = rect->y + (rect->height - arrow_rect.height) / 2;
  1.1249 +
  1.1250 +    if (state_type == GTK_STATE_ACTIVE) {
  1.1251 +        gtk_widget_style_get(scrollbar,
  1.1252 +                             "arrow-displacement-x", &arrow_displacement_x,
  1.1253 +                             "arrow-displacement-y", &arrow_displacement_y,
  1.1254 +                             NULL);
  1.1255 +
  1.1256 +        arrow_rect.x += arrow_displacement_x;
  1.1257 +        arrow_rect.y += arrow_displacement_y;
  1.1258 +    }
  1.1259 +
  1.1260 +    gtk_paint_arrow(style, drawable, state_type, shadow_type, cliprect,
  1.1261 +                    scrollbar, detail, arrow_type, TRUE, arrow_rect.x,
  1.1262 +                    arrow_rect.y, arrow_rect.width, arrow_rect.height);
  1.1263 +
  1.1264 +    return MOZ_GTK_SUCCESS;
  1.1265 +}
  1.1266 +
  1.1267 +static gint
  1.1268 +moz_gtk_scrollbar_trough_paint(GtkThemeWidgetType widget,
  1.1269 +                               GdkDrawable* drawable, GdkRectangle* rect,
  1.1270 +                               GdkRectangle* cliprect, GtkWidgetState* state,
  1.1271 +                               GtkTextDirection direction)
  1.1272 +{
  1.1273 +    GtkStyle* style;
  1.1274 +    GtkScrollbar *scrollbar;
  1.1275 +
  1.1276 +    ensure_scrollbar_widget();
  1.1277 +
  1.1278 +    if (widget ==  MOZ_GTK_SCROLLBAR_TRACK_HORIZONTAL)
  1.1279 +        scrollbar = GTK_SCROLLBAR(gHorizScrollbarWidget);
  1.1280 +    else
  1.1281 +        scrollbar = GTK_SCROLLBAR(gVertScrollbarWidget);
  1.1282 +
  1.1283 +    gtk_widget_set_direction(GTK_WIDGET(scrollbar), direction);
  1.1284 +
  1.1285 +    style = GTK_WIDGET(scrollbar)->style;
  1.1286 +
  1.1287 +    TSOffsetStyleGCs(style, rect->x, rect->y);
  1.1288 +    gtk_style_apply_default_background(style, drawable, TRUE, GTK_STATE_ACTIVE,
  1.1289 +                                       cliprect, rect->x, rect->y,
  1.1290 +                                       rect->width, rect->height);
  1.1291 +
  1.1292 +    gtk_paint_box(style, drawable, GTK_STATE_ACTIVE, GTK_SHADOW_IN, cliprect,
  1.1293 +                  GTK_WIDGET(scrollbar), "trough", rect->x, rect->y,
  1.1294 +                  rect->width, rect->height);
  1.1295 +
  1.1296 +    if (state->focused) {
  1.1297 +        gtk_paint_focus(style, drawable, GTK_STATE_ACTIVE, cliprect,
  1.1298 +                        GTK_WIDGET(scrollbar), "trough",
  1.1299 +                        rect->x, rect->y, rect->width, rect->height);
  1.1300 +    }
  1.1301 +
  1.1302 +    return MOZ_GTK_SUCCESS;
  1.1303 +}
  1.1304 +
  1.1305 +static gint
  1.1306 +moz_gtk_scrollbar_thumb_paint(GtkThemeWidgetType widget,
  1.1307 +                              GdkDrawable* drawable, GdkRectangle* rect,
  1.1308 +                              GdkRectangle* cliprect, GtkWidgetState* state,
  1.1309 +                              GtkTextDirection direction)
  1.1310 +{
  1.1311 +    GtkStateType state_type = (state->inHover || state->active) ?
  1.1312 +        GTK_STATE_PRELIGHT : GTK_STATE_NORMAL;
  1.1313 +    GtkShadowType shadow_type = GTK_SHADOW_OUT;
  1.1314 +    GtkStyle* style;
  1.1315 +    GtkScrollbar *scrollbar;
  1.1316 +    GtkAdjustment *adj;
  1.1317 +    gboolean activate_slider;
  1.1318 +
  1.1319 +    ensure_scrollbar_widget();
  1.1320 +
  1.1321 +    if (widget == MOZ_GTK_SCROLLBAR_THUMB_HORIZONTAL)
  1.1322 +        scrollbar = GTK_SCROLLBAR(gHorizScrollbarWidget);
  1.1323 +    else
  1.1324 +        scrollbar = GTK_SCROLLBAR(gVertScrollbarWidget);
  1.1325 +
  1.1326 +    gtk_widget_set_direction(GTK_WIDGET(scrollbar), direction);
  1.1327 +
  1.1328 +    /* Make sure to set the scrollbar range before painting so that
  1.1329 +       everything is drawn properly.  At least the bluecurve (and
  1.1330 +       maybe other) themes don't draw the top or bottom black line
  1.1331 +       surrounding the scrollbar if the theme thinks that it's butted
  1.1332 +       up against the scrollbar arrows.  Note the increases of the
  1.1333 +       clip rect below. */
  1.1334 +    adj = gtk_range_get_adjustment(GTK_RANGE(scrollbar));
  1.1335 +
  1.1336 +    if (widget == MOZ_GTK_SCROLLBAR_THUMB_HORIZONTAL) {
  1.1337 +        adj->page_size = rect->width;
  1.1338 +    }
  1.1339 +    else {
  1.1340 +        adj->page_size = rect->height;
  1.1341 +    }
  1.1342 +
  1.1343 +    adj->lower = 0;
  1.1344 +    adj->value = state->curpos;
  1.1345 +    adj->upper = state->maxpos;
  1.1346 +    gtk_adjustment_changed(adj);
  1.1347 +
  1.1348 +    style = GTK_WIDGET(scrollbar)->style;
  1.1349 +    
  1.1350 +    gtk_widget_style_get(GTK_WIDGET(scrollbar), "activate-slider",
  1.1351 +                         &activate_slider, NULL);
  1.1352 +    
  1.1353 +    if (activate_slider && state->active) {
  1.1354 +        shadow_type = GTK_SHADOW_IN;
  1.1355 +        state_type = GTK_STATE_ACTIVE;
  1.1356 +    }
  1.1357 +
  1.1358 +    TSOffsetStyleGCs(style, rect->x, rect->y);
  1.1359 +
  1.1360 +    gtk_paint_slider(style, drawable, state_type, shadow_type, cliprect,
  1.1361 +                     GTK_WIDGET(scrollbar), "slider", rect->x, rect->y,
  1.1362 +                     rect->width,  rect->height,
  1.1363 +                     (widget == MOZ_GTK_SCROLLBAR_THUMB_HORIZONTAL) ?
  1.1364 +                     GTK_ORIENTATION_HORIZONTAL : GTK_ORIENTATION_VERTICAL);
  1.1365 +
  1.1366 +    return MOZ_GTK_SUCCESS;
  1.1367 +}
  1.1368 +
  1.1369 +static gint
  1.1370 +moz_gtk_spin_paint(GdkDrawable* drawable, GdkRectangle* rect,
  1.1371 +                   GtkTextDirection direction)
  1.1372 +{
  1.1373 +    GtkStyle* style;
  1.1374 +
  1.1375 +    ensure_spin_widget();
  1.1376 +    gtk_widget_set_direction(gSpinWidget, direction);
  1.1377 +    style = gSpinWidget->style;
  1.1378 +
  1.1379 +    TSOffsetStyleGCs(style, rect->x, rect->y);
  1.1380 +    gtk_paint_box(style, drawable, GTK_STATE_NORMAL, GTK_SHADOW_IN, NULL,
  1.1381 +                  gSpinWidget, "spinbutton",
  1.1382 +                  rect->x, rect->y, rect->width, rect->height);
  1.1383 +    return MOZ_GTK_SUCCESS;
  1.1384 +}
  1.1385 +
  1.1386 +static gint
  1.1387 +moz_gtk_spin_updown_paint(GdkDrawable* drawable, GdkRectangle* rect,
  1.1388 +                          gboolean isDown, GtkWidgetState* state,
  1.1389 +                          GtkTextDirection direction)
  1.1390 +{
  1.1391 +    GdkRectangle arrow_rect;
  1.1392 +    GtkStateType state_type = ConvertGtkState(state);
  1.1393 +    GtkShadowType shadow_type = state_type == GTK_STATE_ACTIVE ?
  1.1394 +                                  GTK_SHADOW_IN : GTK_SHADOW_OUT;
  1.1395 +    GtkStyle* style;
  1.1396 +
  1.1397 +    ensure_spin_widget();
  1.1398 +    style = gSpinWidget->style;
  1.1399 +    gtk_widget_set_direction(gSpinWidget, direction);
  1.1400 +
  1.1401 +    TSOffsetStyleGCs(style, rect->x, rect->y);
  1.1402 +    gtk_paint_box(style, drawable, state_type, shadow_type, NULL, gSpinWidget,
  1.1403 +                  isDown ? "spinbutton_down" : "spinbutton_up",
  1.1404 +                  rect->x, rect->y, rect->width, rect->height);
  1.1405 +
  1.1406 +    /* hard code these values */
  1.1407 +    arrow_rect.width = 6;
  1.1408 +    arrow_rect.height = 6;
  1.1409 +    arrow_rect.x = rect->x + (rect->width - arrow_rect.width) / 2;
  1.1410 +    arrow_rect.y = rect->y + (rect->height - arrow_rect.height) / 2;
  1.1411 +    arrow_rect.y += isDown ? -1 : 1;
  1.1412 +
  1.1413 +    gtk_paint_arrow(style, drawable, state_type, shadow_type, NULL,
  1.1414 +                    gSpinWidget, "spinbutton",
  1.1415 +                    isDown ? GTK_ARROW_DOWN : GTK_ARROW_UP, TRUE,
  1.1416 +                    arrow_rect.x, arrow_rect.y,
  1.1417 +                    arrow_rect.width, arrow_rect.height);
  1.1418 +
  1.1419 +    return MOZ_GTK_SUCCESS;
  1.1420 +}
  1.1421 +
  1.1422 +static gint
  1.1423 +moz_gtk_scale_paint(GdkDrawable* drawable, GdkRectangle* rect,
  1.1424 +                    GdkRectangle* cliprect, GtkWidgetState* state,
  1.1425 +                    GtkOrientation flags, GtkTextDirection direction)
  1.1426 +{
  1.1427 +  gint x = 0, y = 0;
  1.1428 +  GtkStateType state_type = ConvertGtkState(state);
  1.1429 +  GtkStyle* style;
  1.1430 +  GtkWidget* widget;
  1.1431 +
  1.1432 +  ensure_scale_widget();
  1.1433 +  widget = ((flags == GTK_ORIENTATION_HORIZONTAL) ? gHScaleWidget : gVScaleWidget);
  1.1434 +  gtk_widget_set_direction(widget, direction);
  1.1435 +
  1.1436 +  style = widget->style;
  1.1437 +
  1.1438 +  if (flags == GTK_ORIENTATION_HORIZONTAL) {
  1.1439 +    x = XTHICKNESS(style);
  1.1440 +    y++;
  1.1441 +  }
  1.1442 +  else {
  1.1443 +    x++;
  1.1444 +    y = YTHICKNESS(style);
  1.1445 +  }
  1.1446 +
  1.1447 +  TSOffsetStyleGCs(style, rect->x, rect->y);
  1.1448 +
  1.1449 +  gtk_paint_box(style, drawable, GTK_STATE_ACTIVE, GTK_SHADOW_IN, cliprect,
  1.1450 +                widget, "trough", rect->x + x, rect->y + y,
  1.1451 +                rect->width - 2*x, rect->height - 2*y);
  1.1452 +
  1.1453 +  if (state->focused)
  1.1454 +    gtk_paint_focus(style, drawable, state_type, cliprect, widget, "trough",
  1.1455 +                    rect->x, rect->y, rect->width, rect->height);
  1.1456 +
  1.1457 +  return MOZ_GTK_SUCCESS;
  1.1458 +}
  1.1459 +
  1.1460 +static gint
  1.1461 +moz_gtk_scale_thumb_paint(GdkDrawable* drawable, GdkRectangle* rect,
  1.1462 +                          GdkRectangle* cliprect, GtkWidgetState* state,
  1.1463 +                          GtkOrientation flags, GtkTextDirection direction)
  1.1464 +{
  1.1465 +  GtkStateType state_type = ConvertGtkState(state);
  1.1466 +  GtkStyle* style;
  1.1467 +  GtkWidget* widget;
  1.1468 +  gint thumb_width, thumb_height, x, y;
  1.1469 +
  1.1470 +  ensure_scale_widget();
  1.1471 +  widget = ((flags == GTK_ORIENTATION_HORIZONTAL) ? gHScaleWidget : gVScaleWidget);
  1.1472 +  gtk_widget_set_direction(widget, direction);
  1.1473 +
  1.1474 +  style = widget->style;
  1.1475 +
  1.1476 +  /* determine the thumb size, and position the thumb in the center in the opposite axis */
  1.1477 +  if (flags == GTK_ORIENTATION_HORIZONTAL) {
  1.1478 +    moz_gtk_get_scalethumb_metrics(GTK_ORIENTATION_HORIZONTAL, &thumb_width, &thumb_height);
  1.1479 +    x = rect->x;
  1.1480 +    y = rect->y + (rect->height - thumb_height) / 2;
  1.1481 +  }
  1.1482 +  else {
  1.1483 +    moz_gtk_get_scalethumb_metrics(GTK_ORIENTATION_VERTICAL, &thumb_height, &thumb_width);
  1.1484 +    x = rect->x + (rect->width - thumb_width) / 2;
  1.1485 +    y = rect->y;
  1.1486 +  }
  1.1487 +
  1.1488 +  TSOffsetStyleGCs(style, rect->x, rect->y);
  1.1489 +  gtk_paint_slider(style, drawable, state_type, GTK_SHADOW_OUT, cliprect,
  1.1490 +                   widget, (flags == GTK_ORIENTATION_HORIZONTAL) ? "hscale" : "vscale",
  1.1491 +                   x, y, thumb_width, thumb_height, flags);
  1.1492 +
  1.1493 +  return MOZ_GTK_SUCCESS;
  1.1494 +}
  1.1495 +
  1.1496 +static gint
  1.1497 +moz_gtk_gripper_paint(GdkDrawable* drawable, GdkRectangle* rect,
  1.1498 +                      GdkRectangle* cliprect, GtkWidgetState* state,
  1.1499 +                      GtkTextDirection direction)
  1.1500 +{
  1.1501 +    GtkStateType state_type = ConvertGtkState(state);
  1.1502 +    GtkShadowType shadow_type;
  1.1503 +    GtkStyle* style;
  1.1504 +
  1.1505 +    ensure_handlebox_widget();
  1.1506 +    gtk_widget_set_direction(gHandleBoxWidget, direction);
  1.1507 +
  1.1508 +    style = gHandleBoxWidget->style;
  1.1509 +    shadow_type = GTK_HANDLE_BOX(gHandleBoxWidget)->shadow_type;
  1.1510 +
  1.1511 +    TSOffsetStyleGCs(style, rect->x, rect->y);
  1.1512 +    gtk_paint_box(style, drawable, state_type, shadow_type, cliprect,
  1.1513 +                  gHandleBoxWidget, "handlebox_bin", rect->x, rect->y,
  1.1514 +                  rect->width, rect->height);
  1.1515 +
  1.1516 +    return MOZ_GTK_SUCCESS;
  1.1517 +}
  1.1518 +
  1.1519 +static gint
  1.1520 +moz_gtk_hpaned_paint(GdkDrawable* drawable, GdkRectangle* rect,
  1.1521 +                     GdkRectangle* cliprect, GtkWidgetState* state)
  1.1522 +{
  1.1523 +    GtkStateType hpaned_state = ConvertGtkState(state);
  1.1524 +
  1.1525 +    ensure_hpaned_widget();
  1.1526 +    gtk_paint_handle(gHPanedWidget->style, drawable, hpaned_state,
  1.1527 +                     GTK_SHADOW_NONE, cliprect, gHPanedWidget, "paned",
  1.1528 +                     rect->x, rect->y, rect->width, rect->height,
  1.1529 +                     GTK_ORIENTATION_VERTICAL);
  1.1530 +
  1.1531 +    return MOZ_GTK_SUCCESS;
  1.1532 +}
  1.1533 +
  1.1534 +static gint
  1.1535 +moz_gtk_vpaned_paint(GdkDrawable* drawable, GdkRectangle* rect,
  1.1536 +                     GdkRectangle* cliprect, GtkWidgetState* state)
  1.1537 +{
  1.1538 +    GtkStateType vpaned_state = ConvertGtkState(state);
  1.1539 +
  1.1540 +    ensure_vpaned_widget();
  1.1541 +    gtk_paint_handle(gVPanedWidget->style, drawable, vpaned_state,
  1.1542 +                     GTK_SHADOW_NONE, cliprect, gVPanedWidget, "paned",
  1.1543 +                     rect->x, rect->y, rect->width, rect->height,
  1.1544 +                     GTK_ORIENTATION_HORIZONTAL);
  1.1545 +
  1.1546 +    return MOZ_GTK_SUCCESS;
  1.1547 +}
  1.1548 +
  1.1549 +static gint
  1.1550 +moz_gtk_entry_paint(GdkDrawable* drawable, GdkRectangle* rect,
  1.1551 +                    GdkRectangle* cliprect, GtkWidgetState* state,
  1.1552 +                    GtkWidget* widget, GtkTextDirection direction)
  1.1553 +{
  1.1554 +    GtkStateType bg_state = state->disabled ?
  1.1555 +                                GTK_STATE_INSENSITIVE : GTK_STATE_NORMAL;
  1.1556 +    gint x, y, width = rect->width, height = rect->height;
  1.1557 +    GtkStyle* style;
  1.1558 +    gboolean interior_focus;
  1.1559 +    gboolean theme_honors_transparency = FALSE;
  1.1560 +    gint focus_width;
  1.1561 +
  1.1562 +    gtk_widget_set_direction(widget, direction);
  1.1563 +
  1.1564 +    style = widget->style;
  1.1565 +
  1.1566 +    gtk_widget_style_get(widget,
  1.1567 +                         "interior-focus", &interior_focus,
  1.1568 +                         "focus-line-width", &focus_width,
  1.1569 +                         "honors-transparent-bg-hint", &theme_honors_transparency,
  1.1570 +                         NULL);
  1.1571 +
  1.1572 +    /* gtkentry.c uses two windows, one for the entire widget and one for the
  1.1573 +     * text area inside it. The background of both windows is set to the "base"
  1.1574 +     * color of the new state in gtk_entry_state_changed, but only the inner
  1.1575 +     * textarea window uses gtk_paint_flat_box when exposed */
  1.1576 +
  1.1577 +    TSOffsetStyleGCs(style, rect->x, rect->y);
  1.1578 +
  1.1579 +    /* This gets us a lovely greyish disabledish look */
  1.1580 +    gtk_widget_set_sensitive(widget, !state->disabled);
  1.1581 +
  1.1582 +    /* GTK fills the outer widget window with the base color before drawing the widget.
  1.1583 +     * Some older themes rely on this behavior, but many themes nowadays use rounded
  1.1584 +     * corners on their widgets. While most GTK apps are blissfully unaware of this
  1.1585 +     * problem due to their use of the default window background, we render widgets on
  1.1586 +     * many kinds of backgrounds on the web.
  1.1587 +     * If the theme is able to cope with transparency, then we can skip pre-filling
  1.1588 +     * and notify the theme it will paint directly on the canvas. */
  1.1589 +    if (theme_honors_transparency) {
  1.1590 +        g_object_set_data(G_OBJECT(widget), "transparent-bg-hint", GINT_TO_POINTER(TRUE));
  1.1591 +    } else {
  1.1592 +        GdkRectangle clipped_rect;
  1.1593 +        gdk_rectangle_intersect(rect, cliprect, &clipped_rect);
  1.1594 +        if (clipped_rect.width != 0) {
  1.1595 +            gdk_draw_rectangle(drawable, style->base_gc[bg_state], TRUE,
  1.1596 +                               clipped_rect.x, clipped_rect.y,
  1.1597 +                               clipped_rect.width, clipped_rect.height);
  1.1598 +        }
  1.1599 +        g_object_set_data(G_OBJECT(widget), "transparent-bg-hint", GINT_TO_POINTER(FALSE));
  1.1600 +    }
  1.1601 +
  1.1602 +    /* Get the position of the inner window, see _gtk_entry_get_borders */
  1.1603 +    x = XTHICKNESS(style);
  1.1604 +    y = YTHICKNESS(style);
  1.1605 +
  1.1606 +    if (!interior_focus) {
  1.1607 +        x += focus_width;
  1.1608 +        y += focus_width;
  1.1609 +    }
  1.1610 +
  1.1611 +    /* Simulate an expose of the inner window */
  1.1612 +    gtk_paint_flat_box(style, drawable, bg_state, GTK_SHADOW_NONE,
  1.1613 +                       cliprect, widget, "entry_bg",  rect->x + x,
  1.1614 +                       rect->y + y, rect->width - 2*x, rect->height - 2*y);
  1.1615 +
  1.1616 +    /* Now paint the shadow and focus border.
  1.1617 +     * We do like in gtk_entry_draw_frame, we first draw the shadow, a tad
  1.1618 +     * smaller when focused if the focus is not interior, then the focus. */
  1.1619 +    x = rect->x;
  1.1620 +    y = rect->y;
  1.1621 +
  1.1622 +    if (state->focused && !state->disabled) {
  1.1623 +        /* This will get us the lit borders that focused textboxes enjoy on
  1.1624 +         * some themes. */
  1.1625 +        GTK_WIDGET_SET_FLAGS(widget, GTK_HAS_FOCUS);
  1.1626 +
  1.1627 +        if (!interior_focus) {
  1.1628 +            /* Indent the border a little bit if we have exterior focus 
  1.1629 +               (this is what GTK does to draw native entries) */
  1.1630 +            x += focus_width;
  1.1631 +            y += focus_width;
  1.1632 +            width -= 2 * focus_width;
  1.1633 +            height -= 2 * focus_width;
  1.1634 +        }
  1.1635 +    }
  1.1636 +
  1.1637 +    gtk_paint_shadow(style, drawable, GTK_STATE_NORMAL, GTK_SHADOW_IN,
  1.1638 +                     cliprect, widget, "entry", x, y, width, height);
  1.1639 +
  1.1640 +    if (state->focused && !state->disabled) {
  1.1641 +        if (!interior_focus) {
  1.1642 +            gtk_paint_focus(style, drawable,  GTK_STATE_NORMAL, cliprect,
  1.1643 +                            widget, "entry",
  1.1644 +                            rect->x, rect->y, rect->width, rect->height);
  1.1645 +        }
  1.1646 +
  1.1647 +        /* Now unset the focus flag. We don't want other entries to look
  1.1648 +         * like they're focused too! */
  1.1649 +        GTK_WIDGET_UNSET_FLAGS(widget, GTK_HAS_FOCUS);
  1.1650 +    }
  1.1651 +
  1.1652 +    return MOZ_GTK_SUCCESS;
  1.1653 +}
  1.1654 +
  1.1655 +static gint 
  1.1656 +moz_gtk_treeview_paint(GdkDrawable* drawable, GdkRectangle* rect,
  1.1657 +                       GdkRectangle* cliprect, GtkWidgetState* state,
  1.1658 +                       GtkTextDirection direction)
  1.1659 +{
  1.1660 +    gint xthickness, ythickness;
  1.1661 +
  1.1662 +    GtkStyle *style;
  1.1663 +    GtkStateType state_type;
  1.1664 +
  1.1665 +    ensure_tree_view_widget();
  1.1666 +    ensure_scrolled_window_widget();
  1.1667 +
  1.1668 +    gtk_widget_set_direction(gTreeViewWidget, direction);
  1.1669 +    gtk_widget_set_direction(gScrolledWindowWidget, direction);
  1.1670 +
  1.1671 +    /* only handle disabled and normal states, otherwise the whole background
  1.1672 +     * area will be painted differently with other states */
  1.1673 +    state_type = state->disabled ? GTK_STATE_INSENSITIVE : GTK_STATE_NORMAL;
  1.1674 +
  1.1675 +    /* In GTK the treeview sets the background of the window
  1.1676 +     * which contains the cells to the treeview base color.
  1.1677 +     * If we don't set it here the background color will not be correct.*/
  1.1678 +    gtk_widget_modify_bg(gTreeViewWidget, state_type,
  1.1679 +                         &gTreeViewWidget->style->base[state_type]);
  1.1680 +
  1.1681 +    style = gScrolledWindowWidget->style;
  1.1682 +    xthickness = XTHICKNESS(style);
  1.1683 +    ythickness = YTHICKNESS(style);
  1.1684 +
  1.1685 +    TSOffsetStyleGCs(gTreeViewWidget->style, rect->x, rect->y);
  1.1686 +    TSOffsetStyleGCs(style, rect->x, rect->y);
  1.1687 +
  1.1688 +    gtk_paint_flat_box(gTreeViewWidget->style, drawable, state_type,
  1.1689 +                       GTK_SHADOW_NONE, cliprect, gTreeViewWidget, "treeview",
  1.1690 +                       rect->x + xthickness, rect->y + ythickness,
  1.1691 +                       rect->width - 2 * xthickness,
  1.1692 +                       rect->height - 2 * ythickness);
  1.1693 +
  1.1694 +    gtk_paint_shadow(style, drawable, GTK_STATE_NORMAL, GTK_SHADOW_IN,
  1.1695 +                     cliprect, gScrolledWindowWidget, "scrolled_window",
  1.1696 +                     rect->x, rect->y, rect->width, rect->height); 
  1.1697 +
  1.1698 +    return MOZ_GTK_SUCCESS;
  1.1699 +}
  1.1700 +
  1.1701 +static gint
  1.1702 +moz_gtk_tree_header_cell_paint(GdkDrawable* drawable, GdkRectangle* rect,
  1.1703 +                               GdkRectangle* cliprect, GtkWidgetState* state,
  1.1704 +                               gboolean isSorted, GtkTextDirection direction)
  1.1705 +{
  1.1706 +    gtk_tree_view_column_set_sort_indicator(gMiddleTreeViewColumn,
  1.1707 +                                            isSorted);
  1.1708 +
  1.1709 +    moz_gtk_button_paint(drawable, rect, cliprect, state, GTK_RELIEF_NORMAL,
  1.1710 +                         gTreeHeaderCellWidget, direction);
  1.1711 +    return MOZ_GTK_SUCCESS;
  1.1712 +}
  1.1713 +
  1.1714 +static gint
  1.1715 +moz_gtk_tree_header_sort_arrow_paint(GdkDrawable* drawable, GdkRectangle* rect,
  1.1716 +                                     GdkRectangle* cliprect,
  1.1717 +                                     GtkWidgetState* state, GtkArrowType flags,
  1.1718 +                                     GtkTextDirection direction)
  1.1719 +{
  1.1720 +    GdkRectangle arrow_rect;
  1.1721 +    GtkStateType state_type = ConvertGtkState(state);
  1.1722 +    GtkShadowType shadow_type = GTK_SHADOW_IN;
  1.1723 +    GtkArrowType arrow_type = flags;
  1.1724 +    GtkStyle* style;
  1.1725 +
  1.1726 +    ensure_tree_header_cell_widget();
  1.1727 +    gtk_widget_set_direction(gTreeHeaderSortArrowWidget, direction);
  1.1728 +
  1.1729 +    /* hard code these values */
  1.1730 +    arrow_rect.width = 11;
  1.1731 +    arrow_rect.height = 11;
  1.1732 +    arrow_rect.x = rect->x + (rect->width - arrow_rect.width) / 2;
  1.1733 +    arrow_rect.y = rect->y + (rect->height - arrow_rect.height) / 2;
  1.1734 +
  1.1735 +    style = gTreeHeaderSortArrowWidget->style;
  1.1736 +    TSOffsetStyleGCs(style, arrow_rect.x, arrow_rect.y);
  1.1737 +
  1.1738 +    gtk_paint_arrow(style, drawable, state_type, shadow_type, cliprect,
  1.1739 +                    gTreeHeaderSortArrowWidget, "arrow",  arrow_type, TRUE,
  1.1740 +                    arrow_rect.x, arrow_rect.y,
  1.1741 +                    arrow_rect.width, arrow_rect.height);
  1.1742 +
  1.1743 +    return MOZ_GTK_SUCCESS;
  1.1744 +}
  1.1745 +
  1.1746 +static gint
  1.1747 +moz_gtk_treeview_expander_paint(GdkDrawable* drawable, GdkRectangle* rect,
  1.1748 +                                GdkRectangle* cliprect, GtkWidgetState* state,
  1.1749 +                                GtkExpanderStyle expander_state,
  1.1750 +                                GtkTextDirection direction)
  1.1751 +{
  1.1752 +    GtkStyle *style;
  1.1753 +    GtkStateType state_type;
  1.1754 +
  1.1755 +    ensure_tree_view_widget();
  1.1756 +    gtk_widget_set_direction(gTreeViewWidget, direction);
  1.1757 +
  1.1758 +    style = gTreeViewWidget->style;
  1.1759 +
  1.1760 +    /* Because the frame we get is of the entire treeview, we can't get the precise
  1.1761 +     * event state of one expander, thus rendering hover and active feedback useless. */
  1.1762 +    state_type = state->disabled ? GTK_STATE_INSENSITIVE : GTK_STATE_NORMAL;
  1.1763 +
  1.1764 +    TSOffsetStyleGCs(style, rect->x, rect->y);
  1.1765 +    gtk_paint_expander(style, drawable, state_type, cliprect, gTreeViewWidget, "treeview",
  1.1766 +                       rect->x + rect->width / 2, rect->y + rect->height / 2, expander_state);
  1.1767 +
  1.1768 +    return MOZ_GTK_SUCCESS;
  1.1769 +}
  1.1770 +
  1.1771 +static gint
  1.1772 +moz_gtk_combo_box_paint(GdkDrawable* drawable, GdkRectangle* rect,
  1.1773 +                        GdkRectangle* cliprect, GtkWidgetState* state,
  1.1774 +                        gboolean ishtml, GtkTextDirection direction)
  1.1775 +{
  1.1776 +    GdkRectangle arrow_rect, real_arrow_rect;
  1.1777 +    gint arrow_size, separator_width;
  1.1778 +    gboolean wide_separators;
  1.1779 +    GtkStateType state_type = ConvertGtkState(state);
  1.1780 +    GtkShadowType shadow_type = state->active ? GTK_SHADOW_IN : GTK_SHADOW_OUT;
  1.1781 +    GtkStyle* style;
  1.1782 +    GtkRequisition arrow_req;
  1.1783 +
  1.1784 +    ensure_combo_box_widgets();
  1.1785 +
  1.1786 +    /* Also sets the direction on gComboBoxButtonWidget, which is then
  1.1787 +     * inherited by the separator and arrow */
  1.1788 +    moz_gtk_button_paint(drawable, rect, cliprect, state, GTK_RELIEF_NORMAL,
  1.1789 +                         gComboBoxButtonWidget, direction);
  1.1790 +
  1.1791 +    calculate_button_inner_rect(gComboBoxButtonWidget,
  1.1792 +                                rect, &arrow_rect, direction, ishtml);
  1.1793 +    /* Now arrow_rect contains the inner rect ; we want to correct the width
  1.1794 +     * to what the arrow needs (see gtk_combo_box_size_allocate) */
  1.1795 +    gtk_widget_size_request(gComboBoxArrowWidget, &arrow_req);
  1.1796 +    if (direction == GTK_TEXT_DIR_LTR)
  1.1797 +        arrow_rect.x += arrow_rect.width - arrow_req.width;
  1.1798 +    arrow_rect.width = arrow_req.width;
  1.1799 +
  1.1800 +    calculate_arrow_rect(gComboBoxArrowWidget,
  1.1801 +                         &arrow_rect, &real_arrow_rect, direction);
  1.1802 +
  1.1803 +    style = gComboBoxArrowWidget->style;
  1.1804 +    TSOffsetStyleGCs(style, rect->x, rect->y);
  1.1805 +
  1.1806 +    gtk_widget_size_allocate(gComboBoxWidget, rect);
  1.1807 +
  1.1808 +    gtk_paint_arrow(style, drawable, state_type, shadow_type, cliprect,
  1.1809 +                    gComboBoxArrowWidget, "arrow",  GTK_ARROW_DOWN, TRUE,
  1.1810 +                    real_arrow_rect.x, real_arrow_rect.y,
  1.1811 +                    real_arrow_rect.width, real_arrow_rect.height);
  1.1812 +
  1.1813 +
  1.1814 +    /* If there is no separator in the theme, there's nothing left to do. */
  1.1815 +    if (!gComboBoxSeparatorWidget)
  1.1816 +        return MOZ_GTK_SUCCESS;
  1.1817 +
  1.1818 +    style = gComboBoxSeparatorWidget->style;
  1.1819 +    TSOffsetStyleGCs(style, rect->x, rect->y);
  1.1820 +
  1.1821 +    gtk_widget_style_get(gComboBoxSeparatorWidget,
  1.1822 +                         "wide-separators", &wide_separators,
  1.1823 +                         "separator-width", &separator_width,
  1.1824 +                         NULL);
  1.1825 +
  1.1826 +    if (wide_separators) {
  1.1827 +        if (direction == GTK_TEXT_DIR_LTR)
  1.1828 +            arrow_rect.x -= separator_width;
  1.1829 +        else
  1.1830 +            arrow_rect.x += arrow_rect.width;
  1.1831 +
  1.1832 +        gtk_paint_box(style, drawable,
  1.1833 +                      GTK_STATE_NORMAL, GTK_SHADOW_ETCHED_OUT,
  1.1834 +                      cliprect, gComboBoxSeparatorWidget, "vseparator",
  1.1835 +                      arrow_rect.x, arrow_rect.y,
  1.1836 +                      separator_width, arrow_rect.height);
  1.1837 +    } else {
  1.1838 +        if (direction == GTK_TEXT_DIR_LTR)
  1.1839 +            arrow_rect.x -= XTHICKNESS(style);
  1.1840 +        else
  1.1841 +            arrow_rect.x += arrow_rect.width;
  1.1842 +
  1.1843 +        gtk_paint_vline(style, drawable, GTK_STATE_NORMAL, cliprect,
  1.1844 +                        gComboBoxSeparatorWidget, "vseparator",
  1.1845 +                        arrow_rect.y, arrow_rect.y + arrow_rect.height,
  1.1846 +                        arrow_rect.x);
  1.1847 +    }
  1.1848 +
  1.1849 +    return MOZ_GTK_SUCCESS;
  1.1850 +}
  1.1851 +
  1.1852 +static gint
  1.1853 +moz_gtk_arrow_paint(GdkDrawable* drawable, GdkRectangle* rect,
  1.1854 +                    GdkRectangle* cliprect, GtkWidgetState* state,
  1.1855 +                    GtkArrowType arrow_type, GtkTextDirection direction)
  1.1856 +{
  1.1857 +    GtkStyle* style;
  1.1858 +    GtkStateType state_type = ConvertGtkState(state);
  1.1859 +    GtkShadowType shadow_type = state->active ? GTK_SHADOW_IN : GTK_SHADOW_OUT;
  1.1860 +    GdkRectangle arrow_rect;
  1.1861 +
  1.1862 +    ensure_button_arrow_widget();
  1.1863 +    style = gButtonArrowWidget->style;
  1.1864 +    gtk_widget_set_direction(gButtonArrowWidget, direction);
  1.1865 +
  1.1866 +    calculate_arrow_rect(gButtonArrowWidget, rect, &arrow_rect,
  1.1867 +                         direction);
  1.1868 +
  1.1869 +    if (direction == GTK_TEXT_DIR_RTL) {
  1.1870 +        if (arrow_type == GTK_ARROW_LEFT)
  1.1871 +            arrow_type = GTK_ARROW_RIGHT;
  1.1872 +        else if (arrow_type == GTK_ARROW_RIGHT)
  1.1873 +            arrow_type = GTK_ARROW_LEFT;
  1.1874 +    }
  1.1875 +
  1.1876 +    TSOffsetStyleGCs(style, arrow_rect.x, arrow_rect.y);
  1.1877 +    gtk_paint_arrow(style, drawable, state_type, shadow_type, cliprect,
  1.1878 +                    gButtonArrowWidget, "arrow",  arrow_type, TRUE,
  1.1879 +                    arrow_rect.x, arrow_rect.y, arrow_rect.width, arrow_rect.height);
  1.1880 +
  1.1881 +    return MOZ_GTK_SUCCESS;
  1.1882 +}
  1.1883 +
  1.1884 +static gint
  1.1885 +moz_gtk_combo_box_entry_button_paint(GdkDrawable* drawable, GdkRectangle* rect,
  1.1886 +                                     GdkRectangle* cliprect,
  1.1887 +                                     GtkWidgetState* state,
  1.1888 +                                     gboolean input_focus,
  1.1889 +                                     GtkTextDirection direction)
  1.1890 +{
  1.1891 +    gint x_displacement, y_displacement;
  1.1892 +    GdkRectangle arrow_rect, real_arrow_rect;
  1.1893 +    GtkStateType state_type = ConvertGtkState(state);
  1.1894 +    GtkShadowType shadow_type = state->active ? GTK_SHADOW_IN : GTK_SHADOW_OUT;
  1.1895 +    GtkStyle* style;
  1.1896 +
  1.1897 +    ensure_combo_box_entry_widgets();
  1.1898 +
  1.1899 +    if (input_focus) {
  1.1900 +        /* Some themes draw a complementary focus ring for the dropdown button
  1.1901 +         * when the dropdown entry has focus */
  1.1902 +        GTK_WIDGET_SET_FLAGS(gComboBoxEntryTextareaWidget, GTK_HAS_FOCUS);
  1.1903 +    }
  1.1904 +
  1.1905 +    moz_gtk_button_paint(drawable, rect, cliprect, state, GTK_RELIEF_NORMAL,
  1.1906 +                         gComboBoxEntryButtonWidget, direction);
  1.1907 +
  1.1908 +    if (input_focus)
  1.1909 +        GTK_WIDGET_UNSET_FLAGS(gComboBoxEntryTextareaWidget, GTK_HAS_FOCUS);
  1.1910 +
  1.1911 +    calculate_button_inner_rect(gComboBoxEntryButtonWidget,
  1.1912 +                                rect, &arrow_rect, direction, FALSE);
  1.1913 +    if (state_type == GTK_STATE_ACTIVE) {
  1.1914 +        gtk_widget_style_get(gComboBoxEntryButtonWidget,
  1.1915 +                             "child-displacement-x", &x_displacement,
  1.1916 +                             "child-displacement-y", &y_displacement,
  1.1917 +                             NULL);
  1.1918 +        arrow_rect.x += x_displacement;
  1.1919 +        arrow_rect.y += y_displacement;
  1.1920 +    }
  1.1921 +
  1.1922 +    calculate_arrow_rect(gComboBoxEntryArrowWidget,
  1.1923 +                         &arrow_rect, &real_arrow_rect, direction);
  1.1924 +
  1.1925 +    style = gComboBoxEntryArrowWidget->style;
  1.1926 +    TSOffsetStyleGCs(style, real_arrow_rect.x, real_arrow_rect.y);
  1.1927 +
  1.1928 +    gtk_paint_arrow(style, drawable, state_type, shadow_type, cliprect,
  1.1929 +                    gComboBoxEntryArrowWidget, "arrow",  GTK_ARROW_DOWN, TRUE,
  1.1930 +                    real_arrow_rect.x, real_arrow_rect.y,
  1.1931 +                    real_arrow_rect.width, real_arrow_rect.height);
  1.1932 +
  1.1933 +    return MOZ_GTK_SUCCESS;
  1.1934 +}
  1.1935 +
  1.1936 +static gint
  1.1937 +moz_gtk_container_paint(GdkDrawable* drawable, GdkRectangle* rect,
  1.1938 +                        GdkRectangle* cliprect, GtkWidgetState* state, 
  1.1939 +                        gboolean isradio, GtkTextDirection direction)
  1.1940 +{
  1.1941 +    GtkStateType state_type = ConvertGtkState(state);
  1.1942 +    GtkStyle* style;
  1.1943 +    GtkWidget *widget;
  1.1944 +    gboolean interior_focus;
  1.1945 +    gint focus_width, focus_pad;
  1.1946 +
  1.1947 +    if (isradio) {
  1.1948 +        ensure_radiobutton_widget();
  1.1949 +        widget = gRadiobuttonWidget;
  1.1950 +    } else {
  1.1951 +        ensure_checkbox_widget();
  1.1952 +        widget = gCheckboxWidget;
  1.1953 +    }
  1.1954 +    gtk_widget_set_direction(widget, direction);
  1.1955 +
  1.1956 +    style = widget->style;
  1.1957 +    moz_gtk_widget_get_focus(widget, &interior_focus, &focus_width,
  1.1958 +                             &focus_pad);
  1.1959 +
  1.1960 +    TSOffsetStyleGCs(style, rect->x, rect->y);
  1.1961 +
  1.1962 +    /* The detail argument for the gtk_paint_* calls below are "checkbutton"
  1.1963 +       even for radio buttons, to match what gtk does. */
  1.1964 +
  1.1965 +    /* this is for drawing a prelight box */
  1.1966 +    if (state_type == GTK_STATE_PRELIGHT || state_type == GTK_STATE_ACTIVE) {
  1.1967 +        gtk_paint_flat_box(style, drawable, GTK_STATE_PRELIGHT,
  1.1968 +                           GTK_SHADOW_ETCHED_OUT, cliprect, widget,
  1.1969 +                           "checkbutton",
  1.1970 +                           rect->x, rect->y, rect->width, rect->height);
  1.1971 +    }
  1.1972 +
  1.1973 +    if (state_type != GTK_STATE_NORMAL && state_type != GTK_STATE_PRELIGHT)
  1.1974 +        state_type = GTK_STATE_NORMAL;
  1.1975 +
  1.1976 +    if (state->focused && !interior_focus) {
  1.1977 +        gtk_paint_focus(style, drawable, state_type, cliprect, widget,
  1.1978 +                        "checkbutton",
  1.1979 +                        rect->x, rect->y, rect->width, rect->height);
  1.1980 +    }
  1.1981 +
  1.1982 +    return MOZ_GTK_SUCCESS;
  1.1983 +}
  1.1984 +
  1.1985 +static gint
  1.1986 +moz_gtk_toggle_label_paint(GdkDrawable* drawable, GdkRectangle* rect,
  1.1987 +                           GdkRectangle* cliprect, GtkWidgetState* state, 
  1.1988 +                           gboolean isradio, GtkTextDirection direction)
  1.1989 +{
  1.1990 +    GtkStateType state_type;
  1.1991 +    GtkStyle *style;
  1.1992 +    GtkWidget *widget;
  1.1993 +    gboolean interior_focus;
  1.1994 +
  1.1995 +    if (!state->focused)
  1.1996 +        return MOZ_GTK_SUCCESS;
  1.1997 +
  1.1998 +    if (isradio) {
  1.1999 +        ensure_radiobutton_widget();
  1.2000 +        widget = gRadiobuttonWidget;
  1.2001 +    } else {
  1.2002 +        ensure_checkbox_widget();
  1.2003 +        widget = gCheckboxWidget;
  1.2004 +    }
  1.2005 +    gtk_widget_set_direction(widget, direction);
  1.2006 +
  1.2007 +    gtk_widget_style_get(widget, "interior-focus", &interior_focus, NULL);
  1.2008 +    if (!interior_focus)
  1.2009 +        return MOZ_GTK_SUCCESS;
  1.2010 +
  1.2011 +    state_type = ConvertGtkState(state);
  1.2012 +
  1.2013 +    style = widget->style;
  1.2014 +    TSOffsetStyleGCs(style, rect->x, rect->y);
  1.2015 +
  1.2016 +    /* Always "checkbutton" to match gtkcheckbutton.c */
  1.2017 +    gtk_paint_focus(style, drawable, state_type, cliprect, widget,
  1.2018 +                    "checkbutton",
  1.2019 +                    rect->x, rect->y, rect->width, rect->height);
  1.2020 +
  1.2021 +    return MOZ_GTK_SUCCESS;
  1.2022 +}
  1.2023 +
  1.2024 +static gint
  1.2025 +moz_gtk_toolbar_paint(GdkDrawable* drawable, GdkRectangle* rect,
  1.2026 +                      GdkRectangle* cliprect, GtkTextDirection direction)
  1.2027 +{
  1.2028 +    GtkStyle* style;
  1.2029 +    GtkShadowType shadow_type;
  1.2030 +
  1.2031 +    ensure_toolbar_widget();
  1.2032 +    gtk_widget_set_direction(gToolbarWidget, direction);
  1.2033 +
  1.2034 +    style = gToolbarWidget->style;
  1.2035 +
  1.2036 +    TSOffsetStyleGCs(style, rect->x, rect->y);
  1.2037 +
  1.2038 +    gtk_style_apply_default_background(style, drawable, TRUE,
  1.2039 +                                       GTK_STATE_NORMAL,
  1.2040 +                                       cliprect, rect->x, rect->y,
  1.2041 +                                       rect->width, rect->height);
  1.2042 +
  1.2043 +    gtk_widget_style_get(gToolbarWidget, "shadow-type", &shadow_type, NULL);
  1.2044 +
  1.2045 +    gtk_paint_box (style, drawable, GTK_STATE_NORMAL, shadow_type,
  1.2046 +                   cliprect, gToolbarWidget, "toolbar",
  1.2047 +                   rect->x, rect->y, rect->width, rect->height);
  1.2048 +
  1.2049 +    return MOZ_GTK_SUCCESS;
  1.2050 +}
  1.2051 +
  1.2052 +static gint
  1.2053 +moz_gtk_toolbar_separator_paint(GdkDrawable* drawable, GdkRectangle* rect,
  1.2054 +                                GdkRectangle* cliprect,
  1.2055 +                                GtkTextDirection direction)
  1.2056 +{
  1.2057 +    GtkStyle* style;
  1.2058 +    gint     separator_width;
  1.2059 +    gint     paint_width;
  1.2060 +    gboolean wide_separators;
  1.2061 +    
  1.2062 +    /* Defined as constants in GTK+ 2.10.14 */
  1.2063 +    const double start_fraction = 0.2;
  1.2064 +    const double end_fraction = 0.8;
  1.2065 +
  1.2066 +    ensure_toolbar_separator_widget();
  1.2067 +    gtk_widget_set_direction(gToolbarSeparatorWidget, direction);
  1.2068 +
  1.2069 +    style = gToolbarSeparatorWidget->style;
  1.2070 +
  1.2071 +    gtk_widget_style_get(gToolbarWidget,
  1.2072 +                         "wide-separators", &wide_separators,
  1.2073 +                         "separator-width", &separator_width,
  1.2074 +                         NULL);
  1.2075 +
  1.2076 +    TSOffsetStyleGCs(style, rect->x, rect->y);
  1.2077 +
  1.2078 +    if (wide_separators) {
  1.2079 +        if (separator_width > rect->width)
  1.2080 +            separator_width = rect->width;
  1.2081 +
  1.2082 +        gtk_paint_box(style, drawable,
  1.2083 +                      GTK_STATE_NORMAL, GTK_SHADOW_ETCHED_OUT,
  1.2084 +                      cliprect, gToolbarWidget, "vseparator",
  1.2085 +                      rect->x + (rect->width - separator_width) / 2,
  1.2086 +                      rect->y + rect->height * start_fraction,
  1.2087 +                      separator_width,
  1.2088 +                      rect->height * (end_fraction - start_fraction));
  1.2089 +                       
  1.2090 +    } else {
  1.2091 +        paint_width = style->xthickness;
  1.2092 +        
  1.2093 +        if (paint_width > rect->width)
  1.2094 +            paint_width = rect->width;
  1.2095 +    
  1.2096 +        gtk_paint_vline(style, drawable,
  1.2097 +                        GTK_STATE_NORMAL, cliprect, gToolbarSeparatorWidget,
  1.2098 +                        "toolbar",
  1.2099 +                        rect->y + rect->height * start_fraction,
  1.2100 +                        rect->y + rect->height * end_fraction,
  1.2101 +                        rect->x + (rect->width - paint_width) / 2);
  1.2102 +    }
  1.2103 +    
  1.2104 +    return MOZ_GTK_SUCCESS;
  1.2105 +}
  1.2106 +
  1.2107 +static gint
  1.2108 +moz_gtk_tooltip_paint(GdkDrawable* drawable, GdkRectangle* rect,
  1.2109 +                      GdkRectangle* cliprect, GtkTextDirection direction)
  1.2110 +{
  1.2111 +    GtkStyle* style;
  1.2112 +
  1.2113 +    ensure_tooltip_widget();
  1.2114 +    gtk_widget_set_direction(gTooltipWidget, direction);
  1.2115 +
  1.2116 +    style = gtk_rc_get_style_by_paths(gtk_settings_get_default(),
  1.2117 +                                      "gtk-tooltips", "GtkWindow",
  1.2118 +                                      GTK_TYPE_WINDOW);
  1.2119 +
  1.2120 +    style = gtk_style_attach(style, gTooltipWidget->window);
  1.2121 +    TSOffsetStyleGCs(style, rect->x, rect->y);
  1.2122 +    gtk_paint_flat_box(style, drawable, GTK_STATE_NORMAL, GTK_SHADOW_OUT,
  1.2123 +                       cliprect, gTooltipWidget, "tooltip",
  1.2124 +                       rect->x, rect->y, rect->width, rect->height);
  1.2125 +
  1.2126 +    return MOZ_GTK_SUCCESS;
  1.2127 +}
  1.2128 +
  1.2129 +static gint
  1.2130 +moz_gtk_resizer_paint(GdkDrawable* drawable, GdkRectangle* rect,
  1.2131 +                      GdkRectangle* cliprect, GtkWidgetState* state,
  1.2132 +                      GtkTextDirection direction)
  1.2133 +{
  1.2134 +    GtkStyle* style;
  1.2135 +    GtkStateType state_type = ConvertGtkState(state);
  1.2136 +
  1.2137 +    ensure_frame_widget();
  1.2138 +    gtk_widget_set_direction(gStatusbarWidget, direction);
  1.2139 +
  1.2140 +    style = gStatusbarWidget->style;
  1.2141 +
  1.2142 +    TSOffsetStyleGCs(style, rect->x, rect->y);
  1.2143 +
  1.2144 +    gtk_paint_resize_grip(style, drawable, state_type, cliprect, gStatusbarWidget,
  1.2145 +                          "statusbar", (direction == GTK_TEXT_DIR_LTR) ?
  1.2146 +                          GDK_WINDOW_EDGE_SOUTH_EAST :
  1.2147 +                          GDK_WINDOW_EDGE_SOUTH_WEST,
  1.2148 +                          rect->x, rect->y, rect->width, rect->height);
  1.2149 +    return MOZ_GTK_SUCCESS;
  1.2150 +}
  1.2151 +
  1.2152 +static gint
  1.2153 +moz_gtk_frame_paint(GdkDrawable* drawable, GdkRectangle* rect,
  1.2154 +                    GdkRectangle* cliprect, GtkTextDirection direction)
  1.2155 +{
  1.2156 +    GtkStyle* style;
  1.2157 +    GtkShadowType shadow_type;
  1.2158 +
  1.2159 +    ensure_frame_widget();
  1.2160 +    gtk_widget_set_direction(gFrameWidget, direction);
  1.2161 +
  1.2162 +    style = gFrameWidget->style;
  1.2163 +
  1.2164 +    gtk_widget_style_get(gStatusbarWidget, "shadow-type", &shadow_type, NULL);
  1.2165 +
  1.2166 +    TSOffsetStyleGCs(style, rect->x, rect->y);
  1.2167 +    gtk_paint_shadow(style, drawable, GTK_STATE_NORMAL, shadow_type,
  1.2168 +                     cliprect, gFrameWidget, "frame", rect->x, rect->y,
  1.2169 +                     rect->width, rect->height);
  1.2170 +
  1.2171 +    return MOZ_GTK_SUCCESS;
  1.2172 +}
  1.2173 +
  1.2174 +static gint
  1.2175 +moz_gtk_progressbar_paint(GdkDrawable* drawable, GdkRectangle* rect,
  1.2176 +                          GdkRectangle* cliprect, GtkTextDirection direction)
  1.2177 +{
  1.2178 +    GtkStyle* style;
  1.2179 +
  1.2180 +    ensure_progress_widget();
  1.2181 +    gtk_widget_set_direction(gProgressWidget, direction);
  1.2182 +
  1.2183 +    style = gProgressWidget->style;
  1.2184 +
  1.2185 +    TSOffsetStyleGCs(style, rect->x, rect->y);
  1.2186 +    gtk_paint_box(style, drawable, GTK_STATE_NORMAL, GTK_SHADOW_IN,
  1.2187 +                  cliprect, gProgressWidget, "trough", rect->x, rect->y,
  1.2188 +                  rect->width, rect->height);
  1.2189 +
  1.2190 +    return MOZ_GTK_SUCCESS;
  1.2191 +}
  1.2192 +
  1.2193 +static gint
  1.2194 +moz_gtk_progress_chunk_paint(GdkDrawable* drawable, GdkRectangle* rect,
  1.2195 +                             GdkRectangle* cliprect, GtkTextDirection direction,
  1.2196 +                             GtkThemeWidgetType widget)
  1.2197 +{
  1.2198 +    GtkStyle* style;
  1.2199 +
  1.2200 +    ensure_progress_widget();
  1.2201 +    gtk_widget_set_direction(gProgressWidget, direction);
  1.2202 +
  1.2203 +    style = gProgressWidget->style;
  1.2204 +
  1.2205 +    TSOffsetStyleGCs(style, rect->x, rect->y);
  1.2206 +
  1.2207 +    if (widget == MOZ_GTK_PROGRESS_CHUNK_INDETERMINATE ||
  1.2208 +        widget == MOZ_GTK_PROGRESS_CHUNK_VERTICAL_INDETERMINATE) {
  1.2209 +      /**
  1.2210 +       * The bar's size and the bar speed are set depending of the progress'
  1.2211 +       * size. These could also be constant for all progress bars easily.
  1.2212 +       */
  1.2213 +      gboolean vertical = (widget == MOZ_GTK_PROGRESS_CHUNK_VERTICAL_INDETERMINATE);
  1.2214 +
  1.2215 +      /* The size of the dimension we are going to use for the animation. */
  1.2216 +      const gint progressSize = vertical ? rect->height : rect->width;
  1.2217 +
  1.2218 +      /* The bar is using a fifth of the element size, based on GtkProgressBar
  1.2219 +       * activity-blocks property. */
  1.2220 +      const gint barSize = MAX(1, progressSize / 5);
  1.2221 +
  1.2222 +      /* Represents the travel that has to be done for a complete cycle. */
  1.2223 +      const gint travel = 2 * (progressSize - barSize);
  1.2224 +
  1.2225 +      /* period equals to travel / pixelsPerMillisecond
  1.2226 +       * where pixelsPerMillisecond equals progressSize / 1000.0.
  1.2227 +       * This is equivalent to 1600. */
  1.2228 +      static const guint period = 1600;
  1.2229 +      const gint t = PR_IntervalToMilliseconds(PR_IntervalNow()) % period;
  1.2230 +      const gint dx = travel * t / period;
  1.2231 +
  1.2232 +      if (vertical) {
  1.2233 +        rect->y += (dx < travel / 2) ? dx : travel - dx;
  1.2234 +        rect->height = barSize;
  1.2235 +      } else {
  1.2236 +        rect->x += (dx < travel / 2) ? dx : travel - dx;
  1.2237 +        rect->width = barSize;
  1.2238 +      }
  1.2239 +    }
  1.2240 +
  1.2241 +    gtk_paint_box(style, drawable, GTK_STATE_PRELIGHT, GTK_SHADOW_OUT,
  1.2242 +                  cliprect, gProgressWidget, "bar", rect->x, rect->y,
  1.2243 +                  rect->width, rect->height);
  1.2244 +
  1.2245 +    return MOZ_GTK_SUCCESS;
  1.2246 +}
  1.2247 +
  1.2248 +gint
  1.2249 +moz_gtk_get_tab_thickness(void)
  1.2250 +{
  1.2251 +    ensure_tab_widget();
  1.2252 +    if (YTHICKNESS(gTabWidget->style) < 2)
  1.2253 +        return 2; /* some themes don't set ythickness correctly */
  1.2254 +
  1.2255 +    return YTHICKNESS(gTabWidget->style);
  1.2256 +}
  1.2257 +
  1.2258 +static gint
  1.2259 +moz_gtk_tab_paint(GdkDrawable* drawable, GdkRectangle* rect,
  1.2260 +                  GdkRectangle* cliprect, GtkWidgetState* state,
  1.2261 +                  GtkTabFlags flags, GtkTextDirection direction)
  1.2262 +{
  1.2263 +    /* When the tab isn't selected, we just draw a notebook extension.
  1.2264 +     * When it is selected, we overwrite the adjacent border of the tabpanel
  1.2265 +     * touching the tab with a pierced border (called "the gap") to make the
  1.2266 +     * tab appear physically attached to the tabpanel; see details below. */
  1.2267 +
  1.2268 +    GtkStyle* style;
  1.2269 +    GdkRectangle focusRect;
  1.2270 +
  1.2271 +    ensure_tab_widget();
  1.2272 +    gtk_widget_set_direction(gTabWidget, direction);
  1.2273 +
  1.2274 +    style = gTabWidget->style;
  1.2275 +    focusRect = *rect;
  1.2276 +    TSOffsetStyleGCs(style, rect->x, rect->y);
  1.2277 +
  1.2278 +    if ((flags & MOZ_GTK_TAB_SELECTED) == 0) {
  1.2279 +        /* Only draw the tab */
  1.2280 +        gtk_paint_extension(style, drawable, GTK_STATE_ACTIVE, GTK_SHADOW_OUT,
  1.2281 +                            cliprect, gTabWidget, "tab",
  1.2282 +                            rect->x, rect->y, rect->width, rect->height,
  1.2283 +                            (flags & MOZ_GTK_TAB_BOTTOM) ?
  1.2284 +                                GTK_POS_TOP : GTK_POS_BOTTOM );
  1.2285 +    } else {
  1.2286 +        /* Draw the tab and the gap
  1.2287 +         * We want the gap to be positioned exactly on the tabpanel top
  1.2288 +         * border; since tabbox.css may set a negative margin so that the tab
  1.2289 +         * frame rect already overlaps the tabpanel frame rect, we need to take
  1.2290 +         * that into account when drawing. To that effect, nsNativeThemeGTK
  1.2291 +         * passes us this negative margin (bmargin in the graphic below) in the
  1.2292 +         * lowest bits of |flags|.  We use it to set gap_voffset, the distance
  1.2293 +         * between the top of the gap and the bottom of the tab (resp. the
  1.2294 +         * bottom of the gap and the top of the tab when we draw a bottom tab),
  1.2295 +         * while ensuring that the gap always touches the border of the tab,
  1.2296 +         * i.e. 0 <= gap_voffset <= gap_height, to avoid surprinsing results
  1.2297 +         * with big negative or positive margins.
  1.2298 +         * Here is a graphical explanation in the case of top tabs:
  1.2299 +         *             ___________________________
  1.2300 +         *            /                           \
  1.2301 +         *           |            T A B            |
  1.2302 +         * ----------|. . . . . . . . . . . . . . .|----- top of tabpanel
  1.2303 +         *           :    ^       bmargin          :  ^
  1.2304 +         *           :    | (-negative margin,     :  |
  1.2305 +         *  bottom   :    v  passed in flags)      :  |       gap_height
  1.2306 +         *    of  -> :.............................:  |    (the size of the
  1.2307 +         * the tab   .       part of the gap       .  |  tabpanel top border)
  1.2308 +         *           .      outside of the tab     .  v
  1.2309 +         * ----------------------------------------------
  1.2310 +         *
  1.2311 +         * To draw the gap, we use gtk_paint_box_gap(), see comment in
  1.2312 +         * moz_gtk_tabpanels_paint(). This box_gap is made 3 * gap_height tall,
  1.2313 +         * which should suffice to ensure that the only visible border is the
  1.2314 +         * pierced one.  If the tab is in the middle, we make the box_gap begin
  1.2315 +         * a bit to the left of the tab and end a bit to the right, adjusting
  1.2316 +         * the gap position so it still is under the tab, because we want the
  1.2317 +         * rendering of a gap in the middle of a tabpanel.  This is the role of
  1.2318 +         * the gints gap_{l,r}_offset. On the contrary, if the tab is the
  1.2319 +         * first, we align the start border of the box_gap with the start
  1.2320 +         * border of the tab (left if LTR, right if RTL), by setting the
  1.2321 +         * appropriate offset to 0.*/
  1.2322 +        gint gap_loffset, gap_roffset, gap_voffset, gap_height;
  1.2323 +
  1.2324 +        /* Get height needed by the gap */
  1.2325 +        gap_height = moz_gtk_get_tab_thickness();
  1.2326 +
  1.2327 +        /* Extract gap_voffset from the first bits of flags */
  1.2328 +        gap_voffset = flags & MOZ_GTK_TAB_MARGIN_MASK;
  1.2329 +        if (gap_voffset > gap_height)
  1.2330 +            gap_voffset = gap_height;
  1.2331 +
  1.2332 +        /* Set gap_{l,r}_offset to appropriate values */
  1.2333 +        gap_loffset = gap_roffset = 20; /* should be enough */
  1.2334 +        if (flags & MOZ_GTK_TAB_FIRST) {
  1.2335 +            if (direction == GTK_TEXT_DIR_RTL)
  1.2336 +                gap_roffset = 0;
  1.2337 +            else
  1.2338 +                gap_loffset = 0;
  1.2339 +        }
  1.2340 +
  1.2341 +        if (flags & MOZ_GTK_TAB_BOTTOM) {
  1.2342 +            /* Draw the tab */
  1.2343 +            focusRect.y += gap_voffset;
  1.2344 +            focusRect.height -= gap_voffset;
  1.2345 +            gtk_paint_extension(style, drawable, GTK_STATE_NORMAL,
  1.2346 +                                GTK_SHADOW_OUT, cliprect, gTabWidget, "tab",
  1.2347 +                                rect->x, rect->y + gap_voffset, rect->width,
  1.2348 +                                rect->height - gap_voffset, GTK_POS_TOP);
  1.2349 +
  1.2350 +            /* Draw the gap; erase with background color before painting in
  1.2351 +             * case theme does not */
  1.2352 +            gtk_style_apply_default_background(style, drawable, TRUE,
  1.2353 +                                               GTK_STATE_NORMAL, cliprect,
  1.2354 +                                               rect->x,
  1.2355 +                                               rect->y + gap_voffset
  1.2356 +                                                       - gap_height,
  1.2357 +                                               rect->width, gap_height);
  1.2358 +            gtk_paint_box_gap(style, drawable, GTK_STATE_NORMAL, GTK_SHADOW_OUT,
  1.2359 +                              cliprect, gTabWidget, "notebook",
  1.2360 +                              rect->x - gap_loffset,
  1.2361 +                              rect->y + gap_voffset - 3 * gap_height,
  1.2362 +                              rect->width + gap_loffset + gap_roffset,
  1.2363 +                              3 * gap_height, GTK_POS_BOTTOM,
  1.2364 +                              gap_loffset, rect->width);
  1.2365 +        } else {
  1.2366 +            /* Draw the tab */
  1.2367 +            focusRect.height -= gap_voffset;
  1.2368 +            gtk_paint_extension(style, drawable, GTK_STATE_NORMAL,
  1.2369 +                                GTK_SHADOW_OUT, cliprect, gTabWidget, "tab",
  1.2370 +                                rect->x, rect->y, rect->width,
  1.2371 +                                rect->height - gap_voffset, GTK_POS_BOTTOM);
  1.2372 +
  1.2373 +            /* Draw the gap; erase with background color before painting in
  1.2374 +             * case theme does not */
  1.2375 +            gtk_style_apply_default_background(style, drawable, TRUE,
  1.2376 +                                               GTK_STATE_NORMAL, cliprect,
  1.2377 +                                               rect->x,
  1.2378 +                                               rect->y + rect->height
  1.2379 +                                                       - gap_voffset,
  1.2380 +                                               rect->width, gap_height);
  1.2381 +            gtk_paint_box_gap(style, drawable, GTK_STATE_NORMAL, GTK_SHADOW_OUT,
  1.2382 +                              cliprect, gTabWidget, "notebook",
  1.2383 +                              rect->x - gap_loffset,
  1.2384 +                              rect->y + rect->height - gap_voffset,
  1.2385 +                              rect->width + gap_loffset + gap_roffset,
  1.2386 +                              3 * gap_height, GTK_POS_TOP,
  1.2387 +                              gap_loffset, rect->width);
  1.2388 +        }
  1.2389 +
  1.2390 +    }
  1.2391 +
  1.2392 +    if (state->focused) {
  1.2393 +      /* Paint the focus ring */
  1.2394 +      focusRect.x += XTHICKNESS(style);
  1.2395 +      focusRect.width -= XTHICKNESS(style) * 2;
  1.2396 +      focusRect.y += YTHICKNESS(style);
  1.2397 +      focusRect.height -= YTHICKNESS(style) * 2;
  1.2398 +
  1.2399 +      gtk_paint_focus(style, drawable,
  1.2400 +                      /* Believe it or not, NORMAL means a selected tab and
  1.2401 +                         ACTIVE means an unselected tab. */
  1.2402 +                      (flags & MOZ_GTK_TAB_SELECTED) ? GTK_STATE_NORMAL
  1.2403 +                                                     : GTK_STATE_ACTIVE,
  1.2404 +                      cliprect, gTabWidget, "tab",
  1.2405 +                      focusRect.x, focusRect.y, focusRect.width, focusRect.height);
  1.2406 +    }
  1.2407 +
  1.2408 +    return MOZ_GTK_SUCCESS;
  1.2409 +}
  1.2410 +
  1.2411 +static gint
  1.2412 +moz_gtk_tabpanels_paint(GdkDrawable* drawable, GdkRectangle* rect,
  1.2413 +                        GdkRectangle* cliprect, GtkTextDirection direction)
  1.2414 +{
  1.2415 +    /* We have three problems here:
  1.2416 +     * - Most engines draw gtk_paint_box differently to gtk_paint_box_gap, the
  1.2417 +     *   former implies there are no tabs, eg. Clearlooks.
  1.2418 +     * - Wanting a gap of width 0 doesn't actually guarantee a zero-width gap, eg.
  1.2419 +     *   Clearlooks.
  1.2420 +     * - Our old approach of a negative X position could cause rendering errors
  1.2421 +     *   on the box's corner, eg. themes using the Pixbuf engine.
  1.2422 +     */
  1.2423 +    GtkStyle* style;
  1.2424 +    GdkRectangle halfClipRect;
  1.2425 +
  1.2426 +    ensure_tab_widget();
  1.2427 +    gtk_widget_set_direction(gTabWidget, direction);
  1.2428 +
  1.2429 +    style = gTabWidget->style;
  1.2430 +    TSOffsetStyleGCs(style, rect->x, rect->y);
  1.2431 +
  1.2432 +    /* Our approach is as follows:
  1.2433 +     * - Draw the box in two passes. Pass in a clip rect to draw the left half of the
  1.2434 +     *   box, with the gap specified to the right outside the clip rect so that it is
  1.2435 +     *   not drawn.
  1.2436 +     * - The right half is drawn with the gap to the left outside the modified clip rect.
  1.2437 +     */
  1.2438 +    if (!gdk_rectangle_intersect(rect, cliprect, &halfClipRect))
  1.2439 +      return MOZ_GTK_SUCCESS;
  1.2440 +
  1.2441 +    halfClipRect.width = (halfClipRect.width / 2) + 1;
  1.2442 +    gtk_paint_box_gap(style, drawable, GTK_STATE_NORMAL, GTK_SHADOW_OUT,
  1.2443 +                      &halfClipRect, gTabWidget, "notebook", rect->x, rect->y,
  1.2444 +                      rect->width, rect->height,
  1.2445 +                      GTK_POS_TOP, halfClipRect.width + 1, 0);
  1.2446 +
  1.2447 +    halfClipRect.x += halfClipRect.width;
  1.2448 +    gtk_paint_box_gap(style, drawable, GTK_STATE_NORMAL, GTK_SHADOW_OUT,
  1.2449 +                      &halfClipRect, gTabWidget, "notebook", rect->x, rect->y,
  1.2450 +                      rect->width, rect->height,
  1.2451 +                      GTK_POS_TOP, -10, 0);
  1.2452 +
  1.2453 +    return MOZ_GTK_SUCCESS;
  1.2454 +}
  1.2455 +
  1.2456 +static gint
  1.2457 +moz_gtk_tab_scroll_arrow_paint(GdkDrawable* drawable, GdkRectangle* rect,
  1.2458 +                               GdkRectangle* cliprect, GtkWidgetState* state,
  1.2459 +                               GtkArrowType arrow_type,
  1.2460 +                               GtkTextDirection direction)
  1.2461 +{
  1.2462 +    GtkStateType state_type = ConvertGtkState(state);
  1.2463 +    GtkShadowType shadow_type = state->active ? GTK_SHADOW_IN : GTK_SHADOW_OUT;
  1.2464 +    GtkStyle* style;
  1.2465 +    gint arrow_size = MIN(rect->width, rect->height);
  1.2466 +    gint x = rect->x + (rect->width - arrow_size) / 2;
  1.2467 +    gint y = rect->y + (rect->height - arrow_size) / 2;
  1.2468 +
  1.2469 +    ensure_tab_widget();
  1.2470 +
  1.2471 +    style = gTabWidget->style;
  1.2472 +    TSOffsetStyleGCs(style, rect->x, rect->y);
  1.2473 +
  1.2474 +    if (direction == GTK_TEXT_DIR_RTL) {
  1.2475 +        arrow_type = (arrow_type == GTK_ARROW_LEFT) ?
  1.2476 +                         GTK_ARROW_RIGHT : GTK_ARROW_LEFT;
  1.2477 +    }
  1.2478 +
  1.2479 +    gtk_paint_arrow(style, drawable, state_type, shadow_type, NULL,
  1.2480 +                    gTabWidget, "notebook", arrow_type, TRUE,
  1.2481 +                    x, y, arrow_size, arrow_size);
  1.2482 +
  1.2483 +    return MOZ_GTK_SUCCESS;
  1.2484 +}
  1.2485 +
  1.2486 +static gint
  1.2487 +moz_gtk_menu_bar_paint(GdkDrawable* drawable, GdkRectangle* rect,
  1.2488 +                       GdkRectangle* cliprect, GtkTextDirection direction)
  1.2489 +{
  1.2490 +    GtkStyle* style;
  1.2491 +    GtkShadowType shadow_type;
  1.2492 +    ensure_menu_bar_widget();
  1.2493 +    gtk_widget_set_direction(gMenuBarWidget, direction);
  1.2494 +
  1.2495 +    gtk_widget_style_get(gMenuBarWidget, "shadow-type", &shadow_type, NULL);
  1.2496 +
  1.2497 +    style = gMenuBarWidget->style;
  1.2498 +
  1.2499 +    TSOffsetStyleGCs(style, rect->x, rect->y);
  1.2500 +    gtk_style_apply_default_background(style, drawable, TRUE, GTK_STATE_NORMAL,
  1.2501 +                                       cliprect, rect->x, rect->y,
  1.2502 +                                       rect->width, rect->height);
  1.2503 +
  1.2504 +    gtk_paint_box(style, drawable, GTK_STATE_NORMAL, shadow_type,
  1.2505 +                  cliprect, gMenuBarWidget, "menubar", rect->x, rect->y,
  1.2506 +                  rect->width, rect->height);
  1.2507 +    return MOZ_GTK_SUCCESS;
  1.2508 +}
  1.2509 +
  1.2510 +static gint
  1.2511 +moz_gtk_menu_popup_paint(GdkDrawable* drawable, GdkRectangle* rect,
  1.2512 +                         GdkRectangle* cliprect, GtkTextDirection direction)
  1.2513 +{
  1.2514 +    GtkStyle* style;
  1.2515 +    ensure_menu_popup_widget();
  1.2516 +    gtk_widget_set_direction(gMenuPopupWidget, direction);
  1.2517 +
  1.2518 +    style = gMenuPopupWidget->style;
  1.2519 +
  1.2520 +    TSOffsetStyleGCs(style, rect->x, rect->y);
  1.2521 +    gtk_style_apply_default_background(style, drawable, TRUE, GTK_STATE_NORMAL,
  1.2522 +                                       cliprect, rect->x, rect->y,
  1.2523 +                                       rect->width, rect->height);
  1.2524 +    gtk_paint_box(style, drawable, GTK_STATE_NORMAL, GTK_SHADOW_OUT, 
  1.2525 +                  cliprect, gMenuPopupWidget, "menu",
  1.2526 +                  rect->x, rect->y, rect->width, rect->height);
  1.2527 +
  1.2528 +    return MOZ_GTK_SUCCESS;
  1.2529 +}
  1.2530 +
  1.2531 +static gint
  1.2532 +moz_gtk_menu_separator_paint(GdkDrawable* drawable, GdkRectangle* rect,
  1.2533 +                             GdkRectangle* cliprect, GtkTextDirection direction)
  1.2534 +{
  1.2535 +    GtkStyle* style;
  1.2536 +    gboolean wide_separators;
  1.2537 +    gint separator_height;
  1.2538 +    guint horizontal_padding;
  1.2539 +    gint paint_height;
  1.2540 +
  1.2541 +    ensure_menu_separator_widget();
  1.2542 +    gtk_widget_set_direction(gMenuSeparatorWidget, direction);
  1.2543 +
  1.2544 +    style = gMenuSeparatorWidget->style;
  1.2545 +
  1.2546 +    gtk_widget_style_get(gMenuSeparatorWidget,
  1.2547 +                         "wide-separators",    &wide_separators,
  1.2548 +                         "separator-height",   &separator_height,
  1.2549 +                         "horizontal-padding", &horizontal_padding,
  1.2550 +                         NULL);
  1.2551 +
  1.2552 +    TSOffsetStyleGCs(style, rect->x, rect->y);
  1.2553 +
  1.2554 +    if (wide_separators) {
  1.2555 +        if (separator_height > rect->height)
  1.2556 +            separator_height = rect->height;
  1.2557 +
  1.2558 +        gtk_paint_box(style, drawable,
  1.2559 +                      GTK_STATE_NORMAL, GTK_SHADOW_ETCHED_OUT,
  1.2560 +                      cliprect, gMenuSeparatorWidget, "hseparator",
  1.2561 +                      rect->x + horizontal_padding + style->xthickness,
  1.2562 +                      rect->y + (rect->height - separator_height - style->ythickness) / 2,
  1.2563 +                      rect->width - 2 * (horizontal_padding + style->xthickness),
  1.2564 +                      separator_height);
  1.2565 +    } else {
  1.2566 +        paint_height = style->ythickness;
  1.2567 +        if (paint_height > rect->height)
  1.2568 +            paint_height = rect->height;
  1.2569 +
  1.2570 +        gtk_paint_hline(style, drawable,
  1.2571 +                        GTK_STATE_NORMAL, cliprect, gMenuSeparatorWidget,
  1.2572 +                        "menuitem",
  1.2573 +                        rect->x + horizontal_padding + style->xthickness,
  1.2574 +                        rect->x + rect->width - horizontal_padding - style->xthickness - 1,
  1.2575 +                        rect->y + (rect->height - style->ythickness) / 2);
  1.2576 +    }
  1.2577 +
  1.2578 +    return MOZ_GTK_SUCCESS;
  1.2579 +}
  1.2580 +
  1.2581 +static gint
  1.2582 +moz_gtk_menu_item_paint(GdkDrawable* drawable, GdkRectangle* rect,
  1.2583 +                        GdkRectangle* cliprect, GtkWidgetState* state,
  1.2584 +                        gint flags, GtkTextDirection direction)
  1.2585 +{
  1.2586 +    GtkStyle* style;
  1.2587 +    GtkShadowType shadow_type;
  1.2588 +    GtkWidget* item_widget;
  1.2589 +
  1.2590 +    if (state->inHover && !state->disabled) {
  1.2591 +        if (flags & MOZ_TOPLEVEL_MENU_ITEM) {
  1.2592 +            ensure_menu_bar_item_widget();
  1.2593 +            item_widget = gMenuBarItemWidget;
  1.2594 +        } else {
  1.2595 +            ensure_menu_item_widget();
  1.2596 +            item_widget = gMenuItemWidget;
  1.2597 +        }
  1.2598 +        gtk_widget_set_direction(item_widget, direction);
  1.2599 +        
  1.2600 +        style = item_widget->style;
  1.2601 +        TSOffsetStyleGCs(style, rect->x, rect->y);
  1.2602 +
  1.2603 +        gtk_widget_style_get(item_widget, "selected-shadow-type",
  1.2604 +                             &shadow_type, NULL);
  1.2605 +
  1.2606 +        gtk_paint_box(style, drawable, GTK_STATE_PRELIGHT, shadow_type,
  1.2607 +                      cliprect, item_widget, "menuitem", rect->x, rect->y,
  1.2608 +                      rect->width, rect->height);
  1.2609 +    }
  1.2610 +
  1.2611 +    return MOZ_GTK_SUCCESS;
  1.2612 +}
  1.2613 +
  1.2614 +static gint
  1.2615 +moz_gtk_menu_arrow_paint(GdkDrawable* drawable, GdkRectangle* rect,
  1.2616 +                         GdkRectangle* cliprect, GtkWidgetState* state,
  1.2617 +                         GtkTextDirection direction)
  1.2618 +{
  1.2619 +    GtkStyle* style;
  1.2620 +    GtkStateType state_type = ConvertGtkState(state);
  1.2621 +
  1.2622 +    ensure_menu_item_widget();
  1.2623 +    gtk_widget_set_direction(gMenuItemWidget, direction);
  1.2624 +
  1.2625 +    style = gMenuItemWidget->style;
  1.2626 +
  1.2627 +    TSOffsetStyleGCs(style, rect->x, rect->y);
  1.2628 +    gtk_paint_arrow(style, drawable, state_type,
  1.2629 +                    (state_type == GTK_STATE_PRELIGHT) ? GTK_SHADOW_IN : GTK_SHADOW_OUT,
  1.2630 +                    cliprect, gMenuItemWidget, "menuitem",
  1.2631 +                    (direction == GTK_TEXT_DIR_LTR) ? GTK_ARROW_RIGHT : GTK_ARROW_LEFT,
  1.2632 +                    TRUE, rect->x, rect->y, rect->width, rect->height);
  1.2633 +
  1.2634 +    return MOZ_GTK_SUCCESS;
  1.2635 +}
  1.2636 +
  1.2637 +static gint
  1.2638 +moz_gtk_check_menu_item_paint(GdkDrawable* drawable, GdkRectangle* rect,
  1.2639 +                              GdkRectangle* cliprect, GtkWidgetState* state,
  1.2640 +                              gboolean checked, gboolean isradio,
  1.2641 +                              GtkTextDirection direction)
  1.2642 +{
  1.2643 +    GtkStateType state_type = ConvertGtkState(state);
  1.2644 +    GtkStyle* style;
  1.2645 +    GtkShadowType shadow_type = (checked)?GTK_SHADOW_IN:GTK_SHADOW_OUT;
  1.2646 +    gint offset;
  1.2647 +    gint indicator_size, horizontal_padding;
  1.2648 +    gint x, y;
  1.2649 +
  1.2650 +    moz_gtk_menu_item_paint(drawable, rect, cliprect, state, FALSE, direction);
  1.2651 +
  1.2652 +    ensure_check_menu_item_widget();
  1.2653 +    gtk_widget_set_direction(gCheckMenuItemWidget, direction);
  1.2654 +
  1.2655 +    gtk_widget_style_get (gCheckMenuItemWidget,
  1.2656 +                          "indicator-size", &indicator_size,
  1.2657 +                          "horizontal-padding", &horizontal_padding,
  1.2658 +                          NULL);
  1.2659 +
  1.2660 +    if (checked || GTK_CHECK_MENU_ITEM(gCheckMenuItemWidget)->always_show_toggle) {
  1.2661 +      style = gCheckMenuItemWidget->style;
  1.2662 +
  1.2663 +      offset = GTK_CONTAINER(gCheckMenuItemWidget)->border_width +
  1.2664 +             gCheckMenuItemWidget->style->xthickness + 2;
  1.2665 +
  1.2666 +      x = (direction == GTK_TEXT_DIR_RTL) ?
  1.2667 +            rect->width - indicator_size - offset - horizontal_padding: rect->x + offset + horizontal_padding;
  1.2668 +      y = rect->y + (rect->height - indicator_size) / 2;
  1.2669 +
  1.2670 +      TSOffsetStyleGCs(style, x, y);
  1.2671 +      gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(gCheckMenuItemWidget),
  1.2672 +                                     checked);
  1.2673 +
  1.2674 +      if (isradio) {
  1.2675 +        gtk_paint_option(style, drawable, state_type, shadow_type, cliprect,
  1.2676 +                         gCheckMenuItemWidget, "option",
  1.2677 +                         x, y, indicator_size, indicator_size);
  1.2678 +      } else {
  1.2679 +        gtk_paint_check(style, drawable, state_type, shadow_type, cliprect,
  1.2680 +                        gCheckMenuItemWidget, "check",
  1.2681 +                        x, y, indicator_size, indicator_size);
  1.2682 +      }
  1.2683 +    }
  1.2684 +
  1.2685 +    return MOZ_GTK_SUCCESS;
  1.2686 +}
  1.2687 +
  1.2688 +static gint
  1.2689 +moz_gtk_window_paint(GdkDrawable* drawable, GdkRectangle* rect,
  1.2690 +                     GdkRectangle* cliprect, GtkTextDirection direction)
  1.2691 +{
  1.2692 +    GtkStyle* style;
  1.2693 +
  1.2694 +    ensure_window_widget();
  1.2695 +    gtk_widget_set_direction(gProtoWindow, direction);
  1.2696 +
  1.2697 +    style = gProtoWindow->style;
  1.2698 +
  1.2699 +    TSOffsetStyleGCs(style, rect->x, rect->y);
  1.2700 +    gtk_style_apply_default_background(style, drawable, TRUE,
  1.2701 +                                       GTK_STATE_NORMAL,
  1.2702 +                                       cliprect, rect->x, rect->y,
  1.2703 +                                       rect->width, rect->height);
  1.2704 +    return MOZ_GTK_SUCCESS;
  1.2705 +}
  1.2706 +
  1.2707 +gint
  1.2708 +moz_gtk_get_widget_border(GtkThemeWidgetType widget, gint* left, gint* top,
  1.2709 +                          gint* right, gint* bottom, GtkTextDirection direction,
  1.2710 +                          gboolean inhtml)
  1.2711 +{
  1.2712 +    GtkWidget* w;
  1.2713 +
  1.2714 +    switch (widget) {
  1.2715 +    case MOZ_GTK_BUTTON:
  1.2716 +        {
  1.2717 +            GtkBorder inner_border;
  1.2718 +            gboolean interior_focus;
  1.2719 +            gint focus_width, focus_pad;
  1.2720 +
  1.2721 +            ensure_button_widget();
  1.2722 +            *left = *top = *right = *bottom = GTK_CONTAINER(gButtonWidget)->border_width;
  1.2723 +
  1.2724 +            /* Don't add this padding in HTML, otherwise the buttons will
  1.2725 +               become too big and stuff the layout. */
  1.2726 +            if (!inhtml) {
  1.2727 +                moz_gtk_widget_get_focus(gButtonWidget, &interior_focus, &focus_width, &focus_pad);
  1.2728 +                moz_gtk_button_get_inner_border(gButtonWidget, &inner_border);
  1.2729 +                *left += focus_width + focus_pad + inner_border.left;
  1.2730 +                *right += focus_width + focus_pad + inner_border.right;
  1.2731 +                *top += focus_width + focus_pad + inner_border.top;
  1.2732 +                *bottom += focus_width + focus_pad + inner_border.bottom;
  1.2733 +            }
  1.2734 +
  1.2735 +            *left += gButtonWidget->style->xthickness;
  1.2736 +            *right += gButtonWidget->style->xthickness;
  1.2737 +            *top += gButtonWidget->style->ythickness;
  1.2738 +            *bottom += gButtonWidget->style->ythickness;
  1.2739 +            return MOZ_GTK_SUCCESS;
  1.2740 +        }
  1.2741 +    case MOZ_GTK_ENTRY:
  1.2742 +        ensure_entry_widget();
  1.2743 +        w = gEntryWidget;
  1.2744 +        break;
  1.2745 +    case MOZ_GTK_TREEVIEW:
  1.2746 +        ensure_tree_view_widget();
  1.2747 +        w = gTreeViewWidget;
  1.2748 +        break;
  1.2749 +    case MOZ_GTK_TREE_HEADER_CELL:
  1.2750 +        {
  1.2751 +            /* A Tree Header in GTK is just a different styled button 
  1.2752 +             * It must be placed in a TreeView for getting the correct style
  1.2753 +             * assigned.
  1.2754 +             * That is why the following code is the same as for MOZ_GTK_BUTTON.  
  1.2755 +             * */
  1.2756 +
  1.2757 +            GtkBorder inner_border;
  1.2758 +            gboolean interior_focus;
  1.2759 +            gint focus_width, focus_pad;
  1.2760 +
  1.2761 +            ensure_tree_header_cell_widget();
  1.2762 +            *left = *top = *right = *bottom = GTK_CONTAINER(gTreeHeaderCellWidget)->border_width;
  1.2763 +
  1.2764 +            moz_gtk_widget_get_focus(gTreeHeaderCellWidget, &interior_focus, &focus_width, &focus_pad);
  1.2765 +            moz_gtk_button_get_inner_border(gTreeHeaderCellWidget, &inner_border);
  1.2766 +            *left += focus_width + focus_pad + inner_border.left;
  1.2767 +            *right += focus_width + focus_pad + inner_border.right;
  1.2768 +            *top += focus_width + focus_pad + inner_border.top;
  1.2769 +            *bottom += focus_width + focus_pad + inner_border.bottom;
  1.2770 +            
  1.2771 +            *left += gTreeHeaderCellWidget->style->xthickness;
  1.2772 +            *right += gTreeHeaderCellWidget->style->xthickness;
  1.2773 +            *top += gTreeHeaderCellWidget->style->ythickness;
  1.2774 +            *bottom += gTreeHeaderCellWidget->style->ythickness;
  1.2775 +            return MOZ_GTK_SUCCESS;
  1.2776 +        }
  1.2777 +    case MOZ_GTK_TREE_HEADER_SORTARROW:
  1.2778 +        ensure_tree_header_cell_widget();
  1.2779 +        w = gTreeHeaderSortArrowWidget;
  1.2780 +        break;
  1.2781 +    case MOZ_GTK_DROPDOWN_ENTRY:
  1.2782 +        ensure_combo_box_entry_widgets();
  1.2783 +        w = gComboBoxEntryTextareaWidget;
  1.2784 +        break;
  1.2785 +    case MOZ_GTK_DROPDOWN_ARROW:
  1.2786 +        ensure_combo_box_entry_widgets();
  1.2787 +        w = gComboBoxEntryButtonWidget;
  1.2788 +        break;
  1.2789 +    case MOZ_GTK_DROPDOWN:
  1.2790 +        {
  1.2791 +            /* We need to account for the arrow on the dropdown, so text
  1.2792 +             * doesn't come too close to the arrow, or in some cases spill
  1.2793 +             * into the arrow. */
  1.2794 +            gboolean ignored_interior_focus, wide_separators;
  1.2795 +            gint focus_width, focus_pad, separator_width;
  1.2796 +            GtkRequisition arrow_req;
  1.2797 +
  1.2798 +            ensure_combo_box_widgets();
  1.2799 +
  1.2800 +            *left = GTK_CONTAINER(gComboBoxButtonWidget)->border_width;
  1.2801 +
  1.2802 +            if (!inhtml) {
  1.2803 +                moz_gtk_widget_get_focus(gComboBoxButtonWidget,
  1.2804 +                                         &ignored_interior_focus,
  1.2805 +                                         &focus_width, &focus_pad);
  1.2806 +                *left += focus_width + focus_pad;
  1.2807 +            }
  1.2808 +
  1.2809 +            *top = *left + gComboBoxButtonWidget->style->ythickness;
  1.2810 +            *left += gComboBoxButtonWidget->style->xthickness;
  1.2811 +
  1.2812 +            *right = *left; *bottom = *top;
  1.2813 +
  1.2814 +            /* If there is no separator, don't try to count its width. */
  1.2815 +            separator_width = 0;
  1.2816 +            if (gComboBoxSeparatorWidget) {
  1.2817 +                gtk_widget_style_get(gComboBoxSeparatorWidget,
  1.2818 +                                     "wide-separators", &wide_separators,
  1.2819 +                                     "separator-width", &separator_width,
  1.2820 +                                     NULL);
  1.2821 +
  1.2822 +                if (!wide_separators)
  1.2823 +                    separator_width =
  1.2824 +                        XTHICKNESS(gComboBoxSeparatorWidget->style);
  1.2825 +            }
  1.2826 +
  1.2827 +            gtk_widget_size_request(gComboBoxArrowWidget, &arrow_req);
  1.2828 +
  1.2829 +            if (direction == GTK_TEXT_DIR_RTL)
  1.2830 +                *left += separator_width + arrow_req.width;
  1.2831 +            else
  1.2832 +                *right += separator_width + arrow_req.width;
  1.2833 +
  1.2834 +            return MOZ_GTK_SUCCESS;
  1.2835 +        }
  1.2836 +    case MOZ_GTK_TABPANELS:
  1.2837 +        ensure_tab_widget();
  1.2838 +        w = gTabWidget;
  1.2839 +        break;
  1.2840 +    case MOZ_GTK_PROGRESSBAR:
  1.2841 +        ensure_progress_widget();
  1.2842 +        w = gProgressWidget;
  1.2843 +        break;
  1.2844 +    case MOZ_GTK_SPINBUTTON_ENTRY:
  1.2845 +    case MOZ_GTK_SPINBUTTON_UP:
  1.2846 +    case MOZ_GTK_SPINBUTTON_DOWN:
  1.2847 +        ensure_spin_widget();
  1.2848 +        w = gSpinWidget;
  1.2849 +        break;
  1.2850 +    case MOZ_GTK_SCALE_HORIZONTAL:
  1.2851 +        ensure_scale_widget();
  1.2852 +        w = gHScaleWidget;
  1.2853 +        break;
  1.2854 +    case MOZ_GTK_SCALE_VERTICAL:
  1.2855 +        ensure_scale_widget();
  1.2856 +        w = gVScaleWidget;
  1.2857 +        break;
  1.2858 +    case MOZ_GTK_FRAME:
  1.2859 +        ensure_frame_widget();
  1.2860 +        w = gFrameWidget;
  1.2861 +        break;
  1.2862 +    case MOZ_GTK_CHECKBUTTON_LABEL:
  1.2863 +    case MOZ_GTK_RADIOBUTTON_LABEL:
  1.2864 +        {
  1.2865 +            gboolean interior_focus;
  1.2866 +            gint focus_width, focus_pad;
  1.2867 +
  1.2868 +            /* If the focus is interior, then the label has a border of
  1.2869 +               (focus_width + focus_pad). */
  1.2870 +            if (widget == MOZ_GTK_CHECKBUTTON_LABEL) {
  1.2871 +                ensure_checkbox_widget();
  1.2872 +                moz_gtk_widget_get_focus(gCheckboxWidget, &interior_focus,
  1.2873 +                                           &focus_width, &focus_pad);
  1.2874 +            }
  1.2875 +            else {
  1.2876 +                ensure_radiobutton_widget();
  1.2877 +                moz_gtk_widget_get_focus(gRadiobuttonWidget, &interior_focus,
  1.2878 +                                        &focus_width, &focus_pad);
  1.2879 +            }
  1.2880 +
  1.2881 +            if (interior_focus)
  1.2882 +                *left = *top = *right = *bottom = (focus_width + focus_pad);
  1.2883 +            else
  1.2884 +                *left = *top = *right = *bottom = 0;
  1.2885 +
  1.2886 +            return MOZ_GTK_SUCCESS;
  1.2887 +        }
  1.2888 +
  1.2889 +    case MOZ_GTK_CHECKBUTTON_CONTAINER:
  1.2890 +    case MOZ_GTK_RADIOBUTTON_CONTAINER:
  1.2891 +        {
  1.2892 +            gboolean interior_focus;
  1.2893 +            gint focus_width, focus_pad;
  1.2894 +
  1.2895 +            /* If the focus is _not_ interior, then the container has a border
  1.2896 +               of (focus_width + focus_pad). */
  1.2897 +            if (widget == MOZ_GTK_CHECKBUTTON_CONTAINER) {
  1.2898 +                ensure_checkbox_widget();
  1.2899 +                moz_gtk_widget_get_focus(gCheckboxWidget, &interior_focus,
  1.2900 +                                           &focus_width, &focus_pad);
  1.2901 +                w = gCheckboxWidget;
  1.2902 +            } else {
  1.2903 +                ensure_radiobutton_widget();
  1.2904 +                moz_gtk_widget_get_focus(gRadiobuttonWidget, &interior_focus,
  1.2905 +                                        &focus_width, &focus_pad);
  1.2906 +                w = gRadiobuttonWidget;
  1.2907 +            }
  1.2908 +
  1.2909 +            *left = *top = *right = *bottom = GTK_CONTAINER(w)->border_width;
  1.2910 +
  1.2911 +            if (!interior_focus) {
  1.2912 +                *left += (focus_width + focus_pad);
  1.2913 +                *right += (focus_width + focus_pad);
  1.2914 +                *top += (focus_width + focus_pad);
  1.2915 +                *bottom += (focus_width + focus_pad);
  1.2916 +            }
  1.2917 +
  1.2918 +            return MOZ_GTK_SUCCESS;
  1.2919 +        }
  1.2920 +    case MOZ_GTK_MENUPOPUP:
  1.2921 +        ensure_menu_popup_widget();
  1.2922 +        w = gMenuPopupWidget;
  1.2923 +        break;
  1.2924 +    case MOZ_GTK_MENUITEM:
  1.2925 +        ensure_menu_item_widget();
  1.2926 +        ensure_menu_bar_item_widget();
  1.2927 +        w = gMenuItemWidget;
  1.2928 +        break;
  1.2929 +    case MOZ_GTK_CHECKMENUITEM:
  1.2930 +    case MOZ_GTK_RADIOMENUITEM:
  1.2931 +        ensure_check_menu_item_widget();
  1.2932 +        w = gCheckMenuItemWidget;
  1.2933 +        break;
  1.2934 +    case MOZ_GTK_TAB:
  1.2935 +        ensure_tab_widget();
  1.2936 +        w = gTabWidget;
  1.2937 +        break;
  1.2938 +    /* These widgets have no borders, since they are not containers. */
  1.2939 +    case MOZ_GTK_SPLITTER_HORIZONTAL:
  1.2940 +    case MOZ_GTK_SPLITTER_VERTICAL:
  1.2941 +    case MOZ_GTK_CHECKBUTTON:
  1.2942 +    case MOZ_GTK_RADIOBUTTON:
  1.2943 +    case MOZ_GTK_SCROLLBAR_BUTTON:
  1.2944 +    case MOZ_GTK_SCROLLBAR_TRACK_HORIZONTAL:
  1.2945 +    case MOZ_GTK_SCROLLBAR_TRACK_VERTICAL:
  1.2946 +    case MOZ_GTK_SCROLLBAR_THUMB_HORIZONTAL:
  1.2947 +    case MOZ_GTK_SCROLLBAR_THUMB_VERTICAL:
  1.2948 +    case MOZ_GTK_SCALE_THUMB_HORIZONTAL:
  1.2949 +    case MOZ_GTK_SCALE_THUMB_VERTICAL:
  1.2950 +    case MOZ_GTK_GRIPPER:
  1.2951 +    case MOZ_GTK_PROGRESS_CHUNK:
  1.2952 +    case MOZ_GTK_PROGRESS_CHUNK_INDETERMINATE:
  1.2953 +    case MOZ_GTK_PROGRESS_CHUNK_VERTICAL_INDETERMINATE:
  1.2954 +    case MOZ_GTK_TREEVIEW_EXPANDER:
  1.2955 +    case MOZ_GTK_TOOLBAR_SEPARATOR:
  1.2956 +    case MOZ_GTK_MENUSEPARATOR:
  1.2957 +    /* These widgets have no borders.*/
  1.2958 +    case MOZ_GTK_SPINBUTTON:
  1.2959 +    case MOZ_GTK_TOOLTIP:
  1.2960 +    case MOZ_GTK_WINDOW:
  1.2961 +    case MOZ_GTK_RESIZER:
  1.2962 +    case MOZ_GTK_MENUARROW:
  1.2963 +    case MOZ_GTK_TOOLBARBUTTON_ARROW:
  1.2964 +    case MOZ_GTK_TOOLBAR:
  1.2965 +    case MOZ_GTK_MENUBAR:
  1.2966 +    case MOZ_GTK_TAB_SCROLLARROW:
  1.2967 +        *left = *top = *right = *bottom = 0;
  1.2968 +        return MOZ_GTK_SUCCESS;
  1.2969 +    default:
  1.2970 +        g_warning("Unsupported widget type: %d", widget);
  1.2971 +        return MOZ_GTK_UNKNOWN_WIDGET;
  1.2972 +    }
  1.2973 +
  1.2974 +    *right = *left = XTHICKNESS(w->style);
  1.2975 +    *bottom = *top = YTHICKNESS(w->style);
  1.2976 +
  1.2977 +    return MOZ_GTK_SUCCESS;
  1.2978 +}
  1.2979 +
  1.2980 +gint
  1.2981 +moz_gtk_get_combo_box_entry_button_size(gint* width, gint* height)
  1.2982 +{
  1.2983 +    /*
  1.2984 +     * We get the requisition of the drop down button, which includes
  1.2985 +     * all padding, border and focus line widths the button uses,
  1.2986 +     * as well as the minimum arrow size and its padding
  1.2987 +     * */
  1.2988 +    GtkRequisition requisition;
  1.2989 +    ensure_combo_box_entry_widgets();
  1.2990 +
  1.2991 +    gtk_widget_size_request(gComboBoxEntryButtonWidget, &requisition);
  1.2992 +    *width = requisition.width;
  1.2993 +    *height = requisition.height;
  1.2994 +
  1.2995 +    return MOZ_GTK_SUCCESS;
  1.2996 +}
  1.2997 +
  1.2998 +gint
  1.2999 +moz_gtk_get_tab_scroll_arrow_size(gint* width, gint* height)
  1.3000 +{
  1.3001 +    gint arrow_size;
  1.3002 +
  1.3003 +    ensure_tab_widget();
  1.3004 +    gtk_widget_style_get(gTabWidget,
  1.3005 +                         "scroll-arrow-hlength", &arrow_size,
  1.3006 +                         NULL);
  1.3007 +
  1.3008 +    *height = *width = arrow_size;
  1.3009 +
  1.3010 +    return MOZ_GTK_SUCCESS;
  1.3011 +}
  1.3012 +
  1.3013 +gint
  1.3014 +moz_gtk_get_arrow_size(gint* width, gint* height)
  1.3015 +{
  1.3016 +    GtkRequisition requisition;
  1.3017 +    ensure_button_arrow_widget();
  1.3018 +
  1.3019 +    gtk_widget_size_request(gButtonArrowWidget, &requisition);
  1.3020 +    *width = requisition.width;
  1.3021 +    *height = requisition.height;
  1.3022 +
  1.3023 +    return MOZ_GTK_SUCCESS;
  1.3024 +}
  1.3025 +
  1.3026 +gint
  1.3027 +moz_gtk_get_toolbar_separator_width(gint* size)
  1.3028 +{
  1.3029 +    gboolean wide_separators;
  1.3030 +    gint separator_width;
  1.3031 +    GtkStyle* style;
  1.3032 +
  1.3033 +    ensure_toolbar_widget();
  1.3034 +
  1.3035 +    style = gToolbarWidget->style;
  1.3036 +
  1.3037 +    gtk_widget_style_get(gToolbarWidget,
  1.3038 +                         "space-size", size,
  1.3039 +                         "wide-separators",  &wide_separators,
  1.3040 +                         "separator-width", &separator_width,
  1.3041 +                         NULL);
  1.3042 +
  1.3043 +    /* Just in case... */
  1.3044 +    *size = MAX(*size, (wide_separators ? separator_width : style->xthickness));
  1.3045 +
  1.3046 +    return MOZ_GTK_SUCCESS;
  1.3047 +}
  1.3048 +
  1.3049 +gint
  1.3050 +moz_gtk_get_expander_size(gint* size)
  1.3051 +{
  1.3052 +    ensure_expander_widget();
  1.3053 +    gtk_widget_style_get(gExpanderWidget,
  1.3054 +                         "expander-size", size,
  1.3055 +                         NULL);
  1.3056 +
  1.3057 +    return MOZ_GTK_SUCCESS;
  1.3058 +}
  1.3059 +
  1.3060 +gint
  1.3061 +moz_gtk_get_treeview_expander_size(gint* size)
  1.3062 +{
  1.3063 +    ensure_tree_view_widget();
  1.3064 +    gtk_widget_style_get(gTreeViewWidget,
  1.3065 +                         "expander-size", size,
  1.3066 +                         NULL);
  1.3067 +
  1.3068 +    return MOZ_GTK_SUCCESS;
  1.3069 +}
  1.3070 +
  1.3071 +gint
  1.3072 +moz_gtk_get_menu_separator_height(gint *size)
  1.3073 +{
  1.3074 +    gboolean wide_separators;
  1.3075 +    gint     separator_height;
  1.3076 +
  1.3077 +    ensure_menu_separator_widget();
  1.3078 +
  1.3079 +    gtk_widget_style_get(gMenuSeparatorWidget,
  1.3080 +                          "wide-separators",  &wide_separators,
  1.3081 +                          "separator-height", &separator_height,
  1.3082 +                          NULL);
  1.3083 +
  1.3084 +    if (wide_separators)
  1.3085 +        *size = separator_height + gMenuSeparatorWidget->style->ythickness;
  1.3086 +    else
  1.3087 +        *size = gMenuSeparatorWidget->style->ythickness * 2;
  1.3088 +
  1.3089 +    return MOZ_GTK_SUCCESS;
  1.3090 +}
  1.3091 +
  1.3092 +gint
  1.3093 +moz_gtk_get_scalethumb_metrics(GtkOrientation orient, gint* thumb_length, gint* thumb_height)
  1.3094 +{
  1.3095 +  GtkWidget* widget;
  1.3096 +
  1.3097 +  ensure_scale_widget();
  1.3098 +  widget = ((orient == GTK_ORIENTATION_HORIZONTAL) ? gHScaleWidget : gVScaleWidget);
  1.3099 +
  1.3100 +  gtk_widget_style_get (widget,
  1.3101 +                        "slider_length", thumb_length,
  1.3102 +                        "slider_width", thumb_height,
  1.3103 +                        NULL);
  1.3104 +
  1.3105 +  return MOZ_GTK_SUCCESS;
  1.3106 +}
  1.3107 +
  1.3108 +gint
  1.3109 +moz_gtk_get_scrollbar_metrics(MozGtkScrollbarMetrics *metrics)
  1.3110 +{
  1.3111 +    ensure_scrollbar_widget();
  1.3112 +
  1.3113 +    gtk_widget_style_get (gHorizScrollbarWidget,
  1.3114 +                          "slider_width", &metrics->slider_width,
  1.3115 +                          "trough_border", &metrics->trough_border,
  1.3116 +                          "stepper_size", &metrics->stepper_size,
  1.3117 +                          "stepper_spacing", &metrics->stepper_spacing,
  1.3118 +                          NULL);
  1.3119 +
  1.3120 +    metrics->min_slider_size =
  1.3121 +        GTK_RANGE(gHorizScrollbarWidget)->min_slider_size;
  1.3122 +
  1.3123 +    return MOZ_GTK_SUCCESS;
  1.3124 +}
  1.3125 +
  1.3126 +gboolean
  1.3127 +moz_gtk_images_in_menus()
  1.3128 +{
  1.3129 +    gboolean result;
  1.3130 +    GtkSettings* settings;
  1.3131 +
  1.3132 +    ensure_image_menu_item_widget();
  1.3133 +    settings = gtk_widget_get_settings(gImageMenuItemWidget);
  1.3134 +
  1.3135 +    g_object_get(settings, "gtk-menu-images", &result, NULL);
  1.3136 +    return result;
  1.3137 +}
  1.3138 +
  1.3139 +gboolean
  1.3140 +moz_gtk_images_in_buttons()
  1.3141 +{
  1.3142 +    gboolean result;
  1.3143 +    GtkSettings* settings;
  1.3144 +
  1.3145 +    ensure_button_widget();
  1.3146 +    settings = gtk_widget_get_settings(gButtonWidget);
  1.3147 +
  1.3148 +    g_object_get(settings, "gtk-button-images", &result, NULL);
  1.3149 +    return result;
  1.3150 +}
  1.3151 +
  1.3152 +gint
  1.3153 +moz_gtk_widget_paint(GtkThemeWidgetType widget, GdkDrawable* drawable,
  1.3154 +                     GdkRectangle* rect, GdkRectangle* cliprect,
  1.3155 +                     GtkWidgetState* state, gint flags,
  1.3156 +                     GtkTextDirection direction)
  1.3157 +{
  1.3158 +    switch (widget) {
  1.3159 +    case MOZ_GTK_BUTTON:
  1.3160 +        if (state->depressed) {
  1.3161 +            ensure_toggle_button_widget();
  1.3162 +            return moz_gtk_button_paint(drawable, rect, cliprect, state,
  1.3163 +                                        (GtkReliefStyle) flags,
  1.3164 +                                        gToggleButtonWidget, direction);
  1.3165 +        }
  1.3166 +        ensure_button_widget();
  1.3167 +        return moz_gtk_button_paint(drawable, rect, cliprect, state,
  1.3168 +                                    (GtkReliefStyle) flags, gButtonWidget,
  1.3169 +                                    direction);
  1.3170 +        break;
  1.3171 +    case MOZ_GTK_CHECKBUTTON:
  1.3172 +    case MOZ_GTK_RADIOBUTTON:
  1.3173 +        return moz_gtk_toggle_paint(drawable, rect, cliprect, state,
  1.3174 +                                    !!(flags & MOZ_GTK_WIDGET_CHECKED),
  1.3175 +                                    !!(flags & MOZ_GTK_WIDGET_INCONSISTENT),
  1.3176 +                                    (widget == MOZ_GTK_RADIOBUTTON),
  1.3177 +                                    direction);
  1.3178 +        break;
  1.3179 +    case MOZ_GTK_SCROLLBAR_BUTTON:
  1.3180 +        return moz_gtk_scrollbar_button_paint(drawable, rect, cliprect, state,
  1.3181 +                                              (GtkScrollbarButtonFlags) flags,
  1.3182 +                                              direction);
  1.3183 +        break;
  1.3184 +    case MOZ_GTK_SCROLLBAR_TRACK_HORIZONTAL:
  1.3185 +    case MOZ_GTK_SCROLLBAR_TRACK_VERTICAL:
  1.3186 +        return moz_gtk_scrollbar_trough_paint(widget, drawable, rect,
  1.3187 +                                              cliprect, state, direction);
  1.3188 +        break;
  1.3189 +    case MOZ_GTK_SCROLLBAR_THUMB_HORIZONTAL:
  1.3190 +    case MOZ_GTK_SCROLLBAR_THUMB_VERTICAL:
  1.3191 +        return moz_gtk_scrollbar_thumb_paint(widget, drawable, rect,
  1.3192 +                                             cliprect, state, direction);
  1.3193 +        break;
  1.3194 +    case MOZ_GTK_SCALE_HORIZONTAL:
  1.3195 +    case MOZ_GTK_SCALE_VERTICAL:
  1.3196 +        return moz_gtk_scale_paint(drawable, rect, cliprect, state,
  1.3197 +                                   (GtkOrientation) flags, direction);
  1.3198 +        break;
  1.3199 +    case MOZ_GTK_SCALE_THUMB_HORIZONTAL:
  1.3200 +    case MOZ_GTK_SCALE_THUMB_VERTICAL:
  1.3201 +        return moz_gtk_scale_thumb_paint(drawable, rect, cliprect, state,
  1.3202 +                                         (GtkOrientation) flags, direction);
  1.3203 +        break;
  1.3204 +    case MOZ_GTK_SPINBUTTON:
  1.3205 +        return moz_gtk_spin_paint(drawable, rect, direction);
  1.3206 +        break;
  1.3207 +    case MOZ_GTK_SPINBUTTON_UP:
  1.3208 +    case MOZ_GTK_SPINBUTTON_DOWN:
  1.3209 +        return moz_gtk_spin_updown_paint(drawable, rect,
  1.3210 +                                         (widget == MOZ_GTK_SPINBUTTON_DOWN),
  1.3211 +                                         state, direction);
  1.3212 +        break;
  1.3213 +    case MOZ_GTK_SPINBUTTON_ENTRY:
  1.3214 +        ensure_spin_widget();
  1.3215 +        return moz_gtk_entry_paint(drawable, rect, cliprect, state,
  1.3216 +                                   gSpinWidget, direction);
  1.3217 +        break;
  1.3218 +    case MOZ_GTK_GRIPPER:
  1.3219 +        return moz_gtk_gripper_paint(drawable, rect, cliprect, state,
  1.3220 +                                     direction);
  1.3221 +        break;
  1.3222 +    case MOZ_GTK_TREEVIEW:
  1.3223 +        return moz_gtk_treeview_paint(drawable, rect, cliprect, state,
  1.3224 +                                      direction);
  1.3225 +        break;
  1.3226 +    case MOZ_GTK_TREE_HEADER_CELL:
  1.3227 +        return moz_gtk_tree_header_cell_paint(drawable, rect, cliprect, state,
  1.3228 +                                              flags, direction);
  1.3229 +        break;
  1.3230 +    case MOZ_GTK_TREE_HEADER_SORTARROW:
  1.3231 +        return moz_gtk_tree_header_sort_arrow_paint(drawable, rect, cliprect,
  1.3232 +                                                    state,
  1.3233 +                                                    (GtkArrowType) flags,
  1.3234 +                                                    direction);
  1.3235 +        break;
  1.3236 +    case MOZ_GTK_TREEVIEW_EXPANDER:
  1.3237 +        return moz_gtk_treeview_expander_paint(drawable, rect, cliprect, state,
  1.3238 +                                               (GtkExpanderStyle) flags, direction);
  1.3239 +        break;
  1.3240 +    case MOZ_GTK_ENTRY:
  1.3241 +        ensure_entry_widget();
  1.3242 +        return moz_gtk_entry_paint(drawable, rect, cliprect, state,
  1.3243 +                                   gEntryWidget, direction);
  1.3244 +        break;
  1.3245 +    case MOZ_GTK_DROPDOWN:
  1.3246 +        return moz_gtk_combo_box_paint(drawable, rect, cliprect, state,
  1.3247 +                                       (gboolean) flags, direction);
  1.3248 +        break;
  1.3249 +    case MOZ_GTK_DROPDOWN_ARROW:
  1.3250 +        return moz_gtk_combo_box_entry_button_paint(drawable, rect, cliprect,
  1.3251 +                                                    state, flags, direction);
  1.3252 +        break;
  1.3253 +    case MOZ_GTK_DROPDOWN_ENTRY:
  1.3254 +        ensure_combo_box_entry_widgets();
  1.3255 +        return moz_gtk_entry_paint(drawable, rect, cliprect, state,
  1.3256 +                                   gComboBoxEntryTextareaWidget, direction);
  1.3257 +        break;
  1.3258 +    case MOZ_GTK_CHECKBUTTON_CONTAINER:
  1.3259 +    case MOZ_GTK_RADIOBUTTON_CONTAINER:
  1.3260 +        return moz_gtk_container_paint(drawable, rect, cliprect, state,
  1.3261 +                                       (widget == MOZ_GTK_RADIOBUTTON_CONTAINER),
  1.3262 +                                       direction);
  1.3263 +        break;
  1.3264 +    case MOZ_GTK_CHECKBUTTON_LABEL:
  1.3265 +    case MOZ_GTK_RADIOBUTTON_LABEL:
  1.3266 +        return moz_gtk_toggle_label_paint(drawable, rect, cliprect, state,
  1.3267 +                                          (widget == MOZ_GTK_RADIOBUTTON_LABEL),
  1.3268 +                                          direction);
  1.3269 +        break;
  1.3270 +    case MOZ_GTK_TOOLBAR:
  1.3271 +        return moz_gtk_toolbar_paint(drawable, rect, cliprect, direction);
  1.3272 +        break;
  1.3273 +    case MOZ_GTK_TOOLBAR_SEPARATOR:
  1.3274 +        return moz_gtk_toolbar_separator_paint(drawable, rect, cliprect,
  1.3275 +                                               direction);
  1.3276 +        break;
  1.3277 +    case MOZ_GTK_TOOLTIP:
  1.3278 +        return moz_gtk_tooltip_paint(drawable, rect, cliprect, direction);
  1.3279 +        break;
  1.3280 +    case MOZ_GTK_FRAME:
  1.3281 +        return moz_gtk_frame_paint(drawable, rect, cliprect, direction);
  1.3282 +        break;
  1.3283 +    case MOZ_GTK_RESIZER:
  1.3284 +        return moz_gtk_resizer_paint(drawable, rect, cliprect, state,
  1.3285 +                                     direction);
  1.3286 +        break;
  1.3287 +    case MOZ_GTK_PROGRESSBAR:
  1.3288 +        return moz_gtk_progressbar_paint(drawable, rect, cliprect, direction);
  1.3289 +        break;
  1.3290 +    case MOZ_GTK_PROGRESS_CHUNK:
  1.3291 +    case MOZ_GTK_PROGRESS_CHUNK_INDETERMINATE:
  1.3292 +    case MOZ_GTK_PROGRESS_CHUNK_VERTICAL_INDETERMINATE:
  1.3293 +        return moz_gtk_progress_chunk_paint(drawable, rect, cliprect,
  1.3294 +                                            direction, widget);
  1.3295 +        break;
  1.3296 +    case MOZ_GTK_TAB:
  1.3297 +        return moz_gtk_tab_paint(drawable, rect, cliprect, state,
  1.3298 +                                 (GtkTabFlags) flags, direction);
  1.3299 +        break;
  1.3300 +    case MOZ_GTK_TABPANELS:
  1.3301 +        return moz_gtk_tabpanels_paint(drawable, rect, cliprect, direction);
  1.3302 +        break;
  1.3303 +    case MOZ_GTK_TAB_SCROLLARROW:
  1.3304 +        return moz_gtk_tab_scroll_arrow_paint(drawable, rect, cliprect, state,
  1.3305 +                                              (GtkArrowType) flags, direction);
  1.3306 +        break;
  1.3307 +    case MOZ_GTK_MENUBAR:
  1.3308 +        return moz_gtk_menu_bar_paint(drawable, rect, cliprect, direction);
  1.3309 +        break;
  1.3310 +    case MOZ_GTK_MENUPOPUP:
  1.3311 +        return moz_gtk_menu_popup_paint(drawable, rect, cliprect, direction);
  1.3312 +        break;
  1.3313 +    case MOZ_GTK_MENUSEPARATOR:
  1.3314 +        return moz_gtk_menu_separator_paint(drawable, rect, cliprect,
  1.3315 +                                            direction);
  1.3316 +        break;
  1.3317 +    case MOZ_GTK_MENUITEM:
  1.3318 +        return moz_gtk_menu_item_paint(drawable, rect, cliprect, state, flags,
  1.3319 +                                       direction);
  1.3320 +        break;
  1.3321 +    case MOZ_GTK_MENUARROW:
  1.3322 +        return moz_gtk_menu_arrow_paint(drawable, rect, cliprect, state,
  1.3323 +                                        direction);
  1.3324 +        break;
  1.3325 +    case MOZ_GTK_TOOLBARBUTTON_ARROW:
  1.3326 +        return moz_gtk_arrow_paint(drawable, rect, cliprect, state,
  1.3327 +                                   (GtkArrowType) flags, direction);
  1.3328 +        break;
  1.3329 +    case MOZ_GTK_CHECKMENUITEM:
  1.3330 +    case MOZ_GTK_RADIOMENUITEM:
  1.3331 +        return moz_gtk_check_menu_item_paint(drawable, rect, cliprect, state,
  1.3332 +                                             (gboolean) flags,
  1.3333 +                                             (widget == MOZ_GTK_RADIOMENUITEM),
  1.3334 +                                             direction);
  1.3335 +        break;
  1.3336 +    case MOZ_GTK_SPLITTER_HORIZONTAL:
  1.3337 +        return moz_gtk_vpaned_paint(drawable, rect, cliprect, state);
  1.3338 +        break;
  1.3339 +    case MOZ_GTK_SPLITTER_VERTICAL:
  1.3340 +        return moz_gtk_hpaned_paint(drawable, rect, cliprect, state);
  1.3341 +        break;
  1.3342 +    case MOZ_GTK_WINDOW:
  1.3343 +        return moz_gtk_window_paint(drawable, rect, cliprect, direction);
  1.3344 +        break;
  1.3345 +    default:
  1.3346 +        g_warning("Unknown widget type: %d", widget);
  1.3347 +    }
  1.3348 +
  1.3349 +    return MOZ_GTK_UNKNOWN_WIDGET;
  1.3350 +}
  1.3351 +
  1.3352 +GtkWidget* moz_gtk_get_scrollbar_widget(void)
  1.3353 +{
  1.3354 +    NS_ASSERTION(is_initialized, "Forgot to call moz_gtk_init()");
  1.3355 +    ensure_scrollbar_widget();
  1.3356 +    return gHorizScrollbarWidget;
  1.3357 +}
  1.3358 +
  1.3359 +gint
  1.3360 +moz_gtk_shutdown()
  1.3361 +{
  1.3362 +    GtkWidgetClass *entry_class;
  1.3363 +
  1.3364 +    if (gTooltipWidget)
  1.3365 +        gtk_widget_destroy(gTooltipWidget);
  1.3366 +    /* This will destroy all of our widgets */
  1.3367 +    if (gProtoWindow)
  1.3368 +        gtk_widget_destroy(gProtoWindow);
  1.3369 +
  1.3370 +    gProtoWindow = NULL;
  1.3371 +    gProtoLayout = NULL;
  1.3372 +    gButtonWidget = NULL;
  1.3373 +    gToggleButtonWidget = NULL;
  1.3374 +    gButtonArrowWidget = NULL;
  1.3375 +    gCheckboxWidget = NULL;
  1.3376 +    gRadiobuttonWidget = NULL;
  1.3377 +    gHorizScrollbarWidget = NULL;
  1.3378 +    gVertScrollbarWidget = NULL;
  1.3379 +    gSpinWidget = NULL;
  1.3380 +    gHScaleWidget = NULL;
  1.3381 +    gVScaleWidget = NULL;
  1.3382 +    gEntryWidget = NULL;
  1.3383 +    gComboBoxWidget = NULL;
  1.3384 +    gComboBoxButtonWidget = NULL;
  1.3385 +    gComboBoxSeparatorWidget = NULL;
  1.3386 +    gComboBoxArrowWidget = NULL;
  1.3387 +    gComboBoxEntryWidget = NULL;
  1.3388 +    gComboBoxEntryButtonWidget = NULL;
  1.3389 +    gComboBoxEntryArrowWidget = NULL;
  1.3390 +    gComboBoxEntryTextareaWidget = NULL;
  1.3391 +    gHandleBoxWidget = NULL;
  1.3392 +    gToolbarWidget = NULL;
  1.3393 +    gStatusbarWidget = NULL;
  1.3394 +    gFrameWidget = NULL;
  1.3395 +    gProgressWidget = NULL;
  1.3396 +    gTabWidget = NULL;
  1.3397 +    gTooltipWidget = NULL;
  1.3398 +    gMenuBarWidget = NULL;
  1.3399 +    gMenuBarItemWidget = NULL;
  1.3400 +    gMenuPopupWidget = NULL;
  1.3401 +    gMenuItemWidget = NULL;
  1.3402 +    gImageMenuItemWidget = NULL;
  1.3403 +    gCheckMenuItemWidget = NULL;
  1.3404 +    gTreeViewWidget = NULL;
  1.3405 +    gMiddleTreeViewColumn = NULL;
  1.3406 +    gTreeHeaderCellWidget = NULL;
  1.3407 +    gTreeHeaderSortArrowWidget = NULL;
  1.3408 +    gExpanderWidget = NULL;
  1.3409 +    gToolbarSeparatorWidget = NULL;
  1.3410 +    gMenuSeparatorWidget = NULL;
  1.3411 +    gHPanedWidget = NULL;
  1.3412 +    gVPanedWidget = NULL;
  1.3413 +    gScrolledWindowWidget = NULL;
  1.3414 +
  1.3415 +    entry_class = g_type_class_peek(GTK_TYPE_ENTRY);
  1.3416 +    g_type_class_unref(entry_class);
  1.3417 +
  1.3418 +    is_initialized = FALSE;
  1.3419 +
  1.3420 +    return MOZ_GTK_SUCCESS;
  1.3421 +}

mercurial