Bug 1350643 - Part 3: Add GetDPI to nsIScreen & ScreenDetails. r=kanru
authorSamael Wang <freesamael@gmail.com>
Tue, 06 Jun 2017 18:09:34 +0800
changeset 369867 abfd88baf39108831d7a9337f841ecb623b5594c
parent 369866 dce3ec16f2b530c75009fd1f6c4317d05df7e396
child 369868 ea47118382b93663fa6e7cd96584c19de3d3f2e8
push id32208
push userarchaeopteryx@coole-files.de
push dateFri, 21 Jul 2017 09:12:51 +0000
treeherdermozilla-central@0faada5c2f30 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskanru
bugs1350643
milestone56.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 1350643 - Part 3: Add GetDPI to nsIScreen & ScreenDetails. r=kanru MozReview-Commit-ID: HEFyuYV26Wy
dom/ipc/DOMTypes.ipdlh
widget/Screen.cpp
widget/Screen.h
widget/ScreenManager.cpp
widget/cocoa/ScreenHelperCocoa.mm
widget/gtk/ScreenHelperGTK.cpp
widget/headless/HeadlessScreenHelper.cpp
widget/nsBaseScreen.cpp
widget/nsBaseScreen.h
widget/nsIScreen.idl
widget/windows/ScreenHelperWin.cpp
--- a/dom/ipc/DOMTypes.ipdlh
+++ b/dom/ipc/DOMTypes.ipdlh
@@ -82,16 +82,17 @@ struct ScreenDetails {
   LayoutDeviceIntRect rect;
   DesktopIntRect rectDisplayPix;
   LayoutDeviceIntRect availRect;
   DesktopIntRect availRectDisplayPix;
   int32_t pixelDepth;
   int32_t colorDepth;
   DesktopToLayoutDeviceScale contentsScaleFactor;
   CSSToLayoutDeviceScale defaultCSSScaleFactor;
+  float dpi;
 };
 
 struct DimensionInfo
 {
   CSSRect rect;
   CSSSize size;
   ScreenOrientationInternal orientation;
   LayoutDeviceIntPoint clientOffset;
--- a/widget/Screen.cpp
+++ b/widget/Screen.cpp
@@ -11,58 +11,62 @@
 namespace mozilla {
 namespace widget {
 
 NS_IMPL_ISUPPORTS(Screen, nsIScreen)
 
 Screen::Screen(LayoutDeviceIntRect aRect, LayoutDeviceIntRect aAvailRect,
                uint32_t aPixelDepth, uint32_t aColorDepth,
                DesktopToLayoutDeviceScale aContentsScale,
-               CSSToLayoutDeviceScale aDefaultCssScale)
+               CSSToLayoutDeviceScale aDefaultCssScale,
+               float aDPI)
   : mRect(aRect)
   , mAvailRect(aAvailRect)
   , mRectDisplayPix(RoundedToInt(aRect / aContentsScale))
   , mAvailRectDisplayPix(RoundedToInt(aAvailRect / aContentsScale))
   , mPixelDepth(aPixelDepth)
   , mColorDepth(aColorDepth)
   , mContentsScale(aContentsScale)
   , mDefaultCssScale(aDefaultCssScale)
+  , mDPI(aDPI)
 {
 }
 
 Screen::Screen(const mozilla::dom::ScreenDetails& aScreen)
   : mRect(aScreen.rect())
   , mAvailRect(aScreen.availRect())
   , mRectDisplayPix(aScreen.rectDisplayPix())
   , mAvailRectDisplayPix(aScreen.availRectDisplayPix())
   , mPixelDepth(aScreen.pixelDepth())
   , mColorDepth(aScreen.colorDepth())
   , mContentsScale(aScreen.contentsScaleFactor())
   , mDefaultCssScale(aScreen.defaultCSSScaleFactor())
+  , mDPI(aScreen.dpi())
 {
 }
 
 Screen::Screen(const Screen& aOther)
   : mRect(aOther.mRect)
   , mAvailRect(aOther.mAvailRect)
   , mRectDisplayPix(aOther.mRectDisplayPix)
   , mAvailRectDisplayPix(aOther.mAvailRectDisplayPix)
   , mPixelDepth(aOther.mPixelDepth)
   , mColorDepth(aOther.mColorDepth)
   , mContentsScale(aOther.mContentsScale)
   , mDefaultCssScale(aOther.mDefaultCssScale)
+  , mDPI(aOther.mDPI)
 {
 }
 
 mozilla::dom::ScreenDetails
 Screen::ToScreenDetails()
 {
   return mozilla::dom::ScreenDetails(
     mRect, mRectDisplayPix, mAvailRect, mAvailRectDisplayPix,
-    mPixelDepth, mColorDepth, mContentsScale, mDefaultCssScale);
+    mPixelDepth, mColorDepth, mContentsScale, mDefaultCssScale, mDPI);
 }
 
 NS_IMETHODIMP
 Screen::GetRect(int32_t* aOutLeft,
                 int32_t* aOutTop,
                 int32_t* aOutWidth,
                 int32_t* aOutHeight)
 {
@@ -140,10 +144,17 @@ Screen::GetDefaultCSSScaleFactor(double 
   if (scale > 0.0) {
     *aOutScale = scale;
   } else {
     *aOutScale = mDefaultCssScale.scale;
   }
   return NS_OK;
 }
 
+NS_IMETHODIMP
+Screen::GetDpi(float* aDPI)
+{
+  *aDPI = mDPI;
+  return NS_OK;
+}
+
 } // namespace widget
 } // namespace mozilla
