forked from mirrors/gecko-dev
Bug 1798213 - For widget-less pages keep defaulting to primary screen scale factor. r=tnikkel,layout-reviewers,extension-reviewers,robwu
This restores the previous behavior in a somewhat more principled way. The extensions code is still broken in multi-monitor cases, but that's a more complicated fix. Differential Revision: https://phabricator.services.mozilla.com/D161997
This commit is contained in:
parent
06ebad6fd8
commit
a8a5c8fe6a
8 changed files with 114 additions and 31 deletions
|
|
@ -473,10 +473,10 @@ ParentShowInfo BrowserParent::GetShowInfo() {
|
||||||
TryCacheDPIAndScale();
|
TryCacheDPIAndScale();
|
||||||
if (mFrameElement) {
|
if (mFrameElement) {
|
||||||
nsAutoString name;
|
nsAutoString name;
|
||||||
mFrameElement->GetAttr(kNameSpaceID_None, nsGkAtoms::name, name);
|
mFrameElement->GetAttr(nsGkAtoms::name, name);
|
||||||
bool isTransparent =
|
bool isTransparent =
|
||||||
nsContentUtils::IsChromeDoc(mFrameElement->OwnerDoc()) &&
|
nsContentUtils::IsChromeDoc(mFrameElement->OwnerDoc()) &&
|
||||||
mFrameElement->HasAttr(kNameSpaceID_None, nsGkAtoms::transparent);
|
mFrameElement->HasAttr(nsGkAtoms::transparent);
|
||||||
return ParentShowInfo(name, false, isTransparent, mDPI, mRounding,
|
return ParentShowInfo(name, false, isTransparent, mDPI, mRounding,
|
||||||
mDefaultScale.scale);
|
mDefaultScale.scale);
|
||||||
}
|
}
|
||||||
|
|
@ -546,6 +546,10 @@ void BrowserParent::SetOwnerElement(Element* aElement) {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
AddWindowListeners();
|
AddWindowListeners();
|
||||||
|
|
||||||
|
// The DPI depends on our frame element's widget, so invalidate now in case
|
||||||
|
// we've tried to cache it already.
|
||||||
|
mDPI = -1;
|
||||||
TryCacheDPIAndScale();
|
TryCacheDPIAndScale();
|
||||||
|
|
||||||
if (mRemoteLayerTreeOwner.IsInitialized()) {
|
if (mRemoteLayerTreeOwner.IsInitialized()) {
|
||||||
|
|
@ -3427,17 +3431,17 @@ void BrowserParent::TryCacheDPIAndScale() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const auto oldDefaultScale = mDefaultScale;
|
||||||
nsCOMPtr<nsIWidget> widget = GetWidget();
|
nsCOMPtr<nsIWidget> widget = GetWidget();
|
||||||
|
mDPI = widget ? widget->GetDPI() : nsIWidget::GetFallbackDPI();
|
||||||
|
mRounding = widget ? widget->RoundsWidgetCoordinatesTo() : 1;
|
||||||
|
mDefaultScale =
|
||||||
|
widget ? widget->GetDefaultScale() : nsIWidget::GetFallbackDefaultScale();
|
||||||
|
|
||||||
if (widget) {
|
if (mDefaultScale != oldDefaultScale) {
|
||||||
mDPI = widget->GetDPI();
|
// The change of the default scale factor will affect the child dimensions
|
||||||
mRounding = widget->RoundsWidgetCoordinatesTo();
|
// so we need to invalidate it.
|
||||||
if (mDefaultScale != widget->GetDefaultScale()) {
|
mUpdatedDimensions = false;
|
||||||
// The change of the default scale factor will affect the child dimensions
|
|
||||||
// so we need to invalidate it.
|
|
||||||
mUpdatedDimensions = false;
|
|
||||||
}
|
|
||||||
mDefaultScale = widget->GetDefaultScale();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3582,18 +3586,19 @@ void BrowserParent::PreserveLayers(bool aPreserveLayers) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void BrowserParent::NotifyResolutionChanged() {
|
void BrowserParent::NotifyResolutionChanged() {
|
||||||
if (!mIsDestroyed) {
|
if (mIsDestroyed) {
|
||||||
// TryCacheDPIAndScale()'s cache is keyed off of
|
return;
|
||||||
// mDPI being greater than 0, so this invalidates it.
|
|
||||||
mDPI = -1;
|
|
||||||
TryCacheDPIAndScale();
|
|
||||||
// If mDPI was set to -1 to invalidate it and then TryCacheDPIAndScale
|
|
||||||
// fails to cache the values, then mDefaultScale.scale might be invalid.
|
|
||||||
// We don't want to send that value to content. Just send -1 for it too in
|
|
||||||
// that case.
|
|
||||||
Unused << SendUIResolutionChanged(mDPI, mRounding,
|
|
||||||
mDPI < 0 ? -1.0 : mDefaultScale.scale);
|
|
||||||
}
|
}
|
||||||
|
// TryCacheDPIAndScale()'s cache is keyed off of
|
||||||
|
// mDPI being greater than 0, so this invalidates it.
|
||||||
|
mDPI = -1;
|
||||||
|
TryCacheDPIAndScale();
|
||||||
|
// If mDPI was set to -1 to invalidate it and then TryCacheDPIAndScale
|
||||||
|
// fails to cache the values, then mDefaultScale.scale might be invalid.
|
||||||
|
// We don't want to send that value to content. Just send -1 for it too in
|
||||||
|
// that case.
|
||||||
|
Unused << SendUIResolutionChanged(mDPI, mRounding,
|
||||||
|
mDPI < 0 ? -1.0 : mDefaultScale.scale);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BrowserParent::CanCancelContentJS(
|
bool BrowserParent::CanCancelContentJS(
|
||||||
|
|
|
||||||
|
|
@ -87,6 +87,7 @@ skip-if = toolkit == 'android' || tsan # near-permafail after landing bug 127005
|
||||||
[test_ext_background_canvas.html]
|
[test_ext_background_canvas.html]
|
||||||
[test_ext_background_page.html]
|
[test_ext_background_page.html]
|
||||||
skip-if = (toolkit == 'android') # android doesn't have devtools
|
skip-if = (toolkit == 'android') # android doesn't have devtools
|
||||||
|
[test_ext_background_page_dpi.html]
|
||||||
[test_ext_browserAction_openPopup.html]
|
[test_ext_browserAction_openPopup.html]
|
||||||
[test_ext_browserAction_openPopup_incognito_window.html]
|
[test_ext_browserAction_openPopup_incognito_window.html]
|
||||||
skip-if = os == "android" # cannot open private windows - bug 1372178
|
skip-if = os == "android" # cannot open private windows - bug 1372178
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,46 @@
|
||||||
|
<!DOCTYPE HTML>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>DPI of background page</title>
|
||||||
|
<script src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||||
|
<script src="/tests/SimpleTest/ExtensionTestUtils.js"></script>
|
||||||
|
<script src="head.js"></script>
|
||||||
|
<link rel="stylesheet" href="/tests/SimpleTest/test.css">
|
||||||
|
<script>
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
async function testDPIMatches(description) {
|
||||||
|
let extension = ExtensionTestUtils.loadExtension({
|
||||||
|
background: function() {
|
||||||
|
browser.test.sendMessage("dpi", window.devicePixelRatio);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
await extension.startup();
|
||||||
|
let dpi = await extension.awaitMessage("dpi");
|
||||||
|
await extension.unload();
|
||||||
|
|
||||||
|
// This assumes that the window is loaded in a device DPI.
|
||||||
|
is(
|
||||||
|
dpi,
|
||||||
|
window.devicePixelRatio,
|
||||||
|
`DPI in a background page should match DPI in primary chrome page ${description}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
add_task(async function test_dpi_simple() {
|
||||||
|
await testDPIMatches("by default");
|
||||||
|
});
|
||||||
|
|
||||||
|
add_task(async function test_dpi_devPixelsPerPx() {
|
||||||
|
await SpecialPowers.pushPrefEnv({
|
||||||
|
set: [["layout.css.devPixelsPerPx", 1.5]],
|
||||||
|
});
|
||||||
|
await testDPIMatches("with devPixelsPerPx");
|
||||||
|
await SpecialPowers.popPrefEnv();
|
||||||
|
});
|
||||||
|
|
||||||
|
add_task(async function test_dpi_os_zoom() {
|
||||||
|
await SpecialPowers.pushPrefEnv({ set: [["ui.textScaleFactor", 200]] });
|
||||||
|
await testDPIMatches("with OS zoom");
|
||||||
|
await SpecialPowers.popPrefEnv();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
@ -382,9 +382,9 @@ class PuppetWidget : public nsBaseWidget,
|
||||||
ContentCacheInChild mContentCache;
|
ContentCacheInChild mContentCache;
|
||||||
|
|
||||||
// The DPI of the parent widget containing this widget.
|
// The DPI of the parent widget containing this widget.
|
||||||
float mDPI = 96;
|
float mDPI = GetFallbackDPI();
|
||||||
int32_t mRounding = 1;
|
int32_t mRounding = 1;
|
||||||
double mDefaultScale = 1.0f;
|
double mDefaultScale = GetFallbackDefaultScale().scale;
|
||||||
|
|
||||||
ScreenIntMargin mSafeAreaInsets;
|
ScreenIntMargin mSafeAreaInsets;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -129,15 +129,21 @@ Screen::GetContentsScaleFactor(double* aOutScale) {
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CSSToLayoutDeviceScale Screen::GetCSSToLayoutDeviceScale(
|
||||||
|
IncludeOSZoom aIncludeOSZoom) const {
|
||||||
|
auto scale = CSSToLayoutDeviceScale(StaticPrefs::layout_css_devPixelsPerPx());
|
||||||
|
if (scale.scale <= 0.0) {
|
||||||
|
scale = mDefaultCssScale;
|
||||||
|
}
|
||||||
|
if (bool(aIncludeOSZoom)) {
|
||||||
|
scale.scale *= LookAndFeel::SystemZoomSettings().mFullZoom;
|
||||||
|
}
|
||||||
|
return scale;
|
||||||
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
Screen::GetDefaultCSSScaleFactor(double* aOutScale) {
|
Screen::GetDefaultCSSScaleFactor(double* aOutScale) {
|
||||||
double scale = StaticPrefs::layout_css_devPixelsPerPx();
|
*aOutScale = GetCSSToLayoutDeviceScale(IncludeOSZoom::Yes).scale;
|
||||||
if (scale > 0.0) {
|
|
||||||
*aOutScale = scale;
|
|
||||||
} else {
|
|
||||||
*aOutScale = mDefaultCssScale.scale;
|
|
||||||
}
|
|
||||||
*aOutScale *= LookAndFeel::SystemZoomSettings().mFullZoom;
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -51,6 +51,9 @@ class Screen final : public nsIScreen {
|
||||||
return mContentsScale;
|
return mContentsScale;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum class IncludeOSZoom : bool { No, Yes };
|
||||||
|
CSSToLayoutDeviceScale GetCSSToLayoutDeviceScale(IncludeOSZoom) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual ~Screen() = default;
|
virtual ~Screen() = default;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -59,6 +59,7 @@
|
||||||
#include "mozilla/layers/InputAPZContext.h"
|
#include "mozilla/layers/InputAPZContext.h"
|
||||||
#include "mozilla/layers/WebRenderLayerManager.h"
|
#include "mozilla/layers/WebRenderLayerManager.h"
|
||||||
#include "mozilla/webrender/WebRenderTypes.h"
|
#include "mozilla/webrender/WebRenderTypes.h"
|
||||||
|
#include "mozilla/widget/ScreenManager.h"
|
||||||
#include "nsAppDirectoryServiceDefs.h"
|
#include "nsAppDirectoryServiceDefs.h"
|
||||||
#include "nsCOMPtr.h"
|
#include "nsCOMPtr.h"
|
||||||
#include "nsContentUtils.h"
|
#include "nsContentUtils.h"
|
||||||
|
|
@ -2105,6 +2106,17 @@ void nsIWidget::OnLongTapTimerCallback(nsITimer* aTimer, void* aClosure) {
|
||||||
self->mLongTapTouchPoint = nullptr;
|
self->mLongTapTouchPoint = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float nsIWidget::GetFallbackDPI() {
|
||||||
|
RefPtr<const Screen> primaryScreen =
|
||||||
|
ScreenManager::GetSingleton().GetPrimaryScreen();
|
||||||
|
return primaryScreen->GetDPI();
|
||||||
|
}
|
||||||
|
|
||||||
|
CSSToLayoutDeviceScale nsIWidget::GetFallbackDefaultScale() {
|
||||||
|
RefPtr<const Screen> s = ScreenManager::GetSingleton().GetPrimaryScreen();
|
||||||
|
return s->GetCSSToLayoutDeviceScale(Screen::IncludeOSZoom::No);
|
||||||
|
}
|
||||||
|
|
||||||
nsresult nsIWidget::ClearNativeTouchSequence(nsIObserver* aObserver) {
|
nsresult nsIWidget::ClearNativeTouchSequence(nsIObserver* aObserver) {
|
||||||
AutoObserverNotifier notifier(aObserver, "cleartouch");
|
AutoObserverNotifier notifier(aObserver, "cleartouch");
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -594,6 +594,11 @@ class nsIWidget : public nsISupports {
|
||||||
*/
|
*/
|
||||||
virtual float GetDPI() = 0;
|
virtual float GetDPI() = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fallback DPI for when there's no widget available.
|
||||||
|
*/
|
||||||
|
static float GetFallbackDPI();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the scaling factor between device pixels and the platform-
|
* Return the scaling factor between device pixels and the platform-
|
||||||
* dependent "desktop pixels" used to manage window positions on a
|
* dependent "desktop pixels" used to manage window positions on a
|
||||||
|
|
@ -618,6 +623,11 @@ class nsIWidget : public nsISupports {
|
||||||
*/
|
*/
|
||||||
mozilla::CSSToLayoutDeviceScale GetDefaultScale();
|
mozilla::CSSToLayoutDeviceScale GetDefaultScale();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fallback default scale for when there's no widget available.
|
||||||
|
*/
|
||||||
|
static mozilla::CSSToLayoutDeviceScale GetFallbackDefaultScale();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the first child of this widget. Will return null if
|
* Return the first child of this widget. Will return null if
|
||||||
* there are no children.
|
* there are no children.
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue