diff --git a/widget/src/gtk2/gtk2drawing.c b/widget/src/gtk2/gtk2drawing.c index c44ef2c85f3..435944a0e4e 100644 --- a/widget/src/gtk2/gtk2drawing.c +++ b/widget/src/gtk2/gtk2drawing.c @@ -142,6 +142,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; } @@ -286,6 +287,7 @@ moz_gtk_get_combo_box_inner_button(GtkWidget *widget, gpointer client_data) 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); } } @@ -304,6 +306,7 @@ moz_gtk_get_combo_box_button_inner_widgets(GtkWidget *widget, } else return; gtk_widget_realize(widget); + g_object_set_data(G_OBJECT(widget), "transparent-bg-hint", TRUE); } static gint @@ -343,6 +346,8 @@ ensure_combo_box_widgets() 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 @@ -392,6 +397,7 @@ moz_gtk_get_combo_box_entry_inner_widgets(GtkWidget *widget, } else return; gtk_widget_realize(widget); + g_object_set_data(G_OBJECT(widget), "transparent-bg-hint", TRUE); } static void @@ -402,6 +408,7 @@ moz_gtk_get_combo_box_entry_arrow(GtkWidget *widget, gpointer client_data) 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); } } @@ -452,6 +459,8 @@ ensure_combo_box_entry_widgets() 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; @@ -491,6 +500,7 @@ ensure_toolbar_widget() gToolbarWidget = gtk_toolbar_new(); gtk_container_add(GTK_CONTAINER(gHandleBoxWidget), gToolbarWidget); gtk_widget_realize(gToolbarWidget); + g_object_set_data(G_OBJECT(gToolbarWidget), "transparent-bg-hint", TRUE); } return MOZ_GTK_SUCCESS; } @@ -578,6 +588,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; } @@ -591,6 +603,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; } @@ -604,6 +618,8 @@ 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; } @@ -617,6 +633,8 @@ ensure_image_menu_item_widget() 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; } @@ -630,6 +648,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; } @@ -643,6 +663,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; } @@ -696,6 +718,10 @@ ensure_tree_header_cell_widget() /* 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; } @@ -845,10 +871,23 @@ moz_gtk_button_paint(GdkDrawable* drawable, GdkRectangle* rect, gint moz_gtk_init() { + GtkWidgetClass *entry_class; + is_initialized = TRUE; have_arrow_scaling = (gtk_major_version > 2 || (gtk_major_version == 2 && gtk_minor_version >= 12)); + /* 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; } @@ -1463,6 +1502,7 @@ moz_gtk_entry_paint(GdkDrawable* drawable, GdkRectangle* rect, 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); @@ -1472,6 +1512,7 @@ moz_gtk_entry_paint(GdkDrawable* drawable, GdkRectangle* rect, 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 @@ -1484,9 +1525,20 @@ moz_gtk_entry_paint(GdkDrawable* drawable, GdkRectangle* rect, /* This gets us a lovely greyish disabledish look */ gtk_widget_set_sensitive(widget, !state->disabled); - /* Draw the default window background */ - gdk_draw_rectangle(drawable, style->base_gc[bg_state], TRUE, - cliprect->x, cliprect->y, cliprect->width, cliprect->height); + /* 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); + } /* Get the position of the inner window, see _gtk_entry_get_borders */ x = XTHICKNESS(style); @@ -3182,6 +3234,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 */ @@ -3232,6 +3286,9 @@ moz_gtk_shutdown() gVPanedWidget = NULL; gScrolledWindowWidget = NULL; + entry_class = g_type_class_peek(GTK_TYPE_ENTRY); + g_type_class_unref(entry_class); + is_initialized = FALSE; return MOZ_GTK_SUCCESS;