diff --git a/widget/gtk/WidgetStyleCache.cpp b/widget/gtk/WidgetStyleCache.cpp index 4c111c6eacc4..4cf8f6c84900 100644 --- a/widget/gtk/WidgetStyleCache.cpp +++ b/widget/gtk/WidgetStyleCache.cpp @@ -10,6 +10,7 @@ #include "gtkdrawing.h" #include "mozilla/Assertions.h" #include "mozilla/PodOperations.h" +#include "mozilla/ScopeExit.h" #include "nsDebug.h" #include "nsPrintfCString.h" #include "nsString.h" @@ -26,6 +27,8 @@ enum class CSDStyle { Normal, }; +static bool gHeaderBarShouldDrawContainer = false; +static bool gMaximizedHeaderBarShouldDrawContainer = false; static CSDStyle gCSDStyle = CSDStyle::Unknown; static GtkWidget* sWidgetStorage[MOZ_GTK_WIDGET_NODE_COUNT]; static GtkStyleContext* sStyleStorage[MOZ_GTK_WIDGET_NODE_COUNT]; @@ -440,6 +443,21 @@ static GtkWidget* CreateNotebookWidget() { return widget; } +static bool HasBackground(GtkStyleContext* aStyle) { + GdkRGBA gdkColor; + gtk_style_context_get_background_color(aStyle, GTK_STATE_FLAG_NORMAL, + &gdkColor); + if (gdkColor.alpha != 0.0) { + return true; + } + + GValue value = G_VALUE_INIT; + gtk_style_context_get_property(aStyle, "background-image", + GTK_STATE_FLAG_NORMAL, &value); + auto cleanup = mozilla::MakeScopeExit([&] { g_value_unset(&value); }); + return g_value_get_boxed(&value); +} + static void CreateHeaderBarWidget(WidgetNodeType aAppearance) { GtkWidget* window = gtk_window_new(GTK_WINDOW_TOPLEVEL); GtkStyleContext* windowStyle = gtk_widget_get_style_context(window); @@ -489,7 +507,27 @@ static void CreateHeaderBarWidget(WidgetNodeType aAppearance) { } gtk_container_add(GTK_CONTAINER(window), fixed); - gtk_container_add(GTK_CONTAINER(fixed), sWidgetStorage[aAppearance]); + gtk_container_add(GTK_CONTAINER(fixed), headerBar); + + gtk_style_context_invalidate(headerBarStyle); + gtk_style_context_invalidate(fixedStyle); + + // Some themes like Elementary's style the container of the headerbar rather + // than the header bar itself. + bool& shouldDrawContainer = aAppearance == MOZ_GTK_HEADER_BAR + ? gHeaderBarShouldDrawContainer + : gMaximizedHeaderBarShouldDrawContainer; + shouldDrawContainer = [&] { + const bool headerBarHasBackground = HasBackground(headerBarStyle); + if (headerBarHasBackground && GetBorderRadius(headerBarStyle)) { + return false; + } + if (HasBackground(fixedStyle) && + (GetBorderRadius(fixedStyle) || !headerBarHasBackground)) { + return true; + } + return false; + }(); } #define ICON_SCALE_VARIANTS 2 @@ -554,7 +592,7 @@ static void CreateHeaderBarButton(GtkWidget* aParentWidget, // We bypass GetWidget() here because we create all titlebar // buttons at once when a first one is requested. - NS_ASSERTION(sWidgetStorage[aAppearance] == nullptr, + NS_ASSERTION(!sWidgetStorage[aAppearance], "Titlebar button is already created!"); sWidgetStorage[aAppearance] = widget; @@ -754,6 +792,8 @@ static GtkWidget* CreateWidget(WidgetNodeType aAppearance) { return CreateComboBoxEntryArrowWidget(); case MOZ_GTK_HEADERBAR_WINDOW: case MOZ_GTK_HEADERBAR_WINDOW_MAXIMIZED: + case MOZ_GTK_HEADERBAR_FIXED: + case MOZ_GTK_HEADERBAR_FIXED_MAXIMIZED: case MOZ_GTK_HEADER_BAR: case MOZ_GTK_HEADER_BAR_MAXIMIZED: case MOZ_GTK_HEADER_BAR_BUTTON_CLOSE: @@ -1461,6 +1501,15 @@ void StyleContextSetScale(GtkStyleContext* style, gint aScaleFactor) { } } +bool HeaderBarShouldDrawContainer(WidgetNodeType aNodeType) { + MOZ_ASSERT(aNodeType == MOZ_GTK_HEADER_BAR || + aNodeType == MOZ_GTK_HEADER_BAR_MAXIMIZED); + mozilla::Unused << GetWidget(aNodeType); + return aNodeType == MOZ_GTK_HEADER_BAR + ? gHeaderBarShouldDrawContainer + : gMaximizedHeaderBarShouldDrawContainer; +} + gint GetBorderRadius(GtkStyleContext* aStyle) { GValue value = G_VALUE_INIT; // NOTE(emilio): In an ideal world, we'd query the two longhands diff --git a/widget/gtk/WidgetStyleCache.h b/widget/gtk/WidgetStyleCache.h index f5e6bbd570e2..f38b75fae6d9 100644 --- a/widget/gtk/WidgetStyleCache.h +++ b/widget/gtk/WidgetStyleCache.h @@ -58,4 +58,6 @@ void StyleContextSetScale(GtkStyleContext* style, gint aScaleFactor); gint GetBorderRadius(GtkStyleContext* aStyle); +bool HeaderBarShouldDrawContainer(WidgetNodeType); + #endif // WidgetStyleCache_h diff --git a/widget/gtk/gtk3drawing.cpp b/widget/gtk/gtk3drawing.cpp index 5e3e55f714f7..b3fc3b30d8a3 100644 --- a/widget/gtk/gtk3drawing.cpp +++ b/widget/gtk/gtk3drawing.cpp @@ -2177,15 +2177,12 @@ static gint moz_gtk_header_bar_paint(WidgetNodeType widgetType, cairo_t* cr, // Some themes like Elementary's style the container of the headerbar rather // than the header bar itself. - if (!GetBorderRadius(style)) { + if (HeaderBarShouldDrawContainer(widgetType)) { auto containerType = widgetType == MOZ_GTK_HEADER_BAR ? MOZ_GTK_HEADERBAR_FIXED : MOZ_GTK_HEADERBAR_FIXED_MAXIMIZED; - GtkStyleContext* containerStyle = GetStyleContext( + style = GetStyleContext( containerType, state->scale, GTK_TEXT_DIR_NONE, state_flags); - if (GetBorderRadius(containerStyle)) { - style = containerStyle; - } } // Some themes (Adwaita for instance) draws bold dark line at diff --git a/widget/gtk/nsLookAndFeel.cpp b/widget/gtk/nsLookAndFeel.cpp index f740a902a870..1716eb94ad13 100644 --- a/widget/gtk/nsLookAndFeel.cpp +++ b/widget/gtk/nsLookAndFeel.cpp @@ -1549,7 +1549,10 @@ void nsLookAndFeel::PerThemeData::Init() { g_object_unref(accelStyle); } - style = GetStyleContext(MOZ_GTK_HEADER_BAR); + const auto effectiveHeaderBarStyle = + HeaderBarShouldDrawContainer(MOZ_GTK_HEADER_BAR) ? MOZ_GTK_HEADERBAR_FIXED + : MOZ_GTK_HEADER_BAR; + style = GetStyleContext(effectiveHeaderBarStyle); { gtk_style_context_get_color(style, GTK_STATE_FLAG_NORMAL, &color); mTitlebarText = GDK_RGBA_TO_NS_RGBA(color); @@ -1559,15 +1562,7 @@ void nsLookAndFeel::PerThemeData::Init() { mTitlebarInactiveText = GDK_RGBA_TO_NS_RGBA(color); mTitlebarInactiveBackground = GetBackgroundColor(style, mTitlebarText, GTK_STATE_FLAG_BACKDROP); - mTitlebarRadius = 0; - if (!IsSolidCSDStyleUsed()) { - mTitlebarRadius = GetBorderRadius(style); - if (!mTitlebarRadius) { - // Some themes like ElementaryOS set the radius on the headerbar parent. - style = GetStyleContext(MOZ_GTK_HEADERBAR_FIXED); - mTitlebarRadius = GetBorderRadius(style); - } - } + mTitlebarRadius = IsSolidCSDStyleUsed() ? 0 : GetBorderRadius(style); } style = GetStyleContext(MOZ_GTK_MENUPOPUP);