widget/gtk/gtk2drawing.c

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

michael@0 1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
michael@0 2 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 3 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 5
michael@0 6 /*
michael@0 7 * This file contains painting functions for each of the gtk2 widgets.
michael@0 8 * Adapted from the gtkdrawing.c, and gtk+2.0 source.
michael@0 9 */
michael@0 10
michael@0 11 #include <gtk/gtk.h>
michael@0 12 #include <gdk/gdkprivate.h>
michael@0 13 #include <string.h>
michael@0 14 #include "gtkdrawing.h"
michael@0 15 #include "nsDebug.h"
michael@0 16 #include "prinrval.h"
michael@0 17
michael@0 18 #include <math.h>
michael@0 19
michael@0 20 #define XTHICKNESS(style) (style->xthickness)
michael@0 21 #define YTHICKNESS(style) (style->ythickness)
michael@0 22 #define WINDOW_IS_MAPPED(window) ((window) && GDK_IS_WINDOW(window) && gdk_window_is_visible(window))
michael@0 23
michael@0 24 static GtkWidget* gProtoWindow;
michael@0 25 static GtkWidget* gProtoLayout;
michael@0 26 static GtkWidget* gButtonWidget;
michael@0 27 static GtkWidget* gToggleButtonWidget;
michael@0 28 static GtkWidget* gButtonArrowWidget;
michael@0 29 static GtkWidget* gCheckboxWidget;
michael@0 30 static GtkWidget* gRadiobuttonWidget;
michael@0 31 static GtkWidget* gHorizScrollbarWidget;
michael@0 32 static GtkWidget* gVertScrollbarWidget;
michael@0 33 static GtkWidget* gSpinWidget;
michael@0 34 static GtkWidget* gHScaleWidget;
michael@0 35 static GtkWidget* gVScaleWidget;
michael@0 36 static GtkWidget* gEntryWidget;
michael@0 37 static GtkWidget* gComboBoxWidget;
michael@0 38 static GtkWidget* gComboBoxButtonWidget;
michael@0 39 static GtkWidget* gComboBoxArrowWidget;
michael@0 40 static GtkWidget* gComboBoxSeparatorWidget;
michael@0 41 static GtkWidget* gComboBoxEntryWidget;
michael@0 42 static GtkWidget* gComboBoxEntryTextareaWidget;
michael@0 43 static GtkWidget* gComboBoxEntryButtonWidget;
michael@0 44 static GtkWidget* gComboBoxEntryArrowWidget;
michael@0 45 static GtkWidget* gHandleBoxWidget;
michael@0 46 static GtkWidget* gToolbarWidget;
michael@0 47 static GtkWidget* gFrameWidget;
michael@0 48 static GtkWidget* gStatusbarWidget;
michael@0 49 static GtkWidget* gProgressWidget;
michael@0 50 static GtkWidget* gTabWidget;
michael@0 51 static GtkWidget* gTooltipWidget;
michael@0 52 static GtkWidget* gMenuBarWidget;
michael@0 53 static GtkWidget* gMenuBarItemWidget;
michael@0 54 static GtkWidget* gMenuPopupWidget;
michael@0 55 static GtkWidget* gMenuItemWidget;
michael@0 56 static GtkWidget* gImageMenuItemWidget;
michael@0 57 static GtkWidget* gCheckMenuItemWidget;
michael@0 58 static GtkWidget* gTreeViewWidget;
michael@0 59 static GtkTreeViewColumn* gMiddleTreeViewColumn;
michael@0 60 static GtkWidget* gTreeHeaderCellWidget;
michael@0 61 static GtkWidget* gTreeHeaderSortArrowWidget;
michael@0 62 static GtkWidget* gExpanderWidget;
michael@0 63 static GtkWidget* gToolbarSeparatorWidget;
michael@0 64 static GtkWidget* gMenuSeparatorWidget;
michael@0 65 static GtkWidget* gHPanedWidget;
michael@0 66 static GtkWidget* gVPanedWidget;
michael@0 67 static GtkWidget* gScrolledWindowWidget;
michael@0 68
michael@0 69 static style_prop_t style_prop_func;
michael@0 70 static gboolean have_arrow_scaling;
michael@0 71 static gboolean is_initialized;
michael@0 72
michael@0 73 /* Because we have such an unconventional way of drawing widgets, signal to the GTK theme engine
michael@0 74 that they are drawing for Mozilla instead of a conventional GTK app so they can do any specific
michael@0 75 things they may want to do. */
michael@0 76 static void
michael@0 77 moz_gtk_set_widget_name(GtkWidget* widget)
michael@0 78 {
michael@0 79 gtk_widget_set_name(widget, "MozillaGtkWidget");
michael@0 80 }
michael@0 81
michael@0 82 gint
michael@0 83 moz_gtk_enable_style_props(style_prop_t styleGetProp)
michael@0 84 {
michael@0 85 style_prop_func = styleGetProp;
michael@0 86 return MOZ_GTK_SUCCESS;
michael@0 87 }
michael@0 88
michael@0 89 static gint
michael@0 90 ensure_window_widget()
michael@0 91 {
michael@0 92 if (!gProtoWindow) {
michael@0 93 gProtoWindow = gtk_window_new(GTK_WINDOW_POPUP);
michael@0 94 gtk_widget_realize(gProtoWindow);
michael@0 95 moz_gtk_set_widget_name(gProtoWindow);
michael@0 96 }
michael@0 97 return MOZ_GTK_SUCCESS;
michael@0 98 }
michael@0 99
michael@0 100 static gint
michael@0 101 setup_widget_prototype(GtkWidget* widget)
michael@0 102 {
michael@0 103 ensure_window_widget();
michael@0 104 if (!gProtoLayout) {
michael@0 105 gProtoLayout = gtk_fixed_new();
michael@0 106 gtk_container_add(GTK_CONTAINER(gProtoWindow), gProtoLayout);
michael@0 107 }
michael@0 108
michael@0 109 gtk_container_add(GTK_CONTAINER(gProtoLayout), widget);
michael@0 110 gtk_widget_realize(widget);
michael@0 111 g_object_set_data(G_OBJECT(widget), "transparent-bg-hint", GINT_TO_POINTER(TRUE));
michael@0 112 return MOZ_GTK_SUCCESS;
michael@0 113 }
michael@0 114
michael@0 115 static gint
michael@0 116 ensure_button_widget()
michael@0 117 {
michael@0 118 if (!gButtonWidget) {
michael@0 119 gButtonWidget = gtk_button_new_with_label("M");
michael@0 120 setup_widget_prototype(gButtonWidget);
michael@0 121 }
michael@0 122 return MOZ_GTK_SUCCESS;
michael@0 123 }
michael@0 124
michael@0 125 static gint
michael@0 126 ensure_hpaned_widget()
michael@0 127 {
michael@0 128 if (!gHPanedWidget) {
michael@0 129 gHPanedWidget = gtk_hpaned_new();
michael@0 130 setup_widget_prototype(gHPanedWidget);
michael@0 131 }
michael@0 132 return MOZ_GTK_SUCCESS;
michael@0 133 }
michael@0 134
michael@0 135 static gint
michael@0 136 ensure_vpaned_widget()
michael@0 137 {
michael@0 138 if (!gVPanedWidget) {
michael@0 139 gVPanedWidget = gtk_vpaned_new();
michael@0 140 setup_widget_prototype(gVPanedWidget);
michael@0 141 }
michael@0 142 return MOZ_GTK_SUCCESS;
michael@0 143 }
michael@0 144
michael@0 145 static gint
michael@0 146 ensure_toggle_button_widget()
michael@0 147 {
michael@0 148 if (!gToggleButtonWidget) {
michael@0 149 gToggleButtonWidget = gtk_toggle_button_new();
michael@0 150 setup_widget_prototype(gToggleButtonWidget);
michael@0 151 /* toggle button must be set active to get the right style on hover. */
michael@0 152 GTK_TOGGLE_BUTTON(gToggleButtonWidget)->active = TRUE;
michael@0 153 }
michael@0 154 return MOZ_GTK_SUCCESS;
michael@0 155 }
michael@0 156
michael@0 157 static gint
michael@0 158 ensure_button_arrow_widget()
michael@0 159 {
michael@0 160 if (!gButtonArrowWidget) {
michael@0 161 ensure_toggle_button_widget();
michael@0 162
michael@0 163 gButtonArrowWidget = gtk_arrow_new(GTK_ARROW_DOWN, GTK_SHADOW_OUT);
michael@0 164 gtk_container_add(GTK_CONTAINER(gToggleButtonWidget), gButtonArrowWidget);
michael@0 165 gtk_widget_realize(gButtonArrowWidget);
michael@0 166 }
michael@0 167 return MOZ_GTK_SUCCESS;
michael@0 168 }
michael@0 169
michael@0 170 static gint
michael@0 171 ensure_checkbox_widget()
michael@0 172 {
michael@0 173 if (!gCheckboxWidget) {
michael@0 174 gCheckboxWidget = gtk_check_button_new_with_label("M");
michael@0 175 setup_widget_prototype(gCheckboxWidget);
michael@0 176 }
michael@0 177 return MOZ_GTK_SUCCESS;
michael@0 178 }
michael@0 179
michael@0 180 static gint
michael@0 181 ensure_radiobutton_widget()
michael@0 182 {
michael@0 183 if (!gRadiobuttonWidget) {
michael@0 184 gRadiobuttonWidget = gtk_radio_button_new_with_label(NULL, "M");
michael@0 185 setup_widget_prototype(gRadiobuttonWidget);
michael@0 186 }
michael@0 187 return MOZ_GTK_SUCCESS;
michael@0 188 }
michael@0 189
michael@0 190 static gint
michael@0 191 ensure_scrollbar_widget()
michael@0 192 {
michael@0 193 if (!gVertScrollbarWidget) {
michael@0 194 gVertScrollbarWidget = gtk_vscrollbar_new(NULL);
michael@0 195 setup_widget_prototype(gVertScrollbarWidget);
michael@0 196 }
michael@0 197 if (!gHorizScrollbarWidget) {
michael@0 198 gHorizScrollbarWidget = gtk_hscrollbar_new(NULL);
michael@0 199 setup_widget_prototype(gHorizScrollbarWidget);
michael@0 200 }
michael@0 201 return MOZ_GTK_SUCCESS;
michael@0 202 }
michael@0 203
michael@0 204 static gint
michael@0 205 ensure_spin_widget()
michael@0 206 {
michael@0 207 if (!gSpinWidget) {
michael@0 208 gSpinWidget = gtk_spin_button_new(NULL, 1, 0);
michael@0 209 setup_widget_prototype(gSpinWidget);
michael@0 210 }
michael@0 211 return MOZ_GTK_SUCCESS;
michael@0 212 }
michael@0 213
michael@0 214 static gint
michael@0 215 ensure_scale_widget()
michael@0 216 {
michael@0 217 if (!gHScaleWidget) {
michael@0 218 gHScaleWidget = gtk_hscale_new(NULL);
michael@0 219 setup_widget_prototype(gHScaleWidget);
michael@0 220 }
michael@0 221 if (!gVScaleWidget) {
michael@0 222 gVScaleWidget = gtk_vscale_new(NULL);
michael@0 223 setup_widget_prototype(gVScaleWidget);
michael@0 224 }
michael@0 225 return MOZ_GTK_SUCCESS;
michael@0 226 }
michael@0 227
michael@0 228 static gint
michael@0 229 ensure_entry_widget()
michael@0 230 {
michael@0 231 if (!gEntryWidget) {
michael@0 232 gEntryWidget = gtk_entry_new();
michael@0 233 setup_widget_prototype(gEntryWidget);
michael@0 234 }
michael@0 235 return MOZ_GTK_SUCCESS;
michael@0 236 }
michael@0 237
michael@0 238 /* We need to have pointers to the inner widgets (button, separator, arrow)
michael@0 239 * of the ComboBox to get the correct rendering from theme engines which
michael@0 240 * special cases their look. Since the inner layout can change, we ask GTK
michael@0 241 * to NULL our pointers when they are about to become invalid because the
michael@0 242 * corresponding widgets don't exist anymore. It's the role of
michael@0 243 * g_object_add_weak_pointer().
michael@0 244 * Note that if we don't find the inner widgets (which shouldn't happen), we
michael@0 245 * fallback to use generic "non-inner" widgets, and they don't need that kind
michael@0 246 * of weak pointer since they are explicit children of gProtoWindow and as
michael@0 247 * such GTK holds a strong reference to them. */
michael@0 248 static void
michael@0 249 moz_gtk_get_combo_box_inner_button(GtkWidget *widget, gpointer client_data)
michael@0 250 {
michael@0 251 if (GTK_IS_TOGGLE_BUTTON(widget)) {
michael@0 252 gComboBoxButtonWidget = widget;
michael@0 253 g_object_add_weak_pointer(G_OBJECT(widget),
michael@0 254 (gpointer) &gComboBoxButtonWidget);
michael@0 255 gtk_widget_realize(widget);
michael@0 256 g_object_set_data(G_OBJECT(widget), "transparent-bg-hint", GINT_TO_POINTER(TRUE));
michael@0 257 }
michael@0 258 }
michael@0 259
michael@0 260 static void
michael@0 261 moz_gtk_get_combo_box_button_inner_widgets(GtkWidget *widget,
michael@0 262 gpointer client_data)
michael@0 263 {
michael@0 264 if (GTK_IS_SEPARATOR(widget)) {
michael@0 265 gComboBoxSeparatorWidget = widget;
michael@0 266 g_object_add_weak_pointer(G_OBJECT(widget),
michael@0 267 (gpointer) &gComboBoxSeparatorWidget);
michael@0 268 } else if (GTK_IS_ARROW(widget)) {
michael@0 269 gComboBoxArrowWidget = widget;
michael@0 270 g_object_add_weak_pointer(G_OBJECT(widget),
michael@0 271 (gpointer) &gComboBoxArrowWidget);
michael@0 272 } else
michael@0 273 return;
michael@0 274 gtk_widget_realize(widget);
michael@0 275 g_object_set_data(G_OBJECT(widget), "transparent-bg-hint", GINT_TO_POINTER(TRUE));
michael@0 276 }
michael@0 277
michael@0 278 static gint
michael@0 279 ensure_combo_box_widgets()
michael@0 280 {
michael@0 281 GtkWidget* buttonChild;
michael@0 282
michael@0 283 if (gComboBoxButtonWidget && gComboBoxArrowWidget)
michael@0 284 return MOZ_GTK_SUCCESS;
michael@0 285
michael@0 286 /* Create a ComboBox if needed */
michael@0 287 if (!gComboBoxWidget) {
michael@0 288 gComboBoxWidget = gtk_combo_box_new();
michael@0 289 setup_widget_prototype(gComboBoxWidget);
michael@0 290 }
michael@0 291
michael@0 292 /* Get its inner Button */
michael@0 293 gtk_container_forall(GTK_CONTAINER(gComboBoxWidget),
michael@0 294 moz_gtk_get_combo_box_inner_button,
michael@0 295 NULL);
michael@0 296
michael@0 297 if (gComboBoxButtonWidget) {
michael@0 298 /* Get the widgets inside the Button */
michael@0 299 buttonChild = GTK_BIN(gComboBoxButtonWidget)->child;
michael@0 300 if (GTK_IS_HBOX(buttonChild)) {
michael@0 301 /* appears-as-list = FALSE, cell-view = TRUE; the button
michael@0 302 * contains an hbox. This hbox is there because the ComboBox
michael@0 303 * needs to place a cell renderer, a separator, and an arrow in
michael@0 304 * the button when appears-as-list is FALSE. */
michael@0 305 gtk_container_forall(GTK_CONTAINER(buttonChild),
michael@0 306 moz_gtk_get_combo_box_button_inner_widgets,
michael@0 307 NULL);
michael@0 308 } else if(GTK_IS_ARROW(buttonChild)) {
michael@0 309 /* appears-as-list = TRUE, or cell-view = FALSE;
michael@0 310 * the button only contains an arrow */
michael@0 311 gComboBoxArrowWidget = buttonChild;
michael@0 312 g_object_add_weak_pointer(G_OBJECT(buttonChild), (gpointer)
michael@0 313 &gComboBoxArrowWidget);
michael@0 314 gtk_widget_realize(gComboBoxArrowWidget);
michael@0 315 g_object_set_data(G_OBJECT(gComboBoxArrowWidget),
michael@0 316 "transparent-bg-hint", GINT_TO_POINTER(TRUE));
michael@0 317 }
michael@0 318 } else {
michael@0 319 /* Shouldn't be reached with current internal gtk implementation; we
michael@0 320 * use a generic toggle button as last resort fallback to avoid
michael@0 321 * crashing. */
michael@0 322 ensure_toggle_button_widget();
michael@0 323 gComboBoxButtonWidget = gToggleButtonWidget;
michael@0 324 }
michael@0 325
michael@0 326 if (!gComboBoxArrowWidget) {
michael@0 327 /* Shouldn't be reached with current internal gtk implementation;
michael@0 328 * we gButtonArrowWidget as last resort fallback to avoid
michael@0 329 * crashing. */
michael@0 330 ensure_button_arrow_widget();
michael@0 331 gComboBoxArrowWidget = gButtonArrowWidget;
michael@0 332 }
michael@0 333
michael@0 334 /* We don't test the validity of gComboBoxSeparatorWidget since there
michael@0 335 * is none when "appears-as-list" = TRUE or "cell-view" = FALSE; if it
michael@0 336 * is invalid we just won't paint it. */
michael@0 337
michael@0 338 return MOZ_GTK_SUCCESS;
michael@0 339 }
michael@0 340
michael@0 341 /* We need to have pointers to the inner widgets (entry, button, arrow) of
michael@0 342 * the ComboBoxEntry to get the correct rendering from theme engines which
michael@0 343 * special cases their look. Since the inner layout can change, we ask GTK
michael@0 344 * to NULL our pointers when they are about to become invalid because the
michael@0 345 * corresponding widgets don't exist anymore. It's the role of
michael@0 346 * g_object_add_weak_pointer().
michael@0 347 * Note that if we don't find the inner widgets (which shouldn't happen), we
michael@0 348 * fallback to use generic "non-inner" widgets, and they don't need that kind
michael@0 349 * of weak pointer since they are explicit children of gProtoWindow and as
michael@0 350 * such GTK holds a strong reference to them. */
michael@0 351 static void
michael@0 352 moz_gtk_get_combo_box_entry_inner_widgets(GtkWidget *widget,
michael@0 353 gpointer client_data)
michael@0 354 {
michael@0 355 if (GTK_IS_TOGGLE_BUTTON(widget)) {
michael@0 356 gComboBoxEntryButtonWidget = widget;
michael@0 357 g_object_add_weak_pointer(G_OBJECT(widget),
michael@0 358 (gpointer) &gComboBoxEntryButtonWidget);
michael@0 359 } else if (GTK_IS_ENTRY(widget)) {
michael@0 360 gComboBoxEntryTextareaWidget = widget;
michael@0 361 g_object_add_weak_pointer(G_OBJECT(widget),
michael@0 362 (gpointer) &gComboBoxEntryTextareaWidget);
michael@0 363 } else
michael@0 364 return;
michael@0 365 gtk_widget_realize(widget);
michael@0 366 g_object_set_data(G_OBJECT(widget), "transparent-bg-hint", GINT_TO_POINTER(TRUE));
michael@0 367 }
michael@0 368
michael@0 369 static void
michael@0 370 moz_gtk_get_combo_box_entry_arrow(GtkWidget *widget, gpointer client_data)
michael@0 371 {
michael@0 372 if (GTK_IS_ARROW(widget)) {
michael@0 373 gComboBoxEntryArrowWidget = widget;
michael@0 374 g_object_add_weak_pointer(G_OBJECT(widget),
michael@0 375 (gpointer) &gComboBoxEntryArrowWidget);
michael@0 376 gtk_widget_realize(widget);
michael@0 377 g_object_set_data(G_OBJECT(widget), "transparent-bg-hint", GINT_TO_POINTER(TRUE));
michael@0 378 }
michael@0 379 }
michael@0 380
michael@0 381 static gint
michael@0 382 ensure_combo_box_entry_widgets()
michael@0 383 {
michael@0 384 GtkWidget* buttonChild;
michael@0 385
michael@0 386 if (gComboBoxEntryTextareaWidget &&
michael@0 387 gComboBoxEntryButtonWidget &&
michael@0 388 gComboBoxEntryArrowWidget)
michael@0 389 return MOZ_GTK_SUCCESS;
michael@0 390
michael@0 391 /* Create a ComboBoxEntry if needed */
michael@0 392 if (!gComboBoxEntryWidget) {
michael@0 393 gComboBoxEntryWidget = gtk_combo_box_entry_new();
michael@0 394 setup_widget_prototype(gComboBoxEntryWidget);
michael@0 395 }
michael@0 396
michael@0 397 /* Get its inner Entry and Button */
michael@0 398 gtk_container_forall(GTK_CONTAINER(gComboBoxEntryWidget),
michael@0 399 moz_gtk_get_combo_box_entry_inner_widgets,
michael@0 400 NULL);
michael@0 401
michael@0 402 if (!gComboBoxEntryTextareaWidget) {
michael@0 403 ensure_entry_widget();
michael@0 404 gComboBoxEntryTextareaWidget = gEntryWidget;
michael@0 405 }
michael@0 406
michael@0 407 if (gComboBoxEntryButtonWidget) {
michael@0 408 /* Get the Arrow inside the Button */
michael@0 409 buttonChild = GTK_BIN(gComboBoxEntryButtonWidget)->child;
michael@0 410 if (GTK_IS_HBOX(buttonChild)) {
michael@0 411 /* appears-as-list = FALSE, cell-view = TRUE; the button
michael@0 412 * contains an hbox. This hbox is there because ComboBoxEntry
michael@0 413 * inherits from ComboBox which needs to place a cell renderer,
michael@0 414 * a separator, and an arrow in the button when appears-as-list
michael@0 415 * is FALSE. Here the hbox should only contain an arrow, since
michael@0 416 * a ComboBoxEntry doesn't need all those widgets in the
michael@0 417 * button. */
michael@0 418 gtk_container_forall(GTK_CONTAINER(buttonChild),
michael@0 419 moz_gtk_get_combo_box_entry_arrow,
michael@0 420 NULL);
michael@0 421 } else if(GTK_IS_ARROW(buttonChild)) {
michael@0 422 /* appears-as-list = TRUE, or cell-view = FALSE;
michael@0 423 * the button only contains an arrow */
michael@0 424 gComboBoxEntryArrowWidget = buttonChild;
michael@0 425 g_object_add_weak_pointer(G_OBJECT(buttonChild), (gpointer)
michael@0 426 &gComboBoxEntryArrowWidget);
michael@0 427 gtk_widget_realize(gComboBoxEntryArrowWidget);
michael@0 428 g_object_set_data(G_OBJECT(gComboBoxEntryArrowWidget),
michael@0 429 "transparent-bg-hint", GINT_TO_POINTER(TRUE));
michael@0 430 }
michael@0 431 } else {
michael@0 432 /* Shouldn't be reached with current internal gtk implementation;
michael@0 433 * we use a generic toggle button as last resort fallback to avoid
michael@0 434 * crashing. */
michael@0 435 ensure_toggle_button_widget();
michael@0 436 gComboBoxEntryButtonWidget = gToggleButtonWidget;
michael@0 437 }
michael@0 438
michael@0 439 if (!gComboBoxEntryArrowWidget) {
michael@0 440 /* Shouldn't be reached with current internal gtk implementation;
michael@0 441 * we gButtonArrowWidget as last resort fallback to avoid
michael@0 442 * crashing. */
michael@0 443 ensure_button_arrow_widget();
michael@0 444 gComboBoxEntryArrowWidget = gButtonArrowWidget;
michael@0 445 }
michael@0 446
michael@0 447 return MOZ_GTK_SUCCESS;
michael@0 448 }
michael@0 449
michael@0 450
michael@0 451 static gint
michael@0 452 ensure_handlebox_widget()
michael@0 453 {
michael@0 454 if (!gHandleBoxWidget) {
michael@0 455 gHandleBoxWidget = gtk_handle_box_new();
michael@0 456 setup_widget_prototype(gHandleBoxWidget);
michael@0 457 }
michael@0 458 return MOZ_GTK_SUCCESS;
michael@0 459 }
michael@0 460
michael@0 461 static gint
michael@0 462 ensure_toolbar_widget()
michael@0 463 {
michael@0 464 if (!gToolbarWidget) {
michael@0 465 ensure_handlebox_widget();
michael@0 466 gToolbarWidget = gtk_toolbar_new();
michael@0 467 gtk_container_add(GTK_CONTAINER(gHandleBoxWidget), gToolbarWidget);
michael@0 468 gtk_widget_realize(gToolbarWidget);
michael@0 469 g_object_set_data(G_OBJECT(gToolbarWidget), "transparent-bg-hint", GINT_TO_POINTER(TRUE));
michael@0 470 }
michael@0 471 return MOZ_GTK_SUCCESS;
michael@0 472 }
michael@0 473
michael@0 474 static gint
michael@0 475 ensure_toolbar_separator_widget()
michael@0 476 {
michael@0 477 if (!gToolbarSeparatorWidget) {
michael@0 478 ensure_toolbar_widget();
michael@0 479 gToolbarSeparatorWidget = GTK_WIDGET(gtk_separator_tool_item_new());
michael@0 480 setup_widget_prototype(gToolbarSeparatorWidget);
michael@0 481 }
michael@0 482 return MOZ_GTK_SUCCESS;
michael@0 483 }
michael@0 484
michael@0 485 static gint
michael@0 486 ensure_tooltip_widget()
michael@0 487 {
michael@0 488 if (!gTooltipWidget) {
michael@0 489 gTooltipWidget = gtk_window_new(GTK_WINDOW_POPUP);
michael@0 490 gtk_widget_realize(gTooltipWidget);
michael@0 491 moz_gtk_set_widget_name(gTooltipWidget);
michael@0 492 }
michael@0 493 return MOZ_GTK_SUCCESS;
michael@0 494 }
michael@0 495
michael@0 496 static gint
michael@0 497 ensure_tab_widget()
michael@0 498 {
michael@0 499 if (!gTabWidget) {
michael@0 500 gTabWidget = gtk_notebook_new();
michael@0 501 setup_widget_prototype(gTabWidget);
michael@0 502 }
michael@0 503 return MOZ_GTK_SUCCESS;
michael@0 504 }
michael@0 505
michael@0 506 static gint
michael@0 507 ensure_progress_widget()
michael@0 508 {
michael@0 509 if (!gProgressWidget) {
michael@0 510 gProgressWidget = gtk_progress_bar_new();
michael@0 511 setup_widget_prototype(gProgressWidget);
michael@0 512 }
michael@0 513 return MOZ_GTK_SUCCESS;
michael@0 514 }
michael@0 515
michael@0 516 static gint
michael@0 517 ensure_statusbar_widget()
michael@0 518 {
michael@0 519 if (!gStatusbarWidget) {
michael@0 520 gStatusbarWidget = gtk_statusbar_new();
michael@0 521 setup_widget_prototype(gStatusbarWidget);
michael@0 522 }
michael@0 523 return MOZ_GTK_SUCCESS;
michael@0 524 }
michael@0 525
michael@0 526 static gint
michael@0 527 ensure_frame_widget()
michael@0 528 {
michael@0 529 if (!gFrameWidget) {
michael@0 530 ensure_statusbar_widget();
michael@0 531 gFrameWidget = gtk_frame_new(NULL);
michael@0 532 gtk_container_add(GTK_CONTAINER(gStatusbarWidget), gFrameWidget);
michael@0 533 gtk_widget_realize(gFrameWidget);
michael@0 534 }
michael@0 535 return MOZ_GTK_SUCCESS;
michael@0 536 }
michael@0 537
michael@0 538 static gint
michael@0 539 ensure_menu_bar_widget()
michael@0 540 {
michael@0 541 if (!gMenuBarWidget) {
michael@0 542 gMenuBarWidget = gtk_menu_bar_new();
michael@0 543 setup_widget_prototype(gMenuBarWidget);
michael@0 544 }
michael@0 545 return MOZ_GTK_SUCCESS;
michael@0 546 }
michael@0 547
michael@0 548 static gint
michael@0 549 ensure_menu_bar_item_widget()
michael@0 550 {
michael@0 551 if (!gMenuBarItemWidget) {
michael@0 552 ensure_menu_bar_widget();
michael@0 553 gMenuBarItemWidget = gtk_menu_item_new();
michael@0 554 gtk_menu_shell_append(GTK_MENU_SHELL(gMenuBarWidget),
michael@0 555 gMenuBarItemWidget);
michael@0 556 gtk_widget_realize(gMenuBarItemWidget);
michael@0 557 g_object_set_data(G_OBJECT(gMenuBarItemWidget),
michael@0 558 "transparent-bg-hint", GINT_TO_POINTER(TRUE));
michael@0 559 }
michael@0 560 return MOZ_GTK_SUCCESS;
michael@0 561 }
michael@0 562
michael@0 563 static gint
michael@0 564 ensure_menu_popup_widget()
michael@0 565 {
michael@0 566 if (!gMenuPopupWidget) {
michael@0 567 ensure_menu_bar_item_widget();
michael@0 568 gMenuPopupWidget = gtk_menu_new();
michael@0 569 gtk_menu_item_set_submenu(GTK_MENU_ITEM(gMenuBarItemWidget),
michael@0 570 gMenuPopupWidget);
michael@0 571 gtk_widget_realize(gMenuPopupWidget);
michael@0 572 g_object_set_data(G_OBJECT(gMenuPopupWidget),
michael@0 573 "transparent-bg-hint", GINT_TO_POINTER(TRUE));
michael@0 574 }
michael@0 575 return MOZ_GTK_SUCCESS;
michael@0 576 }
michael@0 577
michael@0 578 static gint
michael@0 579 ensure_menu_item_widget()
michael@0 580 {
michael@0 581 if (!gMenuItemWidget) {
michael@0 582 ensure_menu_popup_widget();
michael@0 583 gMenuItemWidget = gtk_menu_item_new_with_label("M");
michael@0 584 gtk_menu_shell_append(GTK_MENU_SHELL(gMenuPopupWidget),
michael@0 585 gMenuItemWidget);
michael@0 586 gtk_widget_realize(gMenuItemWidget);
michael@0 587 g_object_set_data(G_OBJECT(gMenuItemWidget),
michael@0 588 "transparent-bg-hint", GINT_TO_POINTER(TRUE));
michael@0 589 }
michael@0 590 return MOZ_GTK_SUCCESS;
michael@0 591 }
michael@0 592
michael@0 593 static gint
michael@0 594 ensure_image_menu_item_widget()
michael@0 595 {
michael@0 596 if (!gImageMenuItemWidget) {
michael@0 597 ensure_menu_popup_widget();
michael@0 598 gImageMenuItemWidget = gtk_image_menu_item_new();
michael@0 599 gtk_menu_shell_append(GTK_MENU_SHELL(gMenuPopupWidget),
michael@0 600 gImageMenuItemWidget);
michael@0 601 gtk_widget_realize(gImageMenuItemWidget);
michael@0 602 g_object_set_data(G_OBJECT(gImageMenuItemWidget),
michael@0 603 "transparent-bg-hint", GINT_TO_POINTER(TRUE));
michael@0 604 }
michael@0 605 return MOZ_GTK_SUCCESS;
michael@0 606 }
michael@0 607
michael@0 608 static gint
michael@0 609 ensure_menu_separator_widget()
michael@0 610 {
michael@0 611 if (!gMenuSeparatorWidget) {
michael@0 612 ensure_menu_popup_widget();
michael@0 613 gMenuSeparatorWidget = gtk_separator_menu_item_new();
michael@0 614 gtk_menu_shell_append(GTK_MENU_SHELL(gMenuPopupWidget),
michael@0 615 gMenuSeparatorWidget);
michael@0 616 gtk_widget_realize(gMenuSeparatorWidget);
michael@0 617 g_object_set_data(G_OBJECT(gMenuSeparatorWidget),
michael@0 618 "transparent-bg-hint", GINT_TO_POINTER(TRUE));
michael@0 619 }
michael@0 620 return MOZ_GTK_SUCCESS;
michael@0 621 }
michael@0 622
michael@0 623 static gint
michael@0 624 ensure_check_menu_item_widget()
michael@0 625 {
michael@0 626 if (!gCheckMenuItemWidget) {
michael@0 627 ensure_menu_popup_widget();
michael@0 628 gCheckMenuItemWidget = gtk_check_menu_item_new_with_label("M");
michael@0 629 gtk_menu_shell_append(GTK_MENU_SHELL(gMenuPopupWidget),
michael@0 630 gCheckMenuItemWidget);
michael@0 631 gtk_widget_realize(gCheckMenuItemWidget);
michael@0 632 g_object_set_data(G_OBJECT(gCheckMenuItemWidget),
michael@0 633 "transparent-bg-hint", GINT_TO_POINTER(TRUE));
michael@0 634 }
michael@0 635 return MOZ_GTK_SUCCESS;
michael@0 636 }
michael@0 637
michael@0 638 static gint
michael@0 639 ensure_tree_view_widget()
michael@0 640 {
michael@0 641 if (!gTreeViewWidget) {
michael@0 642 gTreeViewWidget = gtk_tree_view_new();
michael@0 643 setup_widget_prototype(gTreeViewWidget);
michael@0 644 }
michael@0 645 return MOZ_GTK_SUCCESS;
michael@0 646 }
michael@0 647
michael@0 648 static gint
michael@0 649 ensure_tree_header_cell_widget()
michael@0 650 {
michael@0 651 if(!gTreeHeaderCellWidget) {
michael@0 652 /*
michael@0 653 * Some GTK engines paint the first and last cell
michael@0 654 * of a TreeView header with a highlight.
michael@0 655 * Since we do not know where our widget will be relative
michael@0 656 * to the other buttons in the TreeView header, we must
michael@0 657 * paint it as a button that is between two others,
michael@0 658 * thus ensuring it is neither the first or last button
michael@0 659 * in the header.
michael@0 660 * GTK doesn't give us a way to do this explicitly,
michael@0 661 * so we must paint with a button that is between two
michael@0 662 * others.
michael@0 663 */
michael@0 664
michael@0 665 GtkTreeViewColumn* firstTreeViewColumn;
michael@0 666 GtkTreeViewColumn* lastTreeViewColumn;
michael@0 667
michael@0 668 ensure_tree_view_widget();
michael@0 669
michael@0 670 /* Create and append our three columns */
michael@0 671 firstTreeViewColumn = gtk_tree_view_column_new();
michael@0 672 gtk_tree_view_column_set_title(firstTreeViewColumn, "M");
michael@0 673 gtk_tree_view_append_column(GTK_TREE_VIEW(gTreeViewWidget), firstTreeViewColumn);
michael@0 674
michael@0 675 gMiddleTreeViewColumn = gtk_tree_view_column_new();
michael@0 676 gtk_tree_view_column_set_title(gMiddleTreeViewColumn, "M");
michael@0 677 gtk_tree_view_append_column(GTK_TREE_VIEW(gTreeViewWidget),
michael@0 678 gMiddleTreeViewColumn);
michael@0 679
michael@0 680 lastTreeViewColumn = gtk_tree_view_column_new();
michael@0 681 gtk_tree_view_column_set_title(lastTreeViewColumn, "M");
michael@0 682 gtk_tree_view_append_column(GTK_TREE_VIEW(gTreeViewWidget), lastTreeViewColumn);
michael@0 683
michael@0 684 /* Use the middle column's header for our button */
michael@0 685 gTreeHeaderCellWidget = gMiddleTreeViewColumn->button;
michael@0 686 gTreeHeaderSortArrowWidget = gMiddleTreeViewColumn->arrow;
michael@0 687 g_object_set_data(G_OBJECT(gTreeHeaderCellWidget),
michael@0 688 "transparent-bg-hint", GINT_TO_POINTER(TRUE));
michael@0 689 g_object_set_data(G_OBJECT(gTreeHeaderSortArrowWidget),
michael@0 690 "transparent-bg-hint", GINT_TO_POINTER(TRUE));
michael@0 691 }
michael@0 692 return MOZ_GTK_SUCCESS;
michael@0 693 }
michael@0 694
michael@0 695 static gint
michael@0 696 ensure_expander_widget()
michael@0 697 {
michael@0 698 if (!gExpanderWidget) {
michael@0 699 gExpanderWidget = gtk_expander_new("M");
michael@0 700 setup_widget_prototype(gExpanderWidget);
michael@0 701 }
michael@0 702 return MOZ_GTK_SUCCESS;
michael@0 703 }
michael@0 704
michael@0 705 static gint
michael@0 706 ensure_scrolled_window_widget()
michael@0 707 {
michael@0 708 if (!gScrolledWindowWidget) {
michael@0 709 gScrolledWindowWidget = gtk_scrolled_window_new(NULL, NULL);
michael@0 710 setup_widget_prototype(gScrolledWindowWidget);
michael@0 711 }
michael@0 712 return MOZ_GTK_SUCCESS;
michael@0 713 }
michael@0 714
michael@0 715 static GtkStateType
michael@0 716 ConvertGtkState(GtkWidgetState* state)
michael@0 717 {
michael@0 718 if (state->disabled)
michael@0 719 return GTK_STATE_INSENSITIVE;
michael@0 720 else if (state->depressed)
michael@0 721 return (state->inHover ? GTK_STATE_PRELIGHT : GTK_STATE_ACTIVE);
michael@0 722 else if (state->inHover)
michael@0 723 return (state->active ? GTK_STATE_ACTIVE : GTK_STATE_PRELIGHT);
michael@0 724 else
michael@0 725 return GTK_STATE_NORMAL;
michael@0 726 }
michael@0 727
michael@0 728 static gint
michael@0 729 TSOffsetStyleGCArray(GdkGC** gcs, gint xorigin, gint yorigin)
michael@0 730 {
michael@0 731 int i;
michael@0 732 /* there are 5 gc's in each array, for each of the widget states */
michael@0 733 for (i = 0; i < 5; ++i)
michael@0 734 gdk_gc_set_ts_origin(gcs[i], xorigin, yorigin);
michael@0 735 return MOZ_GTK_SUCCESS;
michael@0 736 }
michael@0 737
michael@0 738 static gint
michael@0 739 TSOffsetStyleGCs(GtkStyle* style, gint xorigin, gint yorigin)
michael@0 740 {
michael@0 741 TSOffsetStyleGCArray(style->fg_gc, xorigin, yorigin);
michael@0 742 TSOffsetStyleGCArray(style->bg_gc, xorigin, yorigin);
michael@0 743 TSOffsetStyleGCArray(style->light_gc, xorigin, yorigin);
michael@0 744 TSOffsetStyleGCArray(style->dark_gc, xorigin, yorigin);
michael@0 745 TSOffsetStyleGCArray(style->mid_gc, xorigin, yorigin);
michael@0 746 TSOffsetStyleGCArray(style->text_gc, xorigin, yorigin);
michael@0 747 TSOffsetStyleGCArray(style->base_gc, xorigin, yorigin);
michael@0 748 gdk_gc_set_ts_origin(style->black_gc, xorigin, yorigin);
michael@0 749 gdk_gc_set_ts_origin(style->white_gc, xorigin, yorigin);
michael@0 750 return MOZ_GTK_SUCCESS;
michael@0 751 }
michael@0 752
michael@0 753 gint
michael@0 754 moz_gtk_init()
michael@0 755 {
michael@0 756 GtkWidgetClass *entry_class;
michael@0 757
michael@0 758 if (is_initialized)
michael@0 759 return MOZ_GTK_SUCCESS;
michael@0 760
michael@0 761 is_initialized = TRUE;
michael@0 762 have_arrow_scaling = (gtk_major_version > 2 ||
michael@0 763 (gtk_major_version == 2 && gtk_minor_version >= 12));
michael@0 764
michael@0 765 /* Add style property to GtkEntry.
michael@0 766 * Adding the style property to the normal GtkEntry class means that it
michael@0 767 * will work without issues inside GtkComboBox and for Spinbuttons. */
michael@0 768 entry_class = g_type_class_ref(GTK_TYPE_ENTRY);
michael@0 769 gtk_widget_class_install_style_property(entry_class,
michael@0 770 g_param_spec_boolean("honors-transparent-bg-hint",
michael@0 771 "Transparent BG enabling flag",
michael@0 772 "If TRUE, the theme is able to draw the GtkEntry on non-prefilled background.",
michael@0 773 FALSE,
michael@0 774 G_PARAM_READWRITE));
michael@0 775
michael@0 776 return MOZ_GTK_SUCCESS;
michael@0 777 }
michael@0 778
michael@0 779 GdkColormap*
michael@0 780 moz_gtk_widget_get_colormap()
michael@0 781 {
michael@0 782 /* Child widgets inherit the colormap from the GtkWindow. */
michael@0 783 ensure_window_widget();
michael@0 784 return gtk_widget_get_colormap(gProtoWindow);
michael@0 785 }
michael@0 786
michael@0 787 gint
michael@0 788 moz_gtk_checkbox_get_metrics(gint* indicator_size, gint* indicator_spacing)
michael@0 789 {
michael@0 790 ensure_checkbox_widget();
michael@0 791
michael@0 792 gtk_widget_style_get (gCheckboxWidget,
michael@0 793 "indicator_size", indicator_size,
michael@0 794 "indicator_spacing", indicator_spacing,
michael@0 795 NULL);
michael@0 796
michael@0 797 return MOZ_GTK_SUCCESS;
michael@0 798 }
michael@0 799
michael@0 800 gint
michael@0 801 moz_gtk_radio_get_metrics(gint* indicator_size, gint* indicator_spacing)
michael@0 802 {
michael@0 803 ensure_radiobutton_widget();
michael@0 804
michael@0 805 gtk_widget_style_get (gRadiobuttonWidget,
michael@0 806 "indicator_size", indicator_size,
michael@0 807 "indicator_spacing", indicator_spacing,
michael@0 808 NULL);
michael@0 809
michael@0 810 return MOZ_GTK_SUCCESS;
michael@0 811 }
michael@0 812
michael@0 813 gint
michael@0 814 moz_gtk_widget_get_focus(GtkWidget* widget, gboolean* interior_focus,
michael@0 815 gint* focus_width, gint* focus_pad)
michael@0 816 {
michael@0 817 gtk_widget_style_get (widget,
michael@0 818 "interior-focus", interior_focus,
michael@0 819 "focus-line-width", focus_width,
michael@0 820 "focus-padding", focus_pad,
michael@0 821 NULL);
michael@0 822
michael@0 823 return MOZ_GTK_SUCCESS;
michael@0 824 }
michael@0 825
michael@0 826 gint
michael@0 827 moz_gtk_menuitem_get_horizontal_padding(gint* horizontal_padding)
michael@0 828 {
michael@0 829 ensure_menu_item_widget();
michael@0 830
michael@0 831 gtk_widget_style_get (gMenuItemWidget,
michael@0 832 "horizontal-padding", horizontal_padding,
michael@0 833 NULL);
michael@0 834
michael@0 835 return MOZ_GTK_SUCCESS;
michael@0 836 }
michael@0 837
michael@0 838 gint
michael@0 839 moz_gtk_checkmenuitem_get_horizontal_padding(gint* horizontal_padding)
michael@0 840 {
michael@0 841 ensure_check_menu_item_widget();
michael@0 842
michael@0 843 gtk_widget_style_get (gCheckMenuItemWidget,
michael@0 844 "horizontal-padding", horizontal_padding,
michael@0 845 NULL);
michael@0 846
michael@0 847 return MOZ_GTK_SUCCESS;
michael@0 848 }
michael@0 849
michael@0 850 gint
michael@0 851 moz_gtk_button_get_default_overflow(gint* border_top, gint* border_left,
michael@0 852 gint* border_bottom, gint* border_right)
michael@0 853 {
michael@0 854 GtkBorder* default_outside_border;
michael@0 855
michael@0 856 ensure_button_widget();
michael@0 857 gtk_widget_style_get(gButtonWidget,
michael@0 858 "default-outside-border", &default_outside_border,
michael@0 859 NULL);
michael@0 860
michael@0 861 if (default_outside_border) {
michael@0 862 *border_top = default_outside_border->top;
michael@0 863 *border_left = default_outside_border->left;
michael@0 864 *border_bottom = default_outside_border->bottom;
michael@0 865 *border_right = default_outside_border->right;
michael@0 866 gtk_border_free(default_outside_border);
michael@0 867 } else {
michael@0 868 *border_top = *border_left = *border_bottom = *border_right = 0;
michael@0 869 }
michael@0 870 return MOZ_GTK_SUCCESS;
michael@0 871 }
michael@0 872
michael@0 873 static gint
michael@0 874 moz_gtk_button_get_default_border(gint* border_top, gint* border_left,
michael@0 875 gint* border_bottom, gint* border_right)
michael@0 876 {
michael@0 877 GtkBorder* default_border;
michael@0 878
michael@0 879 ensure_button_widget();
michael@0 880 gtk_widget_style_get(gButtonWidget,
michael@0 881 "default-border", &default_border,
michael@0 882 NULL);
michael@0 883
michael@0 884 if (default_border) {
michael@0 885 *border_top = default_border->top;
michael@0 886 *border_left = default_border->left;
michael@0 887 *border_bottom = default_border->bottom;
michael@0 888 *border_right = default_border->right;
michael@0 889 gtk_border_free(default_border);
michael@0 890 } else {
michael@0 891 /* see gtkbutton.c */
michael@0 892 *border_top = *border_left = *border_bottom = *border_right = 1;
michael@0 893 }
michael@0 894 return MOZ_GTK_SUCCESS;
michael@0 895 }
michael@0 896
michael@0 897 gint
michael@0 898 moz_gtk_splitter_get_metrics(gint orientation, gint* size)
michael@0 899 {
michael@0 900 if (orientation == GTK_ORIENTATION_HORIZONTAL) {
michael@0 901 ensure_hpaned_widget();
michael@0 902 gtk_widget_style_get(gHPanedWidget, "handle_size", size, NULL);
michael@0 903 } else {
michael@0 904 ensure_vpaned_widget();
michael@0 905 gtk_widget_style_get(gVPanedWidget, "handle_size", size, NULL);
michael@0 906 }
michael@0 907 return MOZ_GTK_SUCCESS;
michael@0 908 }
michael@0 909
michael@0 910 gint
michael@0 911 moz_gtk_button_get_inner_border(GtkWidget* widget, GtkBorder* inner_border)
michael@0 912 {
michael@0 913 static const GtkBorder default_inner_border = { 1, 1, 1, 1 };
michael@0 914 GtkBorder *tmp_border;
michael@0 915
michael@0 916 gtk_widget_style_get (widget, "inner-border", &tmp_border, NULL);
michael@0 917
michael@0 918 if (tmp_border) {
michael@0 919 *inner_border = *tmp_border;
michael@0 920 gtk_border_free(tmp_border);
michael@0 921 }
michael@0 922 else
michael@0 923 *inner_border = default_inner_border;
michael@0 924
michael@0 925 return MOZ_GTK_SUCCESS;
michael@0 926 }
michael@0 927
michael@0 928 static gint
michael@0 929 moz_gtk_button_paint(GdkDrawable* drawable, GdkRectangle* rect,
michael@0 930 GdkRectangle* cliprect, GtkWidgetState* state,
michael@0 931 GtkReliefStyle relief, GtkWidget* widget,
michael@0 932 GtkTextDirection direction)
michael@0 933 {
michael@0 934 GtkShadowType shadow_type;
michael@0 935 GtkStyle* style = widget->style;
michael@0 936 GtkStateType button_state = ConvertGtkState(state);
michael@0 937 gint x = rect->x, y=rect->y, width=rect->width, height=rect->height;
michael@0 938
michael@0 939 gboolean interior_focus;
michael@0 940 gint focus_width, focus_pad;
michael@0 941
michael@0 942 moz_gtk_widget_get_focus(widget, &interior_focus, &focus_width, &focus_pad);
michael@0 943
michael@0 944 if (WINDOW_IS_MAPPED(drawable)) {
michael@0 945 gdk_window_set_back_pixmap(drawable, NULL, TRUE);
michael@0 946 gdk_window_clear_area(drawable, cliprect->x, cliprect->y,
michael@0 947 cliprect->width, cliprect->height);
michael@0 948 }
michael@0 949
michael@0 950 gtk_widget_set_state(widget, button_state);
michael@0 951 gtk_widget_set_direction(widget, direction);
michael@0 952
michael@0 953 if (state->isDefault)
michael@0 954 GTK_WIDGET_SET_FLAGS(widget, GTK_HAS_DEFAULT);
michael@0 955
michael@0 956 GTK_BUTTON(widget)->relief = relief;
michael@0 957
michael@0 958 /* Some theme engines love to cause us pain in that gtk_paint_focus is a
michael@0 959 no-op on buttons and button-like widgets. They only listen to this flag. */
michael@0 960 if (state->focused && !state->disabled)
michael@0 961 GTK_WIDGET_SET_FLAGS(widget, GTK_HAS_FOCUS);
michael@0 962
michael@0 963 if (!interior_focus && state->focused) {
michael@0 964 x += focus_width + focus_pad;
michael@0 965 y += focus_width + focus_pad;
michael@0 966 width -= 2 * (focus_width + focus_pad);
michael@0 967 height -= 2 * (focus_width + focus_pad);
michael@0 968 }
michael@0 969
michael@0 970 shadow_type = button_state == GTK_STATE_ACTIVE ||
michael@0 971 state->depressed ? GTK_SHADOW_IN : GTK_SHADOW_OUT;
michael@0 972
michael@0 973 if (state->isDefault && relief == GTK_RELIEF_NORMAL) {
michael@0 974 /* handle default borders both outside and inside the button */
michael@0 975 gint default_top, default_left, default_bottom, default_right;
michael@0 976 moz_gtk_button_get_default_overflow(&default_top, &default_left,
michael@0 977 &default_bottom, &default_right);
michael@0 978 x -= default_left;
michael@0 979 y -= default_top;
michael@0 980 width += default_left + default_right;
michael@0 981 height += default_top + default_bottom;
michael@0 982 gtk_paint_box(style, drawable, GTK_STATE_NORMAL, GTK_SHADOW_IN, cliprect,
michael@0 983 widget, "buttondefault", x, y, width, height);
michael@0 984
michael@0 985 moz_gtk_button_get_default_border(&default_top, &default_left,
michael@0 986 &default_bottom, &default_right);
michael@0 987 x += default_left;
michael@0 988 y += default_top;
michael@0 989 width -= (default_left + default_right);
michael@0 990 height -= (default_top + default_bottom);
michael@0 991 }
michael@0 992
michael@0 993 if (relief != GTK_RELIEF_NONE || state->depressed ||
michael@0 994 (button_state != GTK_STATE_NORMAL &&
michael@0 995 button_state != GTK_STATE_INSENSITIVE)) {
michael@0 996 TSOffsetStyleGCs(style, x, y);
michael@0 997 /* the following line can trigger an assertion (Crux theme)
michael@0 998 file ../../gdk/gdkwindow.c: line 1846 (gdk_window_clear_area):
michael@0 999 assertion `GDK_IS_WINDOW (window)' failed */
michael@0 1000 gtk_paint_box(style, drawable, button_state, shadow_type, cliprect,
michael@0 1001 widget, "button", x, y, width, height);
michael@0 1002 }
michael@0 1003
michael@0 1004 if (state->focused) {
michael@0 1005 if (interior_focus) {
michael@0 1006 x += widget->style->xthickness + focus_pad;
michael@0 1007 y += widget->style->ythickness + focus_pad;
michael@0 1008 width -= 2 * (widget->style->xthickness + focus_pad);
michael@0 1009 height -= 2 * (widget->style->ythickness + focus_pad);
michael@0 1010 } else {
michael@0 1011 x -= focus_width + focus_pad;
michael@0 1012 y -= focus_width + focus_pad;
michael@0 1013 width += 2 * (focus_width + focus_pad);
michael@0 1014 height += 2 * (focus_width + focus_pad);
michael@0 1015 }
michael@0 1016
michael@0 1017 TSOffsetStyleGCs(style, x, y);
michael@0 1018 gtk_paint_focus(style, drawable, button_state, cliprect,
michael@0 1019 widget, "button", x, y, width, height);
michael@0 1020 }
michael@0 1021
michael@0 1022 GTK_WIDGET_UNSET_FLAGS(widget, GTK_HAS_DEFAULT);
michael@0 1023 GTK_WIDGET_UNSET_FLAGS(widget, GTK_HAS_FOCUS);
michael@0 1024 return MOZ_GTK_SUCCESS;
michael@0 1025 }
michael@0 1026
michael@0 1027 static gint
michael@0 1028 moz_gtk_toggle_paint(GdkDrawable* drawable, GdkRectangle* rect,
michael@0 1029 GdkRectangle* cliprect, GtkWidgetState* state,
michael@0 1030 gboolean selected, gboolean inconsistent,
michael@0 1031 gboolean isradio, GtkTextDirection direction)
michael@0 1032 {
michael@0 1033 GtkStateType state_type = ConvertGtkState(state);
michael@0 1034 GtkShadowType shadow_type = (selected)?GTK_SHADOW_IN:GTK_SHADOW_OUT;
michael@0 1035 gint indicator_size, indicator_spacing;
michael@0 1036 gint x, y, width, height;
michael@0 1037 gint focus_x, focus_y, focus_width, focus_height;
michael@0 1038 GtkWidget *w;
michael@0 1039 GtkStyle *style;
michael@0 1040
michael@0 1041 if (isradio) {
michael@0 1042 moz_gtk_radio_get_metrics(&indicator_size, &indicator_spacing);
michael@0 1043 w = gRadiobuttonWidget;
michael@0 1044 } else {
michael@0 1045 moz_gtk_checkbox_get_metrics(&indicator_size, &indicator_spacing);
michael@0 1046 w = gCheckboxWidget;
michael@0 1047 }
michael@0 1048
michael@0 1049 // XXX we should assert rect->height >= indicator_size too
michael@0 1050 // after bug 369581 is fixed.
michael@0 1051 NS_ASSERTION(rect->width >= indicator_size,
michael@0 1052 "GetMinimumWidgetSize was ignored");
michael@0 1053
michael@0 1054 // Paint it center aligned in the rect.
michael@0 1055 x = rect->x + (rect->width - indicator_size) / 2;
michael@0 1056 y = rect->y + (rect->height - indicator_size) / 2;
michael@0 1057 width = indicator_size;
michael@0 1058 height = indicator_size;
michael@0 1059
michael@0 1060 focus_x = x - indicator_spacing;
michael@0 1061 focus_y = y - indicator_spacing;
michael@0 1062 focus_width = width + 2 * indicator_spacing;
michael@0 1063 focus_height = height + 2 * indicator_spacing;
michael@0 1064
michael@0 1065 style = w->style;
michael@0 1066 TSOffsetStyleGCs(style, x, y);
michael@0 1067
michael@0 1068 gtk_widget_set_sensitive(w, !state->disabled);
michael@0 1069 gtk_widget_set_direction(w, direction);
michael@0 1070 GTK_TOGGLE_BUTTON(w)->active = selected;
michael@0 1071
michael@0 1072 if (isradio) {
michael@0 1073 gtk_paint_option(style, drawable, state_type, shadow_type, cliprect,
michael@0 1074 gRadiobuttonWidget, "radiobutton", x, y,
michael@0 1075 width, height);
michael@0 1076 if (state->focused) {
michael@0 1077 gtk_paint_focus(style, drawable, GTK_STATE_ACTIVE, cliprect,
michael@0 1078 gRadiobuttonWidget, "radiobutton", focus_x, focus_y,
michael@0 1079 focus_width, focus_height);
michael@0 1080 }
michael@0 1081 }
michael@0 1082 else {
michael@0 1083 /*
michael@0 1084 * 'indeterminate' type on checkboxes. In GTK, the shadow type
michael@0 1085 * must also be changed for the state to be drawn.
michael@0 1086 */
michael@0 1087 if (inconsistent) {
michael@0 1088 gtk_toggle_button_set_inconsistent(GTK_TOGGLE_BUTTON(gCheckboxWidget), TRUE);
michael@0 1089 shadow_type = GTK_SHADOW_ETCHED_IN;
michael@0 1090 } else {
michael@0 1091 gtk_toggle_button_set_inconsistent(GTK_TOGGLE_BUTTON(gCheckboxWidget), FALSE);
michael@0 1092 }
michael@0 1093
michael@0 1094 gtk_paint_check(style, drawable, state_type, shadow_type, cliprect,
michael@0 1095 gCheckboxWidget, "checkbutton", x, y, width, height);
michael@0 1096 if (state->focused) {
michael@0 1097 gtk_paint_focus(style, drawable, GTK_STATE_ACTIVE, cliprect,
michael@0 1098 gCheckboxWidget, "checkbutton", focus_x, focus_y,
michael@0 1099 focus_width, focus_height);
michael@0 1100 }
michael@0 1101 }
michael@0 1102
michael@0 1103 return MOZ_GTK_SUCCESS;
michael@0 1104 }
michael@0 1105
michael@0 1106 static gint
michael@0 1107 calculate_button_inner_rect(GtkWidget* button, GdkRectangle* rect,
michael@0 1108 GdkRectangle* inner_rect,
michael@0 1109 GtkTextDirection direction,
michael@0 1110 gboolean ignore_focus)
michael@0 1111 {
michael@0 1112 GtkBorder inner_border;
michael@0 1113 gboolean interior_focus;
michael@0 1114 gint focus_width, focus_pad;
michael@0 1115 GtkStyle* style;
michael@0 1116
michael@0 1117 style = button->style;
michael@0 1118
michael@0 1119 /* This mirrors gtkbutton's child positioning */
michael@0 1120 moz_gtk_button_get_inner_border(button, &inner_border);
michael@0 1121 moz_gtk_widget_get_focus(button, &interior_focus,
michael@0 1122 &focus_width, &focus_pad);
michael@0 1123
michael@0 1124 if (ignore_focus)
michael@0 1125 focus_width = focus_pad = 0;
michael@0 1126
michael@0 1127 inner_rect->x = rect->x + XTHICKNESS(style) + focus_width + focus_pad;
michael@0 1128 inner_rect->x += direction == GTK_TEXT_DIR_LTR ?
michael@0 1129 inner_border.left : inner_border.right;
michael@0 1130 inner_rect->y = rect->y + inner_border.top + YTHICKNESS(style) +
michael@0 1131 focus_width + focus_pad;
michael@0 1132 inner_rect->width = MAX(1, rect->width - inner_border.left -
michael@0 1133 inner_border.right - (XTHICKNESS(style) + focus_pad + focus_width) * 2);
michael@0 1134 inner_rect->height = MAX(1, rect->height - inner_border.top -
michael@0 1135 inner_border.bottom - (YTHICKNESS(style) + focus_pad + focus_width) * 2);
michael@0 1136
michael@0 1137 return MOZ_GTK_SUCCESS;
michael@0 1138 }
michael@0 1139
michael@0 1140
michael@0 1141 static gint
michael@0 1142 calculate_arrow_rect(GtkWidget* arrow, GdkRectangle* rect,
michael@0 1143 GdkRectangle* arrow_rect, GtkTextDirection direction)
michael@0 1144 {
michael@0 1145 /* defined in gtkarrow.c */
michael@0 1146 gfloat arrow_scaling = 0.7;
michael@0 1147 gfloat xalign, xpad;
michael@0 1148 gint extent;
michael@0 1149 GtkMisc* misc = GTK_MISC(arrow);
michael@0 1150
michael@0 1151 if (have_arrow_scaling)
michael@0 1152 gtk_widget_style_get(arrow, "arrow_scaling", &arrow_scaling, NULL);
michael@0 1153
michael@0 1154 extent = MIN((rect->width - misc->xpad * 2),
michael@0 1155 (rect->height - misc->ypad * 2)) * arrow_scaling;
michael@0 1156
michael@0 1157 xalign = direction == GTK_TEXT_DIR_LTR ? misc->xalign : 1.0 - misc->xalign;
michael@0 1158 xpad = misc->xpad + (rect->width - extent) * xalign;
michael@0 1159
michael@0 1160 arrow_rect->x = direction == GTK_TEXT_DIR_LTR ?
michael@0 1161 floor(rect->x + xpad) : ceil(rect->x + xpad);
michael@0 1162 arrow_rect->y = floor(rect->y + misc->ypad +
michael@0 1163 ((rect->height - extent) * misc->yalign));
michael@0 1164
michael@0 1165 arrow_rect->width = arrow_rect->height = extent;
michael@0 1166
michael@0 1167 return MOZ_GTK_SUCCESS;
michael@0 1168 }
michael@0 1169
michael@0 1170 static gint
michael@0 1171 moz_gtk_scrollbar_button_paint(GdkDrawable* drawable, GdkRectangle* rect,
michael@0 1172 GdkRectangle* cliprect, GtkWidgetState* state,
michael@0 1173 GtkScrollbarButtonFlags flags,
michael@0 1174 GtkTextDirection direction)
michael@0 1175 {
michael@0 1176 GtkStateType state_type = ConvertGtkState(state);
michael@0 1177 GtkShadowType shadow_type = (state->active) ?
michael@0 1178 GTK_SHADOW_IN : GTK_SHADOW_OUT;
michael@0 1179 GdkRectangle arrow_rect;
michael@0 1180 GtkStyle* style;
michael@0 1181 GtkWidget *scrollbar;
michael@0 1182 GtkArrowType arrow_type;
michael@0 1183 gint arrow_displacement_x, arrow_displacement_y;
michael@0 1184 const char* detail = (flags & MOZ_GTK_STEPPER_VERTICAL) ?
michael@0 1185 "vscrollbar" : "hscrollbar";
michael@0 1186
michael@0 1187 ensure_scrollbar_widget();
michael@0 1188
michael@0 1189 if (flags & MOZ_GTK_STEPPER_VERTICAL)
michael@0 1190 scrollbar = gVertScrollbarWidget;
michael@0 1191 else
michael@0 1192 scrollbar = gHorizScrollbarWidget;
michael@0 1193
michael@0 1194 gtk_widget_set_direction(scrollbar, direction);
michael@0 1195
michael@0 1196 /* Some theme engines (i.e., ClearLooks) check the scrollbar's allocation
michael@0 1197 to determine where it should paint rounded corners on the buttons.
michael@0 1198 We need to trick them into drawing the buttons the way we want them. */
michael@0 1199
michael@0 1200 scrollbar->allocation.x = rect->x;
michael@0 1201 scrollbar->allocation.y = rect->y;
michael@0 1202 scrollbar->allocation.width = rect->width;
michael@0 1203 scrollbar->allocation.height = rect->height;
michael@0 1204
michael@0 1205 if (flags & MOZ_GTK_STEPPER_VERTICAL) {
michael@0 1206 scrollbar->allocation.height *= 5;
michael@0 1207 if (flags & MOZ_GTK_STEPPER_DOWN) {
michael@0 1208 arrow_type = GTK_ARROW_DOWN;
michael@0 1209 if (flags & MOZ_GTK_STEPPER_BOTTOM)
michael@0 1210 scrollbar->allocation.y -= 4 * rect->height;
michael@0 1211 else
michael@0 1212 scrollbar->allocation.y -= rect->height;
michael@0 1213
michael@0 1214 } else {
michael@0 1215 arrow_type = GTK_ARROW_UP;
michael@0 1216 if (flags & MOZ_GTK_STEPPER_BOTTOM)
michael@0 1217 scrollbar->allocation.y -= 3 * rect->height;
michael@0 1218 }
michael@0 1219 } else {
michael@0 1220 scrollbar->allocation.width *= 5;
michael@0 1221 if (flags & MOZ_GTK_STEPPER_DOWN) {
michael@0 1222 arrow_type = GTK_ARROW_RIGHT;
michael@0 1223 if (flags & MOZ_GTK_STEPPER_BOTTOM)
michael@0 1224 scrollbar->allocation.x -= 4 * rect->width;
michael@0 1225 else
michael@0 1226 scrollbar->allocation.x -= rect->width;
michael@0 1227 } else {
michael@0 1228 arrow_type = GTK_ARROW_LEFT;
michael@0 1229 if (flags & MOZ_GTK_STEPPER_BOTTOM)
michael@0 1230 scrollbar->allocation.x -= 3 * rect->width;
michael@0 1231 }
michael@0 1232 }
michael@0 1233
michael@0 1234 style = scrollbar->style;
michael@0 1235
michael@0 1236 TSOffsetStyleGCs(style, rect->x, rect->y);
michael@0 1237
michael@0 1238 gtk_paint_box(style, drawable, state_type, shadow_type, cliprect,
michael@0 1239 scrollbar, detail, rect->x, rect->y,
michael@0 1240 rect->width, rect->height);
michael@0 1241
michael@0 1242 arrow_rect.width = rect->width / 2;
michael@0 1243 arrow_rect.height = rect->height / 2;
michael@0 1244 arrow_rect.x = rect->x + (rect->width - arrow_rect.width) / 2;
michael@0 1245 arrow_rect.y = rect->y + (rect->height - arrow_rect.height) / 2;
michael@0 1246
michael@0 1247 if (state_type == GTK_STATE_ACTIVE) {
michael@0 1248 gtk_widget_style_get(scrollbar,
michael@0 1249 "arrow-displacement-x", &arrow_displacement_x,
michael@0 1250 "arrow-displacement-y", &arrow_displacement_y,
michael@0 1251 NULL);
michael@0 1252
michael@0 1253 arrow_rect.x += arrow_displacement_x;
michael@0 1254 arrow_rect.y += arrow_displacement_y;
michael@0 1255 }
michael@0 1256
michael@0 1257 gtk_paint_arrow(style, drawable, state_type, shadow_type, cliprect,
michael@0 1258 scrollbar, detail, arrow_type, TRUE, arrow_rect.x,
michael@0 1259 arrow_rect.y, arrow_rect.width, arrow_rect.height);
michael@0 1260
michael@0 1261 return MOZ_GTK_SUCCESS;
michael@0 1262 }
michael@0 1263
michael@0 1264 static gint
michael@0 1265 moz_gtk_scrollbar_trough_paint(GtkThemeWidgetType widget,
michael@0 1266 GdkDrawable* drawable, GdkRectangle* rect,
michael@0 1267 GdkRectangle* cliprect, GtkWidgetState* state,
michael@0 1268 GtkTextDirection direction)
michael@0 1269 {
michael@0 1270 GtkStyle* style;
michael@0 1271 GtkScrollbar *scrollbar;
michael@0 1272
michael@0 1273 ensure_scrollbar_widget();
michael@0 1274
michael@0 1275 if (widget == MOZ_GTK_SCROLLBAR_TRACK_HORIZONTAL)
michael@0 1276 scrollbar = GTK_SCROLLBAR(gHorizScrollbarWidget);
michael@0 1277 else
michael@0 1278 scrollbar = GTK_SCROLLBAR(gVertScrollbarWidget);
michael@0 1279
michael@0 1280 gtk_widget_set_direction(GTK_WIDGET(scrollbar), direction);
michael@0 1281
michael@0 1282 style = GTK_WIDGET(scrollbar)->style;
michael@0 1283
michael@0 1284 TSOffsetStyleGCs(style, rect->x, rect->y);
michael@0 1285 gtk_style_apply_default_background(style, drawable, TRUE, GTK_STATE_ACTIVE,
michael@0 1286 cliprect, rect->x, rect->y,
michael@0 1287 rect->width, rect->height);
michael@0 1288
michael@0 1289 gtk_paint_box(style, drawable, GTK_STATE_ACTIVE, GTK_SHADOW_IN, cliprect,
michael@0 1290 GTK_WIDGET(scrollbar), "trough", rect->x, rect->y,
michael@0 1291 rect->width, rect->height);
michael@0 1292
michael@0 1293 if (state->focused) {
michael@0 1294 gtk_paint_focus(style, drawable, GTK_STATE_ACTIVE, cliprect,
michael@0 1295 GTK_WIDGET(scrollbar), "trough",
michael@0 1296 rect->x, rect->y, rect->width, rect->height);
michael@0 1297 }
michael@0 1298
michael@0 1299 return MOZ_GTK_SUCCESS;
michael@0 1300 }
michael@0 1301
michael@0 1302 static gint
michael@0 1303 moz_gtk_scrollbar_thumb_paint(GtkThemeWidgetType widget,
michael@0 1304 GdkDrawable* drawable, GdkRectangle* rect,
michael@0 1305 GdkRectangle* cliprect, GtkWidgetState* state,
michael@0 1306 GtkTextDirection direction)
michael@0 1307 {
michael@0 1308 GtkStateType state_type = (state->inHover || state->active) ?
michael@0 1309 GTK_STATE_PRELIGHT : GTK_STATE_NORMAL;
michael@0 1310 GtkShadowType shadow_type = GTK_SHADOW_OUT;
michael@0 1311 GtkStyle* style;
michael@0 1312 GtkScrollbar *scrollbar;
michael@0 1313 GtkAdjustment *adj;
michael@0 1314 gboolean activate_slider;
michael@0 1315
michael@0 1316 ensure_scrollbar_widget();
michael@0 1317
michael@0 1318 if (widget == MOZ_GTK_SCROLLBAR_THUMB_HORIZONTAL)
michael@0 1319 scrollbar = GTK_SCROLLBAR(gHorizScrollbarWidget);
michael@0 1320 else
michael@0 1321 scrollbar = GTK_SCROLLBAR(gVertScrollbarWidget);
michael@0 1322
michael@0 1323 gtk_widget_set_direction(GTK_WIDGET(scrollbar), direction);
michael@0 1324
michael@0 1325 /* Make sure to set the scrollbar range before painting so that
michael@0 1326 everything is drawn properly. At least the bluecurve (and
michael@0 1327 maybe other) themes don't draw the top or bottom black line
michael@0 1328 surrounding the scrollbar if the theme thinks that it's butted
michael@0 1329 up against the scrollbar arrows. Note the increases of the
michael@0 1330 clip rect below. */
michael@0 1331 adj = gtk_range_get_adjustment(GTK_RANGE(scrollbar));
michael@0 1332
michael@0 1333 if (widget == MOZ_GTK_SCROLLBAR_THUMB_HORIZONTAL) {
michael@0 1334 adj->page_size = rect->width;
michael@0 1335 }
michael@0 1336 else {
michael@0 1337 adj->page_size = rect->height;
michael@0 1338 }
michael@0 1339
michael@0 1340 adj->lower = 0;
michael@0 1341 adj->value = state->curpos;
michael@0 1342 adj->upper = state->maxpos;
michael@0 1343 gtk_adjustment_changed(adj);
michael@0 1344
michael@0 1345 style = GTK_WIDGET(scrollbar)->style;
michael@0 1346
michael@0 1347 gtk_widget_style_get(GTK_WIDGET(scrollbar), "activate-slider",
michael@0 1348 &activate_slider, NULL);
michael@0 1349
michael@0 1350 if (activate_slider && state->active) {
michael@0 1351 shadow_type = GTK_SHADOW_IN;
michael@0 1352 state_type = GTK_STATE_ACTIVE;
michael@0 1353 }
michael@0 1354
michael@0 1355 TSOffsetStyleGCs(style, rect->x, rect->y);
michael@0 1356
michael@0 1357 gtk_paint_slider(style, drawable, state_type, shadow_type, cliprect,
michael@0 1358 GTK_WIDGET(scrollbar), "slider", rect->x, rect->y,
michael@0 1359 rect->width, rect->height,
michael@0 1360 (widget == MOZ_GTK_SCROLLBAR_THUMB_HORIZONTAL) ?
michael@0 1361 GTK_ORIENTATION_HORIZONTAL : GTK_ORIENTATION_VERTICAL);
michael@0 1362
michael@0 1363 return MOZ_GTK_SUCCESS;
michael@0 1364 }
michael@0 1365
michael@0 1366 static gint
michael@0 1367 moz_gtk_spin_paint(GdkDrawable* drawable, GdkRectangle* rect,
michael@0 1368 GtkTextDirection direction)
michael@0 1369 {
michael@0 1370 GtkStyle* style;
michael@0 1371
michael@0 1372 ensure_spin_widget();
michael@0 1373 gtk_widget_set_direction(gSpinWidget, direction);
michael@0 1374 style = gSpinWidget->style;
michael@0 1375
michael@0 1376 TSOffsetStyleGCs(style, rect->x, rect->y);
michael@0 1377 gtk_paint_box(style, drawable, GTK_STATE_NORMAL, GTK_SHADOW_IN, NULL,
michael@0 1378 gSpinWidget, "spinbutton",
michael@0 1379 rect->x, rect->y, rect->width, rect->height);
michael@0 1380 return MOZ_GTK_SUCCESS;
michael@0 1381 }
michael@0 1382
michael@0 1383 static gint
michael@0 1384 moz_gtk_spin_updown_paint(GdkDrawable* drawable, GdkRectangle* rect,
michael@0 1385 gboolean isDown, GtkWidgetState* state,
michael@0 1386 GtkTextDirection direction)
michael@0 1387 {
michael@0 1388 GdkRectangle arrow_rect;
michael@0 1389 GtkStateType state_type = ConvertGtkState(state);
michael@0 1390 GtkShadowType shadow_type = state_type == GTK_STATE_ACTIVE ?
michael@0 1391 GTK_SHADOW_IN : GTK_SHADOW_OUT;
michael@0 1392 GtkStyle* style;
michael@0 1393
michael@0 1394 ensure_spin_widget();
michael@0 1395 style = gSpinWidget->style;
michael@0 1396 gtk_widget_set_direction(gSpinWidget, direction);
michael@0 1397
michael@0 1398 TSOffsetStyleGCs(style, rect->x, rect->y);
michael@0 1399 gtk_paint_box(style, drawable, state_type, shadow_type, NULL, gSpinWidget,
michael@0 1400 isDown ? "spinbutton_down" : "spinbutton_up",
michael@0 1401 rect->x, rect->y, rect->width, rect->height);
michael@0 1402
michael@0 1403 /* hard code these values */
michael@0 1404 arrow_rect.width = 6;
michael@0 1405 arrow_rect.height = 6;
michael@0 1406 arrow_rect.x = rect->x + (rect->width - arrow_rect.width) / 2;
michael@0 1407 arrow_rect.y = rect->y + (rect->height - arrow_rect.height) / 2;
michael@0 1408 arrow_rect.y += isDown ? -1 : 1;
michael@0 1409
michael@0 1410 gtk_paint_arrow(style, drawable, state_type, shadow_type, NULL,
michael@0 1411 gSpinWidget, "spinbutton",
michael@0 1412 isDown ? GTK_ARROW_DOWN : GTK_ARROW_UP, TRUE,
michael@0 1413 arrow_rect.x, arrow_rect.y,
michael@0 1414 arrow_rect.width, arrow_rect.height);
michael@0 1415
michael@0 1416 return MOZ_GTK_SUCCESS;
michael@0 1417 }
michael@0 1418
michael@0 1419 static gint
michael@0 1420 moz_gtk_scale_paint(GdkDrawable* drawable, GdkRectangle* rect,
michael@0 1421 GdkRectangle* cliprect, GtkWidgetState* state,
michael@0 1422 GtkOrientation flags, GtkTextDirection direction)
michael@0 1423 {
michael@0 1424 gint x = 0, y = 0;
michael@0 1425 GtkStateType state_type = ConvertGtkState(state);
michael@0 1426 GtkStyle* style;
michael@0 1427 GtkWidget* widget;
michael@0 1428
michael@0 1429 ensure_scale_widget();
michael@0 1430 widget = ((flags == GTK_ORIENTATION_HORIZONTAL) ? gHScaleWidget : gVScaleWidget);
michael@0 1431 gtk_widget_set_direction(widget, direction);
michael@0 1432
michael@0 1433 style = widget->style;
michael@0 1434
michael@0 1435 if (flags == GTK_ORIENTATION_HORIZONTAL) {
michael@0 1436 x = XTHICKNESS(style);
michael@0 1437 y++;
michael@0 1438 }
michael@0 1439 else {
michael@0 1440 x++;
michael@0 1441 y = YTHICKNESS(style);
michael@0 1442 }
michael@0 1443
michael@0 1444 TSOffsetStyleGCs(style, rect->x, rect->y);
michael@0 1445
michael@0 1446 gtk_paint_box(style, drawable, GTK_STATE_ACTIVE, GTK_SHADOW_IN, cliprect,
michael@0 1447 widget, "trough", rect->x + x, rect->y + y,
michael@0 1448 rect->width - 2*x, rect->height - 2*y);
michael@0 1449
michael@0 1450 if (state->focused)
michael@0 1451 gtk_paint_focus(style, drawable, state_type, cliprect, widget, "trough",
michael@0 1452 rect->x, rect->y, rect->width, rect->height);
michael@0 1453
michael@0 1454 return MOZ_GTK_SUCCESS;
michael@0 1455 }
michael@0 1456
michael@0 1457 static gint
michael@0 1458 moz_gtk_scale_thumb_paint(GdkDrawable* drawable, GdkRectangle* rect,
michael@0 1459 GdkRectangle* cliprect, GtkWidgetState* state,
michael@0 1460 GtkOrientation flags, GtkTextDirection direction)
michael@0 1461 {
michael@0 1462 GtkStateType state_type = ConvertGtkState(state);
michael@0 1463 GtkStyle* style;
michael@0 1464 GtkWidget* widget;
michael@0 1465 gint thumb_width, thumb_height, x, y;
michael@0 1466
michael@0 1467 ensure_scale_widget();
michael@0 1468 widget = ((flags == GTK_ORIENTATION_HORIZONTAL) ? gHScaleWidget : gVScaleWidget);
michael@0 1469 gtk_widget_set_direction(widget, direction);
michael@0 1470
michael@0 1471 style = widget->style;
michael@0 1472
michael@0 1473 /* determine the thumb size, and position the thumb in the center in the opposite axis */
michael@0 1474 if (flags == GTK_ORIENTATION_HORIZONTAL) {
michael@0 1475 moz_gtk_get_scalethumb_metrics(GTK_ORIENTATION_HORIZONTAL, &thumb_width, &thumb_height);
michael@0 1476 x = rect->x;
michael@0 1477 y = rect->y + (rect->height - thumb_height) / 2;
michael@0 1478 }
michael@0 1479 else {
michael@0 1480 moz_gtk_get_scalethumb_metrics(GTK_ORIENTATION_VERTICAL, &thumb_height, &thumb_width);
michael@0 1481 x = rect->x + (rect->width - thumb_width) / 2;
michael@0 1482 y = rect->y;
michael@0 1483 }
michael@0 1484
michael@0 1485 TSOffsetStyleGCs(style, rect->x, rect->y);
michael@0 1486 gtk_paint_slider(style, drawable, state_type, GTK_SHADOW_OUT, cliprect,
michael@0 1487 widget, (flags == GTK_ORIENTATION_HORIZONTAL) ? "hscale" : "vscale",
michael@0 1488 x, y, thumb_width, thumb_height, flags);
michael@0 1489
michael@0 1490 return MOZ_GTK_SUCCESS;
michael@0 1491 }
michael@0 1492
michael@0 1493 static gint
michael@0 1494 moz_gtk_gripper_paint(GdkDrawable* drawable, GdkRectangle* rect,
michael@0 1495 GdkRectangle* cliprect, GtkWidgetState* state,
michael@0 1496 GtkTextDirection direction)
michael@0 1497 {
michael@0 1498 GtkStateType state_type = ConvertGtkState(state);
michael@0 1499 GtkShadowType shadow_type;
michael@0 1500 GtkStyle* style;
michael@0 1501
michael@0 1502 ensure_handlebox_widget();
michael@0 1503 gtk_widget_set_direction(gHandleBoxWidget, direction);
michael@0 1504
michael@0 1505 style = gHandleBoxWidget->style;
michael@0 1506 shadow_type = GTK_HANDLE_BOX(gHandleBoxWidget)->shadow_type;
michael@0 1507
michael@0 1508 TSOffsetStyleGCs(style, rect->x, rect->y);
michael@0 1509 gtk_paint_box(style, drawable, state_type, shadow_type, cliprect,
michael@0 1510 gHandleBoxWidget, "handlebox_bin", rect->x, rect->y,
michael@0 1511 rect->width, rect->height);
michael@0 1512
michael@0 1513 return MOZ_GTK_SUCCESS;
michael@0 1514 }
michael@0 1515
michael@0 1516 static gint
michael@0 1517 moz_gtk_hpaned_paint(GdkDrawable* drawable, GdkRectangle* rect,
michael@0 1518 GdkRectangle* cliprect, GtkWidgetState* state)
michael@0 1519 {
michael@0 1520 GtkStateType hpaned_state = ConvertGtkState(state);
michael@0 1521
michael@0 1522 ensure_hpaned_widget();
michael@0 1523 gtk_paint_handle(gHPanedWidget->style, drawable, hpaned_state,
michael@0 1524 GTK_SHADOW_NONE, cliprect, gHPanedWidget, "paned",
michael@0 1525 rect->x, rect->y, rect->width, rect->height,
michael@0 1526 GTK_ORIENTATION_VERTICAL);
michael@0 1527
michael@0 1528 return MOZ_GTK_SUCCESS;
michael@0 1529 }
michael@0 1530
michael@0 1531 static gint
michael@0 1532 moz_gtk_vpaned_paint(GdkDrawable* drawable, GdkRectangle* rect,
michael@0 1533 GdkRectangle* cliprect, GtkWidgetState* state)
michael@0 1534 {
michael@0 1535 GtkStateType vpaned_state = ConvertGtkState(state);
michael@0 1536
michael@0 1537 ensure_vpaned_widget();
michael@0 1538 gtk_paint_handle(gVPanedWidget->style, drawable, vpaned_state,
michael@0 1539 GTK_SHADOW_NONE, cliprect, gVPanedWidget, "paned",
michael@0 1540 rect->x, rect->y, rect->width, rect->height,
michael@0 1541 GTK_ORIENTATION_HORIZONTAL);
michael@0 1542
michael@0 1543 return MOZ_GTK_SUCCESS;
michael@0 1544 }
michael@0 1545
michael@0 1546 static gint
michael@0 1547 moz_gtk_entry_paint(GdkDrawable* drawable, GdkRectangle* rect,
michael@0 1548 GdkRectangle* cliprect, GtkWidgetState* state,
michael@0 1549 GtkWidget* widget, GtkTextDirection direction)
michael@0 1550 {
michael@0 1551 GtkStateType bg_state = state->disabled ?
michael@0 1552 GTK_STATE_INSENSITIVE : GTK_STATE_NORMAL;
michael@0 1553 gint x, y, width = rect->width, height = rect->height;
michael@0 1554 GtkStyle* style;
michael@0 1555 gboolean interior_focus;
michael@0 1556 gboolean theme_honors_transparency = FALSE;
michael@0 1557 gint focus_width;
michael@0 1558
michael@0 1559 gtk_widget_set_direction(widget, direction);
michael@0 1560
michael@0 1561 style = widget->style;
michael@0 1562
michael@0 1563 gtk_widget_style_get(widget,
michael@0 1564 "interior-focus", &interior_focus,
michael@0 1565 "focus-line-width", &focus_width,
michael@0 1566 "honors-transparent-bg-hint", &theme_honors_transparency,
michael@0 1567 NULL);
michael@0 1568
michael@0 1569 /* gtkentry.c uses two windows, one for the entire widget and one for the
michael@0 1570 * text area inside it. The background of both windows is set to the "base"
michael@0 1571 * color of the new state in gtk_entry_state_changed, but only the inner
michael@0 1572 * textarea window uses gtk_paint_flat_box when exposed */
michael@0 1573
michael@0 1574 TSOffsetStyleGCs(style, rect->x, rect->y);
michael@0 1575
michael@0 1576 /* This gets us a lovely greyish disabledish look */
michael@0 1577 gtk_widget_set_sensitive(widget, !state->disabled);
michael@0 1578
michael@0 1579 /* GTK fills the outer widget window with the base color before drawing the widget.
michael@0 1580 * Some older themes rely on this behavior, but many themes nowadays use rounded
michael@0 1581 * corners on their widgets. While most GTK apps are blissfully unaware of this
michael@0 1582 * problem due to their use of the default window background, we render widgets on
michael@0 1583 * many kinds of backgrounds on the web.
michael@0 1584 * If the theme is able to cope with transparency, then we can skip pre-filling
michael@0 1585 * and notify the theme it will paint directly on the canvas. */
michael@0 1586 if (theme_honors_transparency) {
michael@0 1587 g_object_set_data(G_OBJECT(widget), "transparent-bg-hint", GINT_TO_POINTER(TRUE));
michael@0 1588 } else {
michael@0 1589 GdkRectangle clipped_rect;
michael@0 1590 gdk_rectangle_intersect(rect, cliprect, &clipped_rect);
michael@0 1591 if (clipped_rect.width != 0) {
michael@0 1592 gdk_draw_rectangle(drawable, style->base_gc[bg_state], TRUE,
michael@0 1593 clipped_rect.x, clipped_rect.y,
michael@0 1594 clipped_rect.width, clipped_rect.height);
michael@0 1595 }
michael@0 1596 g_object_set_data(G_OBJECT(widget), "transparent-bg-hint", GINT_TO_POINTER(FALSE));
michael@0 1597 }
michael@0 1598
michael@0 1599 /* Get the position of the inner window, see _gtk_entry_get_borders */
michael@0 1600 x = XTHICKNESS(style);
michael@0 1601 y = YTHICKNESS(style);
michael@0 1602
michael@0 1603 if (!interior_focus) {
michael@0 1604 x += focus_width;
michael@0 1605 y += focus_width;
michael@0 1606 }
michael@0 1607
michael@0 1608 /* Simulate an expose of the inner window */
michael@0 1609 gtk_paint_flat_box(style, drawable, bg_state, GTK_SHADOW_NONE,
michael@0 1610 cliprect, widget, "entry_bg", rect->x + x,
michael@0 1611 rect->y + y, rect->width - 2*x, rect->height - 2*y);
michael@0 1612
michael@0 1613 /* Now paint the shadow and focus border.
michael@0 1614 * We do like in gtk_entry_draw_frame, we first draw the shadow, a tad
michael@0 1615 * smaller when focused if the focus is not interior, then the focus. */
michael@0 1616 x = rect->x;
michael@0 1617 y = rect->y;
michael@0 1618
michael@0 1619 if (state->focused && !state->disabled) {
michael@0 1620 /* This will get us the lit borders that focused textboxes enjoy on
michael@0 1621 * some themes. */
michael@0 1622 GTK_WIDGET_SET_FLAGS(widget, GTK_HAS_FOCUS);
michael@0 1623
michael@0 1624 if (!interior_focus) {
michael@0 1625 /* Indent the border a little bit if we have exterior focus
michael@0 1626 (this is what GTK does to draw native entries) */
michael@0 1627 x += focus_width;
michael@0 1628 y += focus_width;
michael@0 1629 width -= 2 * focus_width;
michael@0 1630 height -= 2 * focus_width;
michael@0 1631 }
michael@0 1632 }
michael@0 1633
michael@0 1634 gtk_paint_shadow(style, drawable, GTK_STATE_NORMAL, GTK_SHADOW_IN,
michael@0 1635 cliprect, widget, "entry", x, y, width, height);
michael@0 1636
michael@0 1637 if (state->focused && !state->disabled) {
michael@0 1638 if (!interior_focus) {
michael@0 1639 gtk_paint_focus(style, drawable, GTK_STATE_NORMAL, cliprect,
michael@0 1640 widget, "entry",
michael@0 1641 rect->x, rect->y, rect->width, rect->height);
michael@0 1642 }
michael@0 1643
michael@0 1644 /* Now unset the focus flag. We don't want other entries to look
michael@0 1645 * like they're focused too! */
michael@0 1646 GTK_WIDGET_UNSET_FLAGS(widget, GTK_HAS_FOCUS);
michael@0 1647 }
michael@0 1648
michael@0 1649 return MOZ_GTK_SUCCESS;
michael@0 1650 }
michael@0 1651
michael@0 1652 static gint
michael@0 1653 moz_gtk_treeview_paint(GdkDrawable* drawable, GdkRectangle* rect,
michael@0 1654 GdkRectangle* cliprect, GtkWidgetState* state,
michael@0 1655 GtkTextDirection direction)
michael@0 1656 {
michael@0 1657 gint xthickness, ythickness;
michael@0 1658
michael@0 1659 GtkStyle *style;
michael@0 1660 GtkStateType state_type;
michael@0 1661
michael@0 1662 ensure_tree_view_widget();
michael@0 1663 ensure_scrolled_window_widget();
michael@0 1664
michael@0 1665 gtk_widget_set_direction(gTreeViewWidget, direction);
michael@0 1666 gtk_widget_set_direction(gScrolledWindowWidget, direction);
michael@0 1667
michael@0 1668 /* only handle disabled and normal states, otherwise the whole background
michael@0 1669 * area will be painted differently with other states */
michael@0 1670 state_type = state->disabled ? GTK_STATE_INSENSITIVE : GTK_STATE_NORMAL;
michael@0 1671
michael@0 1672 /* In GTK the treeview sets the background of the window
michael@0 1673 * which contains the cells to the treeview base color.
michael@0 1674 * If we don't set it here the background color will not be correct.*/
michael@0 1675 gtk_widget_modify_bg(gTreeViewWidget, state_type,
michael@0 1676 &gTreeViewWidget->style->base[state_type]);
michael@0 1677
michael@0 1678 style = gScrolledWindowWidget->style;
michael@0 1679 xthickness = XTHICKNESS(style);
michael@0 1680 ythickness = YTHICKNESS(style);
michael@0 1681
michael@0 1682 TSOffsetStyleGCs(gTreeViewWidget->style, rect->x, rect->y);
michael@0 1683 TSOffsetStyleGCs(style, rect->x, rect->y);
michael@0 1684
michael@0 1685 gtk_paint_flat_box(gTreeViewWidget->style, drawable, state_type,
michael@0 1686 GTK_SHADOW_NONE, cliprect, gTreeViewWidget, "treeview",
michael@0 1687 rect->x + xthickness, rect->y + ythickness,
michael@0 1688 rect->width - 2 * xthickness,
michael@0 1689 rect->height - 2 * ythickness);
michael@0 1690
michael@0 1691 gtk_paint_shadow(style, drawable, GTK_STATE_NORMAL, GTK_SHADOW_IN,
michael@0 1692 cliprect, gScrolledWindowWidget, "scrolled_window",
michael@0 1693 rect->x, rect->y, rect->width, rect->height);
michael@0 1694
michael@0 1695 return MOZ_GTK_SUCCESS;
michael@0 1696 }
michael@0 1697
michael@0 1698 static gint
michael@0 1699 moz_gtk_tree_header_cell_paint(GdkDrawable* drawable, GdkRectangle* rect,
michael@0 1700 GdkRectangle* cliprect, GtkWidgetState* state,
michael@0 1701 gboolean isSorted, GtkTextDirection direction)
michael@0 1702 {
michael@0 1703 gtk_tree_view_column_set_sort_indicator(gMiddleTreeViewColumn,
michael@0 1704 isSorted);
michael@0 1705
michael@0 1706 moz_gtk_button_paint(drawable, rect, cliprect, state, GTK_RELIEF_NORMAL,
michael@0 1707 gTreeHeaderCellWidget, direction);
michael@0 1708 return MOZ_GTK_SUCCESS;
michael@0 1709 }
michael@0 1710
michael@0 1711 static gint
michael@0 1712 moz_gtk_tree_header_sort_arrow_paint(GdkDrawable* drawable, GdkRectangle* rect,
michael@0 1713 GdkRectangle* cliprect,
michael@0 1714 GtkWidgetState* state, GtkArrowType flags,
michael@0 1715 GtkTextDirection direction)
michael@0 1716 {
michael@0 1717 GdkRectangle arrow_rect;
michael@0 1718 GtkStateType state_type = ConvertGtkState(state);
michael@0 1719 GtkShadowType shadow_type = GTK_SHADOW_IN;
michael@0 1720 GtkArrowType arrow_type = flags;
michael@0 1721 GtkStyle* style;
michael@0 1722
michael@0 1723 ensure_tree_header_cell_widget();
michael@0 1724 gtk_widget_set_direction(gTreeHeaderSortArrowWidget, direction);
michael@0 1725
michael@0 1726 /* hard code these values */
michael@0 1727 arrow_rect.width = 11;
michael@0 1728 arrow_rect.height = 11;
michael@0 1729 arrow_rect.x = rect->x + (rect->width - arrow_rect.width) / 2;
michael@0 1730 arrow_rect.y = rect->y + (rect->height - arrow_rect.height) / 2;
michael@0 1731
michael@0 1732 style = gTreeHeaderSortArrowWidget->style;
michael@0 1733 TSOffsetStyleGCs(style, arrow_rect.x, arrow_rect.y);
michael@0 1734
michael@0 1735 gtk_paint_arrow(style, drawable, state_type, shadow_type, cliprect,
michael@0 1736 gTreeHeaderSortArrowWidget, "arrow", arrow_type, TRUE,
michael@0 1737 arrow_rect.x, arrow_rect.y,
michael@0 1738 arrow_rect.width, arrow_rect.height);
michael@0 1739
michael@0 1740 return MOZ_GTK_SUCCESS;
michael@0 1741 }
michael@0 1742
michael@0 1743 static gint
michael@0 1744 moz_gtk_treeview_expander_paint(GdkDrawable* drawable, GdkRectangle* rect,
michael@0 1745 GdkRectangle* cliprect, GtkWidgetState* state,
michael@0 1746 GtkExpanderStyle expander_state,
michael@0 1747 GtkTextDirection direction)
michael@0 1748 {
michael@0 1749 GtkStyle *style;
michael@0 1750 GtkStateType state_type;
michael@0 1751
michael@0 1752 ensure_tree_view_widget();
michael@0 1753 gtk_widget_set_direction(gTreeViewWidget, direction);
michael@0 1754
michael@0 1755 style = gTreeViewWidget->style;
michael@0 1756
michael@0 1757 /* Because the frame we get is of the entire treeview, we can't get the precise
michael@0 1758 * event state of one expander, thus rendering hover and active feedback useless. */
michael@0 1759 state_type = state->disabled ? GTK_STATE_INSENSITIVE : GTK_STATE_NORMAL;
michael@0 1760
michael@0 1761 TSOffsetStyleGCs(style, rect->x, rect->y);
michael@0 1762 gtk_paint_expander(style, drawable, state_type, cliprect, gTreeViewWidget, "treeview",
michael@0 1763 rect->x + rect->width / 2, rect->y + rect->height / 2, expander_state);
michael@0 1764
michael@0 1765 return MOZ_GTK_SUCCESS;
michael@0 1766 }
michael@0 1767
michael@0 1768 static gint
michael@0 1769 moz_gtk_combo_box_paint(GdkDrawable* drawable, GdkRectangle* rect,
michael@0 1770 GdkRectangle* cliprect, GtkWidgetState* state,
michael@0 1771 gboolean ishtml, GtkTextDirection direction)
michael@0 1772 {
michael@0 1773 GdkRectangle arrow_rect, real_arrow_rect;
michael@0 1774 gint arrow_size, separator_width;
michael@0 1775 gboolean wide_separators;
michael@0 1776 GtkStateType state_type = ConvertGtkState(state);
michael@0 1777 GtkShadowType shadow_type = state->active ? GTK_SHADOW_IN : GTK_SHADOW_OUT;
michael@0 1778 GtkStyle* style;
michael@0 1779 GtkRequisition arrow_req;
michael@0 1780
michael@0 1781 ensure_combo_box_widgets();
michael@0 1782
michael@0 1783 /* Also sets the direction on gComboBoxButtonWidget, which is then
michael@0 1784 * inherited by the separator and arrow */
michael@0 1785 moz_gtk_button_paint(drawable, rect, cliprect, state, GTK_RELIEF_NORMAL,
michael@0 1786 gComboBoxButtonWidget, direction);
michael@0 1787
michael@0 1788 calculate_button_inner_rect(gComboBoxButtonWidget,
michael@0 1789 rect, &arrow_rect, direction, ishtml);
michael@0 1790 /* Now arrow_rect contains the inner rect ; we want to correct the width
michael@0 1791 * to what the arrow needs (see gtk_combo_box_size_allocate) */
michael@0 1792 gtk_widget_size_request(gComboBoxArrowWidget, &arrow_req);
michael@0 1793 if (direction == GTK_TEXT_DIR_LTR)
michael@0 1794 arrow_rect.x += arrow_rect.width - arrow_req.width;
michael@0 1795 arrow_rect.width = arrow_req.width;
michael@0 1796
michael@0 1797 calculate_arrow_rect(gComboBoxArrowWidget,
michael@0 1798 &arrow_rect, &real_arrow_rect, direction);
michael@0 1799
michael@0 1800 style = gComboBoxArrowWidget->style;
michael@0 1801 TSOffsetStyleGCs(style, rect->x, rect->y);
michael@0 1802
michael@0 1803 gtk_widget_size_allocate(gComboBoxWidget, rect);
michael@0 1804
michael@0 1805 gtk_paint_arrow(style, drawable, state_type, shadow_type, cliprect,
michael@0 1806 gComboBoxArrowWidget, "arrow", GTK_ARROW_DOWN, TRUE,
michael@0 1807 real_arrow_rect.x, real_arrow_rect.y,
michael@0 1808 real_arrow_rect.width, real_arrow_rect.height);
michael@0 1809
michael@0 1810
michael@0 1811 /* If there is no separator in the theme, there's nothing left to do. */
michael@0 1812 if (!gComboBoxSeparatorWidget)
michael@0 1813 return MOZ_GTK_SUCCESS;
michael@0 1814
michael@0 1815 style = gComboBoxSeparatorWidget->style;
michael@0 1816 TSOffsetStyleGCs(style, rect->x, rect->y);
michael@0 1817
michael@0 1818 gtk_widget_style_get(gComboBoxSeparatorWidget,
michael@0 1819 "wide-separators", &wide_separators,
michael@0 1820 "separator-width", &separator_width,
michael@0 1821 NULL);
michael@0 1822
michael@0 1823 if (wide_separators) {
michael@0 1824 if (direction == GTK_TEXT_DIR_LTR)
michael@0 1825 arrow_rect.x -= separator_width;
michael@0 1826 else
michael@0 1827 arrow_rect.x += arrow_rect.width;
michael@0 1828
michael@0 1829 gtk_paint_box(style, drawable,
michael@0 1830 GTK_STATE_NORMAL, GTK_SHADOW_ETCHED_OUT,
michael@0 1831 cliprect, gComboBoxSeparatorWidget, "vseparator",
michael@0 1832 arrow_rect.x, arrow_rect.y,
michael@0 1833 separator_width, arrow_rect.height);
michael@0 1834 } else {
michael@0 1835 if (direction == GTK_TEXT_DIR_LTR)
michael@0 1836 arrow_rect.x -= XTHICKNESS(style);
michael@0 1837 else
michael@0 1838 arrow_rect.x += arrow_rect.width;
michael@0 1839
michael@0 1840 gtk_paint_vline(style, drawable, GTK_STATE_NORMAL, cliprect,
michael@0 1841 gComboBoxSeparatorWidget, "vseparator",
michael@0 1842 arrow_rect.y, arrow_rect.y + arrow_rect.height,
michael@0 1843 arrow_rect.x);
michael@0 1844 }
michael@0 1845
michael@0 1846 return MOZ_GTK_SUCCESS;
michael@0 1847 }
michael@0 1848
michael@0 1849 static gint
michael@0 1850 moz_gtk_arrow_paint(GdkDrawable* drawable, GdkRectangle* rect,
michael@0 1851 GdkRectangle* cliprect, GtkWidgetState* state,
michael@0 1852 GtkArrowType arrow_type, GtkTextDirection direction)
michael@0 1853 {
michael@0 1854 GtkStyle* style;
michael@0 1855 GtkStateType state_type = ConvertGtkState(state);
michael@0 1856 GtkShadowType shadow_type = state->active ? GTK_SHADOW_IN : GTK_SHADOW_OUT;
michael@0 1857 GdkRectangle arrow_rect;
michael@0 1858
michael@0 1859 ensure_button_arrow_widget();
michael@0 1860 style = gButtonArrowWidget->style;
michael@0 1861 gtk_widget_set_direction(gButtonArrowWidget, direction);
michael@0 1862
michael@0 1863 calculate_arrow_rect(gButtonArrowWidget, rect, &arrow_rect,
michael@0 1864 direction);
michael@0 1865
michael@0 1866 if (direction == GTK_TEXT_DIR_RTL) {
michael@0 1867 if (arrow_type == GTK_ARROW_LEFT)
michael@0 1868 arrow_type = GTK_ARROW_RIGHT;
michael@0 1869 else if (arrow_type == GTK_ARROW_RIGHT)
michael@0 1870 arrow_type = GTK_ARROW_LEFT;
michael@0 1871 }
michael@0 1872
michael@0 1873 TSOffsetStyleGCs(style, arrow_rect.x, arrow_rect.y);
michael@0 1874 gtk_paint_arrow(style, drawable, state_type, shadow_type, cliprect,
michael@0 1875 gButtonArrowWidget, "arrow", arrow_type, TRUE,
michael@0 1876 arrow_rect.x, arrow_rect.y, arrow_rect.width, arrow_rect.height);
michael@0 1877
michael@0 1878 return MOZ_GTK_SUCCESS;
michael@0 1879 }
michael@0 1880
michael@0 1881 static gint
michael@0 1882 moz_gtk_combo_box_entry_button_paint(GdkDrawable* drawable, GdkRectangle* rect,
michael@0 1883 GdkRectangle* cliprect,
michael@0 1884 GtkWidgetState* state,
michael@0 1885 gboolean input_focus,
michael@0 1886 GtkTextDirection direction)
michael@0 1887 {
michael@0 1888 gint x_displacement, y_displacement;
michael@0 1889 GdkRectangle arrow_rect, real_arrow_rect;
michael@0 1890 GtkStateType state_type = ConvertGtkState(state);
michael@0 1891 GtkShadowType shadow_type = state->active ? GTK_SHADOW_IN : GTK_SHADOW_OUT;
michael@0 1892 GtkStyle* style;
michael@0 1893
michael@0 1894 ensure_combo_box_entry_widgets();
michael@0 1895
michael@0 1896 if (input_focus) {
michael@0 1897 /* Some themes draw a complementary focus ring for the dropdown button
michael@0 1898 * when the dropdown entry has focus */
michael@0 1899 GTK_WIDGET_SET_FLAGS(gComboBoxEntryTextareaWidget, GTK_HAS_FOCUS);
michael@0 1900 }
michael@0 1901
michael@0 1902 moz_gtk_button_paint(drawable, rect, cliprect, state, GTK_RELIEF_NORMAL,
michael@0 1903 gComboBoxEntryButtonWidget, direction);
michael@0 1904
michael@0 1905 if (input_focus)
michael@0 1906 GTK_WIDGET_UNSET_FLAGS(gComboBoxEntryTextareaWidget, GTK_HAS_FOCUS);
michael@0 1907
michael@0 1908 calculate_button_inner_rect(gComboBoxEntryButtonWidget,
michael@0 1909 rect, &arrow_rect, direction, FALSE);
michael@0 1910 if (state_type == GTK_STATE_ACTIVE) {
michael@0 1911 gtk_widget_style_get(gComboBoxEntryButtonWidget,
michael@0 1912 "child-displacement-x", &x_displacement,
michael@0 1913 "child-displacement-y", &y_displacement,
michael@0 1914 NULL);
michael@0 1915 arrow_rect.x += x_displacement;
michael@0 1916 arrow_rect.y += y_displacement;
michael@0 1917 }
michael@0 1918
michael@0 1919 calculate_arrow_rect(gComboBoxEntryArrowWidget,
michael@0 1920 &arrow_rect, &real_arrow_rect, direction);
michael@0 1921
michael@0 1922 style = gComboBoxEntryArrowWidget->style;
michael@0 1923 TSOffsetStyleGCs(style, real_arrow_rect.x, real_arrow_rect.y);
michael@0 1924
michael@0 1925 gtk_paint_arrow(style, drawable, state_type, shadow_type, cliprect,
michael@0 1926 gComboBoxEntryArrowWidget, "arrow", GTK_ARROW_DOWN, TRUE,
michael@0 1927 real_arrow_rect.x, real_arrow_rect.y,
michael@0 1928 real_arrow_rect.width, real_arrow_rect.height);
michael@0 1929
michael@0 1930 return MOZ_GTK_SUCCESS;
michael@0 1931 }
michael@0 1932
michael@0 1933 static gint
michael@0 1934 moz_gtk_container_paint(GdkDrawable* drawable, GdkRectangle* rect,
michael@0 1935 GdkRectangle* cliprect, GtkWidgetState* state,
michael@0 1936 gboolean isradio, GtkTextDirection direction)
michael@0 1937 {
michael@0 1938 GtkStateType state_type = ConvertGtkState(state);
michael@0 1939 GtkStyle* style;
michael@0 1940 GtkWidget *widget;
michael@0 1941 gboolean interior_focus;
michael@0 1942 gint focus_width, focus_pad;
michael@0 1943
michael@0 1944 if (isradio) {
michael@0 1945 ensure_radiobutton_widget();
michael@0 1946 widget = gRadiobuttonWidget;
michael@0 1947 } else {
michael@0 1948 ensure_checkbox_widget();
michael@0 1949 widget = gCheckboxWidget;
michael@0 1950 }
michael@0 1951 gtk_widget_set_direction(widget, direction);
michael@0 1952
michael@0 1953 style = widget->style;
michael@0 1954 moz_gtk_widget_get_focus(widget, &interior_focus, &focus_width,
michael@0 1955 &focus_pad);
michael@0 1956
michael@0 1957 TSOffsetStyleGCs(style, rect->x, rect->y);
michael@0 1958
michael@0 1959 /* The detail argument for the gtk_paint_* calls below are "checkbutton"
michael@0 1960 even for radio buttons, to match what gtk does. */
michael@0 1961
michael@0 1962 /* this is for drawing a prelight box */
michael@0 1963 if (state_type == GTK_STATE_PRELIGHT || state_type == GTK_STATE_ACTIVE) {
michael@0 1964 gtk_paint_flat_box(style, drawable, GTK_STATE_PRELIGHT,
michael@0 1965 GTK_SHADOW_ETCHED_OUT, cliprect, widget,
michael@0 1966 "checkbutton",
michael@0 1967 rect->x, rect->y, rect->width, rect->height);
michael@0 1968 }
michael@0 1969
michael@0 1970 if (state_type != GTK_STATE_NORMAL && state_type != GTK_STATE_PRELIGHT)
michael@0 1971 state_type = GTK_STATE_NORMAL;
michael@0 1972
michael@0 1973 if (state->focused && !interior_focus) {
michael@0 1974 gtk_paint_focus(style, drawable, state_type, cliprect, widget,
michael@0 1975 "checkbutton",
michael@0 1976 rect->x, rect->y, rect->width, rect->height);
michael@0 1977 }
michael@0 1978
michael@0 1979 return MOZ_GTK_SUCCESS;
michael@0 1980 }
michael@0 1981
michael@0 1982 static gint
michael@0 1983 moz_gtk_toggle_label_paint(GdkDrawable* drawable, GdkRectangle* rect,
michael@0 1984 GdkRectangle* cliprect, GtkWidgetState* state,
michael@0 1985 gboolean isradio, GtkTextDirection direction)
michael@0 1986 {
michael@0 1987 GtkStateType state_type;
michael@0 1988 GtkStyle *style;
michael@0 1989 GtkWidget *widget;
michael@0 1990 gboolean interior_focus;
michael@0 1991
michael@0 1992 if (!state->focused)
michael@0 1993 return MOZ_GTK_SUCCESS;
michael@0 1994
michael@0 1995 if (isradio) {
michael@0 1996 ensure_radiobutton_widget();
michael@0 1997 widget = gRadiobuttonWidget;
michael@0 1998 } else {
michael@0 1999 ensure_checkbox_widget();
michael@0 2000 widget = gCheckboxWidget;
michael@0 2001 }
michael@0 2002 gtk_widget_set_direction(widget, direction);
michael@0 2003
michael@0 2004 gtk_widget_style_get(widget, "interior-focus", &interior_focus, NULL);
michael@0 2005 if (!interior_focus)
michael@0 2006 return MOZ_GTK_SUCCESS;
michael@0 2007
michael@0 2008 state_type = ConvertGtkState(state);
michael@0 2009
michael@0 2010 style = widget->style;
michael@0 2011 TSOffsetStyleGCs(style, rect->x, rect->y);
michael@0 2012
michael@0 2013 /* Always "checkbutton" to match gtkcheckbutton.c */
michael@0 2014 gtk_paint_focus(style, drawable, state_type, cliprect, widget,
michael@0 2015 "checkbutton",
michael@0 2016 rect->x, rect->y, rect->width, rect->height);
michael@0 2017
michael@0 2018 return MOZ_GTK_SUCCESS;
michael@0 2019 }
michael@0 2020
michael@0 2021 static gint
michael@0 2022 moz_gtk_toolbar_paint(GdkDrawable* drawable, GdkRectangle* rect,
michael@0 2023 GdkRectangle* cliprect, GtkTextDirection direction)
michael@0 2024 {
michael@0 2025 GtkStyle* style;
michael@0 2026 GtkShadowType shadow_type;
michael@0 2027
michael@0 2028 ensure_toolbar_widget();
michael@0 2029 gtk_widget_set_direction(gToolbarWidget, direction);
michael@0 2030
michael@0 2031 style = gToolbarWidget->style;
michael@0 2032
michael@0 2033 TSOffsetStyleGCs(style, rect->x, rect->y);
michael@0 2034
michael@0 2035 gtk_style_apply_default_background(style, drawable, TRUE,
michael@0 2036 GTK_STATE_NORMAL,
michael@0 2037 cliprect, rect->x, rect->y,
michael@0 2038 rect->width, rect->height);
michael@0 2039
michael@0 2040 gtk_widget_style_get(gToolbarWidget, "shadow-type", &shadow_type, NULL);
michael@0 2041
michael@0 2042 gtk_paint_box (style, drawable, GTK_STATE_NORMAL, shadow_type,
michael@0 2043 cliprect, gToolbarWidget, "toolbar",
michael@0 2044 rect->x, rect->y, rect->width, rect->height);
michael@0 2045
michael@0 2046 return MOZ_GTK_SUCCESS;
michael@0 2047 }
michael@0 2048
michael@0 2049 static gint
michael@0 2050 moz_gtk_toolbar_separator_paint(GdkDrawable* drawable, GdkRectangle* rect,
michael@0 2051 GdkRectangle* cliprect,
michael@0 2052 GtkTextDirection direction)
michael@0 2053 {
michael@0 2054 GtkStyle* style;
michael@0 2055 gint separator_width;
michael@0 2056 gint paint_width;
michael@0 2057 gboolean wide_separators;
michael@0 2058
michael@0 2059 /* Defined as constants in GTK+ 2.10.14 */
michael@0 2060 const double start_fraction = 0.2;
michael@0 2061 const double end_fraction = 0.8;
michael@0 2062
michael@0 2063 ensure_toolbar_separator_widget();
michael@0 2064 gtk_widget_set_direction(gToolbarSeparatorWidget, direction);
michael@0 2065
michael@0 2066 style = gToolbarSeparatorWidget->style;
michael@0 2067
michael@0 2068 gtk_widget_style_get(gToolbarWidget,
michael@0 2069 "wide-separators", &wide_separators,
michael@0 2070 "separator-width", &separator_width,
michael@0 2071 NULL);
michael@0 2072
michael@0 2073 TSOffsetStyleGCs(style, rect->x, rect->y);
michael@0 2074
michael@0 2075 if (wide_separators) {
michael@0 2076 if (separator_width > rect->width)
michael@0 2077 separator_width = rect->width;
michael@0 2078
michael@0 2079 gtk_paint_box(style, drawable,
michael@0 2080 GTK_STATE_NORMAL, GTK_SHADOW_ETCHED_OUT,
michael@0 2081 cliprect, gToolbarWidget, "vseparator",
michael@0 2082 rect->x + (rect->width - separator_width) / 2,
michael@0 2083 rect->y + rect->height * start_fraction,
michael@0 2084 separator_width,
michael@0 2085 rect->height * (end_fraction - start_fraction));
michael@0 2086
michael@0 2087 } else {
michael@0 2088 paint_width = style->xthickness;
michael@0 2089
michael@0 2090 if (paint_width > rect->width)
michael@0 2091 paint_width = rect->width;
michael@0 2092
michael@0 2093 gtk_paint_vline(style, drawable,
michael@0 2094 GTK_STATE_NORMAL, cliprect, gToolbarSeparatorWidget,
michael@0 2095 "toolbar",
michael@0 2096 rect->y + rect->height * start_fraction,
michael@0 2097 rect->y + rect->height * end_fraction,
michael@0 2098 rect->x + (rect->width - paint_width) / 2);
michael@0 2099 }
michael@0 2100
michael@0 2101 return MOZ_GTK_SUCCESS;
michael@0 2102 }
michael@0 2103
michael@0 2104 static gint
michael@0 2105 moz_gtk_tooltip_paint(GdkDrawable* drawable, GdkRectangle* rect,
michael@0 2106 GdkRectangle* cliprect, GtkTextDirection direction)
michael@0 2107 {
michael@0 2108 GtkStyle* style;
michael@0 2109
michael@0 2110 ensure_tooltip_widget();
michael@0 2111 gtk_widget_set_direction(gTooltipWidget, direction);
michael@0 2112
michael@0 2113 style = gtk_rc_get_style_by_paths(gtk_settings_get_default(),
michael@0 2114 "gtk-tooltips", "GtkWindow",
michael@0 2115 GTK_TYPE_WINDOW);
michael@0 2116
michael@0 2117 style = gtk_style_attach(style, gTooltipWidget->window);
michael@0 2118 TSOffsetStyleGCs(style, rect->x, rect->y);
michael@0 2119 gtk_paint_flat_box(style, drawable, GTK_STATE_NORMAL, GTK_SHADOW_OUT,
michael@0 2120 cliprect, gTooltipWidget, "tooltip",
michael@0 2121 rect->x, rect->y, rect->width, rect->height);
michael@0 2122
michael@0 2123 return MOZ_GTK_SUCCESS;
michael@0 2124 }
michael@0 2125
michael@0 2126 static gint
michael@0 2127 moz_gtk_resizer_paint(GdkDrawable* drawable, GdkRectangle* rect,
michael@0 2128 GdkRectangle* cliprect, GtkWidgetState* state,
michael@0 2129 GtkTextDirection direction)
michael@0 2130 {
michael@0 2131 GtkStyle* style;
michael@0 2132 GtkStateType state_type = ConvertGtkState(state);
michael@0 2133
michael@0 2134 ensure_frame_widget();
michael@0 2135 gtk_widget_set_direction(gStatusbarWidget, direction);
michael@0 2136
michael@0 2137 style = gStatusbarWidget->style;
michael@0 2138
michael@0 2139 TSOffsetStyleGCs(style, rect->x, rect->y);
michael@0 2140
michael@0 2141 gtk_paint_resize_grip(style, drawable, state_type, cliprect, gStatusbarWidget,
michael@0 2142 "statusbar", (direction == GTK_TEXT_DIR_LTR) ?
michael@0 2143 GDK_WINDOW_EDGE_SOUTH_EAST :
michael@0 2144 GDK_WINDOW_EDGE_SOUTH_WEST,
michael@0 2145 rect->x, rect->y, rect->width, rect->height);
michael@0 2146 return MOZ_GTK_SUCCESS;
michael@0 2147 }
michael@0 2148
michael@0 2149 static gint
michael@0 2150 moz_gtk_frame_paint(GdkDrawable* drawable, GdkRectangle* rect,
michael@0 2151 GdkRectangle* cliprect, GtkTextDirection direction)
michael@0 2152 {
michael@0 2153 GtkStyle* style;
michael@0 2154 GtkShadowType shadow_type;
michael@0 2155
michael@0 2156 ensure_frame_widget();
michael@0 2157 gtk_widget_set_direction(gFrameWidget, direction);
michael@0 2158
michael@0 2159 style = gFrameWidget->style;
michael@0 2160
michael@0 2161 gtk_widget_style_get(gStatusbarWidget, "shadow-type", &shadow_type, NULL);
michael@0 2162
michael@0 2163 TSOffsetStyleGCs(style, rect->x, rect->y);
michael@0 2164 gtk_paint_shadow(style, drawable, GTK_STATE_NORMAL, shadow_type,
michael@0 2165 cliprect, gFrameWidget, "frame", rect->x, rect->y,
michael@0 2166 rect->width, rect->height);
michael@0 2167
michael@0 2168 return MOZ_GTK_SUCCESS;
michael@0 2169 }
michael@0 2170
michael@0 2171 static gint
michael@0 2172 moz_gtk_progressbar_paint(GdkDrawable* drawable, GdkRectangle* rect,
michael@0 2173 GdkRectangle* cliprect, GtkTextDirection direction)
michael@0 2174 {
michael@0 2175 GtkStyle* style;
michael@0 2176
michael@0 2177 ensure_progress_widget();
michael@0 2178 gtk_widget_set_direction(gProgressWidget, direction);
michael@0 2179
michael@0 2180 style = gProgressWidget->style;
michael@0 2181
michael@0 2182 TSOffsetStyleGCs(style, rect->x, rect->y);
michael@0 2183 gtk_paint_box(style, drawable, GTK_STATE_NORMAL, GTK_SHADOW_IN,
michael@0 2184 cliprect, gProgressWidget, "trough", rect->x, rect->y,
michael@0 2185 rect->width, rect->height);
michael@0 2186
michael@0 2187 return MOZ_GTK_SUCCESS;
michael@0 2188 }
michael@0 2189
michael@0 2190 static gint
michael@0 2191 moz_gtk_progress_chunk_paint(GdkDrawable* drawable, GdkRectangle* rect,
michael@0 2192 GdkRectangle* cliprect, GtkTextDirection direction,
michael@0 2193 GtkThemeWidgetType widget)
michael@0 2194 {
michael@0 2195 GtkStyle* style;
michael@0 2196
michael@0 2197 ensure_progress_widget();
michael@0 2198 gtk_widget_set_direction(gProgressWidget, direction);
michael@0 2199
michael@0 2200 style = gProgressWidget->style;
michael@0 2201
michael@0 2202 TSOffsetStyleGCs(style, rect->x, rect->y);
michael@0 2203
michael@0 2204 if (widget == MOZ_GTK_PROGRESS_CHUNK_INDETERMINATE ||
michael@0 2205 widget == MOZ_GTK_PROGRESS_CHUNK_VERTICAL_INDETERMINATE) {
michael@0 2206 /**
michael@0 2207 * The bar's size and the bar speed are set depending of the progress'
michael@0 2208 * size. These could also be constant for all progress bars easily.
michael@0 2209 */
michael@0 2210 gboolean vertical = (widget == MOZ_GTK_PROGRESS_CHUNK_VERTICAL_INDETERMINATE);
michael@0 2211
michael@0 2212 /* The size of the dimension we are going to use for the animation. */
michael@0 2213 const gint progressSize = vertical ? rect->height : rect->width;
michael@0 2214
michael@0 2215 /* The bar is using a fifth of the element size, based on GtkProgressBar
michael@0 2216 * activity-blocks property. */
michael@0 2217 const gint barSize = MAX(1, progressSize / 5);
michael@0 2218
michael@0 2219 /* Represents the travel that has to be done for a complete cycle. */
michael@0 2220 const gint travel = 2 * (progressSize - barSize);
michael@0 2221
michael@0 2222 /* period equals to travel / pixelsPerMillisecond
michael@0 2223 * where pixelsPerMillisecond equals progressSize / 1000.0.
michael@0 2224 * This is equivalent to 1600. */
michael@0 2225 static const guint period = 1600;
michael@0 2226 const gint t = PR_IntervalToMilliseconds(PR_IntervalNow()) % period;
michael@0 2227 const gint dx = travel * t / period;
michael@0 2228
michael@0 2229 if (vertical) {
michael@0 2230 rect->y += (dx < travel / 2) ? dx : travel - dx;
michael@0 2231 rect->height = barSize;
michael@0 2232 } else {
michael@0 2233 rect->x += (dx < travel / 2) ? dx : travel - dx;
michael@0 2234 rect->width = barSize;
michael@0 2235 }
michael@0 2236 }
michael@0 2237
michael@0 2238 gtk_paint_box(style, drawable, GTK_STATE_PRELIGHT, GTK_SHADOW_OUT,
michael@0 2239 cliprect, gProgressWidget, "bar", rect->x, rect->y,
michael@0 2240 rect->width, rect->height);
michael@0 2241
michael@0 2242 return MOZ_GTK_SUCCESS;
michael@0 2243 }
michael@0 2244
michael@0 2245 gint
michael@0 2246 moz_gtk_get_tab_thickness(void)
michael@0 2247 {
michael@0 2248 ensure_tab_widget();
michael@0 2249 if (YTHICKNESS(gTabWidget->style) < 2)
michael@0 2250 return 2; /* some themes don't set ythickness correctly */
michael@0 2251
michael@0 2252 return YTHICKNESS(gTabWidget->style);
michael@0 2253 }
michael@0 2254
michael@0 2255 static gint
michael@0 2256 moz_gtk_tab_paint(GdkDrawable* drawable, GdkRectangle* rect,
michael@0 2257 GdkRectangle* cliprect, GtkWidgetState* state,
michael@0 2258 GtkTabFlags flags, GtkTextDirection direction)
michael@0 2259 {
michael@0 2260 /* When the tab isn't selected, we just draw a notebook extension.
michael@0 2261 * When it is selected, we overwrite the adjacent border of the tabpanel
michael@0 2262 * touching the tab with a pierced border (called "the gap") to make the
michael@0 2263 * tab appear physically attached to the tabpanel; see details below. */
michael@0 2264
michael@0 2265 GtkStyle* style;
michael@0 2266 GdkRectangle focusRect;
michael@0 2267
michael@0 2268 ensure_tab_widget();
michael@0 2269 gtk_widget_set_direction(gTabWidget, direction);
michael@0 2270
michael@0 2271 style = gTabWidget->style;
michael@0 2272 focusRect = *rect;
michael@0 2273 TSOffsetStyleGCs(style, rect->x, rect->y);
michael@0 2274
michael@0 2275 if ((flags & MOZ_GTK_TAB_SELECTED) == 0) {
michael@0 2276 /* Only draw the tab */
michael@0 2277 gtk_paint_extension(style, drawable, GTK_STATE_ACTIVE, GTK_SHADOW_OUT,
michael@0 2278 cliprect, gTabWidget, "tab",
michael@0 2279 rect->x, rect->y, rect->width, rect->height,
michael@0 2280 (flags & MOZ_GTK_TAB_BOTTOM) ?
michael@0 2281 GTK_POS_TOP : GTK_POS_BOTTOM );
michael@0 2282 } else {
michael@0 2283 /* Draw the tab and the gap
michael@0 2284 * We want the gap to be positioned exactly on the tabpanel top
michael@0 2285 * border; since tabbox.css may set a negative margin so that the tab
michael@0 2286 * frame rect already overlaps the tabpanel frame rect, we need to take
michael@0 2287 * that into account when drawing. To that effect, nsNativeThemeGTK
michael@0 2288 * passes us this negative margin (bmargin in the graphic below) in the
michael@0 2289 * lowest bits of |flags|. We use it to set gap_voffset, the distance
michael@0 2290 * between the top of the gap and the bottom of the tab (resp. the
michael@0 2291 * bottom of the gap and the top of the tab when we draw a bottom tab),
michael@0 2292 * while ensuring that the gap always touches the border of the tab,
michael@0 2293 * i.e. 0 <= gap_voffset <= gap_height, to avoid surprinsing results
michael@0 2294 * with big negative or positive margins.
michael@0 2295 * Here is a graphical explanation in the case of top tabs:
michael@0 2296 * ___________________________
michael@0 2297 * / \
michael@0 2298 * | T A B |
michael@0 2299 * ----------|. . . . . . . . . . . . . . .|----- top of tabpanel
michael@0 2300 * : ^ bmargin : ^
michael@0 2301 * : | (-negative margin, : |
michael@0 2302 * bottom : v passed in flags) : | gap_height
michael@0 2303 * of -> :.............................: | (the size of the
michael@0 2304 * the tab . part of the gap . | tabpanel top border)
michael@0 2305 * . outside of the tab . v
michael@0 2306 * ----------------------------------------------
michael@0 2307 *
michael@0 2308 * To draw the gap, we use gtk_paint_box_gap(), see comment in
michael@0 2309 * moz_gtk_tabpanels_paint(). This box_gap is made 3 * gap_height tall,
michael@0 2310 * which should suffice to ensure that the only visible border is the
michael@0 2311 * pierced one. If the tab is in the middle, we make the box_gap begin
michael@0 2312 * a bit to the left of the tab and end a bit to the right, adjusting
michael@0 2313 * the gap position so it still is under the tab, because we want the
michael@0 2314 * rendering of a gap in the middle of a tabpanel. This is the role of
michael@0 2315 * the gints gap_{l,r}_offset. On the contrary, if the tab is the
michael@0 2316 * first, we align the start border of the box_gap with the start
michael@0 2317 * border of the tab (left if LTR, right if RTL), by setting the
michael@0 2318 * appropriate offset to 0.*/
michael@0 2319 gint gap_loffset, gap_roffset, gap_voffset, gap_height;
michael@0 2320
michael@0 2321 /* Get height needed by the gap */
michael@0 2322 gap_height = moz_gtk_get_tab_thickness();
michael@0 2323
michael@0 2324 /* Extract gap_voffset from the first bits of flags */
michael@0 2325 gap_voffset = flags & MOZ_GTK_TAB_MARGIN_MASK;
michael@0 2326 if (gap_voffset > gap_height)
michael@0 2327 gap_voffset = gap_height;
michael@0 2328
michael@0 2329 /* Set gap_{l,r}_offset to appropriate values */
michael@0 2330 gap_loffset = gap_roffset = 20; /* should be enough */
michael@0 2331 if (flags & MOZ_GTK_TAB_FIRST) {
michael@0 2332 if (direction == GTK_TEXT_DIR_RTL)
michael@0 2333 gap_roffset = 0;
michael@0 2334 else
michael@0 2335 gap_loffset = 0;
michael@0 2336 }
michael@0 2337
michael@0 2338 if (flags & MOZ_GTK_TAB_BOTTOM) {
michael@0 2339 /* Draw the tab */
michael@0 2340 focusRect.y += gap_voffset;
michael@0 2341 focusRect.height -= gap_voffset;
michael@0 2342 gtk_paint_extension(style, drawable, GTK_STATE_NORMAL,
michael@0 2343 GTK_SHADOW_OUT, cliprect, gTabWidget, "tab",
michael@0 2344 rect->x, rect->y + gap_voffset, rect->width,
michael@0 2345 rect->height - gap_voffset, GTK_POS_TOP);
michael@0 2346
michael@0 2347 /* Draw the gap; erase with background color before painting in
michael@0 2348 * case theme does not */
michael@0 2349 gtk_style_apply_default_background(style, drawable, TRUE,
michael@0 2350 GTK_STATE_NORMAL, cliprect,
michael@0 2351 rect->x,
michael@0 2352 rect->y + gap_voffset
michael@0 2353 - gap_height,
michael@0 2354 rect->width, gap_height);
michael@0 2355 gtk_paint_box_gap(style, drawable, GTK_STATE_NORMAL, GTK_SHADOW_OUT,
michael@0 2356 cliprect, gTabWidget, "notebook",
michael@0 2357 rect->x - gap_loffset,
michael@0 2358 rect->y + gap_voffset - 3 * gap_height,
michael@0 2359 rect->width + gap_loffset + gap_roffset,
michael@0 2360 3 * gap_height, GTK_POS_BOTTOM,
michael@0 2361 gap_loffset, rect->width);
michael@0 2362 } else {
michael@0 2363 /* Draw the tab */
michael@0 2364 focusRect.height -= gap_voffset;
michael@0 2365 gtk_paint_extension(style, drawable, GTK_STATE_NORMAL,
michael@0 2366 GTK_SHADOW_OUT, cliprect, gTabWidget, "tab",
michael@0 2367 rect->x, rect->y, rect->width,
michael@0 2368 rect->height - gap_voffset, GTK_POS_BOTTOM);
michael@0 2369
michael@0 2370 /* Draw the gap; erase with background color before painting in
michael@0 2371 * case theme does not */
michael@0 2372 gtk_style_apply_default_background(style, drawable, TRUE,
michael@0 2373 GTK_STATE_NORMAL, cliprect,
michael@0 2374 rect->x,
michael@0 2375 rect->y + rect->height
michael@0 2376 - gap_voffset,
michael@0 2377 rect->width, gap_height);
michael@0 2378 gtk_paint_box_gap(style, drawable, GTK_STATE_NORMAL, GTK_SHADOW_OUT,
michael@0 2379 cliprect, gTabWidget, "notebook",
michael@0 2380 rect->x - gap_loffset,
michael@0 2381 rect->y + rect->height - gap_voffset,
michael@0 2382 rect->width + gap_loffset + gap_roffset,
michael@0 2383 3 * gap_height, GTK_POS_TOP,
michael@0 2384 gap_loffset, rect->width);
michael@0 2385 }
michael@0 2386
michael@0 2387 }
michael@0 2388
michael@0 2389 if (state->focused) {
michael@0 2390 /* Paint the focus ring */
michael@0 2391 focusRect.x += XTHICKNESS(style);
michael@0 2392 focusRect.width -= XTHICKNESS(style) * 2;
michael@0 2393 focusRect.y += YTHICKNESS(style);
michael@0 2394 focusRect.height -= YTHICKNESS(style) * 2;
michael@0 2395
michael@0 2396 gtk_paint_focus(style, drawable,
michael@0 2397 /* Believe it or not, NORMAL means a selected tab and
michael@0 2398 ACTIVE means an unselected tab. */
michael@0 2399 (flags & MOZ_GTK_TAB_SELECTED) ? GTK_STATE_NORMAL
michael@0 2400 : GTK_STATE_ACTIVE,
michael@0 2401 cliprect, gTabWidget, "tab",
michael@0 2402 focusRect.x, focusRect.y, focusRect.width, focusRect.height);
michael@0 2403 }
michael@0 2404
michael@0 2405 return MOZ_GTK_SUCCESS;
michael@0 2406 }
michael@0 2407
michael@0 2408 static gint
michael@0 2409 moz_gtk_tabpanels_paint(GdkDrawable* drawable, GdkRectangle* rect,
michael@0 2410 GdkRectangle* cliprect, GtkTextDirection direction)
michael@0 2411 {
michael@0 2412 /* We have three problems here:
michael@0 2413 * - Most engines draw gtk_paint_box differently to gtk_paint_box_gap, the
michael@0 2414 * former implies there are no tabs, eg. Clearlooks.
michael@0 2415 * - Wanting a gap of width 0 doesn't actually guarantee a zero-width gap, eg.
michael@0 2416 * Clearlooks.
michael@0 2417 * - Our old approach of a negative X position could cause rendering errors
michael@0 2418 * on the box's corner, eg. themes using the Pixbuf engine.
michael@0 2419 */
michael@0 2420 GtkStyle* style;
michael@0 2421 GdkRectangle halfClipRect;
michael@0 2422
michael@0 2423 ensure_tab_widget();
michael@0 2424 gtk_widget_set_direction(gTabWidget, direction);
michael@0 2425
michael@0 2426 style = gTabWidget->style;
michael@0 2427 TSOffsetStyleGCs(style, rect->x, rect->y);
michael@0 2428
michael@0 2429 /* Our approach is as follows:
michael@0 2430 * - Draw the box in two passes. Pass in a clip rect to draw the left half of the
michael@0 2431 * box, with the gap specified to the right outside the clip rect so that it is
michael@0 2432 * not drawn.
michael@0 2433 * - The right half is drawn with the gap to the left outside the modified clip rect.
michael@0 2434 */
michael@0 2435 if (!gdk_rectangle_intersect(rect, cliprect, &halfClipRect))
michael@0 2436 return MOZ_GTK_SUCCESS;
michael@0 2437
michael@0 2438 halfClipRect.width = (halfClipRect.width / 2) + 1;
michael@0 2439 gtk_paint_box_gap(style, drawable, GTK_STATE_NORMAL, GTK_SHADOW_OUT,
michael@0 2440 &halfClipRect, gTabWidget, "notebook", rect->x, rect->y,
michael@0 2441 rect->width, rect->height,
michael@0 2442 GTK_POS_TOP, halfClipRect.width + 1, 0);
michael@0 2443
michael@0 2444 halfClipRect.x += halfClipRect.width;
michael@0 2445 gtk_paint_box_gap(style, drawable, GTK_STATE_NORMAL, GTK_SHADOW_OUT,
michael@0 2446 &halfClipRect, gTabWidget, "notebook", rect->x, rect->y,
michael@0 2447 rect->width, rect->height,
michael@0 2448 GTK_POS_TOP, -10, 0);
michael@0 2449
michael@0 2450 return MOZ_GTK_SUCCESS;
michael@0 2451 }
michael@0 2452
michael@0 2453 static gint
michael@0 2454 moz_gtk_tab_scroll_arrow_paint(GdkDrawable* drawable, GdkRectangle* rect,
michael@0 2455 GdkRectangle* cliprect, GtkWidgetState* state,
michael@0 2456 GtkArrowType arrow_type,
michael@0 2457 GtkTextDirection direction)
michael@0 2458 {
michael@0 2459 GtkStateType state_type = ConvertGtkState(state);
michael@0 2460 GtkShadowType shadow_type = state->active ? GTK_SHADOW_IN : GTK_SHADOW_OUT;
michael@0 2461 GtkStyle* style;
michael@0 2462 gint arrow_size = MIN(rect->width, rect->height);
michael@0 2463 gint x = rect->x + (rect->width - arrow_size) / 2;
michael@0 2464 gint y = rect->y + (rect->height - arrow_size) / 2;
michael@0 2465
michael@0 2466 ensure_tab_widget();
michael@0 2467
michael@0 2468 style = gTabWidget->style;
michael@0 2469 TSOffsetStyleGCs(style, rect->x, rect->y);
michael@0 2470
michael@0 2471 if (direction == GTK_TEXT_DIR_RTL) {
michael@0 2472 arrow_type = (arrow_type == GTK_ARROW_LEFT) ?
michael@0 2473 GTK_ARROW_RIGHT : GTK_ARROW_LEFT;
michael@0 2474 }
michael@0 2475
michael@0 2476 gtk_paint_arrow(style, drawable, state_type, shadow_type, NULL,
michael@0 2477 gTabWidget, "notebook", arrow_type, TRUE,
michael@0 2478 x, y, arrow_size, arrow_size);
michael@0 2479
michael@0 2480 return MOZ_GTK_SUCCESS;
michael@0 2481 }
michael@0 2482
michael@0 2483 static gint
michael@0 2484 moz_gtk_menu_bar_paint(GdkDrawable* drawable, GdkRectangle* rect,
michael@0 2485 GdkRectangle* cliprect, GtkTextDirection direction)
michael@0 2486 {
michael@0 2487 GtkStyle* style;
michael@0 2488 GtkShadowType shadow_type;
michael@0 2489 ensure_menu_bar_widget();
michael@0 2490 gtk_widget_set_direction(gMenuBarWidget, direction);
michael@0 2491
michael@0 2492 gtk_widget_style_get(gMenuBarWidget, "shadow-type", &shadow_type, NULL);
michael@0 2493
michael@0 2494 style = gMenuBarWidget->style;
michael@0 2495
michael@0 2496 TSOffsetStyleGCs(style, rect->x, rect->y);
michael@0 2497 gtk_style_apply_default_background(style, drawable, TRUE, GTK_STATE_NORMAL,
michael@0 2498 cliprect, rect->x, rect->y,
michael@0 2499 rect->width, rect->height);
michael@0 2500
michael@0 2501 gtk_paint_box(style, drawable, GTK_STATE_NORMAL, shadow_type,
michael@0 2502 cliprect, gMenuBarWidget, "menubar", rect->x, rect->y,
michael@0 2503 rect->width, rect->height);
michael@0 2504 return MOZ_GTK_SUCCESS;
michael@0 2505 }
michael@0 2506
michael@0 2507 static gint
michael@0 2508 moz_gtk_menu_popup_paint(GdkDrawable* drawable, GdkRectangle* rect,
michael@0 2509 GdkRectangle* cliprect, GtkTextDirection direction)
michael@0 2510 {
michael@0 2511 GtkStyle* style;
michael@0 2512 ensure_menu_popup_widget();
michael@0 2513 gtk_widget_set_direction(gMenuPopupWidget, direction);
michael@0 2514
michael@0 2515 style = gMenuPopupWidget->style;
michael@0 2516
michael@0 2517 TSOffsetStyleGCs(style, rect->x, rect->y);
michael@0 2518 gtk_style_apply_default_background(style, drawable, TRUE, GTK_STATE_NORMAL,
michael@0 2519 cliprect, rect->x, rect->y,
michael@0 2520 rect->width, rect->height);
michael@0 2521 gtk_paint_box(style, drawable, GTK_STATE_NORMAL, GTK_SHADOW_OUT,
michael@0 2522 cliprect, gMenuPopupWidget, "menu",
michael@0 2523 rect->x, rect->y, rect->width, rect->height);
michael@0 2524
michael@0 2525 return MOZ_GTK_SUCCESS;
michael@0 2526 }
michael@0 2527
michael@0 2528 static gint
michael@0 2529 moz_gtk_menu_separator_paint(GdkDrawable* drawable, GdkRectangle* rect,
michael@0 2530 GdkRectangle* cliprect, GtkTextDirection direction)
michael@0 2531 {
michael@0 2532 GtkStyle* style;
michael@0 2533 gboolean wide_separators;
michael@0 2534 gint separator_height;
michael@0 2535 guint horizontal_padding;
michael@0 2536 gint paint_height;
michael@0 2537
michael@0 2538 ensure_menu_separator_widget();
michael@0 2539 gtk_widget_set_direction(gMenuSeparatorWidget, direction);
michael@0 2540
michael@0 2541 style = gMenuSeparatorWidget->style;
michael@0 2542
michael@0 2543 gtk_widget_style_get(gMenuSeparatorWidget,
michael@0 2544 "wide-separators", &wide_separators,
michael@0 2545 "separator-height", &separator_height,
michael@0 2546 "horizontal-padding", &horizontal_padding,
michael@0 2547 NULL);
michael@0 2548
michael@0 2549 TSOffsetStyleGCs(style, rect->x, rect->y);
michael@0 2550
michael@0 2551 if (wide_separators) {
michael@0 2552 if (separator_height > rect->height)
michael@0 2553 separator_height = rect->height;
michael@0 2554
michael@0 2555 gtk_paint_box(style, drawable,
michael@0 2556 GTK_STATE_NORMAL, GTK_SHADOW_ETCHED_OUT,
michael@0 2557 cliprect, gMenuSeparatorWidget, "hseparator",
michael@0 2558 rect->x + horizontal_padding + style->xthickness,
michael@0 2559 rect->y + (rect->height - separator_height - style->ythickness) / 2,
michael@0 2560 rect->width - 2 * (horizontal_padding + style->xthickness),
michael@0 2561 separator_height);
michael@0 2562 } else {
michael@0 2563 paint_height = style->ythickness;
michael@0 2564 if (paint_height > rect->height)
michael@0 2565 paint_height = rect->height;
michael@0 2566
michael@0 2567 gtk_paint_hline(style, drawable,
michael@0 2568 GTK_STATE_NORMAL, cliprect, gMenuSeparatorWidget,
michael@0 2569 "menuitem",
michael@0 2570 rect->x + horizontal_padding + style->xthickness,
michael@0 2571 rect->x + rect->width - horizontal_padding - style->xthickness - 1,
michael@0 2572 rect->y + (rect->height - style->ythickness) / 2);
michael@0 2573 }
michael@0 2574
michael@0 2575 return MOZ_GTK_SUCCESS;
michael@0 2576 }
michael@0 2577
michael@0 2578 static gint
michael@0 2579 moz_gtk_menu_item_paint(GdkDrawable* drawable, GdkRectangle* rect,
michael@0 2580 GdkRectangle* cliprect, GtkWidgetState* state,
michael@0 2581 gint flags, GtkTextDirection direction)
michael@0 2582 {
michael@0 2583 GtkStyle* style;
michael@0 2584 GtkShadowType shadow_type;
michael@0 2585 GtkWidget* item_widget;
michael@0 2586
michael@0 2587 if (state->inHover && !state->disabled) {
michael@0 2588 if (flags & MOZ_TOPLEVEL_MENU_ITEM) {
michael@0 2589 ensure_menu_bar_item_widget();
michael@0 2590 item_widget = gMenuBarItemWidget;
michael@0 2591 } else {
michael@0 2592 ensure_menu_item_widget();
michael@0 2593 item_widget = gMenuItemWidget;
michael@0 2594 }
michael@0 2595 gtk_widget_set_direction(item_widget, direction);
michael@0 2596
michael@0 2597 style = item_widget->style;
michael@0 2598 TSOffsetStyleGCs(style, rect->x, rect->y);
michael@0 2599
michael@0 2600 gtk_widget_style_get(item_widget, "selected-shadow-type",
michael@0 2601 &shadow_type, NULL);
michael@0 2602
michael@0 2603 gtk_paint_box(style, drawable, GTK_STATE_PRELIGHT, shadow_type,
michael@0 2604 cliprect, item_widget, "menuitem", rect->x, rect->y,
michael@0 2605 rect->width, rect->height);
michael@0 2606 }
michael@0 2607
michael@0 2608 return MOZ_GTK_SUCCESS;
michael@0 2609 }
michael@0 2610
michael@0 2611 static gint
michael@0 2612 moz_gtk_menu_arrow_paint(GdkDrawable* drawable, GdkRectangle* rect,
michael@0 2613 GdkRectangle* cliprect, GtkWidgetState* state,
michael@0 2614 GtkTextDirection direction)
michael@0 2615 {
michael@0 2616 GtkStyle* style;
michael@0 2617 GtkStateType state_type = ConvertGtkState(state);
michael@0 2618
michael@0 2619 ensure_menu_item_widget();
michael@0 2620 gtk_widget_set_direction(gMenuItemWidget, direction);
michael@0 2621
michael@0 2622 style = gMenuItemWidget->style;
michael@0 2623
michael@0 2624 TSOffsetStyleGCs(style, rect->x, rect->y);
michael@0 2625 gtk_paint_arrow(style, drawable, state_type,
michael@0 2626 (state_type == GTK_STATE_PRELIGHT) ? GTK_SHADOW_IN : GTK_SHADOW_OUT,
michael@0 2627 cliprect, gMenuItemWidget, "menuitem",
michael@0 2628 (direction == GTK_TEXT_DIR_LTR) ? GTK_ARROW_RIGHT : GTK_ARROW_LEFT,
michael@0 2629 TRUE, rect->x, rect->y, rect->width, rect->height);
michael@0 2630
michael@0 2631 return MOZ_GTK_SUCCESS;
michael@0 2632 }
michael@0 2633
michael@0 2634 static gint
michael@0 2635 moz_gtk_check_menu_item_paint(GdkDrawable* drawable, GdkRectangle* rect,
michael@0 2636 GdkRectangle* cliprect, GtkWidgetState* state,
michael@0 2637 gboolean checked, gboolean isradio,
michael@0 2638 GtkTextDirection direction)
michael@0 2639 {
michael@0 2640 GtkStateType state_type = ConvertGtkState(state);
michael@0 2641 GtkStyle* style;
michael@0 2642 GtkShadowType shadow_type = (checked)?GTK_SHADOW_IN:GTK_SHADOW_OUT;
michael@0 2643 gint offset;
michael@0 2644 gint indicator_size, horizontal_padding;
michael@0 2645 gint x, y;
michael@0 2646
michael@0 2647 moz_gtk_menu_item_paint(drawable, rect, cliprect, state, FALSE, direction);
michael@0 2648
michael@0 2649 ensure_check_menu_item_widget();
michael@0 2650 gtk_widget_set_direction(gCheckMenuItemWidget, direction);
michael@0 2651
michael@0 2652 gtk_widget_style_get (gCheckMenuItemWidget,
michael@0 2653 "indicator-size", &indicator_size,
michael@0 2654 "horizontal-padding", &horizontal_padding,
michael@0 2655 NULL);
michael@0 2656
michael@0 2657 if (checked || GTK_CHECK_MENU_ITEM(gCheckMenuItemWidget)->always_show_toggle) {
michael@0 2658 style = gCheckMenuItemWidget->style;
michael@0 2659
michael@0 2660 offset = GTK_CONTAINER(gCheckMenuItemWidget)->border_width +
michael@0 2661 gCheckMenuItemWidget->style->xthickness + 2;
michael@0 2662
michael@0 2663 x = (direction == GTK_TEXT_DIR_RTL) ?
michael@0 2664 rect->width - indicator_size - offset - horizontal_padding: rect->x + offset + horizontal_padding;
michael@0 2665 y = rect->y + (rect->height - indicator_size) / 2;
michael@0 2666
michael@0 2667 TSOffsetStyleGCs(style, x, y);
michael@0 2668 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(gCheckMenuItemWidget),
michael@0 2669 checked);
michael@0 2670
michael@0 2671 if (isradio) {
michael@0 2672 gtk_paint_option(style, drawable, state_type, shadow_type, cliprect,
michael@0 2673 gCheckMenuItemWidget, "option",
michael@0 2674 x, y, indicator_size, indicator_size);
michael@0 2675 } else {
michael@0 2676 gtk_paint_check(style, drawable, state_type, shadow_type, cliprect,
michael@0 2677 gCheckMenuItemWidget, "check",
michael@0 2678 x, y, indicator_size, indicator_size);
michael@0 2679 }
michael@0 2680 }
michael@0 2681
michael@0 2682 return MOZ_GTK_SUCCESS;
michael@0 2683 }
michael@0 2684
michael@0 2685 static gint
michael@0 2686 moz_gtk_window_paint(GdkDrawable* drawable, GdkRectangle* rect,
michael@0 2687 GdkRectangle* cliprect, GtkTextDirection direction)
michael@0 2688 {
michael@0 2689 GtkStyle* style;
michael@0 2690
michael@0 2691 ensure_window_widget();
michael@0 2692 gtk_widget_set_direction(gProtoWindow, direction);
michael@0 2693
michael@0 2694 style = gProtoWindow->style;
michael@0 2695
michael@0 2696 TSOffsetStyleGCs(style, rect->x, rect->y);
michael@0 2697 gtk_style_apply_default_background(style, drawable, TRUE,
michael@0 2698 GTK_STATE_NORMAL,
michael@0 2699 cliprect, rect->x, rect->y,
michael@0 2700 rect->width, rect->height);
michael@0 2701 return MOZ_GTK_SUCCESS;
michael@0 2702 }
michael@0 2703
michael@0 2704 gint
michael@0 2705 moz_gtk_get_widget_border(GtkThemeWidgetType widget, gint* left, gint* top,
michael@0 2706 gint* right, gint* bottom, GtkTextDirection direction,
michael@0 2707 gboolean inhtml)
michael@0 2708 {
michael@0 2709 GtkWidget* w;
michael@0 2710
michael@0 2711 switch (widget) {
michael@0 2712 case MOZ_GTK_BUTTON:
michael@0 2713 {
michael@0 2714 GtkBorder inner_border;
michael@0 2715 gboolean interior_focus;
michael@0 2716 gint focus_width, focus_pad;
michael@0 2717
michael@0 2718 ensure_button_widget();
michael@0 2719 *left = *top = *right = *bottom = GTK_CONTAINER(gButtonWidget)->border_width;
michael@0 2720
michael@0 2721 /* Don't add this padding in HTML, otherwise the buttons will
michael@0 2722 become too big and stuff the layout. */
michael@0 2723 if (!inhtml) {
michael@0 2724 moz_gtk_widget_get_focus(gButtonWidget, &interior_focus, &focus_width, &focus_pad);
michael@0 2725 moz_gtk_button_get_inner_border(gButtonWidget, &inner_border);
michael@0 2726 *left += focus_width + focus_pad + inner_border.left;
michael@0 2727 *right += focus_width + focus_pad + inner_border.right;
michael@0 2728 *top += focus_width + focus_pad + inner_border.top;
michael@0 2729 *bottom += focus_width + focus_pad + inner_border.bottom;
michael@0 2730 }
michael@0 2731
michael@0 2732 *left += gButtonWidget->style->xthickness;
michael@0 2733 *right += gButtonWidget->style->xthickness;
michael@0 2734 *top += gButtonWidget->style->ythickness;
michael@0 2735 *bottom += gButtonWidget->style->ythickness;
michael@0 2736 return MOZ_GTK_SUCCESS;
michael@0 2737 }
michael@0 2738 case MOZ_GTK_ENTRY:
michael@0 2739 ensure_entry_widget();
michael@0 2740 w = gEntryWidget;
michael@0 2741 break;
michael@0 2742 case MOZ_GTK_TREEVIEW:
michael@0 2743 ensure_tree_view_widget();
michael@0 2744 w = gTreeViewWidget;
michael@0 2745 break;
michael@0 2746 case MOZ_GTK_TREE_HEADER_CELL:
michael@0 2747 {
michael@0 2748 /* A Tree Header in GTK is just a different styled button
michael@0 2749 * It must be placed in a TreeView for getting the correct style
michael@0 2750 * assigned.
michael@0 2751 * That is why the following code is the same as for MOZ_GTK_BUTTON.
michael@0 2752 * */
michael@0 2753
michael@0 2754 GtkBorder inner_border;
michael@0 2755 gboolean interior_focus;
michael@0 2756 gint focus_width, focus_pad;
michael@0 2757
michael@0 2758 ensure_tree_header_cell_widget();
michael@0 2759 *left = *top = *right = *bottom = GTK_CONTAINER(gTreeHeaderCellWidget)->border_width;
michael@0 2760
michael@0 2761 moz_gtk_widget_get_focus(gTreeHeaderCellWidget, &interior_focus, &focus_width, &focus_pad);
michael@0 2762 moz_gtk_button_get_inner_border(gTreeHeaderCellWidget, &inner_border);
michael@0 2763 *left += focus_width + focus_pad + inner_border.left;
michael@0 2764 *right += focus_width + focus_pad + inner_border.right;
michael@0 2765 *top += focus_width + focus_pad + inner_border.top;
michael@0 2766 *bottom += focus_width + focus_pad + inner_border.bottom;
michael@0 2767
michael@0 2768 *left += gTreeHeaderCellWidget->style->xthickness;
michael@0 2769 *right += gTreeHeaderCellWidget->style->xthickness;
michael@0 2770 *top += gTreeHeaderCellWidget->style->ythickness;
michael@0 2771 *bottom += gTreeHeaderCellWidget->style->ythickness;
michael@0 2772 return MOZ_GTK_SUCCESS;
michael@0 2773 }
michael@0 2774 case MOZ_GTK_TREE_HEADER_SORTARROW:
michael@0 2775 ensure_tree_header_cell_widget();
michael@0 2776 w = gTreeHeaderSortArrowWidget;
michael@0 2777 break;
michael@0 2778 case MOZ_GTK_DROPDOWN_ENTRY:
michael@0 2779 ensure_combo_box_entry_widgets();
michael@0 2780 w = gComboBoxEntryTextareaWidget;
michael@0 2781 break;
michael@0 2782 case MOZ_GTK_DROPDOWN_ARROW:
michael@0 2783 ensure_combo_box_entry_widgets();
michael@0 2784 w = gComboBoxEntryButtonWidget;
michael@0 2785 break;
michael@0 2786 case MOZ_GTK_DROPDOWN:
michael@0 2787 {
michael@0 2788 /* We need to account for the arrow on the dropdown, so text
michael@0 2789 * doesn't come too close to the arrow, or in some cases spill
michael@0 2790 * into the arrow. */
michael@0 2791 gboolean ignored_interior_focus, wide_separators;
michael@0 2792 gint focus_width, focus_pad, separator_width;
michael@0 2793 GtkRequisition arrow_req;
michael@0 2794
michael@0 2795 ensure_combo_box_widgets();
michael@0 2796
michael@0 2797 *left = GTK_CONTAINER(gComboBoxButtonWidget)->border_width;
michael@0 2798
michael@0 2799 if (!inhtml) {
michael@0 2800 moz_gtk_widget_get_focus(gComboBoxButtonWidget,
michael@0 2801 &ignored_interior_focus,
michael@0 2802 &focus_width, &focus_pad);
michael@0 2803 *left += focus_width + focus_pad;
michael@0 2804 }
michael@0 2805
michael@0 2806 *top = *left + gComboBoxButtonWidget->style->ythickness;
michael@0 2807 *left += gComboBoxButtonWidget->style->xthickness;
michael@0 2808
michael@0 2809 *right = *left; *bottom = *top;
michael@0 2810
michael@0 2811 /* If there is no separator, don't try to count its width. */
michael@0 2812 separator_width = 0;
michael@0 2813 if (gComboBoxSeparatorWidget) {
michael@0 2814 gtk_widget_style_get(gComboBoxSeparatorWidget,
michael@0 2815 "wide-separators", &wide_separators,
michael@0 2816 "separator-width", &separator_width,
michael@0 2817 NULL);
michael@0 2818
michael@0 2819 if (!wide_separators)
michael@0 2820 separator_width =
michael@0 2821 XTHICKNESS(gComboBoxSeparatorWidget->style);
michael@0 2822 }
michael@0 2823
michael@0 2824 gtk_widget_size_request(gComboBoxArrowWidget, &arrow_req);
michael@0 2825
michael@0 2826 if (direction == GTK_TEXT_DIR_RTL)
michael@0 2827 *left += separator_width + arrow_req.width;
michael@0 2828 else
michael@0 2829 *right += separator_width + arrow_req.width;
michael@0 2830
michael@0 2831 return MOZ_GTK_SUCCESS;
michael@0 2832 }
michael@0 2833 case MOZ_GTK_TABPANELS:
michael@0 2834 ensure_tab_widget();
michael@0 2835 w = gTabWidget;
michael@0 2836 break;
michael@0 2837 case MOZ_GTK_PROGRESSBAR:
michael@0 2838 ensure_progress_widget();
michael@0 2839 w = gProgressWidget;
michael@0 2840 break;
michael@0 2841 case MOZ_GTK_SPINBUTTON_ENTRY:
michael@0 2842 case MOZ_GTK_SPINBUTTON_UP:
michael@0 2843 case MOZ_GTK_SPINBUTTON_DOWN:
michael@0 2844 ensure_spin_widget();
michael@0 2845 w = gSpinWidget;
michael@0 2846 break;
michael@0 2847 case MOZ_GTK_SCALE_HORIZONTAL:
michael@0 2848 ensure_scale_widget();
michael@0 2849 w = gHScaleWidget;
michael@0 2850 break;
michael@0 2851 case MOZ_GTK_SCALE_VERTICAL:
michael@0 2852 ensure_scale_widget();
michael@0 2853 w = gVScaleWidget;
michael@0 2854 break;
michael@0 2855 case MOZ_GTK_FRAME:
michael@0 2856 ensure_frame_widget();
michael@0 2857 w = gFrameWidget;
michael@0 2858 break;
michael@0 2859 case MOZ_GTK_CHECKBUTTON_LABEL:
michael@0 2860 case MOZ_GTK_RADIOBUTTON_LABEL:
michael@0 2861 {
michael@0 2862 gboolean interior_focus;
michael@0 2863 gint focus_width, focus_pad;
michael@0 2864
michael@0 2865 /* If the focus is interior, then the label has a border of
michael@0 2866 (focus_width + focus_pad). */
michael@0 2867 if (widget == MOZ_GTK_CHECKBUTTON_LABEL) {
michael@0 2868 ensure_checkbox_widget();
michael@0 2869 moz_gtk_widget_get_focus(gCheckboxWidget, &interior_focus,
michael@0 2870 &focus_width, &focus_pad);
michael@0 2871 }
michael@0 2872 else {
michael@0 2873 ensure_radiobutton_widget();
michael@0 2874 moz_gtk_widget_get_focus(gRadiobuttonWidget, &interior_focus,
michael@0 2875 &focus_width, &focus_pad);
michael@0 2876 }
michael@0 2877
michael@0 2878 if (interior_focus)
michael@0 2879 *left = *top = *right = *bottom = (focus_width + focus_pad);
michael@0 2880 else
michael@0 2881 *left = *top = *right = *bottom = 0;
michael@0 2882
michael@0 2883 return MOZ_GTK_SUCCESS;
michael@0 2884 }
michael@0 2885
michael@0 2886 case MOZ_GTK_CHECKBUTTON_CONTAINER:
michael@0 2887 case MOZ_GTK_RADIOBUTTON_CONTAINER:
michael@0 2888 {
michael@0 2889 gboolean interior_focus;
michael@0 2890 gint focus_width, focus_pad;
michael@0 2891
michael@0 2892 /* If the focus is _not_ interior, then the container has a border
michael@0 2893 of (focus_width + focus_pad). */
michael@0 2894 if (widget == MOZ_GTK_CHECKBUTTON_CONTAINER) {
michael@0 2895 ensure_checkbox_widget();
michael@0 2896 moz_gtk_widget_get_focus(gCheckboxWidget, &interior_focus,
michael@0 2897 &focus_width, &focus_pad);
michael@0 2898 w = gCheckboxWidget;
michael@0 2899 } else {
michael@0 2900 ensure_radiobutton_widget();
michael@0 2901 moz_gtk_widget_get_focus(gRadiobuttonWidget, &interior_focus,
michael@0 2902 &focus_width, &focus_pad);
michael@0 2903 w = gRadiobuttonWidget;
michael@0 2904 }
michael@0 2905
michael@0 2906 *left = *top = *right = *bottom = GTK_CONTAINER(w)->border_width;
michael@0 2907
michael@0 2908 if (!interior_focus) {
michael@0 2909 *left += (focus_width + focus_pad);
michael@0 2910 *right += (focus_width + focus_pad);
michael@0 2911 *top += (focus_width + focus_pad);
michael@0 2912 *bottom += (focus_width + focus_pad);
michael@0 2913 }
michael@0 2914
michael@0 2915 return MOZ_GTK_SUCCESS;
michael@0 2916 }
michael@0 2917 case MOZ_GTK_MENUPOPUP:
michael@0 2918 ensure_menu_popup_widget();
michael@0 2919 w = gMenuPopupWidget;
michael@0 2920 break;
michael@0 2921 case MOZ_GTK_MENUITEM:
michael@0 2922 ensure_menu_item_widget();
michael@0 2923 ensure_menu_bar_item_widget();
michael@0 2924 w = gMenuItemWidget;
michael@0 2925 break;
michael@0 2926 case MOZ_GTK_CHECKMENUITEM:
michael@0 2927 case MOZ_GTK_RADIOMENUITEM:
michael@0 2928 ensure_check_menu_item_widget();
michael@0 2929 w = gCheckMenuItemWidget;
michael@0 2930 break;
michael@0 2931 case MOZ_GTK_TAB:
michael@0 2932 ensure_tab_widget();
michael@0 2933 w = gTabWidget;
michael@0 2934 break;
michael@0 2935 /* These widgets have no borders, since they are not containers. */
michael@0 2936 case MOZ_GTK_SPLITTER_HORIZONTAL:
michael@0 2937 case MOZ_GTK_SPLITTER_VERTICAL:
michael@0 2938 case MOZ_GTK_CHECKBUTTON:
michael@0 2939 case MOZ_GTK_RADIOBUTTON:
michael@0 2940 case MOZ_GTK_SCROLLBAR_BUTTON:
michael@0 2941 case MOZ_GTK_SCROLLBAR_TRACK_HORIZONTAL:
michael@0 2942 case MOZ_GTK_SCROLLBAR_TRACK_VERTICAL:
michael@0 2943 case MOZ_GTK_SCROLLBAR_THUMB_HORIZONTAL:
michael@0 2944 case MOZ_GTK_SCROLLBAR_THUMB_VERTICAL:
michael@0 2945 case MOZ_GTK_SCALE_THUMB_HORIZONTAL:
michael@0 2946 case MOZ_GTK_SCALE_THUMB_VERTICAL:
michael@0 2947 case MOZ_GTK_GRIPPER:
michael@0 2948 case MOZ_GTK_PROGRESS_CHUNK:
michael@0 2949 case MOZ_GTK_PROGRESS_CHUNK_INDETERMINATE:
michael@0 2950 case MOZ_GTK_PROGRESS_CHUNK_VERTICAL_INDETERMINATE:
michael@0 2951 case MOZ_GTK_TREEVIEW_EXPANDER:
michael@0 2952 case MOZ_GTK_TOOLBAR_SEPARATOR:
michael@0 2953 case MOZ_GTK_MENUSEPARATOR:
michael@0 2954 /* These widgets have no borders.*/
michael@0 2955 case MOZ_GTK_SPINBUTTON:
michael@0 2956 case MOZ_GTK_TOOLTIP:
michael@0 2957 case MOZ_GTK_WINDOW:
michael@0 2958 case MOZ_GTK_RESIZER:
michael@0 2959 case MOZ_GTK_MENUARROW:
michael@0 2960 case MOZ_GTK_TOOLBARBUTTON_ARROW:
michael@0 2961 case MOZ_GTK_TOOLBAR:
michael@0 2962 case MOZ_GTK_MENUBAR:
michael@0 2963 case MOZ_GTK_TAB_SCROLLARROW:
michael@0 2964 *left = *top = *right = *bottom = 0;
michael@0 2965 return MOZ_GTK_SUCCESS;
michael@0 2966 default:
michael@0 2967 g_warning("Unsupported widget type: %d", widget);
michael@0 2968 return MOZ_GTK_UNKNOWN_WIDGET;
michael@0 2969 }
michael@0 2970
michael@0 2971 *right = *left = XTHICKNESS(w->style);
michael@0 2972 *bottom = *top = YTHICKNESS(w->style);
michael@0 2973
michael@0 2974 return MOZ_GTK_SUCCESS;
michael@0 2975 }
michael@0 2976
michael@0 2977 gint
michael@0 2978 moz_gtk_get_combo_box_entry_button_size(gint* width, gint* height)
michael@0 2979 {
michael@0 2980 /*
michael@0 2981 * We get the requisition of the drop down button, which includes
michael@0 2982 * all padding, border and focus line widths the button uses,
michael@0 2983 * as well as the minimum arrow size and its padding
michael@0 2984 * */
michael@0 2985 GtkRequisition requisition;
michael@0 2986 ensure_combo_box_entry_widgets();
michael@0 2987
michael@0 2988 gtk_widget_size_request(gComboBoxEntryButtonWidget, &requisition);
michael@0 2989 *width = requisition.width;
michael@0 2990 *height = requisition.height;
michael@0 2991
michael@0 2992 return MOZ_GTK_SUCCESS;
michael@0 2993 }
michael@0 2994
michael@0 2995 gint
michael@0 2996 moz_gtk_get_tab_scroll_arrow_size(gint* width, gint* height)
michael@0 2997 {
michael@0 2998 gint arrow_size;
michael@0 2999
michael@0 3000 ensure_tab_widget();
michael@0 3001 gtk_widget_style_get(gTabWidget,
michael@0 3002 "scroll-arrow-hlength", &arrow_size,
michael@0 3003 NULL);
michael@0 3004
michael@0 3005 *height = *width = arrow_size;
michael@0 3006
michael@0 3007 return MOZ_GTK_SUCCESS;
michael@0 3008 }
michael@0 3009
michael@0 3010 gint
michael@0 3011 moz_gtk_get_arrow_size(gint* width, gint* height)
michael@0 3012 {
michael@0 3013 GtkRequisition requisition;
michael@0 3014 ensure_button_arrow_widget();
michael@0 3015
michael@0 3016 gtk_widget_size_request(gButtonArrowWidget, &requisition);
michael@0 3017 *width = requisition.width;
michael@0 3018 *height = requisition.height;
michael@0 3019
michael@0 3020 return MOZ_GTK_SUCCESS;
michael@0 3021 }
michael@0 3022
michael@0 3023 gint
michael@0 3024 moz_gtk_get_toolbar_separator_width(gint* size)
michael@0 3025 {
michael@0 3026 gboolean wide_separators;
michael@0 3027 gint separator_width;
michael@0 3028 GtkStyle* style;
michael@0 3029
michael@0 3030 ensure_toolbar_widget();
michael@0 3031
michael@0 3032 style = gToolbarWidget->style;
michael@0 3033
michael@0 3034 gtk_widget_style_get(gToolbarWidget,
michael@0 3035 "space-size", size,
michael@0 3036 "wide-separators", &wide_separators,
michael@0 3037 "separator-width", &separator_width,
michael@0 3038 NULL);
michael@0 3039
michael@0 3040 /* Just in case... */
michael@0 3041 *size = MAX(*size, (wide_separators ? separator_width : style->xthickness));
michael@0 3042
michael@0 3043 return MOZ_GTK_SUCCESS;
michael@0 3044 }
michael@0 3045
michael@0 3046 gint
michael@0 3047 moz_gtk_get_expander_size(gint* size)
michael@0 3048 {
michael@0 3049 ensure_expander_widget();
michael@0 3050 gtk_widget_style_get(gExpanderWidget,
michael@0 3051 "expander-size", size,
michael@0 3052 NULL);
michael@0 3053
michael@0 3054 return MOZ_GTK_SUCCESS;
michael@0 3055 }
michael@0 3056
michael@0 3057 gint
michael@0 3058 moz_gtk_get_treeview_expander_size(gint* size)
michael@0 3059 {
michael@0 3060 ensure_tree_view_widget();
michael@0 3061 gtk_widget_style_get(gTreeViewWidget,
michael@0 3062 "expander-size", size,
michael@0 3063 NULL);
michael@0 3064
michael@0 3065 return MOZ_GTK_SUCCESS;
michael@0 3066 }
michael@0 3067
michael@0 3068 gint
michael@0 3069 moz_gtk_get_menu_separator_height(gint *size)
michael@0 3070 {
michael@0 3071 gboolean wide_separators;
michael@0 3072 gint separator_height;
michael@0 3073
michael@0 3074 ensure_menu_separator_widget();
michael@0 3075
michael@0 3076 gtk_widget_style_get(gMenuSeparatorWidget,
michael@0 3077 "wide-separators", &wide_separators,
michael@0 3078 "separator-height", &separator_height,
michael@0 3079 NULL);
michael@0 3080
michael@0 3081 if (wide_separators)
michael@0 3082 *size = separator_height + gMenuSeparatorWidget->style->ythickness;
michael@0 3083 else
michael@0 3084 *size = gMenuSeparatorWidget->style->ythickness * 2;
michael@0 3085
michael@0 3086 return MOZ_GTK_SUCCESS;
michael@0 3087 }
michael@0 3088
michael@0 3089 gint
michael@0 3090 moz_gtk_get_scalethumb_metrics(GtkOrientation orient, gint* thumb_length, gint* thumb_height)
michael@0 3091 {
michael@0 3092 GtkWidget* widget;
michael@0 3093
michael@0 3094 ensure_scale_widget();
michael@0 3095 widget = ((orient == GTK_ORIENTATION_HORIZONTAL) ? gHScaleWidget : gVScaleWidget);
michael@0 3096
michael@0 3097 gtk_widget_style_get (widget,
michael@0 3098 "slider_length", thumb_length,
michael@0 3099 "slider_width", thumb_height,
michael@0 3100 NULL);
michael@0 3101
michael@0 3102 return MOZ_GTK_SUCCESS;
michael@0 3103 }
michael@0 3104
michael@0 3105 gint
michael@0 3106 moz_gtk_get_scrollbar_metrics(MozGtkScrollbarMetrics *metrics)
michael@0 3107 {
michael@0 3108 ensure_scrollbar_widget();
michael@0 3109
michael@0 3110 gtk_widget_style_get (gHorizScrollbarWidget,
michael@0 3111 "slider_width", &metrics->slider_width,
michael@0 3112 "trough_border", &metrics->trough_border,
michael@0 3113 "stepper_size", &metrics->stepper_size,
michael@0 3114 "stepper_spacing", &metrics->stepper_spacing,
michael@0 3115 NULL);
michael@0 3116
michael@0 3117 metrics->min_slider_size =
michael@0 3118 GTK_RANGE(gHorizScrollbarWidget)->min_slider_size;
michael@0 3119
michael@0 3120 return MOZ_GTK_SUCCESS;
michael@0 3121 }
michael@0 3122
michael@0 3123 gboolean
michael@0 3124 moz_gtk_images_in_menus()
michael@0 3125 {
michael@0 3126 gboolean result;
michael@0 3127 GtkSettings* settings;
michael@0 3128
michael@0 3129 ensure_image_menu_item_widget();
michael@0 3130 settings = gtk_widget_get_settings(gImageMenuItemWidget);
michael@0 3131
michael@0 3132 g_object_get(settings, "gtk-menu-images", &result, NULL);
michael@0 3133 return result;
michael@0 3134 }
michael@0 3135
michael@0 3136 gboolean
michael@0 3137 moz_gtk_images_in_buttons()
michael@0 3138 {
michael@0 3139 gboolean result;
michael@0 3140 GtkSettings* settings;
michael@0 3141
michael@0 3142 ensure_button_widget();
michael@0 3143 settings = gtk_widget_get_settings(gButtonWidget);
michael@0 3144
michael@0 3145 g_object_get(settings, "gtk-button-images", &result, NULL);
michael@0 3146 return result;
michael@0 3147 }
michael@0 3148
michael@0 3149 gint
michael@0 3150 moz_gtk_widget_paint(GtkThemeWidgetType widget, GdkDrawable* drawable,
michael@0 3151 GdkRectangle* rect, GdkRectangle* cliprect,
michael@0 3152 GtkWidgetState* state, gint flags,
michael@0 3153 GtkTextDirection direction)
michael@0 3154 {
michael@0 3155 switch (widget) {
michael@0 3156 case MOZ_GTK_BUTTON:
michael@0 3157 if (state->depressed) {
michael@0 3158 ensure_toggle_button_widget();
michael@0 3159 return moz_gtk_button_paint(drawable, rect, cliprect, state,
michael@0 3160 (GtkReliefStyle) flags,
michael@0 3161 gToggleButtonWidget, direction);
michael@0 3162 }
michael@0 3163 ensure_button_widget();
michael@0 3164 return moz_gtk_button_paint(drawable, rect, cliprect, state,
michael@0 3165 (GtkReliefStyle) flags, gButtonWidget,
michael@0 3166 direction);
michael@0 3167 break;
michael@0 3168 case MOZ_GTK_CHECKBUTTON:
michael@0 3169 case MOZ_GTK_RADIOBUTTON:
michael@0 3170 return moz_gtk_toggle_paint(drawable, rect, cliprect, state,
michael@0 3171 !!(flags & MOZ_GTK_WIDGET_CHECKED),
michael@0 3172 !!(flags & MOZ_GTK_WIDGET_INCONSISTENT),
michael@0 3173 (widget == MOZ_GTK_RADIOBUTTON),
michael@0 3174 direction);
michael@0 3175 break;
michael@0 3176 case MOZ_GTK_SCROLLBAR_BUTTON:
michael@0 3177 return moz_gtk_scrollbar_button_paint(drawable, rect, cliprect, state,
michael@0 3178 (GtkScrollbarButtonFlags) flags,
michael@0 3179 direction);
michael@0 3180 break;
michael@0 3181 case MOZ_GTK_SCROLLBAR_TRACK_HORIZONTAL:
michael@0 3182 case MOZ_GTK_SCROLLBAR_TRACK_VERTICAL:
michael@0 3183 return moz_gtk_scrollbar_trough_paint(widget, drawable, rect,
michael@0 3184 cliprect, state, direction);
michael@0 3185 break;
michael@0 3186 case MOZ_GTK_SCROLLBAR_THUMB_HORIZONTAL:
michael@0 3187 case MOZ_GTK_SCROLLBAR_THUMB_VERTICAL:
michael@0 3188 return moz_gtk_scrollbar_thumb_paint(widget, drawable, rect,
michael@0 3189 cliprect, state, direction);
michael@0 3190 break;
michael@0 3191 case MOZ_GTK_SCALE_HORIZONTAL:
michael@0 3192 case MOZ_GTK_SCALE_VERTICAL:
michael@0 3193 return moz_gtk_scale_paint(drawable, rect, cliprect, state,
michael@0 3194 (GtkOrientation) flags, direction);
michael@0 3195 break;
michael@0 3196 case MOZ_GTK_SCALE_THUMB_HORIZONTAL:
michael@0 3197 case MOZ_GTK_SCALE_THUMB_VERTICAL:
michael@0 3198 return moz_gtk_scale_thumb_paint(drawable, rect, cliprect, state,
michael@0 3199 (GtkOrientation) flags, direction);
michael@0 3200 break;
michael@0 3201 case MOZ_GTK_SPINBUTTON:
michael@0 3202 return moz_gtk_spin_paint(drawable, rect, direction);
michael@0 3203 break;
michael@0 3204 case MOZ_GTK_SPINBUTTON_UP:
michael@0 3205 case MOZ_GTK_SPINBUTTON_DOWN:
michael@0 3206 return moz_gtk_spin_updown_paint(drawable, rect,
michael@0 3207 (widget == MOZ_GTK_SPINBUTTON_DOWN),
michael@0 3208 state, direction);
michael@0 3209 break;
michael@0 3210 case MOZ_GTK_SPINBUTTON_ENTRY:
michael@0 3211 ensure_spin_widget();
michael@0 3212 return moz_gtk_entry_paint(drawable, rect, cliprect, state,
michael@0 3213 gSpinWidget, direction);
michael@0 3214 break;
michael@0 3215 case MOZ_GTK_GRIPPER:
michael@0 3216 return moz_gtk_gripper_paint(drawable, rect, cliprect, state,
michael@0 3217 direction);
michael@0 3218 break;
michael@0 3219 case MOZ_GTK_TREEVIEW:
michael@0 3220 return moz_gtk_treeview_paint(drawable, rect, cliprect, state,
michael@0 3221 direction);
michael@0 3222 break;
michael@0 3223 case MOZ_GTK_TREE_HEADER_CELL:
michael@0 3224 return moz_gtk_tree_header_cell_paint(drawable, rect, cliprect, state,
michael@0 3225 flags, direction);
michael@0 3226 break;
michael@0 3227 case MOZ_GTK_TREE_HEADER_SORTARROW:
michael@0 3228 return moz_gtk_tree_header_sort_arrow_paint(drawable, rect, cliprect,
michael@0 3229 state,
michael@0 3230 (GtkArrowType) flags,
michael@0 3231 direction);
michael@0 3232 break;
michael@0 3233 case MOZ_GTK_TREEVIEW_EXPANDER:
michael@0 3234 return moz_gtk_treeview_expander_paint(drawable, rect, cliprect, state,
michael@0 3235 (GtkExpanderStyle) flags, direction);
michael@0 3236 break;
michael@0 3237 case MOZ_GTK_ENTRY:
michael@0 3238 ensure_entry_widget();
michael@0 3239 return moz_gtk_entry_paint(drawable, rect, cliprect, state,
michael@0 3240 gEntryWidget, direction);
michael@0 3241 break;
michael@0 3242 case MOZ_GTK_DROPDOWN:
michael@0 3243 return moz_gtk_combo_box_paint(drawable, rect, cliprect, state,
michael@0 3244 (gboolean) flags, direction);
michael@0 3245 break;
michael@0 3246 case MOZ_GTK_DROPDOWN_ARROW:
michael@0 3247 return moz_gtk_combo_box_entry_button_paint(drawable, rect, cliprect,
michael@0 3248 state, flags, direction);
michael@0 3249 break;
michael@0 3250 case MOZ_GTK_DROPDOWN_ENTRY:
michael@0 3251 ensure_combo_box_entry_widgets();
michael@0 3252 return moz_gtk_entry_paint(drawable, rect, cliprect, state,
michael@0 3253 gComboBoxEntryTextareaWidget, direction);
michael@0 3254 break;
michael@0 3255 case MOZ_GTK_CHECKBUTTON_CONTAINER:
michael@0 3256 case MOZ_GTK_RADIOBUTTON_CONTAINER:
michael@0 3257 return moz_gtk_container_paint(drawable, rect, cliprect, state,
michael@0 3258 (widget == MOZ_GTK_RADIOBUTTON_CONTAINER),
michael@0 3259 direction);
michael@0 3260 break;
michael@0 3261 case MOZ_GTK_CHECKBUTTON_LABEL:
michael@0 3262 case MOZ_GTK_RADIOBUTTON_LABEL:
michael@0 3263 return moz_gtk_toggle_label_paint(drawable, rect, cliprect, state,
michael@0 3264 (widget == MOZ_GTK_RADIOBUTTON_LABEL),
michael@0 3265 direction);
michael@0 3266 break;
michael@0 3267 case MOZ_GTK_TOOLBAR:
michael@0 3268 return moz_gtk_toolbar_paint(drawable, rect, cliprect, direction);
michael@0 3269 break;
michael@0 3270 case MOZ_GTK_TOOLBAR_SEPARATOR:
michael@0 3271 return moz_gtk_toolbar_separator_paint(drawable, rect, cliprect,
michael@0 3272 direction);
michael@0 3273 break;
michael@0 3274 case MOZ_GTK_TOOLTIP:
michael@0 3275 return moz_gtk_tooltip_paint(drawable, rect, cliprect, direction);
michael@0 3276 break;
michael@0 3277 case MOZ_GTK_FRAME:
michael@0 3278 return moz_gtk_frame_paint(drawable, rect, cliprect, direction);
michael@0 3279 break;
michael@0 3280 case MOZ_GTK_RESIZER:
michael@0 3281 return moz_gtk_resizer_paint(drawable, rect, cliprect, state,
michael@0 3282 direction);
michael@0 3283 break;
michael@0 3284 case MOZ_GTK_PROGRESSBAR:
michael@0 3285 return moz_gtk_progressbar_paint(drawable, rect, cliprect, direction);
michael@0 3286 break;
michael@0 3287 case MOZ_GTK_PROGRESS_CHUNK:
michael@0 3288 case MOZ_GTK_PROGRESS_CHUNK_INDETERMINATE:
michael@0 3289 case MOZ_GTK_PROGRESS_CHUNK_VERTICAL_INDETERMINATE:
michael@0 3290 return moz_gtk_progress_chunk_paint(drawable, rect, cliprect,
michael@0 3291 direction, widget);
michael@0 3292 break;
michael@0 3293 case MOZ_GTK_TAB:
michael@0 3294 return moz_gtk_tab_paint(drawable, rect, cliprect, state,
michael@0 3295 (GtkTabFlags) flags, direction);
michael@0 3296 break;
michael@0 3297 case MOZ_GTK_TABPANELS:
michael@0 3298 return moz_gtk_tabpanels_paint(drawable, rect, cliprect, direction);
michael@0 3299 break;
michael@0 3300 case MOZ_GTK_TAB_SCROLLARROW:
michael@0 3301 return moz_gtk_tab_scroll_arrow_paint(drawable, rect, cliprect, state,
michael@0 3302 (GtkArrowType) flags, direction);
michael@0 3303 break;
michael@0 3304 case MOZ_GTK_MENUBAR:
michael@0 3305 return moz_gtk_menu_bar_paint(drawable, rect, cliprect, direction);
michael@0 3306 break;
michael@0 3307 case MOZ_GTK_MENUPOPUP:
michael@0 3308 return moz_gtk_menu_popup_paint(drawable, rect, cliprect, direction);
michael@0 3309 break;
michael@0 3310 case MOZ_GTK_MENUSEPARATOR:
michael@0 3311 return moz_gtk_menu_separator_paint(drawable, rect, cliprect,
michael@0 3312 direction);
michael@0 3313 break;
michael@0 3314 case MOZ_GTK_MENUITEM:
michael@0 3315 return moz_gtk_menu_item_paint(drawable, rect, cliprect, state, flags,
michael@0 3316 direction);
michael@0 3317 break;
michael@0 3318 case MOZ_GTK_MENUARROW:
michael@0 3319 return moz_gtk_menu_arrow_paint(drawable, rect, cliprect, state,
michael@0 3320 direction);
michael@0 3321 break;
michael@0 3322 case MOZ_GTK_TOOLBARBUTTON_ARROW:
michael@0 3323 return moz_gtk_arrow_paint(drawable, rect, cliprect, state,
michael@0 3324 (GtkArrowType) flags, direction);
michael@0 3325 break;
michael@0 3326 case MOZ_GTK_CHECKMENUITEM:
michael@0 3327 case MOZ_GTK_RADIOMENUITEM:
michael@0 3328 return moz_gtk_check_menu_item_paint(drawable, rect, cliprect, state,
michael@0 3329 (gboolean) flags,
michael@0 3330 (widget == MOZ_GTK_RADIOMENUITEM),
michael@0 3331 direction);
michael@0 3332 break;
michael@0 3333 case MOZ_GTK_SPLITTER_HORIZONTAL:
michael@0 3334 return moz_gtk_vpaned_paint(drawable, rect, cliprect, state);
michael@0 3335 break;
michael@0 3336 case MOZ_GTK_SPLITTER_VERTICAL:
michael@0 3337 return moz_gtk_hpaned_paint(drawable, rect, cliprect, state);
michael@0 3338 break;
michael@0 3339 case MOZ_GTK_WINDOW:
michael@0 3340 return moz_gtk_window_paint(drawable, rect, cliprect, direction);
michael@0 3341 break;
michael@0 3342 default:
michael@0 3343 g_warning("Unknown widget type: %d", widget);
michael@0 3344 }
michael@0 3345
michael@0 3346 return MOZ_GTK_UNKNOWN_WIDGET;
michael@0 3347 }
michael@0 3348
michael@0 3349 GtkWidget* moz_gtk_get_scrollbar_widget(void)
michael@0 3350 {
michael@0 3351 NS_ASSERTION(is_initialized, "Forgot to call moz_gtk_init()");
michael@0 3352 ensure_scrollbar_widget();
michael@0 3353 return gHorizScrollbarWidget;
michael@0 3354 }
michael@0 3355
michael@0 3356 gint
michael@0 3357 moz_gtk_shutdown()
michael@0 3358 {
michael@0 3359 GtkWidgetClass *entry_class;
michael@0 3360
michael@0 3361 if (gTooltipWidget)
michael@0 3362 gtk_widget_destroy(gTooltipWidget);
michael@0 3363 /* This will destroy all of our widgets */
michael@0 3364 if (gProtoWindow)
michael@0 3365 gtk_widget_destroy(gProtoWindow);
michael@0 3366
michael@0 3367 gProtoWindow = NULL;
michael@0 3368 gProtoLayout = NULL;
michael@0 3369 gButtonWidget = NULL;
michael@0 3370 gToggleButtonWidget = NULL;
michael@0 3371 gButtonArrowWidget = NULL;
michael@0 3372 gCheckboxWidget = NULL;
michael@0 3373 gRadiobuttonWidget = NULL;
michael@0 3374 gHorizScrollbarWidget = NULL;
michael@0 3375 gVertScrollbarWidget = NULL;
michael@0 3376 gSpinWidget = NULL;
michael@0 3377 gHScaleWidget = NULL;
michael@0 3378 gVScaleWidget = NULL;
michael@0 3379 gEntryWidget = NULL;
michael@0 3380 gComboBoxWidget = NULL;
michael@0 3381 gComboBoxButtonWidget = NULL;
michael@0 3382 gComboBoxSeparatorWidget = NULL;
michael@0 3383 gComboBoxArrowWidget = NULL;
michael@0 3384 gComboBoxEntryWidget = NULL;
michael@0 3385 gComboBoxEntryButtonWidget = NULL;
michael@0 3386 gComboBoxEntryArrowWidget = NULL;
michael@0 3387 gComboBoxEntryTextareaWidget = NULL;
michael@0 3388 gHandleBoxWidget = NULL;
michael@0 3389 gToolbarWidget = NULL;
michael@0 3390 gStatusbarWidget = NULL;
michael@0 3391 gFrameWidget = NULL;
michael@0 3392 gProgressWidget = NULL;
michael@0 3393 gTabWidget = NULL;
michael@0 3394 gTooltipWidget = NULL;
michael@0 3395 gMenuBarWidget = NULL;
michael@0 3396 gMenuBarItemWidget = NULL;
michael@0 3397 gMenuPopupWidget = NULL;
michael@0 3398 gMenuItemWidget = NULL;
michael@0 3399 gImageMenuItemWidget = NULL;
michael@0 3400 gCheckMenuItemWidget = NULL;
michael@0 3401 gTreeViewWidget = NULL;
michael@0 3402 gMiddleTreeViewColumn = NULL;
michael@0 3403 gTreeHeaderCellWidget = NULL;
michael@0 3404 gTreeHeaderSortArrowWidget = NULL;
michael@0 3405 gExpanderWidget = NULL;
michael@0 3406 gToolbarSeparatorWidget = NULL;
michael@0 3407 gMenuSeparatorWidget = NULL;
michael@0 3408 gHPanedWidget = NULL;
michael@0 3409 gVPanedWidget = NULL;
michael@0 3410 gScrolledWindowWidget = NULL;
michael@0 3411
michael@0 3412 entry_class = g_type_class_peek(GTK_TYPE_ENTRY);
michael@0 3413 g_type_class_unref(entry_class);
michael@0 3414
michael@0 3415 is_initialized = FALSE;
michael@0 3416
michael@0 3417 return MOZ_GTK_SUCCESS;
michael@0 3418 }

mercurial