firefox/widget-rebase.patch

3963 lines
154 KiB
Diff
Raw Normal View History

diff -up firefox-50.0/widget/gtk/gtk3drawing.cpp.widget-rebase firefox-50.0/widget/gtk/gtk3drawing.cpp
--- firefox-50.0/widget/gtk/gtk3drawing.cpp.widget-rebase 2016-10-31 21:15:38.000000000 +0100
+++ firefox-50.0/widget/gtk/gtk3drawing.cpp 2016-11-24 11:57:52.033064782 +0100
@@ -18,27 +18,6 @@
#include <math.h>
-static GtkWidget* gProtoLayout;
-static GtkWidget* gHScaleWidget;
-static GtkWidget* gVScaleWidget;
-static GtkWidget* gComboBoxWidget;
-static GtkWidget* gComboBoxButtonWidget;
-static GtkWidget* gComboBoxArrowWidget;
-static GtkWidget* gComboBoxSeparatorWidget;
-static GtkWidget* gComboBoxEntryWidget;
-static GtkWidget* gComboBoxEntryTextareaWidget;
-static GtkWidget* gComboBoxEntryButtonWidget;
-static GtkWidget* gComboBoxEntryArrowWidget;
-static GtkWidget* gTabWidget;
-static GtkWidget* gImageMenuItemWidget;
-static GtkWidget* gCheckMenuItemWidget;
-static GtkWidget* gTreeViewWidget;
-static GtkTreeViewColumn* gMiddleTreeViewColumn;
-static GtkWidget* gTreeHeaderCellWidget;
-static GtkWidget* gTreeHeaderSortArrowWidget;
-static GtkWidget* gHPanedWidget;
-static GtkWidget* gVPanedWidget;
-
static style_prop_t style_prop_func;
static gboolean have_arrow_scaling;
static gboolean checkbox_check_state;
@@ -54,6 +33,13 @@ static gboolean is_initialized;
#define GTK_STATE_FLAG_CHECKED (1 << 11)
#endif
+static gint
+moz_gtk_get_tab_thickness(GtkStyleContext *style);
+
+static gint
+moz_gtk_menu_item_paint(WidgetNodeType widget, cairo_t *cr, GdkRectangle* rect,
+ GtkWidgetState* state, GtkTextDirection direction);
+
static GtkStateFlags
GetStateFlagsFromGtkWidgetState(GtkWidgetState* state)
{
@@ -73,338 +59,17 @@ GetStateFlagsFromGtkWidgetState(GtkWidge
return stateFlags;
}
-gint
-moz_gtk_enable_style_props(style_prop_t styleGetProp)
-{
- style_prop_func = styleGetProp;
- return MOZ_GTK_SUCCESS;
-}
-
-static gint
-setup_widget_prototype(GtkWidget* widget)
-{
- if (!gProtoLayout) {
- gProtoLayout = GetWidget(MOZ_GTK_WINDOW_CONTAINER);
- }
- gtk_container_add(GTK_CONTAINER(gProtoLayout), widget);
- return MOZ_GTK_SUCCESS;
-}
-
-static gint
-ensure_hpaned_widget()
-{
- if (!gHPanedWidget) {
- gHPanedWidget = gtk_paned_new(GTK_ORIENTATION_HORIZONTAL);
- setup_widget_prototype(gHPanedWidget);
- }
- return MOZ_GTK_SUCCESS;
-}
-
-static gint
-ensure_vpaned_widget()
-{
- if (!gVPanedWidget) {
- gVPanedWidget = gtk_paned_new(GTK_ORIENTATION_VERTICAL);
- setup_widget_prototype(gVPanedWidget);
- }
- return MOZ_GTK_SUCCESS;
-}
-
-static gint
-ensure_scale_widget()
-{
- if (!gHScaleWidget) {
- gHScaleWidget = gtk_scale_new(GTK_ORIENTATION_HORIZONTAL, NULL);
- setup_widget_prototype(gHScaleWidget);
- }
- if (!gVScaleWidget) {
- gVScaleWidget = gtk_scale_new(GTK_ORIENTATION_VERTICAL, NULL);
- setup_widget_prototype(gVScaleWidget);
- }
- return MOZ_GTK_SUCCESS;
-}
-
-/* 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 gProtoLayout 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);
- }
-}
-
-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);
-}
-
-static gint
-ensure_combo_box_widgets()
-{
- 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_get_child(GTK_BIN(gComboBoxButtonWidget));
- if (GTK_IS_BOX(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);
- }
- } else {
- /* Shouldn't be reached with current internal gtk implementation; we
- * use a generic toggle button as last resort fallback to avoid
- * crashing. */
- gComboBoxButtonWidget = GetWidget(MOZ_GTK_TOGGLE_BUTTON);
- }
-
- if (!gComboBoxArrowWidget) {
- /* Shouldn't be reached with current internal gtk implementation;
- * we gButtonArrowWidget as last resort fallback to avoid
- * crashing. */
- gComboBoxArrowWidget = GetWidget(MOZ_GTK_BUTTON_ARROW);
- }
-
- /* 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 gProtoLayout and as
- * such GTK holds a strong reference to them. */
-static void
-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);
-}
-
-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);
- }
-}
-
-static gint
-ensure_combo_box_entry_widgets()
-{
- GtkWidget* buttonChild;
-
- if (gComboBoxEntryTextareaWidget &&
- gComboBoxEntryButtonWidget &&
- gComboBoxEntryArrowWidget)
- return MOZ_GTK_SUCCESS;
-
- /* Create a ComboBoxEntry if needed */
- if (!gComboBoxEntryWidget) {
- gComboBoxEntryWidget = gtk_combo_box_new_with_entry();
- setup_widget_prototype(gComboBoxEntryWidget);
- }
-
- /* Get its inner Entry and Button */
- gtk_container_forall(GTK_CONTAINER(gComboBoxEntryWidget),
- moz_gtk_get_combo_box_entry_inner_widgets,
- NULL);
-
- if (!gComboBoxEntryTextareaWidget) {
- gComboBoxEntryTextareaWidget = GetWidget(MOZ_GTK_ENTRY);
- }
-
- if (gComboBoxEntryButtonWidget) {
- /* Get the Arrow inside the Button */
- buttonChild = gtk_bin_get_child(GTK_BIN(gComboBoxEntryButtonWidget));
- if (GTK_IS_BOX(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_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);
- }
- } else {
- /* Shouldn't be reached with current internal gtk implementation;
- * we use a generic toggle button as last resort fallback to avoid
- * crashing. */
- gComboBoxEntryButtonWidget = GetWidget(MOZ_GTK_TOGGLE_BUTTON);
- }
-
- if (!gComboBoxEntryArrowWidget) {
- /* Shouldn't be reached with current internal gtk implementation;
- * we gButtonArrowWidget as last resort fallback to avoid
- * crashing. */
- gComboBoxEntryArrowWidget = GetWidget(MOZ_GTK_BUTTON_ARROW);
- }
-
- return MOZ_GTK_SUCCESS;
-}
-
-static gint
-ensure_tab_widget()
-{
- if (!gTabWidget) {
- gTabWidget = gtk_notebook_new();
- setup_widget_prototype(gTabWidget);
- }
- return MOZ_GTK_SUCCESS;
-}
-
-static gint
-ensure_image_menu_item_widget()
-{
- if (!gImageMenuItemWidget) {
- gImageMenuItemWidget = gtk_image_menu_item_new();
- gtk_menu_shell_append(GTK_MENU_SHELL(GetWidget(MOZ_GTK_MENUPOPUP)),
- gImageMenuItemWidget);
- gtk_widget_realize(gImageMenuItemWidget);
- }
- return MOZ_GTK_SUCCESS;
-}
-
-static gint
-ensure_check_menu_item_widget()
-{
- if (!gCheckMenuItemWidget) {
- gCheckMenuItemWidget = gtk_check_menu_item_new();
- gtk_menu_shell_append(GTK_MENU_SHELL(GetWidget(MOZ_GTK_MENUPOPUP)),
- gCheckMenuItemWidget);
- gtk_widget_realize(gCheckMenuItemWidget);
- }
- return MOZ_GTK_SUCCESS;
-}
-
-static gint
-ensure_tree_view_widget()
+static GtkStateFlags
+GetStateFlagsFromGtkTabFlags(GtkTabFlags flags)
{
- if (!gTreeViewWidget) {
- gTreeViewWidget = gtk_tree_view_new();
- setup_widget_prototype(gTreeViewWidget);
- }
- return MOZ_GTK_SUCCESS;
+ return ((flags & MOZ_GTK_TAB_SELECTED) == 0) ?
+ GTK_STATE_FLAG_NORMAL : GTK_STATE_FLAG_ACTIVE;
}
-static gint
-ensure_tree_header_cell_widget()
+gint
+moz_gtk_enable_style_props(style_prop_t styleGetProp)
{
- if(!gTreeHeaderCellWidget) {
- /*
- * 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;
-
- ensure_tree_view_widget();
-
- /* 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(gMiddleTreeViewColumn, "M");
- gtk_tree_view_append_column(GTK_TREE_VIEW(gTreeViewWidget),
- 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_get_button(gMiddleTreeViewColumn);
- /* TODO, but it can't be NULL */
- gTreeHeaderSortArrowWidget = gtk_button_new();
- }
+ style_prop_func = styleGetProp;
return MOZ_GTK_SUCCESS;
}
@@ -423,13 +88,17 @@ moz_gtk_init()
else
checkbox_check_state = GTK_STATE_FLAG_ACTIVE;
- if(!gtk_check_version(3, 12, 0)) {
- ensure_tab_widget();
- gtk_style_context_get_style(gtk_widget_get_style_context(gTabWidget),
+ if (gtk_check_version(3, 12, 0) == nullptr &&
+ gtk_check_version(3, 20, 0) != nullptr)
+ {
+ // Deprecated for Gtk >= 3.20+
+ GtkStyleContext *style = ClaimStyleContext(MOZ_GTK_TAB_TOP);
+ gtk_style_context_get_style(style,
"has-tab-gap", &notebook_has_tab_gap, NULL);
+ ReleaseStyleContext(style);
}
else {
- notebook_has_tab_gap = TRUE;
+ notebook_has_tab_gap = true;
}
return MOZ_GTK_SUCCESS;
@@ -455,16 +124,24 @@ moz_gtk_radio_get_metrics(gint* indicato
return MOZ_GTK_SUCCESS;
}
-gint
-moz_gtk_get_focus_outline_size(gint* focus_h_width, gint* focus_v_width)
+static gint
+moz_gtk_get_focus_outline_size(GtkStyleContext* style,
+ gint* focus_h_width, gint* focus_v_width)
{
GtkBorder border;
GtkBorder padding;
- GtkStyleContext *style = ClaimStyleContext(MOZ_GTK_ENTRY);
gtk_style_context_get_border(style, GTK_STATE_FLAG_NORMAL, &border);
gtk_style_context_get_padding(style, GTK_STATE_FLAG_NORMAL, &padding);
*focus_h_width = border.left + padding.left;
*focus_v_width = border.top + padding.top;
+ return MOZ_GTK_SUCCESS;
+}
+
+gint
+moz_gtk_get_focus_outline_size(gint* focus_h_width, gint* focus_v_width)
+{
+ GtkStyleContext *style = ClaimStyleContext(MOZ_GTK_ENTRY);
+ moz_gtk_get_focus_outline_size(style, focus_h_width, focus_v_width);
ReleaseStyleContext(style);
return MOZ_GTK_SUCCESS;
}
@@ -472,22 +149,22 @@ moz_gtk_get_focus_outline_size(gint* foc
gint
moz_gtk_menuitem_get_horizontal_padding(gint* horizontal_padding)
{
- gtk_widget_style_get(GetWidget(MOZ_GTK_MENUITEM),
- "horizontal-padding", horizontal_padding,
- nullptr);
-
+ GtkStyleContext *style = ClaimStyleContext(MOZ_GTK_MENUITEM);
+ gtk_style_context_get_style(style,
+ "horizontal-padding", horizontal_padding,
+ nullptr);
+ ReleaseStyleContext(style);
return MOZ_GTK_SUCCESS;
}
gint
moz_gtk_checkmenuitem_get_horizontal_padding(gint* horizontal_padding)
{
- ensure_check_menu_item_widget();
-
- gtk_style_context_get_style(gtk_widget_get_style_context(gCheckMenuItemWidget),
+ GtkStyleContext *style = ClaimStyleContext(MOZ_GTK_CHECKMENUITEM);
+ gtk_style_context_get_style(style,
"horizontal-padding", horizontal_padding,
- NULL);
-
+ nullptr);
+ ReleaseStyleContext(style);
return MOZ_GTK_SUCCESS;
}
@@ -543,15 +220,14 @@ moz_gtk_button_get_default_border(gint*
gint
moz_gtk_splitter_get_metrics(gint orientation, gint* size)
{
+ GtkStyleContext *style;
if (orientation == GTK_ORIENTATION_HORIZONTAL) {
- ensure_hpaned_widget();
- gtk_style_context_get_style(gtk_widget_get_style_context(gHPanedWidget),
- "handle_size", size, NULL);
+ style = ClaimStyleContext(MOZ_GTK_SPLITTER_HORIZONTAL);
} else {
- ensure_vpaned_widget();
- gtk_style_context_get_style(gtk_widget_get_style_context(gVPanedWidget),
- "handle_size", size, NULL);
+ style = ClaimStyleContext(MOZ_GTK_SPLITTER_VERTICAL);
}
+ gtk_style_context_get_style(style, "handle_size", size, NULL);
+ ReleaseStyleContext(style);
return MOZ_GTK_SUCCESS;
}
@@ -756,8 +432,66 @@ calculate_arrow_rect(GtkWidget* arrow, G
return MOZ_GTK_SUCCESS;
}
+void
+moz_gtk_get_widget_min_size(WidgetNodeType aGtkWidgetType, int* width,
+ int* height)
+{
+ GtkStyleContext* style = ClaimStyleContext(aGtkWidgetType);
+ GtkStateFlags state_flags = gtk_style_context_get_state(style);
+ gtk_style_context_get(style, state_flags,
+ "min-height", height,
+ "min-width", width,
+ nullptr);
+
+ GtkBorder border, padding, margin;
+ gtk_style_context_get_border(style, state_flags, &border);
+ gtk_style_context_get_padding(style, state_flags, &padding);
+ gtk_style_context_get_margin(style, state_flags, &margin);
+ ReleaseStyleContext(style);
+
+ *width += border.left + border.right + margin.left + margin.right +
+ padding.left + padding.right;
+ *height += border.top + border.bottom + margin.top + margin.bottom +
+ padding.top + padding.bottom;
+}
+
+static void
+Inset(GdkRectangle* rect, GtkBorder& aBorder)
+{
+ MOZ_ASSERT(rect);
+ rect->x += aBorder.left;
+ rect->y += aBorder.top;
+ rect->width -= aBorder.left + aBorder.right;
+ rect->height -= aBorder.top + aBorder.bottom;
+}
+
+// Inset a rectangle by the margins specified in a style context.
+static void
+InsetByMargin(GdkRectangle* rect, GtkStyleContext* style)
+{
+ MOZ_ASSERT(rect);
+ GtkBorder margin;
+
+ gtk_style_context_get_margin(style, gtk_style_context_get_state(style),
+ &margin);
+ Inset(rect, margin);
+}
+
+// Inset a rectangle by the border and padding specified in a style context.
+static void
+InsetByBorderPadding(GdkRectangle* rect, GtkStyleContext* style)
+{
+ GtkStateFlags state = gtk_style_context_get_state(style);
+ GtkBorder padding, border;
+
+ gtk_style_context_get_padding(style, state, &padding);
+ Inset(rect, padding);
+ gtk_style_context_get_border(style, state, &border);
+ Inset(rect, border);
+}
+
static gint
-moz_gtk_scrollbar_button_paint(cairo_t *cr, GdkRectangle* rect,
+moz_gtk_scrollbar_button_paint(cairo_t *cr, const GdkRectangle* aRect,
GtkWidgetState* state,
GtkScrollbarButtonFlags flags,
GtkTextDirection direction)
@@ -795,32 +529,38 @@ moz_gtk_scrollbar_button_paint(cairo_t *
gtk_style_context_add_class(style, GTK_STYLE_CLASS_TOP);
}
- /* Scrollbar button has to be inset by trough_border because its DOM element
- * is filling width of vertical scrollbar's track (or height in case
- * of horizontal scrollbars). */
-
- MozGtkScrollbarMetrics metrics;
- moz_gtk_get_scrollbar_metrics(&metrics);
- if (flags & MOZ_GTK_STEPPER_VERTICAL) {
- rect->x += metrics.trough_border;
- rect->width = metrics.slider_width;
+ GdkRectangle rect = *aRect;
+ if (gtk_check_version(3,20,0) == nullptr) {
+ // The "trough-border" is not used since GTK 3.20. The stepper margin
+ // box occupies the full width of the "contents" gadget content box.
+ InsetByMargin(&rect, style);
} else {
- rect->y += metrics.trough_border;
- rect->height = metrics.slider_width;
+ // Scrollbar button has to be inset by trough_border because its DOM
+ // element is filling width of vertical scrollbar's track (or height
+ // in case of horizontal scrollbars).
+ MozGtkScrollbarMetrics metrics;
+ moz_gtk_get_scrollbar_metrics(&metrics);
+ if (flags & MOZ_GTK_STEPPER_VERTICAL) {
+ rect.x += metrics.trough_border;
+ rect.width = metrics.slider_width;
+ } else {
+ rect.y += metrics.trough_border;
+ rect.height = metrics.slider_width;
+ }
}
- 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(style, cr, rect.x, rect.y, rect.width, rect.height);
+ gtk_render_frame(style, cr, rect.x, rect.y, rect.width, rect.height);
- arrow_rect.width = rect->width / 2;
- arrow_rect.height = rect->height / 2;
+ arrow_rect.width = rect.width / 2;
+ arrow_rect.height = rect.height / 2;
gfloat arrow_scaling;
gtk_style_context_get_style(style, "arrow-scaling", &arrow_scaling, NULL);
- gdouble arrow_size = MIN(rect->width, rect->height) * arrow_scaling;
- arrow_rect.x = rect->x + (rect->width - arrow_size) / 2;
- arrow_rect.y = rect->y + (rect->height - arrow_size) / 2;
+ gdouble arrow_size = MIN(rect.width, rect.height) * arrow_scaling;
+ arrow_rect.x = rect.x + (rect.width - arrow_size) / 2;
+ arrow_rect.y = rect.y + (rect.height - arrow_size) / 2;
if (state_flags & GTK_STATE_FLAG_ACTIVE) {
gtk_style_context_get_style(style,
@@ -862,19 +602,23 @@ moz_gtk_update_scrollbar_style(GtkStyleC
static void
moz_gtk_draw_styled_frame(GtkStyleContext* style, cairo_t *cr,
- GdkRectangle* rect, bool drawFocus)
+ const GdkRectangle* aRect, bool drawFocus)
{
- 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);
+ GdkRectangle rect = *aRect;
+ if (gtk_check_version(3, 6, 0) == nullptr) {
+ InsetByMargin(&rect, 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);
if (drawFocus) {
gtk_render_focus(style, cr,
- rect->x, rect->y, rect->width, rect->height);
+ rect.x, rect.y, rect.width, rect.height);
}
}
static gint
moz_gtk_scrollbar_trough_paint(WidgetNodeType widget,
- cairo_t *cr, GdkRectangle* rect,
+ cairo_t *cr, const GdkRectangle* rect,
GtkWidgetState* state,
GtkScrollbarTrackFlags flags,
GtkTextDirection direction)
@@ -886,26 +630,28 @@ moz_gtk_scrollbar_trough_paint(WidgetNod
ReleaseStyleContext(style);
}
- bool isHorizontal = (widget == MOZ_GTK_SCROLLBAR_HORIZONTAL);
- GtkStyleContext* style;
+ GtkStyleContext* style = ClaimStyleContext(widget, direction);
+ moz_gtk_draw_styled_frame(style, cr, rect, state->focused);
+ ReleaseStyleContext(style);
- // Draw all child CSS Nodes for Gtk >= 3.20
- if (gtk_check_version(3, 20, 0) == nullptr) {
- style = ClaimStyleContext(widget, direction);
- moz_gtk_update_scrollbar_style(style, widget, direction);
- moz_gtk_draw_styled_frame(style, cr, rect, state->focused);
- ReleaseStyleContext(style);
+ return MOZ_GTK_SUCCESS;
+}
- style = ClaimStyleContext(isHorizontal ?
- MOZ_GTK_SCROLLBAR_CONTENTS_HORIZONTAL :
- MOZ_GTK_SCROLLBAR_CONTENTS_VERTICAL,
- direction);
- moz_gtk_draw_styled_frame(style, cr, rect, state->focused);
- ReleaseStyleContext(style);
- }
- style = ClaimStyleContext(isHorizontal ?
- MOZ_GTK_SCROLLBAR_TROUGH_HORIZONTAL :
- MOZ_GTK_SCROLLBAR_TROUGH_VERTICAL,
+static gint
+moz_gtk_scrollbar_paint(WidgetNodeType widget,
+ cairo_t *cr, const GdkRectangle* rect,
+ GtkWidgetState* state,
+ GtkTextDirection direction)
+{
+ GtkStyleContext* style = ClaimStyleContext(widget, direction);
+ moz_gtk_update_scrollbar_style(style, widget, direction);
+
+ moz_gtk_draw_styled_frame(style, cr, rect, state->focused);
+
+ ReleaseStyleContext(style);
+ style = ClaimStyleContext((widget == MOZ_GTK_SCROLLBAR_HORIZONTAL) ?
+ MOZ_GTK_SCROLLBAR_CONTENTS_HORIZONTAL :
+ MOZ_GTK_SCROLLBAR_CONTENTS_VERTICAL,
direction);
moz_gtk_draw_styled_frame(style, cr, rect, state->focused);
ReleaseStyleContext(style);
@@ -915,21 +661,21 @@ moz_gtk_scrollbar_trough_paint(WidgetNod
static gint
moz_gtk_scrollbar_thumb_paint(WidgetNodeType widget,
- cairo_t *cr, GdkRectangle* rect,
+ cairo_t *cr, const GdkRectangle* aRect,
GtkWidgetState* state,
GtkTextDirection direction)
{
GtkStateFlags state_flags = GetStateFlagsFromGtkWidgetState(state);
- GtkBorder margin;
+ GdkRectangle rect = *aRect;
GtkStyleContext* style = ClaimStyleContext(widget, direction, state_flags);
- gtk_style_context_get_margin (style, state_flags, &margin);
+ InsetByMargin(&rect, style);
gtk_render_slider(style, cr,
- rect->x + margin.left,
- rect->y + margin.top,
- rect->width - margin.left - margin.right,
- rect->height - margin.top - margin.bottom,
+ rect.x,
+ rect.y,
+ rect.width,
+ rect.height,
(widget == MOZ_GTK_SCROLLBAR_THUMB_HORIZONTAL) ?
GTK_ORIENTATION_HORIZONTAL : GTK_ORIENTATION_VERTICAL);
@@ -987,18 +733,15 @@ moz_gtk_scale_paint(cairo_t *cr, GdkRect
GtkStateFlags state_flags = GetStateFlagsFromGtkWidgetState(state);
gint x, y, width, height, min_width, min_height;
GtkStyleContext* style;
- GtkWidget* widget;
GtkBorder margin;
- ensure_scale_widget();
- widget = ((flags == GTK_ORIENTATION_HORIZONTAL) ? gHScaleWidget : gVScaleWidget);
- gtk_widget_set_direction(widget, direction);
moz_gtk_get_scale_metrics(flags, &min_width, &min_height);
- style = gtk_widget_get_style_context(widget);
- gtk_style_context_save(style);
- gtk_style_context_add_class(style, GTK_STYLE_CLASS_TROUGH);
- gtk_style_context_get_margin(style, state_flags, &margin);
+ WidgetNodeType widget = (flags == GTK_ORIENTATION_HORIZONTAL) ?
+ MOZ_GTK_SCALE_TROUGH_HORIZONTAL :
+ MOZ_GTK_SCALE_TROUGH_VERTICAL;
+ style = ClaimStyleContext(widget, direction, state_flags);
+ gtk_style_context_get_margin(style, state_flags, &margin);
// Clamp the dimension perpendicular to the direction that the slider crosses
// to the minimum size.
@@ -1020,7 +763,8 @@ moz_gtk_scale_paint(cairo_t *cr, GdkRect
if (state->focused)
gtk_render_focus(style, cr,
rect->x, rect->y, rect->width, rect->height);
- gtk_style_context_restore(style);
+
+ ReleaseStyleContext(style);
return MOZ_GTK_SUCCESS;
}
@@ -1031,17 +775,8 @@ moz_gtk_scale_thumb_paint(cairo_t *cr, G
{
GtkStateFlags state_flags = GetStateFlagsFromGtkWidgetState(state);
GtkStyleContext* style;
- GtkWidget* widget;
gint thumb_width, thumb_height, x, y;
- ensure_scale_widget();
- widget = ((flags == GTK_ORIENTATION_HORIZONTAL) ? gHScaleWidget : gVScaleWidget);
- gtk_widget_set_direction(widget, direction);
-
- style = gtk_widget_get_style_context(widget);
- gtk_style_context_save(style);
- gtk_style_context_add_class(style, GTK_STYLE_CLASS_SLIDER);
- gtk_style_context_set_state(style, state_flags);
/* determine the thumb size, and position the thumb in the center in the opposite axis
*/
if (flags == GTK_ORIENTATION_HORIZONTAL) {
@@ -1055,8 +790,13 @@ moz_gtk_scale_thumb_paint(cairo_t *cr, G
y = rect->y;
}
+ WidgetNodeType widget = (flags == GTK_ORIENTATION_HORIZONTAL) ?
+ MOZ_GTK_SCALE_THUMB_HORIZONTAL :
+ MOZ_GTK_SCALE_THUMB_VERTICAL;
+ style = ClaimStyleContext(widget, direction, state_flags);
gtk_render_slider(style, cr, x, y, thumb_width, thumb_height, flags);
- gtk_style_context_restore(style);
+ ReleaseStyleContext(style);
+
return MOZ_GTK_SUCCESS;
}
@@ -1078,17 +818,13 @@ static gint
moz_gtk_hpaned_paint(cairo_t *cr, GdkRectangle* rect,
GtkWidgetState* state)
{
- GtkStyleContext* style;
-
- ensure_hpaned_widget();
- style = gtk_widget_get_style_context(gHPanedWidget);
- gtk_style_context_save(style);
- gtk_style_context_add_class(style, GTK_STYLE_CLASS_PANE_SEPARATOR);
- gtk_style_context_set_state(style, GetStateFlagsFromGtkWidgetState(state));
+ GtkStyleContext* style =
+ ClaimStyleContext(MOZ_GTK_SPLITTER_SEPARATOR_HORIZONTAL,
+ GTK_TEXT_DIR_LTR,
+ GetStateFlagsFromGtkWidgetState(state));
gtk_render_handle(style, cr,
rect->x, rect->y, rect->width, rect->height);
- gtk_style_context_restore(style);
-
+ ReleaseStyleContext(style);
return MOZ_GTK_SUCCESS;
}
@@ -1096,17 +832,13 @@ static gint
moz_gtk_vpaned_paint(cairo_t *cr, GdkRectangle* rect,
GtkWidgetState* state)
{
- GtkStyleContext* style;
-
- ensure_vpaned_widget();
- style = gtk_widget_get_style_context(gVPanedWidget);
- gtk_style_context_save(style);
- gtk_style_context_add_class(style, GTK_STYLE_CLASS_PANE_SEPARATOR);
- gtk_style_context_set_state(style, GetStateFlagsFromGtkWidgetState(state));
+ GtkStyleContext* style =
+ ClaimStyleContext(MOZ_GTK_SPLITTER_SEPARATOR_VERTICAL,
+ GTK_TEXT_DIR_LTR,
+ GetStateFlagsFromGtkWidgetState(state));
gtk_render_handle(style, cr,
rect->x, rect->y, rect->width, rect->height);
- gtk_style_context_restore(style);
-
+ ReleaseStyleContext(style);
return MOZ_GTK_SUCCESS;
}
@@ -1114,60 +846,26 @@ 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)
+ GtkStyleContext* style)
{
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
- gtk_widget_set_direction(widget, direction);
-
- style = gtk_widget_get_style_context(widget);
-
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);
+ moz_gtk_get_focus_outline_size(style, &h, &v);
rect->x -= h;
rect->width += 2 * h;
rect->y -= v;
rect->height += 2 * v;
width = rect->width;
height = rect->height;
- }
-
- /* 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 */
-
- /* This gets us a lovely greyish disabledish look */
- gtk_widget_set_sensitive(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
- * 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 (state->disabled) {
- gtk_style_context_set_state(style, GTK_STATE_FLAG_INSENSITIVE);
- }
-
- if (!draw_focus_outline_only) {
+ } else {
gtk_render_background(style, cr, x, y, width, height);
}
gtk_render_frame(style, cr, x, y, width, height);
- gtk_style_context_restore(style);
-
return MOZ_GTK_SUCCESS;
}
@@ -1214,9 +912,6 @@ moz_gtk_treeview_paint(cairo_t *cr, GdkR
GtkStateFlags state_flags;
GtkBorder border;
- ensure_tree_view_widget();
- gtk_widget_set_direction(gTreeViewWidget, direction);
-
/* only handle disabled and normal states, otherwise the whole background
* area will be painted differently with other states */
state_flags = state->disabled ? GTK_STATE_FLAG_INSENSITIVE : GTK_STATE_FLAG_NORMAL;
@@ -1225,19 +920,19 @@ moz_gtk_treeview_paint(cairo_t *cr, GdkR
gtk_style_context_get_border(style, state_flags, &border);
xthickness = border.left;
ythickness = border.top;
+ ReleaseStyleContext(style);
- style_tree = gtk_widget_get_style_context(gTreeViewWidget);
- gtk_style_context_save(style_tree);
- gtk_style_context_add_class(style_tree, GTK_STYLE_CLASS_VIEW);
-
+ style_tree = ClaimStyleContext(MOZ_GTK_TREEVIEW_VIEW, direction);
gtk_render_background(style_tree, cr,
rect->x + xthickness, rect->y + ythickness,
rect->width - 2 * xthickness,
rect->height - 2 * ythickness);
+ ReleaseStyleContext(style_tree);
+
+ style = ClaimStyleContext(MOZ_GTK_SCROLLED_WINDOW, direction);
gtk_render_frame(style, cr,
rect->x, rect->y, rect->width, rect->height);
ReleaseStyleContext(style);
- gtk_style_context_restore(style_tree);
return MOZ_GTK_SUCCESS;
}
@@ -1247,7 +942,7 @@ moz_gtk_tree_header_cell_paint(cairo_t *
gboolean isSorted, GtkTextDirection direction)
{
moz_gtk_button_paint(cr, rect, state, GTK_RELIEF_NORMAL,
- gTreeHeaderCellWidget, direction);
+ GetWidget(MOZ_GTK_TREE_HEADER_CELL), direction);
return MOZ_GTK_SUCCESS;
}
@@ -1260,18 +955,13 @@ moz_gtk_tree_header_sort_arrow_paint(cai
gdouble arrow_angle;
GtkStyleContext* style;
- ensure_tree_header_cell_widget();
- gtk_widget_set_direction(gTreeHeaderSortArrowWidget, direction);
-
/* hard code these values */
arrow_rect.width = 11;
arrow_rect.height = 11;
arrow_rect.x = rect->x + (rect->width - arrow_rect.width) / 2;
arrow_rect.y = rect->y + (rect->height - arrow_rect.height) / 2;
- style = gtk_widget_get_style_context(gTreeHeaderSortArrowWidget);
- gtk_style_context_save(style);
- gtk_style_context_set_state(style, GetStateFlagsFromGtkWidgetState(state));
-
+ style = ClaimStyleContext(MOZ_GTK_TREE_HEADER_SORTARROW, direction,
+ GetStateFlagsFromGtkWidgetState(state));
switch (arrow_type) {
case GTK_ARROW_LEFT:
arrow_angle = ARROW_LEFT;
@@ -1290,7 +980,7 @@ moz_gtk_tree_header_sort_arrow_paint(cai
gtk_render_arrow(style, cr, arrow_angle,
arrow_rect.x, arrow_rect.y,
arrow_rect.width);
- gtk_style_context_restore(style);
+ ReleaseStyleContext(style);
return MOZ_GTK_SUCCESS;
}
@@ -1302,37 +992,28 @@ moz_gtk_treeview_expander_paint(cairo_t
GtkExpanderStyle expander_state,
GtkTextDirection direction)
{
- GtkStyleContext *style;
- GtkStateFlags state_flags;
-
- ensure_tree_view_widget();
- gtk_widget_set_direction(gTreeViewWidget, direction);
-
- style = gtk_widget_get_style_context(gTreeViewWidget);
- gtk_style_context_save(style);
- gtk_style_context_add_class(style, GTK_STYLE_CLASS_EXPANDER);
-
/* Because the frame we get is of the entire treeview, we can't get the precise
* event state of one expander, thus rendering hover and active feedback useless. */
- state_flags = state->disabled ? GTK_STATE_FLAG_INSENSITIVE : GTK_STATE_FLAG_NORMAL;
+ GtkStateFlags state_flags = state->disabled ? GTK_STATE_FLAG_INSENSITIVE :
+ GTK_STATE_FLAG_NORMAL;
/* GTK_STATE_FLAG_ACTIVE controls expanded/colapsed state rendering
* in gtk_render_expander()
*/
if (expander_state == GTK_EXPANDER_EXPANDED)
- state_flags = static_cast<GtkStateFlags>(state_flags|GTK_STATE_FLAG_ACTIVE);
+ state_flags = static_cast<GtkStateFlags>(state_flags|checkbox_check_state);
else
- state_flags = static_cast<GtkStateFlags>(state_flags&~(GTK_STATE_FLAG_ACTIVE));
-
- gtk_style_context_set_state(style, state_flags);
+ state_flags = static_cast<GtkStateFlags>(state_flags&~(checkbox_check_state));
+ GtkStyleContext *style = ClaimStyleContext(MOZ_GTK_TREEVIEW_EXPANDER,
+ direction, state_flags);
gtk_render_expander(style, cr,
rect->x,
rect->y,
rect->width,
rect->height);
- gtk_style_context_restore(style);
+ ReleaseStyleContext(style);
return MOZ_GTK_SUCCESS;
}
@@ -1349,34 +1030,37 @@ moz_gtk_combo_box_paint(cairo_t *cr, Gdk
GtkStyleContext* style;
GtkRequisition arrow_req;
- ensure_combo_box_widgets();
+ GtkWidget* comboBoxButton = GetWidget(MOZ_GTK_COMBOBOX_BUTTON);
+ GtkWidget* comboBoxArrow = GetWidget(MOZ_GTK_COMBOBOX_ARROW);
/* Also sets the direction on gComboBoxButtonWidget, which is then
* inherited by the separator and arrow */
moz_gtk_button_paint(cr, rect, state, GTK_RELIEF_NORMAL,
- gComboBoxButtonWidget, direction);
+ comboBoxButton, direction);
- calculate_button_inner_rect(gComboBoxButtonWidget,
- rect, &arrow_rect, direction);
+ calculate_button_inner_rect(comboBoxButton, rect, &arrow_rect, direction);
/* 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_get_preferred_size(gComboBoxArrowWidget, NULL, &arrow_req);
+ gtk_widget_get_preferred_size(comboBoxArrow, NULL, &arrow_req);
+
if (direction == GTK_TEXT_DIR_LTR)
arrow_rect.x += arrow_rect.width - arrow_req.width;
arrow_rect.width = arrow_req.width;
- calculate_arrow_rect(gComboBoxArrowWidget,
+ calculate_arrow_rect(comboBoxArrow,
&arrow_rect, &real_arrow_rect, direction);
- style = gtk_widget_get_style_context(gComboBoxArrowWidget);
+ style = ClaimStyleContext(MOZ_GTK_COMBOBOX_ARROW);
gtk_render_arrow(style, cr, ARROW_DOWN,
real_arrow_rect.x, real_arrow_rect.y,
real_arrow_rect.width);
+ ReleaseStyleContext(style);
/* If there is no separator in the theme, there's nothing left to do. */
- if (!gComboBoxSeparatorWidget)
+ GtkWidget* widget = GetWidget(MOZ_GTK_COMBOBOX_SEPARATOR);
+ if (!widget)
return MOZ_GTK_SUCCESS;
- style = gtk_widget_get_style_context(gComboBoxSeparatorWidget);
+ style = gtk_widget_get_style_context(widget);
gtk_style_context_get_style(style,
"wide-separators", &wide_separators,
"separator-width", &separator_width,
@@ -1460,15 +1144,14 @@ moz_gtk_combo_box_entry_button_paint(cai
GtkStateFlags state_flags = GetStateFlagsFromGtkWidgetState(state);
GtkStyleContext* style;
- ensure_combo_box_entry_widgets();
-
+ GtkWidget* comboBoxEntry = GetWidget(MOZ_GTK_COMBOBOX_ENTRY_BUTTON);
moz_gtk_button_paint(cr, rect, state, GTK_RELIEF_NORMAL,
- gComboBoxEntryButtonWidget, direction);
+ comboBoxEntry, direction);
+ calculate_button_inner_rect(comboBoxEntry, rect, &arrow_rect, direction);
- calculate_button_inner_rect(gComboBoxEntryButtonWidget,
- rect, &arrow_rect, direction);
if (state_flags & GTK_STATE_FLAG_ACTIVE) {
- gtk_style_context_get_style(gtk_widget_get_style_context(gComboBoxEntryButtonWidget),
+ style = gtk_widget_get_style_context(comboBoxEntry);
+ gtk_style_context_get_style(style,
"child-displacement-x", &x_displacement,
"child-displacement-y", &y_displacement,
NULL);
@@ -1476,15 +1159,14 @@ moz_gtk_combo_box_entry_button_paint(cai
arrow_rect.y += y_displacement;
}
- calculate_arrow_rect(gComboBoxEntryArrowWidget,
+ calculate_arrow_rect(GetWidget(MOZ_GTK_COMBOBOX_ENTRY_ARROW),
&arrow_rect, &real_arrow_rect, direction);
- style = gtk_widget_get_style_context(gComboBoxEntryArrowWidget);
-
+ style = ClaimStyleContext(MOZ_GTK_COMBOBOX_ENTRY_ARROW);
gtk_render_arrow(style, cr, ARROW_DOWN,
real_arrow_rect.x, real_arrow_rect.y,
real_arrow_rect.width);
-
+ ReleaseStyleContext(style);
return MOZ_GTK_SUCCESS;
}
@@ -1504,7 +1186,6 @@ moz_gtk_container_paint(cairo_t *cr, Gdk
}
ReleaseStyleContext(style);
-
return MOZ_GTK_SUCCESS;
}
@@ -1590,12 +1271,53 @@ moz_gtk_toolbar_separator_paint(cairo_t
}
static gint
-moz_gtk_tooltip_paint(cairo_t *cr, GdkRectangle* rect,
+moz_gtk_tooltip_paint(cairo_t *cr, const GdkRectangle* aRect,
GtkTextDirection direction)
{
+ // Tooltip widget is made in GTK3 as following tree:
+ // Tooltip window
+ // Horizontal Box
+ // Icon (not supported by Firefox)
+ // Label
+ // Each element can be fully styled by CSS of GTK theme.
+ // We have to draw all elements with appropriate offset and right dimensions.
+
+ // Tooltip drawing
GtkStyleContext* style = ClaimStyleContext(MOZ_GTK_TOOLTIP, 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);
+ GdkRectangle rect = *aRect;
+ 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);
+
+ // Horizontal Box drawing
+ //
+ // The box element has hard-coded 6px margin-* GtkWidget properties, which
+ // are added between the window dimensions and the CSS margin box of the
+ // horizontal box. The frame of the tooltip window is drawn in the
+ // 6px margin.
+ // For drawing Horizontal Box we have to inset drawing area by that 6px
+ // plus its CSS margin.
+ GtkStyleContext* boxStyle =
+ CreateStyleForWidget(gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0), style);
+
+ rect.x += 6;
+ rect.y += 6;
+ rect.width -= 12;
+ rect.height -= 12;
+
+ InsetByMargin(&rect, boxStyle);
+ gtk_render_background(boxStyle, cr, rect.x, rect.y, rect.width, rect.height);
+ gtk_render_frame(boxStyle, cr, rect.x, rect.y, rect.width, rect.height);
+
+ // Label drawing
+ InsetByBorderPadding(&rect, boxStyle);
+
+ GtkStyleContext* labelStyle =
+ CreateStyleForWidget(gtk_label_new(nullptr), boxStyle);
+ moz_gtk_draw_styled_frame(labelStyle, cr, &rect, false);
+ g_object_unref(labelStyle);
+
+ g_object_unref(boxStyle);
+
ReleaseStyleContext(style);
return MOZ_GTK_SUCCESS;
}
@@ -1721,46 +1443,35 @@ moz_gtk_progress_chunk_paint(cairo_t *cr
return MOZ_GTK_SUCCESS;
}
-gint
-moz_gtk_get_tab_thickness(void)
+static gint
+moz_gtk_get_tab_thickness(GtkStyleContext *style)
{
- GtkBorder border;
- GtkStyleContext * style;
-
- ensure_tab_widget();
if (!notebook_has_tab_gap)
return 0; /* tabs do not overdraw the tabpanel border with "no gap" style */
- style = gtk_widget_get_style_context(gTabWidget);
- gtk_style_context_add_class(style, GTK_STYLE_CLASS_NOTEBOOK);
+ GtkBorder border;
gtk_style_context_get_border(style, GTK_STATE_FLAG_NORMAL, &border);
-
if (border.top < 2)
return 2; /* some themes don't set ythickness correctly */
return border.top;
}
-static void
-moz_gtk_tab_prepare_style_context(GtkStyleContext *style,
- GtkTabFlags flags)
-{
- gtk_style_context_set_state(style, ((flags & MOZ_GTK_TAB_SELECTED) == 0) ?
- GTK_STATE_FLAG_NORMAL :
- GTK_STATE_FLAG_ACTIVE);
- gtk_style_context_add_region(style, GTK_STYLE_REGION_TAB,
- (flags & MOZ_GTK_TAB_FIRST) ?
- GTK_REGION_FIRST : static_cast<GtkRegionFlags>(0));
- gtk_style_context_add_class(style, (flags & MOZ_GTK_TAB_BOTTOM) ?
- GTK_STYLE_CLASS_BOTTOM :
- GTK_STYLE_CLASS_TOP);
+gint
+moz_gtk_get_tab_thickness(WidgetNodeType aNodeType)
+{
+ GtkStyleContext *style = ClaimStyleContext(aNodeType);
+ int thickness = moz_gtk_get_tab_thickness(style);
+ ReleaseStyleContext(style);
+ return thickness;
}
/* actual small tabs */
static gint
moz_gtk_tab_paint(cairo_t *cr, GdkRectangle* rect,
GtkWidgetState* state,
- GtkTabFlags flags, GtkTextDirection direction)
+ GtkTabFlags flags, GtkTextDirection direction,
+ WidgetNodeType widget)
{
/* When the tab isn't selected, we just draw a notebook extension.
* When it is selected, we overwrite the adjacent border of the tabpanel
@@ -1772,14 +1483,10 @@ moz_gtk_tab_paint(cairo_t *cr, GdkRectan
GdkRectangle focusRect;
GdkRectangle backRect;
int initial_gap = 0;
+ bool isBottomTab = (widget == MOZ_GTK_TAB_BOTTOM);
- ensure_tab_widget();
- gtk_widget_set_direction(gTabWidget, direction);
-
- style = gtk_widget_get_style_context(gTabWidget);
- gtk_style_context_save(style);
- moz_gtk_tab_prepare_style_context(style, flags);
-
+ style = ClaimStyleContext(widget, direction,
+ GetStateFlagsFromGtkTabFlags(flags));
tabRect = *rect;
if (flags & MOZ_GTK_TAB_FIRST) {
@@ -1798,8 +1505,7 @@ moz_gtk_tab_paint(cairo_t *cr, GdkRectan
/* Only draw the tab */
gtk_render_extension(style, cr,
tabRect.x, tabRect.y, tabRect.width, tabRect.height,
- (flags & MOZ_GTK_TAB_BOTTOM) ?
- GTK_POS_TOP : GTK_POS_BOTTOM );
+ isBottomTab ? GTK_POS_TOP : GTK_POS_BOTTOM );
} else {
/* Draw the tab and the gap
* We want the gap to be positioned exactly on the tabpanel top
@@ -1840,7 +1546,7 @@ moz_gtk_tab_paint(cairo_t *cr, GdkRectan
gint gap_loffset, gap_roffset, gap_voffset, gap_height;
/* Get height needed by the gap */
- gap_height = moz_gtk_get_tab_thickness();
+ gap_height = moz_gtk_get_tab_thickness(style);
/* Extract gap_voffset from the first bits of flags */
gap_voffset = flags & MOZ_GTK_TAB_MARGIN_MASK;
@@ -1856,7 +1562,7 @@ moz_gtk_tab_paint(cairo_t *cr, GdkRectan
gap_loffset = initial_gap;
}
- if (flags & MOZ_GTK_TAB_BOTTOM) {
+ if (isBottomTab) {
/* Draw the tab on bottom */
focusRect.y += gap_voffset;
focusRect.height -= gap_voffset;
@@ -1920,15 +1626,9 @@ moz_gtk_tab_paint(cairo_t *cr, GdkRectan
gtk_render_frame(style, cr, tabRect.x, tabRect.y, tabRect.width, tabRect.height);
}
- gtk_style_context_restore(style);
-
if (state->focused) {
/* Paint the focus ring */
GtkBorder padding;
-
- gtk_style_context_save(style);
- moz_gtk_tab_prepare_style_context(style, flags);
-
gtk_style_context_get_padding(style, GetStateFlagsFromGtkWidgetState(state), &padding);
focusRect.x += padding.left;
@@ -1938,10 +1638,8 @@ moz_gtk_tab_paint(cairo_t *cr, GdkRectan
gtk_render_focus(style, cr,
focusRect.x, focusRect.y, focusRect.width, focusRect.height);
-
- gtk_style_context_restore(style);
}
-
+ ReleaseStyleContext(style);
return MOZ_GTK_SUCCESS;
}
@@ -1951,14 +1649,7 @@ static gint
moz_gtk_tabpanels_paint(cairo_t *cr, GdkRectangle* rect,
GtkTextDirection direction)
{
- GtkStyleContext* style;
-
- ensure_tab_widget();
- gtk_widget_set_direction(gTabWidget, direction);
-
- style = gtk_widget_get_style_context(gTabWidget);
- gtk_style_context_save(style);
-
+ GtkStyleContext* style = ClaimStyleContext(MOZ_GTK_TABPANELS, direction);
gtk_render_background(style, cr, rect->x, rect->y,
rect->width, rect->height);
/*
@@ -1982,7 +1673,7 @@ moz_gtk_tabpanels_paint(cairo_t *cr, Gdk
rect->width, rect->height,
GTK_POS_TOP, rect->width - 1, rect->width);
cairo_restore(cr);
-
+
/* right side */
cairo_save(cr);
cairo_rectangle(cr, rect->x + rect->width / 2, rect->y,
@@ -1995,7 +1686,7 @@ moz_gtk_tabpanels_paint(cairo_t *cr, Gdk
GTK_POS_TOP, 0, 1);
cairo_restore(cr);
- gtk_style_context_restore(style);
+ ReleaseStyleContext(style);
return MOZ_GTK_SUCCESS;
}
@@ -2005,17 +1696,12 @@ moz_gtk_tab_scroll_arrow_paint(cairo_t *
GtkArrowType arrow_type,
GtkTextDirection direction)
{
- GtkStateFlags state_flags = GetStateFlagsFromGtkWidgetState(state);
GtkStyleContext* style;
gdouble arrow_angle;
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 = gtk_widget_get_style_context(gTabWidget);
- gtk_style_context_save(style);
if (direction == GTK_TEXT_DIR_RTL) {
arrow_type = (arrow_type == GTK_ARROW_LEFT) ?
GTK_ARROW_RIGHT : GTK_ARROW_LEFT;
@@ -2035,12 +1721,12 @@ moz_gtk_tab_scroll_arrow_paint(cairo_t *
break;
}
if (arrow_type != GTK_ARROW_NONE) {
- gtk_style_context_add_class(style, GTK_STYLE_CLASS_NOTEBOOK); /* TODO TEST */
- gtk_style_context_set_state(style, state_flags);
+ style = ClaimStyleContext(MOZ_GTK_TAB_SCROLLARROW, direction,
+ GetStateFlagsFromGtkWidgetState(state));
gtk_render_arrow(style, cr, arrow_angle,
x, y, arrow_size);
+ ReleaseStyleContext(style);
}
- gtk_style_context_restore(style);
return MOZ_GTK_SUCCESS;
}
@@ -2092,22 +1778,25 @@ static gint
moz_gtk_menu_separator_paint(cairo_t *cr, GdkRectangle* rect,
GtkTextDirection direction)
{
+ GtkWidgetState defaultState = { 0 };
+ moz_gtk_menu_item_paint(MOZ_GTK_MENUSEPARATOR, cr, rect,
+ &defaultState, direction);
+
+ if (gtk_get_minor_version() >= 20)
+ return MOZ_GTK_SUCCESS;
+
GtkStyleContext* style;
gboolean wide_separators;
gint separator_height;
- guint border_width;
gint x, y, w;
GtkBorder padding;
- border_width =
- gtk_container_get_border_width(GTK_CONTAINER(
- GetWidget(MOZ_GTK_MENUSEPARATOR)));
style = ClaimStyleContext(MOZ_GTK_MENUSEPARATOR, direction);
gtk_style_context_get_padding(style, GTK_STATE_FLAG_NORMAL, &padding);
- x = rect->x + border_width;
- y = rect->y + border_width;
- w = rect->width - border_width * 2;
+ x = rect->x;
+ y = rect->y;
+ w = rect->width;
gtk_style_context_save(style);
gtk_style_context_add_class(style, GTK_STYLE_CLASS_SEPARATOR);
@@ -2144,37 +1833,32 @@ moz_gtk_menu_item_paint(WidgetNodeType w
{
gint x, y, w, h;
- if (state->inHover && !state->disabled) {
- guint border_width =
- gtk_container_get_border_width(GTK_CONTAINER(GetWidget(widget)));
- GtkStateFlags state_flags = GetStateFlagsFromGtkWidgetState(state);
- GtkStyleContext* style =
- ClaimStyleContext(widget, direction, state_flags);
-
- bool pre_3_6 = gtk_check_version(3, 6, 0) != nullptr;
- if (pre_3_6) {
- // GTK+ 3.4 saves the style context and adds the menubar class to
- // menubar children, but does each of these only when drawing, not
- // during layout.
- gtk_style_context_save(style);
- if (widget == MOZ_GTK_MENUBARITEM) {
- gtk_style_context_add_class(style, GTK_STYLE_CLASS_MENUBAR);
- }
+ GtkStateFlags state_flags = GetStateFlagsFromGtkWidgetState(state);
+ GtkStyleContext* style = ClaimStyleContext(widget, direction, state_flags);
+
+ bool pre_3_6 = gtk_check_version(3, 6, 0) != nullptr;
+ if (pre_3_6) {
+ // GTK+ 3.4 saves the style context and adds the menubar class to
+ // menubar children, but does each of these only when drawing, not
+ // during layout.
+ gtk_style_context_save(style);
+ if (widget == MOZ_GTK_MENUBARITEM) {
+ gtk_style_context_add_class(style, GTK_STYLE_CLASS_MENUBAR);
}
+ }
- x = rect->x + border_width;
- y = rect->y + border_width;
- w = rect->width - border_width * 2;
- h = rect->height - border_width * 2;
+ x = rect->x;
+ y = rect->y;
+ w = rect->width;
+ h = rect->height;
- gtk_render_background(style, cr, x, y, w, h);
- gtk_render_frame(style, cr, x, y, w, h);
+ gtk_render_background(style, cr, x, y, w, h);
+ gtk_render_frame(style, cr, x, y, w, h);
- if (pre_3_6) {
- gtk_style_context_restore(style);
- }
- ReleaseStyleContext(style);
+ if (pre_3_6) {
+ gtk_style_context_restore(style);
}
+ ReleaseStyleContext(style);
return MOZ_GTK_SUCCESS;
}
@@ -2194,63 +1878,68 @@ moz_gtk_menu_arrow_paint(cairo_t *cr, Gd
return MOZ_GTK_SUCCESS;
}
-// See gtk_real_check_menu_item_draw_indicator() for reference.
+// For reference, see gtk_check_menu_item_size_allocate() in GTK versions after
+// 3.20 and gtk_real_check_menu_item_draw_indicator() in earlier versions.
static gint
-moz_gtk_check_menu_item_paint(cairo_t *cr, GdkRectangle* rect,
+moz_gtk_check_menu_item_paint(WidgetNodeType widgetType,
+ cairo_t *cr, GdkRectangle* rect,
GtkWidgetState* state,
- gboolean checked, gboolean isradio,
- GtkTextDirection direction)
+ gboolean checked, GtkTextDirection direction)
{
GtkStateFlags state_flags = GetStateFlagsFromGtkWidgetState(state);
GtkStyleContext* style;
- GtkBorder padding;
- gint offset;
gint indicator_size, horizontal_padding;
gint x, y;
moz_gtk_menu_item_paint(MOZ_GTK_MENUITEM, cr, rect, state, direction);
- ensure_check_menu_item_widget();
- gtk_widget_set_direction(gCheckMenuItemWidget, direction);
-
- style = gtk_widget_get_style_context(gCheckMenuItemWidget);
- gtk_style_context_save(style);
+ if (checked) {
+ state_flags = static_cast<GtkStateFlags>(state_flags|checkbox_check_state);
+ }
+ bool pre_3_20 = gtk_get_minor_version() < 20;
+ gint offset;
+ style = ClaimStyleContext(widgetType, direction);
gtk_style_context_get_style(style,
"indicator-size", &indicator_size,
"horizontal-padding", &horizontal_padding,
NULL);
-
- if (isradio) {
- gtk_style_context_add_class(style, GTK_STYLE_CLASS_RADIO);
+ if (pre_3_20) {
+ GtkBorder padding;
+ gtk_style_context_get_padding(style, state_flags, &padding);
+ offset = horizontal_padding + padding.left + 2;
} else {
- gtk_style_context_add_class(style, GTK_STYLE_CLASS_CHECK);
- }
-
- if (checked) {
- state_flags = static_cast<GtkStateFlags>(state_flags|checkbox_check_state);
+ GdkRectangle r = { 0 };
+ InsetByMargin(&r, style);
+ InsetByBorderPadding(&r, style);
+ offset = r.x;
}
-
- gtk_style_context_set_state(style, state_flags);
- gtk_style_context_get_padding(style, state_flags, &padding);
+ ReleaseStyleContext(style);
- offset = gtk_container_get_border_width(GTK_CONTAINER(gCheckMenuItemWidget)) +
- padding.left + 2;
+ bool isRadio = (widgetType == MOZ_GTK_RADIOMENUITEM);
+ WidgetNodeType indicatorType = isRadio ? MOZ_GTK_RADIOMENUITEM_INDICATOR
+ : MOZ_GTK_CHECKMENUITEM_INDICATOR;
+ style = ClaimStyleContext(indicatorType, direction, state_flags);
if (direction == GTK_TEXT_DIR_RTL) {
- x = rect->width - indicator_size - offset - horizontal_padding;
+ x = rect->width - indicator_size - offset;
}
else {
- x = rect->x + offset + horizontal_padding;
+ x = rect->x + offset;
}
y = rect->y + (rect->height - indicator_size) / 2;
- if (isradio) {
+ if (!pre_3_20) {
+ gtk_render_background(style, cr, x, y, indicator_size, indicator_size);
+ gtk_render_frame(style, cr, x, y, indicator_size, indicator_size);
+ }
+
+ if (isRadio) {
gtk_render_option(style, cr, x, y, indicator_size, indicator_size);
} else {
gtk_render_check(style, cr, x, y, indicator_size, indicator_size);
}
- gtk_style_context_restore(style);
+ ReleaseStyleContext(style);
return MOZ_GTK_SUCCESS;
}
@@ -2271,6 +1960,20 @@ moz_gtk_info_bar_paint(cairo_t *cr, GdkR
}
static void
+moz_gtk_add_style_margin(GtkStyleContext* style,
+ gint* left, gint* top, gint* right, gint* bottom)
+{
+ GtkBorder margin;
+
+ gtk_style_context_get_margin(style, GTK_STATE_FLAG_NORMAL, &margin);
+
+ *left += margin.left;
+ *right += margin.right;
+ *top += margin.top;
+ *bottom += margin.bottom;
+}
+
+static void
moz_gtk_add_style_border(GtkStyleContext* style,
gint* left, gint* top, gint* right, gint* bottom)
{
@@ -2298,6 +2001,15 @@ moz_gtk_add_style_padding(GtkStyleContex
*bottom += padding.bottom;
}
+static void moz_gtk_add_margin_border_padding(GtkStyleContext *style,
+ gint* left, gint* top,
+ gint* right, gint* bottom)
+{
+ moz_gtk_add_style_margin(style, left, top, right, bottom);
+ moz_gtk_add_style_border(style, left, top, right, bottom);
+ moz_gtk_add_style_padding(style, left, top, right, bottom);
+}
+
gint
moz_gtk_get_widget_border(WidgetNodeType widget, gint* left, gint* top,
gint* right, gint* bottom, GtkTextDirection direction,
@@ -2362,26 +2074,24 @@ moz_gtk_get_widget_border(WidgetNodeType
* assigned.
* That is why the following code is the same as for MOZ_GTK_BUTTON.
* */
- ensure_tree_header_cell_widget();
- *left = *top = *right = *bottom = gtk_container_get_border_width(GTK_CONTAINER(gTreeHeaderCellWidget));
-
- style = gtk_widget_get_style_context(gTreeHeaderCellWidget);
+ *left = *top = *right = *bottom =
+ gtk_container_get_border_width(GTK_CONTAINER(
+ GetWidget(MOZ_GTK_TREE_HEADER_CELL)));
+ style = ClaimStyleContext(MOZ_GTK_TREE_HEADER_CELL);
moz_gtk_add_style_border(style, left, top, right, bottom);
moz_gtk_add_style_padding(style, left, top, right, bottom);
+ ReleaseStyleContext(style);
return MOZ_GTK_SUCCESS;
}
case MOZ_GTK_TREE_HEADER_SORTARROW:
- ensure_tree_header_cell_widget();
- w = gTreeHeaderSortArrowWidget;
+ w = GetWidget(MOZ_GTK_TREE_HEADER_SORTARROW);
break;
case MOZ_GTK_DROPDOWN_ENTRY:
- ensure_combo_box_entry_widgets();
- w = gComboBoxEntryTextareaWidget;
+ w = GetWidget(MOZ_GTK_COMBOBOX_ENTRY_TEXTAREA);
break;
case MOZ_GTK_DROPDOWN_ARROW:
- ensure_combo_box_entry_widgets();
- w = gComboBoxEntryButtonWidget;
+ w = GetWidget(MOZ_GTK_COMBOBOX_ENTRY_BUTTON);
break;
case MOZ_GTK_DROPDOWN:
{
@@ -2393,32 +2103,33 @@ moz_gtk_get_widget_border(WidgetNodeType
GtkRequisition arrow_req;
GtkBorder border;
- ensure_combo_box_widgets();
-
- *left = *top = *right = *bottom =
- gtk_container_get_border_width(GTK_CONTAINER(gComboBoxButtonWidget));
-
- style = gtk_widget_get_style_context(gComboBoxButtonWidget);
-
+ *left = *top = *right = *bottom =
+ gtk_container_get_border_width(GTK_CONTAINER(
+ GetWidget(MOZ_GTK_COMBOBOX_BUTTON)));
+ style = ClaimStyleContext(MOZ_GTK_COMBOBOX_BUTTON);
moz_gtk_add_style_padding(style, left, top, right, bottom);
moz_gtk_add_style_border(style, left, top, right, bottom);
+ ReleaseStyleContext(style);
/* If there is no separator, don't try to count its width. */
separator_width = 0;
- if (gComboBoxSeparatorWidget) {
- style = gtk_widget_get_style_context(gComboBoxSeparatorWidget);
+ GtkWidget* comboBoxSeparator = GetWidget(MOZ_GTK_COMBOBOX_SEPARATOR);
+ if (comboBoxSeparator) {
+ style = gtk_widget_get_style_context(comboBoxSeparator);
gtk_style_context_get_style(style,
"wide-separators", &wide_separators,
"separator-width", &separator_width,
NULL);
if (!wide_separators) {
- gtk_style_context_get_border(style, GTK_STATE_FLAG_NORMAL, &border);
+ gtk_style_context_get_border(style, GTK_STATE_FLAG_NORMAL,
+ &border);
separator_width = border.left;
}
}
- gtk_widget_get_preferred_size(gComboBoxArrowWidget, NULL, &arrow_req);
+ gtk_widget_get_preferred_size(GetWidget(MOZ_GTK_COMBOBOX_ARROW),
+ NULL, &arrow_req);
if (direction == GTK_TEXT_DIR_RTL)
*left += separator_width + arrow_req.width;
@@ -2428,8 +2139,7 @@ moz_gtk_get_widget_border(WidgetNodeType
return MOZ_GTK_SUCCESS;
}
case MOZ_GTK_TABPANELS:
- ensure_tab_widget();
- w = gTabWidget;
+ w = GetWidget(MOZ_GTK_TABPANELS);
break;
case MOZ_GTK_PROGRESSBAR:
w = GetWidget(MOZ_GTK_PROGRESSBAR);
@@ -2440,12 +2150,8 @@ moz_gtk_get_widget_border(WidgetNodeType
w = GetWidget(MOZ_GTK_SPINBUTTON);
break;
case MOZ_GTK_SCALE_HORIZONTAL:
- ensure_scale_widget();
- w = gHScaleWidget;
- break;
case MOZ_GTK_SCALE_VERTICAL:
- ensure_scale_widget();
- w = gVScaleWidget;
+ w = GetWidget(widget);
break;
case MOZ_GTK_FRAME:
w = GetWidget(MOZ_GTK_FRAME);
@@ -2471,17 +2177,18 @@ moz_gtk_get_widget_border(WidgetNodeType
case MOZ_GTK_CHECKMENUITEM:
case MOZ_GTK_RADIOMENUITEM:
{
- if (widget == MOZ_GTK_MENUBARITEM || widget == MOZ_GTK_MENUITEM) {
- // Bug 1274143 for MOZ_GTK_MENUBARITEM
- w = GetWidget(MOZ_GTK_MENUITEM);
+ // Bug 1274143 for MOZ_GTK_MENUBARITEM
+ WidgetNodeType type =
+ widget == MOZ_GTK_MENUBARITEM ? MOZ_GTK_MENUITEM : widget;
+ style = ClaimStyleContext(type);
+
+ if (gtk_get_minor_version() < 20) {
+ moz_gtk_add_style_padding(style, left, top, right, bottom);
} else {
- ensure_check_menu_item_widget();
- w = gCheckMenuItemWidget;
+ moz_gtk_add_margin_border_padding(style,
+ left, top, right, bottom);
}
-
- *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);
+ ReleaseStyleContext(style);
return MOZ_GTK_SUCCESS;
}
case MOZ_GTK_INFO_BAR:
@@ -2490,11 +2197,86 @@ moz_gtk_get_widget_border(WidgetNodeType
case MOZ_GTK_TOOLTIP:
{
style = ClaimStyleContext(MOZ_GTK_TOOLTIP);
- moz_gtk_add_style_border(style, left, top, right, bottom);
- moz_gtk_add_style_padding(style, left, top, right, bottom);
+ // In GTK 3 there are 6 pixels of additional margin around the box.
+ // See details there:
+ // https://github.com/GNOME/gtk/blob/5ea69a136bd7e4970b3a800390e20314665aaed2/gtk/ui/gtktooltipwindow.ui#L11
+ *left = *right = *top = *bottom = 6;
+
+ // We also need to add margin/padding/borders from Tooltip content.
+ // Tooltip contains horizontal box, where icon and label is put.
+ // We ignore icon as long as we don't have support for it.
+ GtkStyleContext* boxStyle =
+ CreateStyleForWidget(gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0),
+ style);
+ moz_gtk_add_margin_border_padding(boxStyle,
+ left, top, right, bottom);
+
+ GtkStyleContext* labelStyle =
+ CreateStyleForWidget(gtk_label_new(nullptr), boxStyle);
+ moz_gtk_add_margin_border_padding(labelStyle,
+ left, top, right, bottom);
+
+ g_object_unref(labelStyle);
+ g_object_unref(boxStyle);
+
ReleaseStyleContext(style);
return MOZ_GTK_SUCCESS;
}
+ case MOZ_GTK_SCROLLBAR_VERTICAL:
+ case MOZ_GTK_SCROLLBAR_TROUGH_HORIZONTAL:
+ {
+ if (gtk_check_version(3,20,0) == nullptr) {
+ style = ClaimStyleContext(widget);
+ moz_gtk_add_margin_border_padding(style, left, top, right, bottom);
+ ReleaseStyleContext(style);
+ if (widget == MOZ_GTK_SCROLLBAR_VERTICAL) {
+ style = ClaimStyleContext(MOZ_GTK_SCROLLBAR_CONTENTS_VERTICAL);
+ moz_gtk_add_margin_border_padding(style, left, top, right, bottom);
+ ReleaseStyleContext(style);
+ }
+ } else {
+ MozGtkScrollbarMetrics metrics;
+ moz_gtk_get_scrollbar_metrics(&metrics);
+ /* Top and bottom border for whole vertical scrollbar, top and bottom
+ * border for horizontal track - to correctly position thumb element */
+ *top = *bottom = metrics.trough_border;
+ }
+ return MOZ_GTK_SUCCESS;
+ }
+ break;
+
+ case MOZ_GTK_SCROLLBAR_HORIZONTAL:
+ case MOZ_GTK_SCROLLBAR_TROUGH_VERTICAL:
+ {
+ if (gtk_check_version(3,20,0) == nullptr) {
+ style = ClaimStyleContext(widget);
+ moz_gtk_add_margin_border_padding(style, left, top, right, bottom);
+ ReleaseStyleContext(style);
+ if (widget == MOZ_GTK_SCROLLBAR_HORIZONTAL) {
+ style = ClaimStyleContext(MOZ_GTK_SCROLLBAR_CONTENTS_HORIZONTAL);
+ moz_gtk_add_margin_border_padding(style, left, top, right, bottom);
+ ReleaseStyleContext(style);
+ }
+ } else {
+ MozGtkScrollbarMetrics metrics;
+ moz_gtk_get_scrollbar_metrics(&metrics);
+ *left = *right = metrics.trough_border;
+ }
+ return MOZ_GTK_SUCCESS;
+ }
+ break;
+
+ case MOZ_GTK_SCROLLBAR_THUMB_HORIZONTAL:
+ case MOZ_GTK_SCROLLBAR_THUMB_VERTICAL:
+ {
+ if (gtk_check_version(3,20,0) == nullptr) {
+ style = ClaimStyleContext(widget);
+ moz_gtk_add_margin_border_padding(style, left, top, right, bottom);
+ ReleaseStyleContext(style);
+ }
+ return MOZ_GTK_SUCCESS;
+ }
+ break;
/* These widgets have no borders, since they are not containers. */
case MOZ_GTK_CHECKBUTTON_LABEL:
case MOZ_GTK_RADIOBUTTON_LABEL:
@@ -2503,10 +2285,6 @@ moz_gtk_get_widget_border(WidgetNodeType
case MOZ_GTK_CHECKBUTTON:
case MOZ_GTK_RADIOBUTTON:
case MOZ_GTK_SCROLLBAR_BUTTON:
- case MOZ_GTK_SCROLLBAR_HORIZONTAL:
- case MOZ_GTK_SCROLLBAR_VERTICAL:
- case MOZ_GTK_SCROLLBAR_THUMB_HORIZONTAL:
- case MOZ_GTK_SCROLLBAR_THUMB_VERTICAL:
case MOZ_GTK_SCALE_THUMB_HORIZONTAL:
case MOZ_GTK_SCALE_THUMB_VERTICAL:
case MOZ_GTK_GRIPPER:
@@ -2540,35 +2318,48 @@ moz_gtk_get_widget_border(WidgetNodeType
gint
moz_gtk_get_tab_border(gint* left, gint* top, gint* right, gint* bottom,
- GtkTextDirection direction, GtkTabFlags flags)
+ GtkTextDirection direction, GtkTabFlags flags,
+ WidgetNodeType widget)
{
- GtkStyleContext* style;
- int tab_curvature;
-
- ensure_tab_widget();
-
- style = gtk_widget_get_style_context(gTabWidget);
- gtk_style_context_save(style);
- moz_gtk_tab_prepare_style_context(style, flags);
+ GtkStyleContext* style = ClaimStyleContext(widget, direction,
+ GetStateFlagsFromGtkTabFlags(flags));
*left = *top = *right = *bottom = 0;
moz_gtk_add_style_padding(style, left, top, right, bottom);
- gtk_style_context_get_style(style, "tab-curvature", &tab_curvature, NULL);
- *left += tab_curvature;
- *right += tab_curvature;
+ // Gtk >= 3.20 does not use those styles
+ if (gtk_check_version(3, 20, 0) != nullptr) {
+ int tab_curvature;
- if (flags & MOZ_GTK_TAB_FIRST) {
- int initial_gap;
- gtk_style_context_get_style(style, "initial-gap", &initial_gap, NULL);
- if (direction == GTK_TEXT_DIR_RTL)
- *right += initial_gap;
- else
- *left += initial_gap;
- }
+ gtk_style_context_get_style(style, "tab-curvature", &tab_curvature, NULL);
+ *left += tab_curvature;
+ *right += tab_curvature;
+
+ if (flags & MOZ_GTK_TAB_FIRST) {
+ int initial_gap = 0;
+ gtk_style_context_get_style(style, "initial-gap", &initial_gap, NULL);
+ if (direction == GTK_TEXT_DIR_RTL)
+ *right += initial_gap;
+ else
+ *left += initial_gap;
+ }
+ } else {
+ GtkBorder margin;
- gtk_style_context_restore(style);
+ gtk_style_context_get_margin(style, GTK_STATE_FLAG_NORMAL, &margin);
+ *left += margin.left;
+ *right += margin.right;
+ if (flags & MOZ_GTK_TAB_FIRST) {
+ ReleaseStyleContext(style);
+ style = ClaimStyleContext(MOZ_GTK_NOTEBOOK_HEADER, direction);
+ gtk_style_context_get_margin(style, GTK_STATE_FLAG_NORMAL, &margin);
+ *left += margin.left;
+ *right += margin.right;
+ }
+ }
+
+ ReleaseStyleContext(style);
return MOZ_GTK_SUCCESS;
}
@@ -2581,9 +2372,9 @@ moz_gtk_get_combo_box_entry_button_size(
* as well as the minimum arrow size and its padding
* */
GtkRequisition requisition;
- ensure_combo_box_entry_widgets();
- gtk_widget_get_preferred_size(gComboBoxEntryButtonWidget, NULL, &requisition);
+ gtk_widget_get_preferred_size(GetWidget(MOZ_GTK_COMBOBOX_ENTRY_BUTTON),
+ NULL, &requisition);
*width = requisition.width;
*height = requisition.height;
@@ -2595,10 +2386,11 @@ moz_gtk_get_tab_scroll_arrow_size(gint*
{
gint arrow_size;
- ensure_tab_widget();
- gtk_style_context_get_style(gtk_widget_get_style_context(gTabWidget),
+ GtkStyleContext *style = ClaimStyleContext(MOZ_GTK_TABPANELS);
+ gtk_style_context_get_style(style,
"scroll-arrow-hlength", &arrow_size,
NULL);
+ ReleaseStyleContext(style);
*height = *width = arrow_size;
@@ -2611,8 +2403,7 @@ moz_gtk_get_arrow_size(WidgetNodeType wi
GtkWidget* widget;
switch (widgetType) {
case MOZ_GTK_DROPDOWN:
- ensure_combo_box_widgets();
- widget = gComboBoxArrowWidget;
+ widget = GetWidget(MOZ_GTK_COMBOBOX_ARROW);
break;
default:
widget = GetWidget(MOZ_GTK_BUTTON_ARROW);
@@ -2659,11 +2450,9 @@ moz_gtk_get_expander_size(gint* size)
gint
moz_gtk_get_treeview_expander_size(gint* size)
{
- ensure_tree_view_widget();
- gtk_style_context_get_style(gtk_widget_get_style_context(gTreeViewWidget),
- "expander-size", size,
- NULL);
-
+ GtkStyleContext* style = ClaimStyleContext(MOZ_GTK_TREEVIEW);
+ gtk_style_context_get_style(style, "expander-size", size, NULL);
+ ReleaseStyleContext(style);
return MOZ_GTK_SUCCESS;
}
@@ -2674,14 +2463,7 @@ moz_gtk_get_menu_separator_height(gint *
gboolean wide_separators;
gint separator_height;
GtkBorder padding;
- GtkStyleContext* style;
- guint border_width;
-
- border_width =
- gtk_container_get_border_width(GTK_CONTAINER(
- GetWidget(MOZ_GTK_MENUSEPARATOR)));
-
- style = ClaimStyleContext(MOZ_GTK_MENUSEPARATOR);
+ GtkStyleContext* style = ClaimStyleContext(MOZ_GTK_MENUSEPARATOR);
gtk_style_context_get_padding(style, GTK_STATE_FLAG_NORMAL, &padding);
gtk_style_context_save(style);
@@ -2695,7 +2477,7 @@ moz_gtk_get_menu_separator_height(gint *
gtk_style_context_restore(style);
ReleaseStyleContext(style);
- *size = padding.top + padding.bottom + border_width*2;
+ *size = padding.top + padding.bottom;
*size += (wide_separators) ? separator_height : 1;
return MOZ_GTK_SUCCESS;
@@ -2726,34 +2508,60 @@ void
moz_gtk_get_scale_metrics(GtkOrientation orient, gint* scale_width,
gint* scale_height)
{
- gint thumb_length, thumb_height, trough_border;
- GtkWidget* widget = orient == GTK_ORIENTATION_HORIZONTAL ?
- gHScaleWidget : gVScaleWidget;
- moz_gtk_get_scalethumb_metrics(orient, &thumb_length, &thumb_height);
- gtk_style_context_get_style(gtk_widget_get_style_context(widget),
- "trough-border", &trough_border, NULL);
-
- if (orient == GTK_ORIENTATION_HORIZONTAL) {
- *scale_width = thumb_length + trough_border * 2;
- *scale_height = thumb_height + trough_border * 2;
+ WidgetNodeType widget = (orient == GTK_ORIENTATION_HORIZONTAL) ?
+ MOZ_GTK_SCALE_HORIZONTAL :
+ MOZ_GTK_SCALE_VERTICAL;
+
+ if (gtk_check_version(3, 20, 0) != nullptr) {
+ gint thumb_length, thumb_height, trough_border;
+ moz_gtk_get_scalethumb_metrics(orient, &thumb_length, &thumb_height);
+
+ GtkStyleContext* style = ClaimStyleContext(widget);
+ gtk_style_context_get_style(style, "trough-border", &trough_border, NULL);
+
+ if (orient == GTK_ORIENTATION_HORIZONTAL) {
+ *scale_width = thumb_length + trough_border * 2;
+ *scale_height = thumb_height + trough_border * 2;
+ } else {
+ *scale_width = thumb_height + trough_border * 2;
+ *scale_height = thumb_length + trough_border * 2;
+ }
+ ReleaseStyleContext(style);
} else {
- *scale_width = thumb_height + trough_border * 2;
- *scale_height = thumb_length + trough_border * 2;
+ GtkStyleContext* style = ClaimStyleContext(widget);
+ gtk_style_context_get(style, gtk_style_context_get_state(style),
+ "min-width", scale_width,
+ "min-height", scale_height,
+ nullptr);
+ ReleaseStyleContext(style);
}
}
gint
moz_gtk_get_scalethumb_metrics(GtkOrientation orient, gint* thumb_length, gint* thumb_height)
{
- GtkWidget* widget;
- ensure_scale_widget();
- widget = ((orient == GTK_ORIENTATION_HORIZONTAL) ? gHScaleWidget : gVScaleWidget);
-
- gtk_style_context_get_style(gtk_widget_get_style_context(widget),
- "slider_length", thumb_length,
- "slider_width", thumb_height,
- NULL);
+ if (gtk_check_version(3, 20, 0) != nullptr) {
+ WidgetNodeType widget = (orient == GTK_ORIENTATION_HORIZONTAL) ?
+ MOZ_GTK_SCALE_HORIZONTAL:
+ MOZ_GTK_SCALE_VERTICAL;
+ GtkStyleContext* style = ClaimStyleContext(widget);
+ gtk_style_context_get_style(style,
+ "slider_length", thumb_length,
+ "slider_width", thumb_height,
+ NULL);
+ ReleaseStyleContext(style);
+ } else {
+ WidgetNodeType widget = (orient == GTK_ORIENTATION_HORIZONTAL) ?
+ MOZ_GTK_SCALE_THUMB_HORIZONTAL:
+ MOZ_GTK_SCALE_THUMB_VERTICAL;
+ GtkStyleContext* style = ClaimStyleContext(widget);
+ gtk_style_context_get(style, gtk_style_context_get_state(style),
+ "min-width", thumb_length,
+ "min-height", thumb_height,
+ nullptr);
+ ReleaseStyleContext(style);
+ }
return MOZ_GTK_SUCCESS;
}
@@ -2761,6 +2569,9 @@ moz_gtk_get_scalethumb_metrics(GtkOrient
gint
moz_gtk_get_scrollbar_metrics(MozGtkScrollbarMetrics *metrics)
{
+ // For Gtk >= 3.20 scrollbar metrics are ignored
+ MOZ_ASSERT(gtk_check_version(3, 20, 0) != nullptr);
+
GtkStyleContext* style = ClaimStyleContext(MOZ_GTK_SCROLLBAR_VERTICAL);
gtk_style_context_get_style(style,
"slider_width", &metrics->slider_width,
@@ -2771,41 +2582,9 @@ moz_gtk_get_scrollbar_metrics(MozGtkScro
nullptr);
ReleaseStyleContext(style);
- if(!gtk_check_version(3, 20, 0)) {
- style = ClaimStyleContext(MOZ_GTK_SCROLLBAR_THUMB_VERTICAL);
- gtk_style_context_get(style, gtk_style_context_get_state(style),
- "min-height", &metrics->min_slider_size, nullptr);
- ReleaseStyleContext(style);
- }
-
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;
-}
-
-gboolean
-moz_gtk_images_in_buttons()
-{
- gboolean result;
- GtkSettings* settings;
-
- settings = gtk_widget_get_settings(GetWidget(MOZ_GTK_BUTTON));
-
- g_object_get(settings, "gtk-button-images", &result, NULL);
- return result;
-}
-
/* cairo_t *cr argument has to be a system-cairo. */
gint
moz_gtk_widget_paint(WidgetNodeType widget, cairo_t *cr,
@@ -2846,10 +2625,25 @@ moz_gtk_widget_paint(WidgetNodeType widg
break;
case MOZ_GTK_SCROLLBAR_HORIZONTAL:
case MOZ_GTK_SCROLLBAR_VERTICAL:
- return moz_gtk_scrollbar_trough_paint(widget, cr, rect,
- state,
- (GtkScrollbarTrackFlags) flags,
- direction);
+ if (gtk_check_version(3,20,0) == nullptr) {
+ return moz_gtk_scrollbar_paint(widget, cr, rect, state, direction);
+ } else {
+ WidgetNodeType trough_widget = (widget == MOZ_GTK_SCROLLBAR_HORIZONTAL) ?
+ MOZ_GTK_SCROLLBAR_TROUGH_HORIZONTAL : MOZ_GTK_SCROLLBAR_TROUGH_VERTICAL;
+ return moz_gtk_scrollbar_trough_paint(trough_widget, cr, rect,
+ state,
+ (GtkScrollbarTrackFlags) flags,
+ direction);
+ }
+ break;
+ case MOZ_GTK_SCROLLBAR_TROUGH_HORIZONTAL:
+ case MOZ_GTK_SCROLLBAR_TROUGH_VERTICAL:
+ if (gtk_check_version(3,20,0) == nullptr) {
+ return moz_gtk_scrollbar_trough_paint(widget, cr, rect,
+ state,
+ (GtkScrollbarTrackFlags) flags,
+ direction);
+ }
break;
case MOZ_GTK_SCROLLBAR_THUMB_HORIZONTAL:
case MOZ_GTK_SCROLLBAR_THUMB_VERTICAL:
@@ -2876,9 +2670,13 @@ moz_gtk_widget_paint(WidgetNodeType widg
state, direction);
break;
case MOZ_GTK_SPINBUTTON_ENTRY:
- // TODO - use MOZ_GTK_SPINBUTTON_ENTRY style directly
- return moz_gtk_entry_paint(cr, rect, state,
- GetWidget(MOZ_GTK_SPINBUTTON), direction);
+ {
+ GtkStyleContext* style = ClaimStyleContext(MOZ_GTK_SPINBUTTON_ENTRY,
+ direction, GetStateFlagsFromGtkWidgetState(state));
+ gint ret = moz_gtk_entry_paint(cr, rect, state, style);
+ ReleaseStyleContext(style);
+ return ret;
+ }
break;
case MOZ_GTK_GRIPPER:
return moz_gtk_gripper_paint(cr, rect, state,
@@ -2903,9 +2701,13 @@ moz_gtk_widget_paint(WidgetNodeType widg
(GtkExpanderStyle) flags, direction);
break;
case MOZ_GTK_ENTRY:
- return moz_gtk_entry_paint(cr, rect, state, GetWidget(MOZ_GTK_ENTRY),
- direction);
- break;
+ {
+ GtkStyleContext* style = ClaimStyleContext(MOZ_GTK_ENTRY,
+ direction, GetStateFlagsFromGtkWidgetState(state));
+ gint ret = moz_gtk_entry_paint(cr, rect, state, style);
+ ReleaseStyleContext(style);
+ return ret;
+ }
case MOZ_GTK_TEXT_VIEW:
return moz_gtk_text_view_paint(cr, rect, state, direction);
break;
@@ -2917,9 +2719,13 @@ moz_gtk_widget_paint(WidgetNodeType widg
state, flags, direction);
break;
case MOZ_GTK_DROPDOWN_ENTRY:
- ensure_combo_box_entry_widgets();
- return moz_gtk_entry_paint(cr, rect, state,
- gComboBoxEntryTextareaWidget, direction);
+ {
+ GtkStyleContext* style = ClaimStyleContext(MOZ_GTK_COMBOBOX_ENTRY_TEXTAREA,
+ direction, GetStateFlagsFromGtkWidgetState(state));
+ gint ret = moz_gtk_entry_paint(cr, rect, state, style);
+ ReleaseStyleContext(style);
+ return ret;
+ }
break;
case MOZ_GTK_CHECKBUTTON_CONTAINER:
case MOZ_GTK_RADIOBUTTON_CONTAINER:
@@ -2957,9 +2763,10 @@ moz_gtk_widget_paint(WidgetNodeType widg
return moz_gtk_progress_chunk_paint(cr, rect,
direction, widget);
break;
- case MOZ_GTK_TAB:
+ case MOZ_GTK_TAB_TOP:
+ case MOZ_GTK_TAB_BOTTOM:
return moz_gtk_tab_paint(cr, rect, state,
- (GtkTabFlags) flags, direction);
+ (GtkTabFlags) flags, direction, widget);
break;
case MOZ_GTK_TABPANELS:
return moz_gtk_tabpanels_paint(cr, rect, direction);
@@ -2992,10 +2799,8 @@ moz_gtk_widget_paint(WidgetNodeType widg
break;
case MOZ_GTK_CHECKMENUITEM:
case MOZ_GTK_RADIOMENUITEM:
- return moz_gtk_check_menu_item_paint(cr, rect, state,
- (gboolean) flags,
- (widget == MOZ_GTK_RADIOMENUITEM),
- direction);
+ return moz_gtk_check_menu_item_paint(widget, cr, rect, state,
+ (gboolean) flags, direction);
break;
case MOZ_GTK_SPLITTER_HORIZONTAL:
return moz_gtk_vpaned_paint(cr, rect, state);
@@ -3043,31 +2848,6 @@ moz_gtk_shutdown()
/* This will destroy all of our widgets */
ResetWidgetCache();
- /* TODO - replace it with appropriate widget */
- if (gTreeHeaderSortArrowWidget)
- gtk_widget_destroy(gTreeHeaderSortArrowWidget);
-
- gProtoLayout = NULL;
- gHScaleWidget = NULL;
- gVScaleWidget = NULL;
- gComboBoxWidget = NULL;
- gComboBoxButtonWidget = NULL;
- gComboBoxSeparatorWidget = NULL;
- gComboBoxArrowWidget = NULL;
- gComboBoxEntryWidget = NULL;
- gComboBoxEntryButtonWidget = NULL;
- gComboBoxEntryArrowWidget = NULL;
- gComboBoxEntryTextareaWidget = NULL;
- gTabWidget = NULL;
- gImageMenuItemWidget = NULL;
- gCheckMenuItemWidget = NULL;
- gTreeViewWidget = NULL;
- gMiddleTreeViewColumn = NULL;
- gTreeHeaderCellWidget = NULL;
- gTreeHeaderSortArrowWidget = NULL;
- gHPanedWidget = NULL;
- gVPanedWidget = NULL;
-
is_initialized = FALSE;
return MOZ_GTK_SUCCESS;
diff -up firefox-50.0/widget/gtk/gtkdrawing.h.widget-rebase firefox-50.0/widget/gtk/gtkdrawing.h
--- firefox-50.0/widget/gtk/gtkdrawing.h.widget-rebase 2016-10-31 21:15:38.000000000 +0100
+++ firefox-50.0/widget/gtk/gtkdrawing.h 2016-11-24 11:57:52.034064779 +0100
@@ -61,8 +61,6 @@ typedef enum {
typedef enum {
/* first eight bits are used to pass a margin */
MOZ_GTK_TAB_MARGIN_MASK = 0xFF,
- /* bottom tabs */
- MOZ_GTK_TAB_BOTTOM = 1 << 8,
/* the first tab in the group */
MOZ_GTK_TAB_FIRST = 1 << 9,
/* the selected tab */
@@ -128,6 +126,11 @@ typedef enum {
/* Paints a GtkScale. */
MOZ_GTK_SCALE_HORIZONTAL,
MOZ_GTK_SCALE_VERTICAL,
+ /* Paints a GtkScale trough. */
+ MOZ_GTK_SCALE_CONTENTS_HORIZONTAL,
+ MOZ_GTK_SCALE_CONTENTS_VERTICAL,
+ MOZ_GTK_SCALE_TROUGH_HORIZONTAL,
+ MOZ_GTK_SCALE_TROUGH_VERTICAL,
/* Paints a GtkScale thumb. */
MOZ_GTK_SCALE_THUMB_HORIZONTAL,
MOZ_GTK_SCALE_THUMB_VERTICAL,
@@ -173,14 +176,22 @@ typedef enum {
MOZ_GTK_PROGRESS_CHUNK_INDETERMINATE,
/* Paints a progress chunk of a vertical indeterminated GtkProgressBar. */
MOZ_GTK_PROGRESS_CHUNK_VERTICAL_INDETERMINATE,
+ /* Used as root style of whole GtkNotebook widget */
+ MOZ_GTK_NOTEBOOK,
+ /* Used as root style of active GtkNotebook area which contains tabs and arrows. */
+ MOZ_GTK_NOTEBOOK_HEADER,
/* Paints a tab of a GtkNotebook. flags is a GtkTabFlags, defined above. */
- MOZ_GTK_TAB,
+ MOZ_GTK_TAB_TOP,
+ /* Paints a tab of a GtkNotebook. flags is a GtkTabFlags, defined above. */
+ MOZ_GTK_TAB_BOTTOM,
/* Paints the background and border of a GtkNotebook. */
MOZ_GTK_TABPANELS,
/* Paints a GtkArrow for a GtkNotebook. flags is a GtkArrowType. */
MOZ_GTK_TAB_SCROLLARROW,
- /* Paints the background and border of a GtkTreeView */
+ /* Paints the expander and border of a GtkTreeView */
MOZ_GTK_TREEVIEW,
+ /* Paints the border of a GtkTreeView */
+ MOZ_GTK_TREEVIEW_VIEW,
/* Paints treeheader cells */
MOZ_GTK_TREE_HEADER_CELL,
/* Paints sort arrows in treeheader cells */
@@ -199,19 +210,44 @@ typedef enum {
MOZ_GTK_MENUBARITEM,
/* Paints items of popup menus. */
MOZ_GTK_MENUITEM,
+ /* Paints a menuitem with check indicator, or the gets the style context for
+ a menuitem that contains a checkbox. */
MOZ_GTK_CHECKMENUITEM,
+ /* Gets the style context for a checkbox in a check menuitem. */
+ MOZ_GTK_CHECKMENUITEM_INDICATOR,
MOZ_GTK_RADIOMENUITEM,
+ MOZ_GTK_RADIOMENUITEM_INDICATOR,
MOZ_GTK_MENUSEPARATOR,
- /* Paints a GtkVPaned separator */
+ /* GtkVPaned base class */
MOZ_GTK_SPLITTER_HORIZONTAL,
- /* Paints a GtkHPaned separator */
+ /* GtkHPaned base class */
MOZ_GTK_SPLITTER_VERTICAL,
+ /* Paints a GtkVPaned separator */
+ MOZ_GTK_SPLITTER_SEPARATOR_HORIZONTAL,
+ /* Paints a GtkHPaned separator */
+ MOZ_GTK_SPLITTER_SEPARATOR_VERTICAL,
/* Paints the background of a window, dialog or page. */
MOZ_GTK_WINDOW,
/* Window container for all widgets */
MOZ_GTK_WINDOW_CONTAINER,
/* Paints a GtkInfoBar, for notifications. */
MOZ_GTK_INFO_BAR,
+ /* Used for widget tree construction. */
+ MOZ_GTK_COMBOBOX,
+ /* Paints a GtkComboBox button widget. */
+ MOZ_GTK_COMBOBOX_BUTTON,
+ /* Paints a GtkComboBox arrow widget. */
+ MOZ_GTK_COMBOBOX_ARROW,
+ /* Paints a GtkComboBox separator widget. */
+ MOZ_GTK_COMBOBOX_SEPARATOR,
+ /* Used for widget tree construction. */
+ MOZ_GTK_COMBOBOX_ENTRY,
+ /* Paints a GtkComboBox entry widget. */
+ MOZ_GTK_COMBOBOX_ENTRY_TEXTAREA,
+ /* Paints a GtkComboBox entry button widget. */
+ MOZ_GTK_COMBOBOX_ENTRY_BUTTON,
+ /* Paints a GtkComboBox entry arrow widget. */
+ MOZ_GTK_COMBOBOX_ENTRY_ARROW,
/* Used for scrolled window shell. */
MOZ_GTK_SCROLLED_WINDOW,
@@ -300,12 +336,14 @@ gint moz_gtk_get_widget_border(WidgetNod
* top/bottom: [OUT] the tab's top/bottom border
* direction: the text direction for the widget
* flags: tab-dependant flags; see the GtkTabFlags definition.
+ * widget: tab widget
*
* returns: MOZ_GTK_SUCCESS if there was no error, an error code otherwise
*/
gint
moz_gtk_get_tab_border(gint* left, gint* top, gint* right, gint* bottom,
- GtkTextDirection direction, GtkTabFlags flags);
+ GtkTextDirection direction, GtkTabFlags flags,
+ WidgetNodeType widget);
/**
* Get the desired size of a GtkCheckButton
@@ -481,19 +519,8 @@ GtkWidget* moz_gtk_get_scrollbar_widget(
/**
* Get the YTHICKNESS of a tab (notebook extension).
*/
-gint moz_gtk_get_tab_thickness(void);
-
-/**
- * Get a boolean which indicates whether or not to use images in menus.
- * If TRUE, use images in menus.
- */
-gboolean moz_gtk_images_in_menus(void);
-
-/**
- * Get a boolean which indicates whether or not to use images in buttons.
- * If TRUE, use images in buttons.
- */
-gboolean moz_gtk_images_in_buttons(void);
+gint
+moz_gtk_get_tab_thickness(WidgetNodeType aNodeType);
/**
* Get a boolean which indicates whether the theme draws scrollbar buttons.
@@ -501,6 +528,13 @@ gboolean moz_gtk_images_in_buttons(void)
*/
gboolean moz_gtk_has_scrollbar_buttons(void);
+/**
+ * Get minimum widget size as sum of margin, padding, border and min-width,
+ * min-height.
+ */
+void moz_gtk_get_widget_min_size(WidgetNodeType aGtkWidgetType, int* width,
+ int* height);
+
#if (MOZ_WIDGET_GTK == 2)
#ifdef __cplusplus
}
diff -up firefox-50.0/widget/gtk/mozgtk/mozgtk.c.widget-rebase firefox-50.0/widget/gtk/mozgtk/mozgtk.c
--- firefox-50.0/widget/gtk/mozgtk/mozgtk.c.widget-rebase 2016-10-31 21:15:38.000000000 +0100
+++ firefox-50.0/widget/gtk/mozgtk/mozgtk.c 2016-11-24 11:57:52.034064779 +0100
@@ -9,6 +9,7 @@ STUB(gdk_atom_name)
STUB(gdk_beep)
STUB(gdk_cairo_create)
STUB(gdk_color_free)
+STUB(gdk_color_parse)
STUB(gdk_cursor_new_for_display)
STUB(gdk_cursor_new_from_name)
STUB(gdk_cursor_new_from_pixbuf)
@@ -244,7 +245,6 @@ STUB(gtk_icon_theme_get_icon_sizes)
STUB(gtk_icon_theme_lookup_by_gicon)
STUB(gtk_icon_theme_lookup_icon)
STUB(gtk_image_get_type)
-STUB(gtk_image_menu_item_new)
STUB(gtk_image_new)
STUB(gtk_image_new_from_stock)
STUB(gtk_image_set_from_pixbuf)
@@ -530,6 +530,7 @@ STUB(gtk_get_minor_version)
STUB(gtk_menu_button_new)
STUB(gtk_offscreen_window_new)
STUB(gtk_paned_new)
+STUB(gtk_radio_menu_item_new)
STUB(gtk_render_activity)
STUB(gtk_render_arrow)
STUB(gtk_render_background)
@@ -561,6 +562,7 @@ STUB(gtk_style_context_get_state)
STUB(gtk_style_context_get_style)
STUB(gtk_style_context_has_class)
STUB(gtk_style_context_invalidate)
+STUB(gtk_style_context_list_classes)
STUB(gtk_style_context_new)
STUB(gtk_style_context_remove_class)
STUB(gtk_style_context_remove_region)
@@ -575,10 +577,10 @@ STUB(gtk_tree_view_column_get_button)
STUB(gtk_widget_get_preferred_size)
STUB(gtk_widget_get_state_flags)
STUB(gtk_widget_get_style_context)
-STUB(gtk_widget_path_append_for_widget)
STUB(gtk_widget_path_append_type)
STUB(gtk_widget_path_copy)
STUB(gtk_widget_path_free)
+STUB(gtk_widget_path_iter_add_class)
STUB(gtk_widget_path_new)
STUB(gtk_widget_path_unref)
STUB(gtk_widget_set_visual)
diff -up firefox-50.0/widget/gtk/nsLookAndFeel.cpp.widget-rebase firefox-50.0/widget/gtk/nsLookAndFeel.cpp
--- firefox-50.0/widget/gtk/nsLookAndFeel.cpp.widget-rebase 2016-11-24 12:00:04.563704500 +0100
+++ firefox-50.0/widget/gtk/nsLookAndFeel.cpp 2016-11-24 12:00:47.316588277 +0100
@@ -786,10 +786,10 @@ nsLookAndFeel::GetIntImpl(IntID aID, int
aResult = NS_STYLE_TEXT_DECORATION_STYLE_WAVY;
break;
case eIntID_ImagesInMenus:
- aResult = moz_gtk_images_in_menus();
+ aResult = 0;
break;
case eIntID_ImagesInButtons:
- aResult = moz_gtk_images_in_buttons();
+ aResult = 0;
break;
case eIntID_MenuBarDrag:
aResult = sMenuSupportsDrag;
diff -up firefox-50.0/widget/gtk/nsNativeThemeGTK.cpp.widget-rebase firefox-50.0/widget/gtk/nsNativeThemeGTK.cpp
--- firefox-50.0/widget/gtk/nsNativeThemeGTK.cpp.widget-rebase 2016-10-31 21:15:38.000000000 +0100
+++ firefox-50.0/widget/gtk/nsNativeThemeGTK.cpp 2016-11-24 11:57:52.034064779 +0100
@@ -149,19 +149,15 @@ static void SetWidgetStateSafe(uint8_t *
aSafeVector[key >> 3] |= (1 << (key & 7));
}
-static GtkTextDirection GetTextDirection(nsIFrame* aFrame)
+/* static */ GtkTextDirection
+nsNativeThemeGTK::GetTextDirection(nsIFrame* aFrame)
{
- if (!aFrame)
- return GTK_TEXT_DIR_NONE;
-
- switch (aFrame->StyleVisibility()->mDirection) {
- case NS_STYLE_DIRECTION_RTL:
- return GTK_TEXT_DIR_RTL;
- case NS_STYLE_DIRECTION_LTR:
- return GTK_TEXT_DIR_LTR;
- }
-
- return GTK_TEXT_DIR_NONE;
+ // IsFrameRTL() treats vertical-rl modes as right-to-left (in addition to
+ // horizontal text with direction=RTL), rather than just considering the
+ // text direction. GtkTextDirection does not have distinct values for
+ // vertical writing modes, but considering the block flow direction is
+ // important for resizers and scrollbar elements, at least.
+ return IsFrameRTL(aFrame) ? GTK_TEXT_DIR_RTL : GTK_TEXT_DIR_LTR;
}
// Returns positive for negative margins (otherwise 0).
@@ -193,205 +189,199 @@ nsNativeThemeGTK::GetGtkWidgetAndState(u
gint* aWidgetFlags)
{
if (aState) {
- if (!aFrame) {
- // reset the entire struct to zero
- memset(aState, 0, sizeof(GtkWidgetState));
- } else {
+ // For XUL checkboxes and radio buttons, the state of the parent
+ // determines our state.
+ nsIFrame *stateFrame = aFrame;
+ if (aFrame && ((aWidgetFlags && (aWidgetType == NS_THEME_CHECKBOX ||
+ aWidgetType == NS_THEME_RADIO)) ||
+ aWidgetType == NS_THEME_CHECKBOX_LABEL ||
+ aWidgetType == NS_THEME_RADIO_LABEL)) {
- // For XUL checkboxes and radio buttons, the state of the parent
- // determines our state.
- nsIFrame *stateFrame = aFrame;
- if (aFrame && ((aWidgetFlags && (aWidgetType == NS_THEME_CHECKBOX ||
- aWidgetType == NS_THEME_RADIO)) ||
- aWidgetType == NS_THEME_CHECKBOX_LABEL ||
- aWidgetType == NS_THEME_RADIO_LABEL)) {
-
- nsIAtom* atom = nullptr;
- if (IsFrameContentNodeInNamespace(aFrame, kNameSpaceID_XUL)) {
- if (aWidgetType == NS_THEME_CHECKBOX_LABEL ||
- aWidgetType == NS_THEME_RADIO_LABEL) {
- // Adjust stateFrame so GetContentState finds the correct state.
- stateFrame = aFrame = aFrame->GetParent()->GetParent();
- } else {
- // GetContentState knows to look one frame up for radio/checkbox
- // widgets, so don't adjust stateFrame here.
- aFrame = aFrame->GetParent();
+ nsIAtom* atom = nullptr;
+ if (IsFrameContentNodeInNamespace(aFrame, kNameSpaceID_XUL)) {
+ if (aWidgetType == NS_THEME_CHECKBOX_LABEL ||
+ aWidgetType == NS_THEME_RADIO_LABEL) {
+ // Adjust stateFrame so GetContentState finds the correct state.
+ stateFrame = aFrame = aFrame->GetParent()->GetParent();
+ } else {
+ // GetContentState knows to look one frame up for radio/checkbox
+ // widgets, so don't adjust stateFrame here.
+ aFrame = aFrame->GetParent();
+ }
+ if (aWidgetFlags) {
+ if (!atom) {
+ atom = (aWidgetType == NS_THEME_CHECKBOX ||
+ aWidgetType == NS_THEME_CHECKBOX_LABEL) ? nsGkAtoms::checked
+ : nsGkAtoms::selected;
}
- if (aWidgetFlags) {
- if (!atom) {
- atom = (aWidgetType == NS_THEME_CHECKBOX ||
- aWidgetType == NS_THEME_CHECKBOX_LABEL) ? nsGkAtoms::checked
- : nsGkAtoms::selected;
- }
- *aWidgetFlags = CheckBooleanAttr(aFrame, atom);
+ *aWidgetFlags = CheckBooleanAttr(aFrame, atom);
+ }
+ } else {
+ if (aWidgetFlags) {
+ nsCOMPtr<nsIDOMHTMLInputElement> inputElt(do_QueryInterface(aFrame->GetContent()));
+ *aWidgetFlags = 0;
+ if (inputElt) {
+ bool isHTMLChecked;
+ inputElt->GetChecked(&isHTMLChecked);
+ if (isHTMLChecked)
+ *aWidgetFlags |= MOZ_GTK_WIDGET_CHECKED;
}
- } else {
- if (aWidgetFlags) {
- nsCOMPtr<nsIDOMHTMLInputElement> inputElt(do_QueryInterface(aFrame->GetContent()));
- *aWidgetFlags = 0;
- if (inputElt) {
- bool isHTMLChecked;
- inputElt->GetChecked(&isHTMLChecked);
- if (isHTMLChecked)
- *aWidgetFlags |= MOZ_GTK_WIDGET_CHECKED;
- }
- if (GetIndeterminate(aFrame))
- *aWidgetFlags |= MOZ_GTK_WIDGET_INCONSISTENT;
- }
+ if (GetIndeterminate(aFrame))
+ *aWidgetFlags |= MOZ_GTK_WIDGET_INCONSISTENT;
}
- } else if (aWidgetType == NS_THEME_TOOLBARBUTTON_DROPDOWN ||
- aWidgetType == NS_THEME_TREEHEADERSORTARROW ||
- aWidgetType == NS_THEME_BUTTON_ARROW_PREVIOUS ||
- aWidgetType == NS_THEME_BUTTON_ARROW_NEXT ||
- aWidgetType == NS_THEME_BUTTON_ARROW_UP ||
- aWidgetType == NS_THEME_BUTTON_ARROW_DOWN) {
- // The state of an arrow comes from its parent.
- stateFrame = aFrame = aFrame->GetParent();
- }
-
- EventStates eventState = GetContentState(stateFrame, aWidgetType);
-
- aState->disabled = IsDisabled(aFrame, eventState) || IsReadOnly(aFrame);
- aState->active = eventState.HasState(NS_EVENT_STATE_ACTIVE);
- aState->focused = eventState.HasState(NS_EVENT_STATE_FOCUS);
- aState->inHover = eventState.HasState(NS_EVENT_STATE_HOVER);
- aState->isDefault = IsDefaultButton(aFrame);
- aState->canDefault = FALSE; // XXX fix me
- aState->depressed = FALSE;
-
- if (aWidgetType == NS_THEME_FOCUS_OUTLINE) {
- aState->disabled = FALSE;
- aState->active = FALSE;
- aState->inHover = FALSE;
- aState->isDefault = FALSE;
- aState->canDefault = FALSE;
-
- aState->focused = TRUE;
- aState->depressed = TRUE; // see moz_gtk_entry_paint()
- } else if (aWidgetType == NS_THEME_BUTTON ||
- aWidgetType == NS_THEME_TOOLBARBUTTON ||
- aWidgetType == NS_THEME_DUALBUTTON ||
- aWidgetType == NS_THEME_TOOLBARBUTTON_DROPDOWN ||
- aWidgetType == NS_THEME_MENULIST ||
- aWidgetType == NS_THEME_MENULIST_BUTTON) {
- aState->active &= aState->inHover;
}
-
- if (IsFrameContentNodeInNamespace(aFrame, kNameSpaceID_XUL)) {
- // For these widget types, some element (either a child or parent)
- // actually has element focus, so we check the focused attribute
- // to see whether to draw in the focused state.
- if (aWidgetType == NS_THEME_NUMBER_INPUT ||
- aWidgetType == NS_THEME_TEXTFIELD ||
- aWidgetType == NS_THEME_TEXTFIELD_MULTILINE ||
- aWidgetType == NS_THEME_MENULIST_TEXTFIELD ||
- aWidgetType == NS_THEME_SPINNER_TEXTFIELD ||
- aWidgetType == NS_THEME_RADIO_CONTAINER ||
- aWidgetType == NS_THEME_RADIO_LABEL) {
- aState->focused = IsFocused(aFrame);
- } else if (aWidgetType == NS_THEME_RADIO ||
- aWidgetType == NS_THEME_CHECKBOX) {
- // In XUL, checkboxes and radios shouldn't have focus rings, their labels do
- aState->focused = FALSE;
+ } else if (aWidgetType == NS_THEME_TOOLBARBUTTON_DROPDOWN ||
+ aWidgetType == NS_THEME_TREEHEADERSORTARROW ||
+ aWidgetType == NS_THEME_BUTTON_ARROW_PREVIOUS ||
+ aWidgetType == NS_THEME_BUTTON_ARROW_NEXT ||
+ aWidgetType == NS_THEME_BUTTON_ARROW_UP ||
+ aWidgetType == NS_THEME_BUTTON_ARROW_DOWN) {
+ // The state of an arrow comes from its parent.
+ stateFrame = aFrame = aFrame->GetParent();
+ }
+
+ EventStates eventState = GetContentState(stateFrame, aWidgetType);
+
+ aState->disabled = IsDisabled(aFrame, eventState) || IsReadOnly(aFrame);
+ aState->active = eventState.HasState(NS_EVENT_STATE_ACTIVE);
+ aState->focused = eventState.HasState(NS_EVENT_STATE_FOCUS);
+ aState->inHover = eventState.HasState(NS_EVENT_STATE_HOVER);
+ aState->isDefault = IsDefaultButton(aFrame);
+ aState->canDefault = FALSE; // XXX fix me
+ aState->depressed = FALSE;
+
+ if (aWidgetType == NS_THEME_FOCUS_OUTLINE) {
+ aState->disabled = FALSE;
+ aState->active = FALSE;
+ aState->inHover = FALSE;
+ aState->isDefault = FALSE;
+ aState->canDefault = FALSE;
+
+ aState->focused = TRUE;
+ aState->depressed = TRUE; // see moz_gtk_entry_paint()
+ } else if (aWidgetType == NS_THEME_BUTTON ||
+ aWidgetType == NS_THEME_TOOLBARBUTTON ||
+ aWidgetType == NS_THEME_DUALBUTTON ||
+ aWidgetType == NS_THEME_TOOLBARBUTTON_DROPDOWN ||
+ aWidgetType == NS_THEME_MENULIST ||
+ aWidgetType == NS_THEME_MENULIST_BUTTON) {
+ aState->active &= aState->inHover;
+ }
+
+ if (IsFrameContentNodeInNamespace(aFrame, kNameSpaceID_XUL)) {
+ // For these widget types, some element (either a child or parent)
+ // actually has element focus, so we check the focused attribute
+ // to see whether to draw in the focused state.
+ if (aWidgetType == NS_THEME_NUMBER_INPUT ||
+ aWidgetType == NS_THEME_TEXTFIELD ||
+ aWidgetType == NS_THEME_TEXTFIELD_MULTILINE ||
+ aWidgetType == NS_THEME_MENULIST_TEXTFIELD ||
+ aWidgetType == NS_THEME_SPINNER_TEXTFIELD ||
+ aWidgetType == NS_THEME_RADIO_CONTAINER ||
+ aWidgetType == NS_THEME_RADIO_LABEL) {
+ aState->focused = IsFocused(aFrame);
+ } else if (aWidgetType == NS_THEME_RADIO ||
+ aWidgetType == NS_THEME_CHECKBOX) {
+ // In XUL, checkboxes and radios shouldn't have focus rings, their labels do
+ aState->focused = FALSE;
+ }
+
+ if (aWidgetType == NS_THEME_SCROLLBARTHUMB_VERTICAL ||
+ aWidgetType == NS_THEME_SCROLLBARTHUMB_HORIZONTAL) {
+ // for scrollbars we need to go up two to go from the thumb to
+ // the slider to the actual scrollbar object
+ nsIFrame *tmpFrame = aFrame->GetParent()->GetParent();
+
+ aState->curpos = CheckIntAttr(tmpFrame, nsGkAtoms::curpos, 0);
+ aState->maxpos = CheckIntAttr(tmpFrame, nsGkAtoms::maxpos, 100);
+
+ if (CheckBooleanAttr(aFrame, nsGkAtoms::active)) {
+ aState->active = TRUE;
+ // Set hover state to emulate Gtk style of active scrollbar thumb
+ aState->inHover = TRUE;
}
+ }
- if (aWidgetType == NS_THEME_SCROLLBARTHUMB_VERTICAL ||
- aWidgetType == NS_THEME_SCROLLBARTHUMB_HORIZONTAL) {
- // for scrollbars we need to go up two to go from the thumb to
- // the slider to the actual scrollbar object
- nsIFrame *tmpFrame = aFrame->GetParent()->GetParent();
-
- aState->curpos = CheckIntAttr(tmpFrame, nsGkAtoms::curpos, 0);
- aState->maxpos = CheckIntAttr(tmpFrame, nsGkAtoms::maxpos, 100);
-
- if (CheckBooleanAttr(aFrame, nsGkAtoms::active)) {
- aState->active = TRUE;
- // Set hover state to emulate Gtk style of active scrollbar thumb
- aState->inHover = TRUE;
- }
+ if (aWidgetType == NS_THEME_SCROLLBARBUTTON_UP ||
+ aWidgetType == NS_THEME_SCROLLBARBUTTON_DOWN ||
+ aWidgetType == NS_THEME_SCROLLBARBUTTON_LEFT ||
+ aWidgetType == NS_THEME_SCROLLBARBUTTON_RIGHT) {
+ // set the state to disabled when the scrollbar is scrolled to
+ // the beginning or the end, depending on the button type.
+ int32_t curpos = CheckIntAttr(aFrame, nsGkAtoms::curpos, 0);
+ int32_t maxpos = CheckIntAttr(aFrame, nsGkAtoms::maxpos, 100);
+ if (ShouldScrollbarButtonBeDisabled(curpos, maxpos, aWidgetType)) {
+ aState->disabled = true;
}
- if (aWidgetType == NS_THEME_SCROLLBARBUTTON_UP ||
- aWidgetType == NS_THEME_SCROLLBARBUTTON_DOWN ||
- aWidgetType == NS_THEME_SCROLLBARBUTTON_LEFT ||
- aWidgetType == NS_THEME_SCROLLBARBUTTON_RIGHT) {
- // set the state to disabled when the scrollbar is scrolled to
- // the beginning or the end, depending on the button type.
- int32_t curpos = CheckIntAttr(aFrame, nsGkAtoms::curpos, 0);
- int32_t maxpos = CheckIntAttr(aFrame, nsGkAtoms::maxpos, 100);
- if (ShouldScrollbarButtonBeDisabled(curpos, maxpos, aWidgetType)) {
- aState->disabled = true;
- }
+ // In order to simulate native GTK scrollbar click behavior,
+ // we set the active attribute on the element to true if it's
+ // pressed with any mouse button.
+ // This allows us to show that it's active without setting :active
+ else if (CheckBooleanAttr(aFrame, nsGkAtoms::active))
+ aState->active = true;
+
+ if (aWidgetFlags) {
+ *aWidgetFlags = GetScrollbarButtonType(aFrame);
+ if (aWidgetType - NS_THEME_SCROLLBARBUTTON_UP < 2)
+ *aWidgetFlags |= MOZ_GTK_STEPPER_VERTICAL;
+ }
+ }
- // In order to simulate native GTK scrollbar click behavior,
- // we set the active attribute on the element to true if it's
- // pressed with any mouse button.
- // This allows us to show that it's active without setting :active
- else if (CheckBooleanAttr(aFrame, nsGkAtoms::active))
- aState->active = true;
-
- if (aWidgetFlags) {
- *aWidgetFlags = GetScrollbarButtonType(aFrame);
- if (aWidgetType - NS_THEME_SCROLLBARBUTTON_UP < 2)
- *aWidgetFlags |= MOZ_GTK_STEPPER_VERTICAL;
- }
+ // menu item state is determined by the attribute "_moz-menuactive",
+ // and not by the mouse hovering (accessibility). as a special case,
+ // menus which are children of a menu bar are only marked as prelight
+ // if they are open, not on normal hover.
+
+ if (aWidgetType == NS_THEME_MENUITEM ||
+ aWidgetType == NS_THEME_CHECKMENUITEM ||
+ aWidgetType == NS_THEME_RADIOMENUITEM ||
+ aWidgetType == NS_THEME_MENUSEPARATOR ||
+ aWidgetType == NS_THEME_MENUARROW) {
+ bool isTopLevel = false;
+ nsMenuFrame *menuFrame = do_QueryFrame(aFrame);
+ if (menuFrame) {
+ isTopLevel = menuFrame->IsOnMenuBar();
}
- // menu item state is determined by the attribute "_moz-menuactive",
- // and not by the mouse hovering (accessibility). as a special case,
- // menus which are children of a menu bar are only marked as prelight
- // if they are open, not on normal hover.
-
- if (aWidgetType == NS_THEME_MENUITEM ||
- aWidgetType == NS_THEME_CHECKMENUITEM ||
- aWidgetType == NS_THEME_RADIOMENUITEM ||
- aWidgetType == NS_THEME_MENUSEPARATOR ||
- aWidgetType == NS_THEME_MENUARROW) {
- bool isTopLevel = false;
- nsMenuFrame *menuFrame = do_QueryFrame(aFrame);
- if (menuFrame) {
- isTopLevel = menuFrame->IsOnMenuBar();
- }
+ if (isTopLevel) {
+ aState->inHover = menuFrame->IsOpen();
+ } else {
+ aState->inHover = CheckBooleanAttr(aFrame, nsGkAtoms::menuactive);
+ }
- if (isTopLevel) {
- aState->inHover = menuFrame->IsOpen();
- } else {
- aState->inHover = CheckBooleanAttr(aFrame, nsGkAtoms::menuactive);
- }
+ aState->active = FALSE;
- aState->active = FALSE;
-
- if (aWidgetType == NS_THEME_CHECKMENUITEM ||
- aWidgetType == NS_THEME_RADIOMENUITEM) {
- *aWidgetFlags = 0;
- if (aFrame && aFrame->GetContent()) {
- *aWidgetFlags = aFrame->GetContent()->
- AttrValueIs(kNameSpaceID_None, nsGkAtoms::checked,
- nsGkAtoms::_true, eIgnoreCase);
- }
+ if (aWidgetType == NS_THEME_CHECKMENUITEM ||
+ aWidgetType == NS_THEME_RADIOMENUITEM) {
+ *aWidgetFlags = 0;
+ if (aFrame && aFrame->GetContent()) {
+ *aWidgetFlags = aFrame->GetContent()->
+ AttrValueIs(kNameSpaceID_None, nsGkAtoms::checked,
+ nsGkAtoms::_true, eIgnoreCase);
}
}
+ }
- // A button with drop down menu open or an activated toggle button
- // should always appear depressed.
- if (aWidgetType == NS_THEME_BUTTON ||
- aWidgetType == NS_THEME_TOOLBARBUTTON ||
- aWidgetType == NS_THEME_DUALBUTTON ||
- aWidgetType == NS_THEME_TOOLBARBUTTON_DROPDOWN ||
- aWidgetType == NS_THEME_MENULIST ||
- aWidgetType == NS_THEME_MENULIST_BUTTON) {
- bool menuOpen = IsOpenButton(aFrame);
- aState->depressed = IsCheckedButton(aFrame) || menuOpen;
- // we must not highlight buttons with open drop down menus on hover.
- aState->inHover = aState->inHover && !menuOpen;
- }
-
- // When the input field of the drop down button has focus, some themes
- // should draw focus for the drop down button as well.
- if (aWidgetType == NS_THEME_MENULIST_BUTTON && aWidgetFlags) {
- *aWidgetFlags = CheckBooleanAttr(aFrame, nsGkAtoms::parentfocused);
- }
+ // A button with drop down menu open or an activated toggle button
+ // should always appear depressed.
+ if (aWidgetType == NS_THEME_BUTTON ||
+ aWidgetType == NS_THEME_TOOLBARBUTTON ||
+ aWidgetType == NS_THEME_DUALBUTTON ||
+ aWidgetType == NS_THEME_TOOLBARBUTTON_DROPDOWN ||
+ aWidgetType == NS_THEME_MENULIST ||
+ aWidgetType == NS_THEME_MENULIST_BUTTON) {
+ bool menuOpen = IsOpenButton(aFrame);
+ aState->depressed = IsCheckedButton(aFrame) || menuOpen;
+ // we must not highlight buttons with open drop down menus on hover.
+ aState->inHover = aState->inHover && !menuOpen;
+ }
+
+ // When the input field of the drop down button has focus, some themes
+ // should draw focus for the drop down button as well.
+ if (aWidgetType == NS_THEME_MENULIST_BUTTON && aWidgetFlags) {
+ *aWidgetFlags = CheckBooleanAttr(aFrame, nsGkAtoms::parentfocused);
}
}
}
@@ -435,6 +425,20 @@ nsNativeThemeGTK::GetGtkWidgetAndState(u
else
*aWidgetFlags = 0;
break;
+ case NS_THEME_SCROLLBARTRACK_HORIZONTAL:
+ if (gtk_check_version(3,20,0) == nullptr) {
+ aGtkWidgetType = MOZ_GTK_SCROLLBAR_TROUGH_HORIZONTAL;
+ } else {
+ return false;
+ }
+ break;
+ case NS_THEME_SCROLLBARTRACK_VERTICAL:
+ if (gtk_check_version(3,20,0) == nullptr) {
+ aGtkWidgetType = MOZ_GTK_SCROLLBAR_TROUGH_VERTICAL;
+ } else {
+ return false;
+ }
+ break;
case NS_THEME_SCROLLBARTHUMB_VERTICAL:
aGtkWidgetType = MOZ_GTK_SCROLLBAR_THUMB_VERTICAL;
break;
@@ -644,17 +648,17 @@ nsNativeThemeGTK::GetGtkWidgetAndState(u
break;
case NS_THEME_TAB:
{
+ if (IsBottomTab(aFrame)) {
+ aGtkWidgetType = MOZ_GTK_TAB_BOTTOM;
+ } else {
+ aGtkWidgetType = MOZ_GTK_TAB_TOP;
+ }
+
if (aWidgetFlags) {
/* First bits will be used to store max(0,-bmargin) where bmargin
* is the bottom margin of the tab in pixels (resp. top margin,
* for bottom tabs). */
- if (IsBottomTab(aFrame)) {
- *aWidgetFlags = MOZ_GTK_TAB_BOTTOM;
- } else {
- *aWidgetFlags = 0;
- }
-
- *aWidgetFlags |= GetTabMarginPixels(aFrame);
+ *aWidgetFlags = GetTabMarginPixels(aFrame);
if (IsSelectedTab(aFrame))
*aWidgetFlags |= MOZ_GTK_TAB_SELECTED;
@@ -662,8 +666,6 @@ nsNativeThemeGTK::GetGtkWidgetAndState(u
if (IsFirstTab(aFrame))
*aWidgetFlags |= MOZ_GTK_TAB_FIRST;
}
-
- aGtkWidgetType = MOZ_GTK_TAB;
}
break;
case NS_THEME_SPLITTER:
@@ -862,12 +864,19 @@ DrawThemeWithCairo(gfxContext* aContext,
cairo_matrix_t mat;
GfxMatrixToCairoMatrix(transform, mat);
+ nsIntSize clipSize((aDrawSize.width + aScaleFactor - 1) / aScaleFactor,
+ (aDrawSize.height + aScaleFactor - 1) / aScaleFactor);
+
#ifndef MOZ_TREE_CAIRO
// Directly use the Cairo draw target to render the widget if using system Cairo everywhere.
BorrowedCairoContext borrowCairo(aDrawTarget);
if (borrowCairo.mCairo) {
cairo_set_matrix(borrowCairo.mCairo, &mat);
+ cairo_new_path(borrowCairo.mCairo);
+ cairo_rectangle(borrowCairo.mCairo, 0, 0, clipSize.width, clipSize.height);
+ cairo_clip(borrowCairo.mCairo);
+
moz_gtk_widget_paint(aGTKWidgetType, borrowCairo.mCairo, &aGDKRect, &aState, aFlags, aDirection);
borrowCairo.Finish();
@@ -908,6 +917,10 @@ DrawThemeWithCairo(gfxContext* aContext,
cairo_set_matrix(cr, &mat);
+ cairo_new_path(cr);
+ cairo_rectangle(cr, 0, 0, clipSize.width, clipSize.height);
+ cairo_clip(cr);
+
moz_gtk_widget_paint(aGTKWidgetType, cr, &aGDKRect, &aState, aFlags, aDirection);
cairo_destroy(cr);
@@ -942,6 +955,10 @@ DrawThemeWithCairo(gfxContext* aContext,
cairo_set_matrix(cr, &mat);
+ cairo_new_path(cr);
+ cairo_rectangle(cr, 0, 0, clipSize.width, clipSize.height);
+ cairo_clip(cr);
+
moz_gtk_widget_paint(aGTKWidgetType, cr, &aGDKRect, &aState, aFlags, aDirection);
cairo_destroy(cr);
@@ -1062,7 +1079,8 @@ nsNativeThemeGTK::GetExtraSizeForWidget(
if (!IsSelectedTab(aFrame))
return false;
- gint gap_height = moz_gtk_get_tab_thickness();
+ gint gap_height = moz_gtk_get_tab_thickness(IsBottomTab(aFrame) ?
+ MOZ_GTK_TAB_BOTTOM : MOZ_GTK_TAB_TOP);
if (!gap_height)
return false;
@@ -1097,14 +1115,7 @@ nsNativeThemeGTK::DrawWidgetBackground(n
{
GtkWidgetState state;
WidgetNodeType gtkWidgetType;
- // For resizer drawing, we want IsFrameRTL, which treats vertical-rl modes
- // as right-to-left (in addition to horizontal text with direction=RTL),
- // rather than just considering the text direction.
- // This will make resizers on vertically-oriented elements render properly.
- GtkTextDirection direction =
- aWidgetType == NS_THEME_RESIZER
- ? (IsFrameRTL(aFrame) ? GTK_TEXT_DIR_RTL : GTK_TEXT_DIR_LTR)
- : GetTextDirection(aFrame);
+ GtkTextDirection direction = GetTextDirection(aFrame);
gint flags;
if (!GetGtkWidgetAndState(aWidgetType, aFrame, gtkWidgetType, &state,
&flags))
@@ -1240,6 +1251,21 @@ nsNativeThemeGTK::DrawWidgetBackground(n
return NS_OK;
}
+WidgetNodeType
+nsNativeThemeGTK::NativeThemeToGtkTheme(uint8_t aWidgetType, nsIFrame* aFrame)
+{
+ WidgetNodeType gtkWidgetType;
+ gint unusedFlags;
+
+ if (!GetGtkWidgetAndState(aWidgetType, aFrame, gtkWidgetType, nullptr,
+ &unusedFlags))
+ {
+ MOZ_ASSERT_UNREACHABLE("Unknown native widget to gtk widget mapping");
+ return MOZ_GTK_WINDOW;
+ }
+ return gtkWidgetType;
+}
+
NS_IMETHODIMP
nsNativeThemeGTK::GetWidgetBorder(nsDeviceContext* aContext, nsIFrame* aFrame,
uint8_t aWidgetType, nsIntMargin* aResult)
@@ -1247,24 +1273,6 @@ nsNativeThemeGTK::GetWidgetBorder(nsDevi
GtkTextDirection direction = GetTextDirection(aFrame);
aResult->top = aResult->left = aResult->right = aResult->bottom = 0;
switch (aWidgetType) {
- case NS_THEME_SCROLLBAR_VERTICAL:
- case NS_THEME_SCROLLBARTRACK_HORIZONTAL:
- {
- MozGtkScrollbarMetrics metrics;
- moz_gtk_get_scrollbar_metrics(&metrics);
- /* Top and bottom border for whole vertical scrollbar, top and bottom
- * border for horizontal track - to correctly position thumb element */
- aResult->top = aResult->bottom = metrics.trough_border;
- }
- break;
- case NS_THEME_SCROLLBAR_HORIZONTAL:
- case NS_THEME_SCROLLBARTRACK_VERTICAL:
- {
- MozGtkScrollbarMetrics metrics;
- moz_gtk_get_scrollbar_metrics(&metrics);
- aResult->left = aResult->right = metrics.trough_border;
- }
- break;
case NS_THEME_TOOLBOX:
// gtk has no toolbox equivalent. So, although we map toolbox to
// gtk's 'toolbar' for purposes of painting the widget background,
@@ -1289,7 +1297,7 @@ nsNativeThemeGTK::GetWidgetBorder(nsDevi
moz_gtk_get_tab_border(&aResult->left, &aResult->top,
&aResult->right, &aResult->bottom, direction,
- (GtkTabFlags)flags);
+ (GtkTabFlags)flags, gtkWidgetType);
}
break;
case NS_THEME_MENUITEM:
@@ -1304,8 +1312,9 @@ nsNativeThemeGTK::GetWidgetBorder(nsDevi
default:
{
WidgetNodeType gtkWidgetType;
+ gint unusedFlags;
if (GetGtkWidgetAndState(aWidgetType, aFrame, gtkWidgetType, nullptr,
- nullptr)) {
+ &unusedFlags)) {
moz_gtk_get_widget_border(gtkWidgetType, &aResult->left, &aResult->top,
&aResult->right, &aResult->bottom, direction,
IsFrameContentNodeInNamespace(aFrame, kNameSpaceID_XHTML));
@@ -1418,22 +1427,33 @@ nsNativeThemeGTK::GetMinimumWidgetSize(n
case NS_THEME_SCROLLBARBUTTON_UP:
case NS_THEME_SCROLLBARBUTTON_DOWN:
{
- MozGtkScrollbarMetrics metrics;
- moz_gtk_get_scrollbar_metrics(&metrics);
+ if (gtk_check_version(3,20,0) == nullptr) {
+ moz_gtk_get_widget_min_size(MOZ_GTK_SCROLLBAR_BUTTON,
+ &(aResult->width), &(aResult->height));
+ } else {
+ MozGtkScrollbarMetrics metrics;
+ moz_gtk_get_scrollbar_metrics(&metrics);
+
+ aResult->width = metrics.slider_width;
+ aResult->height = metrics.stepper_size;
+ }
- aResult->width = metrics.slider_width;
- aResult->height = metrics.stepper_size;
*aIsOverridable = false;
}
break;
case NS_THEME_SCROLLBARBUTTON_LEFT:
case NS_THEME_SCROLLBARBUTTON_RIGHT:
{
- MozGtkScrollbarMetrics metrics;
- moz_gtk_get_scrollbar_metrics(&metrics);
+ if (gtk_check_version(3,20,0) == nullptr) {
+ moz_gtk_get_widget_min_size(MOZ_GTK_SCROLLBAR_BUTTON,
+ &(aResult->width), &(aResult->height));
+ } else {
+ MozGtkScrollbarMetrics metrics;
+ moz_gtk_get_scrollbar_metrics(&metrics);
- aResult->width = metrics.stepper_size;
- aResult->height = metrics.slider_width;
+ aResult->width = metrics.stepper_size;
+ aResult->height = metrics.slider_width;
+ }
*aIsOverridable = false;
}
break;
@@ -1460,39 +1480,65 @@ nsNativeThemeGTK::GetMinimumWidgetSize(n
* the thumb isn't a direct child of the scrollbar, unlike the buttons
* or track. So add a minimum size to the track as well to prevent a
* 0-width scrollbar. */
- MozGtkScrollbarMetrics metrics;
- moz_gtk_get_scrollbar_metrics(&metrics);
+ if (gtk_check_version(3,20,0) == nullptr) {
+ // Thumb min dimensions to start with
+ WidgetNodeType thumbType = aWidgetType == NS_THEME_SCROLLBAR_VERTICAL ?
+ MOZ_GTK_SCROLLBAR_THUMB_VERTICAL : MOZ_GTK_SCROLLBAR_THUMB_HORIZONTAL;
+ moz_gtk_get_widget_min_size(thumbType, &(aResult->width), &(aResult->height));
+
+ // Add scrollbar's borders
+ nsIntMargin border;
+ nsNativeThemeGTK::GetWidgetBorder(aFrame->PresContext()->DeviceContext(),
+ aFrame, aWidgetType, &border);
+ aResult->width += border.left + border.right;
+ aResult->height += border.top + border.bottom;
+
+ // Add track's borders
+ uint8_t trackType = aWidgetType == NS_THEME_SCROLLBAR_VERTICAL ?
+ NS_THEME_SCROLLBARTRACK_VERTICAL : NS_THEME_SCROLLBARTRACK_HORIZONTAL;
+ nsNativeThemeGTK::GetWidgetBorder(aFrame->PresContext()->DeviceContext(),
+ aFrame, trackType, &border);
+ aResult->width += border.left + border.right;
+ aResult->height += border.top + border.bottom;
+ } else {
+ MozGtkScrollbarMetrics metrics;
+ moz_gtk_get_scrollbar_metrics(&metrics);
- // Require room for the slider in the track if we don't have buttons.
- bool hasScrollbarButtons = moz_gtk_has_scrollbar_buttons();
+ // Require room for the slider in the track if we don't have buttons.
+ bool hasScrollbarButtons = moz_gtk_has_scrollbar_buttons();
- if (aWidgetType == NS_THEME_SCROLLBAR_VERTICAL) {
- aResult->width = metrics.slider_width + 2 * metrics.trough_border;
- if (!hasScrollbarButtons)
- aResult->height = metrics.min_slider_size + 2 * metrics.trough_border;
- } else {
- aResult->height = metrics.slider_width + 2 * metrics.trough_border;
- if (!hasScrollbarButtons)
- aResult->width = metrics.min_slider_size + 2 * metrics.trough_border;
+ if (aWidgetType == NS_THEME_SCROLLBAR_VERTICAL) {
+ aResult->width = metrics.slider_width + 2 * metrics.trough_border;
+ if (!hasScrollbarButtons)
+ aResult->height = metrics.min_slider_size + 2 * metrics.trough_border;
+ } else {
+ aResult->height = metrics.slider_width + 2 * metrics.trough_border;
+ if (!hasScrollbarButtons)
+ aResult->width = metrics.min_slider_size + 2 * metrics.trough_border;
+ }
+ *aIsOverridable = false;
}
- *aIsOverridable = false;
}
break;
case NS_THEME_SCROLLBARTHUMB_VERTICAL:
case NS_THEME_SCROLLBARTHUMB_HORIZONTAL:
{
- MozGtkScrollbarMetrics metrics;
- moz_gtk_get_scrollbar_metrics(&metrics);
-
- if (aWidgetType == NS_THEME_SCROLLBARTHUMB_VERTICAL) {
- aResult->width = metrics.slider_width;
- aResult->height = metrics.min_slider_size;
+ if (gtk_check_version(3,20,0) == nullptr) {
+ moz_gtk_get_widget_min_size(NativeThemeToGtkTheme(aWidgetType, aFrame),
+ &(aResult->width), &(aResult->height));
} else {
- aResult->height = metrics.slider_width;
- aResult->width = metrics.min_slider_size;
- }
+ MozGtkScrollbarMetrics metrics;
+ moz_gtk_get_scrollbar_metrics(&metrics);
+ if (aWidgetType == NS_THEME_SCROLLBARTHUMB_VERTICAL) {
+ aResult->width = metrics.slider_width;
+ aResult->height = metrics.min_slider_size;
+ } else {
+ aResult->height = metrics.slider_width;
+ aResult->width = metrics.min_slider_size;
+ }
+ }
*aIsOverridable = false;
}
break;
diff -up firefox-50.0/widget/gtk/nsNativeThemeGTK.h.widget-rebase firefox-50.0/widget/gtk/nsNativeThemeGTK.h
--- firefox-50.0/widget/gtk/nsNativeThemeGTK.h.widget-rebase 2016-07-25 22:22:07.000000000 +0200
+++ firefox-50.0/widget/gtk/nsNativeThemeGTK.h 2016-11-24 11:57:52.035064777 +0100
@@ -74,6 +74,7 @@ protected:
virtual ~nsNativeThemeGTK();
private:
+ GtkTextDirection GetTextDirection(nsIFrame* aFrame);
gint GetTabMarginPixels(nsIFrame* aFrame);
bool GetGtkWidgetAndState(uint8_t aWidgetType, nsIFrame* aFrame,
WidgetNodeType& aGtkWidgetType,
@@ -82,6 +83,7 @@ private:
nsIntMargin* aExtra);
void RefreshWidgetWindow(nsIFrame* aFrame);
+ WidgetNodeType NativeThemeToGtkTheme(uint8_t aWidgetType, nsIFrame* aFrame);
uint8_t mDisabledWidgetTypes[32];
uint8_t mSafeWidgetStates[1024]; // 256 widgets * 32 bits per widget
diff -up firefox-50.0/widget/gtk/WidgetStyleCache.cpp.widget-rebase firefox-50.0/widget/gtk/WidgetStyleCache.cpp
--- firefox-50.0/widget/gtk/WidgetStyleCache.cpp.widget-rebase 2016-10-31 21:15:38.000000000 +0100
+++ firefox-50.0/widget/gtk/WidgetStyleCache.cpp 2016-11-24 11:57:52.035064777 +0100
@@ -25,6 +25,8 @@ static bool sStyleContextNeedsRestore;
static GtkStyleContext* sCurrentStyleContext;
#endif
static GtkStyleContext*
+GetWidgetRootStyle(WidgetNodeType aNodeType);
+static GtkStyleContext*
GetCssNodeStyleInternal(WidgetNodeType aNodeType);
static GtkWidget*
@@ -93,14 +95,6 @@ CreateMenuPopupWidget()
}
static GtkWidget*
-CreateMenuItemWidget(WidgetNodeType aShellType)
-{
- GtkWidget* widget = gtk_menu_item_new();
- gtk_menu_shell_append(GTK_MENU_SHELL(GetWidget(aShellType)), widget);
- return widget;
-}
-
-static GtkWidget*
CreateProgressWidget()
{
GtkWidget* widget = gtk_progress_bar_new();
@@ -211,6 +205,235 @@ CreateEntryWidget()
}
static GtkWidget*
+CreateComboBoxWidget()
+{
+ GtkWidget* widget = gtk_combo_box_new();
+ AddToWindowContainer(widget);
+ return widget;
+}
+
+typedef struct
+{
+ GType type;
+ GtkWidget** widget;
+} GtkInnerWidgetInfo;
+
+static void
+GetInnerWidget(GtkWidget* widget, gpointer client_data)
+{
+ auto info = static_cast<GtkInnerWidgetInfo*>(client_data);
+
+ if (G_TYPE_CHECK_INSTANCE_TYPE(widget, info->type)) {
+ *info->widget = widget;
+ }
+
+ gtk_widget_realize(widget);
+}
+
+static GtkWidget*
+CreateComboBoxButtonWidget()
+{
+ GtkWidget* comboBox = GetWidget(MOZ_GTK_COMBOBOX);
+ GtkWidget* comboBoxButton = nullptr;
+
+ /* Get its inner Button */
+ GtkInnerWidgetInfo info = { GTK_TYPE_TOGGLE_BUTTON,
+ &comboBoxButton };
+ gtk_container_forall(GTK_CONTAINER(comboBox),
+ GetInnerWidget, &info);
+
+ if (!comboBoxButton) {
+ /* Shouldn't be reached with current internal gtk implementation; we
+ * use a generic toggle button as last resort fallback to avoid
+ * crashing. */
+ comboBoxButton = GetWidget(MOZ_GTK_TOGGLE_BUTTON);
+ } else {
+ /* 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 gProtoLayout and as
+ * such GTK holds a strong reference to them. */
+ g_object_add_weak_pointer(G_OBJECT(comboBoxButton),
+ reinterpret_cast<gpointer *>(sWidgetStorage) +
+ MOZ_GTK_COMBOBOX_BUTTON);
+ }
+
+ return comboBoxButton;
+}
+
+static GtkWidget*
+CreateComboBoxArrowWidget()
+{
+ GtkWidget* comboBoxButton = GetWidget(MOZ_GTK_COMBOBOX_BUTTON);
+ GtkWidget* comboBoxArrow = nullptr;
+
+ /* Get the widgets inside the Button */
+ GtkWidget* buttonChild = gtk_bin_get_child(GTK_BIN(comboBoxButton));
+ if (GTK_IS_BOX(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. */
+ GtkInnerWidgetInfo info = { GTK_TYPE_ARROW,
+ &comboBoxArrow };
+ gtk_container_forall(GTK_CONTAINER(buttonChild),
+ GetInnerWidget, &info);
+ } else if (GTK_IS_ARROW(buttonChild)) {
+ /* appears-as-list = TRUE, or cell-view = FALSE;
+ * the button only contains an arrow */
+ comboBoxArrow = buttonChild;
+ gtk_widget_realize(comboBoxArrow);
+ }
+
+ if (!comboBoxArrow) {
+ /* Shouldn't be reached with current internal gtk implementation;
+ * we gButtonArrowWidget as last resort fallback to avoid
+ * crashing. */
+ comboBoxArrow = GetWidget(MOZ_GTK_BUTTON_ARROW);
+ } else {
+ g_object_add_weak_pointer(G_OBJECT(comboBoxArrow),
+ reinterpret_cast<gpointer *>(sWidgetStorage) +
+ MOZ_GTK_COMBOBOX_ARROW);
+ }
+
+ return comboBoxArrow;
+}
+
+static GtkWidget*
+CreateComboBoxSeparatorWidget()
+{
+ // Ensure to search for separator only once as it can fail
+ // TODO - it won't initialize after ResetWidgetCache() call
+ static bool isMissingSeparator = false;
+ if (isMissingSeparator)
+ return nullptr;
+
+ /* Get the widgets inside the Button */
+ GtkWidget* comboBoxSeparator = nullptr;
+ GtkWidget* buttonChild =
+ gtk_bin_get_child(GTK_BIN(GetWidget(MOZ_GTK_COMBOBOX_BUTTON)));
+ if (GTK_IS_BOX(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. */
+ GtkInnerWidgetInfo info = { GTK_TYPE_SEPARATOR,
+ &comboBoxSeparator };
+ gtk_container_forall(GTK_CONTAINER(buttonChild),
+ GetInnerWidget, &info);
+ }
+
+ if (comboBoxSeparator) {
+ g_object_add_weak_pointer(G_OBJECT(comboBoxSeparator),
+ reinterpret_cast<gpointer *>(sWidgetStorage) +
+ MOZ_GTK_COMBOBOX_SEPARATOR);
+ } else {
+ /* comboBoxSeparator may be NULL
+ * when "appears-as-list" = TRUE or "cell-view" = FALSE;
+ * if there is no separator, then we just won't paint it. */
+ isMissingSeparator = true;
+ }
+
+ return comboBoxSeparator;
+}
+
+static GtkWidget*
+CreateComboBoxEntryWidget()
+{
+ GtkWidget* widget = gtk_combo_box_new_with_entry();
+ AddToWindowContainer(widget);
+ return widget;
+}
+
+static GtkWidget*
+CreateComboBoxEntryTextareaWidget()
+{
+ GtkWidget* comboBoxTextarea = nullptr;
+
+ /* Get its inner Entry and Button */
+ GtkInnerWidgetInfo info = { GTK_TYPE_ENTRY,
+ &comboBoxTextarea };
+ gtk_container_forall(GTK_CONTAINER(GetWidget(MOZ_GTK_COMBOBOX_ENTRY)),
+ GetInnerWidget, &info);
+
+ if (!comboBoxTextarea) {
+ comboBoxTextarea = GetWidget(MOZ_GTK_ENTRY);
+ } else {
+ g_object_add_weak_pointer(G_OBJECT(comboBoxTextarea),
+ reinterpret_cast<gpointer *>(sWidgetStorage) +
+ MOZ_GTK_COMBOBOX_ENTRY);
+ }
+
+ return comboBoxTextarea;
+}
+
+static GtkWidget*
+CreateComboBoxEntryButtonWidget()
+{
+ GtkWidget* comboBoxButton = nullptr;
+
+ /* Get its inner Entry and Button */
+ GtkInnerWidgetInfo info = { GTK_TYPE_TOGGLE_BUTTON,
+ &comboBoxButton };
+ gtk_container_forall(GTK_CONTAINER(GetWidget(MOZ_GTK_COMBOBOX_ENTRY)),
+ GetInnerWidget, &info);
+
+ if (!comboBoxButton) {
+ comboBoxButton = GetWidget(MOZ_GTK_TOGGLE_BUTTON);
+ } else {
+ g_object_add_weak_pointer(G_OBJECT(comboBoxButton),
+ reinterpret_cast<gpointer *>(sWidgetStorage) +
+ MOZ_GTK_COMBOBOX_ENTRY_BUTTON);
+ }
+
+ return comboBoxButton;
+}
+
+static GtkWidget*
+CreateComboBoxEntryArrowWidget()
+{
+ GtkWidget* comboBoxArrow = nullptr;
+
+ /* Get the Arrow inside the Button */
+ GtkWidget* buttonChild =
+ gtk_bin_get_child(GTK_BIN(GetWidget(MOZ_GTK_COMBOBOX_ENTRY_BUTTON)));
+
+ if (GTK_IS_BOX(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. */
+ GtkInnerWidgetInfo info = { GTK_TYPE_ARROW,
+ &comboBoxArrow };
+ gtk_container_forall(GTK_CONTAINER(buttonChild),
+ GetInnerWidget, &info);
+ } else if (GTK_IS_ARROW(buttonChild)) {
+ /* appears-as-list = TRUE, or cell-view = FALSE;
+ * the button only contains an arrow */
+ comboBoxArrow = buttonChild;
+ gtk_widget_realize(comboBoxArrow);
+ }
+
+ if (!comboBoxArrow) {
+ /* Shouldn't be reached with current internal gtk implementation;
+ * we gButtonArrowWidget as last resort fallback to avoid
+ * crashing. */
+ comboBoxArrow = GetWidget(MOZ_GTK_BUTTON_ARROW);
+ } else {
+ g_object_add_weak_pointer(G_OBJECT(comboBoxArrow),
+ reinterpret_cast<gpointer *>(sWidgetStorage) +
+ MOZ_GTK_COMBOBOX_ENTRY_ARROW);
+ }
+
+ return comboBoxArrow;
+}
+
+static GtkWidget*
CreateScrolledWindowWidget()
{
GtkWidget* widget = gtk_scrolled_window_new(nullptr, nullptr);
@@ -237,6 +460,95 @@ CreateMenuSeparatorWidget()
return widget;
}
+static GtkWidget*
+CreateTreeViewWidget()
+{
+ GtkWidget* widget = gtk_tree_view_new();
+ AddToWindowContainer(widget);
+ return widget;
+}
+
+static GtkWidget*
+CreateTreeHeaderCellWidget()
+{
+ /*
+ * 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* middleTreeViewColumn;
+ GtkTreeViewColumn* lastTreeViewColumn;
+
+ GtkWidget *treeView = GetWidget(MOZ_GTK_TREEVIEW);
+
+ /* 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(treeView),
+ firstTreeViewColumn);
+
+ middleTreeViewColumn = gtk_tree_view_column_new();
+ gtk_tree_view_column_set_title(middleTreeViewColumn, "M");
+ gtk_tree_view_append_column(GTK_TREE_VIEW(treeView),
+ middleTreeViewColumn);
+
+ lastTreeViewColumn = gtk_tree_view_column_new();
+ gtk_tree_view_column_set_title(lastTreeViewColumn, "M");
+ gtk_tree_view_append_column(GTK_TREE_VIEW(treeView),
+ lastTreeViewColumn);
+
+ /* Use the middle column's header for our button */
+ return gtk_tree_view_column_get_button(middleTreeViewColumn);
+}
+
+static GtkWidget*
+CreateTreeHeaderSortArrowWidget()
+{
+ /* TODO, but it can't be NULL */
+ GtkWidget* widget = gtk_button_new();
+ AddToWindowContainer(widget);
+ return widget;
+}
+
+static GtkWidget*
+CreateHPanedWidget()
+{
+ GtkWidget* widget = gtk_paned_new(GTK_ORIENTATION_HORIZONTAL);
+ AddToWindowContainer(widget);
+ return widget;
+}
+
+static GtkWidget*
+CreateVPanedWidget()
+{
+ GtkWidget* widget = gtk_paned_new(GTK_ORIENTATION_VERTICAL);
+ AddToWindowContainer(widget);
+ return widget;
+}
+
+static GtkWidget*
+CreateScaleWidget(GtkOrientation aOrientation)
+{
+ GtkWidget* widget = gtk_scale_new(aOrientation, nullptr);
+ AddToWindowContainer(widget);
+ return widget;
+}
+
+static GtkWidget*
+CreateNotebookWidget()
+{
+ GtkWidget* widget = gtk_notebook_new();
+ AddToWindowContainer(widget);
+ return widget;
+}
static GtkWidget*
CreateWidget(WidgetNodeType aWidgetType)
@@ -262,10 +574,6 @@ CreateWidget(WidgetNodeType aWidgetType)
return CreateMenuBarWidget();
case MOZ_GTK_MENUPOPUP:
return CreateMenuPopupWidget();
- case MOZ_GTK_MENUBARITEM:
- return CreateMenuItemWidget(MOZ_GTK_MENUBAR);
- case MOZ_GTK_MENUITEM:
- return CreateMenuItemWidget(MOZ_GTK_MENUPOPUP);
case MOZ_GTK_MENUSEPARATOR:
return CreateMenuSeparatorWidget();
case MOZ_GTK_EXPANDER:
@@ -294,6 +602,38 @@ CreateWidget(WidgetNodeType aWidgetType)
return CreateScrolledWindowWidget();
case MOZ_GTK_TEXT_VIEW:
return CreateTextViewWidget();
+ case MOZ_GTK_TREEVIEW:
+ return CreateTreeViewWidget();
+ case MOZ_GTK_TREE_HEADER_CELL:
+ return CreateTreeHeaderCellWidget();
+ case MOZ_GTK_TREE_HEADER_SORTARROW:
+ return CreateTreeHeaderSortArrowWidget();
+ case MOZ_GTK_SPLITTER_HORIZONTAL:
+ return CreateHPanedWidget();
+ case MOZ_GTK_SPLITTER_VERTICAL:
+ return CreateVPanedWidget();
+ case MOZ_GTK_SCALE_HORIZONTAL:
+ return CreateScaleWidget(GTK_ORIENTATION_HORIZONTAL);
+ case MOZ_GTK_SCALE_VERTICAL:
+ return CreateScaleWidget(GTK_ORIENTATION_VERTICAL);
+ case MOZ_GTK_NOTEBOOK:
+ return CreateNotebookWidget();
+ case MOZ_GTK_COMBOBOX:
+ return CreateComboBoxWidget();
+ case MOZ_GTK_COMBOBOX_BUTTON:
+ return CreateComboBoxButtonWidget();
+ case MOZ_GTK_COMBOBOX_ARROW:
+ return CreateComboBoxArrowWidget();
+ case MOZ_GTK_COMBOBOX_SEPARATOR:
+ return CreateComboBoxSeparatorWidget();
+ case MOZ_GTK_COMBOBOX_ENTRY:
+ return CreateComboBoxEntryWidget();
+ case MOZ_GTK_COMBOBOX_ENTRY_TEXTAREA:
+ return CreateComboBoxEntryTextareaWidget();
+ case MOZ_GTK_COMBOBOX_ENTRY_BUTTON:
+ return CreateComboBoxEntryButtonWidget();
+ case MOZ_GTK_COMBOBOX_ENTRY_ARROW:
+ return CreateComboBoxEntryArrowWidget();
default:
/* Not implemented */
return nullptr;
@@ -314,27 +654,53 @@ GetWidget(WidgetNodeType aWidgetType)
GtkStyleContext*
CreateStyleForWidget(GtkWidget* aWidget, GtkStyleContext* aParentStyle)
{
- GtkWidgetPath* path = aParentStyle ?
- gtk_widget_path_copy(gtk_style_context_get_path(aParentStyle)) :
- gtk_widget_path_new();
-
- // Work around https://bugzilla.gnome.org/show_bug.cgi?id=767312
- // which exists in GTK+ 3.20.
- gtk_widget_get_style_context(aWidget);
+ static auto sGtkWidgetClassGetCSSName =
+ reinterpret_cast<const char* (*)(GtkWidgetClass*)>
+ (dlsym(RTLD_DEFAULT, "gtk_widget_class_get_css_name"));
+
+ GtkWidgetClass *widgetClass = GTK_WIDGET_GET_CLASS(aWidget);
+ const gchar* name = sGtkWidgetClassGetCSSName ?
+ sGtkWidgetClassGetCSSName(widgetClass) : nullptr;
+
+ GtkStyleContext *context =
+ CreateCSSNode(name, aParentStyle, G_TYPE_FROM_CLASS(widgetClass));
+
+ // Classes are stored on the style context instead of the path so that any
+ // future gtk_style_context_save() will inherit classes on the head CSS
+ // node, in the same way as happens when called on a style context owned by
+ // a widget.
+ //
+ // Classes can be stored on a GtkCssNodeDeclaration and/or the path.
+ // gtk_style_context_save() reuses the GtkCssNodeDeclaration, and appends a
+ // new object to the path, without copying the classes from the old path
+ // head. The new head picks up classes from the GtkCssNodeDeclaration, but
+ // not the path. GtkWidgets store their classes on the
+ // GtkCssNodeDeclaration, so make sure to add classes there.
+ //
+ // Picking up classes from the style context also means that
+ // https://bugzilla.gnome.org/show_bug.cgi?id=767312, which can stop
+ // gtk_widget_path_append_for_widget() from finding classes in GTK 3.20,
+ // is not a problem.
+ GtkStyleContext* widgetStyle = gtk_widget_get_style_context(aWidget);
+ GList* classes = gtk_style_context_list_classes(widgetStyle);
+ for (GList* link = classes; link; link = link->next) {
+ gtk_style_context_add_class(context, static_cast<gchar*>(link->data));
+ }
+ g_list_free(classes);
- gtk_widget_path_append_for_widget(path, aWidget);
// Release any floating reference on aWidget.
g_object_ref_sink(aWidget);
g_object_unref(aWidget);
- GtkStyleContext *context = gtk_style_context_new();
- gtk_style_context_set_path(context, path);
- gtk_style_context_set_parent(context, aParentStyle);
- gtk_widget_path_unref(path);
-
return context;
}
+static GtkStyleContext*
+CreateStyleForWidget(GtkWidget* aWidget, WidgetNodeType aParentType)
+{
+ return CreateStyleForWidget(aWidget, GetWidgetRootStyle(aParentType));
+}
+
GtkStyleContext*
CreateCSSNode(const char* aName, GtkStyleContext* aParentStyle, GType aType)
{
@@ -342,13 +708,26 @@ CreateCSSNode(const char* aName, GtkStyl
reinterpret_cast<void (*)(GtkWidgetPath *, gint, const char *)>
(dlsym(RTLD_DEFAULT, "gtk_widget_path_iter_set_object_name"));
- GtkWidgetPath* path = aParentStyle ?
- gtk_widget_path_copy(gtk_style_context_get_path(aParentStyle)) :
- gtk_widget_path_new();
+ GtkWidgetPath* path;
+ if (aParentStyle) {
+ path = gtk_widget_path_copy(gtk_style_context_get_path(aParentStyle));
+ // Copy classes from the parent style context to its corresponding node in
+ // the path, because GTK will only match against ancestor classes if they
+ // are on the path.
+ GList* classes = gtk_style_context_list_classes(aParentStyle);
+ for (GList* link = classes; link; link = link->next) {
+ gtk_widget_path_iter_add_class(path, -1, static_cast<gchar*>(link->data));
+ }
+ g_list_free(classes);
+ } else {
+ path = gtk_widget_path_new();
+ }
gtk_widget_path_append_type(path, aType);
- (*sGtkWidgetPathIterSetObjectName)(path, -1, aName);
+ if (sGtkWidgetPathIterSetObjectName) {
+ (*sGtkWidgetPathIterSetObjectName)(path, -1, aName);
+ }
GtkStyleContext *context = gtk_style_context_new();
gtk_style_context_set_path(context, path);
@@ -358,6 +737,40 @@ CreateCSSNode(const char* aName, GtkStyl
return context;
}
+// Return a style context matching that of the root CSS node of a widget.
+// This is used by all GTK versions.
+static GtkStyleContext*
+GetWidgetRootStyle(WidgetNodeType aNodeType)
+{
+ GtkStyleContext* style = sStyleStorage[aNodeType];
+ if (style)
+ return style;
+
+ switch (aNodeType) {
+ case MOZ_GTK_MENUBARITEM:
+ style = CreateStyleForWidget(gtk_menu_item_new(), MOZ_GTK_MENUBAR);
+ break;
+ case MOZ_GTK_MENUITEM:
+ style = CreateStyleForWidget(gtk_menu_item_new(), MOZ_GTK_MENUPOPUP);
+ break;
+ case MOZ_GTK_CHECKMENUITEM:
+ style = CreateStyleForWidget(gtk_check_menu_item_new(), MOZ_GTK_MENUPOPUP);
+ break;
+ case MOZ_GTK_RADIOMENUITEM:
+ style = CreateStyleForWidget(gtk_radio_menu_item_new(nullptr),
+ MOZ_GTK_MENUPOPUP);
+ break;
+ default:
+ GtkWidget* widget = GetWidget(aNodeType);
+ MOZ_ASSERT(widget);
+ return gtk_widget_get_style_context(widget);
+ }
+
+ MOZ_ASSERT(style);
+ sStyleStorage[aNodeType] = style;
+ return style;
+}
+
static GtkStyleContext*
CreateChildCSSNode(const char* aName, WidgetNodeType aParentNodeType)
{
@@ -367,7 +780,7 @@ CreateChildCSSNode(const char* aName, Wi
static GtkStyleContext*
GetWidgetStyleWithClass(WidgetNodeType aWidgetType, const gchar* aStyleClass)
{
- GtkStyleContext* style = gtk_widget_get_style_context(GetWidget(aWidgetType));
+ GtkStyleContext* style = GetWidgetRootStyle(aWidgetType);
gtk_style_context_save(style);
MOZ_ASSERT(!sStyleContextNeedsRestore);
sStyleContextNeedsRestore = true;
@@ -408,6 +821,10 @@ GetCssNodeStyleInternal(WidgetNodeType a
style = CreateChildCSSNode(GTK_STYLE_CLASS_SLIDER,
MOZ_GTK_SCROLLBAR_TROUGH_VERTICAL);
break;
+ case MOZ_GTK_SCROLLBAR_BUTTON:
+ style = CreateChildCSSNode(GTK_STYLE_CLASS_BUTTON,
+ MOZ_GTK_SCROLLBAR_CONTENTS_VERTICAL);
+ break;
case MOZ_GTK_RADIOBUTTON:
style = CreateChildCSSNode(GTK_STYLE_CLASS_RADIO,
MOZ_GTK_RADIOBUTTON_CONTAINER);
@@ -416,6 +833,14 @@ GetCssNodeStyleInternal(WidgetNodeType a
style = CreateChildCSSNode(GTK_STYLE_CLASS_CHECK,
MOZ_GTK_CHECKBUTTON_CONTAINER);
break;
+ case MOZ_GTK_RADIOMENUITEM_INDICATOR:
+ style = CreateChildCSSNode(GTK_STYLE_CLASS_RADIO,
+ MOZ_GTK_RADIOMENUITEM);
+ break;
+ case MOZ_GTK_CHECKMENUITEM_INDICATOR:
+ style = CreateChildCSSNode(GTK_STYLE_CLASS_CHECK,
+ MOZ_GTK_CHECKMENUITEM);
+ break;
case MOZ_GTK_PROGRESS_TROUGH:
/* Progress bar background (trough) */
style = CreateChildCSSNode(GTK_STYLE_CLASS_TROUGH,
@@ -451,11 +876,77 @@ GetCssNodeStyleInternal(WidgetNodeType a
return GetWidgetStyleWithClass(MOZ_GTK_TEXT_VIEW,
GTK_STYLE_CLASS_VIEW);
case MOZ_GTK_FRAME_BORDER:
- return CreateChildCSSNode("border", MOZ_GTK_FRAME);
- default:
- // TODO - create style from style path
- GtkWidget* widget = GetWidget(aNodeType);
+ style = CreateChildCSSNode("border", MOZ_GTK_FRAME);
+ break;
+ case MOZ_GTK_TREEVIEW_VIEW:
+ // TODO - create from CSS node
+ return GetWidgetStyleWithClass(MOZ_GTK_TREEVIEW,
+ GTK_STYLE_CLASS_VIEW);
+ case MOZ_GTK_TREEVIEW_EXPANDER:
+ // TODO - create from CSS node
+ return GetWidgetStyleWithClass(MOZ_GTK_TREEVIEW,
+ GTK_STYLE_CLASS_EXPANDER);
+ case MOZ_GTK_SPLITTER_SEPARATOR_HORIZONTAL:
+ style = CreateChildCSSNode("separator",
+ MOZ_GTK_SPLITTER_HORIZONTAL);
+ break;
+ case MOZ_GTK_SPLITTER_SEPARATOR_VERTICAL:
+ style = CreateChildCSSNode("separator",
+ MOZ_GTK_SPLITTER_VERTICAL);
+ break;
+ case MOZ_GTK_SCALE_CONTENTS_HORIZONTAL:
+ style = CreateChildCSSNode("contents",
+ MOZ_GTK_SCALE_HORIZONTAL);
+ break;
+ case MOZ_GTK_SCALE_CONTENTS_VERTICAL:
+ style = CreateChildCSSNode("contents",
+ MOZ_GTK_SCALE_VERTICAL);
+ break;
+ case MOZ_GTK_SCALE_TROUGH_HORIZONTAL:
+ style = CreateChildCSSNode(GTK_STYLE_CLASS_TROUGH,
+ MOZ_GTK_SCALE_CONTENTS_HORIZONTAL);
+ break;
+ case MOZ_GTK_SCALE_TROUGH_VERTICAL:
+ style = CreateChildCSSNode(GTK_STYLE_CLASS_TROUGH,
+ MOZ_GTK_SCALE_CONTENTS_VERTICAL);
+ break;
+ case MOZ_GTK_SCALE_THUMB_HORIZONTAL:
+ style = CreateChildCSSNode(GTK_STYLE_CLASS_SLIDER,
+ MOZ_GTK_SCALE_TROUGH_HORIZONTAL);
+ break;
+ case MOZ_GTK_SCALE_THUMB_VERTICAL:
+ style = CreateChildCSSNode(GTK_STYLE_CLASS_SLIDER,
+ MOZ_GTK_SCALE_TROUGH_VERTICAL);
+ break;
+ case MOZ_GTK_TAB_TOP:
+ {
+ // TODO - create from CSS node
+ style = GetWidgetStyleWithClass(MOZ_GTK_NOTEBOOK,
+ GTK_STYLE_CLASS_TOP);
+ gtk_style_context_add_region(style, GTK_STYLE_REGION_TAB,
+ static_cast<GtkRegionFlags>(0));
+ return style;
+ }
+ case MOZ_GTK_TAB_BOTTOM:
+ {
+ // TODO - create from CSS node
+ style = GetWidgetStyleWithClass(MOZ_GTK_NOTEBOOK,
+ GTK_STYLE_CLASS_BOTTOM);
+ gtk_style_context_add_region(style, GTK_STYLE_REGION_TAB,
+ static_cast<GtkRegionFlags>(0));
+ return style;
+ }
+ case MOZ_GTK_NOTEBOOK:
+ case MOZ_GTK_NOTEBOOK_HEADER:
+ case MOZ_GTK_TABPANELS:
+ case MOZ_GTK_TAB_SCROLLARROW:
+ {
+ // TODO - create from CSS node
+ GtkWidget* widget = GetWidget(MOZ_GTK_NOTEBOOK);
return gtk_widget_get_style_context(widget);
+ }
+ default:
+ return GetWidgetRootStyle(aNodeType);
}
MOZ_ASSERT(style, "missing style context for node type");
@@ -486,6 +977,12 @@ GetWidgetStyleInternal(WidgetNodeType aN
case MOZ_GTK_CHECKBUTTON:
return GetWidgetStyleWithClass(MOZ_GTK_CHECKBUTTON_CONTAINER,
GTK_STYLE_CLASS_CHECK);
+ case MOZ_GTK_RADIOMENUITEM_INDICATOR:
+ return GetWidgetStyleWithClass(MOZ_GTK_RADIOMENUITEM,
+ GTK_STYLE_CLASS_RADIO);
+ case MOZ_GTK_CHECKMENUITEM_INDICATOR:
+ return GetWidgetStyleWithClass(MOZ_GTK_CHECKMENUITEM,
+ GTK_STYLE_CLASS_CHECK);
case MOZ_GTK_PROGRESS_TROUGH:
return GetWidgetStyleWithClass(MOZ_GTK_PROGRESSBAR,
GTK_STYLE_CLASS_TROUGH);
@@ -519,11 +1016,57 @@ GetWidgetStyleInternal(WidgetNodeType aN
return GetWidgetStyleWithClass(MOZ_GTK_TEXT_VIEW,
GTK_STYLE_CLASS_VIEW);
case MOZ_GTK_FRAME_BORDER:
- return GetWidgetStyleInternal(MOZ_GTK_FRAME);
- default:
- GtkWidget* widget = GetWidget(aNodeType);
- MOZ_ASSERT(widget);
+ return GetWidgetRootStyle(MOZ_GTK_FRAME);
+ case MOZ_GTK_TREEVIEW_VIEW:
+ return GetWidgetStyleWithClass(MOZ_GTK_TREEVIEW,
+ GTK_STYLE_CLASS_VIEW);
+ case MOZ_GTK_TREEVIEW_EXPANDER:
+ return GetWidgetStyleWithClass(MOZ_GTK_TREEVIEW,
+ GTK_STYLE_CLASS_EXPANDER);
+ case MOZ_GTK_SPLITTER_SEPARATOR_HORIZONTAL:
+ return GetWidgetStyleWithClass(MOZ_GTK_SPLITTER_HORIZONTAL,
+ GTK_STYLE_CLASS_PANE_SEPARATOR);
+ case MOZ_GTK_SPLITTER_SEPARATOR_VERTICAL:
+ return GetWidgetStyleWithClass(MOZ_GTK_SPLITTER_VERTICAL,
+ GTK_STYLE_CLASS_PANE_SEPARATOR);
+ case MOZ_GTK_SCALE_TROUGH_HORIZONTAL:
+ return GetWidgetStyleWithClass(MOZ_GTK_SCALE_HORIZONTAL,
+ GTK_STYLE_CLASS_TROUGH);
+ case MOZ_GTK_SCALE_TROUGH_VERTICAL:
+ return GetWidgetStyleWithClass(MOZ_GTK_SCALE_VERTICAL,
+ GTK_STYLE_CLASS_TROUGH);
+ case MOZ_GTK_SCALE_THUMB_HORIZONTAL:
+ return GetWidgetStyleWithClass(MOZ_GTK_SCALE_HORIZONTAL,
+ GTK_STYLE_CLASS_SLIDER);
+ case MOZ_GTK_SCALE_THUMB_VERTICAL:
+ return GetWidgetStyleWithClass(MOZ_GTK_SCALE_VERTICAL,
+ GTK_STYLE_CLASS_SLIDER);
+ case MOZ_GTK_TAB_TOP:
+ {
+ GtkStyleContext* style = GetWidgetStyleWithClass(MOZ_GTK_NOTEBOOK,
+ GTK_STYLE_CLASS_TOP);
+ gtk_style_context_add_region(style, GTK_STYLE_REGION_TAB,
+ static_cast<GtkRegionFlags>(0));
+ return style;
+ }
+ case MOZ_GTK_TAB_BOTTOM:
+ {
+ GtkStyleContext* style = GetWidgetStyleWithClass(MOZ_GTK_NOTEBOOK,
+ GTK_STYLE_CLASS_BOTTOM);
+ gtk_style_context_add_region(style, GTK_STYLE_REGION_TAB,
+ static_cast<GtkRegionFlags>(0));
+ return style;
+ }
+ case MOZ_GTK_NOTEBOOK:
+ case MOZ_GTK_NOTEBOOK_HEADER:
+ case MOZ_GTK_TABPANELS:
+ case MOZ_GTK_TAB_SCROLLARROW:
+ {
+ GtkWidget* widget = GetWidget(MOZ_GTK_NOTEBOOK);
return gtk_widget_get_style_context(widget);
+ }
+ default:
+ return GetWidgetRootStyle(aNodeType);
}
}
diff -up firefox-50.0/widget/gtk/WidgetStyleCache.h.widget-rebase firefox-50.0/widget/gtk/WidgetStyleCache.h
--- firefox-50.0/widget/gtk/WidgetStyleCache.h.widget-rebase 2016-10-31 21:15:38.000000000 +0100
+++ firefox-50.0/widget/gtk/WidgetStyleCache.h 2016-11-24 11:57:52.035064777 +0100
@@ -28,7 +28,6 @@ GetWidget(WidgetNodeType aNodeType);
GtkStyleContext*
CreateStyleForWidget(GtkWidget* aWidget, GtkStyleContext* aParentStyle);
-// CreateCSSNode is implemented for gtk >= 3.20 only.
GtkStyleContext*
CreateCSSNode(const char* aName,
GtkStyleContext* aParentStyle,