Bug 1472276 - Make -moz-cellhighlight distinct from Highlight and -moz-field r=karlt draft
authorTim Nguyen <ntim.bugs@gmail.com>
Fri, 29 Jun 2018 19:23:03 +0100
changeset 828213 42bb15e86252d72a3f58831079162d0f4723afc9
parent 821479 143984185dcece46031c970179ddea4837a6c01d
push id118649
push userbmo:ntim.bugs@gmail.com
push dateFri, 10 Aug 2018 08:39:11 +0000
reviewerskarlt
bugs1472276
milestone63.0a1
Bug 1472276 - Make -moz-cellhighlight distinct from Highlight and -moz-field r=karlt Since focused+selected tree cells will no longer get an outline, we will start using a different background for the unfocused state. That background needs to be distinct from Highlight, used on selected and focused items and also distinct from -moz-appearance: listbox, which is used as the box background. MozReview-Commit-ID: 7hcnueYlOXR
widget/LookAndFeel.h
widget/gtk/moz.build
widget/gtk/nsLookAndFeel.cpp
widget/gtk/nsLookAndFeel.h
--- a/widget/LookAndFeel.h
+++ b/widget/LookAndFeel.h
@@ -101,17 +101,19 @@ public:
     // Colors which will hopefully become CSS3
     eColorID__moz_field,
     eColorID__moz_fieldtext,
     eColorID__moz_dialog,
     eColorID__moz_dialogtext,
     // used to highlight valid regions to drop something onto
     eColorID__moz_dragtargetzone,
 
-    // used to cell text background, selected but not focus
+    // used to cell text background, selected but not focus.
+    // It is not necessarily a system color, but it is
+    // distinct from -moz-appearance: listbox; and Highlight
     eColorID__moz_cellhighlight,
     // used to cell text, selected but not focus
     eColorID__moz_cellhighlighttext,
     // used to html select cell text background, selected but not focus
     eColorID__moz_html_cellhighlight,
     // used to html select cell text, selected but not focus
     eColorID__moz_html_cellhighlighttext,
     // used to button text background, when mouse is over
--- a/widget/gtk/moz.build
+++ b/widget/gtk/moz.build
@@ -119,16 +119,17 @@ else:
         'WidgetStyleCache.cpp',
     ]
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
 
 LOCAL_INCLUDES += [
+    '/layout/base',
     '/layout/generic',
     '/layout/xul',
     '/other-licenses/atk-1.0',
     '/widget',
     '/widget/headless',
 ]
 
 if CONFIG['MOZ_X11']:
--- a/widget/gtk/nsLookAndFeel.cpp
+++ b/widget/gtk/nsLookAndFeel.cpp
@@ -27,16 +27,17 @@
 #include "WidgetUtils.h"
 #include "nsWindow.h"
 
 #include "mozilla/gfx/2D.h"
 
 #include <cairo-gobject.h>
 #include "WidgetStyleCache.h"
 #include "prenv.h"
