Bug 1350643 - Part 3: Add GetDPI to nsIScreen & ScreenDetails. r?kanru draft
authorSamael Wang <freesamael@gmail.com>
Tue, 06 Jun 2017 18:09:34 +0800
changeset 611031 ef9b6bc092765b1b5353673698ed6e9adfbd6052
parent 611030 c6cc7dc6199206f5649eff5493c17ea75b6ec34b
child 611032 afeaa2fc3729fbcb80cfb2e19ed934a090d0aac1
push id69104
push userbmo:sawang@mozilla.com
push dateWed, 19 Jul 2017 06:01:44 +0000
reviewerskanru
bugs1350643
milestone56.0a1
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;
 }