1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 * This file contains painting functions for each of the gtk2 widgets.
8 * Adapted from the gtkdrawing.c, and gtk+2.0 source.
12 #include <gdk/gdkprivate.h>
14 #include "gtkdrawing.h"
20 static GtkWidget
* gProtoWindow
;
21 static GtkWidget
* gProtoLayout
;
22 static GtkWidget
* gButtonWidget
;
23 static GtkWidget
* gToggleButtonWidget
;
24 static GtkWidget
* gButtonArrowWidget
;
25 static GtkWidget
* gCheckboxWidget
;
26 static GtkWidget
* gRadiobuttonWidget
;
27 static GtkWidget
* gHorizScrollbarWidget
;
28 static GtkWidget
* gVertScrollbarWidget
;
29 static GtkWidget
* gSpinWidget
;
30 static GtkWidget
* gHScaleWidget
;
31 static GtkWidget
* gVScaleWidget
;
32 static GtkWidget
* gEntryWidget
;
33 static GtkWidget
* gComboBoxWidget
;
34 static GtkWidget
* gComboBoxButtonWidget
;
35 static GtkWidget
* gComboBoxArrowWidget
;
36 static GtkWidget
* gComboBoxSeparatorWidget
;
37 static GtkWidget
* gComboBoxEntryWidget
;
38 static GtkWidget
* gComboBoxEntryTextareaWidget
;
39 static GtkWidget
* gComboBoxEntryButtonWidget
;
40 static GtkWidget
* gComboBoxEntryArrowWidget
;
41 static GtkWidget
* gHandleBoxWidget
;
42 static GtkWidget
* gToolbarWidget
;
43 static GtkWidget
* gFrameWidget
;
44 static GtkWidget
* gStatusbarWidget
;
45 static GtkWidget
* gProgressWidget
;
46 static GtkWidget
* gTabWidget
;
47 static GtkWidget
* gTooltipWidget
;
48 static GtkWidget
* gMenuBarWidget
;
49 static GtkWidget
* gMenuBarItemWidget
;
50 static GtkWidget
* gMenuPopupWidget
;
51 static GtkWidget
* gMenuItemWidget
;
52 static GtkWidget
* gImageMenuItemWidget
;
53 static GtkWidget
* gCheckMenuItemWidget
;
54 static GtkWidget
* gTreeViewWidget
;
55 static GtkTreeViewColumn
* gMiddleTreeViewColumn
;
56 static GtkWidget
* gTreeHeaderCellWidget
;
57 static GtkWidget
* gTreeHeaderSortArrowWidget
;
58 static GtkWidget
* gExpanderWidget
;
59 static GtkWidget
* gToolbarSeparatorWidget
;
60 static GtkWidget
* gMenuSeparatorWidget
;
61 static GtkWidget
* gHPanedWidget
;
62 static GtkWidget
* gVPanedWidget
;
63 static GtkWidget
* gScrolledWindowWidget
;
65 static style_prop_t style_prop_func
;
66 static gboolean have_arrow_scaling
;
67 static gboolean is_initialized
;
70 #define ARROW_DOWN G_PI
71 #define ARROW_RIGHT G_PI_2
72 #define ARROW_LEFT (G_PI+G_PI_2)
75 GetStateFlagsFromGtkWidgetState(GtkWidgetState
* state
)
77 GtkStateFlags stateFlags
= GTK_STATE_FLAG_NORMAL
;
80 stateFlags
= GTK_STATE_FLAG_INSENSITIVE
;
82 if (state
->depressed
|| state
->active
)
83 stateFlags
|= GTK_STATE_FLAG_ACTIVE
;
85 stateFlags
|= GTK_STATE_FLAG_PRELIGHT
;
87 stateFlags
|= GTK_STATE_FLAG_FOCUSED
;
93 /* Because we have such an unconventional way of drawing widgets, signal to the GTK theme engine
94 that they are drawing for Mozilla instead of a conventional GTK app so they can do any specific
95 things they may want to do. */
97 moz_gtk_set_widget_name(GtkWidget
* widget
)
99 gtk_widget_set_name(widget
, "MozillaGtkWidget");
103 moz_gtk_enable_style_props(style_prop_t styleGetProp
)
105 style_prop_func
= styleGetProp
;
106 return MOZ_GTK_SUCCESS
;
110 ensure_window_widget()
113 gProtoWindow
= gtk_window_new(GTK_WINDOW_POPUP
);
114 gtk_widget_realize(gProtoWindow
);
115 moz_gtk_set_widget_name(gProtoWindow
);
117 return MOZ_GTK_SUCCESS
;
121 setup_widget_prototype(GtkWidget
* widget
)
123 ensure_window_widget();
125 gProtoLayout
= gtk_fixed_new();
126 gtk_container_add(GTK_CONTAINER(gProtoWindow
), gProtoLayout
);
129 gtk_container_add(GTK_CONTAINER(gProtoLayout
), widget
);
130 gtk_widget_realize(widget
);
131 return MOZ_GTK_SUCCESS
;
135 ensure_button_widget()
137 if (!gButtonWidget
) {
138 gButtonWidget
= gtk_button_new_with_label("M");
139 setup_widget_prototype(gButtonWidget
);
141 return MOZ_GTK_SUCCESS
;
145 ensure_hpaned_widget()
147 if (!gHPanedWidget
) {
148 gHPanedWidget
= gtk_paned_new(GTK_ORIENTATION_HORIZONTAL
);
149 setup_widget_prototype(gHPanedWidget
);
151 return MOZ_GTK_SUCCESS
;
155 ensure_vpaned_widget()
157 if (!gVPanedWidget
) {
158 gVPanedWidget
= gtk_paned_new(GTK_ORIENTATION_VERTICAL
);
159 setup_widget_prototype(gVPanedWidget
);
161 return MOZ_GTK_SUCCESS
;
165 ensure_toggle_button_widget()
167 if (!gToggleButtonWidget
) {
168 gToggleButtonWidget
= gtk_toggle_button_new();
169 setup_widget_prototype(gToggleButtonWidget
);
171 return MOZ_GTK_SUCCESS
;
175 ensure_button_arrow_widget()
177 if (!gButtonArrowWidget
) {
178 ensure_toggle_button_widget();
180 gButtonArrowWidget
= gtk_arrow_new(GTK_ARROW_DOWN
, GTK_SHADOW_OUT
);
181 gtk_container_add(GTK_CONTAINER(gToggleButtonWidget
), gButtonArrowWidget
);
182 gtk_widget_realize(gButtonArrowWidget
);
183 gtk_widget_show(gButtonArrowWidget
);
185 return MOZ_GTK_SUCCESS
;
189 ensure_checkbox_widget()
191 if (!gCheckboxWidget
) {
192 gCheckboxWidget
= gtk_check_button_new_with_label("M");
193 setup_widget_prototype(gCheckboxWidget
);
195 return MOZ_GTK_SUCCESS
;
199 ensure_radiobutton_widget()
201 if (!gRadiobuttonWidget
) {
202 gRadiobuttonWidget
= gtk_radio_button_new_with_label(NULL
, "M");
203 setup_widget_prototype(gRadiobuttonWidget
);
205 return MOZ_GTK_SUCCESS
;
209 ensure_scrollbar_widget()
211 if (!gVertScrollbarWidget
) {
212 gVertScrollbarWidget
= gtk_scrollbar_new(GTK_ORIENTATION_VERTICAL
, NULL
);
213 setup_widget_prototype(gVertScrollbarWidget
);
215 if (!gHorizScrollbarWidget
) {
216 gHorizScrollbarWidget
= gtk_scrollbar_new(GTK_ORIENTATION_HORIZONTAL
, NULL
);
217 setup_widget_prototype(gHorizScrollbarWidget
);
219 return MOZ_GTK_SUCCESS
;
226 gSpinWidget
= gtk_spin_button_new(NULL
, 1, 0);
227 setup_widget_prototype(gSpinWidget
);
229 return MOZ_GTK_SUCCESS
;
233 ensure_scale_widget()
235 if (!gHScaleWidget
) {
236 gHScaleWidget
= gtk_scale_new(GTK_ORIENTATION_HORIZONTAL
, NULL
);
237 setup_widget_prototype(gHScaleWidget
);
239 if (!gVScaleWidget
) {
240 gVScaleWidget
= gtk_scale_new(GTK_ORIENTATION_VERTICAL
, NULL
);
241 setup_widget_prototype(gVScaleWidget
);
243 return MOZ_GTK_SUCCESS
;
247 ensure_entry_widget()
250 gEntryWidget
= gtk_entry_new();
251 setup_widget_prototype(gEntryWidget
);
253 return MOZ_GTK_SUCCESS
;
256 /* We need to have pointers to the inner widgets (button, separator, arrow)
257 * of the ComboBox to get the correct rendering from theme engines which
258 * special cases their look. Since the inner layout can change, we ask GTK
259 * to NULL our pointers when they are about to become invalid because the
260 * corresponding widgets don't exist anymore. It's the role of
261 * g_object_add_weak_pointer().
262 * Note that if we don't find the inner widgets (which shouldn't happen), we
263 * fallback to use generic "non-inner" widgets, and they don't need that kind
264 * of weak pointer since they are explicit children of gProtoWindow and as
265 * such GTK holds a strong reference to them. */
267 moz_gtk_get_combo_box_inner_button(GtkWidget
*widget
, gpointer client_data
)
269 if (GTK_IS_TOGGLE_BUTTON(widget
)) {
270 gComboBoxButtonWidget
= widget
;
271 g_object_add_weak_pointer(G_OBJECT(widget
),
272 (gpointer
) &gComboBoxButtonWidget
);
273 gtk_widget_realize(widget
);
278 moz_gtk_get_combo_box_button_inner_widgets(GtkWidget
*widget
,
279 gpointer client_data
)
281 if (GTK_IS_SEPARATOR(widget
)) {
282 gComboBoxSeparatorWidget
= widget
;
283 g_object_add_weak_pointer(G_OBJECT(widget
),
284 (gpointer
) &gComboBoxSeparatorWidget
);
285 } else if (GTK_IS_ARROW(widget
)) {
286 gComboBoxArrowWidget
= widget
;
287 g_object_add_weak_pointer(G_OBJECT(widget
),
288 (gpointer
) &gComboBoxArrowWidget
);
291 gtk_widget_realize(widget
);
295 ensure_combo_box_widgets()
297 GtkWidget
* buttonChild
;
299 if (gComboBoxButtonWidget
&& gComboBoxArrowWidget
)
300 return MOZ_GTK_SUCCESS
;
302 /* Create a ComboBox if needed */
303 if (!gComboBoxWidget
) {
304 gComboBoxWidget
= gtk_combo_box_new();
305 setup_widget_prototype(gComboBoxWidget
);
308 /* Get its inner Button */
309 gtk_container_forall(GTK_CONTAINER(gComboBoxWidget
),
310 moz_gtk_get_combo_box_inner_button
,
313 if (gComboBoxButtonWidget
) {
314 /* Get the widgets inside the Button */
315 buttonChild
= gtk_bin_get_child(GTK_BIN(gComboBoxButtonWidget
));
316 if (GTK_IS_BOX(buttonChild
)) {
317 /* appears-as-list = FALSE, cell-view = TRUE; the button
318 * contains an hbox. This hbox is there because the ComboBox
319 * needs to place a cell renderer, a separator, and an arrow in
320 * the button when appears-as-list is FALSE. */
321 gtk_container_forall(GTK_CONTAINER(buttonChild
),
322 moz_gtk_get_combo_box_button_inner_widgets
,
324 } else if(GTK_IS_ARROW(buttonChild
)) {
325 /* appears-as-list = TRUE, or cell-view = FALSE;
326 * the button only contains an arrow */
327 gComboBoxArrowWidget
= buttonChild
;
328 g_object_add_weak_pointer(G_OBJECT(buttonChild
), (gpointer
)
329 &gComboBoxArrowWidget
);
330 gtk_widget_realize(gComboBoxArrowWidget
);
333 /* Shouldn't be reached with current internal gtk implementation; we
334 * use a generic toggle button as last resort fallback to avoid
336 ensure_toggle_button_widget();
337 gComboBoxButtonWidget
= gToggleButtonWidget
;
340 if (!gComboBoxArrowWidget
) {
341 /* Shouldn't be reached with current internal gtk implementation;
342 * we gButtonArrowWidget as last resort fallback to avoid
344 ensure_button_arrow_widget();
345 gComboBoxArrowWidget
= gButtonArrowWidget
;
348 /* We don't test the validity of gComboBoxSeparatorWidget since there
349 * is none when "appears-as-list" = TRUE or "cell-view" = FALSE; if it
350 * is invalid we just won't paint it. */
352 return MOZ_GTK_SUCCESS
;
355 /* We need to have pointers to the inner widgets (entry, button, arrow) of
356 * the ComboBoxEntry to get the correct rendering from theme engines which
357 * special cases their look. Since the inner layout can change, we ask GTK
358 * to NULL our pointers when they are about to become invalid because the
359 * corresponding widgets don't exist anymore. It's the role of
360 * g_object_add_weak_pointer().
361 * Note that if we don't find the inner widgets (which shouldn't happen), we
362 * fallback to use generic "non-inner" widgets, and they don't need that kind
363 * of weak pointer since they are explicit children of gProtoWindow and as
364 * such GTK holds a strong reference to them. */
366 moz_gtk_get_combo_box_entry_inner_widgets(GtkWidget
*widget
,
367 gpointer client_data
)
369 if (GTK_IS_TOGGLE_BUTTON(widget
)) {
370 gComboBoxEntryButtonWidget
= widget
;
371 g_object_add_weak_pointer(G_OBJECT(widget
),
372 (gpointer
) &gComboBoxEntryButtonWidget
);
373 } else if (GTK_IS_ENTRY(widget
)) {
374 gComboBoxEntryTextareaWidget
= widget
;
375 g_object_add_weak_pointer(G_OBJECT(widget
),
376 (gpointer
) &gComboBoxEntryTextareaWidget
);
379 gtk_widget_realize(widget
);
383 moz_gtk_get_combo_box_entry_arrow(GtkWidget
*widget
, gpointer client_data
)
385 if (GTK_IS_ARROW(widget
)) {
386 gComboBoxEntryArrowWidget
= widget
;
387 g_object_add_weak_pointer(G_OBJECT(widget
),
388 (gpointer
) &gComboBoxEntryArrowWidget
);
389 gtk_widget_realize(widget
);
394 ensure_combo_box_entry_widgets()
396 GtkWidget
* buttonChild
;
398 if (gComboBoxEntryTextareaWidget
&&
399 gComboBoxEntryButtonWidget
&&
400 gComboBoxEntryArrowWidget
)
401 return MOZ_GTK_SUCCESS
;
403 /* Create a ComboBoxEntry if needed */
404 if (!gComboBoxEntryWidget
) {
405 gComboBoxEntryWidget
= gtk_combo_box_new_with_entry();
406 setup_widget_prototype(gComboBoxEntryWidget
);
409 /* Get its inner Entry and Button */
410 gtk_container_forall(GTK_CONTAINER(gComboBoxEntryWidget
),
411 moz_gtk_get_combo_box_entry_inner_widgets
,
414 if (!gComboBoxEntryTextareaWidget
) {
415 ensure_entry_widget();
416 gComboBoxEntryTextareaWidget
= gEntryWidget
;
419 if (gComboBoxEntryButtonWidget
) {
420 /* Get the Arrow inside the Button */
421 buttonChild
= gtk_bin_get_child(GTK_BIN(gComboBoxEntryButtonWidget
));
422 if (GTK_IS_BOX(buttonChild
)) {
423 /* appears-as-list = FALSE, cell-view = TRUE; the button
424 * contains an hbox. This hbox is there because the ComboBox
425 * needs to place a cell renderer, a separator, and an arrow in
426 * the button when appears-as-list is FALSE. */
427 gtk_container_forall(GTK_CONTAINER(buttonChild
),
428 moz_gtk_get_combo_box_entry_arrow
,
430 } else if(GTK_IS_ARROW(buttonChild
)) {
431 /* appears-as-list = TRUE, or cell-view = FALSE;
432 * the button only contains an arrow */
433 gComboBoxEntryArrowWidget
= buttonChild
;
434 g_object_add_weak_pointer(G_OBJECT(buttonChild
), (gpointer
)
435 &gComboBoxEntryArrowWidget
);
436 gtk_widget_realize(gComboBoxEntryArrowWidget
);
439 /* Shouldn't be reached with current internal gtk implementation;
440 * we use a generic toggle button as last resort fallback to avoid
442 ensure_toggle_button_widget();
443 gComboBoxEntryButtonWidget
= gToggleButtonWidget
;
446 if (!gComboBoxEntryArrowWidget
) {
447 /* Shouldn't be reached with current internal gtk implementation;
448 * we gButtonArrowWidget as last resort fallback to avoid
450 ensure_button_arrow_widget();
451 gComboBoxEntryArrowWidget
= gButtonArrowWidget
;
454 return MOZ_GTK_SUCCESS
;
459 ensure_handlebox_widget()
461 if (!gHandleBoxWidget
) {
462 gHandleBoxWidget
= gtk_handle_box_new();
463 setup_widget_prototype(gHandleBoxWidget
);
465 return MOZ_GTK_SUCCESS
;
469 ensure_toolbar_widget()
471 if (!gToolbarWidget
) {
472 ensure_handlebox_widget();
473 gToolbarWidget
= gtk_toolbar_new();
474 gtk_container_add(GTK_CONTAINER(gHandleBoxWidget
), gToolbarWidget
);
475 gtk_widget_realize(gToolbarWidget
);
477 return MOZ_GTK_SUCCESS
;
481 ensure_toolbar_separator_widget()
483 if (!gToolbarSeparatorWidget
) {
484 ensure_toolbar_widget();
485 gToolbarSeparatorWidget
= GTK_WIDGET(gtk_separator_tool_item_new());
486 setup_widget_prototype(gToolbarSeparatorWidget
);
488 return MOZ_GTK_SUCCESS
;
492 ensure_tooltip_widget()
494 if (!gTooltipWidget
) {
495 gTooltipWidget
= gtk_window_new(GTK_WINDOW_POPUP
);
496 gtk_widget_realize(gTooltipWidget
);
497 moz_gtk_set_widget_name(gTooltipWidget
);
499 return MOZ_GTK_SUCCESS
;
506 gTabWidget
= gtk_notebook_new();
507 setup_widget_prototype(gTabWidget
);
509 return MOZ_GTK_SUCCESS
;
513 ensure_progress_widget()
515 if (!gProgressWidget
) {
516 gProgressWidget
= gtk_progress_bar_new();
517 setup_widget_prototype(gProgressWidget
);
519 return MOZ_GTK_SUCCESS
;
523 ensure_statusbar_widget()
525 if (!gStatusbarWidget
) {
526 gStatusbarWidget
= gtk_statusbar_new();
527 setup_widget_prototype(gStatusbarWidget
);
529 return MOZ_GTK_SUCCESS
;
533 ensure_frame_widget()
536 ensure_statusbar_widget();
537 gFrameWidget
= gtk_frame_new(NULL
);
538 gtk_container_add(GTK_CONTAINER(gStatusbarWidget
), gFrameWidget
);
539 gtk_widget_realize(gFrameWidget
);
541 return MOZ_GTK_SUCCESS
;
545 ensure_menu_bar_widget()
547 if (!gMenuBarWidget
) {
548 gMenuBarWidget
= gtk_menu_bar_new();
549 setup_widget_prototype(gMenuBarWidget
);
551 return MOZ_GTK_SUCCESS
;
555 ensure_menu_bar_item_widget()
557 if (!gMenuBarItemWidget
) {
558 ensure_menu_bar_widget();
559 gMenuBarItemWidget
= gtk_menu_item_new();
560 gtk_menu_shell_append(GTK_MENU_SHELL(gMenuBarWidget
),
562 gtk_widget_realize(gMenuBarItemWidget
);
564 return MOZ_GTK_SUCCESS
;
568 ensure_menu_popup_widget()
570 if (!gMenuPopupWidget
) {
571 ensure_menu_bar_item_widget();
572 gMenuPopupWidget
= gtk_menu_new();
573 gtk_menu_item_set_submenu(GTK_MENU_ITEM(gMenuBarItemWidget
),
575 gtk_widget_realize(gMenuPopupWidget
);
577 return MOZ_GTK_SUCCESS
;
581 ensure_menu_item_widget()
583 if (!gMenuItemWidget
) {
584 ensure_menu_popup_widget();
585 gMenuItemWidget
= gtk_menu_item_new_with_label("M");
586 gtk_menu_shell_append(GTK_MENU_SHELL(gMenuPopupWidget
),
588 gtk_widget_realize(gMenuItemWidget
);
590 return MOZ_GTK_SUCCESS
;
594 ensure_image_menu_item_widget()
596 if (!gImageMenuItemWidget
) {
597 ensure_menu_popup_widget();
598 gImageMenuItemWidget
= gtk_image_menu_item_new();
599 gtk_menu_shell_append(GTK_MENU_SHELL(gMenuPopupWidget
),
600 gImageMenuItemWidget
);
601 gtk_widget_realize(gImageMenuItemWidget
);
603 return MOZ_GTK_SUCCESS
;
607 ensure_menu_separator_widget()
609 if (!gMenuSeparatorWidget
) {
610 ensure_menu_popup_widget();
611 gMenuSeparatorWidget
= gtk_separator_menu_item_new();
612 gtk_menu_shell_append(GTK_MENU_SHELL(gMenuPopupWidget
),
613 gMenuSeparatorWidget
);
614 gtk_widget_realize(gMenuSeparatorWidget
);
616 return MOZ_GTK_SUCCESS
;
620 ensure_check_menu_item_widget()
622 if (!gCheckMenuItemWidget
) {
623 ensure_menu_popup_widget();
624 gCheckMenuItemWidget
= gtk_check_menu_item_new_with_label("M");
625 gtk_menu_shell_append(GTK_MENU_SHELL(gMenuPopupWidget
),
626 gCheckMenuItemWidget
);
627 gtk_widget_realize(gCheckMenuItemWidget
);
629 return MOZ_GTK_SUCCESS
;
633 ensure_tree_view_widget()
635 if (!gTreeViewWidget
) {
636 gTreeViewWidget
= gtk_tree_view_new();
637 setup_widget_prototype(gTreeViewWidget
);
639 return MOZ_GTK_SUCCESS
;
643 ensure_tree_header_cell_widget()
645 if(!gTreeHeaderCellWidget
) {
647 * Some GTK engines paint the first and last cell
648 * of a TreeView header with a highlight.
649 * Since we do not know where our widget will be relative
650 * to the other buttons in the TreeView header, we must
651 * paint it as a button that is between two others,
652 * thus ensuring it is neither the first or last button
654 * GTK doesn't give us a way to do this explicitly,
655 * so we must paint with a button that is between two
659 GtkTreeViewColumn
* firstTreeViewColumn
;
660 GtkTreeViewColumn
* lastTreeViewColumn
;
662 ensure_tree_view_widget();
664 /* Create and append our three columns */
665 firstTreeViewColumn
= gtk_tree_view_column_new();
666 gtk_tree_view_column_set_title(firstTreeViewColumn
, "M");
667 gtk_tree_view_append_column(GTK_TREE_VIEW(gTreeViewWidget
), firstTreeViewColumn
);
669 gMiddleTreeViewColumn
= gtk_tree_view_column_new();
670 gtk_tree_view_column_set_title(gMiddleTreeViewColumn
, "M");
671 gtk_tree_view_append_column(GTK_TREE_VIEW(gTreeViewWidget
),
672 gMiddleTreeViewColumn
);
674 lastTreeViewColumn
= gtk_tree_view_column_new();
675 gtk_tree_view_column_set_title(lastTreeViewColumn
, "M");
676 gtk_tree_view_append_column(GTK_TREE_VIEW(gTreeViewWidget
), lastTreeViewColumn
);
678 /* Use the middle column's header for our button */
679 gTreeHeaderCellWidget
= gtk_tree_view_column_get_button(gMiddleTreeViewColumn
);
680 /* TODO, but it can't be NULL */
681 gTreeHeaderSortArrowWidget
= gtk_button_new();
683 return MOZ_GTK_SUCCESS
;
687 ensure_expander_widget()
689 if (!gExpanderWidget
) {
690 gExpanderWidget
= gtk_expander_new("M");
691 setup_widget_prototype(gExpanderWidget
);
693 return MOZ_GTK_SUCCESS
;
697 ensure_scrolled_window_widget()
699 if (!gScrolledWindowWidget
) {
700 gScrolledWindowWidget
= gtk_scrolled_window_new(NULL
, NULL
);
701 setup_widget_prototype(gScrolledWindowWidget
);
703 return MOZ_GTK_SUCCESS
;
709 GtkWidgetClass
*entry_class
;
712 return MOZ_GTK_SUCCESS
;
714 is_initialized
= TRUE
;
715 have_arrow_scaling
= (gtk_major_version
> 2 ||
716 (gtk_major_version
== 2 && gtk_minor_version
>= 12));
718 /* Add style property to GtkEntry.
719 * Adding the style property to the normal GtkEntry class means that it
720 * will work without issues inside GtkComboBox and for Spinbuttons. */
721 entry_class
= g_type_class_ref(GTK_TYPE_ENTRY
);
723 return MOZ_GTK_SUCCESS
;
727 moz_gtk_checkbox_get_metrics(gint
* indicator_size
, gint
* indicator_spacing
)
729 ensure_checkbox_widget();
731 gtk_widget_style_get (gCheckboxWidget
,
732 "indicator_size", indicator_size
,
733 "indicator_spacing", indicator_spacing
,
736 return MOZ_GTK_SUCCESS
;
740 moz_gtk_radio_get_metrics(gint
* indicator_size
, gint
* indicator_spacing
)
742 ensure_radiobutton_widget();
744 gtk_widget_style_get (gRadiobuttonWidget
,
745 "indicator_size", indicator_size
,
746 "indicator_spacing", indicator_spacing
,
749 return MOZ_GTK_SUCCESS
;
753 moz_gtk_get_focus_outline_size(gint
* focus_h_width
, gint
* focus_v_width
)
755 gboolean interior_focus
;
756 gint focus_width
= 0;
758 ensure_entry_widget();
759 gtk_widget_style_get(gEntryWidget
,
760 "interior-focus", &interior_focus
,
761 "focus-line-width", &focus_width
,
763 if (interior_focus
) {
765 GtkStyleContext
*style
= gtk_widget_get_style_context(gEntryWidget
);
766 gtk_style_context_get_border(style
, 0, &border
);
767 *focus_h_width
= border
.left
+ focus_width
;
768 *focus_v_width
= border
.top
+ focus_width
;
770 *focus_h_width
= focus_width
;
771 *focus_v_width
= focus_width
;
773 return MOZ_GTK_SUCCESS
;
777 moz_gtk_widget_get_focus(GtkWidget
* widget
, gboolean
* interior_focus
,
778 gint
* focus_width
, gint
* focus_pad
)
780 gtk_widget_style_get (widget
,
781 "interior-focus", interior_focus
,
782 "focus-line-width", focus_width
,
783 "focus-padding", focus_pad
,
786 return MOZ_GTK_SUCCESS
;
790 moz_gtk_menuitem_get_horizontal_padding(gint
* horizontal_padding
)
792 ensure_menu_item_widget();
794 gtk_widget_style_get (gMenuItemWidget
,
795 "horizontal-padding", horizontal_padding
,
798 return MOZ_GTK_SUCCESS
;
802 moz_gtk_checkmenuitem_get_horizontal_padding(gint
* horizontal_padding
)
804 ensure_check_menu_item_widget();
806 gtk_widget_style_get (gCheckMenuItemWidget
,
807 "horizontal-padding", horizontal_padding
,
810 return MOZ_GTK_SUCCESS
;
814 moz_gtk_button_get_default_overflow(gint
* border_top
, gint
* border_left
,
815 gint
* border_bottom
, gint
* border_right
)
817 GtkBorder
* default_outside_border
;
819 ensure_button_widget();
820 gtk_widget_style_get(gButtonWidget
,
821 "default-outside-border", &default_outside_border
,
824 if (default_outside_border
) {
825 *border_top
= default_outside_border
->top
;
826 *border_left
= default_outside_border
->left
;
827 *border_bottom
= default_outside_border
->bottom
;
828 *border_right
= default_outside_border
->right
;
829 gtk_border_free(default_outside_border
);
831 *border_top
= *border_left
= *border_bottom
= *border_right
= 0;
833 return MOZ_GTK_SUCCESS
;
837 moz_gtk_button_get_default_border(gint
* border_top
, gint
* border_left
,
838 gint
* border_bottom
, gint
* border_right
)
840 GtkBorder
* default_border
;
842 ensure_button_widget();
843 gtk_widget_style_get(gButtonWidget
,
844 "default-border", &default_border
,
847 if (default_border
) {
848 *border_top
= default_border
->top
;
849 *border_left
= default_border
->left
;
850 *border_bottom
= default_border
->bottom
;
851 *border_right
= default_border
->right
;
852 gtk_border_free(default_border
);
854 /* see gtkbutton.c */
855 *border_top
= *border_left
= *border_bottom
= *border_right
= 1;
857 return MOZ_GTK_SUCCESS
;
861 moz_gtk_splitter_get_metrics(gint orientation
, gint
* size
)
863 if (orientation
== GTK_ORIENTATION_HORIZONTAL
) {
864 ensure_hpaned_widget();
865 gtk_widget_style_get(gHPanedWidget
, "handle_size", size
, NULL
);
867 ensure_vpaned_widget();
868 gtk_widget_style_get(gVPanedWidget
, "handle_size", size
, NULL
);
870 return MOZ_GTK_SUCCESS
;
874 moz_gtk_button_get_inner_border(GtkWidget
* widget
, GtkBorder
* inner_border
)
876 static const GtkBorder default_inner_border
= { 1, 1, 1, 1 };
877 GtkBorder
*tmp_border
;
879 gtk_widget_style_get (widget
, "inner-border", &tmp_border
, NULL
);
882 *inner_border
= *tmp_border
;
883 gtk_border_free(tmp_border
);
886 *inner_border
= default_inner_border
;
888 return MOZ_GTK_SUCCESS
;
892 moz_gtk_button_paint(cairo_t
*cr
, GdkRectangle
* rect
,
893 GtkWidgetState
* state
,
894 GtkReliefStyle relief
, GtkWidget
* widget
,
895 GtkTextDirection direction
)
897 GtkStateFlags state_flags
= GetStateFlagsFromGtkWidgetState(state
);
898 GtkStyleContext
* style
= gtk_widget_get_style_context(widget
);
899 gint x
= rect
->x
, y
=rect
->y
, width
=rect
->width
, height
=rect
->height
;
901 gboolean interior_focus
;
902 gint focus_width
, focus_pad
;
904 moz_gtk_widget_get_focus(widget
, &interior_focus
, &focus_width
, &focus_pad
);
905 gtk_widget_set_direction(widget
, direction
);
907 if (!interior_focus
&& state
->focused
) {
908 x
+= focus_width
+ focus_pad
;
909 y
+= focus_width
+ focus_pad
;
910 width
-= 2 * (focus_width
+ focus_pad
);
911 height
-= 2 * (focus_width
+ focus_pad
);
914 gtk_style_context_save(style
);
915 gtk_style_context_set_state(style
, state_flags
);
917 if (state
->isDefault
&& relief
== GTK_RELIEF_NORMAL
) {
918 /* handle default borders both outside and inside the button */
919 gint default_top
, default_left
, default_bottom
, default_right
;
920 moz_gtk_button_get_default_overflow(&default_top
, &default_left
,
921 &default_bottom
, &default_right
);
924 width
+= default_left
+ default_right
;
925 height
+= default_top
+ default_bottom
;
926 gtk_render_background(style
, cr
, x
, y
, width
, height
);
927 gtk_render_frame(style
, cr
, x
, y
, width
, height
);
928 moz_gtk_button_get_default_border(&default_top
, &default_left
,
929 &default_bottom
, &default_right
);
932 width
-= (default_left
+ default_right
);
933 height
-= (default_top
+ default_bottom
);
936 if (relief
!= GTK_RELIEF_NONE
|| state
->depressed
||
937 (state_flags
& GTK_STATE_FLAG_PRELIGHT
)) {
938 /* the following line can trigger an assertion (Crux theme)
939 file ../../gdk/gdkwindow.c: line 1846 (gdk_window_clear_area):
940 assertion `GDK_IS_WINDOW (window)' failed */
941 gtk_render_background(style
, cr
, x
, y
, width
, height
);
942 gtk_render_frame(style
, cr
, x
, y
, width
, height
);
945 if (state
->focused
) {
946 if (interior_focus
) {
948 gtk_style_context_get_border(style
, state_flags
, &border
);
949 x
+= border
.left
+ focus_pad
;
950 y
+= border
.top
+ focus_pad
;
951 width
-= 2 * (border
.left
+ focus_pad
);
952 height
-= 2 * (border
.top
+ focus_pad
);
954 x
-= focus_width
+ focus_pad
;
955 y
-= focus_width
+ focus_pad
;
956 width
+= 2 * (focus_width
+ focus_pad
);
957 height
+= 2 * (focus_width
+ focus_pad
);
960 gtk_render_focus(style
, cr
, x
, y
, width
, height
);
962 gtk_style_context_restore(style
);
963 return MOZ_GTK_SUCCESS
;
967 moz_gtk_toggle_paint(cairo_t
*cr
, GdkRectangle
* rect
,
968 GtkWidgetState
* state
,
969 gboolean selected
, gboolean inconsistent
,
970 gboolean isradio
, GtkTextDirection direction
)
972 gint indicator_size
, indicator_spacing
;
973 gint x
, y
, width
, height
;
974 gint focus_x
, focus_y
, focus_width
, focus_height
;
976 GtkStyleContext
*style
;
979 moz_gtk_radio_get_metrics(&indicator_size
, &indicator_spacing
);
980 w
= gRadiobuttonWidget
;
982 moz_gtk_checkbox_get_metrics(&indicator_size
, &indicator_spacing
);
986 // XXX we should assert rect->height >= indicator_size too
987 // after bug 369581 is fixed.
988 NS_ASSERTION(rect
->width
>= indicator_size
,
989 "GetMinimumWidgetSize was ignored");
991 // Paint it center aligned in the rect.
992 x
= rect
->x
+ (rect
->width
- indicator_size
) / 2;
993 y
= rect
->y
+ (rect
->height
- indicator_size
) / 2;
994 width
= indicator_size
;
995 height
= indicator_size
;
997 focus_x
= x
- indicator_spacing
;
998 focus_y
= y
- indicator_spacing
;
999 focus_width
= width
+ 2 * indicator_spacing
;
1000 focus_height
= height
+ 2 * indicator_spacing
;
1002 style
= gtk_widget_get_style_context(w
);
1004 gtk_widget_set_sensitive(w
, !state
->disabled
);
1005 gtk_widget_set_direction(w
, direction
);
1006 gtk_style_context_save(style
);
1009 gtk_style_context_add_class(style
, GTK_STYLE_CLASS_RADIO
);
1010 gtk_style_context_set_state(style
, selected
? GTK_STATE_FLAG_ACTIVE
:
1011 GTK_STATE_FLAG_NORMAL
);
1012 gtk_render_option(style
, cr
, x
, y
, width
, height
);
1013 if (state
->focused
) {
1014 gtk_render_focus(style
, cr
, focus_x
, focus_y
,
1015 focus_width
, focus_height
);
1020 * 'indeterminate' type on checkboxes. In GTK, the shadow type
1021 * must also be changed for the state to be drawn.
1023 gtk_style_context_add_class(style
, GTK_STYLE_CLASS_CHECK
);
1025 gtk_style_context_set_state(style
, GTK_STATE_FLAG_INCONSISTENT
);
1026 gtk_toggle_button_set_inconsistent(GTK_TOGGLE_BUTTON(gCheckboxWidget
), TRUE
);
1027 } else if (selected
) {
1028 gtk_style_context_set_state(style
, GTK_STATE_FLAG_ACTIVE
);
1030 gtk_toggle_button_set_inconsistent(GTK_TOGGLE_BUTTON(gCheckboxWidget
), FALSE
);
1032 gtk_render_check(style
, cr
, x
, y
, width
, height
);
1033 if (state
->focused
) {
1034 gtk_render_focus(style
, cr
,
1035 focus_x
, focus_y
, focus_width
, focus_height
);
1038 gtk_style_context_restore(style
);
1040 return MOZ_GTK_SUCCESS
;
1044 calculate_button_inner_rect(GtkWidget
* button
, GdkRectangle
* rect
,
1045 GdkRectangle
* inner_rect
,
1046 GtkTextDirection direction
,
1047 gboolean ignore_focus
)
1049 GtkBorder inner_border
;
1050 gboolean interior_focus
;
1051 gint focus_width
, focus_pad
;
1052 GtkStyleContext
* style
;
1055 style
= gtk_widget_get_style_context(button
);
1057 /* This mirrors gtkbutton's child positioning */
1058 moz_gtk_button_get_inner_border(button
, &inner_border
);
1059 moz_gtk_widget_get_focus(button
, &interior_focus
,
1060 &focus_width
, &focus_pad
);
1063 focus_width
= focus_pad
= 0;
1065 gtk_style_context_get_border(style
, 0, &border
);
1067 inner_rect
->x
= rect
->x
+ border
.left
+ focus_width
+ focus_pad
;
1068 inner_rect
->x
+= direction
== GTK_TEXT_DIR_LTR
?
1069 inner_border
.left
: inner_border
.right
;
1070 inner_rect
->y
= rect
->y
+ inner_border
.top
+ border
.top
+
1071 focus_width
+ focus_pad
;
1072 inner_rect
->width
= MAX(1, rect
->width
- inner_border
.left
-
1073 inner_border
.right
- (border
.left
+ focus_pad
+ focus_width
) * 2);
1074 inner_rect
->height
= MAX(1, rect
->height
- inner_border
.top
-
1075 inner_border
.bottom
- (border
.top
+ focus_pad
+ focus_width
) * 2);
1077 return MOZ_GTK_SUCCESS
;
1082 calculate_arrow_rect(GtkWidget
* arrow
, GdkRectangle
* rect
,
1083 GdkRectangle
* arrow_rect
, GtkTextDirection direction
)
1085 /* defined in gtkarrow.c */
1086 gfloat arrow_scaling
= 0.7;
1087 gfloat xalign
, xpad
;
1090 gfloat mxalign
, myalign
;
1091 GtkMisc
* misc
= GTK_MISC(arrow
);
1093 if (have_arrow_scaling
)
1094 gtk_widget_style_get(arrow
, "arrow_scaling", &arrow_scaling
, NULL
);
1096 gtk_misc_get_padding(misc
, &mxpad
, &mypad
);
1097 extent
= MIN((rect
->width
- mxpad
* 2),
1098 (rect
->height
- mypad
* 2)) * arrow_scaling
;
1100 gtk_misc_get_alignment(misc
, &mxalign
, &myalign
);
1102 xalign
= direction
== GTK_TEXT_DIR_LTR
? mxalign
: 1.0 - mxalign
;
1103 xpad
= mxpad
+ (rect
->width
- extent
) * xalign
;
1105 arrow_rect
->x
= direction
== GTK_TEXT_DIR_LTR
?
1106 floor(rect
->x
+ xpad
) : ceil(rect
->x
+ xpad
);
1107 arrow_rect
->y
= floor(rect
->y
+ mypad
+
1108 ((rect
->height
- extent
) * myalign
));
1110 arrow_rect
->width
= arrow_rect
->height
= extent
;
1112 return MOZ_GTK_SUCCESS
;
1116 moz_gtk_scrollbar_button_paint(cairo_t
*cr
, GdkRectangle
* rect
,
1117 GtkWidgetState
* state
,
1118 GtkScrollbarButtonFlags flags
,
1119 GtkTextDirection direction
)
1121 GtkStateFlags state_flags
= GetStateFlagsFromGtkWidgetState(state
);
1122 GtkStateType saved_state
;
1123 GdkRectangle arrow_rect
;
1124 gdouble arrow_angle
;
1125 GtkStyleContext
* style
;
1126 GtkWidget
*scrollbar
;
1127 gint arrow_displacement_x
, arrow_displacement_y
;
1128 const char* detail
= (flags
& MOZ_GTK_STEPPER_VERTICAL
) ?
1129 "vscrollbar" : "hscrollbar";
1131 ensure_scrollbar_widget();
1133 if (flags
& MOZ_GTK_STEPPER_VERTICAL
)
1134 scrollbar
= gVertScrollbarWidget
;
1136 scrollbar
= gHorizScrollbarWidget
;
1138 gtk_widget_set_direction(scrollbar
, direction
);
1140 if (flags
& MOZ_GTK_STEPPER_VERTICAL
) {
1141 arrow_angle
= (flags
& MOZ_GTK_STEPPER_DOWN
) ? ARROW_DOWN
: ARROW_UP
;
1143 arrow_angle
= (flags
& MOZ_GTK_STEPPER_DOWN
) ? ARROW_RIGHT
: ARROW_LEFT
;
1146 style
= gtk_widget_get_style_context(scrollbar
);
1148 gtk_style_context_save(style
);
1149 gtk_style_context_add_class(style
, GTK_STYLE_CLASS_SCROLLBAR
);
1150 gtk_style_context_set_state(style
, state_flags
);
1152 gtk_render_background(style
, cr
, rect
->x
, rect
->y
, rect
->width
, rect
->height
);
1153 gtk_render_frame(style
, cr
, rect
->x
, rect
->y
, rect
->width
, rect
->height
);
1155 arrow_rect
.width
= rect
->width
/ 2;
1156 arrow_rect
.height
= rect
->height
/ 2;
1157 arrow_rect
.x
= rect
->x
+ (rect
->width
- arrow_rect
.width
) / 2;
1158 arrow_rect
.y
= rect
->y
+ (rect
->height
- arrow_rect
.height
) / 2;
1160 if (state_flags
& GTK_STATE_FLAG_ACTIVE
) {
1161 gtk_widget_style_get(scrollbar
,
1162 "arrow-displacement-x", &arrow_displacement_x
,
1163 "arrow-displacement-y", &arrow_displacement_y
,
1166 arrow_rect
.x
+= arrow_displacement_x
;
1167 arrow_rect
.y
+= arrow_displacement_y
;
1170 gtk_render_arrow(style
, cr
, arrow_angle
,
1175 gtk_style_context_restore(style
);
1177 return MOZ_GTK_SUCCESS
;
1181 moz_gtk_scrollbar_trough_paint(GtkThemeWidgetType widget
,
1182 cairo_t
*cr
, GdkRectangle
* rect
,
1183 GtkWidgetState
* state
,
1184 GtkTextDirection direction
)
1186 GtkStyleContext
* style
;
1187 GtkScrollbar
*scrollbar
;
1189 ensure_scrollbar_widget();
1191 if (widget
== MOZ_GTK_SCROLLBAR_TRACK_HORIZONTAL
)
1192 scrollbar
= GTK_SCROLLBAR(gHorizScrollbarWidget
);
1194 scrollbar
= GTK_SCROLLBAR(gVertScrollbarWidget
);
1196 gtk_widget_set_direction(GTK_WIDGET(scrollbar
), direction
);
1198 style
= gtk_widget_get_style_context(GTK_WIDGET(scrollbar
));
1199 gtk_style_context_save(style
);
1200 gtk_style_context_add_class(style
, GTK_STYLE_CLASS_TROUGH
);
1202 gtk_render_background(style
, cr
, rect
->x
, rect
->y
, rect
->width
, rect
->height
);
1203 gtk_render_frame(style
, cr
, rect
->x
, rect
->y
, rect
->width
, rect
->height
);
1205 if (state
->focused
) {
1206 gtk_render_focus(style
, cr
,
1207 rect
->x
, rect
->y
, rect
->width
, rect
->height
);
1209 gtk_style_context_restore(style
);
1210 return MOZ_GTK_SUCCESS
;
1214 moz_gtk_scrollbar_thumb_paint(GtkThemeWidgetType widget
,
1215 cairo_t
*cr
, GdkRectangle
* rect
,
1216 GtkWidgetState
* state
,
1217 GtkTextDirection direction
)
1219 GtkStateFlags state_flags
= GetStateFlagsFromGtkWidgetState(state
);
1220 GtkStyleContext
* style
;
1221 GtkScrollbar
*scrollbar
;
1224 ensure_scrollbar_widget();
1226 if (widget
== MOZ_GTK_SCROLLBAR_THUMB_HORIZONTAL
)
1227 scrollbar
= GTK_SCROLLBAR(gHorizScrollbarWidget
);
1229 scrollbar
= GTK_SCROLLBAR(gVertScrollbarWidget
);
1231 gtk_widget_set_direction(GTK_WIDGET(scrollbar
), direction
);
1233 style
= gtk_widget_get_style_context(GTK_WIDGET(scrollbar
));
1234 gtk_style_context_save(style
);
1236 gtk_style_context_add_class(style
, GTK_STYLE_CLASS_SLIDER
);
1237 gtk_style_context_set_state(style
, state_flags
);
1239 gtk_render_slider(style
, cr
, rect
->x
, rect
->y
,
1240 rect
->width
, rect
->height
,
1241 (widget
== MOZ_GTK_SCROLLBAR_THUMB_HORIZONTAL
) ?
1242 GTK_ORIENTATION_HORIZONTAL
: GTK_ORIENTATION_VERTICAL
);
1244 gtk_style_context_restore(style
);
1246 return MOZ_GTK_SUCCESS
;
1250 moz_gtk_spin_paint(cairo_t
*cr
, GdkRectangle
* rect
,
1251 GtkTextDirection direction
)
1253 GtkStyleContext
* style
;
1255 ensure_spin_widget();
1256 gtk_widget_set_direction(gSpinWidget
, direction
);
1257 style
= gtk_widget_get_style_context(gSpinWidget
);
1258 gtk_style_context_save(style
);
1259 gtk_style_context_add_class(style
, GTK_STYLE_CLASS_SPINBUTTON
);
1260 gtk_render_background(style
, cr
, rect
->x
, rect
->y
, rect
->width
, rect
->height
);
1261 gtk_render_frame(style
, cr
, rect
->x
, rect
->y
, rect
->width
, rect
->height
);
1262 gtk_style_context_restore(style
);
1264 return MOZ_GTK_SUCCESS
;
1268 moz_gtk_spin_updown_paint(cairo_t
*cr
, GdkRectangle
* rect
,
1269 gboolean isDown
, GtkWidgetState
* state
,
1270 GtkTextDirection direction
)
1272 GdkRectangle arrow_rect
;
1273 GtkStyleContext
* style
;
1275 ensure_spin_widget();
1276 style
= gtk_widget_get_style_context(gSpinWidget
);
1277 gtk_style_context_save(style
);
1278 gtk_style_context_add_class(style
, GTK_STYLE_CLASS_SPINBUTTON
);
1279 gtk_style_context_set_state(style
, GetStateFlagsFromGtkWidgetState(state
));
1280 gtk_widget_set_direction(gSpinWidget
, direction
);
1282 gtk_render_background(style
, cr
, rect
->x
, rect
->y
, rect
->width
, rect
->height
);
1283 gtk_render_frame(style
, cr
, rect
->x
, rect
->y
, rect
->width
, rect
->height
);
1286 /* hard code these values */
1287 arrow_rect
.width
= 6;
1288 arrow_rect
.height
= 6;
1289 arrow_rect
.x
= rect
->x
+ (rect
->width
- arrow_rect
.width
) / 2;
1290 arrow_rect
.y
= rect
->y
+ (rect
->height
- arrow_rect
.height
) / 2;
1291 arrow_rect
.y
+= isDown
? -1 : 1;
1293 gtk_render_arrow(style
, cr
,
1294 isDown
? ARROW_DOWN
: ARROW_UP
,
1295 arrow_rect
.x
, arrow_rect
.y
,
1297 gtk_style_context_restore(style
);
1298 return MOZ_GTK_SUCCESS
;
1301 /* See gtk_range_draw() for reference.
1304 moz_gtk_scale_paint(cairo_t
*cr
, GdkRectangle
* rect
,
1305 GtkWidgetState
* state
,
1306 GtkOrientation flags
, GtkTextDirection direction
)
1308 GtkStateFlags state_flags
= GetStateFlagsFromGtkWidgetState(state
);
1310 GtkStyleContext
* style
;
1314 ensure_scale_widget();
1315 widget
= ((flags
== GTK_ORIENTATION_HORIZONTAL
) ? gHScaleWidget
: gVScaleWidget
);
1316 gtk_widget_set_direction(widget
, direction
);
1318 style
= gtk_widget_get_style_context(widget
);
1319 gtk_style_context_save(style
);
1320 gtk_style_context_add_class(style
, GTK_STYLE_CLASS_SCALE
);
1321 gtk_style_context_get_margin(style
, state_flags
, &margin
);
1323 if (flags
== GTK_ORIENTATION_HORIZONTAL
) {
1332 gtk_render_frame(style
, cr
, rect
->x
+ x
, rect
->y
+ y
,
1333 rect
->width
- 2*x
, rect
->height
- 2*y
);
1336 gtk_render_focus(style
, cr
,
1337 rect
->x
, rect
->y
, rect
->width
, rect
->height
);
1338 gtk_style_context_restore(style
);
1339 return MOZ_GTK_SUCCESS
;
1343 moz_gtk_scale_thumb_paint(cairo_t
*cr
, GdkRectangle
* rect
,
1344 GtkWidgetState
* state
,
1345 GtkOrientation flags
, GtkTextDirection direction
)
1347 GtkStateFlags state_flags
= GetStateFlagsFromGtkWidgetState(state
);
1348 GtkStyleContext
* style
;
1350 gint thumb_width
, thumb_height
, x
, y
;
1352 ensure_scale_widget();
1353 widget
= ((flags
== GTK_ORIENTATION_HORIZONTAL
) ? gHScaleWidget
: gVScaleWidget
);
1354 gtk_widget_set_direction(widget
, direction
);
1356 style
= gtk_widget_get_style_context(widget
);
1357 gtk_style_context_add_class(style
, GTK_STYLE_CLASS_SLIDER
);
1358 gtk_style_context_save(style
);
1359 gtk_style_context_set_state(style
, state_flags
);
1360 /* determine the thumb size, and position the thumb in the center in the opposite axis
1362 if (flags
== GTK_ORIENTATION_HORIZONTAL
) {
1363 moz_gtk_get_scalethumb_metrics(GTK_ORIENTATION_HORIZONTAL
, &thumb_width
, &thumb_height
);
1365 y
= rect
->y
+ (rect
->height
- thumb_height
) / 2;
1368 moz_gtk_get_scalethumb_metrics(GTK_ORIENTATION_VERTICAL
, &thumb_height
, &thumb_width
);
1369 x
= rect
->x
+ (rect
->width
- thumb_width
) / 2;
1373 gtk_render_slider(style
, cr
, x
, y
, thumb_width
, thumb_height
, flags
);
1374 gtk_style_context_restore(style
);
1375 return MOZ_GTK_SUCCESS
;
1379 moz_gtk_gripper_paint(cairo_t
*cr
, GdkRectangle
* rect
,
1380 GtkWidgetState
* state
,
1381 GtkTextDirection direction
)
1383 GtkStyleContext
* style
;
1385 ensure_handlebox_widget();
1386 gtk_widget_set_direction(gHandleBoxWidget
, direction
);
1388 style
= gtk_widget_get_style_context(gHandleBoxWidget
);
1389 gtk_style_context_save(style
);
1390 gtk_style_context_add_class(style
, GTK_STYLE_CLASS_GRIP
);
1391 gtk_style_context_set_state(style
, GetStateFlagsFromGtkWidgetState(state
));
1393 gtk_render_background(style
, cr
, rect
->x
, rect
->y
, rect
->width
, rect
->height
);
1394 gtk_render_frame(style
, cr
, rect
->x
, rect
->y
, rect
->width
, rect
->height
);
1395 gtk_style_context_restore(style
);
1397 return MOZ_GTK_SUCCESS
;
1401 moz_gtk_hpaned_paint(cairo_t
*cr
, GdkRectangle
* rect
,
1402 GtkWidgetState
* state
)
1404 GtkStyleContext
* style
;
1406 ensure_hpaned_widget();
1407 style
= gtk_widget_get_style_context(gHPanedWidget
);
1408 gtk_style_context_save(style
);
1409 gtk_style_context_add_class(style
, GTK_STYLE_CLASS_PANE_SEPARATOR
);
1410 gtk_style_context_set_state(style
, GetStateFlagsFromGtkWidgetState(state
));
1411 gtk_render_handle(style
, cr
,
1412 rect
->x
, rect
->y
, rect
->width
, rect
->height
);
1413 gtk_style_context_restore(style
);
1415 return MOZ_GTK_SUCCESS
;
1419 moz_gtk_vpaned_paint(cairo_t
*cr
, GdkRectangle
* rect
,
1420 GtkWidgetState
* state
)
1422 GtkStyleContext
* style
;
1424 ensure_vpaned_widget();
1425 style
= gtk_widget_get_style_context(gVPanedWidget
);
1426 gtk_style_context_save(style
);
1427 gtk_style_context_add_class(style
, GTK_STYLE_CLASS_PANE_SEPARATOR
);
1428 gtk_style_context_set_state(style
, GetStateFlagsFromGtkWidgetState(state
));
1429 gtk_render_handle(style
, cr
,
1430 rect
->x
, rect
->y
, rect
->width
, rect
->height
);
1431 gtk_style_context_restore(style
);
1433 return MOZ_GTK_SUCCESS
;
1436 // See gtk_entry_draw() for reference.
1438 moz_gtk_entry_paint(cairo_t
*cr
, GdkRectangle
* rect
,
1439 GtkWidgetState
* state
,
1440 GtkWidget
* widget
, GtkTextDirection direction
)
1442 gint x
= rect
->x
, y
= rect
->y
, width
= rect
->width
, height
= rect
->height
;
1443 GtkStyleContext
* style
;
1444 gboolean interior_focus
;
1446 int draw_focus_outline_only
= state
->depressed
; // NS_THEME_FOCUS_OUTLINE
1448 gtk_widget_set_direction(widget
, direction
);
1450 style
= gtk_widget_get_style_context(widget
);
1452 gtk_widget_style_get(widget
,
1453 "interior-focus", &interior_focus
,
1454 "focus-line-width", &focus_width
,
1457 if (draw_focus_outline_only
) {
1458 // Inflate the given 'rect' with the focus outline size.
1460 moz_gtk_get_focus_outline_size(&h
, &v
);
1462 rect
->width
+= 2 * h
;
1464 rect
->height
+= 2 * v
;
1465 width
= rect
->width
;
1466 height
= rect
->height
;
1469 /* gtkentry.c uses two windows, one for the entire widget and one for the
1470 * text area inside it. The background of both windows is set to the "base"
1471 * color of the new state in gtk_entry_state_changed, but only the inner
1472 * textarea window uses gtk_paint_flat_box when exposed */
1474 /* This gets us a lovely greyish disabledish look */
1475 gtk_widget_set_sensitive(widget
, !state
->disabled
);
1477 gtk_style_context_save(style
);
1478 gtk_style_context_add_class(style
, GTK_STYLE_CLASS_ENTRY
);
1480 /* Now paint the shadow and focus border.
1481 * We do like in gtk_entry_draw_frame, we first draw the shadow, a tad
1482 * smaller when focused if the focus is not interior, then the focus. */
1484 if (state
->focused
&& !state
->disabled
) {
1485 /* This will get us the lit borders that focused textboxes enjoy on
1487 gtk_style_context_set_state(style
, GTK_STATE_FLAG_FOCUSED
);
1488 if (!interior_focus
) {
1489 /* Indent the border a little bit if we have exterior focus
1490 (this is what GTK does to draw native entries) */
1493 width
-= 2 * focus_width
;
1494 height
-= 2 * focus_width
;
1498 if (state
->disabled
) {
1499 gtk_style_context_set_state(style
, GTK_STATE_FLAG_INSENSITIVE
);
1502 if (!draw_focus_outline_only
) {
1503 gtk_render_background(style
, cr
, x
, y
, width
, height
);
1505 gtk_render_frame(style
, cr
, x
, y
, width
, height
);
1507 if (state
->focused
&& !state
->disabled
) {
1508 if (!interior_focus
) {
1509 gtk_render_focus(style
, cr
, rect
->x
, rect
->y
, rect
->width
, rect
->height
);
1512 gtk_style_context_restore(style
);
1514 return MOZ_GTK_SUCCESS
;
1518 moz_gtk_treeview_paint(cairo_t
*cr
, GdkRectangle
* rect
,
1519 GtkWidgetState
* state
,
1520 GtkTextDirection direction
)
1522 gint xthickness
, ythickness
;
1523 GtkStyleContext
*style
;
1524 GtkStyleContext
*style_tree
;
1525 GtkStateFlags state_flags
;
1528 ensure_tree_view_widget();
1529 ensure_scrolled_window_widget();
1531 gtk_widget_set_direction(gTreeViewWidget
, direction
);
1532 gtk_widget_set_direction(gScrolledWindowWidget
, direction
);
1534 /* only handle disabled and normal states, otherwise the whole background
1535 * area will be painted differently with other states */
1536 state_flags
= state
->disabled
? GTK_STATE_FLAG_INSENSITIVE
: GTK_STATE_FLAG_NORMAL
;
1538 style
= gtk_widget_get_style_context(gScrolledWindowWidget
);
1539 gtk_style_context_save(style
);
1540 gtk_style_context_add_class(style
, GTK_STYLE_CLASS_FRAME
);
1541 gtk_style_context_get_border(style
, state_flags
, &border
);
1542 xthickness
= border
.left
;
1543 ythickness
= border
.top
;
1545 style_tree
= gtk_widget_get_style_context(gTreeViewWidget
);
1546 gtk_style_context_save(style_tree
);
1547 gtk_style_context_add_class(style_tree
, GTK_STYLE_CLASS_VIEW
);
1549 gtk_render_background(style_tree
, cr
,
1550 rect
->x
+ xthickness
, rect
->y
+ ythickness
,
1551 rect
->width
- 2 * xthickness
,
1552 rect
->height
- 2 * ythickness
);
1553 gtk_render_frame(style
, cr
,
1554 rect
->x
, rect
->y
, rect
->width
, rect
->height
);
1555 gtk_style_context_restore(style
);
1556 gtk_style_context_restore(style_tree
);
1557 return MOZ_GTK_SUCCESS
;
1561 moz_gtk_tree_header_cell_paint(cairo_t
*cr
, GdkRectangle
* rect
,
1562 GtkWidgetState
* state
,
1563 gboolean isSorted
, GtkTextDirection direction
)
1565 moz_gtk_button_paint(cr
, rect
, state
, GTK_RELIEF_NORMAL
,
1566 gTreeHeaderCellWidget
, direction
);
1567 return MOZ_GTK_SUCCESS
;
1571 moz_gtk_tree_header_sort_arrow_paint(cairo_t
*cr
, GdkRectangle
* rect
,
1572 GtkWidgetState
* state
, GtkArrowType arrow_type
,
1573 GtkTextDirection direction
)
1575 GdkRectangle arrow_rect
;
1576 gdouble arrow_angle
;
1577 GtkStyleContext
* style
;
1579 ensure_tree_header_cell_widget();
1580 gtk_widget_set_direction(gTreeHeaderSortArrowWidget
, direction
);
1582 /* hard code these values */
1583 arrow_rect
.width
= 11;
1584 arrow_rect
.height
= 11;
1585 arrow_rect
.x
= rect
->x
+ (rect
->width
- arrow_rect
.width
) / 2;
1586 arrow_rect
.y
= rect
->y
+ (rect
->height
- arrow_rect
.height
) / 2;
1587 style
= gtk_widget_get_style_context(gTreeHeaderSortArrowWidget
);
1588 gtk_style_context_save(style
);
1589 gtk_style_context_set_state(style
, GetStateFlagsFromGtkWidgetState(state
));
1591 switch (arrow_type
) {
1592 case GTK_ARROW_LEFT
:
1593 arrow_angle
= ARROW_LEFT
;
1595 case GTK_ARROW_RIGHT
:
1596 arrow_angle
= ARROW_RIGHT
;
1598 case GTK_ARROW_DOWN
:
1599 arrow_angle
= ARROW_DOWN
;
1602 arrow_angle
= ARROW_UP
;
1605 if (arrow_type
!= GTK_ARROW_NONE
)
1606 gtk_render_arrow(style
, cr
, arrow_angle
,
1607 arrow_rect
.x
, arrow_rect
.y
,
1609 gtk_style_context_restore(style
);
1610 return MOZ_GTK_SUCCESS
;
1613 /* See gtk_expander_paint() for reference.
1616 moz_gtk_treeview_expander_paint(cairo_t
*cr
, GdkRectangle
* rect
,
1617 GtkWidgetState
* state
,
1618 GtkExpanderStyle expander_state
,
1619 GtkTextDirection direction
)
1621 GtkStyleContext
*style
;
1622 GtkStateFlags state_flags
;
1624 ensure_tree_view_widget();
1625 gtk_widget_set_direction(gTreeViewWidget
, direction
);
1627 style
= gtk_widget_get_style_context(gTreeViewWidget
);
1628 gtk_style_context_save(style
);
1629 gtk_style_context_add_class(style
, GTK_STYLE_CLASS_EXPANDER
);
1631 /* Because the frame we get is of the entire treeview, we can't get the precise
1632 * event state of one expander, thus rendering hover and active feedback useless. */
1633 state_flags
= state
->disabled
? GTK_STATE_INSENSITIVE
: GTK_STATE_NORMAL
;
1635 /* GTK_STATE_FLAG_ACTIVE controls expanded/colapsed state rendering
1636 * in gtk_render_expander()
1638 if (expander_state
== GTK_EXPANDER_EXPANDED
)
1639 state_flags
|= GTK_STATE_FLAG_ACTIVE
;
1641 state_flags
&= ~(GTK_STATE_FLAG_ACTIVE
);
1643 gtk_style_context_set_state(style
, state_flags
);
1645 gtk_render_expander(style
, cr
,
1651 gtk_style_context_restore(style
);
1652 return MOZ_GTK_SUCCESS
;
1655 /* See gtk_separator_draw() for reference.
1658 moz_gtk_combo_box_paint(cairo_t
*cr
, GdkRectangle
* rect
,
1659 GtkWidgetState
* state
,
1660 gboolean ishtml
, GtkTextDirection direction
)
1662 GdkRectangle arrow_rect
, real_arrow_rect
;
1663 gint arrow_size
, separator_width
;
1664 gboolean wide_separators
;
1665 GtkStyleContext
* style
;
1666 GtkRequisition arrow_req
;
1668 ensure_combo_box_widgets();
1670 /* Also sets the direction on gComboBoxButtonWidget, which is then
1671 * inherited by the separator and arrow */
1672 moz_gtk_button_paint(cr
, rect
, state
, GTK_RELIEF_NORMAL
,
1673 gComboBoxButtonWidget
, direction
);
1675 calculate_button_inner_rect(gComboBoxButtonWidget
,
1676 rect
, &arrow_rect
, direction
, ishtml
);
1677 /* Now arrow_rect contains the inner rect ; we want to correct the width
1678 * to what the arrow needs (see gtk_combo_box_size_allocate) */
1679 gtk_widget_get_preferred_size(gComboBoxArrowWidget
, NULL
, &arrow_req
);
1680 if (direction
== GTK_TEXT_DIR_LTR
)
1681 arrow_rect
.x
+= arrow_rect
.width
- arrow_req
.width
;
1682 arrow_rect
.width
= arrow_req
.width
;
1684 calculate_arrow_rect(gComboBoxArrowWidget
,
1685 &arrow_rect
, &real_arrow_rect
, direction
);
1687 style
= gtk_widget_get_style_context(gComboBoxArrowWidget
);
1688 gtk_render_arrow(style
, cr
, ARROW_DOWN
,
1689 real_arrow_rect
.x
, real_arrow_rect
.y
,
1690 real_arrow_rect
.width
);
1692 /* If there is no separator in the theme, there's nothing left to do. */
1693 if (!gComboBoxSeparatorWidget
)
1694 return MOZ_GTK_SUCCESS
;
1695 style
= gtk_widget_get_style_context(gComboBoxSeparatorWidget
);
1696 gtk_widget_style_get(gComboBoxSeparatorWidget
,
1697 "wide-separators", &wide_separators
,
1698 "separator-width", &separator_width
,
1701 if (wide_separators
) {
1702 if (direction
== GTK_TEXT_DIR_LTR
)
1703 arrow_rect
.x
-= separator_width
;
1705 arrow_rect
.x
+= arrow_rect
.width
;
1707 gtk_render_frame(style
, cr
, arrow_rect
.x
, arrow_rect
.y
, separator_width
, arrow_rect
.height
);
1709 if (direction
== GTK_TEXT_DIR_LTR
) {
1711 GtkStateFlags state_flags
= GetStateFlagsFromGtkWidgetState(state
);
1712 gtk_style_context_get_padding(style
, state_flags
, &padding
);
1713 arrow_rect
.x
-= padding
.left
;
1716 arrow_rect
.x
+= arrow_rect
.width
;
1718 gtk_render_line(style
, cr
,
1719 arrow_rect
.x
, arrow_rect
.y
,
1720 arrow_rect
.x
, arrow_rect
.y
+ arrow_rect
.height
);
1722 return MOZ_GTK_SUCCESS
;
1726 moz_gtk_arrow_paint(cairo_t
*cr
, GdkRectangle
* rect
,
1727 GtkWidgetState
* state
,
1728 GtkArrowType arrow_type
, GtkTextDirection direction
)
1730 GtkStyleContext
* style
;
1731 GtkStateFlags state_flags
= GetStateFlagsFromGtkWidgetState(state
);
1732 GdkRectangle arrow_rect
;
1733 gdouble arrow_angle
;
1735 ensure_button_arrow_widget();
1736 style
= gtk_widget_get_style_context(gButtonArrowWidget
);
1737 gtk_style_context_save(style
);
1738 gtk_style_context_set_state(style
, state_flags
);
1739 gtk_widget_set_direction(gButtonArrowWidget
, direction
);
1741 calculate_arrow_rect(gButtonArrowWidget
, rect
, &arrow_rect
,
1744 if (direction
== GTK_TEXT_DIR_RTL
) {
1745 arrow_type
= (arrow_type
== GTK_ARROW_LEFT
) ?
1746 GTK_ARROW_RIGHT
: GTK_ARROW_LEFT
;
1748 switch (arrow_type
) {
1749 case GTK_ARROW_LEFT
:
1750 arrow_angle
= ARROW_LEFT
;
1752 case GTK_ARROW_RIGHT
:
1753 arrow_angle
= ARROW_RIGHT
;
1755 case GTK_ARROW_DOWN
:
1756 arrow_angle
= ARROW_DOWN
;
1759 arrow_angle
= ARROW_UP
;
1762 if (arrow_type
!= GTK_ARROW_NONE
)
1763 gtk_render_arrow(style
, cr
, arrow_angle
,
1764 arrow_rect
.x
, arrow_rect
.y
, arrow_rect
.width
);
1765 gtk_style_context_restore(style
);
1766 return MOZ_GTK_SUCCESS
;
1770 moz_gtk_combo_box_entry_button_paint(cairo_t
*cr
, GdkRectangle
* rect
,
1771 GtkWidgetState
* state
,
1772 gboolean input_focus
,
1773 GtkTextDirection direction
)
1775 gint x_displacement
, y_displacement
;
1776 GdkRectangle arrow_rect
, real_arrow_rect
;
1777 GtkStateFlags state_flags
= GetStateFlagsFromGtkWidgetState(state
);
1778 GtkStyleContext
* style
;
1780 ensure_combo_box_entry_widgets();
1782 moz_gtk_button_paint(cr
, rect
, state
, GTK_RELIEF_NORMAL
,
1783 gComboBoxEntryButtonWidget
, direction
);
1785 calculate_button_inner_rect(gComboBoxEntryButtonWidget
,
1786 rect
, &arrow_rect
, direction
, FALSE
);
1787 if (state_flags
& GTK_STATE_FLAG_ACTIVE
) {
1788 gtk_widget_style_get(gComboBoxEntryButtonWidget
,
1789 "child-displacement-x", &x_displacement
,
1790 "child-displacement-y", &y_displacement
,
1792 arrow_rect
.x
+= x_displacement
;
1793 arrow_rect
.y
+= y_displacement
;
1796 calculate_arrow_rect(gComboBoxEntryArrowWidget
,
1797 &arrow_rect
, &real_arrow_rect
, direction
);
1799 style
= gtk_widget_get_style_context(gComboBoxEntryArrowWidget
);
1801 gtk_render_arrow(style
, cr
, ARROW_DOWN
,
1802 real_arrow_rect
.x
, real_arrow_rect
.y
,
1803 real_arrow_rect
.width
);
1805 return MOZ_GTK_SUCCESS
;
1809 moz_gtk_container_paint(cairo_t
*cr
, GdkRectangle
* rect
,
1810 GtkWidgetState
* state
,
1811 gboolean isradio
, GtkTextDirection direction
)
1813 GtkStateFlags state_flags
= GetStateFlagsFromGtkWidgetState(state
);
1814 GtkStyleContext
* style
;
1816 gboolean interior_focus
;
1817 gint focus_width
, focus_pad
;
1820 ensure_radiobutton_widget();
1821 widget
= gRadiobuttonWidget
;
1823 ensure_checkbox_widget();
1824 widget
= gCheckboxWidget
;
1826 gtk_widget_set_direction(widget
, direction
);
1828 style
= gtk_widget_get_style_context(widget
);
1829 gtk_style_context_save(style
);
1830 moz_gtk_widget_get_focus(widget
, &interior_focus
, &focus_width
, &focus_pad
);
1831 gtk_style_context_set_state(style
, state_flags
);
1833 /* this is for drawing a prelight box */
1834 if (state_flags
& GTK_STATE_FLAG_PRELIGHT
) {
1835 gtk_render_background(style
, cr
,
1836 rect
->x
, rect
->y
, rect
->width
, rect
->height
);
1839 if (state
->focused
&& !interior_focus
) {
1840 gtk_render_focus(style
, cr
,
1841 rect
->x
, rect
->y
, rect
->width
, rect
->height
);
1843 gtk_style_context_restore(style
);
1845 return MOZ_GTK_SUCCESS
;
1849 moz_gtk_toggle_label_paint(cairo_t
*cr
, GdkRectangle
* rect
,
1850 GtkWidgetState
* state
,
1851 gboolean isradio
, GtkTextDirection direction
)
1853 GtkStyleContext
*style
;
1855 gboolean interior_focus
;
1857 if (!state
->focused
)
1858 return MOZ_GTK_SUCCESS
;
1861 ensure_radiobutton_widget();
1862 widget
= gRadiobuttonWidget
;
1864 ensure_checkbox_widget();
1865 widget
= gCheckboxWidget
;
1867 style
= gtk_widget_get_style_context(widget
);
1868 gtk_style_context_save(style
);
1870 gtk_style_context_add_class(style
, GTK_STYLE_CLASS_RADIO
);
1872 gtk_style_context_add_class(style
, GTK_STYLE_CLASS_CHECK
);
1874 gtk_widget_set_direction(widget
, direction
);
1876 gtk_widget_style_get(widget
, "interior-focus", &interior_focus
, NULL
);
1877 if (!interior_focus
)
1878 return MOZ_GTK_SUCCESS
;
1880 gtk_style_context_set_state(style
, GetStateFlagsFromGtkWidgetState(state
));
1881 gtk_render_focus(style
, cr
,
1882 rect
->x
, rect
->y
, rect
->width
, rect
->height
);
1883 gtk_style_context_restore(style
);
1885 return MOZ_GTK_SUCCESS
;
1889 moz_gtk_toolbar_paint(cairo_t
*cr
, GdkRectangle
* rect
,
1890 GtkTextDirection direction
)
1892 GtkStyleContext
* style
;
1894 ensure_toolbar_widget();
1895 gtk_widget_set_direction(gToolbarWidget
, direction
);
1897 style
= gtk_widget_get_style_context(gToolbarWidget
);
1898 gtk_style_context_save(style
);
1899 gtk_style_context_add_class(style
, GTK_STYLE_CLASS_TOOLBAR
);
1901 gtk_render_background(style
, cr
, rect
->x
, rect
->y
, rect
->width
, rect
->height
);
1902 gtk_render_frame(style
, cr
, rect
->x
, rect
->y
, rect
->width
, rect
->height
);
1903 gtk_style_context_restore(style
);
1905 return MOZ_GTK_SUCCESS
;
1908 /* See _gtk_toolbar_paint_space_line() for reference.
1911 moz_gtk_toolbar_separator_paint(cairo_t
*cr
, GdkRectangle
* rect
,
1912 GtkTextDirection direction
)
1914 GtkStyleContext
* style
;
1915 gint separator_width
;
1917 gboolean wide_separators
;
1919 /* Defined as constants in GTK+ 2.10.14 */
1920 const double start_fraction
= 0.2;
1921 const double end_fraction
= 0.8;
1923 ensure_toolbar_separator_widget();
1924 gtk_widget_set_direction(gToolbarSeparatorWidget
, direction
);
1926 style
= gtk_widget_get_style_context(gToolbarSeparatorWidget
);
1928 gtk_widget_style_get(gToolbarWidget
,
1929 "wide-separators", &wide_separators
,
1930 "separator-width", &separator_width
,
1933 if (wide_separators
) {
1934 if (separator_width
> rect
->width
)
1935 separator_width
= rect
->width
;
1937 gtk_render_frame(style
, cr
,
1938 rect
->x
+ (rect
->width
- separator_width
) / 2,
1939 rect
->y
+ rect
->height
* start_fraction
,
1941 rect
->height
* (end_fraction
- start_fraction
));
1944 gtk_style_context_get_padding(style
, 0, &padding
);
1946 paint_width
= padding
.left
;
1947 if (paint_width
> rect
->width
)
1948 paint_width
= rect
->width
;
1950 gtk_render_line(style
, cr
,
1951 rect
->x
+ (rect
->width
- paint_width
) / 2,
1952 rect
->y
+ rect
->height
* start_fraction
,
1953 rect
->x
+ (rect
->width
- paint_width
) / 2,
1954 rect
->y
+ rect
->height
* end_fraction
);
1957 return MOZ_GTK_SUCCESS
;
1961 moz_gtk_tooltip_paint(cairo_t
*cr
, GdkRectangle
* rect
,
1962 GtkTextDirection direction
)
1964 GtkStyleContext
* style
;
1966 ensure_tooltip_widget();
1967 gtk_widget_set_direction(gTooltipWidget
, direction
);
1969 style
= gtk_widget_get_style_context(gTooltipWidget
);
1970 gtk_style_context_save(style
);
1971 gtk_style_context_add_class(style
, GTK_STYLE_CLASS_TOOLTIP
);
1972 gtk_render_background(style
, cr
, rect
->x
, rect
->y
, rect
->width
, rect
->height
);
1973 gtk_render_frame(style
, cr
, rect
->x
, rect
->y
, rect
->width
, rect
->height
);
1974 gtk_style_context_restore(style
);
1975 return MOZ_GTK_SUCCESS
;
1979 moz_gtk_resizer_paint(cairo_t
*cr
, GdkRectangle
* rect
,
1980 GtkWidgetState
* state
,
1981 GtkTextDirection direction
)
1983 GtkStyleContext
* style
;
1985 ensure_frame_widget();
1986 gtk_widget_set_direction(gStatusbarWidget
, direction
);
1988 style
= gtk_widget_get_style_context(gStatusbarWidget
);
1989 gtk_style_context_save(style
);
1990 gtk_style_context_add_class(style
, GTK_STYLE_CLASS_GRIP
);
1991 gtk_style_context_set_state(style
, GetStateFlagsFromGtkWidgetState(state
));
1993 gtk_render_handle(style
, cr
, rect
->x
, rect
->y
, rect
->width
, rect
->height
);
1994 gtk_style_context_restore(style
);
1996 return MOZ_GTK_SUCCESS
;
2000 moz_gtk_frame_paint(cairo_t
*cr
, GdkRectangle
* rect
,
2001 GtkTextDirection direction
)
2003 GtkStyleContext
* style
;
2005 ensure_frame_widget();
2006 gtk_widget_set_direction(gFrameWidget
, direction
);
2007 style
= gtk_widget_get_style_context(gFrameWidget
);
2008 gtk_style_context_save(style
);
2009 gtk_style_context_add_class(style
, GTK_STYLE_CLASS_FRAME
);
2011 gtk_render_frame(style
, cr
, rect
->x
, rect
->y
, rect
->width
, rect
->height
);
2012 gtk_style_context_restore(style
);
2013 return MOZ_GTK_SUCCESS
;
2017 moz_gtk_progressbar_paint(cairo_t
*cr
, GdkRectangle
* rect
,
2018 GtkTextDirection direction
)
2020 GtkStyleContext
* style
;
2022 ensure_progress_widget();
2023 gtk_widget_set_direction(gProgressWidget
, direction
);
2025 style
= gtk_widget_get_style_context(gProgressWidget
);
2026 gtk_style_context_save(style
);
2027 gtk_style_context_add_class(style
, GTK_STYLE_CLASS_TROUGH
);
2029 gtk_render_background(style
, cr
, rect
->x
, rect
->y
, rect
->width
, rect
->height
);
2030 gtk_render_frame(style
, cr
, rect
->x
, rect
->y
, rect
->width
, rect
->height
);
2031 gtk_style_context_restore(style
);
2033 return MOZ_GTK_SUCCESS
;
2037 moz_gtk_progress_chunk_paint(cairo_t
*cr
, GdkRectangle
* rect
,
2038 GtkTextDirection direction
,
2039 GtkThemeWidgetType widget
)
2041 GtkStyleContext
* style
;
2043 ensure_progress_widget();
2044 gtk_widget_set_direction(gProgressWidget
, direction
);
2046 style
= gtk_widget_get_style_context(gProgressWidget
);
2047 gtk_style_context_save(style
);
2048 gtk_style_context_add_class(style
, GTK_STYLE_CLASS_PROGRESSBAR
);
2050 if (widget
== MOZ_GTK_PROGRESS_CHUNK_INDETERMINATE
||
2051 widget
== MOZ_GTK_PROGRESS_CHUNK_VERTICAL_INDETERMINATE
) {
2053 * The bar's size and the bar speed are set depending of the progress'
2054 * size. These could also be constant for all progress bars easily.
2056 gboolean vertical
= (widget
== MOZ_GTK_PROGRESS_CHUNK_VERTICAL_INDETERMINATE
);
2058 /* The size of the dimension we are going to use for the animation. */
2059 const gint progressSize
= vertical
? rect
->height
: rect
->width
;
2061 /* The bar is using a fifth of the element size, based on GtkProgressBar
2062 * activity-blocks property. */
2063 const gint barSize
= MAX(1, progressSize
/ 5);
2065 /* Represents the travel that has to be done for a complete cycle. */
2066 const gint travel
= 2 * (progressSize
- barSize
);
2068 /* period equals to travel / pixelsPerMillisecond
2069 * where pixelsPerMillisecond equals progressSize / 1000.0.
2070 * This is equivalent to 1600. */
2071 static const guint period
= 1600;
2072 const gint t
= PR_IntervalToMilliseconds(PR_IntervalNow()) % period
;
2073 const gint dx
= travel
* t
/ period
;
2076 rect
->y
+= (dx
< travel
/ 2) ? dx
: travel
- dx
;
2077 rect
->height
= barSize
;
2079 rect
->x
+= (dx
< travel
/ 2) ? dx
: travel
- dx
;
2080 rect
->width
= barSize
;
2084 gtk_render_background(style
, cr
, rect
->x
, rect
->y
, rect
->width
, rect
->height
);
2085 gtk_render_activity(style
, cr
, rect
->x
, rect
->y
, rect
->width
, rect
->height
);
2086 gtk_style_context_restore(style
);
2088 return MOZ_GTK_SUCCESS
;
2092 moz_gtk_get_tab_thickness(void)
2095 GtkStyleContext
* style
;
2097 ensure_tab_widget();
2098 style
= gtk_widget_get_style_context(gTabWidget
);
2099 gtk_style_context_add_class(style
, GTK_STYLE_CLASS_NOTEBOOK
);
2100 gtk_style_context_get_border(style
, 0, &border
);
2103 return 2; /* some themes don't set ythickness correctly */
2108 /* actual small tabs */
2110 moz_gtk_tab_paint(cairo_t
*cr
, GdkRectangle
* rect
,
2111 GtkWidgetState
* state
,
2112 GtkTabFlags flags
, GtkTextDirection direction
)
2114 /* When the tab isn't selected, we just draw a notebook extension.
2115 * When it is selected, we overwrite the adjacent border of the tabpanel
2116 * touching the tab with a pierced border (called "the gap") to make the
2117 * tab appear physically attached to the tabpanel; see details below. */
2119 GtkStyleContext
* style
;
2120 GdkRectangle focusRect
;
2121 GdkRectangle backRect
;
2123 ensure_tab_widget();
2124 gtk_widget_set_direction(gTabWidget
, direction
);
2126 style
= gtk_widget_get_style_context(gTabWidget
);
2127 backRect
= focusRect
= *rect
;
2129 gtk_style_context_save(style
);
2131 if ((flags
& MOZ_GTK_TAB_SELECTED
) == 0) {
2132 /* Only draw the tab */
2133 gtk_style_context_set_state(style
, GTK_STATE_FLAG_NORMAL
);
2134 gtk_render_extension(style
, cr
,
2135 rect
->x
, rect
->y
, rect
->width
, rect
->height
,
2136 (flags
& MOZ_GTK_TAB_BOTTOM
) ?
2137 GTK_POS_TOP
: GTK_POS_BOTTOM
);
2139 /* Draw the tab and the gap
2140 * We want the gap to be positioned exactly on the tabpanel top
2141 * border; since tabbox.css may set a negative margin so that the tab
2142 * frame rect already overlaps the tabpanel frame rect, we need to take
2143 * that into account when drawing. To that effect, nsNativeThemeGTK
2144 * passes us this negative margin (bmargin in the graphic below) in the
2145 * lowest bits of |flags|. We use it to set gap_voffset, the distance
2146 * between the top of the gap and the bottom of the tab (resp. the
2147 * bottom of the gap and the top of the tab when we draw a bottom tab),
2148 * while ensuring that the gap always touches the border of the tab,
2149 * i.e. 0 <= gap_voffset <= gap_height, to avoid surprinsing results
2150 * with big negative or positive margins.
2151 * Here is a graphical explanation in the case of top tabs:
2152 * ___________________________
2155 * ----------|. . . . . . . . . . . . . . .|----- top of tabpanel
2157 * : | (-negative margin, : |
2158 * bottom : v passed in flags) : | gap_height
2159 * of -> :.............................: | (the size of the
2160 * the tab . part of the gap . | tabpanel top border)
2161 * . outside of the tab . v
2162 * ----------------------------------------------
2164 * To draw the gap, we use gtk_paint_box_gap(), see comment in
2165 * moz_gtk_tabpanels_paint(). This box_gap is made 3 * gap_height tall,
2166 * which should suffice to ensure that the only visible border is the
2167 * pierced one. If the tab is in the middle, we make the box_gap begin
2168 * a bit to the left of the tab and end a bit to the right, adjusting
2169 * the gap position so it still is under the tab, because we want the
2170 * rendering of a gap in the middle of a tabpanel. This is the role of
2171 * the gints gap_{l,r}_offset. On the contrary, if the tab is the
2172 * first, we align the start border of the box_gap with the start
2173 * border of the tab (left if LTR, right if RTL), by setting the
2174 * appropriate offset to 0.*/
2175 gint gap_loffset
, gap_roffset
, gap_voffset
, gap_height
;
2177 /* Get height needed by the gap */
2178 gap_height
= moz_gtk_get_tab_thickness();
2180 /* Extract gap_voffset from the first bits of flags */
2181 gap_voffset
= flags
& MOZ_GTK_TAB_MARGIN_MASK
;
2182 if (gap_voffset
> gap_height
)
2183 gap_voffset
= gap_height
;
2185 /* Set gap_{l,r}_offset to appropriate values */
2186 gap_loffset
= gap_roffset
= 20; /* should be enough */
2187 if (flags
& MOZ_GTK_TAB_FIRST
) {
2188 if (direction
== GTK_TEXT_DIR_RTL
)
2194 gtk_style_context_set_state(style
, GTK_STATE_FLAG_ACTIVE
);
2196 /* Adwaita theme engine crashes without it (rhbz#713764) */
2197 gtk_style_context_add_region(style
, GTK_STYLE_REGION_TAB
, 0);
2199 if (flags
& MOZ_GTK_TAB_BOTTOM
) {
2200 /* Draw the tab on bottom */
2201 focusRect
.y
+= gap_voffset
;
2202 focusRect
.height
-= gap_voffset
;
2204 gtk_render_extension(style
, cr
,
2205 rect
->x
, rect
->y
+ gap_voffset
, rect
->width
,
2206 rect
->height
- gap_voffset
, GTK_POS_TOP
);
2208 gtk_style_context_remove_region(style
, GTK_STYLE_REGION_TAB
);
2210 backRect
.y
+= (gap_voffset
- gap_height
);
2211 backRect
.height
= gap_height
;
2213 /* Draw the gap; erase with background color before painting in
2214 * case theme does not */
2215 gtk_render_background(style
, cr
, backRect
.x
, backRect
.y
,
2216 backRect
.width
, backRect
.height
);
2218 cairo_rectangle(cr
, backRect
.x
, backRect
.y
, backRect
.width
, backRect
.height
);
2221 gtk_render_frame_gap(style
, cr
,
2222 rect
->x
- gap_loffset
,
2223 rect
->y
+ gap_voffset
- 3 * gap_height
,
2224 rect
->width
+ gap_loffset
+ gap_roffset
,
2225 3 * gap_height
, GTK_POS_BOTTOM
,
2226 gap_loffset
, gap_loffset
+ rect
->width
);
2229 /* Draw the tab on top */
2230 focusRect
.height
-= gap_voffset
;
2231 gtk_render_extension(style
, cr
,
2232 rect
->x
, rect
->y
, rect
->width
,
2233 rect
->height
- gap_voffset
, GTK_POS_BOTTOM
);
2235 gtk_style_context_remove_region(style
, GTK_STYLE_REGION_TAB
);
2237 backRect
.y
+= (rect
->height
- gap_voffset
);
2238 backRect
.height
= gap_height
;
2240 /* Draw the gap; erase with background color before painting in
2241 * case theme does not */
2242 gtk_render_background(style
, cr
, backRect
.x
, backRect
.y
,
2243 backRect
.width
, backRect
.height
);
2245 cairo_rectangle(cr
, backRect
.x
, backRect
.y
, backRect
.width
, backRect
.height
);
2248 gtk_render_frame_gap(style
, cr
,
2249 rect
->x
- gap_loffset
,
2250 rect
->y
+ rect
->height
- gap_voffset
,
2251 rect
->width
+ gap_loffset
+ gap_roffset
,
2252 3 * gap_height
, GTK_POS_TOP
,
2253 gap_loffset
, gap_loffset
+ rect
->width
);
2258 if (state
->focused
) {
2259 /* Paint the focus ring */
2261 gtk_style_context_get_border(style
, GetStateFlagsFromGtkWidgetState(state
), &border
);
2263 focusRect
.x
+= border
.left
;
2264 focusRect
.width
-= (border
.left
+ border
.right
);
2265 focusRect
.y
+= border
.top
;
2266 focusRect
.height
-= (border
.top
+ border
.bottom
);
2268 gtk_render_focus(style
, cr
,
2269 focusRect
.x
, focusRect
.y
, focusRect
.width
, focusRect
.height
);
2272 gtk_style_context_restore(style
);
2274 return MOZ_GTK_SUCCESS
;
2279 moz_gtk_tabpanels_paint(cairo_t
*cr
, GdkRectangle
* rect
,
2280 GtkTextDirection direction
)
2282 GtkStyleContext
* style
;
2284 ensure_tab_widget();
2285 gtk_widget_set_direction(gTabWidget
, direction
);
2287 style
= gtk_widget_get_style_context(gTabWidget
);
2288 gtk_style_context_save(style
);
2290 gtk_render_background(style
, cr
, rect
->x
, rect
->y
,
2291 rect
->width
, rect
->height
);
2293 * The gap size is not needed in moz_gtk_tabpanels_paint because
2294 * the gap will be painted with the foreground tab in moz_gtk_tab_paint.
2296 * However, if moz_gtk_tabpanels_paint just uses gtk_render_frame(),
2297 * the theme will think that there are no tabs and may draw something
2298 * different.Hence the trick of using two clip regions, and drawing the
2299 * gap outside each clip region, to get the correct frame for
2300 * a tabpanel with tabs.
2304 cairo_rectangle(cr
, rect
->x
, rect
->y
,
2305 rect
->x
+ rect
->width
/ 2,
2306 rect
->y
+ rect
->height
);
2308 gtk_render_frame_gap(style
, cr
,
2310 rect
->width
, rect
->height
,
2311 GTK_POS_TOP
, rect
->width
- 1, rect
->width
);
2316 cairo_rectangle(cr
, rect
->x
+ rect
->width
/ 2, rect
->y
,
2317 rect
->x
+ rect
->width
,
2318 rect
->y
+ rect
->height
);
2320 gtk_render_frame_gap(style
, cr
,
2322 rect
->width
, rect
->height
,
2326 gtk_style_context_restore(style
);
2327 return MOZ_GTK_SUCCESS
;
2331 moz_gtk_tab_scroll_arrow_paint(cairo_t
*cr
, GdkRectangle
* rect
,
2332 GtkWidgetState
* state
,
2333 GtkArrowType arrow_type
,
2334 GtkTextDirection direction
)
2336 GtkStateFlags state_flags
= GetStateFlagsFromGtkWidgetState(state
);
2337 GtkStyleContext
* style
;
2338 gdouble arrow_angle
;
2339 gint arrow_size
= MIN(rect
->width
, rect
->height
);
2340 gint x
= rect
->x
+ (rect
->width
- arrow_size
) / 2;
2341 gint y
= rect
->y
+ (rect
->height
- arrow_size
) / 2;
2343 ensure_tab_widget();
2345 style
= gtk_widget_get_style_context(gTabWidget
);
2346 gtk_style_context_save(style
);
2347 if (direction
== GTK_TEXT_DIR_RTL
) {
2348 arrow_type
= (arrow_type
== GTK_ARROW_LEFT
) ?
2349 GTK_ARROW_RIGHT
: GTK_ARROW_LEFT
;
2351 switch (arrow_type
) {
2352 case GTK_ARROW_LEFT
:
2353 arrow_angle
= ARROW_LEFT
;
2355 case GTK_ARROW_RIGHT
:
2356 arrow_angle
= ARROW_RIGHT
;
2358 case GTK_ARROW_DOWN
:
2359 arrow_angle
= ARROW_DOWN
;
2362 arrow_angle
= ARROW_UP
;
2365 if (arrow_type
!= GTK_ARROW_NONE
) {
2366 gtk_style_context_add_class(style
, GTK_STYLE_CLASS_NOTEBOOK
); /* TODO TEST */
2367 gtk_style_context_set_state(style
, state_flags
);
2368 gtk_render_arrow(style
, cr
, arrow_angle
,
2371 gtk_style_context_restore(style
);
2372 return MOZ_GTK_SUCCESS
;
2376 moz_gtk_menu_bar_paint(cairo_t
*cr
, GdkRectangle
* rect
,
2377 GtkTextDirection direction
)
2379 GtkStyleContext
* style
;
2381 ensure_menu_bar_widget();
2382 gtk_widget_set_direction(gMenuBarWidget
, direction
);
2384 style
= gtk_widget_get_style_context(gMenuBarWidget
);
2385 gtk_style_context_save(style
);
2386 gtk_style_context_add_class(style
, GTK_STYLE_CLASS_MENUBAR
);
2387 gtk_render_background(style
, cr
, rect
->x
, rect
->y
, rect
->width
, rect
->height
);
2388 gtk_render_frame(style
, cr
, rect
->x
, rect
->y
, rect
->width
, rect
->height
);
2389 gtk_style_context_restore(style
);
2391 return MOZ_GTK_SUCCESS
;
2395 moz_gtk_menu_popup_paint(cairo_t
*cr
, GdkRectangle
* rect
,
2396 GtkTextDirection direction
)
2398 GtkStyleContext
* style
;
2400 ensure_menu_popup_widget();
2401 gtk_widget_set_direction(gMenuPopupWidget
, direction
);
2403 style
= gtk_widget_get_style_context(gMenuPopupWidget
);
2404 gtk_style_context_save(style
);
2405 gtk_style_context_add_class(style
, GTK_STYLE_CLASS_MENU
);
2407 gtk_render_background(style
, cr
, rect
->x
, rect
->y
, rect
->width
, rect
->height
);
2408 gtk_render_frame(style
, cr
, rect
->x
, rect
->y
, rect
->width
, rect
->height
);
2409 gtk_style_context_restore(style
);
2411 return MOZ_GTK_SUCCESS
;
2414 // See gtk_menu_item_draw() for reference.
2416 moz_gtk_menu_separator_paint(cairo_t
*cr
, GdkRectangle
* rect
,
2417 GtkTextDirection direction
)
2419 GtkStyleContext
* style
;
2420 gboolean wide_separators
;
2421 gint separator_height
;
2427 ensure_menu_separator_widget();
2428 gtk_widget_set_direction(gMenuSeparatorWidget
, direction
);
2430 border_width
= gtk_container_get_border_width(GTK_CONTAINER(gMenuSeparatorWidget
));
2432 style
= gtk_widget_get_style_context(gMenuSeparatorWidget
);
2433 gtk_style_context_get_padding(style
, 0, &padding
);
2435 x
= rect
->x
+ border_width
;
2436 y
= rect
->y
+ border_width
;
2437 w
= rect
->width
- border_width
* 2;
2438 h
= rect
->height
- border_width
* 2;
2440 gtk_style_context_save(style
);
2441 gtk_style_context_add_class(style
, GTK_STYLE_CLASS_SEPARATOR
);
2443 gtk_widget_style_get(gMenuSeparatorWidget
,
2444 "wide-separators", &wide_separators
,
2445 "separator-height", &separator_height
,
2448 if (wide_separators
) {
2449 gtk_render_frame(style
, cr
,
2452 w
- padding
.left
- padding
.right
,
2455 gtk_render_line(style
, cr
,
2458 x
+ w
- padding
.right
- 1,
2462 gtk_style_context_restore(style
);
2464 return MOZ_GTK_SUCCESS
;
2467 // See gtk_menu_item_draw() for reference.
2469 moz_gtk_menu_item_paint(cairo_t
*cr
, GdkRectangle
* rect
,
2470 GtkWidgetState
* state
,
2471 gint flags
, GtkTextDirection direction
)
2473 GtkStyleContext
* style
;
2474 GtkWidget
* item_widget
;
2478 if (state
->inHover
&& !state
->disabled
) {
2479 if (flags
& MOZ_TOPLEVEL_MENU_ITEM
) {
2480 ensure_menu_bar_item_widget();
2481 item_widget
= gMenuBarItemWidget
;
2483 ensure_menu_item_widget();
2484 item_widget
= gMenuItemWidget
;
2486 style
= gtk_widget_get_style_context(item_widget
);
2487 gtk_style_context_save(style
);
2489 if (flags
& MOZ_TOPLEVEL_MENU_ITEM
) {
2490 gtk_style_context_add_class(style
, GTK_STYLE_CLASS_MENUBAR
);
2493 gtk_widget_set_direction(item_widget
, direction
);
2494 gtk_style_context_add_class(style
, GTK_STYLE_CLASS_MENUITEM
);
2495 gtk_style_context_set_state(style
, GetStateFlagsFromGtkWidgetState(state
));
2497 border_width
= gtk_container_get_border_width(GTK_CONTAINER(item_widget
));
2499 x
= rect
->x
+ border_width
;
2500 y
= rect
->y
+ border_width
;
2501 w
= rect
->width
- border_width
* 2;
2502 h
= rect
->height
- border_width
* 2;
2504 gtk_render_background(style
, cr
, x
, y
, w
, h
);
2505 gtk_render_frame(style
, cr
, x
, y
, w
, h
);
2506 gtk_style_context_restore(style
);
2509 return MOZ_GTK_SUCCESS
;
2513 moz_gtk_menu_arrow_paint(cairo_t
*cr
, GdkRectangle
* rect
,
2514 GtkWidgetState
* state
,
2515 GtkTextDirection direction
)
2517 GtkStyleContext
* style
;
2518 GtkStateFlags state_flags
= GetStateFlagsFromGtkWidgetState(state
);
2520 ensure_menu_item_widget();
2521 gtk_widget_set_direction(gMenuItemWidget
, direction
);
2523 style
= gtk_widget_get_style_context(gMenuItemWidget
);
2524 gtk_style_context_save(style
);
2525 gtk_style_context_add_class(style
, GTK_STYLE_CLASS_MENUITEM
);
2526 gtk_style_context_set_state(style
, state_flags
);
2527 gtk_render_arrow(style
, cr
,
2528 (direction
== GTK_TEXT_DIR_LTR
) ? ARROW_RIGHT
: ARROW_LEFT
,
2529 rect
->x
, rect
->y
, rect
->width
);
2530 gtk_style_context_restore(style
);
2532 return MOZ_GTK_SUCCESS
;
2535 // See gtk_real_check_menu_item_draw_indicator() for reference.
2537 moz_gtk_check_menu_item_paint(cairo_t
*cr
, GdkRectangle
* rect
,
2538 GtkWidgetState
* state
,
2539 gboolean checked
, gboolean isradio
,
2540 GtkTextDirection direction
)
2542 GtkStateFlags state_flags
= GetStateFlagsFromGtkWidgetState(state
);
2543 GtkStyleContext
* style
;
2546 gint indicator_size
, horizontal_padding
;
2549 moz_gtk_menu_item_paint(cr
, rect
, state
, FALSE
, direction
);
2551 ensure_check_menu_item_widget();
2552 gtk_widget_set_direction(gCheckMenuItemWidget
, direction
);
2554 gtk_widget_style_get (gCheckMenuItemWidget
,
2555 "indicator-size", &indicator_size
,
2556 "horizontal-padding", &horizontal_padding
,
2559 style
= gtk_widget_get_style_context(gCheckMenuItemWidget
);
2560 gtk_style_context_save(style
);
2562 gtk_style_context_add_class(style
, GTK_STYLE_CLASS_RADIO
);
2564 gtk_style_context_add_class(style
, GTK_STYLE_CLASS_CHECK
);
2568 state_flags
|= GTK_STATE_FLAG_ACTIVE
;
2570 gtk_style_context_set_state(style
, state_flags
);
2571 gtk_style_context_get_padding(style
, state_flags
, &padding
);
2573 offset
= gtk_container_get_border_width(GTK_CONTAINER(gCheckMenuItemWidget
)) +
2576 if (direction
== GTK_TEXT_DIR_RTL
) {
2577 x
= rect
->width
- indicator_size
- offset
- horizontal_padding
;
2580 x
= rect
->x
+ offset
+ horizontal_padding
;
2582 y
= rect
->y
+ (rect
->height
- indicator_size
) / 2;
2585 gtk_render_option(style
, cr
, x
, y
, indicator_size
, indicator_size
);
2587 gtk_render_check(style
, cr
, x
, y
, indicator_size
, indicator_size
);
2589 gtk_style_context_restore(style
);
2591 return MOZ_GTK_SUCCESS
;
2595 moz_gtk_window_paint(cairo_t
*cr
, GdkRectangle
* rect
,
2596 GtkTextDirection direction
)
2598 GtkStyleContext
* style
;
2600 ensure_window_widget();
2601 gtk_widget_set_direction(gProtoWindow
, direction
);
2603 style
= gtk_widget_get_style_context(gProtoWindow
);
2604 gtk_style_context_save(style
);
2605 gtk_style_context_add_class(style
, GTK_STYLE_CLASS_BACKGROUND
);
2606 gtk_render_background(style
, cr
, rect
->x
, rect
->y
, rect
->width
, rect
->height
);
2607 gtk_style_context_restore(style
);
2609 return MOZ_GTK_SUCCESS
;
2613 moz_gtk_add_style_border(GtkStyleContext
* style
,
2614 gint
* left
, gint
* top
, gint
* right
, gint
* bottom
)
2618 gtk_style_context_get_border(style
, 0, &border
);
2620 *left
+= border
.left
;
2621 *right
+= border
.right
;
2623 *bottom
+= border
.bottom
;
2627 moz_gtk_add_style_padding(GtkStyleContext
* style
,
2628 gint
* left
, gint
* top
, gint
* right
, gint
* bottom
)
2632 gtk_style_context_get_padding(style
, 0, &padding
);
2634 *left
+= padding
.left
;
2635 *right
+= padding
.right
;
2636 *top
+= padding
.top
;
2637 *bottom
+= padding
.bottom
;
2641 moz_gtk_get_widget_border(GtkThemeWidgetType widget
, gint
* left
, gint
* top
,
2642 gint
* right
, gint
* bottom
, GtkTextDirection direction
,
2646 GtkStyleContext
* style
;
2647 *left
= *top
= *right
= *bottom
= 0;
2650 case MOZ_GTK_BUTTON
:
2652 GtkBorder inner_border
;
2653 gboolean interior_focus
;
2654 gint focus_width
, focus_pad
;
2656 ensure_button_widget();
2657 *left
= *top
= *right
= *bottom
= gtk_container_get_border_width(GTK_CONTAINER(gButtonWidget
));
2659 /* Don't add this padding in HTML, otherwise the buttons will
2660 become too big and stuff the layout. */
2662 moz_gtk_widget_get_focus(gButtonWidget
, &interior_focus
, &focus_width
, &focus_pad
);
2663 moz_gtk_button_get_inner_border(gButtonWidget
, &inner_border
);
2664 *left
+= focus_width
+ focus_pad
+ inner_border
.left
;
2665 *right
+= focus_width
+ focus_pad
+ inner_border
.right
;
2666 *top
+= focus_width
+ focus_pad
+ inner_border
.top
;
2667 *bottom
+= focus_width
+ focus_pad
+ inner_border
.bottom
;
2670 moz_gtk_add_style_border(gtk_widget_get_style_context(gButtonWidget
),
2671 left
, top
, right
, bottom
);
2672 return MOZ_GTK_SUCCESS
;
2676 ensure_entry_widget();
2677 style
= gtk_widget_get_style_context(gEntryWidget
);
2678 moz_gtk_add_style_border(style
, left
, top
, right
, bottom
);
2679 moz_gtk_add_style_padding(style
, left
, top
, right
, bottom
);
2680 return MOZ_GTK_SUCCESS
;
2682 case MOZ_GTK_TREEVIEW
:
2684 ensure_scrolled_window_widget();
2685 style
= gtk_widget_get_style_context(gScrolledWindowWidget
);
2686 gtk_style_context_save(style
);
2687 gtk_style_context_add_class(style
, GTK_STYLE_CLASS_FRAME
);
2688 moz_gtk_add_style_border(style
, left
, top
, right
, bottom
);
2689 gtk_style_context_restore(style
);
2690 return MOZ_GTK_SUCCESS
;
2692 case MOZ_GTK_TREE_HEADER_CELL
:
2694 /* A Tree Header in GTK is just a different styled button
2695 * It must be placed in a TreeView for getting the correct style
2697 * That is why the following code is the same as for MOZ_GTK_BUTTON.
2700 GtkBorder inner_border
;
2701 gboolean interior_focus
;
2702 gint focus_width
, focus_pad
;
2704 ensure_tree_header_cell_widget();
2705 *left
= *top
= *right
= *bottom
= gtk_container_get_border_width(GTK_CONTAINER(gTreeHeaderCellWidget
));
2707 moz_gtk_widget_get_focus(gTreeHeaderCellWidget
, &interior_focus
, &focus_width
, &focus_pad
);
2708 moz_gtk_button_get_inner_border(gTreeHeaderCellWidget
, &inner_border
);
2709 *left
+= focus_width
+ focus_pad
+ inner_border
.left
;
2710 *right
+= focus_width
+ focus_pad
+ inner_border
.right
;
2711 *top
+= focus_width
+ focus_pad
+ inner_border
.top
;
2712 *bottom
+= focus_width
+ focus_pad
+ inner_border
.bottom
;
2714 moz_gtk_add_style_border(gtk_widget_get_style_context(gTreeHeaderCellWidget
),
2715 left
, top
, right
, bottom
);
2716 return MOZ_GTK_SUCCESS
;
2718 case MOZ_GTK_TREE_HEADER_SORTARROW
:
2719 ensure_tree_header_cell_widget();
2720 w
= gTreeHeaderSortArrowWidget
;
2722 case MOZ_GTK_DROPDOWN_ENTRY
:
2723 ensure_combo_box_entry_widgets();
2724 w
= gComboBoxEntryTextareaWidget
;
2726 case MOZ_GTK_DROPDOWN_ARROW
:
2727 ensure_combo_box_entry_widgets();
2728 w
= gComboBoxEntryButtonWidget
;
2730 case MOZ_GTK_DROPDOWN
:
2732 /* We need to account for the arrow on the dropdown, so text
2733 * doesn't come too close to the arrow, or in some cases spill
2734 * into the arrow. */
2735 gboolean ignored_interior_focus
, wide_separators
;
2736 gint focus_width
, focus_pad
, separator_width
;
2737 GtkRequisition arrow_req
;
2740 ensure_combo_box_widgets();
2742 *left
= gtk_container_get_border_width(GTK_CONTAINER(gComboBoxButtonWidget
));
2745 moz_gtk_widget_get_focus(gComboBoxButtonWidget
,
2746 &ignored_interior_focus
,
2747 &focus_width
, &focus_pad
);
2748 *left
+= focus_width
+ focus_pad
;
2751 style
= gtk_widget_get_style_context(gComboBoxButtonWidget
);
2752 gtk_style_context_get_border(style
, 0, &border
);
2754 *top
= *left
+ border
.top
;
2755 *left
+= border
.left
;
2757 *right
= *left
; *bottom
= *top
;
2759 /* If there is no separator, don't try to count its width. */
2760 separator_width
= 0;
2761 if (gComboBoxSeparatorWidget
) {
2762 gtk_widget_style_get(gComboBoxSeparatorWidget
,
2763 "wide-separators", &wide_separators
,
2764 "separator-width", &separator_width
,
2767 if (!wide_separators
) {
2768 style
= gtk_widget_get_style_context(gComboBoxSeparatorWidget
);
2769 gtk_style_context_get_border(style
, 0, &border
);
2770 separator_width
= border
.left
;
2774 gtk_widget_get_preferred_size(gComboBoxArrowWidget
, NULL
, &arrow_req
);
2776 if (direction
== GTK_TEXT_DIR_RTL
)
2777 *left
+= separator_width
+ arrow_req
.width
;
2779 *right
+= separator_width
+ arrow_req
.width
;
2781 return MOZ_GTK_SUCCESS
;
2783 case MOZ_GTK_TABPANELS
:
2784 ensure_tab_widget();
2787 case MOZ_GTK_PROGRESSBAR
:
2788 ensure_progress_widget();
2789 w
= gProgressWidget
;
2791 case MOZ_GTK_SPINBUTTON_ENTRY
:
2792 case MOZ_GTK_SPINBUTTON_UP
:
2793 case MOZ_GTK_SPINBUTTON_DOWN
:
2794 ensure_spin_widget();
2797 case MOZ_GTK_SCALE_HORIZONTAL
:
2798 ensure_scale_widget();
2801 case MOZ_GTK_SCALE_VERTICAL
:
2802 ensure_scale_widget();
2806 ensure_frame_widget();
2809 case MOZ_GTK_CHECKBUTTON_LABEL
:
2810 case MOZ_GTK_RADIOBUTTON_LABEL
:
2812 gboolean interior_focus
;
2813 gint focus_width
, focus_pad
;
2815 /* If the focus is interior, then the label has a border of
2816 (focus_width + focus_pad). */
2817 if (widget
== MOZ_GTK_CHECKBUTTON_LABEL
) {
2818 ensure_checkbox_widget();
2819 moz_gtk_widget_get_focus(gCheckboxWidget
, &interior_focus
,
2820 &focus_width
, &focus_pad
);
2823 ensure_radiobutton_widget();
2824 moz_gtk_widget_get_focus(gRadiobuttonWidget
, &interior_focus
,
2825 &focus_width
, &focus_pad
);
2829 *left
= *top
= *right
= *bottom
= (focus_width
+ focus_pad
);
2831 return MOZ_GTK_SUCCESS
;
2834 case MOZ_GTK_CHECKBUTTON_CONTAINER
:
2835 case MOZ_GTK_RADIOBUTTON_CONTAINER
:
2837 gboolean interior_focus
;
2838 gint focus_width
, focus_pad
;
2840 /* If the focus is _not_ interior, then the container has a border
2841 of (focus_width + focus_pad). */
2842 if (widget
== MOZ_GTK_CHECKBUTTON_CONTAINER
) {
2843 ensure_checkbox_widget();
2844 moz_gtk_widget_get_focus(gCheckboxWidget
, &interior_focus
,
2845 &focus_width
, &focus_pad
);
2846 w
= gCheckboxWidget
;
2848 ensure_radiobutton_widget();
2849 moz_gtk_widget_get_focus(gRadiobuttonWidget
, &interior_focus
,
2850 &focus_width
, &focus_pad
);
2851 w
= gRadiobuttonWidget
;
2854 *left
= *top
= *right
= *bottom
= gtk_container_get_border_width(GTK_CONTAINER(w
));
2856 if (!interior_focus
) {
2857 *left
+= (focus_width
+ focus_pad
);
2858 *right
+= (focus_width
+ focus_pad
);
2859 *top
+= (focus_width
+ focus_pad
);
2860 *bottom
+= (focus_width
+ focus_pad
);
2863 return MOZ_GTK_SUCCESS
;
2865 case MOZ_GTK_MENUPOPUP
:
2866 ensure_menu_popup_widget();
2867 w
= gMenuPopupWidget
;
2869 case MOZ_GTK_MENUITEM
:
2870 case MOZ_GTK_CHECKMENUITEM
:
2871 case MOZ_GTK_RADIOMENUITEM
:
2873 if (widget
== MOZ_GTK_MENUITEM
) {
2874 ensure_menu_item_widget();
2875 ensure_menu_bar_item_widget();
2876 w
= gMenuItemWidget
;
2879 ensure_check_menu_item_widget();
2880 w
= gCheckMenuItemWidget
;
2883 *left
= *top
= *right
= *bottom
= gtk_container_get_border_width(GTK_CONTAINER(w
));
2884 moz_gtk_add_style_padding(gtk_widget_get_style_context(w
),
2885 left
, top
, right
, bottom
);
2886 return MOZ_GTK_SUCCESS
;
2889 ensure_tab_widget();
2892 /* These widgets have no borders, since they are not containers. */
2893 case MOZ_GTK_SPLITTER_HORIZONTAL
:
2894 case MOZ_GTK_SPLITTER_VERTICAL
:
2895 case MOZ_GTK_CHECKBUTTON
:
2896 case MOZ_GTK_RADIOBUTTON
:
2897 case MOZ_GTK_SCROLLBAR_BUTTON
:
2898 case MOZ_GTK_SCROLLBAR_TRACK_HORIZONTAL
:
2899 case MOZ_GTK_SCROLLBAR_TRACK_VERTICAL
:
2900 case MOZ_GTK_SCROLLBAR_THUMB_HORIZONTAL
:
2901 case MOZ_GTK_SCROLLBAR_THUMB_VERTICAL
:
2902 case MOZ_GTK_SCALE_THUMB_HORIZONTAL
:
2903 case MOZ_GTK_SCALE_THUMB_VERTICAL
:
2904 case MOZ_GTK_GRIPPER
:
2905 case MOZ_GTK_PROGRESS_CHUNK
:
2906 case MOZ_GTK_PROGRESS_CHUNK_INDETERMINATE
:
2907 case MOZ_GTK_PROGRESS_CHUNK_VERTICAL_INDETERMINATE
:
2908 case MOZ_GTK_TREEVIEW_EXPANDER
:
2909 case MOZ_GTK_TOOLBAR_SEPARATOR
:
2910 case MOZ_GTK_MENUSEPARATOR
:
2911 /* These widgets have no borders.*/
2912 case MOZ_GTK_SPINBUTTON
:
2913 case MOZ_GTK_TOOLTIP
:
2914 case MOZ_GTK_WINDOW
:
2915 case MOZ_GTK_RESIZER
:
2916 case MOZ_GTK_MENUARROW
:
2917 case MOZ_GTK_TOOLBARBUTTON_ARROW
:
2918 case MOZ_GTK_TOOLBAR
:
2919 case MOZ_GTK_MENUBAR
:
2920 case MOZ_GTK_TAB_SCROLLARROW
:
2921 return MOZ_GTK_SUCCESS
;
2923 g_warning("Unsupported widget type: %d", widget
);
2924 return MOZ_GTK_UNKNOWN_WIDGET
;
2926 /* TODO - we're still missing some widget implementations */
2928 moz_gtk_add_style_border(gtk_widget_get_style_context(w
),
2929 left
, top
, right
, bottom
);
2931 return MOZ_GTK_SUCCESS
;
2935 moz_gtk_get_combo_box_entry_button_size(gint
* width
, gint
* height
)
2938 * We get the requisition of the drop down button, which includes
2939 * all padding, border and focus line widths the button uses,
2940 * as well as the minimum arrow size and its padding
2942 GtkRequisition requisition
;
2943 ensure_combo_box_entry_widgets();
2945 gtk_widget_get_preferred_size(gComboBoxEntryButtonWidget
, NULL
, &requisition
);
2946 *width
= requisition
.width
;
2947 *height
= requisition
.height
;
2949 return MOZ_GTK_SUCCESS
;
2953 moz_gtk_get_tab_scroll_arrow_size(gint
* width
, gint
* height
)
2957 ensure_tab_widget();
2958 gtk_widget_style_get(gTabWidget
,
2959 "scroll-arrow-hlength", &arrow_size
,
2962 *height
= *width
= arrow_size
;
2964 return MOZ_GTK_SUCCESS
;
2968 moz_gtk_get_arrow_size(gint
* width
, gint
* height
)
2970 GtkRequisition requisition
;
2971 ensure_button_arrow_widget();
2973 gtk_widget_get_preferred_size(gButtonArrowWidget
, NULL
, &requisition
);
2974 *width
= requisition
.width
;
2975 *height
= requisition
.height
;
2977 return MOZ_GTK_SUCCESS
;
2981 moz_gtk_get_toolbar_separator_width(gint
* size
)
2983 gboolean wide_separators
;
2984 gint separator_width
;
2985 GtkStyleContext
* style
;
2988 ensure_toolbar_widget();
2989 style
= gtk_widget_get_style_context(gToolbarWidget
);
2991 gtk_widget_style_get(gToolbarWidget
,
2993 "wide-separators", &wide_separators
,
2994 "separator-width", &separator_width
,
2996 /* Just in case... */
2997 gtk_style_context_get_border(style
, 0, &border
);
2998 *size
= MAX(*size
, (wide_separators
? separator_width
: border
.left
));
2999 return MOZ_GTK_SUCCESS
;
3003 moz_gtk_get_expander_size(gint
* size
)
3005 ensure_expander_widget();
3006 gtk_widget_style_get(gExpanderWidget
,
3007 "expander-size", size
,
3010 return MOZ_GTK_SUCCESS
;
3014 moz_gtk_get_treeview_expander_size(gint
* size
)
3016 ensure_tree_view_widget();
3017 gtk_widget_style_get(gTreeViewWidget
,
3018 "expander-size", size
,
3021 return MOZ_GTK_SUCCESS
;
3024 // See gtk_menu_item_draw() for reference.
3026 moz_gtk_get_menu_separator_height(gint
*size
)
3028 gboolean wide_separators
;
3029 gint separator_height
;
3031 GtkStyleContext
* style
;
3034 ensure_menu_separator_widget();
3036 border_width
= gtk_container_get_border_width(GTK_CONTAINER(gMenuSeparatorWidget
));
3038 style
= gtk_widget_get_style_context(gMenuSeparatorWidget
);
3039 gtk_style_context_get_padding(style
, 0, &padding
);
3041 gtk_style_context_save(style
);
3042 gtk_style_context_add_class(style
, GTK_STYLE_CLASS_SEPARATOR
);
3044 gtk_widget_style_get(gMenuSeparatorWidget
,
3045 "wide-separators", &wide_separators
,
3046 "separator-height", &separator_height
,
3049 gtk_style_context_restore(style
);
3051 *size
= padding
.top
+ padding
.bottom
+ border_width
*2;
3052 *size
+= (wide_separators
) ? separator_height
: 1;
3054 return MOZ_GTK_SUCCESS
;
3058 moz_gtk_get_scalethumb_metrics(GtkOrientation orient
, gint
* thumb_length
, gint
* thumb_height
)
3062 ensure_scale_widget();
3063 widget
= ((orient
== GTK_ORIENTATION_HORIZONTAL
) ? gHScaleWidget
: gVScaleWidget
);
3065 gtk_widget_style_get (widget
,
3066 "slider_length", thumb_length
,
3067 "slider_width", thumb_height
,
3070 return MOZ_GTK_SUCCESS
;
3074 moz_gtk_get_scrollbar_metrics(MozGtkScrollbarMetrics
*metrics
)
3076 ensure_scrollbar_widget();
3078 gtk_widget_style_get (gHorizScrollbarWidget
,
3079 "slider_width", &metrics
->slider_width
,
3080 "trough_border", &metrics
->trough_border
,
3081 "stepper_size", &metrics
->stepper_size
,
3082 "stepper_spacing", &metrics
->stepper_spacing
,
3085 metrics
->min_slider_size
=
3086 gtk_range_get_min_slider_size(GTK_RANGE(gHorizScrollbarWidget
));
3088 return MOZ_GTK_SUCCESS
;
3092 moz_gtk_images_in_menus()
3095 GtkSettings
* settings
;
3097 ensure_image_menu_item_widget();
3098 settings
= gtk_widget_get_settings(gImageMenuItemWidget
);
3100 g_object_get(settings
, "gtk-menu-images", &result
, NULL
);
3105 moz_gtk_images_in_buttons()
3108 GtkSettings
* settings
;
3110 ensure_button_widget();
3111 settings
= gtk_widget_get_settings(gButtonWidget
);
3113 g_object_get(settings
, "gtk-button-images", &result
, NULL
);
3117 /* cairo_t *cr argument has to be a system-cairo. */
3119 moz_gtk_widget_paint(GtkThemeWidgetType widget
, cairo_t
*cr
,
3121 GtkWidgetState
* state
, gint flags
,
3122 GtkTextDirection direction
)
3124 /* A workaround for https://bugzilla.gnome.org/show_bug.cgi?id=694086
3129 case MOZ_GTK_BUTTON
:
3130 if (state
->depressed
) {
3131 ensure_toggle_button_widget();
3132 return moz_gtk_button_paint(cr
, rect
, state
,
3133 (GtkReliefStyle
) flags
,
3134 gToggleButtonWidget
, direction
);
3136 ensure_button_widget();
3137 return moz_gtk_button_paint(cr
, rect
, state
,
3138 (GtkReliefStyle
) flags
, gButtonWidget
,
3141 case MOZ_GTK_CHECKBUTTON
:
3142 case MOZ_GTK_RADIOBUTTON
:
3143 return moz_gtk_toggle_paint(cr
, rect
, state
,
3144 !!(flags
& MOZ_GTK_WIDGET_CHECKED
),
3145 !!(flags
& MOZ_GTK_WIDGET_INCONSISTENT
),
3146 (widget
== MOZ_GTK_RADIOBUTTON
),
3149 case MOZ_GTK_SCROLLBAR_BUTTON
:
3150 return moz_gtk_scrollbar_button_paint(cr
, rect
, state
,
3151 (GtkScrollbarButtonFlags
) flags
,
3154 case MOZ_GTK_SCROLLBAR_TRACK_HORIZONTAL
:
3155 case MOZ_GTK_SCROLLBAR_TRACK_VERTICAL
:
3156 return moz_gtk_scrollbar_trough_paint(widget
, cr
, rect
,
3159 case MOZ_GTK_SCROLLBAR_THUMB_HORIZONTAL
:
3160 case MOZ_GTK_SCROLLBAR_THUMB_VERTICAL
:
3161 return moz_gtk_scrollbar_thumb_paint(widget
, cr
, rect
,
3164 case MOZ_GTK_SCALE_HORIZONTAL
:
3165 case MOZ_GTK_SCALE_VERTICAL
:
3166 return moz_gtk_scale_paint(cr
, rect
, state
,
3167 (GtkOrientation
) flags
, direction
);
3169 case MOZ_GTK_SCALE_THUMB_HORIZONTAL
:
3170 case MOZ_GTK_SCALE_THUMB_VERTICAL
:
3171 return moz_gtk_scale_thumb_paint(cr
, rect
, state
,
3172 (GtkOrientation
) flags
, direction
);
3174 case MOZ_GTK_SPINBUTTON
:
3175 return moz_gtk_spin_paint(cr
, rect
, direction
);
3177 case MOZ_GTK_SPINBUTTON_UP
:
3178 case MOZ_GTK_SPINBUTTON_DOWN
:
3179 return moz_gtk_spin_updown_paint(cr
, rect
,
3180 (widget
== MOZ_GTK_SPINBUTTON_DOWN
),
3183 case MOZ_GTK_SPINBUTTON_ENTRY
:
3184 ensure_spin_widget();
3185 return moz_gtk_entry_paint(cr
, rect
, state
,
3186 gSpinWidget
, direction
);
3188 case MOZ_GTK_GRIPPER
:
3189 return moz_gtk_gripper_paint(cr
, rect
, state
,
3192 case MOZ_GTK_TREEVIEW
:
3193 return moz_gtk_treeview_paint(cr
, rect
, state
,
3196 case MOZ_GTK_TREE_HEADER_CELL
:
3197 return moz_gtk_tree_header_cell_paint(cr
, rect
, state
,
3200 case MOZ_GTK_TREE_HEADER_SORTARROW
:
3201 return moz_gtk_tree_header_sort_arrow_paint(cr
, rect
,
3203 (GtkArrowType
) flags
,
3206 case MOZ_GTK_TREEVIEW_EXPANDER
:
3207 return moz_gtk_treeview_expander_paint(cr
, rect
, state
,
3208 (GtkExpanderStyle
) flags
, direction
);
3211 ensure_entry_widget();
3212 return moz_gtk_entry_paint(cr
, rect
, state
,
3213 gEntryWidget
, direction
);
3215 case MOZ_GTK_DROPDOWN
:
3216 return moz_gtk_combo_box_paint(cr
, rect
, state
,
3217 (gboolean
) flags
, direction
);
3219 case MOZ_GTK_DROPDOWN_ARROW
:
3220 return moz_gtk_combo_box_entry_button_paint(cr
, rect
,
3221 state
, flags
, direction
);
3223 case MOZ_GTK_DROPDOWN_ENTRY
:
3224 ensure_combo_box_entry_widgets();
3225 return moz_gtk_entry_paint(cr
, rect
, state
,
3226 gComboBoxEntryTextareaWidget
, direction
);
3228 case MOZ_GTK_CHECKBUTTON_CONTAINER
:
3229 case MOZ_GTK_RADIOBUTTON_CONTAINER
:
3230 return moz_gtk_container_paint(cr
, rect
, state
,
3231 (widget
== MOZ_GTK_RADIOBUTTON_CONTAINER
),
3234 case MOZ_GTK_CHECKBUTTON_LABEL
:
3235 case MOZ_GTK_RADIOBUTTON_LABEL
:
3236 return moz_gtk_toggle_label_paint(cr
, rect
, state
,
3237 (widget
== MOZ_GTK_RADIOBUTTON_LABEL
),
3240 case MOZ_GTK_TOOLBAR
:
3241 return moz_gtk_toolbar_paint(cr
, rect
, direction
);
3243 case MOZ_GTK_TOOLBAR_SEPARATOR
:
3244 return moz_gtk_toolbar_separator_paint(cr
, rect
,
3247 case MOZ_GTK_TOOLTIP
:
3248 return moz_gtk_tooltip_paint(cr
, rect
, direction
);
3251 return moz_gtk_frame_paint(cr
, rect
, direction
);
3253 case MOZ_GTK_RESIZER
:
3254 return moz_gtk_resizer_paint(cr
, rect
, state
,
3257 case MOZ_GTK_PROGRESSBAR
:
3258 return moz_gtk_progressbar_paint(cr
, rect
, direction
);
3260 case MOZ_GTK_PROGRESS_CHUNK
:
3261 case MOZ_GTK_PROGRESS_CHUNK_INDETERMINATE
:
3262 case MOZ_GTK_PROGRESS_CHUNK_VERTICAL_INDETERMINATE
:
3263 return moz_gtk_progress_chunk_paint(cr
, rect
,
3267 return moz_gtk_tab_paint(cr
, rect
, state
,
3268 (GtkTabFlags
) flags
, direction
);
3270 case MOZ_GTK_TABPANELS
:
3271 return moz_gtk_tabpanels_paint(cr
, rect
, direction
);
3273 case MOZ_GTK_TAB_SCROLLARROW
:
3274 return moz_gtk_tab_scroll_arrow_paint(cr
, rect
, state
,
3275 (GtkArrowType
) flags
, direction
);
3277 case MOZ_GTK_MENUBAR
:
3278 return moz_gtk_menu_bar_paint(cr
, rect
, direction
);
3280 case MOZ_GTK_MENUPOPUP
:
3281 return moz_gtk_menu_popup_paint(cr
, rect
, direction
);
3283 case MOZ_GTK_MENUSEPARATOR
:
3284 return moz_gtk_menu_separator_paint(cr
, rect
,
3287 case MOZ_GTK_MENUITEM
:
3288 return moz_gtk_menu_item_paint(cr
, rect
, state
, flags
,
3291 case MOZ_GTK_MENUARROW
:
3292 return moz_gtk_menu_arrow_paint(cr
, rect
, state
,
3295 case MOZ_GTK_TOOLBARBUTTON_ARROW
:
3296 return moz_gtk_arrow_paint(cr
, rect
, state
,
3297 (GtkArrowType
) flags
, direction
);
3299 case MOZ_GTK_CHECKMENUITEM
:
3300 case MOZ_GTK_RADIOMENUITEM
:
3301 return moz_gtk_check_menu_item_paint(cr
, rect
, state
,
3303 (widget
== MOZ_GTK_RADIOMENUITEM
),
3306 case MOZ_GTK_SPLITTER_HORIZONTAL
:
3307 return moz_gtk_vpaned_paint(cr
, rect
, state
);
3309 case MOZ_GTK_SPLITTER_VERTICAL
:
3310 return moz_gtk_hpaned_paint(cr
, rect
, state
);
3312 case MOZ_GTK_WINDOW
:
3313 return moz_gtk_window_paint(cr
, rect
, direction
);
3316 g_warning("Unknown widget type: %d", widget
);
3319 return MOZ_GTK_UNKNOWN_WIDGET
;
3322 GtkWidget
* moz_gtk_get_scrollbar_widget(void)
3324 NS_ASSERTION(is_initialized
, "Forgot to call moz_gtk_init()");
3325 ensure_scrollbar_widget();
3326 return gHorizScrollbarWidget
;
3332 GtkWidgetClass
*entry_class
;
3335 gtk_widget_destroy(gTooltipWidget
);
3336 /* This will destroy all of our widgets */
3338 gtk_widget_destroy(gProtoWindow
);
3340 /* TODO - replace it with appropriate widget */
3341 if (gTreeHeaderSortArrowWidget
)
3342 gtk_widget_destroy(gTreeHeaderSortArrowWidget
);
3344 gProtoWindow
= NULL
;
3345 gProtoLayout
= NULL
;
3346 gButtonWidget
= NULL
;
3347 gToggleButtonWidget
= NULL
;
3348 gButtonArrowWidget
= NULL
;
3349 gCheckboxWidget
= NULL
;
3350 gRadiobuttonWidget
= NULL
;
3351 gHorizScrollbarWidget
= NULL
;
3352 gVertScrollbarWidget
= NULL
;
3354 gHScaleWidget
= NULL
;
3355 gVScaleWidget
= NULL
;
3356 gEntryWidget
= NULL
;
3357 gComboBoxWidget
= NULL
;
3358 gComboBoxButtonWidget
= NULL
;
3359 gComboBoxSeparatorWidget
= NULL
;
3360 gComboBoxArrowWidget
= NULL
;
3361 gComboBoxEntryWidget
= NULL
;
3362 gComboBoxEntryButtonWidget
= NULL
;
3363 gComboBoxEntryArrowWidget
= NULL
;
3364 gComboBoxEntryTextareaWidget
= NULL
;
3365 gHandleBoxWidget
= NULL
;
3366 gToolbarWidget
= NULL
;
3367 gStatusbarWidget
= NULL
;
3368 gFrameWidget
= NULL
;
3369 gProgressWidget
= NULL
;
3371 gTooltipWidget
= NULL
;
3372 gMenuBarWidget
= NULL
;
3373 gMenuBarItemWidget
= NULL
;
3374 gMenuPopupWidget
= NULL
;
3375 gMenuItemWidget
= NULL
;
3376 gImageMenuItemWidget
= NULL
;
3377 gCheckMenuItemWidget
= NULL
;
3378 gTreeViewWidget
= NULL
;
3379 gMiddleTreeViewColumn
= NULL
;
3380 gTreeHeaderCellWidget
= NULL
;
3381 gTreeHeaderSortArrowWidget
= NULL
;
3382 gExpanderWidget
= NULL
;
3383 gToolbarSeparatorWidget
= NULL
;
3384 gMenuSeparatorWidget
= NULL
;
3385 gHPanedWidget
= NULL
;
3386 gVPanedWidget
= NULL
;
3387 gScrolledWindowWidget
= NULL
;
3389 entry_class
= g_type_class_peek(GTK_TYPE_ENTRY
);
3390 g_type_class_unref(entry_class
);
3392 is_initialized
= FALSE
;
3394 return MOZ_GTK_SUCCESS
;