--- a/widget/Screen.h
+++ b/widget/Screen.h
@@ -24,32 +24,34 @@ class Screen final : public nsIScreen
 {
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSISCREEN
 
   Screen(LayoutDeviceIntRect aRect, LayoutDeviceIntRect aAvailRect,
          uint32_t aPixelDepth, uint32_t aColorDepth,
          DesktopToLayoutDeviceScale aContentsScale,
-         CSSToLayoutDeviceScale aDefaultCssScale);
+         CSSToLayoutDeviceScale aDefaultCssScale,
+         float dpi);
   explicit Screen(const mozilla::dom::ScreenDetails& aScreenDetails);
   Screen(const Screen& aOther);
 
   mozilla::dom::ScreenDetails ToScreenDetails();
 
 private:
   virtual ~Screen() {}
 
   LayoutDeviceIntRect mRect;
   LayoutDeviceIntRect mAvailRect;
   DesktopIntRect mRectDisplayPix;
   DesktopIntRect mAvailRectDisplayPix;
   uint32_t mPixelDepth;
   uint32_t mColorDepth;
   DesktopToLayoutDeviceScale mContentsScale;
   CSSToLayoutDeviceScale mDefaultCssScale;
+  float mDPI;
 };
 
 } // namespace widget
 } // namespace mozilla
 
 #endif
 
--- a/widget/ScreenManager.cpp
+++ b/widget/ScreenManager.cpp
@@ -124,17 +124,18 @@ ScreenManager::ScreenForRect(int32_t aX,
                              nsIScreen** aOutScreen)
 {
   if (mScreenList.IsEmpty()) {
     MOZ_LOG(sScreenLog, LogLevel::Warning,
             ("No screen available. This can happen in xpcshell."));
     RefPtr<Screen> ret = new Screen(LayoutDeviceIntRect(), LayoutDeviceIntRect(),
                                     0, 0,
                                     DesktopToLayoutDeviceScale(),
-                                    CSSToLayoutDeviceScale());
+                                    CSSToLayoutDeviceScale(),
+                                    96 /* dpi */);
     ret.forget(aOutScreen);
     return NS_OK;
   }
 
   // Optimize for the common case. If the number of screens is only
   // one then just return the primary screen.
   if (mScreenList.Length() == 1) {
     return GetPrimaryScreen(aOutScreen);
@@ -213,17 +214,18 @@ NS_IMETHODIMP
 ScreenManager::GetPrimaryScreen(nsIScreen** aPrimaryScreen)
 {
   if (mScreenList.IsEmpty()) {
     MOZ_LOG(sScreenLog, LogLevel::Warning,
             ("No screen available. This can happen in xpcshell."));
     RefPtr<Screen> ret = new Screen(LayoutDeviceIntRect(), LayoutDeviceIntRect(),
                                     0, 0,
                                     DesktopToLayoutDeviceScale(),
-                                    CSSToLayoutDeviceScale());
+                                    CSSToLayoutDeviceScale(),
+                                    96 /* dpi */);
     ret.forget(aPrimaryScreen);
     return NS_OK;
   }
 
   RefPtr<Screen> ret = mScreenList[0];
   ret.forget(aPrimaryScreen);
   return NS_OK;
 }
--- a/widget/cocoa/ScreenHelperCocoa.mm
+++ b/widget/cocoa/ScreenHelperCocoa.mm
@@ -89,24 +89,26 @@ MakeScreen(NSScreen* aScreen)
   NSRect frame = [aScreen frame];
   LayoutDeviceIntRect rect =
     nsCocoaUtils::CocoaRectToGeckoRectDevPix(frame, contentsScaleFactor.scale);
   frame = [aScreen visibleFrame];
   LayoutDeviceIntRect availRect =
     nsCocoaUtils::CocoaRectToGeckoRectDevPix(frame, contentsScaleFactor.scale);
   NSWindowDepth depth = [aScreen depth];
   uint32_t pixelDepth = NSBitsPerPixelFromDepth(depth);
-
-  MOZ_LOG(sScreenLog, LogLevel::Debug, ("New screen [%d %d %d %d %d %f]",
+  float dpi = 96.0f;
+  MOZ_LOG(sScreenLog, LogLevel::Debug, ("New screen [%d %d %d %d %d %f %f]",
                                         rect.x, rect.y, rect.width, rect.height,
-                                        pixelDepth, contentsScaleFactor.scale));
+                                        pixelDepth, contentsScaleFactor.scale,
+                                        dpi));
 
   RefPtr<Screen> screen = new Screen(rect, availRect,
                                      pixelDepth, pixelDepth,
-                                     contentsScaleFactor, defaultCssScaleFactor);
+                                     contentsScaleFactor, defaultCssScaleFactor,
+                                     dpi);
   return screen.forget();
 
   NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(nullptr);
 }
 
 void
 ScreenHelperCocoa::RefreshScreens()
 {
--- a/widget/gtk/ScreenHelperGTK.cpp
+++ b/widget/gtk/ScreenHelperGTK.cpp
@@ -146,24 +146,26 @@ MakeScreen(GdkScreen* aScreen, gint aMon
                                 workarea.y * gdkScaleFactor,
                                 workarea.width * gdkScaleFactor,
                                 workarea.height * gdkScaleFactor);
   uint32_t pixelDepth = GetGTKPixelDepth();
   DesktopToLayoutDeviceScale contentsScale(1.0);
   CSSToLayoutDeviceScale defaultCssScale(
     gdkScaleFactor * gfxPlatformGtk::GetFontScaleFactor());
 
+  float dpi = 96.0f;
   MOZ_LOG(sScreenLog, LogLevel::Debug,
-           ("New screen [%d %d %d %d (%d %d %d %d) %d %f]",
+           ("New screen [%d %d %d %d (%d %d %d %d) %d %f %f]",
             rect.x, rect.y, rect.width, rect.height,
             availRect.x, availRect.y, availRect.width, availRect.height,
-            pixelDepth, defaultCssScale.scale));
+            pixelDepth, defaultCssScale.scale, dpi));
   RefPtr<Screen> screen = new Screen(rect, availRect,
                                      pixelDepth, pixelDepth,
-                                     contentsScale, defaultCssScale);
+                                     contentsScale, defaultCssScale,
+                                     dpi);
   return screen.forget();
 }
 
 void
 ScreenHelperGTK::RefreshScreens()
 {
   MOZ_LOG(sScreenLog, LogLevel::Debug, ("Refreshing screens"));
   AutoTArray<RefPtr<Screen>, 4> screenList;
--- a/widget/headless/HeadlessScreenHelper.cpp
+++ b/widget/headless/HeadlessScreenHelper.cpp
@@ -31,16 +31,17 @@ HeadlessScreenHelper::GetScreenRect()
 
 HeadlessScreenHelper::HeadlessScreenHelper()
 {
   AutoTArray<RefPtr<Screen>, 1> screenList;
   LayoutDeviceIntRect rect = GetScreenRect();
   RefPtr<Screen> ret = new Screen(rect, rect,
                                   24, 24,
                                   DesktopToLayoutDeviceScale(),
-                                  CSSToLayoutDeviceScale());
+                                  CSSToLayoutDeviceScale(),
+                                  96.0f);
   screenList.AppendElement(ret.forget());
   ScreenManager& screenManager = ScreenManager::GetSingleton();
   screenManager.Refresh(Move(screenList));
 }
 
 } // namespace widget
 } // namespace mozilla
