summaryrefslogtreecommitdiffstats
path: root/WebCore/platform/gtk/gtk2drawing.c
diff options
context:
space:
mode:
authorThe Android Open Source Project <initial-contribution@android.com>2008-12-17 18:05:15 -0800
committerThe Android Open Source Project <initial-contribution@android.com>2008-12-17 18:05:15 -0800
commit1cbdecfa9fc428ac2d8aca0fa91c9580b3d57353 (patch)
tree4457a7306ea5acb43fe05bfe0973b1f7faf97ba2 /WebCore/platform/gtk/gtk2drawing.c
parent9364f22aed35e1a1e9d07c121510f80be3ab0502 (diff)
downloadexternal_webkit-1cbdecfa9fc428ac2d8aca0fa91c9580b3d57353.zip
external_webkit-1cbdecfa9fc428ac2d8aca0fa91c9580b3d57353.tar.gz
external_webkit-1cbdecfa9fc428ac2d8aca0fa91c9580b3d57353.tar.bz2
Code drop from //branches/cupcake/...@124589
Diffstat (limited to 'WebCore/platform/gtk/gtk2drawing.c')
-rw-r--r--WebCore/platform/gtk/gtk2drawing.c1176
1 files changed, 836 insertions, 340 deletions
diff --git a/WebCore/platform/gtk/gtk2drawing.c b/WebCore/platform/gtk/gtk2drawing.c
index 475e9fd..83b4cb4 100644
--- a/WebCore/platform/gtk/gtk2drawing.c
+++ b/WebCore/platform/gtk/gtk2drawing.c
@@ -23,6 +23,7 @@
* Brian Ryner <bryner@brianryner.com> (Original Author)
* Pierre Chanial <p_ch@verizon.net>
* Michael Ventnor <m.ventnor@gmail.com>
+ * Alp Toker <alp@nuanti.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
@@ -57,6 +58,7 @@
static GtkWidget* gProtoWindow;
static GtkWidget* gButtonWidget;
static GtkWidget* gToggleButtonWidget;
+static GtkWidget* gButtonArrowWidget;
static GtkWidget* gCheckboxWidget;
static GtkWidget* gRadiobuttonWidget;
static GtkWidget* gHorizScrollbarWidget;
@@ -65,11 +67,14 @@ static GtkWidget* gSpinWidget;
static GtkWidget* gHScaleWidget;
static GtkWidget* gVScaleWidget;
static GtkWidget* gEntryWidget;
-static GtkWidget* gArrowWidget;
-static GtkWidget* gOptionMenuWidget;
+static GtkWidget* gComboBoxWidget;
+static GtkWidget* gComboBoxButtonWidget;
+static GtkWidget* gComboBoxArrowWidget;
+static GtkWidget* gComboBoxSeparatorWidget;
static GtkWidget* gComboBoxEntryWidget;
-static GtkWidget* gDropdownEntryWidget;
-static GtkWidget* gDropdownButtonWidget;
+static GtkWidget* gComboBoxEntryTextareaWidget;
+static GtkWidget* gComboBoxEntryButtonWidget;
+static GtkWidget* gComboBoxEntryArrowWidget;
static GtkWidget* gHandleBoxWidget;
static GtkWidget* gToolbarWidget;
static GtkWidget* gFrameWidget;
@@ -81,8 +86,10 @@ static GtkWidget* gMenuBarWidget;
static GtkWidget* gMenuBarItemWidget;
static GtkWidget* gMenuPopupWidget;
static GtkWidget* gMenuItemWidget;
+static GtkWidget* gImageMenuItemWidget;
static GtkWidget* gCheckMenuItemWidget;
static GtkWidget* gTreeViewWidget;
+static GtkWidget* gMiddleTreeViewColumn;
static GtkWidget* gTreeHeaderCellWidget;
static GtkWidget* gTreeHeaderSortArrowWidget;
static GtkWidget* gExpanderWidget;
@@ -90,14 +97,22 @@ static GtkWidget* gToolbarSeparatorWidget;
static GtkWidget* gMenuSeparatorWidget;
static GtkWidget* gHPanedWidget;
static GtkWidget* gVPanedWidget;
-
-static GtkShadowType gMenuBarShadowType;
-static GtkShadowType gToolbarShadowType;
+static GtkWidget* gScrolledWindowWidget;
static style_prop_t style_prop_func;
-static gboolean have_menu_shadow_type;
+static gboolean have_arrow_scaling;
+static gboolean have_2_10;
static gboolean is_initialized;
+/* Because we have such an unconventional way of drawing widgets, signal to the GTK theme engine
+ that they are drawing for Mozilla instead of a conventional GTK app so they can do any specific
+ things they may want to do. */
+static void
+moz_gtk_set_widget_name(GtkWidget* widget)
+{
+ gtk_widget_set_name(widget, "MozillaGtkWidget");
+}
+
gint
moz_gtk_enable_style_props(style_prop_t styleGetProp)
{
@@ -111,6 +126,7 @@ ensure_window_widget()
if (!gProtoWindow) {
gProtoWindow = gtk_window_new(GTK_WINDOW_POPUP);
gtk_widget_realize(gProtoWindow);
+ moz_gtk_set_widget_name(gProtoWindow);
}
return MOZ_GTK_SUCCESS;
}
@@ -127,6 +143,7 @@ setup_widget_prototype(GtkWidget* widget)
gtk_container_add(GTK_CONTAINER(protoLayout), widget);
gtk_widget_realize(widget);
+ g_object_set_data(G_OBJECT(widget), "transparent-bg-hint", TRUE);
return MOZ_GTK_SUCCESS;
}
@@ -173,6 +190,19 @@ ensure_toggle_button_widget()
}
static gint
+ensure_button_arrow_widget()
+{
+ if (!gButtonArrowWidget) {
+ ensure_toggle_button_widget();
+
+ gButtonArrowWidget = gtk_arrow_new(GTK_ARROW_DOWN, GTK_SHADOW_OUT);
+ gtk_container_add(GTK_CONTAINER(gToggleButtonWidget), gButtonArrowWidget);
+ gtk_widget_realize(gButtonArrowWidget);
+ }
+ return MOZ_GTK_SUCCESS;
+}
+
+static gint
ensure_checkbox_widget()
{
if (!gCheckboxWidget) {
@@ -240,64 +270,219 @@ ensure_entry_widget()
return MOZ_GTK_SUCCESS;
}
-static gint
-ensure_option_menu_widget()
-{
- if (!gOptionMenuWidget) {
- gOptionMenuWidget = gtk_option_menu_new();
- setup_widget_prototype(gOptionMenuWidget);
+/* We need to have pointers to the inner widgets (button, separator, arrow)
+ * of the ComboBox to get the correct rendering from theme engines which
+ * special cases their look. Since the inner layout can change, we ask GTK
+ * to NULL our pointers when they are about to become invalid because the
+ * corresponding widgets don't exist anymore. It's the role of
+ * g_object_add_weak_pointer().
+ * Note that if we don't find the inner widgets (which shouldn't happen), we
+ * fallback to use generic "non-inner" widgets, and they don't need that kind
+ * of weak pointer since they are explicit children of gProtoWindow and as
+ * such GTK holds a strong reference to them. */
+static void
+moz_gtk_get_combo_box_inner_button(GtkWidget *widget, gpointer client_data)
+{
+ if (GTK_IS_TOGGLE_BUTTON(widget)) {
+ gComboBoxButtonWidget = widget;
+ g_object_add_weak_pointer(G_OBJECT(widget),
+ (gpointer) &gComboBoxButtonWidget);
+ gtk_widget_realize(widget);
+ g_object_set_data(G_OBJECT(widget), "transparent-bg-hint", TRUE);
}
- return MOZ_GTK_SUCCESS;
}
-static gint
-ensure_combo_box_entry_widget()
-{
- if (!gComboBoxEntryWidget) {
- gComboBoxEntryWidget = gtk_combo_box_entry_new();
- setup_widget_prototype(gComboBoxEntryWidget);
- }
- return MOZ_GTK_SUCCESS;
+static void
+moz_gtk_get_combo_box_button_inner_widgets(GtkWidget *widget,
+ gpointer client_data)
+{
+ if (GTK_IS_SEPARATOR(widget)) {
+ gComboBoxSeparatorWidget = widget;
+ g_object_add_weak_pointer(G_OBJECT(widget),
+ (gpointer) &gComboBoxSeparatorWidget);
+ } else if (GTK_IS_ARROW(widget)) {
+ gComboBoxArrowWidget = widget;
+ g_object_add_weak_pointer(G_OBJECT(widget),
+ (gpointer) &gComboBoxArrowWidget);
+ } else
+ return;
+ gtk_widget_realize(widget);
+ g_object_set_data(G_OBJECT(widget), "transparent-bg-hint", TRUE);
}
static gint
-ensure_dropdown_entry_widget()
+ensure_combo_box_widgets()
{
- if (!gDropdownEntryWidget) {
- ensure_combo_box_entry_widget();
+ GtkWidget* buttonChild;
+
+ if (gComboBoxButtonWidget && gComboBoxArrowWidget)
+ return MOZ_GTK_SUCCESS;
+
+ /* Create a ComboBox if needed */
+ if (!gComboBoxWidget) {
+ gComboBoxWidget = gtk_combo_box_new();
+ setup_widget_prototype(gComboBoxWidget);
+ }
+
+ /* Get its inner Button */
+ gtk_container_forall(GTK_CONTAINER(gComboBoxWidget),
+ moz_gtk_get_combo_box_inner_button,
+ NULL);
+
+ if (gComboBoxButtonWidget) {
+ /* Get the widgets inside the Button */
+ buttonChild = GTK_BIN(gComboBoxButtonWidget)->child;
+ if (GTK_IS_HBOX(buttonChild)) {
+ /* appears-as-list = FALSE, cell-view = TRUE; the button
+ * contains an hbox. This hbox is there because the ComboBox
+ * needs to place a cell renderer, a separator, and an arrow in
+ * the button when appears-as-list is FALSE. */
+ gtk_container_forall(GTK_CONTAINER(buttonChild),
+ moz_gtk_get_combo_box_button_inner_widgets,
+ NULL);
+ } else if(GTK_IS_ARROW(buttonChild)) {
+ /* appears-as-list = TRUE, or cell-view = FALSE;
+ * the button only contains an arrow */
+ gComboBoxArrowWidget = buttonChild;
+ g_object_add_weak_pointer(G_OBJECT(buttonChild), (gpointer)
+ &gComboBoxArrowWidget);
+ gtk_widget_realize(gComboBoxArrowWidget);
+ g_object_set_data(G_OBJECT(gComboBoxArrowWidget),
+ "transparent-bg-hint", TRUE);
+ }
+ } else {
+ /* Shouldn't be reached with current internal gtk implementation; we
+ * use a generic toggle button as last resort fallback to avoid
+ * crashing. */
+ ensure_toggle_button_widget();
+ gComboBoxButtonWidget = gToggleButtonWidget;
+ }
- gDropdownEntryWidget = GTK_BIN(gComboBoxEntryWidget)->child;
- gtk_widget_realize(gDropdownEntryWidget);
+ if (!gComboBoxArrowWidget) {
+ /* Shouldn't be reached with current internal gtk implementation;
+ * we gButtonArrowWidget as last resort fallback to avoid
+ * crashing. */
+ ensure_button_arrow_widget();
+ gComboBoxArrowWidget = gButtonArrowWidget;
}
+
+ /* We don't test the validity of gComboBoxSeparatorWidget since there
+ * is none when "appears-as-list" = TRUE or "cell-view" = FALSE; if it
+ * is invalid we just won't paint it. */
+
return MOZ_GTK_SUCCESS;
}
+/* We need to have pointers to the inner widgets (entry, button, arrow) of
+ * the ComboBoxEntry to get the correct rendering from theme engines which
+ * special cases their look. Since the inner layout can change, we ask GTK
+ * to NULL our pointers when they are about to become invalid because the
+ * corresponding widgets don't exist anymore. It's the role of
+ * g_object_add_weak_pointer().
+ * Note that if we don't find the inner widgets (which shouldn't happen), we
+ * fallback to use generic "non-inner" widgets, and they don't need that kind
+ * of weak pointer since they are explicit children of gProtoWindow and as
+ * such GTK holds a strong reference to them. */
static void
-moz_gtk_get_dropdown_button(GtkWidget *widget,
- gpointer client_data)
-{
- if (GTK_IS_TOGGLE_BUTTON(widget))
- gDropdownButtonWidget = widget;
+moz_gtk_get_combo_box_entry_inner_widgets(GtkWidget *widget,
+ gpointer client_data)
+{
+ if (GTK_IS_TOGGLE_BUTTON(widget)) {
+ gComboBoxEntryButtonWidget = widget;
+ g_object_add_weak_pointer(G_OBJECT(widget),
+ (gpointer) &gComboBoxEntryButtonWidget);
+ } else if (GTK_IS_ENTRY(widget)) {
+ gComboBoxEntryTextareaWidget = widget;
+ g_object_add_weak_pointer(G_OBJECT(widget),
+ (gpointer) &gComboBoxEntryTextareaWidget);
+ } else
+ return;
+ gtk_widget_realize(widget);
+ g_object_set_data(G_OBJECT(widget), "transparent-bg-hint", TRUE);
+}
+
+static void
+moz_gtk_get_combo_box_entry_arrow(GtkWidget *widget, gpointer client_data)
+{
+ if (GTK_IS_ARROW(widget)) {
+ gComboBoxEntryArrowWidget = widget;
+ g_object_add_weak_pointer(G_OBJECT(widget),
+ (gpointer) &gComboBoxEntryArrowWidget);
+ gtk_widget_realize(widget);
+ g_object_set_data(G_OBJECT(widget), "transparent-bg-hint", TRUE);
+ }
}
static gint
-ensure_arrow_widget()
+ensure_combo_box_entry_widgets()
{
- if (!gArrowWidget) {
- ensure_combo_box_entry_widget();
+ GtkWidget* buttonChild;
- gtk_container_forall(GTK_CONTAINER(gComboBoxEntryWidget),
- moz_gtk_get_dropdown_button,
- NULL);
+ if (gComboBoxEntryTextareaWidget &&
+ gComboBoxEntryButtonWidget &&
+ gComboBoxEntryArrowWidget)
+ return MOZ_GTK_SUCCESS;
+
+ /* Create a ComboBoxEntry if needed */
+ if (!gComboBoxEntryWidget) {
+ gComboBoxEntryWidget = gtk_combo_box_entry_new();
+ setup_widget_prototype(gComboBoxEntryWidget);
+ }
- gArrowWidget = gtk_arrow_new(GTK_ARROW_DOWN, GTK_SHADOW_OUT);
- gtk_container_add(GTK_CONTAINER(GTK_BIN(gDropdownButtonWidget)->child),
- gArrowWidget);
- gtk_widget_realize(gArrowWidget);
+ /* Get its inner Entry and Button */
+ gtk_container_forall(GTK_CONTAINER(gComboBoxEntryWidget),
+ moz_gtk_get_combo_box_entry_inner_widgets,
+ NULL);
+
+ if (!gComboBoxEntryTextareaWidget) {
+ ensure_entry_widget();
+ gComboBoxEntryTextareaWidget = gEntryWidget;
+ }
+
+ if (gComboBoxEntryButtonWidget) {
+ /* Get the Arrow inside the Button */
+ buttonChild = GTK_BIN(gComboBoxEntryButtonWidget)->child;
+ if (GTK_IS_HBOX(buttonChild)) {
+ /* appears-as-list = FALSE, cell-view = TRUE; the button
+ * contains an hbox. This hbox is there because ComboBoxEntry
+ * inherits from ComboBox which needs to place a cell renderer,
+ * a separator, and an arrow in the button when appears-as-list
+ * is FALSE. Here the hbox should only contain an arrow, since
+ * a ComboBoxEntry doesn't need all those widgets in the
+ * button. */
+ gtk_container_forall(GTK_CONTAINER(buttonChild),
+ moz_gtk_get_combo_box_entry_arrow,
+ NULL);
+ } else if(GTK_IS_ARROW(buttonChild)) {
+ /* appears-as-list = TRUE, or cell-view = FALSE;
+ * the button only contains an arrow */
+ gComboBoxEntryArrowWidget = buttonChild;
+ g_object_add_weak_pointer(G_OBJECT(buttonChild), (gpointer)
+ &gComboBoxEntryArrowWidget);
+ gtk_widget_realize(gComboBoxEntryArrowWidget);
+ g_object_set_data(G_OBJECT(gComboBoxEntryArrowWidget),
+ "transparent-bg-hint", TRUE);
+ }
+ } else {
+ /* Shouldn't be reached with current internal gtk implementation;
+ * we use a generic toggle button as last resort fallback to avoid
+ * crashing. */
+ ensure_toggle_button_widget();
+ gComboBoxEntryButtonWidget = gToggleButtonWidget;
}
+
+ if (!gComboBoxEntryArrowWidget) {
+ /* Shouldn't be reached with current internal gtk implementation;
+ * we gButtonArrowWidget as last resort fallback to avoid
+ * crashing. */
+ ensure_button_arrow_widget();
+ gComboBoxEntryArrowWidget = gButtonArrowWidget;
+ }
+
return MOZ_GTK_SUCCESS;
}
+
static gint
ensure_handlebox_widget()
{
@@ -316,8 +501,7 @@ ensure_toolbar_widget()
gToolbarWidget = gtk_toolbar_new();
gtk_container_add(GTK_CONTAINER(gHandleBoxWidget), gToolbarWidget);
gtk_widget_realize(gToolbarWidget);
- gtk_widget_style_get(gToolbarWidget, "shadow_type", &gToolbarShadowType,
- NULL);
+ g_object_set_data(G_OBJECT(gToolbarWidget), "transparent-bg-hint", TRUE);
}
return MOZ_GTK_SUCCESS;
}
@@ -339,6 +523,7 @@ ensure_tooltip_widget()
if (!gTooltipWidget) {
gTooltipWidget = gtk_window_new(GTK_WINDOW_POPUP);
gtk_widget_realize(gTooltipWidget);
+ moz_gtk_set_widget_name(gTooltipWidget);
}
return MOZ_GTK_SUCCESS;
}
@@ -391,8 +576,6 @@ ensure_menu_bar_widget()
if (!gMenuBarWidget) {
gMenuBarWidget = gtk_menu_bar_new();
setup_widget_prototype(gMenuBarWidget);
- gtk_widget_style_get(gMenuBarWidget, "shadow_type", &gMenuBarShadowType,
- NULL);
}
return MOZ_GTK_SUCCESS;
}
@@ -406,6 +589,8 @@ ensure_menu_bar_item_widget()
gtk_menu_shell_append(GTK_MENU_SHELL(gMenuBarWidget),
gMenuBarItemWidget);
gtk_widget_realize(gMenuBarItemWidget);
+ g_object_set_data(G_OBJECT(gMenuBarItemWidget),
+ "transparent-bg-hint", TRUE);
}
return MOZ_GTK_SUCCESS;
}
@@ -419,6 +604,8 @@ ensure_menu_popup_widget()
gtk_menu_item_set_submenu(GTK_MENU_ITEM(gMenuBarItemWidget),
gMenuPopupWidget);
gtk_widget_realize(gMenuPopupWidget);
+ g_object_set_data(G_OBJECT(gMenuPopupWidget),
+ "transparent-bg-hint", TRUE);
}
return MOZ_GTK_SUCCESS;
}
@@ -432,6 +619,23 @@ ensure_menu_item_widget()
gtk_menu_shell_append(GTK_MENU_SHELL(gMenuPopupWidget),
gMenuItemWidget);
gtk_widget_realize(gMenuItemWidget);
+ g_object_set_data(G_OBJECT(gMenuItemWidget),
+ "transparent-bg-hint", TRUE);
+ }
+ return MOZ_GTK_SUCCESS;
+}
+
+static gint
+ensure_image_menu_item_widget()
+{
+ if (!gImageMenuItemWidget) {
+ ensure_menu_popup_widget();
+ gImageMenuItemWidget = gtk_image_menu_item_new();
+ gtk_menu_shell_append(GTK_MENU_SHELL(gMenuPopupWidget),
+ gImageMenuItemWidget);
+ gtk_widget_realize(gImageMenuItemWidget);
+ g_object_set_data(G_OBJECT(gImageMenuItemWidget),
+ "transparent-bg-hint", TRUE);
}
return MOZ_GTK_SUCCESS;
}
@@ -445,6 +649,8 @@ ensure_menu_separator_widget()
gtk_menu_shell_append(GTK_MENU_SHELL(gMenuPopupWidget),
gMenuSeparatorWidget);
gtk_widget_realize(gMenuSeparatorWidget);
+ g_object_set_data(G_OBJECT(gMenuSeparatorWidget),
+ "transparent-bg-hint", TRUE);
}
return MOZ_GTK_SUCCESS;
}
@@ -458,6 +664,8 @@ ensure_check_menu_item_widget()
gtk_menu_shell_append(GTK_MENU_SHELL(gMenuPopupWidget),
gCheckMenuItemWidget);
gtk_widget_realize(gCheckMenuItemWidget);
+ g_object_set_data(G_OBJECT(gCheckMenuItemWidget),
+ "transparent-bg-hint", TRUE);
}
return MOZ_GTK_SUCCESS;
}
@@ -476,16 +684,45 @@ static gint
ensure_tree_header_cell_widget()
{
if(!gTreeHeaderCellWidget) {
- GtkTreeViewColumn* treeViewColumn;
- ensure_tree_view_widget();
+ /*
+ * Some GTK engines paint the first and last cell
+ * of a TreeView header with a highlight.
+ * Since we do not know where our widget will be relative
+ * to the other buttons in the TreeView header, we must
+ * paint it as a button that is between two others,
+ * thus ensuring it is neither the first or last button
+ * in the header.
+ * GTK doesn't give us a way to do this explicitly,
+ * so we must paint with a button that is between two
+ * others.
+ */
+
+ GtkTreeViewColumn* firstTreeViewColumn;
+ GtkTreeViewColumn* lastTreeViewColumn;
- treeViewColumn = gtk_tree_view_column_new();
- gtk_tree_view_column_set_title(treeViewColumn, "M");
+ ensure_tree_view_widget();
- gtk_tree_view_append_column(GTK_TREE_VIEW(gTreeViewWidget), treeViewColumn);
- gTreeHeaderCellWidget = treeViewColumn->button;
- gtk_tree_view_column_set_sort_indicator(treeViewColumn, TRUE);
- gTreeHeaderSortArrowWidget = treeViewColumn->arrow;
+ /* Create and append our three columns */
+ firstTreeViewColumn = gtk_tree_view_column_new();
+ gtk_tree_view_column_set_title(firstTreeViewColumn, "M");
+ gtk_tree_view_append_column(GTK_TREE_VIEW(gTreeViewWidget), firstTreeViewColumn);
+
+ gMiddleTreeViewColumn = gtk_tree_view_column_new();
+ gtk_tree_view_column_set_title(GTK_TREE_VIEW_COLUMN(gMiddleTreeViewColumn), "M");
+ gtk_tree_view_append_column(GTK_TREE_VIEW(gTreeViewWidget),
+ GTK_TREE_VIEW_COLUMN(gMiddleTreeViewColumn));
+
+ lastTreeViewColumn = gtk_tree_view_column_new();
+ gtk_tree_view_column_set_title(lastTreeViewColumn, "M");
+ gtk_tree_view_append_column(GTK_TREE_VIEW(gTreeViewWidget), lastTreeViewColumn);
+
+ /* Use the middle column's header for our button */
+ gTreeHeaderCellWidget = GTK_TREE_VIEW_COLUMN(gMiddleTreeViewColumn)->button;
+ gTreeHeaderSortArrowWidget = GTK_TREE_VIEW_COLUMN(gMiddleTreeViewColumn)->arrow;
+ g_object_set_data(G_OBJECT(gTreeHeaderCellWidget),
+ "transparent-bg-hint", TRUE);
+ g_object_set_data(G_OBJECT(gTreeHeaderSortArrowWidget),
+ "transparent-bg-hint", TRUE);
}
return MOZ_GTK_SUCCESS;
}
@@ -500,6 +737,16 @@ ensure_expander_widget()
return MOZ_GTK_SUCCESS;
}
+static gint
+ensure_scrolled_window_widget()
+{
+ if (!gScrolledWindowWidget) {
+ gScrolledWindowWidget = gtk_scrolled_window_new(NULL, NULL);
+ setup_widget_prototype(gScrolledWindowWidget);
+ }
+ return MOZ_GTK_SUCCESS;
+}
+
static GtkStateType
ConvertGtkState(GtkWidgetState* state)
{
@@ -566,6 +813,13 @@ moz_gtk_button_paint(GdkDrawable* drawable, GdkRectangle* rect,
if (state->isDefault)
GTK_WIDGET_SET_FLAGS(widget, GTK_HAS_DEFAULT);
+ GTK_BUTTON(widget)->relief = relief;
+
+ /* Some theme engines love to cause us pain in that gtk_paint_focus is a
+ no-op on buttons and button-like widgets. They only listen to this flag. */
+ if (state->focused && !state->disabled)
+ GTK_WIDGET_SET_FLAGS(widget, GTK_HAS_FOCUS);
+
if (!interior_focus && state->focused) {
x += focus_width + focus_pad;
y += focus_width + focus_pad;
@@ -576,7 +830,7 @@ moz_gtk_button_paint(GdkDrawable* drawable, GdkRectangle* rect,
shadow_type = button_state == GTK_STATE_ACTIVE ||
state->depressed ? GTK_SHADOW_IN : GTK_SHADOW_OUT;
- if (state->isDefault && GTK_BUTTON(widget)->relief == GTK_RELIEF_NORMAL) {
+ if (state->isDefault && relief == GTK_RELIEF_NORMAL) {
gtk_paint_box(style, drawable, button_state, shadow_type, cliprect,
widget, "buttondefault", x, y, width, height);
}
@@ -611,16 +865,32 @@ moz_gtk_button_paint(GdkDrawable* drawable, GdkRectangle* rect,
}
GTK_WIDGET_UNSET_FLAGS(widget, GTK_HAS_DEFAULT);
+ GTK_WIDGET_UNSET_FLAGS(widget, GTK_HAS_FOCUS);
return MOZ_GTK_SUCCESS;
}
gint
moz_gtk_init()
{
+ GtkWidgetClass *entry_class;
+
is_initialized = TRUE;
- have_menu_shadow_type =
- (gtk_major_version > 2 ||
- (gtk_major_version == 2 && gtk_minor_version >= 1));
+ have_arrow_scaling = (gtk_major_version > 2 ||
+ (gtk_major_version == 2 && gtk_minor_version >= 12));
+
+ have_2_10 = (gtk_major_version > 2 ||
+ (gtk_major_version == 2 && gtk_minor_version >= 10));
+
+ /* Add style property to GtkEntry.
+ * Adding the style property to the normal GtkEntry class means that it
+ * will work without issues inside GtkComboBox and for Spinbuttons. */
+ entry_class = g_type_class_ref(GTK_TYPE_ENTRY);
+ gtk_widget_class_install_style_property(entry_class,
+ g_param_spec_boolean("honors-transparent-bg-hint",
+ "Transparent BG enabling flag",
+ "If TRUE, the theme is able to draw the GtkEntry on non-prefilled background.",
+ FALSE,
+ G_PARAM_READWRITE));
return MOZ_GTK_SUCCESS;
}
@@ -664,45 +934,6 @@ moz_gtk_widget_get_focus(GtkWidget* widget, gboolean* interior_focus,
return MOZ_GTK_SUCCESS;
}
-static gint
-moz_gtk_option_menu_get_metrics(gboolean* interior_focus,
- GtkRequisition* indicator_size,
- GtkBorder* indicator_spacing,
- gint* focus_width,
- gint* focus_pad)
-{
- static const GtkRequisition default_indicator_size = { 7, 13 };
- static const GtkBorder default_indicator_spacing = { 7, 5, 2, 2 };
- /* these default values are not used in gtkoptionmenu.c
- static const gboolean default_interior_focus = TRUE;
- static const gint default_focus_width = 1;
- static const gint default_focus_pad = 0; */
- GtkRequisition *tmp_indicator_size;
- GtkBorder *tmp_indicator_spacing;
-
- gtk_widget_style_get(gOptionMenuWidget,
- "interior_focus", interior_focus,
- "indicator_size", &tmp_indicator_size,
- "indicator_spacing", &tmp_indicator_spacing,
- "focus_line_width", focus_width,
- "focus_padding", focus_pad,
- NULL);
-
- if (tmp_indicator_size)
- *indicator_size = *tmp_indicator_size;
- else
- *indicator_size = default_indicator_size;
- if (tmp_indicator_spacing)
- *indicator_spacing = *tmp_indicator_spacing;
- else
- *indicator_spacing = default_indicator_spacing;
-
- gtk_requisition_free(tmp_indicator_size);
- gtk_border_free(tmp_indicator_spacing);
-
- return MOZ_GTK_SUCCESS;
-}
-
gint
moz_gtk_splitter_get_metrics(gint orientation, gint* size)
{
@@ -716,6 +947,25 @@ moz_gtk_splitter_get_metrics(gint orientation, gint* size)
return MOZ_GTK_SUCCESS;
}
+gint
+moz_gtk_button_get_inner_border(GtkWidget* widget, GtkBorder* inner_border)
+{
+ static const GtkBorder default_inner_border = { 1, 1, 1, 1 };
+ GtkBorder *tmp_border = NULL;
+
+ if (have_2_10)
+ gtk_widget_style_get (widget, "inner-border", &tmp_border, NULL);
+
+ if (tmp_border) {
+ *inner_border = *tmp_border;
+ gtk_border_free(tmp_border);
+ }
+ else
+ *inner_border = default_inner_border;
+
+ return MOZ_GTK_SUCCESS;
+}
+
static gint
moz_gtk_toggle_paint(GdkDrawable* drawable, GdkRectangle* rect,
GdkRectangle* cliprect, GtkWidgetState* state,
@@ -726,6 +976,7 @@ moz_gtk_toggle_paint(GdkDrawable* drawable, GdkRectangle* rect,
GtkShadowType shadow_type = (selected)?GTK_SHADOW_IN:GTK_SHADOW_OUT;
gint indicator_size, indicator_spacing;
gint x, y, width, height;
+ gint focus_x, focus_y, focus_width, focus_height;
GtkWidget *w;
GtkStyle *style;
@@ -737,11 +988,19 @@ moz_gtk_toggle_paint(GdkDrawable* drawable, GdkRectangle* rect,
w = gCheckboxWidget;
}
- /* offset by indicator_spacing, and centered vertically within the rect */
- x = rect->x + indicator_spacing;
+ /*
+ * vertically center in the box, since XUL sometimes ignores our
+ * GetMinimumWidgetSize in the vertical dimension
+ */
+ x = rect->x;
y = rect->y + (rect->height - indicator_size) / 2;
width = indicator_size;
height = indicator_size;
+
+ focus_x = x - indicator_spacing;
+ focus_y = y - indicator_spacing;
+ focus_width = width + 2 * indicator_spacing;
+ focus_height = height + 2 * indicator_spacing;
style = w->style;
TSOffsetStyleGCs(style, x, y);
@@ -756,8 +1015,8 @@ moz_gtk_toggle_paint(GdkDrawable* drawable, GdkRectangle* rect,
width, height);
if (state->focused) {
gtk_paint_focus(style, drawable, GTK_STATE_ACTIVE, cliprect,
- gRadiobuttonWidget, "radiobutton", rect->x, rect->y,
- rect->width, rect->height);
+ gRadiobuttonWidget, "radiobutton", focus_x, focus_y,
+ focus_width, focus_height);
}
}
else {
@@ -765,8 +1024,8 @@ moz_gtk_toggle_paint(GdkDrawable* drawable, GdkRectangle* rect,
gCheckboxWidget, "checkbutton", x, y, width, height);
if (state->focused) {
gtk_paint_focus(style, drawable, GTK_STATE_ACTIVE, cliprect,
- gCheckboxWidget, "checkbutton", rect->x, rect->y,
- rect->width, rect->height);
+ gCheckboxWidget, "checkbutton", focus_x, focus_y,
+ focus_width, focus_height);
}
}
@@ -774,20 +1033,63 @@ moz_gtk_toggle_paint(GdkDrawable* drawable, GdkRectangle* rect,
}
static gint
-calculate_arrow_dimensions(GdkRectangle* rect, GdkRectangle* arrow_rect)
+calculate_button_inner_rect(GtkWidget* button, GdkRectangle* rect,
+ GdkRectangle* inner_rect,
+ GtkTextDirection direction,
+ gboolean ignore_focus)
+{
+ GtkBorder inner_border;
+ gboolean interior_focus;
+ gint focus_width, focus_pad;
+ GtkStyle* style;
+
+ style = button->style;
+
+ /* This mirrors gtkbutton's child positioning */
+ moz_gtk_button_get_inner_border(button, &inner_border);
+ moz_gtk_widget_get_focus(button, &interior_focus,
+ &focus_width, &focus_pad);
+
+ if (ignore_focus)
+ focus_width = focus_pad = 0;
+
+ inner_rect->x = rect->x + XTHICKNESS(style) + focus_width + focus_pad;
+ inner_rect->x += direction == GTK_TEXT_DIR_LTR ?
+ inner_border.left : inner_border.right;
+ inner_rect->y = rect->y + inner_border.top + YTHICKNESS(style) +
+ focus_width + focus_pad;
+ inner_rect->width = MAX(1, rect->width - inner_border.left -
+ inner_border.right - (XTHICKNESS(style) + focus_pad + focus_width) * 2);
+ inner_rect->height = MAX(1, rect->height - inner_border.top -
+ inner_border.bottom - (YTHICKNESS(style) + focus_pad + focus_width) * 2);
+
+ return MOZ_GTK_SUCCESS;
+}
+
+
+static gint
+calculate_arrow_rect(GtkWidget* arrow, GdkRectangle* rect,
+ GdkRectangle* arrow_rect, GtkTextDirection direction)
{
- GtkMisc* misc = GTK_MISC(gArrowWidget);
+ /* defined in gtkarrow.c */
+ gfloat arrow_scaling = 0.7;
+ gfloat xalign, xpad;
+ gint extent;
+ GtkMisc* misc = GTK_MISC(arrow);
- gint extent = MIN(rect->width - misc->xpad * 2,
- rect->height - misc->ypad * 2);
+ if (have_arrow_scaling)
+ gtk_widget_style_get(arrow, "arrow_scaling", &arrow_scaling, NULL);
- arrow_rect->x = ((rect->x + misc->xpad) * (1.0 - misc->xalign) +
- (rect->x + rect->width - extent - misc->xpad) *
- misc->xalign);
+ extent = MIN((rect->width - misc->xpad * 2),
+ (rect->height - misc->ypad * 2)) * arrow_scaling;
- arrow_rect->y = ((rect->y + misc->ypad) * (1.0 - misc->yalign) +
- (rect->y + rect->height - extent - misc->ypad) *
- misc->yalign);
+ xalign = direction == GTK_TEXT_DIR_LTR ? misc->xalign : 1.0 - misc->xalign;
+ xpad = misc->xpad + (rect->width - extent) * xalign;
+
+ arrow_rect->x = direction == GTK_TEXT_DIR_LTR ?
+ floor(rect->x + xpad) : ceil(rect->x + xpad);
+ arrow_rect->y = floor(rect->y + misc->ypad +
+ ((rect->height - extent) * misc->yalign));
arrow_rect->width = arrow_rect->height = extent;
@@ -803,11 +1105,11 @@ moz_gtk_scrollbar_button_paint(GdkDrawable* drawable, GdkRectangle* rect,
GtkStateType state_type = ConvertGtkState(state);
GtkShadowType shadow_type = (state->active) ?
GTK_SHADOW_IN : GTK_SHADOW_OUT;
- GdkRectangle button_rect;
GdkRectangle arrow_rect;
GtkStyle* style;
GtkWidget *scrollbar;
GtkArrowType arrow_type;
+ gint arrow_displacement_x, arrow_displacement_y;
const char* detail = (flags & MOZ_GTK_STEPPER_VERTICAL) ?
"vscrollbar" : "hscrollbar";
@@ -860,20 +1162,26 @@ moz_gtk_scrollbar_button_paint(GdkDrawable* drawable, GdkRectangle* rect,
style = scrollbar->style;
- ensure_arrow_widget();
-
- calculate_arrow_dimensions(rect, &button_rect);
- TSOffsetStyleGCs(style, button_rect.x, button_rect.y);
+ TSOffsetStyleGCs(style, rect->x, rect->y);
gtk_paint_box(style, drawable, state_type, shadow_type, cliprect,
- scrollbar, detail, button_rect.x, button_rect.y,
- button_rect.width, button_rect.height);
+ scrollbar, detail, rect->x, rect->y,
+ rect->width, rect->height);
+
+ arrow_rect.width = rect->width / 2;
+ arrow_rect.height = rect->height / 2;
+ arrow_rect.x = rect->x + (rect->width - arrow_rect.width) / 2;
+ arrow_rect.y = rect->y + (rect->height - arrow_rect.height) / 2;
- arrow_rect.width = button_rect.width / 2;
- arrow_rect.height = button_rect.height / 2;
- arrow_rect.x = button_rect.x + (button_rect.width - arrow_rect.width) / 2;
- arrow_rect.y = button_rect.y +
- (button_rect.height - arrow_rect.height) / 2;
+ if (state_type == GTK_STATE_ACTIVE) {
+ gtk_widget_style_get(scrollbar,
+ "arrow-displacement-x", &arrow_displacement_x,
+ "arrow-displacement-y", &arrow_displacement_y,
+ NULL);
+
+ arrow_rect.x += arrow_displacement_x;
+ arrow_rect.y += arrow_displacement_y;
+ }
gtk_paint_arrow(style, drawable, state_type, shadow_type, cliprect,
scrollbar, detail, arrow_type, TRUE, arrow_rect.x,
@@ -928,9 +1236,11 @@ moz_gtk_scrollbar_thumb_paint(GtkThemeWidgetType widget,
{
GtkStateType state_type = (state->inHover || state->active) ?
GTK_STATE_PRELIGHT : GTK_STATE_NORMAL;
+ GtkShadowType shadow_type = GTK_SHADOW_OUT;
GtkStyle* style;
GtkScrollbar *scrollbar;
GtkAdjustment *adj;
+ gboolean activate_slider;
ensure_scrollbar_widget();
@@ -971,10 +1281,18 @@ moz_gtk_scrollbar_thumb_paint(GtkThemeWidgetType widget,
gtk_adjustment_changed(adj);
style = GTK_WIDGET(scrollbar)->style;
+
+ gtk_widget_style_get(GTK_WIDGET(scrollbar), "activate-slider",
+ &activate_slider, NULL);
+
+ if (activate_slider && state->active) {
+ shadow_type = GTK_SHADOW_IN;
+ state_type = GTK_STATE_ACTIVE;
+ }
TSOffsetStyleGCs(style, rect->x, rect->y);
- gtk_paint_slider(style, drawable, state_type, GTK_SHADOW_OUT, cliprect,
+ gtk_paint_slider(style, drawable, state_type, shadow_type, cliprect,
GTK_WIDGET(scrollbar), "slider", rect->x, rect->y,
rect->width, rect->height,
(widget == MOZ_GTK_SCROLLBAR_THUMB_HORIZONTAL) ?
@@ -1167,52 +1485,87 @@ moz_gtk_vpaned_paint(GdkDrawable* drawable, GdkRectangle* rect,
}
static gint
+moz_gtk_caret_paint(GdkDrawable* drawable, GdkRectangle* rect,
+ GdkRectangle* cliprect, GtkTextDirection direction)
+{
+ ensure_entry_widget();
+ gtk_draw_insertion_cursor(gEntryWidget, drawable, cliprect,
+ rect, TRUE, direction, FALSE);
+
+ return MOZ_GTK_SUCCESS;
+}
+
+static gint
moz_gtk_entry_paint(GdkDrawable* drawable, GdkRectangle* rect,
GdkRectangle* cliprect, GtkWidgetState* state,
GtkWidget* widget, GtkTextDirection direction)
{
+ GtkStateType bg_state = state->disabled ?
+ GTK_STATE_INSENSITIVE : GTK_STATE_NORMAL;
gint x, y, width = rect->width, height = rect->height;
GtkStyle* style;
gboolean interior_focus;
+ gboolean theme_honors_transparency = FALSE;
gint focus_width;
gtk_widget_set_direction(widget, direction);
style = widget->style;
- /* paint the background first */
- x = XTHICKNESS(style);
- y = YTHICKNESS(style);
+ gtk_widget_style_get(widget,
+ "interior-focus", &interior_focus,
+ "focus-line-width", &focus_width,
+ "honors-transparent-bg-hint", &theme_honors_transparency,
+ NULL);
+
+ /* gtkentry.c uses two windows, one for the entire widget and one for the
+ * text area inside it. The background of both windows is set to the "base"
+ * color of the new state in gtk_entry_state_changed, but only the inner
+ * textarea window uses gtk_paint_flat_box when exposed */
+
+ TSOffsetStyleGCs(style, rect->x, rect->y);
/* This gets us a lovely greyish disabledish look */
gtk_widget_set_sensitive(widget, !state->disabled);
- TSOffsetStyleGCs(style, rect->x + x, rect->y + y);
- gtk_paint_flat_box(style, drawable, GTK_STATE_NORMAL, GTK_SHADOW_NONE,
- cliprect, widget, "entry_bg", rect->x + x,
- rect->y + y, rect->width - 2*x, rect->height - 2*y);
+ /* GTK fills the outer widget window with the base color before drawing the widget.
+ * Some older themes rely on this behavior, but many themes nowadays use rounded
+ * corners on their widgets. While most GTK apps are blissfully unaware of this
+ * problem due to their use of the default window background, we render widgets on
+ * many kinds of backgrounds on the web.
+ * If the theme is able to cope with transparency, then we can skip pre-filling
+ * and notify the theme it will paint directly on the canvas. */
+ if (theme_honors_transparency) {
+ g_object_set_data(G_OBJECT(widget), "transparent-bg-hint", TRUE);
+ } else {
+ gdk_draw_rectangle(drawable, style->base_gc[bg_state], TRUE,
+ cliprect->x, cliprect->y, cliprect->width, cliprect->height);
+ g_object_set_data(G_OBJECT(widget), "transparent-bg-hint", FALSE);
+ }
- gtk_widget_style_get(widget,
- "interior-focus", &interior_focus,
- "focus-line-width", &focus_width,
- NULL);
+ /* Get the position of the inner window, see _gtk_entry_get_borders */
+ x = XTHICKNESS(style);
+ y = YTHICKNESS(style);
- /*
- * Now paint the shadow and focus border.
- *
- * gtk+ is able to draw over top of the entry when it gains focus,
- * so the non-focused text border is implicitly already drawn when
- * the entry is drawn in a focused state.
- *
- * Gecko doesn't quite work this way, so always draw the non-focused
- * shadow, then draw the shadow again, inset, if we're focused.
- */
+ if (!interior_focus) {
+ x += focus_width;
+ y += focus_width;
+ }
+
+ /* Simulate an expose of the inner window */
+ gtk_paint_flat_box(style, drawable, bg_state, GTK_SHADOW_NONE,
+ cliprect, widget, "entry_bg", rect->x + x,
+ rect->y + y, rect->width - 2*x, rect->height - 2*y);
+ /* Now paint the shadow and focus border.
+ * We do like in gtk_entry_draw_frame, we first draw the shadow, a tad
+ * smaller when focused if the focus is not interior, then the focus. */
x = rect->x;
y = rect->y;
if (state->focused && !state->disabled) {
- /* This will get us the lit borders that focused textboxes enjoy on some themes. */
+ /* This will get us the lit borders that focused textboxes enjoy on
+ * some themes. */
GTK_WIDGET_SET_FLAGS(widget, GTK_HAS_FOCUS);
if (!interior_focus) {
@@ -1225,19 +1578,18 @@ moz_gtk_entry_paint(GdkDrawable* drawable, GdkRectangle* rect,
}
}
- TSOffsetStyleGCs(style, x, y);
gtk_paint_shadow(style, drawable, GTK_STATE_NORMAL, GTK_SHADOW_IN,
cliprect, widget, "entry", x, y, width, height);
if (state->focused && !state->disabled) {
if (!interior_focus) {
- TSOffsetStyleGCs(style, rect->x, rect->y);
gtk_paint_focus(style, drawable, GTK_STATE_NORMAL, cliprect,
widget, "entry",
rect->x, rect->y, rect->width, rect->height);
}
- /* Now unset the focus flag. We don't want other entries to look like they're focused too! */
+ /* Now unset the focus flag. We don't want other entries to look
+ * like they're focused too! */
GTK_WIDGET_UNSET_FLAGS(widget, GTK_HAS_FOCUS);
}
@@ -1255,7 +1607,10 @@ moz_gtk_treeview_paint(GdkDrawable* drawable, GdkRectangle* rect,
GtkStateType state_type;
ensure_tree_view_widget();
+ ensure_scrolled_window_widget();
+
gtk_widget_set_direction(gTreeViewWidget, direction);
+ gtk_widget_set_direction(gScrolledWindowWidget, direction);
/* only handle disabled and normal states, otherwise the whole background
* area will be painted differently with other states */
@@ -1267,20 +1622,21 @@ moz_gtk_treeview_paint(GdkDrawable* drawable, GdkRectangle* rect,
gtk_widget_modify_bg(gTreeViewWidget, state_type,
&gTreeViewWidget->style->base[state_type]);
- style = gTreeViewWidget->style;
+ style = gScrolledWindowWidget->style;
xthickness = XTHICKNESS(style);
ythickness = YTHICKNESS(style);
+ TSOffsetStyleGCs(gTreeViewWidget->style, rect->x, rect->y);
TSOffsetStyleGCs(style, rect->x, rect->y);
- gtk_paint_flat_box(style, drawable, state_type, GTK_SHADOW_NONE,
- cliprect, gTreeViewWidget, "treeview",
+ gtk_paint_flat_box(gTreeViewWidget->style, drawable, state_type,
+ GTK_SHADOW_NONE, cliprect, gTreeViewWidget, "treeview",
rect->x + xthickness, rect->y + ythickness,
rect->width - 2 * xthickness,
rect->height - 2 * ythickness);
gtk_paint_shadow(style, drawable, GTK_STATE_NORMAL, GTK_SHADOW_IN,
- cliprect, gTreeViewWidget, "scrolled_window",
+ cliprect, gScrolledWindowWidget, "scrolled_window",
rect->x, rect->y, rect->width, rect->height);
return MOZ_GTK_SUCCESS;
@@ -1289,8 +1645,11 @@ moz_gtk_treeview_paint(GdkDrawable* drawable, GdkRectangle* rect,
static gint
moz_gtk_tree_header_cell_paint(GdkDrawable* drawable, GdkRectangle* rect,
GdkRectangle* cliprect, GtkWidgetState* state,
- GtkTextDirection direction)
+ gboolean isSorted, GtkTextDirection direction)
{
+ gtk_tree_view_column_set_sort_indicator(GTK_TREE_VIEW_COLUMN(gMiddleTreeViewColumn),
+ isSorted);
+
moz_gtk_button_paint(drawable, rect, cliprect, state, GTK_RELIEF_NORMAL,
gTreeHeaderCellWidget, direction);
return MOZ_GTK_SUCCESS;
@@ -1375,73 +1734,84 @@ moz_gtk_expander_paint(GdkDrawable* drawable, GdkRectangle* rect,
}
static gint
-moz_gtk_option_menu_paint(GdkDrawable* drawable, GdkRectangle* rect,
- GdkRectangle* cliprect, GtkWidgetState* state,
- GtkTextDirection direction)
+moz_gtk_combo_box_paint(GdkDrawable* drawable, GdkRectangle* rect,
+ GdkRectangle* cliprect, GtkWidgetState* state,
+ gboolean ishtml, GtkTextDirection direction)
{
- GtkStyle* style;
+ GdkRectangle arrow_rect, real_arrow_rect;
+ gint arrow_size, separator_width = 0;
+ gboolean wide_separators = FALSE;
GtkStateType state_type = ConvertGtkState(state);
- gint x = rect->x, y=rect->y, width=rect->width, height=rect->height;
- gint tab_x, tab_y;
- gboolean interior_focus;
- GtkRequisition indicator_size;
- GtkBorder indicator_spacing;
- gint focus_width;
- gint focus_pad;
+ GtkShadowType shadow_type = state->active ? GTK_SHADOW_IN : GTK_SHADOW_OUT;
+ GtkStyle* style;
+ GtkRequisition arrow_req;
- ensure_option_menu_widget();
- gtk_widget_set_direction(gOptionMenuWidget, direction);
- moz_gtk_option_menu_get_metrics(&interior_focus, &indicator_size,
- &indicator_spacing, &focus_width,
- &focus_pad);
+ ensure_combo_box_widgets();
- style = gOptionMenuWidget->style;
+ /* Also sets the direction on gComboBoxButtonWidget, which is then
+ * inherited by the separator and arrow */
+ moz_gtk_button_paint(drawable, rect, cliprect, state, GTK_RELIEF_NORMAL,
+ gComboBoxButtonWidget, direction);
- if (!interior_focus && state->focused) {
- x += focus_width + focus_pad;
- y += focus_width + focus_pad;
- width -= 2 * (focus_width + focus_pad);
- height -= 2 * (focus_width + focus_pad);
- }
+ calculate_button_inner_rect(gComboBoxButtonWidget,
+ rect, &arrow_rect, direction, ishtml);
+ /* Now arrow_rect contains the inner rect ; we want to correct the width
+ * to what the arrow needs (see gtk_combo_box_size_allocate) */
+ gtk_widget_size_request(gComboBoxArrowWidget, &arrow_req);
+ if (direction == GTK_TEXT_DIR_LTR)
+ arrow_rect.x += arrow_rect.width - arrow_req.width;
+ arrow_rect.width = arrow_req.width;
- TSOffsetStyleGCs(style, x, y);
- gtk_paint_box(style, drawable, state_type, GTK_SHADOW_OUT,
- cliprect, gOptionMenuWidget, "optionmenu",
- x, y, width, height);
-
- if (direction == GTK_TEXT_DIR_RTL) {
- tab_x = x + indicator_spacing.right + XTHICKNESS(style);
+ calculate_arrow_rect(gComboBoxArrowWidget,
+ &arrow_rect, &real_arrow_rect, direction);
+
+ style = gComboBoxArrowWidget->style;
+ TSOffsetStyleGCs(style, rect->x, rect->y);
+
+ gtk_widget_size_allocate(gComboBoxWidget, rect);
+
+ gtk_paint_arrow(style, drawable, state_type, shadow_type, cliprect,
+ gComboBoxArrowWidget, "arrow", GTK_ARROW_DOWN, TRUE,
+ real_arrow_rect.x, real_arrow_rect.y,
+ real_arrow_rect.width, real_arrow_rect.height);
+
+
+ /* If there is no separator in the theme, there's nothing left to do. */
+ if (!gComboBoxSeparatorWidget)
+ return MOZ_GTK_SUCCESS;
+
+ style = gComboBoxSeparatorWidget->style;
+ TSOffsetStyleGCs(style, rect->x, rect->y);
+
+ if (have_2_10)
+ gtk_widget_style_get(gComboBoxSeparatorWidget,
+ "wide-separators", &wide_separators,
+ "separator-width", &separator_width,
+ NULL);
+
+ if (wide_separators) {
+ if (direction == GTK_TEXT_DIR_LTR)
+ arrow_rect.x -= separator_width;
+ else
+ arrow_rect.x += arrow_rect.width;
+
+ gtk_paint_box(style, drawable,
+ GTK_STATE_NORMAL, GTK_SHADOW_ETCHED_OUT,
+ cliprect, gComboBoxSeparatorWidget, "vseparator",
+ arrow_rect.x, arrow_rect.y,
+ separator_width, arrow_rect.height);
} else {
- tab_x = x + width - indicator_size.width - indicator_spacing.right -
- XTHICKNESS(style);
+ if (direction == GTK_TEXT_DIR_LTR)
+ arrow_rect.x -= XTHICKNESS(style);
+ else
+ arrow_rect.x += arrow_rect.width;
+
+ gtk_paint_vline(style, drawable, GTK_STATE_NORMAL, cliprect,
+ gComboBoxSeparatorWidget, "vseparator",
+ arrow_rect.y, arrow_rect.y + arrow_rect.height,
+ arrow_rect.x);
}
- tab_y = y + (height - indicator_size.height) / 2;
- TSOffsetStyleGCs(style, tab_x, tab_y);
- gtk_paint_tab(style, drawable, state_type, GTK_SHADOW_OUT, cliprect,
- gOptionMenuWidget, "optionmenutab", tab_x, tab_y,
- indicator_size.width, indicator_size.height);
-
- if (state->focused) {
- if (interior_focus) {
- x += XTHICKNESS(style) + focus_pad;
- y += YTHICKNESS(style) + focus_pad;
- /* Standard GTK combos have their focus ring around the entire
- control, not just the text bit */
- width -= 2 * (XTHICKNESS(style) + focus_pad);
- height -= 2 * (YTHICKNESS(style) + focus_pad);
- } else {
- x -= focus_width + focus_pad;
- y -= focus_width + focus_pad;
- width += 2 * (focus_width + focus_pad);
- height += 2 * (focus_width + focus_pad);
- }
-
- TSOffsetStyleGCs(style, x, y);
- gtk_paint_focus (style, drawable, state_type, cliprect, gOptionMenuWidget,
- "button", x, y, width, height);
- }
-
return MOZ_GTK_SUCCESS;
}
@@ -1454,63 +1824,66 @@ moz_gtk_downarrow_paint(GdkDrawable* drawable, GdkRectangle* rect,
GtkShadowType shadow_type = state->active ? GTK_SHADOW_IN : GTK_SHADOW_OUT;
GdkRectangle arrow_rect;
- ensure_arrow_widget();
- style = gArrowWidget->style;
+ ensure_button_arrow_widget();
+ style = gButtonArrowWidget->style;
- arrow_rect.x = rect->x + 1 + XTHICKNESS(style);
- arrow_rect.y = rect->y + 1 + YTHICKNESS(style);
- arrow_rect.width = MAX(1, rect->width - (arrow_rect.x - rect->x) * 2);
- arrow_rect.height = MAX(1, rect->height - (arrow_rect.y - rect->y) * 2);
+ calculate_arrow_rect(gButtonArrowWidget, rect, &arrow_rect,
+ GTK_TEXT_DIR_LTR);
TSOffsetStyleGCs(style, arrow_rect.x, arrow_rect.y);
gtk_paint_arrow(style, drawable, state_type, shadow_type, cliprect,
- gArrowWidget, "arrow", GTK_ARROW_DOWN, TRUE,
+ gButtonArrowWidget, "arrow", GTK_ARROW_DOWN, TRUE,
arrow_rect.x, arrow_rect.y, arrow_rect.width, arrow_rect.height);
return MOZ_GTK_SUCCESS;
}
static gint
-moz_gtk_dropdown_arrow_paint(GdkDrawable* drawable, GdkRectangle* rect,
- GdkRectangle* cliprect, GtkWidgetState* state,
- GtkTextDirection direction)
+moz_gtk_combo_box_entry_button_paint(GdkDrawable* drawable, GdkRectangle* rect,
+ GdkRectangle* cliprect,
+ GtkWidgetState* state,
+ gboolean input_focus,
+ GtkTextDirection direction)
{
- static gfloat arrow_scaling = 0.7;
- gint real_arrow_padding;
+ gint x_displacement, y_displacement;
GdkRectangle arrow_rect, real_arrow_rect;
GtkStateType state_type = ConvertGtkState(state);
GtkShadowType shadow_type = state->active ? GTK_SHADOW_IN : GTK_SHADOW_OUT;
GtkStyle* style;
- ensure_arrow_widget();
- gtk_widget_set_direction(gDropdownButtonWidget, direction);
+ ensure_combo_box_entry_widgets();
+
+ if (input_focus) {
+ /* Some themes draw a complementary focus ring for the dropdown button
+ * when the dropdown entry has focus */
+ GTK_WIDGET_SET_FLAGS(gComboBoxEntryTextareaWidget, GTK_HAS_FOCUS);
+ }
moz_gtk_button_paint(drawable, rect, cliprect, state, GTK_RELIEF_NORMAL,
- gDropdownButtonWidget, direction);
+ gComboBoxEntryButtonWidget, direction);
- /* This mirrors gtkbutton's child positioning */
- style = gDropdownButtonWidget->style;
- arrow_rect.x = rect->x + 1 + XTHICKNESS(style);
- arrow_rect.y = rect->y + 1 + YTHICKNESS(style);
- arrow_rect.width = MAX(1, rect->width - (arrow_rect.x - rect->x) * 2);
- arrow_rect.height = MAX(1, rect->height - (arrow_rect.y - rect->y) * 2);
-
- calculate_arrow_dimensions(&arrow_rect, &real_arrow_rect);
- style = gArrowWidget->style;
- TSOffsetStyleGCs(style, real_arrow_rect.x, real_arrow_rect.y);
+ if (input_focus)
+ GTK_WIDGET_UNSET_FLAGS(gComboBoxEntryTextareaWidget, GTK_HAS_FOCUS);
+
+ calculate_button_inner_rect(gComboBoxEntryButtonWidget,
+ rect, &arrow_rect, direction, FALSE);
+ if (state_type == GTK_STATE_ACTIVE) {
+ gtk_widget_style_get(gComboBoxEntryButtonWidget,
+ "child-displacement-x", &x_displacement,
+ "child-displacement-y", &y_displacement,
+ NULL);
+ arrow_rect.x += x_displacement;
+ arrow_rect.y += y_displacement;
+ }
- real_arrow_rect.width = real_arrow_rect.height =
- MIN (real_arrow_rect.width, real_arrow_rect.height) * arrow_scaling;
+ calculate_arrow_rect(gComboBoxEntryArrowWidget,
+ &arrow_rect, &real_arrow_rect, direction);
- real_arrow_padding = floor((arrow_rect.width - real_arrow_rect.width) / 2 + 0.5);
- real_arrow_rect.x = arrow_rect.x + real_arrow_padding;
- if (direction == GTK_TEXT_DIR_RTL)
- real_arrow_rect.x = arrow_rect.x + arrow_rect.width -
- real_arrow_rect.width - real_arrow_padding;
- real_arrow_rect.y = floor (arrow_rect.y + ((arrow_rect.height - real_arrow_rect.height) / 2) + 0.5);
+ style = gComboBoxEntryArrowWidget->style;
+ TSOffsetStyleGCs(style, real_arrow_rect.x, real_arrow_rect.y);
gtk_paint_arrow(style, drawable, state_type, shadow_type, cliprect,
- gDropdownButtonWidget, "arrow", GTK_ARROW_DOWN, TRUE,
+ gComboBoxEntryArrowWidget, "arrow", GTK_ARROW_DOWN, TRUE,
real_arrow_rect.x, real_arrow_rect.y,
real_arrow_rect.width, real_arrow_rect.height);
@@ -1624,7 +1997,9 @@ moz_gtk_toolbar_paint(GdkDrawable* drawable, GdkRectangle* rect,
cliprect, rect->x, rect->y,
rect->width, rect->height);
- gtk_paint_box (style, drawable, GTK_STATE_NORMAL, gToolbarShadowType,
+ gtk_widget_style_get(gToolbarWidget, "shadow-type", &shadow_type, NULL);
+
+ gtk_paint_box (style, drawable, GTK_STATE_NORMAL, shadow_type,
cliprect, gToolbarWidget, "toolbar",
rect->x, rect->y, rect->width, rect->height);
@@ -1637,9 +2012,9 @@ moz_gtk_toolbar_separator_paint(GdkDrawable* drawable, GdkRectangle* rect,
GtkTextDirection direction)
{
GtkStyle* style;
- gint separator_width;
+ gint separator_width = 0;
gint paint_width;
- gboolean wide_separators;
+ gboolean wide_separators = FALSE;
/* Defined as constants in GTK+ 2.10.14 */
const double start_fraction = 0.2;
@@ -1650,10 +2025,11 @@ moz_gtk_toolbar_separator_paint(GdkDrawable* drawable, GdkRectangle* rect,
style = gToolbarSeparatorWidget->style;
- gtk_widget_style_get(gToolbarWidget,
- "wide-separators", &wide_separators,
- "separator-width", &separator_width,
- NULL);
+ if (have_2_10)
+ gtk_widget_style_get(gToolbarWidget,
+ "wide-separators", &wide_separators,
+ "separator-width", &separator_width,
+ NULL);
TSOffsetStyleGCs(style, rect->x, rect->y);
@@ -1965,6 +2341,36 @@ moz_gtk_tabpanels_paint(GdkDrawable* drawable, GdkRectangle* rect,
}
static gint
+moz_gtk_tab_scroll_arrow_paint(GdkDrawable* drawable, GdkRectangle* rect,
+ GdkRectangle* cliprect, GtkWidgetState* state,
+ GtkArrowType arrow_type,
+ GtkTextDirection direction)
+{
+ GtkStateType state_type = ConvertGtkState(state);
+ GtkShadowType shadow_type = state->active ? GTK_SHADOW_IN : GTK_SHADOW_OUT;
+ GtkStyle* style;
+ gint arrow_size = MIN(rect->width, rect->height);
+ gint x = rect->x + (rect->width - arrow_size) / 2;
+ gint y = rect->y + (rect->height - arrow_size) / 2;
+
+ ensure_tab_widget();
+
+ style = gTabWidget->style;
+ TSOffsetStyleGCs(style, rect->x, rect->y);
+
+ if (direction == GTK_TEXT_DIR_RTL) {
+ arrow_type = (arrow_type == GTK_ARROW_LEFT) ?
+ GTK_ARROW_RIGHT : GTK_ARROW_LEFT;
+ }
+
+ gtk_paint_arrow(style, drawable, state_type, shadow_type, NULL,
+ gTabWidget, "notebook", arrow_type, TRUE,
+ x, y, arrow_size, arrow_size);
+
+ return MOZ_GTK_SUCCESS;
+}
+
+static gint
moz_gtk_menu_bar_paint(GdkDrawable* drawable, GdkRectangle* rect,
GdkRectangle* cliprect, GtkTextDirection direction)
{
@@ -1973,13 +2379,16 @@ moz_gtk_menu_bar_paint(GdkDrawable* drawable, GdkRectangle* rect,
ensure_menu_bar_widget();
gtk_widget_set_direction(gMenuBarWidget, direction);
+ gtk_widget_style_get(gMenuBarWidget, "shadow-type", &shadow_type, NULL);
+
style = gMenuBarWidget->style;
TSOffsetStyleGCs(style, rect->x, rect->y);
gtk_style_apply_default_background(style, drawable, TRUE, GTK_STATE_NORMAL,
cliprect, rect->x, rect->y,
rect->width, rect->height);
- gtk_paint_box(style, drawable, GTK_STATE_NORMAL, gMenuBarShadowType,
+
+ gtk_paint_box(style, drawable, GTK_STATE_NORMAL, shadow_type,
cliprect, gMenuBarWidget, "menubar", rect->x, rect->y,
rect->width, rect->height);
return MOZ_GTK_SUCCESS;
@@ -2011,9 +2420,9 @@ moz_gtk_menu_separator_paint(GdkDrawable* drawable, GdkRectangle* rect,
GdkRectangle* cliprect, GtkTextDirection direction)
{
GtkStyle* style;
- gboolean wide_separators;
- gint separator_height;
- guint horizontal_padding;
+ gboolean wide_separators = FALSE;
+ gint separator_height = 0;
+ guint horizontal_padding = 0;
gint paint_height;
ensure_menu_separator_widget();
@@ -2021,9 +2430,13 @@ moz_gtk_menu_separator_paint(GdkDrawable* drawable, GdkRectangle* rect,
style = gMenuSeparatorWidget->style;
+ if (have_2_10)
+ gtk_widget_style_get(gMenuSeparatorWidget,
+ "wide-separators", &wide_separators,
+ "separator-height", &separator_height,
+ NULL);
+
gtk_widget_style_get(gMenuSeparatorWidget,
- "wide-separators", &wide_separators,
- "separator-height", &separator_height,
"horizontal-padding", &horizontal_padding,
NULL);
@@ -2077,12 +2490,9 @@ moz_gtk_menu_item_paint(GdkDrawable* drawable, GdkRectangle* rect,
style = item_widget->style;
TSOffsetStyleGCs(style, rect->x, rect->y);
- if (have_menu_shadow_type) {
- gtk_widget_style_get(item_widget, "selected_shadow_type",
- &shadow_type, NULL);
- } else {
- shadow_type = GTK_SHADOW_OUT;
- }
+
+ gtk_widget_style_get(item_widget, "selected-shadow-type",
+ &shadow_type, NULL);
gtk_paint_box(style, drawable, GTK_STATE_PRELIGHT, shadow_type,
cliprect, item_widget, "menuitem", rect->x, rect->y,
@@ -2197,8 +2607,7 @@ moz_gtk_get_widget_border(GtkThemeWidgetType widget, gint* left, gint* top,
switch (widget) {
case MOZ_GTK_BUTTON:
{
- /* Constant in gtkbutton.c */
- static const gint child_spacing = 1;
+ GtkBorder inner_border;
gboolean interior_focus;
gint focus_width, focus_pad;
@@ -2209,10 +2618,11 @@ moz_gtk_get_widget_border(GtkThemeWidgetType widget, gint* left, gint* top,
become too big and stuff the layout. */
if (!inhtml) {
moz_gtk_widget_get_focus(gButtonWidget, &interior_focus, &focus_width, &focus_pad);
- *left += focus_width + focus_pad + child_spacing;
- *right += focus_width + focus_pad + child_spacing;
- *top += focus_width + focus_pad + child_spacing;
- *bottom += focus_width + focus_pad + child_spacing;
+ moz_gtk_button_get_inner_border(gButtonWidget, &inner_border);
+ *left += focus_width + focus_pad + inner_border.left;
+ *right += focus_width + focus_pad + inner_border.right;
+ *top += focus_width + focus_pad + inner_border.top;
+ *bottom += focus_width + focus_pad + inner_border.bottom;
}
*left += gButtonWidget->style->xthickness;
@@ -2221,11 +2631,6 @@ moz_gtk_get_widget_border(GtkThemeWidgetType widget, gint* left, gint* top,
*bottom += gButtonWidget->style->ythickness;
return MOZ_GTK_SUCCESS;
}
-
- case MOZ_GTK_TOOLBAR:
- ensure_toolbar_widget();
- w = gToolbarWidget;
- break;
case MOZ_GTK_ENTRY:
ensure_entry_widget();
w = gEntryWidget;
@@ -2242,19 +2647,19 @@ moz_gtk_get_widget_border(GtkThemeWidgetType widget, gint* left, gint* top,
* That is why the following code is the same as for MOZ_GTK_BUTTON.
* */
- /* Constant in gtkbutton.c */
- static const gint child_spacing = 1;
+ GtkBorder inner_border;
gboolean interior_focus;
gint focus_width, focus_pad;
ensure_tree_header_cell_widget();
*left = *top = *right = *bottom = GTK_CONTAINER(gTreeHeaderCellWidget)->border_width;
- moz_gtk_widget_get_focus(gTreeHeaderCellWidget, &interior_focus, &focus_width, &focus_pad);
- *left += focus_width + focus_pad;
- *right += focus_width + focus_pad;
- *top += focus_width + focus_pad + child_spacing;
- *bottom += focus_width + focus_pad + child_spacing;
+ moz_gtk_widget_get_focus(gTreeHeaderCellWidget, &interior_focus, &focus_width, &focus_pad);
+ moz_gtk_button_get_inner_border(gTreeHeaderCellWidget, &inner_border);
+ *left += focus_width + focus_pad + inner_border.left;
+ *right += focus_width + focus_pad + inner_border.right;
+ *top += focus_width + focus_pad + inner_border.top;
+ *bottom += focus_width + focus_pad + inner_border.bottom;
*left += gTreeHeaderCellWidget->style->xthickness;
*right += gTreeHeaderCellWidget->style->xthickness;
@@ -2267,32 +2672,59 @@ moz_gtk_get_widget_border(GtkThemeWidgetType widget, gint* left, gint* top,
w = gTreeHeaderSortArrowWidget;
break;
case MOZ_GTK_DROPDOWN_ENTRY:
- ensure_dropdown_entry_widget();
- w = gDropdownEntryWidget;
+ ensure_combo_box_entry_widgets();
+ w = gComboBoxEntryTextareaWidget;
break;
case MOZ_GTK_DROPDOWN_ARROW:
- ensure_arrow_widget();
- w = gDropdownButtonWidget;
+ ensure_combo_box_entry_widgets();
+ w = gComboBoxEntryButtonWidget;
break;
case MOZ_GTK_DROPDOWN:
{
- /* We need to account for the arrow on the dropdown, so text doesn't
- come too close to the arrow, or in some cases spill into the arrow. */
- gboolean interior_focus;
- GtkRequisition indicator_size;
- GtkBorder indicator_spacing;
- gint focus_width, focus_pad;
+ /* We need to account for the arrow on the dropdown, so text
+ * doesn't come too close to the arrow, or in some cases spill
+ * into the arrow. */
+ gboolean ignored_interior_focus, wide_separators = FALSE;
+ gint focus_width, focus_pad, separator_width;
+ GtkRequisition arrow_req;
+
+ ensure_combo_box_widgets();
+
+ *left = GTK_CONTAINER(gComboBoxButtonWidget)->border_width;
+
+ if (!inhtml) {
+ moz_gtk_widget_get_focus(gComboBoxButtonWidget,
+ &ignored_interior_focus,
+ &focus_width, &focus_pad);
+ *left += focus_width + focus_pad;
+ }
+
+ *top = *left + gComboBoxButtonWidget->style->ythickness;
+ *left += gComboBoxButtonWidget->style->xthickness;
+
+ *right = *left; *bottom = *top;
+
+ /* If there is no separator, don't try to count its width. */
+ separator_width = 0;
+ if (gComboBoxSeparatorWidget) {
+ if (have_2_10)
+ gtk_widget_style_get(gComboBoxSeparatorWidget,
+ "wide-separators", &wide_separators,
+ "separator-width", &separator_width,
+ NULL);
+
+ if (!wide_separators)
+ separator_width =
+ XTHICKNESS(gComboBoxSeparatorWidget->style);
+ }
- ensure_option_menu_widget();
- *right = *left = gOptionMenuWidget->style->xthickness;
- *bottom = *top = gOptionMenuWidget->style->ythickness;
- moz_gtk_option_menu_get_metrics(&interior_focus, &indicator_size,
- &indicator_spacing, &focus_width, &focus_pad);
+ gtk_widget_size_request(gComboBoxArrowWidget, &arrow_req);
if (direction == GTK_TEXT_DIR_RTL)
- *left += indicator_spacing.left + indicator_size.width + indicator_spacing.right;
+ *left += separator_width + arrow_req.width;
else
- *right += indicator_spacing.left + indicator_size.width + indicator_spacing.right;
+ *right += separator_width + arrow_req.width;
+
return MOZ_GTK_SUCCESS;
}
case MOZ_GTK_TABPANELS:
@@ -2379,10 +2811,6 @@ moz_gtk_get_widget_border(GtkThemeWidgetType widget, gint* left, gint* top,
return MOZ_GTK_SUCCESS;
}
- case MOZ_GTK_MENUBAR:
- ensure_menu_bar_widget();
- w = gMenuBarWidget;
- break;
case MOZ_GTK_MENUPOPUP:
ensure_menu_popup_widget();
w = gMenuPopupWidget;
@@ -2416,6 +2844,7 @@ moz_gtk_get_widget_border(GtkThemeWidgetType widget, gint* left, gint* top,
case MOZ_GTK_GRIPPER:
case MOZ_GTK_PROGRESS_CHUNK:
case MOZ_GTK_EXPANDER:
+ case MOZ_GTK_TREEVIEW_EXPANDER:
case MOZ_GTK_TOOLBAR_SEPARATOR:
case MOZ_GTK_MENUSEPARATOR:
/* These widgets have no borders.*/
@@ -2425,6 +2854,10 @@ moz_gtk_get_widget_border(GtkThemeWidgetType widget, gint* left, gint* top,
case MOZ_GTK_RESIZER:
case MOZ_GTK_MENUARROW:
case MOZ_GTK_TOOLBARBUTTON_ARROW:
+ case MOZ_GTK_TOOLBAR:
+ case MOZ_GTK_MENUBAR:
+ case MOZ_GTK_TAB_SCROLLARROW:
+ case MOZ_GTK_ENTRY_CARET:
*left = *top = *right = *bottom = 0;
return MOZ_GTK_SUCCESS;
default:
@@ -2439,22 +2872,48 @@ moz_gtk_get_widget_border(GtkThemeWidgetType widget, gint* left, gint* top,
}
gint
-moz_gtk_get_dropdown_arrow_size(gint* width, gint* height)
+moz_gtk_get_combo_box_entry_button_size(gint* width, gint* height)
{
- const gint min_arrow_size = 15;
- ensure_arrow_widget();
-
/*
- * First get the border of the dropdown arrow, then add in the requested
- * size of the arrow. Note that the minimum arrow size is fixed at
- * 15 pixels.
- */
+ * We get the requisition of the drop down button, which includes
+ * all padding, border and focus line widths the button uses,
+ * as well as the minimum arrow size and its padding
+ * */
+ GtkRequisition requisition;
+ ensure_combo_box_entry_widgets();
+
+ gtk_widget_size_request(gComboBoxEntryButtonWidget, &requisition);
+ *width = requisition.width;
+ *height = requisition.height;
+
+ return MOZ_GTK_SUCCESS;
+}
+
+gint
+moz_gtk_get_tab_scroll_arrow_size(gint* width, gint* height)
+{
+ gint arrow_size = 16;
+
+ ensure_tab_widget();
+ if (have_2_10)
+ gtk_widget_style_get(gTabWidget,
+ "scroll-arrow-hlength", &arrow_size,
+ NULL);
+
+ *height = *width = arrow_size;
- *width = 2 * (1 + XTHICKNESS(gDropdownButtonWidget->style));
- *width += min_arrow_size + GTK_MISC(gArrowWidget)->xpad * 2;
+ return MOZ_GTK_SUCCESS;
+}
+
+gint
+moz_gtk_get_downarrow_size(gint* width, gint* height)
+{
+ GtkRequisition requisition;
+ ensure_button_arrow_widget();
- *height = 2 * (1 + YTHICKNESS(gDropdownButtonWidget->style));
- *height += min_arrow_size + GTK_MISC(gArrowWidget)->ypad * 2;
+ gtk_widget_size_request(gButtonArrowWidget, &requisition);
+ *width = requisition.width;
+ *height = requisition.height;
return MOZ_GTK_SUCCESS;
}
@@ -2462,18 +2921,22 @@ moz_gtk_get_dropdown_arrow_size(gint* width, gint* height)
gint
moz_gtk_get_toolbar_separator_width(gint* size)
{
- gboolean wide_separators;
- gint separator_width;
+ gboolean wide_separators = FALSE;
+ gint separator_width = 0;
GtkStyle* style;
ensure_toolbar_widget();
style = gToolbarWidget->style;
+ if (have_2_10)
+ gtk_widget_style_get(gToolbarWidget,
+ "wide-separators", &wide_separators,
+ "separator-width", &separator_width,
+ NULL);
+
gtk_widget_style_get(gToolbarWidget,
"space-size", size,
- "wide-separators", &wide_separators,
- "separator-width", &separator_width,
NULL);
/* Just in case... */
@@ -2507,15 +2970,16 @@ moz_gtk_get_treeview_expander_size(gint* size)
gint
moz_gtk_get_menu_separator_height(gint *size)
{
- gboolean wide_separators;
- gint separator_height;
+ gboolean wide_separators = FALSE;
+ gint separator_height = 0;
ensure_menu_separator_widget();
- gtk_widget_style_get(gMenuSeparatorWidget,
- "wide-separators", &wide_separators,
- "separator-height", &separator_height,
- NULL);
+ if (have_2_10)
+ gtk_widget_style_get(gMenuSeparatorWidget,
+ "wide-separators", &wide_separators,
+ "separator-height", &separator_height,
+ NULL);
if (wide_separators)
*size = separator_height + gMenuSeparatorWidget->style->ythickness;
@@ -2559,6 +3023,19 @@ moz_gtk_get_scrollbar_metrics(MozGtkScrollbarMetrics *metrics)
return MOZ_GTK_SUCCESS;
}
+gboolean
+moz_gtk_images_in_menus()
+{
+ gboolean result;
+ GtkSettings* settings;
+
+ ensure_image_menu_item_widget();
+ settings = gtk_widget_get_settings(gImageMenuItemWidget);
+
+ g_object_get(settings, "gtk-menu-images", &result, NULL);
+ return result;
+}
+
gint
moz_gtk_widget_paint(GtkThemeWidgetType widget, GdkDrawable* drawable,
GdkRectangle* rect, GdkRectangle* cliprect,
@@ -2634,7 +3111,7 @@ moz_gtk_widget_paint(GtkThemeWidgetType widget, GdkDrawable* drawable,
break;
case MOZ_GTK_TREE_HEADER_CELL:
return moz_gtk_tree_header_cell_paint(drawable, rect, cliprect, state,
- direction);
+ flags, direction);
break;
case MOZ_GTK_TREE_HEADER_SORTARROW:
return moz_gtk_tree_header_sort_arrow_paint(drawable, rect, cliprect,
@@ -2655,18 +3132,21 @@ moz_gtk_widget_paint(GtkThemeWidgetType widget, GdkDrawable* drawable,
return moz_gtk_entry_paint(drawable, rect, cliprect, state,
gEntryWidget, direction);
break;
+ case MOZ_GTK_ENTRY_CARET:
+ return moz_gtk_caret_paint(drawable, rect, cliprect, direction);
+ break;
case MOZ_GTK_DROPDOWN:
- return moz_gtk_option_menu_paint(drawable, rect, cliprect, state,
- direction);
+ return moz_gtk_combo_box_paint(drawable, rect, cliprect, state,
+ (gboolean) flags, direction);
break;
case MOZ_GTK_DROPDOWN_ARROW:
- return moz_gtk_dropdown_arrow_paint(drawable, rect, cliprect, state,
- direction);
+ return moz_gtk_combo_box_entry_button_paint(drawable, rect, cliprect,
+ state, flags, direction);
break;
case MOZ_GTK_DROPDOWN_ENTRY:
- ensure_dropdown_entry_widget();
+ ensure_combo_box_entry_widgets();
return moz_gtk_entry_paint(drawable, rect, cliprect, state,
- gDropdownEntryWidget, direction);
+ gComboBoxEntryTextareaWidget, direction);
break;
case MOZ_GTK_CHECKBUTTON_CONTAINER:
case MOZ_GTK_RADIOBUTTON_CONTAINER:
@@ -2711,6 +3191,10 @@ moz_gtk_widget_paint(GtkThemeWidgetType widget, GdkDrawable* drawable,
case MOZ_GTK_TABPANELS:
return moz_gtk_tabpanels_paint(drawable, rect, cliprect, direction);
break;
+ case MOZ_GTK_TAB_SCROLLARROW:
+ return moz_gtk_tab_scroll_arrow_paint(drawable, rect, cliprect, state,
+ (GtkArrowType) flags, direction);
+ break;
case MOZ_GTK_MENUBAR:
return moz_gtk_menu_bar_paint(drawable, rect, cliprect, direction);
break;
@@ -2766,6 +3250,8 @@ GtkWidget* moz_gtk_get_scrollbar_widget(void)
gint
moz_gtk_shutdown()
{
+ GtkWidgetClass *entry_class;
+
if (gTooltipWidget)
gtk_widget_destroy(gTooltipWidget);
/* This will destroy all of our widgets */
@@ -2775,6 +3261,7 @@ moz_gtk_shutdown()
gProtoWindow = NULL;
gButtonWidget = NULL;
gToggleButtonWidget = NULL;
+ gButtonArrowWidget = NULL;
gCheckboxWidget = NULL;
gRadiobuttonWidget = NULL;
gHorizScrollbarWidget = NULL;
@@ -2783,11 +3270,14 @@ moz_gtk_shutdown()
gHScaleWidget = NULL;
gVScaleWidget = NULL;
gEntryWidget = NULL;
- gArrowWidget = NULL;
- gOptionMenuWidget = NULL;
- gDropdownButtonWidget = NULL;
- gDropdownEntryWidget = NULL;
+ gComboBoxWidget = NULL;
+ gComboBoxButtonWidget = NULL;
+ gComboBoxSeparatorWidget = NULL;
+ gComboBoxArrowWidget = NULL;
gComboBoxEntryWidget = NULL;
+ gComboBoxEntryButtonWidget = NULL;
+ gComboBoxEntryArrowWidget = NULL;
+ gComboBoxEntryTextareaWidget = NULL;
gHandleBoxWidget = NULL;
gToolbarWidget = NULL;
gStatusbarWidget = NULL;
@@ -2799,8 +3289,10 @@ moz_gtk_shutdown()
gMenuBarItemWidget = NULL;
gMenuPopupWidget = NULL;
gMenuItemWidget = NULL;
+ gImageMenuItemWidget = NULL;
gCheckMenuItemWidget = NULL;
gTreeViewWidget = NULL;
+ gMiddleTreeViewColumn = NULL;
gTreeHeaderCellWidget = NULL;
gTreeHeaderSortArrowWidget = NULL;
gExpanderWidget = NULL;
@@ -2808,6 +3300,10 @@ moz_gtk_shutdown()
gMenuSeparatorWidget = NULL;
gHPanedWidget = NULL;
gVPanedWidget = NULL;
+ gScrolledWindowWidget = NULL;
+
+ entry_class = g_type_class_peek(GTK_TYPE_ENTRY);
+ g_type_class_unref(entry_class);
is_initialized = FALSE;