3963 lines
154 KiB
Diff
3963 lines
154 KiB
Diff
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", ¬ebook_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,
|