summaryrefslogtreecommitdiff
path: root/widget/gtk/WidgetStyleCache.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'widget/gtk/WidgetStyleCache.cpp')
-rw-r--r--widget/gtk/WidgetStyleCache.cpp159
1 files changed, 114 insertions, 45 deletions
diff --git a/widget/gtk/WidgetStyleCache.cpp b/widget/gtk/WidgetStyleCache.cpp
index fd099681f5..f35a451aa6 100644
--- a/widget/gtk/WidgetStyleCache.cpp
+++ b/widget/gtk/WidgetStyleCache.cpp
@@ -434,15 +434,6 @@ CreateScrolledWindowWidget()
}
static GtkWidget*
-CreateTextViewWidget()
-{
- GtkWidget* widget = gtk_text_view_new();
- gtk_container_add(GTK_CONTAINER(GetWidget(MOZ_GTK_SCROLLED_WINDOW)),
- widget);
- return widget;
-}
-
-static GtkWidget*
CreateMenuSeparatorWidget()
{
GtkWidget* widget = gtk_separator_menu_item_new();
@@ -591,8 +582,6 @@ CreateWidget(WidgetNodeType aWidgetType)
return CreateEntryWidget();
case MOZ_GTK_SCROLLED_WINDOW:
return CreateScrolledWindowWidget();
- case MOZ_GTK_TEXT_VIEW:
- return CreateTextViewWidget();
case MOZ_GTK_TREEVIEW:
return CreateTreeViewWidget();
case MOZ_GTK_TREE_HEADER_CELL:
@@ -637,6 +626,24 @@ GetWidget(WidgetNodeType aWidgetType)
GtkWidget* widget = sWidgetStorage[aWidgetType];
if (!widget) {
widget = CreateWidget(aWidgetType);
+ // Some widgets (MOZ_GTK_COMBOBOX_SEPARATOR for instance) may not be
+ // available or implemented.
+ if (!widget)
+ return nullptr;
+ // In GTK versions prior to 3.18, automatic invalidation of style contexts
+ // for widgets was delayed until the next resize event. Gecko however,
+ // typically uses the style context before the resize event runs and so an
+ // explicit invalidation may be required. This is necessary if a style
+ // property was retrieved before all changes were made to the style
+ // context. One such situation is where gtk_button_construct_child()
+ // retrieves the style property "image-spacing" during construction of the
+ // GtkButton, before its parent is set to provide inheritance of ancestor
+ // properties. More recent GTK versions do not need this, but do not
+ // re-resolve until required and so invalidation does not trigger
+ // unnecessary resolution in general.
+ GtkStyleContext* style = gtk_widget_get_style_context(widget);
+ gtk_style_context_invalidate(style);
+
sWidgetStorage[aWidgetType] = widget;
}
return widget;
@@ -725,6 +732,21 @@ CreateCSSNode(const char* aName, GtkStyleContext* aParentStyle, GType aType)
gtk_style_context_set_parent(context, aParentStyle);
gtk_widget_path_unref(path);
+ // In GTK 3.4, gtk_render_* functions use |theming_engine| on the style
+ // context without ensuring any style resolution sets it appropriately
+ // in style_data_lookup(). e.g.
+ // https://git.gnome.org/browse/gtk+/tree/gtk/gtkstylecontext.c?h=3.4.4#n3847
+ //
+ // That can result in incorrect drawing on first draw. To work around this,
+ // force a style look-up to set |theming_engine|. It is sufficient to do
+ // this only on context creation, instead of after every modification to the
+ // context, because themes typically (Ambiance and oxygen-gtk, at least) set
+ // the "engine" property with the '*' selector.
+ if (GTK_MAJOR_VERSION == 3 && gtk_get_minor_version() < 6) {
+ GdkRGBA unused;
+ gtk_style_context_get_color(context, GTK_STATE_FLAG_NORMAL, &unused);
+ }
+
return context;
}
@@ -747,13 +769,38 @@ GetWidgetRootStyle(WidgetNodeType aNodeType)
case MOZ_GTK_IMAGEMENUITEM:
style = CreateStyleForWidget(gtk_image_menu_item_new(), MOZ_GTK_MENUPOPUP);
break;
- case MOZ_GTK_CHECKMENUITEM_CONTAINER:
+ case MOZ_GTK_CHECKMENUITEM:
style = CreateStyleForWidget(gtk_check_menu_item_new(), MOZ_GTK_MENUPOPUP);
break;
- case MOZ_GTK_RADIOMENUITEM_CONTAINER:
+ case MOZ_GTK_RADIOMENUITEM:
style = CreateStyleForWidget(gtk_radio_menu_item_new(nullptr),
MOZ_GTK_MENUPOPUP);
break;
+ case MOZ_GTK_TEXT_VIEW:
+ style = CreateStyleForWidget(gtk_text_view_new(),
+ MOZ_GTK_SCROLLED_WINDOW);
+ break;
+ case MOZ_GTK_TOOLTIP:
+ if (gtk_check_version(3, 20, 0) != nullptr) {
+ // The tooltip style class is added first in CreateTooltipWidget()
+ // and transfered to style in CreateStyleForWidget().
+ GtkWidget* tooltipWindow = CreateTooltipWidget();
+ style = CreateStyleForWidget(tooltipWindow, nullptr);
+ gtk_widget_destroy(tooltipWindow); // Release GtkWindow self-reference.
+ } else {
+ // We create this from the path because GtkTooltipWindow is not public.
+ style = CreateCSSNode("tooltip", nullptr, GTK_TYPE_TOOLTIP);
+ gtk_style_context_add_class(style, GTK_STYLE_CLASS_BACKGROUND);
+ }
+ break;
+ case MOZ_GTK_TOOLTIP_BOX:
+ style = CreateStyleForWidget(gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0),
+ MOZ_GTK_TOOLTIP);
+ break;
+ case MOZ_GTK_TOOLTIP_BOX_LABEL:
+ style = CreateStyleForWidget(gtk_label_new(nullptr),
+ MOZ_GTK_TOOLTIP_BOX);
+ break;
default:
GtkWidget* widget = GetWidget(aNodeType);
MOZ_ASSERT(widget);
@@ -827,13 +874,13 @@ GetCssNodeStyleInternal(WidgetNodeType aNodeType)
style = CreateChildCSSNode(GTK_STYLE_CLASS_CHECK,
MOZ_GTK_CHECKBUTTON_CONTAINER);
break;
- case MOZ_GTK_RADIOMENUITEM:
+ case MOZ_GTK_RADIOMENUITEM_INDICATOR:
style = CreateChildCSSNode(GTK_STYLE_CLASS_RADIO,
- MOZ_GTK_RADIOMENUITEM_CONTAINER);
+ MOZ_GTK_RADIOMENUITEM);
break;
- case MOZ_GTK_CHECKMENUITEM:
+ case MOZ_GTK_CHECKMENUITEM_INDICATOR:
style = CreateChildCSSNode(GTK_STYLE_CLASS_CHECK,
- MOZ_GTK_CHECKMENUITEM_CONTAINER);
+ MOZ_GTK_CHECKMENUITEM);
break;
case MOZ_GTK_PROGRESS_TROUGH:
/* Progress bar background (trough) */
@@ -844,11 +891,6 @@ GetCssNodeStyleInternal(WidgetNodeType aNodeType)
style = CreateChildCSSNode("progress",
MOZ_GTK_PROGRESS_TROUGH);
break;
- case MOZ_GTK_TOOLTIP:
- // We create this from the path because GtkTooltipWindow is not public.
- style = CreateCSSNode("tooltip", nullptr, GTK_TYPE_TOOLTIP);
- gtk_style_context_add_class(style, GTK_STYLE_CLASS_BACKGROUND);
- break;
case MOZ_GTK_GRIPPER:
// TODO - create from CSS node
return GetWidgetStyleWithClass(MOZ_GTK_GRIPPER,
@@ -865,10 +907,28 @@ GetCssNodeStyleInternal(WidgetNodeType aNodeType)
// TODO - create from CSS node
return GetWidgetStyleWithClass(MOZ_GTK_SCROLLED_WINDOW,
GTK_STYLE_CLASS_FRAME);
- case MOZ_GTK_TEXT_VIEW:
- // TODO - create from CSS node
- return GetWidgetStyleWithClass(MOZ_GTK_TEXT_VIEW,
- GTK_STYLE_CLASS_VIEW);
+ case MOZ_GTK_TEXT_VIEW_TEXT:
+ case MOZ_GTK_RESIZER:
+ style = CreateChildCSSNode("text", MOZ_GTK_TEXT_VIEW);
+ if (aNodeType == MOZ_GTK_RESIZER) {
+ // The "grip" class provides the correct builtin icon from
+ // gtk_render_handle(). The icon is drawn with shaded variants of
+ // the background color, and so a transparent background would lead to
+ // a transparent resizer. gtk_render_handle() also uses the
+ // background color to draw a background, and so this style otherwise
+ // matches what is used in GtkTextView to match the background with
+ // textarea elements.
+ GdkRGBA color;
+ gtk_style_context_get_background_color(style, GTK_STATE_FLAG_NORMAL,
+ &color);
+ if (color.alpha == 0.0) {
+ g_object_unref(style);
+ style = CreateStyleForWidget(gtk_text_view_new(),
+ MOZ_GTK_SCROLLED_WINDOW);
+ }
+ gtk_style_context_add_class(style, GTK_STYLE_CLASS_GRIP);
+ }
+ break;
case MOZ_GTK_FRAME_BORDER:
style = CreateChildCSSNode("border", MOZ_GTK_FRAME);
break;
@@ -971,27 +1031,20 @@ GetWidgetStyleInternal(WidgetNodeType aNodeType)
case MOZ_GTK_CHECKBUTTON:
return GetWidgetStyleWithClass(MOZ_GTK_CHECKBUTTON_CONTAINER,
GTK_STYLE_CLASS_CHECK);
- case MOZ_GTK_RADIOMENUITEM:
- return GetWidgetStyleWithClass(MOZ_GTK_RADIOMENUITEM_CONTAINER,
+ case MOZ_GTK_RADIOMENUITEM_INDICATOR:
+ return GetWidgetStyleWithClass(MOZ_GTK_RADIOMENUITEM,
GTK_STYLE_CLASS_RADIO);
- case MOZ_GTK_CHECKMENUITEM:
- return GetWidgetStyleWithClass(MOZ_GTK_CHECKMENUITEM_CONTAINER,
+ 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);
- case MOZ_GTK_TOOLTIP: {
- GtkStyleContext* style = sStyleStorage[aNodeType];
- if (style)
- return style;
-
- // The tooltip style class is added first in CreateTooltipWidget() so
- // that gtk_widget_path_append_for_widget() in CreateStyleForWidget()
- // will find it.
- GtkWidget* tooltipWindow = CreateTooltipWidget();
- style = CreateStyleForWidget(tooltipWindow, nullptr);
- gtk_widget_destroy(tooltipWindow); // Release GtkWindow self-reference.
- sStyleStorage[aNodeType] = style;
+ case MOZ_GTK_PROGRESS_CHUNK: {
+ GtkStyleContext* style =
+ GetWidgetStyleWithClass(MOZ_GTK_PROGRESSBAR,
+ GTK_STYLE_CLASS_PROGRESSBAR);
+ gtk_style_context_remove_class(style, GTK_STYLE_CLASS_TROUGH);
return style;
}
case MOZ_GTK_GRIPPER:
@@ -1006,9 +1059,25 @@ GetWidgetStyleInternal(WidgetNodeType aNodeType)
case MOZ_GTK_SCROLLED_WINDOW:
return GetWidgetStyleWithClass(MOZ_GTK_SCROLLED_WINDOW,
GTK_STYLE_CLASS_FRAME);
- case MOZ_GTK_TEXT_VIEW:
- return GetWidgetStyleWithClass(MOZ_GTK_TEXT_VIEW,
- GTK_STYLE_CLASS_VIEW);
+ case MOZ_GTK_TEXT_VIEW_TEXT:
+ case MOZ_GTK_RESIZER: {
+ // GTK versions prior to 3.20 do not have the view class on the root
+ // node, but add this to determine the background for the text window.
+ GtkStyleContext* style =
+ GetWidgetStyleWithClass(MOZ_GTK_TEXT_VIEW, GTK_STYLE_CLASS_VIEW);
+ if (aNodeType == MOZ_GTK_RESIZER) {
+ // The "grip" class provides the correct builtin icon from
+ // gtk_render_handle(). The icon is drawn with shaded variants of
+ // the background color, and so a transparent background would lead to
+ // a transparent resizer. gtk_render_handle() also uses the
+ // background color to draw a background, and so this style otherwise
+ // matches MOZ_GTK_TEXT_VIEW_TEXT to match the background with
+ // textarea elements. GtkTextView creates a separate text window and
+ // so the background should not be transparent.
+ gtk_style_context_add_class(style, GTK_STYLE_CLASS_GRIP);
+ }
+ return style;
+ }
case MOZ_GTK_FRAME_BORDER:
return GetWidgetRootStyle(MOZ_GTK_FRAME);
case MOZ_GTK_TREEVIEW_VIEW: