Bug 1350643 - Part 6.1: Extract getting DPI logic from LogToPhysFactor & SystemScaleFactor to provide new functions MonitorDPI & SystemDPI. r?jimm draft
authorSamael Wang <freesamael@gmail.com>
Fri, 16 Jun 2017 01:11:41 +0800
changeset 611036 bfcee8a5a1c5bed66484687d488b97d1617e0dc3
parent 611035 65644cf33fef639e42375e18f3ccb0e6574304c8
child 611037 35d464ca97ea04cb05676eee5636e19115816526
push id69104
push userbmo:sawang@mozilla.com
push dateWed, 19 Jul 2017 06:01:44 +0000
reviewersjimm
bugs1350643
milestone56.0a1
Bug 1350643 - Part 6.1: Extract getting DPI logic from LogToPhysFactor & SystemScaleFactor to provide new functions MonitorDPI & SystemDPI. r?jimm MozReview-Commit-ID: E9mXvFMM3pA
widget/windows/WinUtils.cpp
widget/windows/WinUtils.h
--- a/widget/windows/WinUtils.cpp
+++ b/widget/windows/WinUtils.cpp
@@ -544,37 +544,41 @@ WinUtils::Log(const char *fmt, ...)
 
   NS_ASSERTION(gWindowsLog, "Called WinUtils Log() but Widget "
                                "log module doesn't exist!");
   MOZ_LOG(gWindowsLog, LogLevel::Error, (buffer));
   delete[] buffer;
 }
 
 // static
-double
-WinUtils::SystemScaleFactor()
+float
+WinUtils::SystemDPI()
 {
   // The result of GetDeviceCaps won't change dynamically, as it predates
   // per-monitor DPI and support for on-the-fly resolution changes.
   // Therefore, we only need to look it up once.
-  static double systemScale = 0;
-  if (systemScale == 0) {
+  static float dpi = 0;
+  if (dpi <= 0) {
     HDC screenDC = GetDC(nullptr);
-    systemScale = GetDeviceCaps(screenDC, LOGPIXELSY) / 96.0;
+    dpi = GetDeviceCaps(screenDC, LOGPIXELSY);
     ReleaseDC(nullptr, screenDC);
+  }
 
-    if (systemScale == 0) {
-      // Bug 1012487 - This can occur when the Screen DC is used off the
-      // main thread on windows. For now just assume a 100% DPI for this
-      // drawing call.
-      // XXX - fixme!
-      return 1.0;
-    }
-  }
-  return systemScale;
+  // Bug 1012487 - dpi can be 0 when the Screen DC is used off the
+  // main thread on windows. For now just assume a 100% DPI for this
+  // drawing call.
+  // XXX - fixme!
+  return dpi > 0 ? dpi : 96;
+}
+
+// static
+double
+WinUtils::SystemScaleFactor()
+{
+  return SystemDPI() / 96.0;
 }
 
 #if WINVER < 0x603
 typedef enum {
   MDT_EFFECTIVE_DPI = 0,
   MDT_ANGULAR_DPI = 1,
   MDT_RAW_DPI = 2,
   MDT_DEFAULT = MDT_EFFECTIVE_DPI
@@ -617,27 +621,35 @@ SlowIsPerMonitorDPIAware()
 /* static */ bool
 WinUtils::IsPerMonitorDPIAware()
 {
   static bool perMonitorDPIAware = SlowIsPerMonitorDPIAware();
   return perMonitorDPIAware;
 }
 
 /* static */
-double
-WinUtils::LogToPhysFactor(HMONITOR aMonitor)
+float
+WinUtils::MonitorDPI(HMONITOR aMonitor)
 {
   if (IsPerMonitorDPIAware()) {
     UINT dpiX, dpiY = 96;
     sGetDpiForMonitor(aMonitor ? aMonitor : GetPrimaryMonitor(),
                       MDT_EFFECTIVE_DPI, &dpiX, &dpiY);
-    return dpiY / 96.0;
+    return dpiY;
   }
 
-  return SystemScaleFactor();
+  // We're not per-monitor aware, use system DPI instead.
+  return SystemDPI();
+}
+
+/* static */
+double
+WinUtils::LogToPhysFactor(HMONITOR aMonitor)
+{
+  return MonitorDPI(aMonitor) / 96.0;
 }
 
 /* static */
 int32_t
 WinUtils::LogToPhys(HMONITOR aMonitor, double aValue)
 {
   return int32_t(NS_round(aValue * LogToPhysFactor(aMonitor)));
 }
--- a/widget/windows/WinUtils.h
+++ b/widget/windows/WinUtils.h
@@ -204,16 +204,22 @@ public:
    * a session even if the displays are reconfigured. This scale factor
    * is used by Windows theme metrics etc, which do not fully support
    * dynamic resolution changes but are only updated on logout.
    */
   static double SystemScaleFactor();
 
   static bool IsPerMonitorDPIAware();
   /**
+   * Get the DPI of the given monitor if it's per-monitor DPI aware, otherwise
+   * return the system DPI.
+   */
+  static float MonitorDPI(HMONITOR aMonitor);
+  static float SystemDPI();
+  /**
    * Functions to convert between logical pixels as used by most Windows APIs
    * and physical (device) pixels.
    */
   static double LogToPhysFactor(HMONITOR aMonitor);
   static double LogToPhysFactor(HWND aWnd) {
     // if there's an ancestor window, we want to share its DPI setting
     HWND ancestor = ::GetAncestor(aWnd, GA_ROOTOWNER);
     return LogToPhysFactor(::MonitorFromWindow(ancestor ? ancestor : aWnd,