widget/gtk/gtk3drawing.c

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

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

mercurial