# HG changeset patch # User Martin Stransky # Parent 0850966fdb761c309032575cbc6748a27d794983 Bug 1073117 - Theme issues with GTK 3.14 - fix gtk button and entry size, r=?karlt Inner borders and focus theming has been removed in Gtk 3.14 so we can't use them to calculate button size. The size should be computed as border + padding. diff --git a/widget/gtk/gtk2drawing.c b/widget/gtk/gtk2drawing.c --- a/widget/gtk/gtk2drawing.c +++ b/widget/gtk/gtk2drawing.c @@ -826,17 +826,17 @@ moz_gtk_get_focus_outline_size(gint* foc *focus_v_width = YTHICKNESS(gEntryWidget->style) + focus_width; } else { *focus_h_width = focus_width; *focus_v_width = focus_width; } return MOZ_GTK_SUCCESS; } -gint +static gint moz_gtk_widget_get_focus(GtkWidget* widget, gboolean* interior_focus, gint* focus_width, gint* focus_pad) { gtk_widget_style_get (widget, "interior-focus", interior_focus, "focus-line-width", focus_width, "focus-padding", focus_pad, NULL); @@ -923,17 +923,17 @@ moz_gtk_splitter_get_metrics(gint orient gtk_widget_style_get(gHPanedWidget, "handle_size", size, NULL); } else { ensure_vpaned_widget(); gtk_widget_style_get(gVPanedWidget, "handle_size", size, NULL); } return MOZ_GTK_SUCCESS; } -gint +static 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; gtk_widget_style_get (widget, "inner-border", &tmp_border, NULL); if (tmp_border) { diff --git a/widget/gtk/gtk3drawing.c b/widget/gtk/gtk3drawing.c --- a/widget/gtk/gtk3drawing.c +++ b/widget/gtk/gtk3drawing.c @@ -756,48 +756,28 @@ moz_gtk_radio_get_metrics(gint* indicato "indicator_spacing", indicator_spacing, NULL); return MOZ_GTK_SUCCESS; } gint moz_gtk_get_focus_outline_size(gint* focus_h_width, gint* focus_v_width) -{ - gboolean interior_focus; - gint focus_width = 0; +{ + GtkBorder border; + GtkBorder padding; + GtkStyleContext *style; ensure_entry_widget(); - gtk_widget_style_get(gEntryWidget, - "interior-focus", &interior_focus, - "focus-line-width", &focus_width, - NULL); - if (interior_focus) { - GtkBorder border; - GtkStyleContext *style = gtk_widget_get_style_context(gEntryWidget); - gtk_style_context_get_border(style, 0, &border); - *focus_h_width = border.left + focus_width; - *focus_v_width = border.top + focus_width; - } else { - *focus_h_width = focus_width; - *focus_v_width = focus_width; - } - return MOZ_GTK_SUCCESS; -} - -gint -moz_gtk_widget_get_focus(GtkWidget* widget, gboolean* interior_focus, - gint* focus_width, gint* focus_pad) -{ - gtk_widget_style_get (widget, - "interior-focus", interior_focus, - "focus-line-width", focus_width, - "focus-padding", focus_pad, - NULL); - + style = gtk_widget_get_style_context(gEntryWidget); + + gtk_style_context_get_border(style, 0, &border); + gtk_style_context_get_padding(style, 0, &padding); + *focus_h_width = border.left + padding.left; + *focus_v_width = border.top + padding.top; return MOZ_GTK_SUCCESS; } gint moz_gtk_menuitem_get_horizontal_padding(gint* horizontal_padding) { ensure_menu_item_widget(); @@ -875,34 +855,16 @@ moz_gtk_splitter_get_metrics(gint orient gtk_widget_style_get(gHPanedWidget, "handle_size", size, NULL); } else { ensure_vpaned_widget(); gtk_widget_style_get(gVPanedWidget, "handle_size", size, NULL); } 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; - - 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_button_paint(cairo_t *cr, GdkRectangle* rect, GtkWidgetState* state, GtkReliefStyle relief, GtkWidget* widget, GtkTextDirection direction) { GtkStateFlags state_flags = GetStateFlagsFromGtkWidgetState(state); GtkStyleContext* style = gtk_widget_get_style_context(widget); @@ -1032,43 +994,33 @@ moz_gtk_toggle_paint(cairo_t *cr, GdkRec } static gint 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; GtkStyleContext* style; GtkBorder border; + GtkBorder padding = {0, 0, 0, 0}; style = gtk_widget_get_style_context(button); /* 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; - - gtk_style_context_get_border(style, 0, &border); - - inner_rect->x = rect->x + border.left + 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 + border.top + - focus_width + focus_pad; - inner_rect->width = MAX(1, rect->width - inner_border.left - - inner_border.right - (border.left + focus_pad + focus_width) * 2); - inner_rect->height = MAX(1, rect->height - inner_border.top - - inner_border.bottom - (border.top + focus_pad + focus_width) * 2); + gtk_style_context_get_border(style, 0, &border); + if (!ignore_focus) + gtk_style_context_get_padding(style, 0, &padding); + + inner_rect->x = rect->x + border.left + padding.left; + inner_rect->y = rect->y + padding.top + border.top; + inner_rect->width = MAX(1, rect->width - padding.left - + padding.right - border.left * 2); + inner_rect->height = MAX(1, rect->height - padding.top - + padding.bottom - border.top * 2); return MOZ_GTK_SUCCESS; } static gint calculate_arrow_rect(GtkWidget* arrow, GdkRectangle* rect, GdkRectangle* arrow_rect, GtkTextDirection direction) @@ -1427,29 +1379,22 @@ moz_gtk_vpaned_paint(cairo_t *cr, GdkRec // See gtk_entry_draw() for reference. static gint moz_gtk_entry_paint(cairo_t *cr, GdkRectangle* rect, GtkWidgetState* state, GtkWidget* widget, GtkTextDirection direction) { gint x = rect->x, y = rect->y, width = rect->width, height = rect->height; GtkStyleContext* style; - gboolean interior_focus; - gint focus_width; int draw_focus_outline_only = state->depressed; // NS_THEME_FOCUS_OUTLINE gtk_widget_set_direction(widget, direction); style = gtk_widget_get_style_context(widget); - gtk_widget_style_get(widget, - "interior-focus", &interior_focus, - "focus-line-width", &focus_width, - NULL); - if (draw_focus_outline_only) { // Inflate the given 'rect' with the focus outline size. gint h, v; moz_gtk_get_focus_outline_size(&h, &v); rect->x -= h; rect->width += 2 * h; rect->y -= v; rect->height += 2 * v; @@ -1471,40 +1416,27 @@ moz_gtk_entry_paint(cairo_t *cr, GdkRect /* 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. */ if (state->focused && !state->disabled) { /* This will get us the lit borders that focused textboxes enjoy on * some themes. */ gtk_style_context_set_state(style, GTK_STATE_FLAG_FOCUSED); - if (!interior_focus) { - /* Indent the border a little bit if we have exterior focus - (this is what GTK does to draw native entries) */ - x += focus_width; - y += focus_width; - width -= 2 * focus_width; - height -= 2 * focus_width; - } } if (state->disabled) { gtk_style_context_set_state(style, GTK_STATE_FLAG_INSENSITIVE); } if (!draw_focus_outline_only) { gtk_render_background(style, cr, x, y, width, height); } gtk_render_frame(style, cr, x, y, width, height); - if (state->focused && !state->disabled) { - if (!interior_focus) { - gtk_render_focus(style, cr, rect->x, rect->y, rect->width, rect->height); - } - } gtk_style_context_restore(style); return MOZ_GTK_SUCCESS; } static gint moz_gtk_treeview_paint(cairo_t *cr, GdkRectangle* rect, GtkWidgetState* state, @@ -1799,56 +1731,48 @@ moz_gtk_combo_box_entry_button_paint(cai static gint moz_gtk_container_paint(cairo_t *cr, GdkRectangle* rect, GtkWidgetState* state, gboolean isradio, GtkTextDirection direction) { GtkStateFlags state_flags = GetStateFlagsFromGtkWidgetState(state); GtkStyleContext* style; GtkWidget *widget; - gboolean interior_focus; - gint focus_width, focus_pad; if (isradio) { ensure_radiobutton_widget(); widget = gRadiobuttonWidget; } else { ensure_checkbox_widget(); widget = gCheckboxWidget; } gtk_widget_set_direction(widget, direction); style = gtk_widget_get_style_context(widget); gtk_style_context_save(style); - moz_gtk_widget_get_focus(widget, &interior_focus, &focus_width, &focus_pad); gtk_style_context_set_state(style, state_flags); /* this is for drawing a prelight box */ if (state_flags & GTK_STATE_FLAG_PRELIGHT) { gtk_render_background(style, cr, rect->x, rect->y, rect->width, rect->height); } - if (state->focused && !interior_focus) { - gtk_render_focus(style, cr, - rect->x, rect->y, rect->width, rect->height); - } gtk_style_context_restore(style); return MOZ_GTK_SUCCESS; } static gint moz_gtk_toggle_label_paint(cairo_t *cr, GdkRectangle* rect, GtkWidgetState* state, gboolean isradio, GtkTextDirection direction) { GtkStyleContext *style; GtkWidget *widget; - gboolean interior_focus; if (!state->focused) return MOZ_GTK_SUCCESS; if (isradio) { ensure_radiobutton_widget(); widget = gRadiobuttonWidget; } else { @@ -1859,20 +1783,16 @@ moz_gtk_toggle_label_paint(cairo_t *cr, 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); } gtk_widget_set_direction(widget, direction); - gtk_widget_style_get(widget, "interior-focus", &interior_focus, NULL); - if (!interior_focus) - return MOZ_GTK_SUCCESS; - gtk_style_context_set_state(style, GetStateFlagsFromGtkWidgetState(state)); gtk_render_focus(style, cr, rect->x, rect->y, rect->width, rect->height); gtk_style_context_restore(style); return MOZ_GTK_SUCCESS; } @@ -2660,44 +2580,42 @@ moz_gtk_get_widget_border(GtkThemeWidget { GtkWidget* w; GtkStyleContext* style; *left = *top = *right = *bottom = 0; switch (widget) { case MOZ_GTK_BUTTON: { - GtkBorder inner_border; - gboolean interior_focus; - gint focus_width, focus_pad; - ensure_button_widget(); + style = gtk_widget_get_style_context(gButtonWidget); + *left = *top = *right = *bottom = gtk_container_get_border_width(GTK_CONTAINER(gButtonWidget)); /* Don't add this padding in HTML, otherwise the buttons will become too big and stuff the layout. */ if (!inhtml) { - moz_gtk_widget_get_focus(gButtonWidget, &interior_focus, &focus_width, &focus_pad); - 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; + moz_gtk_add_style_padding(style, left, top, right, bottom); } - moz_gtk_add_style_border(gtk_widget_get_style_context(gButtonWidget), - left, top, right, bottom); + moz_gtk_add_style_border(style, left, top, right, bottom); return MOZ_GTK_SUCCESS; } case MOZ_GTK_ENTRY: { ensure_entry_widget(); style = gtk_widget_get_style_context(gEntryWidget); moz_gtk_add_style_border(style, left, top, right, bottom); - moz_gtk_add_style_padding(style, left, top, right, bottom); + + /* Use the document padding in HTML + and GTK style padding in XUL. */ + if (!inhtml) { + moz_gtk_add_style_padding(style, left, top, right, bottom); + } + return MOZ_GTK_SUCCESS; } case MOZ_GTK_TREEVIEW: { ensure_scrolled_window_widget(); style = gtk_widget_get_style_context(gScrolledWindowWidget); gtk_style_context_save(style); gtk_style_context_add_class(style, GTK_STYLE_CLASS_FRAME); @@ -2707,33 +2625,25 @@ moz_gtk_get_widget_border(GtkThemeWidget } case MOZ_GTK_TREE_HEADER_CELL: { /* A Tree Header in GTK is just a different styled button * It must be placed in a TreeView for getting the correct style * assigned. * That is why the following code is the same as for MOZ_GTK_BUTTON. * */ - - GtkBorder inner_border; - gboolean interior_focus; - gint focus_width, focus_pad; + GtkStyleContext *style; ensure_tree_header_cell_widget(); *left = *top = *right = *bottom = gtk_container_get_border_width(GTK_CONTAINER(gTreeHeaderCellWidget)); - 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; - - moz_gtk_add_style_border(gtk_widget_get_style_context(gTreeHeaderCellWidget), - left, top, right, bottom); + style = gtk_widget_get_style_context(gTreeHeaderCellWidget); + + moz_gtk_add_style_border(style, left, top, right, bottom); + moz_gtk_add_style_padding(style, left, top, right, bottom); return MOZ_GTK_SUCCESS; } case MOZ_GTK_TREE_HEADER_SORTARROW: ensure_tree_header_cell_widget(); w = gTreeHeaderSortArrowWidget; break; case MOZ_GTK_DROPDOWN_ENTRY: ensure_combo_box_entry_widgets(); @@ -2743,39 +2653,33 @@ moz_gtk_get_widget_border(GtkThemeWidget 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 ignored_interior_focus, wide_separators; - gint focus_width, focus_pad, separator_width; + gboolean wide_separators; + gint separator_width; GtkRequisition arrow_req; GtkBorder border; ensure_combo_box_widgets(); - *left = gtk_container_get_border_width(GTK_CONTAINER(gComboBoxButtonWidget)); + *left = *top = *right = *bottom = + gtk_container_get_border_width(GTK_CONTAINER(gComboBoxButtonWidget)); + + style = gtk_widget_get_style_context(gComboBoxButtonWidget); if (!inhtml) { - moz_gtk_widget_get_focus(gComboBoxButtonWidget, - &ignored_interior_focus, - &focus_width, &focus_pad); - *left += focus_width + focus_pad; + moz_gtk_add_style_padding(style, left, top, right, bottom); } - style = gtk_widget_get_style_context(gComboBoxButtonWidget); - gtk_style_context_get_border(style, 0, &border); - - *top = *left + border.top; - *left += border.left; - - *right = *left; *bottom = *top; + moz_gtk_add_style_border(style, left, top, right, bottom); /* If there is no separator, don't try to count its width. */ separator_width = 0; if (gComboBoxSeparatorWidget) { gtk_widget_style_get(gComboBoxSeparatorWidget, "wide-separators", &wide_separators, "separator-width", &separator_width, NULL); @@ -2817,70 +2721,33 @@ moz_gtk_get_widget_border(GtkThemeWidget case MOZ_GTK_SCALE_VERTICAL: ensure_scale_widget(); w = gVScaleWidget; break; case MOZ_GTK_FRAME: ensure_frame_widget(); w = gFrameWidget; break; - case MOZ_GTK_CHECKBUTTON_LABEL: - case MOZ_GTK_RADIOBUTTON_LABEL: - { - gboolean interior_focus; - gint focus_width, focus_pad; - - /* If the focus is interior, then the label has a border of - (focus_width + focus_pad). */ - if (widget == MOZ_GTK_CHECKBUTTON_LABEL) { - ensure_checkbox_widget(); - moz_gtk_widget_get_focus(gCheckboxWidget, &interior_focus, - &focus_width, &focus_pad); - } - else { - ensure_radiobutton_widget(); - moz_gtk_widget_get_focus(gRadiobuttonWidget, &interior_focus, - &focus_width, &focus_pad); - } - - if (interior_focus) - *left = *top = *right = *bottom = (focus_width + focus_pad); - - return MOZ_GTK_SUCCESS; - } - case MOZ_GTK_CHECKBUTTON_CONTAINER: case MOZ_GTK_RADIOBUTTON_CONTAINER: { - gboolean interior_focus; - gint focus_width, focus_pad; - - /* If the focus is _not_ interior, then the container has a border - of (focus_width + focus_pad). */ if (widget == MOZ_GTK_CHECKBUTTON_CONTAINER) { ensure_checkbox_widget(); - moz_gtk_widget_get_focus(gCheckboxWidget, &interior_focus, - &focus_width, &focus_pad); w = gCheckboxWidget; } else { ensure_radiobutton_widget(); - moz_gtk_widget_get_focus(gRadiobuttonWidget, &interior_focus, - &focus_width, &focus_pad); w = gRadiobuttonWidget; } + style = gtk_widget_get_style_context(w); *left = *top = *right = *bottom = gtk_container_get_border_width(GTK_CONTAINER(w)); - - if (!interior_focus) { - *left += (focus_width + focus_pad); - *right += (focus_width + focus_pad); - *top += (focus_width + focus_pad); - *bottom += (focus_width + focus_pad); - } - + moz_gtk_add_style_border(style, + left, top, right, bottom); + moz_gtk_add_style_padding(style, + left, top, right, bottom); return MOZ_GTK_SUCCESS; } case MOZ_GTK_MENUPOPUP: ensure_menu_popup_widget(); w = gMenuPopupWidget; break; case MOZ_GTK_MENUITEM: case MOZ_GTK_CHECKMENUITEM: @@ -2897,16 +2764,18 @@ moz_gtk_get_widget_border(GtkThemeWidget } *left = *top = *right = *bottom = gtk_container_get_border_width(GTK_CONTAINER(w)); moz_gtk_add_style_padding(gtk_widget_get_style_context(w), left, top, right, bottom); return MOZ_GTK_SUCCESS; } /* These widgets have no borders, since they are not containers. */ + case MOZ_GTK_CHECKBUTTON_LABEL: + case MOZ_GTK_RADIOBUTTON_LABEL: case MOZ_GTK_SPLITTER_HORIZONTAL: case MOZ_GTK_SPLITTER_VERTICAL: case MOZ_GTK_CHECKBUTTON: case MOZ_GTK_RADIOBUTTON: case MOZ_GTK_SCROLLBAR_BUTTON: case MOZ_GTK_SCROLLBAR_TRACK_HORIZONTAL: case MOZ_GTK_SCROLLBAR_TRACK_VERTICAL: case MOZ_GTK_SCROLLBAR_THUMB_HORIZONTAL: diff --git a/widget/gtk/gtkdrawing.h b/widget/gtk/gtkdrawing.h --- a/widget/gtk/gtkdrawing.h +++ b/widget/gtk/gtkdrawing.h @@ -288,49 +288,26 @@ moz_gtk_checkbox_get_metrics(gint* indic * indicator_spacing: [OUT] the spacing between the indicator and its * container * * returns: MOZ_GTK_SUCCESS if there was no error, an error code otherwise */ gint moz_gtk_radio_get_metrics(gint* indicator_size, gint* indicator_spacing); -/** - * Get the inner-border value for a GtkButton widget (button or tree header) - * widget: [IN] the widget to get the border value for - * inner_border: [OUT] the inner border - * - * returns: MOZ_GTK_SUCCESS if there was no error, an error code otherwise - */ -gint -moz_gtk_button_get_inner_border(GtkWidget* widget, GtkBorder* inner_border); - /** Get the extra size for the focus ring for outline:auto. * widget: [IN] the widget to get the focus metrics for * focus_h_width: [OUT] the horizontal width * focus_v_width: [OUT] the vertical width * * returns: MOZ_GTK_SUCCESS */ gint moz_gtk_get_focus_outline_size(gint* focus_h_width, gint* focus_v_width); -/** Get the focus metrics for a treeheadercell, button, checkbox, or radio button. - * widget: [IN] the widget to get the focus metrics for - * interior_focus: [OUT] whether the focus is drawn around the - * label (TRUE) or around the whole container (FALSE) - * focus_width: [OUT] the width of the focus line - * focus_pad: [OUT] the padding between the focus line and children - * - * returns: MOZ_GTK_SUCCESS if there was no error, an error code otherwise - */ -gint -moz_gtk_widget_get_focus(GtkWidget* widget, gboolean* interior_focus, - gint* focus_width, gint* focus_pad); - /** Get the horizontal padding for the menuitem widget or checkmenuitem widget. * horizontal_padding: [OUT] The left and right padding of the menuitem or checkmenuitem * * returns: MOZ_GTK_SUCCESS if there was no error, an error code otherwise */ gint moz_gtk_menuitem_get_horizontal_padding(gint* horizontal_padding);