widget/gtk/gtk3drawing.c

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

mercurial