--- 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;
}