Bug 1403690 Part 2: Windows change nsLookAndFeel::NativeGetColor to use cached colors. draft
authorBrad Werth <bwerth@mozilla.com>
Mon, 02 Oct 2017 16:17:05 -0700
changeset 687771 4027bb9d9fbc754218cbd9a706d93fbf37b0660f
parent 687770 ab59b699887822640c3ebc61ecaca79ca7b658b8
child 687772 9c24f5c11c8ca1f7e025fb1bfbba8e16e9c68b8c
push id86600
push userbwerth@mozilla.com
push dateFri, 27 Oct 2017 18:57:26 +0000
bugs1403690
milestone58.0a1
Bug 1403690 Part 2: Windows change nsLookAndFeel::NativeGetColor to use cached colors. MozReview-Commit-ID: 7CKUrtCYC0j
widget/cocoa/nsLookAndFeel.h
widget/windows/nsLookAndFeel.cpp
widget/windows/nsLookAndFeel.h
--- a/widget/cocoa/nsLookAndFeel.h
+++ b/widget/cocoa/nsLookAndFeel.h
@@ -9,17 +9,17 @@
 
 class nsLookAndFeel final : public nsXPLookAndFeel
 {
 public:
   nsLookAndFeel();
   virtual ~nsLookAndFeel();
 
   virtual nsresult NativeGetColor(ColorID aID, nscolor &aResult);
-  virtual void NativeInit() final {};
+  virtual void NativeInit() final;
   virtual nsresult GetIntImpl(IntID aID, int32_t &aResult);
   virtual nsresult GetFloatImpl(FloatID aID, float &aResult);
   virtual bool GetFontImpl(FontID aID, nsString& aFontName,
                            gfxFontStyle& aFontStyle,
                            float aDevPixPerCSSPixel);
   virtual char16_t GetPasswordCharacterImpl()
   {
     // unicode value for the bullet character, used for password textfields.
--- a/widget/windows/nsLookAndFeel.cpp
+++ b/widget/windows/nsLookAndFeel.cpp
@@ -9,16 +9,17 @@
 #include "nsStyleConsts.h"
 #include "nsUXThemeData.h"
 #include "nsUXThemeConstants.h"
 #include "WinUtils.h"
 #include "mozilla/Telemetry.h"
 #include "mozilla/WindowsVersion.h"
 #include "gfxFontConstants.h"
 
+
 using namespace mozilla;
 using namespace mozilla::widget;
 
 //static
 LookAndFeel::OperatingSystemVersion
 nsLookAndFeel::GetOperatingSystemVersion()
 {
   static OperatingSystemVersion version = eOperatingSystemVersion_Unknown;
@@ -61,28 +62,56 @@ static int32_t GetSystemParam(long flag,
 }
 
 nsLookAndFeel::nsLookAndFeel()
   : nsXPLookAndFeel()
   , mUseAccessibilityTheme(0)
   , mUseDefaultTheme(0)
   , mNativeThemeId(eWindowsTheme_Generic)
   , mCaretBlinkTime(-1)
+  , mHasColorAccent(false)
+  , mHasColorAccentText(false)
+  , mHasColorMenuHoverText(false)
+  , mHasColorMediaText(false)
+  , mHasColorCommunicationsText(false)
+  , mInitialized(false)
 {
   mozilla::Telemetry::Accumulate(mozilla::Telemetry::TOUCH_ENABLED_DEVICE,
                                  WinUtils::IsTouchDeviceSupportPresent());
 }
 
 nsLookAndFeel::~nsLookAndFeel()
 {
 }
 
+void
+nsLookAndFeel::NativeInit()
+{
+  EnsureInit();
+}
+
+/* virtual */ void
+nsLookAndFeel::RefreshImpl()
+{
+  nsXPLookAndFeel::RefreshImpl();
+
+  for (auto e = mSystemFontCache.begin(), end = mSystemFontCache.end();
+       e != end; ++e) {
+    e->mCacheValid = false;
+  }
+  mCaretBlinkTime = -1;
+
+  mInitialized = false;
+}
+
 nsresult
 nsLookAndFeel::NativeGetColor(ColorID aID, nscolor &aColor)
 {
+  EnsureInit();
+
   nsresult res = NS_OK;
 
   int idx;
   switch (aID) {
     case eColorID_WindowBackground:
         idx = COLOR_WINDOW;
         break;
     case eColorID_WindowForeground:
@@ -184,23 +213,21 @@ nsLookAndFeel::NativeGetColor(ColorID aI
       if (!IsAppThemed()) {
         idx = nsUXThemeData::sFlatMenus ?
                 COLOR_HIGHLIGHTTEXT :
                 COLOR_MENUTEXT;
         break;
       }
       // Fall through
     case eColorID__moz_menuhovertext:
-      if (IsAppThemed()) {
-        res = ::GetColorFromTheme(eUXMenu,
-                                  MENU_POPUPITEM, MPI_HOT, TMT_TEXTCOLOR, aColor);
-        if (NS_SUCCEEDED(res))
-          return res;
-        // fall through to highlight case
+      if (mHasColorMenuHoverText) {
+        aColor = mColorMenuHoverText;
+        return NS_OK;
       }
+      // Fall through
     case eColorID_highlighttext:
     case eColorID__moz_html_cellhighlighttext:
       idx = COLOR_HIGHLIGHTTEXT;
       break;
     case eColorID_inactiveborder:
       idx = COLOR_INACTIVEBORDER;
       break;
     case eColorID_inactivecaption:
@@ -259,46 +286,42 @@ nsLookAndFeel::NativeGetColor(ColorID aI
     case eColorID__moz_comboboxtext:
       idx = COLOR_WINDOWTEXT;
       break;
     case eColorID__moz_dialog:
     case eColorID__moz_cellhighlight:
       idx = COLOR_3DFACE;
       break;
     case eColorID__moz_win_accentcolor:
-      res = GetAccentColor(aColor);
-      if (NS_SUCCEEDED(res)) {
-        return res;
+      if (mHasColorAccent) {
+        aColor = mColorAccent;
+      } else {
+        // Seems to be the default color (hardcoded because of bug 1065998)
+        aColor = NS_RGB(158, 158, 158);
       }
-      // Seems to be the default color (hardcoded because of bug 1065998)
-      aColor = NS_RGB(158, 158, 158);
       return NS_OK;
     case eColorID__moz_win_accentcolortext:
-      res = GetAccentColorText(aColor);
-      if (NS_SUCCEEDED(res)) {
-        return res;
+      if (mHasColorAccentText) {
+        aColor = mColorAccentText;
+      } else {
+        aColor = NS_RGB(0, 0, 0);
       }
-      aColor = NS_RGB(0, 0, 0);
       return NS_OK;
     case eColorID__moz_win_mediatext:
-      if (IsAppThemed()) {
-        res = ::GetColorFromTheme(eUXMediaToolbar,
-                                  TP_BUTTON, TS_NORMAL, TMT_TEXTCOLOR, aColor);
-        if (NS_SUCCEEDED(res))
-          return res;
+      if (mHasColorMediaText) {
+        aColor = mColorMediaText;
+        return NS_OK;
       }
       // if we've gotten here just return -moz-dialogtext instead
       idx = COLOR_WINDOWTEXT;
       break;
     case eColorID__moz_win_communicationstext:
-      if (IsAppThemed()) {
-        res = ::GetColorFromTheme(eUXCommunicationsToolbar,
-                                  TP_BUTTON, TS_NORMAL, TMT_TEXTCOLOR, aColor);
-        if (NS_SUCCEEDED(res))
-          return res;
+      if (mHasColorCommunicationsText) {
+        aColor = mColorCommunicationsText;
+        return NS_OK;
       }
       // if we've gotten here just return -moz-dialogtext instead
       idx = COLOR_WINDOWTEXT;
       break;
     case eColorID__moz_dialogtext:
     case eColorID__moz_cellhighlighttext:
       idx = COLOR_WINDOWTEXT;
       break;
@@ -313,18 +336,17 @@ nsLookAndFeel::NativeGetColor(ColorID aI
       break;
     default:
       NS_WARNING("Unknown color for nsLookAndFeel");
       idx = COLOR_WINDOW;
       res = NS_ERROR_FAILURE;
       break;
     }
 
-  DWORD color = ::GetSysColor(idx);
-  aColor = COLOREF_2_NSRGB(color);
+  aColor = GetColorForSysColorIndex(idx);
 
   return res;
 }
 
 nsresult
 nsLookAndFeel::GetIntImpl(IntID aID, int32_t &aResult)
 {
   nsresult res = nsXPLookAndFeel::GetIntImpl(aID, aResult);
@@ -728,28 +750,16 @@ nsLookAndFeel::GetFontImpl(FontID anID, 
       cacheSlot.mFontStyle = aFontStyle;
     }
   }
   // now convert the logical font size from GetSysFontInfo into device pixels for layout
   aFontStyle.size *= aDevPixPerCSSPixel;
   return status;
 }
 
-/* virtual */ void
-nsLookAndFeel::RefreshImpl()
-{
-  nsXPLookAndFeel::RefreshImpl();
-
-  for (auto e = mSystemFontCache.begin(), end = mSystemFontCache.end();
-       e != end; ++e) {
-    e->mCacheValid = false;
-  }
-  mCaretBlinkTime = -1;
-}
-
 /* virtual */
 char16_t
 nsLookAndFeel::GetPasswordCharacterImpl()
 {
 #define UNICODE_BLACK_CIRCLE_CHAR 0x25cf
   return UNICODE_BLACK_CIRCLE_CHAR;
 }
 
@@ -849,8 +859,52 @@ nsLookAndFeel::GetAccentColorText(nscolo
   float luminance = (NS_GET_R(accentColor) * 2 +
                      NS_GET_G(accentColor) * 5 +
                      NS_GET_B(accentColor)) / 8;
 
   aColor = (luminance <= 128) ? NS_RGB(255, 255, 255) : NS_RGB(0, 0, 0);
 
   return NS_OK;
 }
+
+nscolor
+nsLookAndFeel::GetColorForSysColorIndex(int index)
+{
+  MOZ_ASSERT(index >= SYS_COLOR_MIN && index <= SYS_COLOR_MAX);
+  return mSysColorTable[index - SYS_COLOR_MIN];
+}
+
+void
+nsLookAndFeel::EnsureInit()
+{
+  if (mInitialized) {
+    return;
+  }
+  mInitialized = true;
+
+  nsresult res;
+
+  res = GetAccentColor(mColorAccent);
+  mHasColorAccent = NS_SUCCEEDED(res);
+
+  res = GetAccentColorText(mColorAccentText);
+  mHasColorAccentText = NS_SUCCEEDED(res);
+
+  if (IsAppThemed()) {
+    res = ::GetColorFromTheme(eUXMenu, MENU_POPUPITEM, MPI_HOT, TMT_TEXTCOLOR,
+                              mColorMenuHoverText);
+    mHasColorMenuHoverText = NS_SUCCEEDED(res);
+
+    res = ::GetColorFromTheme(eUXMediaToolbar, TP_BUTTON, TS_NORMAL,
+                              TMT_TEXTCOLOR, mColorMediaText);
+    mHasColorMediaText = NS_SUCCEEDED(res);
+
+    res = ::GetColorFromTheme(eUXCommunicationsToolbar, TP_BUTTON, TS_NORMAL,
+                              TMT_TEXTCOLOR, mColorCommunicationsText);
+    mHasColorCommunicationsText = NS_SUCCEEDED(res);
+  }
+
+  // Fill out the sys color table.
+  for (int i = SYS_COLOR_MIN; i <= SYS_COLOR_MAX; ++i) {
+    DWORD color = ::GetSysColor(i);
+    mSysColorTable[i - SYS_COLOR_MIN] = COLOREF_2_NSRGB(color);
+  }
+}
--- a/widget/windows/nsLookAndFeel.h
+++ b/widget/windows/nsLookAndFeel.h
@@ -30,31 +30,38 @@
 /*
  * Tablet mode detection
  */
 #ifndef SM_SYSTEMDOCKED
 #define SM_CONVERTIBLESLATEMODE 0x00002003
 #define SM_SYSTEMDOCKED         0x00002004
 #endif
 
+/*
+ * Color constant inclusive bounds for GetSysColor
+ */
+#define SYS_COLOR_MIN 0
+#define SYS_COLOR_MAX 30
+#define SYS_COLOR_COUNT (SYS_COLOR_MAX - SYS_COLOR_MIN + 1)
+
 class nsLookAndFeel final : public nsXPLookAndFeel
 {
   static OperatingSystemVersion GetOperatingSystemVersion();
 public:
   nsLookAndFeel();
   virtual ~nsLookAndFeel();
 
+  void NativeInit() final;
+  void RefreshImpl() override;
   nsresult NativeGetColor(ColorID aID, nscolor &aResult) override;
-  void NativeInit() final {};
   nsresult GetIntImpl(IntID aID, int32_t &aResult) override;
   nsresult GetFloatImpl(FloatID aID, float &aResult) override;
   bool GetFontImpl(FontID aID, nsString& aFontName,
                    gfxFontStyle& aFontStyle,
                    float aDevPixPerCSSPixel) override;
-  void RefreshImpl() override;
   char16_t GetPasswordCharacterImpl() override;
 
   nsTArray<LookAndFeelInt> GetIntCacheImpl() override;
   void SetIntCacheImpl(const nsTArray<LookAndFeelInt>& aLookAndFeelIntCache) override;
 
 private:
   /**
    * Fetches the Windows accent color from the Windows settings if
@@ -67,23 +74,43 @@ private:
    * If the Windows accent color from the Windows settings is set
    * to apply to the title bar, this computes the color that should
    * be used for text that is to be written over a background that has
    * the accent color.  Otherwise, (if the accent color should not
    * apply to the title bar) this returns an error code.
    */
   nsresult GetAccentColorText(nscolor& aColor);
 
+  nscolor GetColorForSysColorIndex(int index);
+
   // Content process cached values that get shipped over from the browser
   // process.
   int32_t mUseAccessibilityTheme;
   int32_t mUseDefaultTheme; // is the current theme a known default?
   int32_t mNativeThemeId; // see LookAndFeel enum 'WindowsTheme'
   int32_t mCaretBlinkTime;
 
+  // Cached colors and flags indicating success in their retrieval.
+  nscolor mColorMenuHoverText;
+  bool mHasColorMenuHoverText;
+  nscolor mColorAccent;
+  bool mHasColorAccent;
+  nscolor mColorAccentText;
+  bool mHasColorAccentText;
+  nscolor mColorMediaText;
+  bool mHasColorMediaText;
+  nscolor mColorCommunicationsText;
+  bool mHasColorCommunicationsText;
+
+  nscolor mSysColorTable[SYS_COLOR_COUNT];
+
+  bool mInitialized;
+
+  void EnsureInit();
+
   struct CachedSystemFont {
     CachedSystemFont()
       : mCacheValid(false)
     {}
 
     bool mCacheValid;
     bool mHaveFont;
     nsString mFontName;