Bug 1353493 - Cache the return value for nsIWidget::DefaultScaleOverride(). r=kanru
authorMasatoshi Kimura <VYV03354@nifty.ne.jp>
Thu, 06 Apr 2017 23:30:09 +0900
changeset 399774 f0792bb960b6e16be5d854366ba81ec2a604052c
parent 399773 b21110aa79591ea6556ca0c9781675ec039e6599
child 399775 05a48259d0732cd1880c6cb82452b740135a6688
push id7391
push usermtabara@mozilla.com
push dateMon, 12 Jun 2017 13:08:53 +0000
treeherdermozilla-beta@2191d7f87e2e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskanru
bugs1353493
milestone55.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1353493 - Cache the return value for nsIWidget::DefaultScaleOverride(). r=kanru MozReview-Commit-ID: ExP179bxbHe
layout/base/nsPresContext.cpp
widget/nsBaseWidget.cpp
widget/nsIWidget.h
--- a/layout/base/nsPresContext.cpp
+++ b/layout/base/nsPresContext.cpp
@@ -690,16 +690,22 @@ nsPresContext::AppUnitsPerDevPixelChange
 }
 
 void
 nsPresContext::PreferenceChanged(const char* aPrefName)
 {
   nsDependentCString prefName(aPrefName);
   if (prefName.EqualsLiteral("layout.css.dpi") ||
       prefName.EqualsLiteral("layout.css.devPixelsPerPx")) {
+
+    // We can't use a separate observer, callback, or var cache
+    // Because they don't guarantee the order of function calls.
+    // We have to update the scale override value first.
+    nsIWidget::ScaleOverrideChanged();
+
     int32_t oldAppUnitsPerDevPixel = AppUnitsPerDevPixel();
     if (mDeviceContext->CheckDPIChange() && mShell) {
       nsCOMPtr<nsIPresShell> shell = mShell;
       // Re-fetch the view manager's window dimensions in case there's a deferred
       // resize which hasn't affected our mVisibleArea yet
       nscoord oldWidthAppUnits, oldHeightAppUnits;
       RefPtr<nsViewManager> vm = shell->GetViewManager();
       if (!vm) {
--- a/widget/nsBaseWidget.cpp
+++ b/widget/nsBaseWidget.cpp
@@ -568,30 +568,86 @@ CSSToLayoutDeviceScale nsIWidget::GetDef
 
   if (devPixelsPerCSSPixel <= 0.0) {
     devPixelsPerCSSPixel = GetDefaultScaleInternal();
   }
 
   return CSSToLayoutDeviceScale(devPixelsPerCSSPixel);
 }
 
+// The number of device pixels per CSS pixel. A value <= 0 means choose
+// automatically based on the DPI. A positive value is used as-is. This effectively
+// controls the size of a CSS "px".
+static double sDevPixelsPerCSSPixel = -1.0;
+
+/* static */
+void nsIWidget::ScaleOverrideChanged()
+{
+  nsAdoptingCString prefString = Preferences::GetCString("layout.css.devPixelsPerPx");
+  if (!prefString.IsEmpty()) {
+    sDevPixelsPerCSSPixel = PR_strtod(prefString, nullptr);
+  } else {
+    sDevPixelsPerCSSPixel = -1.0;
+  }
+}
+
+class ProfileChangeObserver final : public nsIObserver
+{
+public:
+  NS_DECL_ISUPPORTS
+  NS_DECL_NSIOBSERVER
+  static void Init();
+private:
+  ProfileChangeObserver();
+  ~ProfileChangeObserver();
+};
+
+ProfileChangeObserver::ProfileChangeObserver()
+{
+}
+
+ProfileChangeObserver::~ProfileChangeObserver()
+{
+}
+
+/* static */
+void ProfileChangeObserver::Init()
+{
+  nsCOMPtr<nsIObserver> profileChangeObserver = new ProfileChangeObserver();
+  nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
+  obs->AddObserver(profileChangeObserver, "profile-do-change", false);
+  // We don't have to observe XPCOM shutdown to remove the observer
+  // explicitly. Also, we don't have to hold a strong reference to the
+  // observer on our own. The observer service will do them for us.
+}
+
+NS_IMPL_ISUPPORTS(ProfileChangeObserver,
+                  nsIObserver)
+
+NS_IMETHODIMP
+ProfileChangeObserver::Observe(nsISupports* aSubject, const char* aTopic,
+                               const char16_t* aData)
+{
+  if (!strcmp(aTopic, "profile-do-change")) {
+    nsIWidget::ScaleOverrideChanged();
+  }
+  return NS_OK;
+}
+
 /* static */
 double nsIWidget::DefaultScaleOverride()
 {
-  // The number of device pixels per CSS pixel. A value <= 0 means choose
-  // automatically based on the DPI. A positive value is used as-is. This effectively
-  // controls the size of a CSS "px".
-  double devPixelsPerCSSPixel = -1.0;
-
-  nsAdoptingCString prefString = Preferences::GetCString("layout.css.devPixelsPerPx");
-  if (!prefString.IsEmpty()) {
-    devPixelsPerCSSPixel = PR_strtod(prefString, nullptr);
+  static bool valueCached = false;
+  if (!valueCached) {
+    ScaleOverrideChanged();
+    ProfileChangeObserver::Init();
+    valueCached = true;
   }
 
-  return devPixelsPerCSSPixel;
+  return sDevPixelsPerCSSPixel;
 }
 
 //-------------------------------------------------------------------------
 //
 // Add a child to the list of children
 //
 //-------------------------------------------------------------------------
 void nsBaseWidget::AddChild(nsIWidget* aChild)
--- a/widget/nsIWidget.h
+++ b/widget/nsIWidget.h
@@ -567,16 +567,22 @@ class nsIWidget : public nsISupports
      * default number of device pixels per CSS pixel to use. This should
      * depend on OS/platform settings such as the Mac's "UI scale factor"
      * or Windows' "font DPI". This will take into account Gecko preferences
      * overriding the system setting.
      */
     mozilla::CSSToLayoutDeviceScale GetDefaultScale();
 
     /**
+     * Cache the scale override value. Call whenever the scale override
+     * value is changed.
+     */
+    static void ScaleOverrideChanged();
+
+    /**
      * Return the Gecko override of the system default scale, if any;
      * returns <= 0.0 if the system scale should be used as-is.
      * nsIWidget::GetDefaultScale() [above] takes this into account.
      * It is exposed here so that code that wants to check for a
      * default-scale override without having a widget on hand can
      * easily access the same value.
      * Note that any scale override is a browser-wide value, whereas
      * the default GetDefaultScale value (when no override is present)