bug 1315527 check root node of frame for border color if no border on the "border" subnode r=stransky+263117 a=jcristau
authorKarl Tomlinson <karlt+@karlt.net>
Mon, 21 Nov 2016 18:07:48 +1300
changeset 353322 21c5d924faf66dda8fe8aa882194c9091c7b8f8f
parent 353321 52cb6e5dd64d39bea974ef9ed1371b274900ee1f
child 353323 a7e613c48e2ab4a4c6a495dc759acf0bbda20d44
push id6795
push userjlund@mozilla.com
push dateMon, 23 Jan 2017 14:19:46 +0000
treeherdermozilla-esr52@76101b503191 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersstransky, jcristau
bugs1315527, 263117
milestone52.0a2
bug 1315527 check root node of frame for border color if no border on the "border" subnode r=stransky+263117 a=jcristau Some themes do not draw the "border" subnode, but instead draw a border on the frame root node. MozReview-Commit-ID: Fx67mQhhYmz
widget/gtk/nsLookAndFeel.cpp
--- a/widget/gtk/nsLookAndFeel.cpp
+++ b/widget/gtk/nsLookAndFeel.cpp
@@ -152,40 +152,65 @@ GetUnicoBorderGradientColors(GtkStyleCon
     gtk_style_context_get_property(aContext, propertyName, state, &value);
 
     bool result = GetGradientColors(&value, aLightColor, aDarkColor);
 
     g_value_unset(&value);
     return result;
 }
 
-
-static void
+// Sets |aLightColor| and |aDarkColor| to colors from |aContext|.  Returns
+// true if |aContext| uses these colors to render a visible border.
+// If returning false, then the colors returned are a fallback from the
+// border-color value even though |aContext| does not use these colors to
+// render a border.
+static bool
 GetBorderColors(GtkStyleContext* aContext,
                 GdkRGBA* aLightColor, GdkRGBA* aDarkColor)
 {
-    if (GetUnicoBorderGradientColors(aContext, aLightColor, aDarkColor))
-        return;
+    // Determine whether the border on this style context is visible.
+    GtkStateFlags state = gtk_style_context_get_state(aContext);
+    GtkBorderStyle borderStyle;
+    gtk_style_context_get(aContext, state, GTK_STYLE_PROPERTY_BORDER_STYLE,
+                          &borderStyle, nullptr);
+    bool visible = borderStyle != GTK_BORDER_STYLE_NONE &&
+        borderStyle != GTK_BORDER_STYLE_HIDDEN;
+    if (visible) {
+        // GTK has an initial value of zero for border-widths, and so themes
+        // need to explicitly set border-widths to make borders visible.
+        GtkBorder border;
+        gtk_style_context_get_border(aContext, GTK_STATE_FLAG_NORMAL, &border);
+        visible = border.top != 0 || border.right != 0 ||
+            border.bottom != 0 || border.left != 0;
+    }
 
-    GtkStateFlags state = gtk_style_context_get_state(aContext);
+    if (visible &&
+        GetUnicoBorderGradientColors(aContext, aLightColor, aDarkColor))
+        return true;
+
+    // The initial value for the border-color is the foreground color, and so
+    // this will usually return a color distinct from the background even if
+    // there is no visible border detected.
     gtk_style_context_get_border_color(aContext, state, aDarkColor);
     // TODO GTK3 - update aLightColor
     // for GTK_BORDER_STYLE_INSET/OUTSET/GROVE/RIDGE border styles.
     // https://bugzilla.mozilla.org/show_bug.cgi?id=978172#c25
     *aLightColor = *aDarkColor;
+    return visible;
 }
 
-static void
+static bool
 GetBorderColors(GtkStyleContext* aContext,
                 nscolor* aLightColor, nscolor* aDarkColor)
 {
     GdkRGBA lightColor, darkColor;
-    GetBorderColors(aContext, &lightColor, &darkColor);
+    bool ret = GetBorderColors(aContext, &lightColor, &darkColor);
     *aLightColor = GDK_RGBA_TO_NS_RGBA(lightColor);
     *aDarkColor = GDK_RGBA_TO_NS_RGBA(darkColor);
+    return ret;
 }
 #endif
 
 nsresult
 nsLookAndFeel::NativeGetColor(ColorID aID, nscolor& aColor)
 {
 #if (MOZ_WIDGET_GTK == 3)
     GdkRGBA gdk_color;
@@ -1335,19 +1360,29 @@ nsLookAndFeel::Init()
     gtk_style_context_save(style);
     gtk_style_context_add_region(style, GTK_STYLE_REGION_ROW, GTK_REGION_ODD);
     gtk_style_context_get_background_color(style, GTK_STATE_FLAG_NORMAL, &color);
     sOddCellBackground = GDK_RGBA_TO_NS_RGBA(color);
     gtk_style_context_restore(style);
 
     gtk_widget_path_free(path);
 
+    // GtkFrame has a "border" subnode on which Adwaita draws the border.
+    // Some themes do not draw on this node but draw a border on the widget
+    // root node, so check the root node if no border is found on the border
+    // node.
     style = ClaimStyleContext(MOZ_GTK_FRAME_BORDER);
-    GetBorderColors(style, &sFrameOuterLightBorder, &sFrameInnerDarkBorder);
+    bool themeUsesColors =
+        GetBorderColors(style, &sFrameOuterLightBorder, &sFrameInnerDarkBorder);
     ReleaseStyleContext(style);
+    if (!themeUsesColors) {
+        style = ClaimStyleContext(MOZ_GTK_FRAME);
+        GetBorderColors(style, &sFrameOuterLightBorder, &sFrameInnerDarkBorder);
+        ReleaseStyleContext(style);
+    }
 
     // GtkInfoBar
     // TODO - Use WidgetCache for it?
     GtkWidget* infoBar = gtk_info_bar_new();
     GtkWidget* infoBarContent = gtk_info_bar_get_content_area(GTK_INFO_BAR(infoBar));
     GtkWidget* infoBarLabel = gtk_label_new(nullptr);
     gtk_container_add(GTK_CONTAINER(parent), infoBar);
     gtk_container_add(GTK_CONTAINER(infoBarContent), infoBarLabel);