--- a/widget/nsBaseScreen.cpp
+++ b/widget/nsBaseScreen.cpp
@@ -39,8 +39,15 @@ nsBaseScreen::GetContentsScaleFactor(dou
 }
 
 NS_IMETHODIMP
 nsBaseScreen::GetDefaultCSSScaleFactor(double* aScaleFactor)
 {
   *aScaleFactor = 1.0;
   return NS_OK;
 }
+
+NS_IMETHODIMP
+nsBaseScreen::GetDpi(float* aDPI)
+{
+  *aDPI = 96;
+  return NS_OK;
+}
--- a/widget/nsBaseScreen.h
+++ b/widget/nsBaseScreen.h
@@ -27,13 +27,15 @@ public:
                                int32_t *outWidth, int32_t *outHeight) override;
   NS_IMETHOD GetAvailRectDisplayPix(int32_t *outLeft,  int32_t *outTop,
                                     int32_t *outWidth, int32_t *outHeight) override;
 
   NS_IMETHOD GetContentsScaleFactor(double* aContentsScaleFactor) override;
 
   NS_IMETHOD GetDefaultCSSScaleFactor(double* aScaleFactor) override;
 
+  NS_IMETHOD GetDpi(float* aDPI) override;
+
 protected:
   virtual ~nsBaseScreen();
 };
 
 #endif // nsBaseScreen_h
--- a/widget/nsIScreen.idl
+++ b/widget/nsIScreen.idl
@@ -41,20 +41,26 @@ interface nsIScreen : nsISupports
    * desktop px and/or per CSS px).
    *
    * This seems poorly named (something like devicePixelsPerDesktopPixel
    * would be more accurate/explicit), but given that it is exposed to
    * front-end code and may also be used by add-ons, it's probably not
    * worth the disruption of changing it.
    *
    * Returns 1.0 if HiDPI mode is disabled or unsupported, or if the
-   * host OS uses device pixels as its desktop pixel units (as in Win8.1
-   * per-monitor dpi support).
+   * host OS uses device pixels as its desktop pixel units (e.g. Windows 7 or
+   * GTK/X11). Per-monitor DPI is available in Windows 8.1+, GTK/Wayland or
+   * macOS.
    */
   readonly attribute double contentsScaleFactor;
 
   /**
    * The default number of device pixels per unscaled CSS pixel for this
    * screen. This is probably what contentsScaleFactor originally meant
    * to be, prior to confusion between CSS pixels and desktop pixel units.
    */
   readonly attribute double defaultCSSScaleFactor;
+
+  /**
+   * The DPI of the screen.
+   */
+  readonly attribute float dpi;
 };
--- a/widget/windows/ScreenHelperWin.cpp
+++ b/widget/windows/ScreenHelperWin.cpp
@@ -43,22 +43,25 @@ CollectMonitors(HMONITOR aMon, HDC hDCSc
                                 info.rcWork.bottom - info.rcWork.top);
   uint32_t pixelDepth = ::GetDeviceCaps(hDCScreen, BITSPIXEL);
   if (pixelDepth == 32) {
     // If a device uses 32 bits per pixel, it's still only using 8 bits
     // per color component, which is what our callers want to know.
     // (Some devices report 32 and some devices report 24.)
     pixelDepth = 24;
   }
-  MOZ_LOG(sScreenLog, LogLevel::Debug, ("New screen [%d %d %d %d %d %f]",
+  float dpi = 96.0f;
+  MOZ_LOG(sScreenLog, LogLevel::Debug, ("New screen [%d %d %d %d %d %f %f]",
                                         rect.x, rect.y, rect.width, rect.height,
-                                        pixelDepth, defaultCssScaleFactor.scale));
+                                        pixelDepth, defaultCssScaleFactor.scale,
+                                        dpi));
   auto screen = new Screen(rect, availRect,
                            pixelDepth, pixelDepth,
-                           contentsScaleFactor, defaultCssScaleFactor);
+                           contentsScaleFactor, defaultCssScaleFactor,
+                           dpi);
   if (info.dwFlags & MONITORINFOF_PRIMARY) {
     // The primary monitor must be the first element of the screen list.
     screens->InsertElementAt(0, Move(screen));
   } else {
     screens->AppendElement(Move(screen));
   }
   return TRUE;
 }