Submitted By: Ken Moffat Date: 2016-06-13 Initial Package Version:46.0 Upstream Status: Applied in an updated version (some files renamed) Origin: Fedora Description: Without this, on versions of gtk+-3 > 3.18 the sliders for browser scrollbars do not appear. diff -up firefox-46.0.1/widget/gtk/gtk3drawing.c.gtk3-20 firefox-46.0.1/widget/gtk/gtk3drawing.c --- firefox-46.0.1/widget/gtk/gtk3drawing.c.gtk3-20 2016-05-03 07:31:12.000000000 +0200 +++ firefox-46.0.1/widget/gtk/gtk3drawing.c 2016-05-20 15:05:08.750151522 +0200 @@ -17,34 +17,86 @@ #include +#define MOZ_WIDGET_STYLES 4 + +typedef struct { + GtkWidget* widget; + + union { + struct { + GtkStyleContext* style; + GtkStyleContext* styleSelection; + } entry; + + struct { + GtkStyleContext* style; + } button; + + struct { + GtkStyleContext* style; + GtkStyleContext* styleBackground; + } tooltip; + + struct { + GtkStyleContext* style; + GtkStyleContext* styleContents; + GtkStyleContext* styleTrough; + GtkStyleContext* styleSlider; + } scroll; + + struct { + GtkStyleContext* style; + GtkStyleContext* styleCheck; + GtkStyleContext* styleLabel; + } check; + + struct { + GtkStyleContext* style; + GtkStyleContext* styleTrough; + GtkStyleContext* styleProgress; + } progress; + + struct { + GtkStyleContext* style; + GtkStyleContext* styleEntry; + GtkStyleContext* styleButtonUp; + GtkStyleContext* styleButtonDown; + } spin; + + struct { + GtkStyleContext* style[MOZ_WIDGET_STYLES]; + } all; + }; +} MozGtkWidget; + static GtkWidget* gProtoWindow; static GtkWidget* gProtoLayout; -static GtkWidget* gButtonWidget; +static MozGtkWidget gButton; static GtkWidget* gToggleButtonWidget; static GtkWidget* gButtonArrowWidget; -static GtkWidget* gCheckboxWidget; -static GtkWidget* gRadiobuttonWidget; -static GtkWidget* gHorizScrollbarWidget; -static GtkWidget* gVertScrollbarWidget; -static GtkWidget* gSpinWidget; +static MozGtkWidget gCheckbox; +static MozGtkWidget gRadiobutton; +static MozGtkWidget gVertScrollbar; +static MozGtkWidget gHorizScrollbar; +static MozGtkWidget gSpin; static GtkWidget* gHScaleWidget; static GtkWidget* gVScaleWidget; -static GtkWidget* gEntryWidget; +static MozGtkWidget gEntry; static GtkWidget* gComboBoxWidget; static GtkWidget* gComboBoxButtonWidget; static GtkWidget* gComboBoxArrowWidget; static GtkWidget* gComboBoxSeparatorWidget; static GtkWidget* gComboBoxEntryWidget; -static GtkWidget* gComboBoxEntryTextareaWidget; +static MozGtkWidget gComboBoxEntryTextarea; static GtkWidget* gComboBoxEntryButtonWidget; static GtkWidget* gComboBoxEntryArrowWidget; static GtkWidget* gHandleBoxWidget; static GtkWidget* gToolbarWidget; static GtkWidget* gFrameWidget; static GtkWidget* gStatusbarWidget; -static GtkWidget* gProgressWidget; +static MozGtkWidget gProgressBar; static GtkWidget* gTabWidget; -static GtkWidget* gTooltipWidget; +static MozGtkWidget gTooltip; static GtkWidget* gMenuBarWidget; static GtkWidget* gMenuBarItemWidget; static GtkWidget* gMenuPopupWidget; @@ -78,6 +130,37 @@ static gboolean is_initialized; #define GTK_STATE_FLAG_CHECKED (1 << 11) #endif +void moz_gtk_widget_free(MozGtkWidget *aMozWidget) +{ + // This was removed as a child of gProtoWindow + if (aMozWidget->widget) { + aMozWidget->widget = NULL; + } + + for(int i = 0; i < MOZ_WIDGET_STYLES; i++) { + if (aMozWidget->all.style[i]) { + g_object_unref(aMozWidget->all.style[i]); + aMozWidget->all.style[i] = NULL; + } + } +} + +// TODO - weak dep!! (dlsym) +#if GTK_CHECK_VERSION(3, 19, 2) +#define moz_gtk_path_set_class_name gtk_widget_path_iter_set_object_name +#else +#define moz_gtk_path_set_class_name gtk_widget_path_iter_add_class +#endif +//gtk_widget_path_iter_get_state + +static void +moz_gtk_get_style_border(GtkStyleContext* style, GtkStateFlags state_flags, + GtkBorder *border); + +static void +moz_gtk_get_style_padding(GtkStyleContext* style, GtkStateFlags state_flags, + GtkBorder *padding); + static GtkStateFlags GetStateFlagsFromGtkWidgetState(GtkWidgetState* state) { @@ -97,6 +180,41 @@ GetStateFlagsFromGtkWidgetState(GtkWidge return stateFlags; } +GtkStyleContext * +moz_gtk_style_create(GtkCssNode *node, GtkStyleContext *parent) +{ + GtkWidgetPath *path; + GtkStyleContext *context; + + if (parent) + path = gtk_widget_path_copy (gtk_style_context_get_path (parent)); + else + path = gtk_widget_path_new (); + + gtk_widget_path_append_type (path, node->type); + if (node->name) + moz_gtk_path_set_class_name(path, -1, node->name); + if (node->class1) + gtk_widget_path_iter_add_class(path, -1, node->class1); + if (node->class2) + gtk_widget_path_iter_add_class(path, -1, node->class2); + + context = gtk_style_context_new (); + gtk_style_context_set_path (context, path); + gtk_style_context_set_parent (context, parent); + + if(!gtk_check_version(3, 14, 0)) { + /* Unfortunately, we have to explicitly set the state again here + * for it to take effect + */ + gtk_style_context_set_state (context, gtk_widget_path_iter_get_state (path, -1)); + } + + gtk_widget_path_unref (path); + + return context; +} + /* 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. */ @@ -141,9 +259,16 @@ setup_widget_prototype(GtkWidget* widget static gint ensure_button_widget() { - if (!gButtonWidget) { - gButtonWidget = gtk_button_new_with_label("M"); - setup_widget_prototype(gButtonWidget); + if (!gButton.widget) { + GtkCssNode path[] = { + { GTK_TYPE_BUTTON, "button", NULL, NULL } + }; + + gButton.widget = gtk_button_new_with_label("M"); + setup_widget_prototype(gButton.widget); + gtk_widget_show(gButton.widget); + + gButton.button.style = moz_gtk_style_create(&path[0], NULL); } return MOZ_GTK_SUCCESS; } @@ -195,9 +320,21 @@ ensure_button_arrow_widget() static gint ensure_checkbox_widget() { - if (!gCheckboxWidget) { - gCheckboxWidget = gtk_check_button_new_with_label("M"); - setup_widget_prototype(gCheckboxWidget); + if (!gCheckbox.widget) { + GtkCssNode path[] = { + { GTK_TYPE_TOGGLE_BUTTON, "checkbutton", NULL, NULL }, + { G_TYPE_NONE, "check", NULL, NULL }, + { G_TYPE_NONE, "label", NULL, NULL } + }; + + gCheckbox.widget = gtk_check_button_new_with_label("M"); + setup_widget_prototype(gCheckbox.widget); + + gCheckbox.check.style = moz_gtk_style_create(&path[0], NULL); + gCheckbox.check.styleCheck = moz_gtk_style_create(&path[1], + gCheckbox.check.style); + gCheckbox.check.styleLabel = moz_gtk_style_create(&path[2], + gCheckbox.check.style); } return MOZ_GTK_SUCCESS; } @@ -205,9 +342,21 @@ ensure_checkbox_widget() static gint ensure_radiobutton_widget() { - if (!gRadiobuttonWidget) { - gRadiobuttonWidget = gtk_radio_button_new_with_label(NULL, "M"); - setup_widget_prototype(gRadiobuttonWidget); + if (!gRadiobutton.widget) { + GtkCssNode path[] = { + { GTK_TYPE_TOGGLE_BUTTON, "radiobutton", NULL, NULL }, + { G_TYPE_NONE, "radio", NULL, NULL }, + { G_TYPE_NONE, "label", NULL, NULL } + }; + + gRadiobutton.widget = gtk_radio_button_new_with_label(NULL, "M"); + setup_widget_prototype(gRadiobutton.widget); + + gRadiobutton.check.style = moz_gtk_style_create(&path[0], NULL); + gRadiobutton.check.styleCheck = moz_gtk_style_create(&path[1], + gRadiobutton.check.style); + gRadiobutton.check.styleLabel = moz_gtk_style_create(&path[2], + gRadiobutton.check.style); } return MOZ_GTK_SUCCESS; } @@ -215,25 +364,62 @@ ensure_radiobutton_widget() static gint ensure_scrollbar_widget() { - if (!gVertScrollbarWidget) { - gVertScrollbarWidget = gtk_scrollbar_new(GTK_ORIENTATION_VERTICAL, NULL); - setup_widget_prototype(gVertScrollbarWidget); - } - if (!gHorizScrollbarWidget) { - gHorizScrollbarWidget = gtk_scrollbar_new(GTK_ORIENTATION_HORIZONTAL, NULL); - setup_widget_prototype(gHorizScrollbarWidget); - } + if (!gVertScrollbar.widget && !gHorizScrollbar.widget) { + GtkCssNode path[] = { + { GTK_TYPE_SCROLLBAR, "scrollbar", "horizontal", "bottom"}, + { GTK_TYPE_SCROLLBAR, "scrollbar", "vertical", "right" }, + { G_TYPE_NONE, "contents", NULL, NULL }, + { G_TYPE_NONE, "trough", NULL, NULL }, + { G_TYPE_NONE, "slider", NULL, NULL } + }; + + gHorizScrollbar.widget = gtk_scrollbar_new(GTK_ORIENTATION_HORIZONTAL, NULL); + setup_widget_prototype(gHorizScrollbar.widget); + + gHorizScrollbar.scroll.style = moz_gtk_style_create(path, NULL); + gHorizScrollbar.scroll.styleContents = moz_gtk_style_create(path+2, + gHorizScrollbar.scroll.style); + gHorizScrollbar.scroll.styleTrough = moz_gtk_style_create(path+3, + gHorizScrollbar.scroll.styleContents); + gHorizScrollbar.scroll.styleSlider = moz_gtk_style_create(path+4, + gHorizScrollbar.scroll.styleTrough); + + gVertScrollbar.widget = gtk_scrollbar_new(GTK_ORIENTATION_VERTICAL, NULL); + setup_widget_prototype(gVertScrollbar.widget); + + gVertScrollbar.scroll.style = moz_gtk_style_create(path+1, NULL); + gVertScrollbar.scroll.styleContents = moz_gtk_style_create(path+2, + gVertScrollbar.scroll.style); + gVertScrollbar.scroll.styleTrough = moz_gtk_style_create(path+3, + gVertScrollbar.scroll.styleContents); + gVertScrollbar.scroll.styleSlider = moz_gtk_style_create(path+4, + gVertScrollbar.scroll.styleTrough); + + } return MOZ_GTK_SUCCESS; } static gint ensure_spin_widget() { - if (!gSpinWidget) { - gSpinWidget = gtk_spin_button_new(NULL, 1, 0); - setup_widget_prototype(gSpinWidget); - } - return MOZ_GTK_SUCCESS; + if (!gSpin.widget) { + GtkCssNode path[] = { + { GTK_TYPE_SPIN_BUTTON, "spinbutton", "horizontal", NULL }, + { GTK_TYPE_SPIN_BUTTON, "spinbutton", "vertical", NULL }, + { GTK_TYPE_ENTRY, "entry", NULL, NULL }, + { G_TYPE_NONE, "button", "up", NULL }, + { G_TYPE_NONE, "button", "down", NULL } + }; + + gSpin.widget = gtk_spin_button_new(NULL, 1, 0); + setup_widget_prototype(gSpin.widget); + + gSpin.spin.style = moz_gtk_style_create(path, NULL); + gSpin.spin.styleButtonUp = moz_gtk_style_create(path+3, gSpin.spin.style); + gSpin.spin.styleButtonDown = moz_gtk_style_create(path+4, gSpin.spin.style); + gSpin.spin.styleEntry = moz_gtk_style_create(path+2, gSpin.spin.style); + } + return MOZ_GTK_SUCCESS; } static gint @@ -253,9 +439,19 @@ ensure_scale_widget() static gint ensure_entry_widget() { - if (!gEntryWidget) { - gEntryWidget = gtk_entry_new(); - setup_widget_prototype(gEntryWidget); + if (!gEntry.widget) { + GtkCssNode path[] = { + { GTK_TYPE_ENTRY, "entry", NULL, NULL }, + { G_TYPE_NONE, "selection", NULL, NULL } + }; + + gEntry.widget = gtk_entry_new(); + setup_widget_prototype(gEntry.widget); + gtk_widget_show(gEntry.widget); + + gEntry.entry.style = moz_gtk_style_create(&path[0], NULL); + gEntry.entry.styleSelection = moz_gtk_style_create(&path[1], + gEntry.entry.style); } return MOZ_GTK_SUCCESS; } @@ -387,9 +583,9 @@ moz_gtk_get_combo_box_entry_inner_widget g_object_add_weak_pointer(G_OBJECT(widget), (gpointer) &gComboBoxEntryButtonWidget); } else if (GTK_IS_ENTRY(widget)) { - gComboBoxEntryTextareaWidget = widget; + gComboBoxEntryTextarea.widget = widget; g_object_add_weak_pointer(G_OBJECT(widget), - (gpointer) &gComboBoxEntryTextareaWidget); + (gpointer) &gComboBoxEntryTextarea.widget); } else return; gtk_widget_realize(widget); @@ -411,7 +607,7 @@ ensure_combo_box_entry_widgets() { GtkWidget* buttonChild; - if (gComboBoxEntryTextareaWidget && + if (gComboBoxEntryTextarea.widget && gComboBoxEntryButtonWidget && gComboBoxEntryArrowWidget) return MOZ_GTK_SUCCESS; @@ -427,9 +623,9 @@ ensure_combo_box_entry_widgets() moz_gtk_get_combo_box_entry_inner_widgets, NULL); - if (!gComboBoxEntryTextareaWidget) { + if (!gComboBoxEntryTextarea.widget) { ensure_entry_widget(); - gComboBoxEntryTextareaWidget = gEntryWidget; + gComboBoxEntryTextarea.widget = gEntry.widget; } if (gComboBoxEntryButtonWidget) { @@ -507,12 +703,18 @@ ensure_toolbar_separator_widget() static gint ensure_tooltip_widget() { - if (!gTooltipWidget) { - gTooltipWidget = gtk_window_new(GTK_WINDOW_POPUP); - GtkStyleContext* style = gtk_widget_get_style_context(gTooltipWidget); - gtk_style_context_add_class(style, GTK_STYLE_CLASS_TOOLTIP); - gtk_widget_realize(gTooltipWidget); - moz_gtk_set_widget_name(gTooltipWidget); + if (!gTooltip.widget) { + GtkCssNode path[] = { + { GTK_TYPE_TOOLTIP, "tooltip", NULL, NULL}, + { GTK_TYPE_TOOLTIP, "tooltip", "background", NULL}, + }; + + gTooltip.widget = gtk_window_new(GTK_WINDOW_POPUP); + gtk_widget_realize(gTooltip.widget); + moz_gtk_set_widget_name(gTooltip.widget); + + gTooltip.tooltip.style = moz_gtk_style_create(&path[0], NULL); + gTooltip.tooltip.styleBackground = moz_gtk_style_create(&path[1], NULL); } return MOZ_GTK_SUCCESS; } @@ -530,9 +732,21 @@ ensure_tab_widget() static gint ensure_progress_widget() { - if (!gProgressWidget) { - gProgressWidget = gtk_progress_bar_new(); - setup_widget_prototype(gProgressWidget); + if (!gProgressBar.widget) { + GtkCssNode path[] = { + { GTK_TYPE_LABEL, "progressbar", NULL, NULL }, + { G_TYPE_NONE, "trough", NULL, NULL }, + { G_TYPE_NONE, "progress", NULL, NULL }, + }; + + gProgressBar.widget = gtk_progress_bar_new(); + setup_widget_prototype(gProgressBar.widget); + + gProgressBar.progress.style = moz_gtk_style_create(&path[0], NULL); + gProgressBar.progress.styleTrough = moz_gtk_style_create(&path[1], + gProgressBar.progress.style); + gProgressBar.progress.styleProgress = moz_gtk_style_create(&path[2], + gProgressBar.progress.styleTrough); } return MOZ_GTK_SUCCESS; } @@ -638,6 +852,11 @@ static gint ensure_check_menu_item_widget() { if (!gCheckMenuItemWidget) { + GtkCssNode path[] = { + { GTK_TYPE_CHECK_MENU_ITEM, "menuitem", NULL, NULL }, + { G_TYPE_NONE, "check", NULL, NULL } + }; + ensure_menu_popup_widget(); gCheckMenuItemWidget = gtk_check_menu_item_new_with_label("M"); gtk_menu_shell_append(GTK_MENU_SHELL(gMenuPopupWidget), @@ -752,7 +971,7 @@ moz_gtk_checkbox_get_metrics(gint* indic { ensure_checkbox_widget(); - gtk_widget_style_get (gCheckboxWidget, + gtk_widget_style_get (gCheckbox.widget, "indicator_size", indicator_size, "indicator_spacing", indicator_spacing, NULL); @@ -765,7 +984,7 @@ moz_gtk_radio_get_metrics(gint* indicato { ensure_radiobutton_widget(); - gtk_widget_style_get (gRadiobuttonWidget, + gtk_widget_style_get (gRadiobutton.widget, "indicator_size", indicator_size, "indicator_spacing", indicator_spacing, NULL); @@ -778,13 +997,13 @@ moz_gtk_get_focus_outline_size(gint* foc { GtkBorder border; GtkBorder padding; - GtkStyleContext *style; + GtkStyleContext* style; ensure_entry_widget(); - style = gtk_widget_get_style_context(gEntryWidget); - gtk_style_context_get_border(style, 0, &border); - gtk_style_context_get_padding(style, 0, &padding); + style = gEntry.entry.style; + gtk_style_context_get_border(style, gtk_style_context_get_state(style), &border); + gtk_style_context_get_padding(style, gtk_style_context_get_state(style), &padding); *focus_h_width = border.left + padding.left; *focus_v_width = border.top + padding.top; return MOZ_GTK_SUCCESS; @@ -821,7 +1040,7 @@ moz_gtk_button_get_default_overflow(gint GtkBorder* default_outside_border; ensure_button_widget(); - gtk_widget_style_get(gButtonWidget, + gtk_widget_style_get(gButton.widget, "default-outside-border", &default_outside_border, NULL); @@ -844,7 +1063,7 @@ moz_gtk_button_get_default_border(gint* GtkBorder* default_border; ensure_button_widget(); - gtk_widget_style_get(gButtonWidget, + gtk_widget_style_get(gButton.widget, "default-border", &default_border, NULL); @@ -935,7 +1154,7 @@ moz_gtk_button_paint(cairo_t *cr, GdkRec if (state->focused) { GtkBorder border; - gtk_style_context_get_border(style, state_flags, &border); + moz_gtk_get_style_border(style, state_flags, &border); x += border.left; y += border.top; width -= (border.left + border.right); @@ -956,15 +1175,14 @@ moz_gtk_toggle_paint(cairo_t *cr, GdkRec gint indicator_size, indicator_spacing; gint x, y, width, height; gint focus_x, focus_y, focus_width, focus_height; - GtkWidget *w; - GtkStyleContext *style; + MozGtkWidget *w; if (isradio) { moz_gtk_radio_get_metrics(&indicator_size, &indicator_spacing); - w = gRadiobuttonWidget; + w = &gRadiobutton; } else { moz_gtk_checkbox_get_metrics(&indicator_size, &indicator_spacing); - w = gCheckboxWidget; + w = &gCheckbox; } // XXX we should assert rect->height >= indicator_size too @@ -983,11 +1201,9 @@ moz_gtk_toggle_paint(cairo_t *cr, GdkRec focus_width = width + 2 * indicator_spacing; focus_height = height + 2 * indicator_spacing; - style = gtk_widget_get_style_context(w); - - gtk_widget_set_sensitive(w, !state->disabled); - gtk_widget_set_direction(w, direction); - gtk_style_context_save(style); + gtk_widget_set_sensitive(w->widget, !state->disabled); + gtk_widget_set_direction(w->widget, direction); + gtk_style_context_save(w->check.styleCheck); if (selected) state_flags |= checkbox_check_state; @@ -995,13 +1211,15 @@ moz_gtk_toggle_paint(cairo_t *cr, GdkRec if (inconsistent) state_flags |= GTK_STATE_FLAG_INCONSISTENT; - gtk_style_context_set_state(style, state_flags); + gtk_style_context_set_state(w->check.styleCheck, state_flags); + + gtk_render_background(w->check.styleCheck, cr, x, y, width, height); + gtk_render_frame(w->check.styleCheck, cr, x, y, width, height); if (isradio) { - gtk_style_context_add_class(style, GTK_STYLE_CLASS_RADIO); - gtk_render_option(style, cr, x, y, width, height); + gtk_render_option(w->check.styleCheck, cr, x, y, width, height); if (state->focused) { - gtk_render_focus(style, cr, focus_x, focus_y, + gtk_render_focus(w->check.styleCheck, cr, focus_x, focus_y, focus_width, focus_height); } } @@ -1010,15 +1228,14 @@ moz_gtk_toggle_paint(cairo_t *cr, GdkRec * 'indeterminate' type on checkboxes. In GTK, the shadow type * must also be changed for the state to be drawn. */ - gtk_style_context_add_class(style, GTK_STYLE_CLASS_CHECK); - gtk_toggle_button_set_inconsistent(GTK_TOGGLE_BUTTON(gCheckboxWidget), inconsistent); - gtk_render_check(style, cr, x, y, width, height); + gtk_toggle_button_set_inconsistent(GTK_TOGGLE_BUTTON(w->widget), inconsistent); + gtk_render_check(w->check.styleCheck, cr, x, y, width, height); if (state->focused) { - gtk_render_focus(style, cr, + gtk_render_focus(w->check.styleCheck, cr, focus_x, focus_y, focus_width, focus_height); } } - gtk_style_context_restore(style); + gtk_style_context_restore(w->check.styleCheck); return MOZ_GTK_SUCCESS; } @@ -1035,8 +1252,8 @@ calculate_button_inner_rect(GtkWidget* b style = gtk_widget_get_style_context(button); /* This mirrors gtkbutton's child positioning */ - gtk_style_context_get_border(style, 0, &border); - gtk_style_context_get_padding(style, 0, &padding); + gtk_style_context_get_border(style, gtk_style_context_get_state(style), &border); + gtk_style_context_get_padding(style, gtk_style_context_get_state(style), &padding); inner_rect->x = rect->x + border.left + padding.left; inner_rect->y = rect->y + padding.top + border.top; @@ -1099,9 +1316,9 @@ moz_gtk_scrollbar_button_paint(cairo_t * ensure_scrollbar_widget(); if (flags & MOZ_GTK_STEPPER_VERTICAL) - scrollbar = gVertScrollbarWidget; + scrollbar = gVertScrollbar.widget; else - scrollbar = gHorizScrollbarWidget; + scrollbar = gHorizScrollbar.widget; gtk_widget_set_direction(scrollbar, direction); @@ -1181,25 +1398,22 @@ moz_gtk_scrollbar_trough_paint(GtkThemeW GtkTextDirection direction) { GtkStyleContext* style; - GtkScrollbar *scrollbar; ensure_scrollbar_widget(); - if (widget == MOZ_GTK_SCROLLBAR_HORIZONTAL) - scrollbar = GTK_SCROLLBAR(gHorizScrollbarWidget); - else - scrollbar = GTK_SCROLLBAR(gVertScrollbarWidget); - - gtk_widget_set_direction(GTK_WIDGET(scrollbar), direction); - if (flags & MOZ_GTK_TRACK_OPAQUE) { style = gtk_widget_get_style_context(GTK_WIDGET(gProtoWindow)); gtk_render_background(style, cr, rect->x, rect->y, rect->width, rect->height); } - style = gtk_widget_get_style_context(GTK_WIDGET(scrollbar)); - gtk_style_context_save(style); - gtk_style_context_add_class(style, GTK_STYLE_CLASS_TROUGH); + if (widget == MOZ_GTK_SCROLLBAR_HORIZONTAL) { + gtk_widget_set_direction(GTK_WIDGET(gHorizScrollbar.widget), direction); + style = gHorizScrollbar.scroll.style; + } + else { + gtk_widget_set_direction(GTK_WIDGET(gVertScrollbar.widget), direction); + style = gVertScrollbar.scroll.style; + } gtk_render_background(style, cr, rect->x, rect->y, rect->width, rect->height); gtk_render_frame(style, cr, rect->x, rect->y, rect->width, rect->height); @@ -1208,7 +1422,6 @@ moz_gtk_scrollbar_trough_paint(GtkThemeW gtk_render_focus(style, cr, rect->x, rect->y, rect->width, rect->height); } - gtk_style_context_restore(style); return MOZ_GTK_SUCCESS; } @@ -1220,24 +1433,20 @@ moz_gtk_scrollbar_thumb_paint(GtkThemeWi { GtkStateFlags state_flags = GetStateFlagsFromGtkWidgetState(state); GtkStyleContext* style; - GtkScrollbar *scrollbar; GtkBorder margin; ensure_scrollbar_widget(); - if (widget == MOZ_GTK_SCROLLBAR_THUMB_HORIZONTAL) - scrollbar = GTK_SCROLLBAR(gHorizScrollbarWidget); - else - scrollbar = GTK_SCROLLBAR(gVertScrollbarWidget); - - gtk_widget_set_direction(GTK_WIDGET(scrollbar), direction); - - style = gtk_widget_get_style_context(GTK_WIDGET(scrollbar)); - gtk_style_context_save(style); + if (widget == MOZ_GTK_SCROLLBAR_THUMB_HORIZONTAL) { + style = gHorizScrollbar.scroll.styleSlider; + gtk_widget_set_direction(GTK_WIDGET(gHorizScrollbar.widget), direction); + } + else { + style = gVertScrollbar.scroll.styleSlider; + gtk_widget_set_direction(GTK_WIDGET(gVertScrollbar.widget), direction); + } - gtk_style_context_add_class(style, GTK_STYLE_CLASS_SLIDER); gtk_style_context_set_state(style, state_flags); - gtk_style_context_get_margin (style, state_flags, &margin); gtk_render_slider(style, cr, @@ -1248,8 +1457,6 @@ moz_gtk_scrollbar_thumb_paint(GtkThemeWi (widget == MOZ_GTK_SCROLLBAR_THUMB_HORIZONTAL) ? GTK_ORIENTATION_HORIZONTAL : GTK_ORIENTATION_VERTICAL); - gtk_style_context_restore(style); - return MOZ_GTK_SUCCESS; } @@ -1260,8 +1467,8 @@ moz_gtk_spin_paint(cairo_t *cr, GdkRecta GtkStyleContext* style; ensure_spin_widget(); - gtk_widget_set_direction(gSpinWidget, direction); - style = gtk_widget_get_style_context(gSpinWidget); + gtk_widget_set_direction(gSpin.widget, direction); + style = gSpin.spin.style; gtk_style_context_save(style); gtk_style_context_add_class(style, GTK_STYLE_CLASS_SPINBUTTON); gtk_render_background(style, cr, rect->x, rect->y, rect->width, rect->height); @@ -1280,11 +1487,10 @@ moz_gtk_spin_updown_paint(cairo_t *cr, G GtkStyleContext* style; ensure_spin_widget(); - style = gtk_widget_get_style_context(gSpinWidget); + style = gSpin.spin.style; gtk_style_context_save(style); - gtk_style_context_add_class(style, GTK_STYLE_CLASS_SPINBUTTON); gtk_style_context_set_state(style, GetStateFlagsFromGtkWidgetState(state)); - gtk_widget_set_direction(gSpinWidget, direction); + gtk_widget_set_direction(gSpin.widget, direction); gtk_render_background(style, cr, rect->x, rect->y, rect->width, rect->height); gtk_render_frame(style, cr, rect->x, rect->y, rect->width, rect->height); @@ -1450,15 +1656,13 @@ moz_gtk_vpaned_paint(cairo_t *cr, GdkRec static gint moz_gtk_entry_paint(cairo_t *cr, GdkRectangle* rect, GtkWidgetState* state, - GtkWidget* widget, GtkTextDirection direction) + MozGtkWidget* w, GtkTextDirection direction) { gint x = rect->x, y = rect->y, width = rect->width, height = rect->height; - GtkStyleContext* style; int draw_focus_outline_only = state->depressed; // NS_THEME_FOCUS_OUTLINE + GtkStyleContext* style = w->entry.style; - gtk_widget_set_direction(widget, direction); - - style = gtk_widget_get_style_context(widget); + gtk_widget_set_direction(w->widget, direction); if (draw_focus_outline_only) { // Inflate the given 'rect' with the focus outline size. @@ -1478,10 +1682,9 @@ moz_gtk_entry_paint(cairo_t *cr, GdkRect * textarea window uses gtk_paint_flat_box when exposed */ /* This gets us a lovely greyish disabledish look */ - gtk_widget_set_sensitive(widget, !state->disabled); + gtk_widget_set_sensitive(w->widget, !state->disabled); gtk_style_context_save(style); - gtk_style_context_add_class(style, GTK_STYLE_CLASS_ENTRY); /* Now paint the shadow and focus border. * We do like in gtk_entry_draw_frame, we first draw the shadow, a tad @@ -1531,7 +1734,7 @@ moz_gtk_treeview_paint(cairo_t *cr, GdkR style = gtk_widget_get_style_context(gScrolledWindowWidget); gtk_style_context_save(style); gtk_style_context_add_class(style, GTK_STYLE_CLASS_FRAME); - gtk_style_context_get_border(style, state_flags, &border); + moz_gtk_get_style_border(style, state_flags, &border); xthickness = border.left; ythickness = border.top; @@ -1702,7 +1905,7 @@ moz_gtk_combo_box_paint(cairo_t *cr, Gdk if (direction == GTK_TEXT_DIR_LTR) { GtkBorder padding; GtkStateFlags state_flags = GetStateFlagsFromGtkWidgetState(state); - gtk_style_context_get_padding(style, state_flags, &padding); + moz_gtk_get_style_padding(style, state_flags, &padding); arrow_rect.x -= padding.left; } else @@ -1804,29 +2007,27 @@ moz_gtk_container_paint(cairo_t *cr, Gdk gboolean isradio, GtkTextDirection direction) { GtkStateFlags state_flags = GetStateFlagsFromGtkWidgetState(state); - GtkStyleContext* style; - GtkWidget *widget; + MozGtkWidget *widget; if (isradio) { ensure_radiobutton_widget(); - widget = gRadiobuttonWidget; + widget = &gRadiobutton; } else { ensure_checkbox_widget(); - widget = gCheckboxWidget; + widget = &gCheckbox; } - gtk_widget_set_direction(widget, direction); + gtk_widget_set_direction(widget->widget, direction); - style = gtk_widget_get_style_context(widget); - gtk_style_context_save(style); - gtk_style_context_set_state(style, state_flags); + gtk_style_context_save(widget->check.style); + gtk_style_context_set_state(widget->check.style, state_flags); /* this is for drawing a prelight box */ if (state_flags & GTK_STATE_FLAG_PRELIGHT) { - gtk_render_background(style, cr, + gtk_render_background(widget->check.style, cr, rect->x, rect->y, rect->width, rect->height); } - gtk_style_context_restore(style); + gtk_style_context_restore(widget->check.style); return MOZ_GTK_SUCCESS; } @@ -1836,32 +2037,26 @@ moz_gtk_toggle_label_paint(cairo_t *cr, GtkWidgetState* state, gboolean isradio, GtkTextDirection direction) { - GtkStyleContext *style; - GtkWidget *widget; + MozGtkWidget *widget; if (!state->focused) return MOZ_GTK_SUCCESS; if (isradio) { ensure_radiobutton_widget(); - widget = gRadiobuttonWidget; + widget = &gRadiobutton; } else { ensure_checkbox_widget(); - widget = gCheckboxWidget; - } - style = gtk_widget_get_style_context(widget); - gtk_style_context_save(style); - if (isradio) { - gtk_style_context_add_class(style, GTK_STYLE_CLASS_RADIO); - } else { - gtk_style_context_add_class(style, GTK_STYLE_CLASS_CHECK); + widget = &gCheckbox; } - gtk_widget_set_direction(widget, direction); + gtk_style_context_save(widget->check.styleLabel); + gtk_widget_set_direction(widget->widget, direction); - gtk_style_context_set_state(style, GetStateFlagsFromGtkWidgetState(state)); - gtk_render_focus(style, cr, + gtk_style_context_set_state(widget->check.styleLabel, + GetStateFlagsFromGtkWidgetState(state)); + gtk_render_focus(widget->check.styleLabel, cr, rect->x, rect->y, rect->width, rect->height); - gtk_style_context_restore(style); + gtk_style_context_restore(widget->check.styleLabel); return MOZ_GTK_SUCCESS; } @@ -1922,7 +2117,7 @@ moz_gtk_toolbar_separator_paint(cairo_t rect->height * (end_fraction - start_fraction)); } else { GtkBorder padding; - gtk_style_context_get_padding(style, 0, &padding); + gtk_style_context_get_padding(style, gtk_style_context_get_state(style), &padding); paint_width = padding.left; if (paint_width > rect->width) @@ -1945,9 +2140,9 @@ moz_gtk_tooltip_paint(cairo_t *cr, GdkRe GtkStyleContext* style; ensure_tooltip_widget(); - gtk_widget_set_direction(gTooltipWidget, direction); + gtk_widget_set_direction(gTooltip.widget, direction); - style = gtk_widget_get_style_context(gTooltipWidget); + style = gTooltip.tooltip.styleBackground; gtk_render_background(style, cr, rect->x, rect->y, rect->width, rect->height); gtk_render_frame(style, cr, rect->x, rect->y, rect->width, rect->height); return MOZ_GTK_SUCCESS; @@ -2006,18 +2201,13 @@ static gint moz_gtk_progressbar_paint(cairo_t *cr, GdkRectangle* rect, GtkTextDirection direction) { - GtkStyleContext* style; - ensure_progress_widget(); - gtk_widget_set_direction(gProgressWidget, direction); + gtk_widget_set_direction(gProgressBar.widget, direction); - style = gtk_widget_get_style_context(gProgressWidget); - gtk_style_context_save(style); - gtk_style_context_add_class(style, GTK_STYLE_CLASS_TROUGH); - - gtk_render_background(style, cr, rect->x, rect->y, rect->width, rect->height); - gtk_render_frame(style, cr, rect->x, rect->y, rect->width, rect->height); - gtk_style_context_restore(style); + gtk_render_background(gProgressBar.progress.styleTrough, cr, + rect->x, rect->y, rect->width, rect->height); + gtk_render_frame(gProgressBar.progress.styleTrough, cr, + rect->x, rect->y, rect->width, rect->height); return MOZ_GTK_SUCCESS; } @@ -2027,15 +2217,8 @@ moz_gtk_progress_chunk_paint(cairo_t *cr GtkTextDirection direction, GtkThemeWidgetType widget) { - GtkStyleContext* style; - ensure_progress_widget(); - gtk_widget_set_direction(gProgressWidget, direction); - - style = gtk_widget_get_style_context(gProgressWidget); - gtk_style_context_save(style); - gtk_style_context_remove_class(style, GTK_STYLE_CLASS_TROUGH); - gtk_style_context_add_class(style, GTK_STYLE_CLASS_PROGRESSBAR); + gtk_widget_set_direction(gProgressBar.widget, direction); if (widget == MOZ_GTK_PROGRESS_CHUNK_INDETERMINATE || widget == MOZ_GTK_PROGRESS_CHUNK_VERTICAL_INDETERMINATE) { @@ -2074,12 +2257,14 @@ moz_gtk_progress_chunk_paint(cairo_t *cr // gtk_render_activity was used to render progress chunks on GTK versions // before 3.13.7, see bug 1173907. if (!gtk_check_version(3, 13, 7)) { - gtk_render_background(style, cr, rect->x, rect->y, rect->width, rect->height); - gtk_render_frame(style, cr, rect->x, rect->y, rect->width, rect->height); + gtk_render_background(gProgressBar.progress.styleProgress, cr, + rect->x, rect->y, rect->width, rect->height); + gtk_render_frame(gProgressBar.progress.styleProgress, cr, + rect->x, rect->y, rect->width, rect->height); } else { - gtk_render_activity(style, cr, rect->x, rect->y, rect->width, rect->height); + gtk_render_activity(gProgressBar.progress.styleProgress, cr, + rect->x, rect->y, rect->width, rect->height); } - gtk_style_context_restore(style); return MOZ_GTK_SUCCESS; } @@ -2096,7 +2281,7 @@ moz_gtk_get_tab_thickness(void) style = gtk_widget_get_style_context(gTabWidget); gtk_style_context_add_class(style, GTK_STYLE_CLASS_NOTEBOOK); - gtk_style_context_get_border(style, 0, &border); + gtk_style_context_get_border(style, gtk_style_context_get_state(style), &border); if (border.top < 2) return 2; /* some themes don't set ythickness correctly */ @@ -2292,7 +2477,7 @@ moz_gtk_tab_paint(cairo_t *cr, GdkRectan gtk_style_context_save(style); moz_gtk_tab_prepare_style_context(style, flags); - gtk_style_context_get_padding(style, GetStateFlagsFromGtkWidgetState(state), &padding); + moz_gtk_get_style_padding(style, GetStateFlagsFromGtkWidgetState(state), &padding); focusRect.x += padding.left; focusRect.width -= (padding.left + padding.right); @@ -2408,7 +2593,7 @@ moz_gtk_tab_scroll_arrow_paint(cairo_t * } static gint -moz_gtk_menu_bar_paint(cairo_t *cr, GdkRectangle* rect, +moz_gtk_menu_bar_paint(cairo_t *cr, GdkRectangle* rect, GtkWidgetState* state, GtkTextDirection direction) { GtkStyleContext* style; @@ -2468,7 +2653,7 @@ moz_gtk_menu_separator_paint(cairo_t *cr border_width = gtk_container_get_border_width(GTK_CONTAINER(gMenuSeparatorWidget)); style = gtk_widget_get_style_context(gMenuSeparatorWidget); - gtk_style_context_get_padding(style, 0, &padding); + gtk_style_context_get_padding(style, gtk_style_context_get_state(style), &padding); x = rect->x + border_width; y = rect->y + border_width; @@ -2521,7 +2706,8 @@ moz_gtk_menu_item_paint(cairo_t *cr, Gdk item_widget = gMenuItemWidget; } style = gtk_widget_get_style_context(item_widget); - gtk_style_context_save(style); +// TODO - FIX! +// gtk_style_context_save(style); if (flags & MOZ_TOPLEVEL_MENU_ITEM) { gtk_style_context_add_class(style, GTK_STYLE_CLASS_MENUBAR); @@ -2540,7 +2726,7 @@ moz_gtk_menu_item_paint(cairo_t *cr, Gdk gtk_render_background(style, cr, x, y, w, h); gtk_render_frame(style, cr, x, y, w, h); - gtk_style_context_restore(style); +// gtk_style_context_restore(style); } return MOZ_GTK_SUCCESS; @@ -2556,7 +2742,10 @@ moz_gtk_menu_arrow_paint(cairo_t *cr, Gd ensure_menu_item_widget(); gtk_widget_set_direction(gMenuItemWidget, direction); - +/* + state_flags |= (direction == GTK_TEXT_DIR_LTR) ? GTK_STATE_FLAG_DIR_LTR : + GTK_STATE_FLAG_DIR_RTL; +*/ style = gtk_widget_get_style_context(gMenuItemWidget); gtk_style_context_save(style); gtk_style_context_add_class(style, GTK_STYLE_CLASS_MENUITEM); @@ -2606,7 +2795,7 @@ moz_gtk_check_menu_item_paint(cairo_t *c } gtk_style_context_set_state(style, state_flags); - gtk_style_context_get_padding(style, state_flags, &padding); + moz_gtk_get_style_padding(style, state_flags, &padding); offset = gtk_container_get_border_width(GTK_CONTAINER(gCheckMenuItemWidget)) + padding.left + 2; @@ -2658,7 +2847,7 @@ moz_gtk_add_style_border(GtkStyleContext { GtkBorder border; - gtk_style_context_get_border(style, 0, &border); + gtk_style_context_get_border(style, gtk_style_context_get_state(style), &border); *left += border.left; *right += border.right; @@ -2667,12 +2856,22 @@ moz_gtk_add_style_border(GtkStyleContext } static void +moz_gtk_get_style_border(GtkStyleContext* style, GtkStateFlags state_flags, + GtkBorder *border) +{ + gtk_style_context_save(style); + gtk_style_context_set_state(style, state_flags); + gtk_style_context_get_border(style, gtk_style_context_get_state(style), border); + gtk_style_context_restore(style); +} + +static void moz_gtk_add_style_padding(GtkStyleContext* style, gint* left, gint* top, gint* right, gint* bottom) { GtkBorder padding; - gtk_style_context_get_padding(style, 0, &padding); + gtk_style_context_get_padding(style, gtk_style_context_get_state(style), &padding); *left += padding.left; *right += padding.right; @@ -2680,6 +2879,16 @@ moz_gtk_add_style_padding(GtkStyleContex *bottom += padding.bottom; } +static void +moz_gtk_get_style_padding(GtkStyleContext* style, GtkStateFlags state_flags, + GtkBorder *padding) +{ + gtk_style_context_save(style); + gtk_style_context_set_state(style, state_flags); + gtk_style_context_get_padding(style, gtk_style_context_get_state(style), padding); + gtk_style_context_restore(style); +} + gint moz_gtk_get_widget_border(GtkThemeWidgetType widget, gint* left, gint* top, gint* right, gint* bottom, GtkTextDirection direction, @@ -2694,37 +2903,35 @@ moz_gtk_get_widget_border(GtkThemeWidget case MOZ_GTK_TOOLBAR_BUTTON: { ensure_button_widget(); - style = gtk_widget_get_style_context(gButtonWidget); - - *left = *top = *right = *bottom = gtk_container_get_border_width(GTK_CONTAINER(gButtonWidget)); - if (widget == MOZ_GTK_TOOLBAR_BUTTON) { - gtk_style_context_save(style); - gtk_style_context_add_class(style, "image-button"); - } - - moz_gtk_add_style_padding(style, left, top, right, bottom); - - if (widget == MOZ_GTK_TOOLBAR_BUTTON) - gtk_style_context_restore(style); + *left = *top = *right = *bottom = gtk_container_get_border_width(GTK_CONTAINER(gButton.widget)); + moz_gtk_add_style_padding(gButton.button.style, left, top, right, bottom); // XXX: Subtract 1 pixel from the border to account for the added // -moz-focus-inner border (Bug 1228281). *left -= 1; *top -= 1; *right -= 1; *bottom -= 1; - moz_gtk_add_style_border(style, left, top, right, bottom); + moz_gtk_add_style_border(gButton.button.style, left, top, right, bottom); + return MOZ_GTK_SUCCESS; } case MOZ_GTK_ENTRY: { ensure_entry_widget(); - style = gtk_widget_get_style_context(gEntryWidget); // XXX: Subtract 1 pixel from the padding to account for the default // padding in forms.css. See bug 1187385. *left = *top = *right = *bottom = -1; - moz_gtk_add_style_padding(style, left, top, right, bottom); - moz_gtk_add_style_border(style, left, top, right, bottom); + moz_gtk_add_style_padding(gEntry.entry.style, left, top, right, bottom); + moz_gtk_add_style_border(gEntry.entry.style, left, top, right, bottom); + + return MOZ_GTK_SUCCESS; + } + case MOZ_GTK_TOOLTIP: + { + ensure_tooltip_widget(); + moz_gtk_add_style_padding(gTooltip.tooltip.styleBackground, left, top, right, bottom); + moz_gtk_add_style_border(gTooltip.tooltip.styleBackground, left, top, right, bottom); return MOZ_GTK_SUCCESS; } case MOZ_GTK_TREEVIEW: @@ -2759,7 +2966,7 @@ moz_gtk_get_widget_border(GtkThemeWidget break; case MOZ_GTK_DROPDOWN_ENTRY: ensure_combo_box_entry_widgets(); - w = gComboBoxEntryTextareaWidget; + w = gComboBoxEntryTextarea.widget; break; case MOZ_GTK_DROPDOWN_ARROW: ensure_combo_box_entry_widgets(); @@ -2795,7 +3002,7 @@ moz_gtk_get_widget_border(GtkThemeWidget if (!wide_separators) { style = gtk_widget_get_style_context(gComboBoxSeparatorWidget); - gtk_style_context_get_border(style, 0, &border); + gtk_style_context_get_border(style, gtk_style_context_get_state(style), &border); separator_width = border.left; } } @@ -2814,14 +3021,17 @@ moz_gtk_get_widget_border(GtkThemeWidget w = gTabWidget; break; case MOZ_GTK_PROGRESSBAR: - ensure_progress_widget(); - w = gProgressWidget; - break; + { + ensure_progress_widget(); + moz_gtk_add_style_border(gProgressBar.progress.styleTrough, + left, top, right, bottom); + return MOZ_GTK_SUCCESS; + } case MOZ_GTK_SPINBUTTON_ENTRY: case MOZ_GTK_SPINBUTTON_UP: case MOZ_GTK_SPINBUTTON_DOWN: ensure_spin_widget(); - w = gSpinWidget; + w = gSpin.widget; break; case MOZ_GTK_SCALE_HORIZONTAL: ensure_scale_widget(); @@ -2840,12 +3050,13 @@ moz_gtk_get_widget_border(GtkThemeWidget { if (widget == MOZ_GTK_CHECKBUTTON_CONTAINER) { ensure_checkbox_widget(); - w = gCheckboxWidget; + w = gCheckbox.widget; + style = gCheckbox.check.styleCheck; } else { ensure_radiobutton_widget(); - w = gRadiobuttonWidget; + w = gRadiobutton.widget; + style = gRadiobutton.check.styleCheck; } - style = gtk_widget_get_style_context(w); *left = *top = *right = *bottom = gtk_container_get_border_width(GTK_CONTAINER(w)); moz_gtk_add_style_border(style, @@ -2904,7 +3115,6 @@ moz_gtk_get_widget_border(GtkThemeWidget case MOZ_GTK_MENUSEPARATOR: /* These widgets have no borders.*/ case MOZ_GTK_SPINBUTTON: - case MOZ_GTK_TOOLTIP: case MOZ_GTK_WINDOW: case MOZ_GTK_RESIZER: case MOZ_GTK_MENUARROW: @@ -2978,6 +3188,32 @@ moz_gtk_get_combo_box_entry_button_size( } gint +moz_gtk_get_entry_height(gint* height) +{ + GtkRequisition requisition; + ensure_entry_widget(); + + gtk_widget_get_preferred_size(gEntry.widget, NULL, &requisition); + *height = requisition.height; + + return MOZ_GTK_SUCCESS; +} + + +gint +moz_gtk_get_button_height(gint* height) +{ + GtkRequisition requisition; + ensure_entry_widget(); + + gtk_widget_get_preferred_size(gButton.widget, NULL, &requisition); + *height = requisition.height; + + return MOZ_GTK_SUCCESS; +} + + +gint moz_gtk_get_tab_scroll_arrow_size(gint* width, gint* height) { gint arrow_size; @@ -3030,7 +3266,7 @@ moz_gtk_get_toolbar_separator_width(gint "separator-width", &separator_width, NULL); /* Just in case... */ - gtk_style_context_get_border(style, 0, &border); + gtk_style_context_get_border(style, gtk_style_context_get_state(style), &border); *size = MAX(*size, (wide_separators ? separator_width : border.left)); return MOZ_GTK_SUCCESS; } @@ -3072,7 +3308,7 @@ moz_gtk_get_menu_separator_height(gint * border_width = gtk_container_get_border_width(GTK_CONTAINER(gMenuSeparatorWidget)); style = gtk_widget_get_style_context(gMenuSeparatorWidget); - gtk_style_context_get_padding(style, 0, &padding); + gtk_style_context_get_padding(style, gtk_style_context_get_state(style), &padding); gtk_style_context_save(style); gtk_style_context_add_class(style, GTK_STYLE_CLASS_SEPARATOR); @@ -3130,15 +3366,21 @@ moz_gtk_get_scrollbar_metrics(MozGtkScro { ensure_scrollbar_widget(); - gtk_widget_style_get (gHorizScrollbarWidget, + gtk_widget_style_get (gHorizScrollbar.widget, "slider_width", &metrics->slider_width, "trough_border", &metrics->trough_border, "stepper_size", &metrics->stepper_size, "stepper_spacing", &metrics->stepper_spacing, NULL); - metrics->min_slider_size = - gtk_range_get_min_slider_size(GTK_RANGE(gHorizScrollbarWidget)); + if (!gtk_check_version(3,19,7)) { + gtk_style_context_get(gVertScrollbar.scroll.styleSlider, + gtk_style_context_get_state(gVertScrollbar.scroll.styleSlider), + "min-height", &metrics->min_slider_size, NULL); + } else { + metrics->min_slider_size = + gtk_range_get_min_slider_size(GTK_RANGE(gVertScrollbar.widget)); + } return MOZ_GTK_SUCCESS; } @@ -3163,7 +3405,7 @@ moz_gtk_images_in_buttons() GtkSettings* settings; ensure_button_widget(); - settings = gtk_widget_get_settings(gButtonWidget); + settings = gtk_widget_get_settings(gButton.widget); g_object_get(settings, "gtk-button-images", &result, NULL); return result; @@ -3191,7 +3433,7 @@ moz_gtk_widget_paint(GtkThemeWidgetType } ensure_button_widget(); return moz_gtk_button_paint(cr, rect, state, - (GtkReliefStyle) flags, gButtonWidget, + (GtkReliefStyle) flags, gButton.widget, direction); break; case MOZ_GTK_CHECKBUTTON: @@ -3241,7 +3483,7 @@ moz_gtk_widget_paint(GtkThemeWidgetType case MOZ_GTK_SPINBUTTON_ENTRY: ensure_spin_widget(); return moz_gtk_entry_paint(cr, rect, state, - gSpinWidget, direction); + &gSpin, direction); break; case MOZ_GTK_GRIPPER: return moz_gtk_gripper_paint(cr, rect, state, @@ -3268,7 +3510,7 @@ moz_gtk_widget_paint(GtkThemeWidgetType case MOZ_GTK_ENTRY: ensure_entry_widget(); return moz_gtk_entry_paint(cr, rect, state, - gEntryWidget, direction); + &gEntry, direction); break; case MOZ_GTK_DROPDOWN: return moz_gtk_combo_box_paint(cr, rect, state, direction); @@ -3280,7 +3522,7 @@ moz_gtk_widget_paint(GtkThemeWidgetType case MOZ_GTK_DROPDOWN_ENTRY: ensure_combo_box_entry_widgets(); return moz_gtk_entry_paint(cr, rect, state, - gComboBoxEntryTextareaWidget, direction); + &gComboBoxEntryTextarea, direction); break; case MOZ_GTK_CHECKBUTTON_CONTAINER: case MOZ_GTK_RADIOBUTTON_CONTAINER: @@ -3332,7 +3574,7 @@ moz_gtk_widget_paint(GtkThemeWidgetType (GtkArrowType) flags, direction); break; case MOZ_GTK_MENUBAR: - return moz_gtk_menu_bar_paint(cr, rect, direction); + return moz_gtk_menu_bar_paint(cr, rect, state, direction); break; case MOZ_GTK_MENUPOPUP: return moz_gtk_menu_popup_paint(cr, rect, direction); @@ -3383,7 +3625,7 @@ GtkWidget* moz_gtk_get_scrollbar_widget( { MOZ_ASSERT(is_initialized, "Forgot to call moz_gtk_init()"); ensure_scrollbar_widget(); - return gHorizScrollbarWidget; + return gVertScrollbar.widget; } gboolean moz_gtk_has_scrollbar_buttons(void) @@ -3391,7 +3633,7 @@ gboolean moz_gtk_has_scrollbar_buttons(v gboolean backward, forward, secondary_backward, secondary_forward; MOZ_ASSERT(is_initialized, "Forgot to call moz_gtk_init()"); ensure_scrollbar_widget(); - gtk_widget_style_get (gHorizScrollbarWidget, + gtk_widget_style_get (gHorizScrollbar.widget, "has-backward-stepper", &backward, "has-forward-stepper", &forward, "has-secondary-backward-stepper", &secondary_backward, @@ -3403,8 +3645,8 @@ gboolean moz_gtk_has_scrollbar_buttons(v gint moz_gtk_shutdown() { - if (gTooltipWidget) - gtk_widget_destroy(gTooltipWidget); + moz_gtk_widget_free(&gTooltip); + /* This will destroy all of our widgets */ if (gProtoWindow) gtk_widget_destroy(gProtoWindow); @@ -3415,17 +3657,19 @@ moz_gtk_shutdown() gProtoWindow = NULL; gProtoLayout = NULL; - gButtonWidget = NULL; + + // MozWidgets + moz_gtk_widget_free(&gButton); gToggleButtonWidget = NULL; gButtonArrowWidget = NULL; - gCheckboxWidget = NULL; - gRadiobuttonWidget = NULL; - gHorizScrollbarWidget = NULL; - gVertScrollbarWidget = NULL; - gSpinWidget = NULL; + moz_gtk_widget_free(&gCheckbox); + moz_gtk_widget_free(&gRadiobutton); + moz_gtk_widget_free(&gHorizScrollbar); + moz_gtk_widget_free(&gVertScrollbar); + moz_gtk_widget_free(&gSpin); gHScaleWidget = NULL; gVScaleWidget = NULL; - gEntryWidget = NULL; + moz_gtk_widget_free(&gEntry); gComboBoxWidget = NULL; gComboBoxButtonWidget = NULL; gComboBoxSeparatorWidget = NULL; @@ -3433,14 +3677,13 @@ moz_gtk_shutdown() gComboBoxEntryWidget = NULL; gComboBoxEntryButtonWidget = NULL; gComboBoxEntryArrowWidget = NULL; - gComboBoxEntryTextareaWidget = NULL; + moz_gtk_widget_free(&gComboBoxEntryTextarea); gHandleBoxWidget = NULL; gToolbarWidget = NULL; gStatusbarWidget = NULL; gFrameWidget = NULL; - gProgressWidget = NULL; + moz_gtk_widget_free(&gProgressBar); gTabWidget = NULL; - gTooltipWidget = NULL; gMenuBarWidget = NULL; gMenuBarItemWidget = NULL; gMenuPopupWidget = NULL; diff -up firefox-46.0.1/widget/gtk/gtkdrawing.h.gtk3-20 firefox-46.0.1/widget/gtk/gtkdrawing.h --- firefox-46.0.1/widget/gtk/gtkdrawing.h.gtk3-20 2016-05-03 07:31:12.000000000 +0200 +++ firefox-46.0.1/widget/gtk/gtkdrawing.h 2016-05-19 15:20:11.656519199 +0200 @@ -67,6 +67,13 @@ typedef enum { MOZ_GTK_TAB_SELECTED = 1 << 10 } GtkTabFlags; +typedef struct { + GType type; + const gchar *name; + const gchar *class1; + const gchar *class2; +} GtkCssNode; + /** flags for menuitems **/ typedef enum { /* menuitem is part of the menubar */ @@ -396,6 +403,9 @@ void moz_gtk_get_arrow_size(GtkThemeWidgetType widgetType, gint* width, gint* height); +gint moz_gtk_get_entry_height(gint* height); +gint moz_gtk_get_button_height(gint* height); + /** * Get the desired size of a toolbar separator * size: [OUT] the desired width @@ -466,6 +476,12 @@ gboolean moz_gtk_images_in_buttons(void) */ gboolean moz_gtk_has_scrollbar_buttons(void); + +GtkStyleContext * +moz_gtk_style_create(GtkCssNode *node, GtkStyleContext *parent); + + + #ifdef __cplusplus } #endif /* __cplusplus */ diff -up firefox-46.0.1/widget/gtk/mozgtk/mozgtk.c.gtk3-20 firefox-46.0.1/widget/gtk/mozgtk/mozgtk.c --- firefox-46.0.1/widget/gtk/mozgtk/mozgtk.c.gtk3-20 2016-05-03 07:31:12.000000000 +0200 +++ firefox-46.0.1/widget/gtk/mozgtk/mozgtk.c 2016-05-20 10:40:19.442320669 +0200 @@ -504,6 +504,11 @@ STUB(gtk_window_set_type_hint) STUB(gtk_window_set_wmclass) STUB(gtk_window_unfullscreen) STUB(gtk_window_unmaximize) +STUB(gtk_widget_get_preferred_height_and_baseline_for_width) +STUB(gtk_entry_get_text_area) +STUB(gtk_check_menu_item_get_type) +STUB(gtk_spin_button_get_type) +STUB(gtk_button_get_type) #endif #ifdef GTK3_SYMBOLS @@ -581,6 +586,14 @@ STUB(gtk_color_chooser_get_type) STUB(gtk_color_chooser_set_rgba) STUB(gtk_color_chooser_get_rgba) STUB(gtk_color_chooser_set_use_alpha) +STUB(gtk_style_context_get_path) +STUB(gtk_widget_path_copy) +STUB(gtk_widget_path_iter_set_object_name) +STUB(gtk_widget_path_iter_add_class) +STUB(gtk_widget_path_iter_get_state) +STUB(gtk_style_context_set_parent) +STUB(gtk_widget_path_unref) +STUB(gtk_tooltip_get_type) #endif #ifdef GTK2_SYMBOLS diff -up firefox-46.0.1/widget/gtk/nsLookAndFeel.cpp.gtk3-20 firefox-46.0.1/widget/gtk/nsLookAndFeel.cpp --- firefox-46.0.1/widget/gtk/nsLookAndFeel.cpp.gtk3-20 2016-05-03 07:31:12.000000000 +0200 +++ firefox-46.0.1/widget/gtk/nsLookAndFeel.cpp 2016-05-20 13:53:54.085049707 +0200 @@ -353,14 +353,18 @@ nsLookAndFeel::NativeGetColor(ColorID aI case eColorID_activeborder: // active window border gtk_style_context_get_border_color(mBackgroundStyle, - GTK_STATE_FLAG_NORMAL, &gdk_color); + gtk_style_context_get_state(mBackgroundStyle), + &gdk_color); aColor = GDK_RGBA_TO_NS_RGBA(gdk_color); break; case eColorID_inactiveborder: // inactive window border + gtk_style_context_save(mBackgroundStyle); + gtk_style_context_set_state(mBackgroundStyle, GTK_STATE_FLAG_INSENSITIVE); gtk_style_context_get_border_color(mBackgroundStyle, - GTK_STATE_FLAG_INSENSITIVE, + gtk_style_context_get_state(mBackgroundStyle), &gdk_color); + gtk_style_context_restore(mBackgroundStyle); aColor = GDK_RGBA_TO_NS_RGBA(gdk_color); break; case eColorID_graytext: // disabled text in windows, menus, etc. @@ -369,9 +373,12 @@ nsLookAndFeel::NativeGetColor(ColorID aI break; case eColorID_inactivecaption: // inactive window caption + gtk_style_context_save(mBackgroundStyle); + gtk_style_context_set_state(mBackgroundStyle, GTK_STATE_FLAG_INSENSITIVE); gtk_style_context_get_background_color(mBackgroundStyle, - GTK_STATE_FLAG_INSENSITIVE, + gtk_style_context_get_state(mBackgroundStyle), &gdk_color); + gtk_style_context_restore(mBackgroundStyle); aColor = GDK_RGBA_TO_NS_RGBA(gdk_color); break; #endif @@ -497,13 +504,17 @@ nsLookAndFeel::NativeGetColor(ColorID aI case eColorID__moz_buttondefault: // default button border color gtk_style_context_get_border_color(mButtonStyle, - GTK_STATE_FLAG_NORMAL, &gdk_color); + gtk_style_context_get_state(mButtonStyle), + &gdk_color); aColor = GDK_RGBA_TO_NS_RGBA(gdk_color); break; case eColorID__moz_buttonhoverface: + gtk_style_context_save(mButtonStyle); + gtk_style_context_set_state(mButtonStyle, GTK_STATE_FLAG_PRELIGHT); gtk_style_context_get_background_color(mButtonStyle, - GTK_STATE_FLAG_PRELIGHT, + gtk_style_context_get_state(mButtonStyle), &gdk_color); + gtk_style_context_restore(mButtonStyle); aColor = GDK_RGBA_TO_NS_RGBA(gdk_color); break; case eColorID__moz_buttonhovertext: @@ -1110,27 +1126,29 @@ nsLookAndFeel::Init() style = create_context(path); gtk_style_context_add_class(style, GTK_STYLE_CLASS_SCROLLBAR); gtk_style_context_add_class(style, GTK_STYLE_CLASS_TROUGH); - gtk_style_context_get_background_color(style, GTK_STATE_FLAG_NORMAL, &color); + gtk_style_context_get_background_color(style, gtk_style_context_get_state(style), &color); sMozScrollbar = GDK_RGBA_TO_NS_RGBA(color); g_object_unref(style); // Window colors style = create_context(path); - gtk_style_context_save(style); gtk_style_context_add_class(style, GTK_STYLE_CLASS_BACKGROUND); - gtk_style_context_get_background_color(style, GTK_STATE_FLAG_NORMAL, &color); + gtk_style_context_get_background_color(style, gtk_style_context_get_state(style), &color); sMozWindowBackground = GDK_RGBA_TO_NS_RGBA(color); - gtk_style_context_get_color(style, GTK_STATE_FLAG_NORMAL, &color); + gtk_style_context_get_color(style, gtk_style_context_get_state(style), &color); sMozWindowText = GDK_RGBA_TO_NS_RGBA(color); - gtk_style_context_restore(style); + g_object_unref(style); // tooltip foreground and background - gtk_style_context_add_class(style, GTK_STYLE_CLASS_TOOLTIP); + GtkCssNode tooltipPath[] = { + { GTK_TYPE_TOOLTIP, "tooltip", NULL, NULL}, + }; + style = moz_gtk_style_create(tooltipPath, NULL); + gtk_style_context_get_color(style, gtk_style_context_get_state(style), &color); + sInfoText = GDK_RGBA_TO_NS_RGBA(color); gtk_style_context_add_class(style, GTK_STYLE_CLASS_BACKGROUND); - gtk_style_context_get_background_color(style, GTK_STATE_FLAG_NORMAL, &color); + gtk_style_context_get_background_color(style, gtk_style_context_get_state(style), &color); sInfoBackground = GDK_RGBA_TO_NS_RGBA(color); - gtk_style_context_get_color(style, GTK_STATE_FLAG_NORMAL, &color); - sInfoText = GDK_RGBA_TO_NS_RGBA(color); g_object_unref(style); // menu foreground & menu background @@ -1144,20 +1162,26 @@ nsLookAndFeel::Init() gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); style = gtk_widget_get_style_context(accel_label); - gtk_style_context_get_color(style, GTK_STATE_FLAG_NORMAL, &color); + gtk_style_context_get_color(style, gtk_style_context_get_state(style), &color); sMenuText = GDK_RGBA_TO_NS_RGBA(color); - gtk_style_context_get_color(style, GTK_STATE_FLAG_INSENSITIVE, &color); + gtk_style_context_save(style); + gtk_style_context_set_state(style, GTK_STATE_FLAG_INSENSITIVE); + gtk_style_context_get_color(style, gtk_style_context_get_state(style), &color); sMenuTextInactive = GDK_RGBA_TO_NS_RGBA(color); + gtk_style_context_restore(style); style = gtk_widget_get_style_context(menu); - gtk_style_context_get_background_color(style, GTK_STATE_FLAG_NORMAL, &color); + gtk_style_context_get_background_color(style, gtk_style_context_get_state(style), &color); sMenuBackground = GDK_RGBA_TO_NS_RGBA(color); style = gtk_widget_get_style_context(menuitem); - gtk_style_context_get_background_color(style, GTK_STATE_FLAG_PRELIGHT, &color); + gtk_style_context_save(style); + gtk_style_context_set_state(style, GTK_STATE_FLAG_PRELIGHT); + gtk_style_context_get_background_color(style, gtk_style_context_get_state(style), &color); sMenuHover = GDK_RGBA_TO_NS_RGBA(color); - gtk_style_context_get_color(style, GTK_STATE_FLAG_PRELIGHT, &color); + gtk_style_context_get_color(style, gtk_style_context_get_state(style), &color); sMenuHoverText = GDK_RGBA_TO_NS_RGBA(color); + gtk_style_context_restore(style); g_object_unref(menu); #endif @@ -1266,44 +1290,54 @@ nsLookAndFeel::Init() GDK_COLOR_TO_NS_RGB(style->dark[GTK_STATE_NORMAL]); } #else + GtkCssNode labelPath[] = { + { GTK_TYPE_LABEL, "label", "view", NULL }, + { G_TYPE_NONE, "selection", NULL, NULL } + }; + + GtkStyleContext *styleLabel; + GtkStyleContext *styleSelection; + GtkBorder padding; + // Text colors - style = gtk_widget_get_style_context(textView); - gtk_style_context_save(style); - gtk_style_context_add_class(style, GTK_STYLE_CLASS_VIEW); - gtk_style_context_get_background_color(style, GTK_STATE_FLAG_NORMAL, &color); + styleLabel = moz_gtk_style_create(labelPath, NULL); + styleSelection = moz_gtk_style_create(labelPath+1, styleLabel); + + gtk_style_context_get_background_color(styleLabel, gtk_style_context_get_state(styleLabel), &color); sMozFieldBackground = GDK_RGBA_TO_NS_RGBA(color); - gtk_style_context_get_color(style, GTK_STATE_FLAG_NORMAL, &color); + gtk_style_context_get_color(styleLabel, gtk_style_context_get_state(styleLabel), &color); sMozFieldText = GDK_RGBA_TO_NS_RGBA(color); // Selected text and background - gtk_style_context_get_background_color(style, - static_cast(GTK_STATE_FLAG_FOCUSED|GTK_STATE_FLAG_SELECTED), - &color); + gtk_style_context_get_background_color(styleSelection, gtk_style_context_get_state(styleSelection), &color); sTextSelectedBackground = GDK_RGBA_TO_NS_RGBA(color); - gtk_style_context_get_color(style, - static_cast(GTK_STATE_FLAG_FOCUSED|GTK_STATE_FLAG_SELECTED), - &color); + gtk_style_context_get_color(styleSelection, gtk_style_context_get_state(styleSelection), &color); sTextSelectedText = GDK_RGBA_TO_NS_RGBA(color); - gtk_style_context_restore(style); // Button text, background, border style = gtk_widget_get_style_context(label); - gtk_style_context_get_color(style, GTK_STATE_FLAG_NORMAL, &color); + gtk_style_context_get_color(style, gtk_style_context_get_state(style), &color); sButtonText = GDK_RGBA_TO_NS_RGBA(color); - gtk_style_context_get_color(style, GTK_STATE_FLAG_PRELIGHT, &color); + gtk_style_context_save(style); + gtk_style_context_set_state(style, GTK_STATE_FLAG_PRELIGHT); + gtk_style_context_get_color(style, gtk_style_context_get_state(style), &color); sButtonHoverText = GDK_RGBA_TO_NS_RGBA(color); + gtk_style_context_restore(style); // Combobox text color style = gtk_widget_get_style_context(comboboxLabel); - gtk_style_context_get_color(style, GTK_STATE_FLAG_NORMAL, &color); + gtk_style_context_get_color(style, gtk_style_context_get_state(style), &color); sComboBoxText = GDK_RGBA_TO_NS_RGBA(color); // Menubar text and hover text colors style = gtk_widget_get_style_context(menuBar); - gtk_style_context_get_color(style, GTK_STATE_FLAG_NORMAL, &color); + gtk_style_context_get_color(style, gtk_style_context_get_state(style), &color); sMenuBarText = GDK_RGBA_TO_NS_RGBA(color); - gtk_style_context_get_color(style, GTK_STATE_FLAG_PRELIGHT, &color); + gtk_style_context_save(style); + gtk_style_context_set_state(style, GTK_STATE_FLAG_PRELIGHT); + gtk_style_context_get_color(style, gtk_style_context_get_state(style), &color); sMenuBarHoverText = GDK_RGBA_TO_NS_RGBA(color); + gtk_style_context_restore(style); // GTK's guide to fancy odd row background colors: // 1) Check if a theme explicitly defines an odd row color @@ -1316,7 +1350,7 @@ nsLookAndFeel::Init() // Get odd row background color gtk_style_context_save(style); gtk_style_context_add_region(style, GTK_STYLE_REGION_ROW, GTK_REGION_ODD); - gtk_style_context_get_background_color(style, GTK_STATE_FLAG_NORMAL, &color); + gtk_style_context_get_background_color(style, gtk_style_context_get_state(style), &color); sOddCellBackground = GDK_RGBA_TO_NS_RGBA(color); gtk_style_context_restore(style); @@ -1334,9 +1368,11 @@ nsLookAndFeel::Init() gtk_container_add(GTK_CONTAINER(parent), infoBar); gtk_container_add(GTK_CONTAINER(infoBarContent), infoBarLabel); style = gtk_widget_get_style_context(infoBarLabel); + gtk_style_context_save(style); gtk_style_context_add_class(style, GTK_STYLE_CLASS_INFO); - gtk_style_context_get_color(style, GTK_STATE_FLAG_NORMAL, &color); + gtk_style_context_get_color(style, gtk_style_context_get_state(style), &color); sInfoBarText = GDK_RGBA_TO_NS_RGBA(color); + gtk_style_context_restore(style); #endif // Some themes have a unified menu bar, and support window dragging on it gboolean supports_menubar_drag = FALSE; diff -up firefox-46.0.1/widget/gtk/nsNativeThemeGTK.cpp.gtk3-20 firefox-46.0.1/widget/gtk/nsNativeThemeGTK.cpp --- firefox-46.0.1/widget/gtk/nsNativeThemeGTK.cpp.gtk3-20 2016-05-03 07:31:12.000000000 +0200 +++ firefox-46.0.1/widget/gtk/nsNativeThemeGTK.cpp 2016-05-19 15:20:11.658519202 +0200 @@ -1567,9 +1567,6 @@ nsNativeThemeGTK::GetMinimumWidgetSize(n case NS_THEME_RADIO_CONTAINER: case NS_THEME_CHECKBOX_LABEL: case NS_THEME_RADIO_LABEL: - case NS_THEME_BUTTON: - case NS_THEME_DROPDOWN: - case NS_THEME_TOOLBAR_BUTTON: case NS_THEME_TREEVIEW_HEADER_CELL: { if (aWidgetType == NS_THEME_DROPDOWN) { @@ -1588,6 +1585,21 @@ nsNativeThemeGTK::GetMinimumWidgetSize(n aResult->height += border.top + border.bottom; } break; + case NS_THEME_BUTTON: + case NS_THEME_DROPDOWN: + case NS_THEME_TOOLBAR_BUTTON: + { + moz_gtk_get_button_height(&aResult->height); + } + break; + case NS_THEME_FOCUS_OUTLINE: + case NS_THEME_NUMBER_INPUT: + case NS_THEME_TEXTFIELD: + case NS_THEME_TEXTFIELD_MULTILINE: + { + moz_gtk_get_entry_height(&aResult->height); + } + break; case NS_THEME_TOOLBAR_SEPARATOR: { gint separator_width;