+#include "nsCSSColorUtils.h"
 
 using namespace mozilla;
 using mozilla::LookAndFeel;
 
 #define GDK_COLOR_TO_NS_RGB(c) \
     ((nscolor) NS_RGB(c.red>>8, c.green>>8, c.blue>>8))
 #define GDK_RGBA_TO_NS_RGBA(c) \
     ((nscolor) NS_RGBA((int)((c).red*255), (int)((c).green*255), \
@@ -210,16 +211,68 @@ GetBorderColors(GtkStyleContext* aContex
 {
     GdkRGBA lightColor, darkColor;
     bool ret = GetBorderColors(aContext, &lightColor, &darkColor);
     *aLightColor = GDK_RGBA_TO_NS_RGBA(lightColor);
     *aDarkColor = GDK_RGBA_TO_NS_RGBA(darkColor);
     return ret;
 }
 
+// Finds ideal cell highlight colors used for unfocused+selected cells distinct
+// from both Highlight, used as focused+selected background, and the listbox
+// background which is assumed to be similar to -moz-field
+nsresult
+nsLookAndFeel::InitCellHighlightColors() {
+    // NS_SUFFICIENT_LUMINOSITY_DIFFERENCE is the a11y standard for text
+    // on a background. Use 20% of that standard since we have a background
+    // on top of another background
+    int32_t minLuminosityDifference = NS_SUFFICIENT_LUMINOSITY_DIFFERENCE / 5;
+    int32_t backLuminosityDifference = NS_LUMINOSITY_DIFFERENCE(
+        mMozWindowBackground, mMozFieldBackground);
+    if (backLuminosityDifference >= minLuminosityDifference) {
+        mMozCellHighlightBackground = mMozWindowBackground;
+        mMozCellHighlightText = mMozWindowText;
+        return NS_OK;
+    }
+
+    uint16_t hue, sat, luminance;
+    uint8_t alpha;
+    mMozCellHighlightBackground = mMozFieldBackground;
+    mMozCellHighlightText = mMozFieldText;
+
+    NS_RGB2HSV(mMozCellHighlightBackground, hue, sat, luminance, alpha);
+
+    uint16_t step = 30;
+    // Lighten the color if the color is very dark
+    if (luminance <= step) {
+        luminance += step;
+    }
+    // Darken it if it is very light
+    else if (luminance >= 255 - step) {
+        luminance -= step;
+    }
+    // Otherwise, compute what works best depending on the text luminance.
+    else {
+        uint16_t textHue, textSat, textLuminance;
+        uint8_t textAlpha;
+        NS_RGB2HSV(mMozCellHighlightText, textHue, textSat, textLuminance,
+            textAlpha);
+        // Text is darker than background, use a lighter shade
+        if (textLuminance < luminance) {
+            luminance += step;
+        }
+        // Otherwise, use a darker shade
+        else {
+            luminance -= step;
+        }
+    }
+    NS_HSV2RGB(mMozCellHighlightBackground, hue, sat, luminance, alpha);
+    return NS_OK;
+}
+
 void
 nsLookAndFeel::NativeInit()
 {
     EnsureInit();
 }
 
 void
 nsLookAndFeel::RefreshImpl()
@@ -266,30 +319,34 @@ nsLookAndFeel::NativeGetColor(ColorID aI
     case eColorID__moz_dialogtext:
         aColor = mMozWindowText;
         break;
     case eColorID_WidgetSelectBackground:
     case eColorID_TextSelectBackground:
     case eColorID_IMESelectedRawTextBackground:
     case eColorID_IMESelectedConvertedTextBackground:
     case eColorID__moz_dragtargetzone:
-    case eColorID__moz_cellhighlight:
     case eColorID__moz_html_cellhighlight:
     case eColorID_highlight: // preference selected item,
         aColor = mTextSelectedBackground;
         break;
     case eColorID_WidgetSelectForeground:
     case eColorID_TextSelectForeground:
     case eColorID_IMESelectedRawTextForeground:
     case eColorID_IMESelectedConvertedTextForeground:
     case eColorID_highlighttext:
-    case eColorID__moz_cellhighlighttext:
     case eColorID__moz_html_cellhighlighttext:
         aColor = mTextSelectedText;
         break;
+    case eColorID__moz_cellhighlight:
+        aColor = mMozCellHighlightBackground;
+        break;
+    case eColorID__moz_cellhighlighttext:
+        aColor = mMozCellHighlightText;
+        break;
     case eColorID_Widget3DHighlight:
         aColor = NS_RGB(0xa0,0xa0,0xa0);
         break;
     case eColorID_Widget3DShadow:
         aColor = NS_RGB(0x40,0x40,0x40);
         break;
     case eColorID_IMERawInputBackground:
     case eColorID_IMEConvertedTextBackground:
@@ -1006,16 +1063,19 @@ nsLookAndFeel::EnsureInit()
 
     // Get odd row background color
     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);
     mOddCellBackground = GDK_RGBA_TO_NS_RGBA(color);
     gtk_style_context_restore(style);
 
+    // Compute cell highlight colors
+    InitCellHighlightColors();
+
     // 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 = GetStyleContext(MOZ_GTK_FRAME_BORDER);
     bool themeUsesColors =
         GetBorderColors(style, &mFrameOuterLightBorder, &mFrameInnerDarkBorder);
     if (!themeUsesColors) {
--- a/widget/gtk/nsLookAndFeel.h
+++ b/widget/gtk/nsLookAndFeel.h
@@ -72,25 +72,30 @@ protected:
     nscolor mComboBoxBackground;
     nscolor mMozFieldText;
     nscolor mMozFieldBackground;
     nscolor mMozWindowText;
     nscolor mMozWindowBackground;
     nscolor mMozWindowActiveBorder;
     nscolor mMozWindowInactiveBorder;
     nscolor mMozWindowInactiveCaption;
+    nscolor mMozCellHighlightBackground;
+    nscolor mMozCellHighlightText;
     nscolor mTextSelectedText;
     nscolor mTextSelectedBackground;
     nscolor mMozScrollbar;
     nscolor mInfoBarText;
     char16_t mInvisibleCharacter;
     float   mCaretRatio;
     bool    mMenuSupportsDrag;
     bool    mCSDAvailable;
     bool    mCSDMaximizeButton;
     bool    mCSDMinimizeButton;
     bool    mCSDCloseButton;
     bool    mInitialized;
 
     void EnsureInit();
+
+private:
+    nsresult InitCellHighlightColors();
 };
 
 #endif