Bug 1792337 - Add a more convenient API to size a window constrained to a default size. r=bytesized,extension-reviewers,robwu,TYLin

Differential Revision: https://phabricator.services.mozilla.com/D158235
This commit is contained in:
Emilio Cobos Álvarez 2022-09-30 00:45:36 +00:00
Родитель c54e38db5d
Коммит ab8ce397d0
10 изменённых файлов: 79 добавлений и 99 удалений

Просмотреть файл

@ -109,25 +109,8 @@ async function init(aEvent) {
document.getElementById("release").hidden = false;
}
// TODO: Add a window.sizeToContentConstrained(width, height) that does this instead.
const prefSize = 620;
let w = {};
let h = {};
window.docShell.contentViewer.getContentSizeConstrained(
prefSize * window.devicePixelRatio,
0,
w,
h
);
w = Math.ceil(w.value / window.devicePixelRatio);
h = Math.ceil(h.value / window.devicePixelRatio);
const appWin = window.docShell.treeOwner
.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIAppWindow);
h += appWin.outerToInnerHeightDifferenceInCSSPixels;
w += appWin.outerToInnerWidthDifferenceInCSSPixels;
window.resizeTo(w, h);
const prefWidth = 620;
window.sizeToContentConstrained(prefWidth, 0);
if (AppConstants.platform == "macosx") {
window.moveTo(

Просмотреть файл

@ -11,8 +11,10 @@ webidl Document;
webidl Node;
%{ C++
#include "mozilla/Maybe.h"
#include "nsTArray.h"
#include "nsRect.h"
#include "Units.h"
class nsIWidget;
class nsPresContext;
@ -273,20 +275,26 @@ interface nsIContentViewer : nsISupports
*/
attribute boolean authorStyleDisabled;
/**
* Requests the size of the content to the container.
*/
void getContentSize(out long width, out long height);
/**
* Returns the preferred width and height of the content, constrained to the
* given maximum values. If either maxWidth or maxHeight is less than zero,
* that dimension is not constrained.
*
* All input and output values are in device pixels, rather than CSS pixels.
* All input and output values are in CSS pixels.
*/
void getContentSizeConstrained(in long maxWidth, in long maxHeight,
out long width, out long height);
void getContentSize(in long maxWidth, in long maxHeight,
out long width, out long height);
%{C++
mozilla::Maybe<mozilla::CSSIntSize> GetContentSize(int32_t aMaxWidth = 0, int32_t aMaxHeight = 0) {
int32_t w = 0;
int32_t h = 0;
if (NS_SUCCEEDED(GetContentSize(aMaxWidth, aMaxHeight, &w, &h))) {
return mozilla::Some(mozilla::CSSIntSize(w, h));
}
return mozilla::Nothing();
}
%}
[noscript, notxpcom] Encoding getReloadEncodingAndSource(out int32_t aSource);
[noscript, notxpcom] void setReloadEncodingAndSource(in Encoding aEncoding, in int32_t aSource);

Просмотреть файл

@ -3931,7 +3931,15 @@ void nsGlobalWindowInner::ResizeBy(int32_t aWidthDif, int32_t aHeightDif,
void nsGlobalWindowInner::SizeToContent(CallerType aCallerType,
ErrorResult& aError) {
FORWARD_TO_OUTER_OR_THROW(SizeToContentOuter, (aCallerType, aError),
FORWARD_TO_OUTER_OR_THROW(SizeToContentOuter, (aCallerType, 0, 0, aError),
aError, );
}
void nsGlobalWindowInner::SizeToContentConstrained(int32_t aMaxWidth,
int32_t aMaxHeight,
ErrorResult& aError) {
FORWARD_TO_OUTER_OR_THROW(SizeToContentOuter,
(CallerType::System, aMaxWidth, aMaxHeight, aError),
aError, );
}

Просмотреть файл

@ -862,6 +862,8 @@ class nsGlobalWindowInner final : public mozilla::dom::EventTarget,
mozilla::ErrorResult& aError);
void SizeToContent(mozilla::dom::CallerType aCallerType,
mozilla::ErrorResult& aError);
void SizeToContentConstrained(int32_t aMaxWidth, int32_t aMaxHeight,
mozilla::ErrorResult& aError);
mozilla::dom::Crypto* GetCrypto(mozilla::ErrorResult& aError);
mozilla::dom::U2F* GetU2f(mozilla::ErrorResult& aError);
nsIControllers* GetControllers(mozilla::ErrorResult& aError);

Просмотреть файл

@ -5466,6 +5466,8 @@ void nsGlobalWindowOuter::ResizeByOuter(int32_t aWidthDif, int32_t aHeightDif,
}
void nsGlobalWindowOuter::SizeToContentOuter(CallerType aCallerType,
int32_t aMaxWidth,
int32_t aMaxHeight,
ErrorResult& aError) {
if (!mDocShell) {
return;
@ -5485,22 +5487,19 @@ void nsGlobalWindowOuter::SizeToContentOuter(CallerType aCallerType,
nsCOMPtr<nsIContentViewer> cv;
mDocShell->GetContentViewer(getter_AddRefs(cv));
if (!cv) {
aError.Throw(NS_ERROR_FAILURE);
return;
return aError.Throw(NS_ERROR_FAILURE);
}
nsIntSize contentSize;
aError = cv->GetContentSize(&contentSize.width, &contentSize.height);
if (aError.Failed()) {
return;
auto contentSize = cv->GetContentSize(aMaxWidth, aMaxHeight);
if (!contentSize) {
return aError.Throw(NS_ERROR_FAILURE);
}
// Make sure the new size is following the CheckSecurityWidthAndHeight
// rules.
nsCOMPtr<nsIDocShellTreeOwner> treeOwner = GetTreeOwner();
if (!treeOwner) {
aError.Throw(NS_ERROR_FAILURE);
return;
return aError.Throw(NS_ERROR_FAILURE);
}
// Don't use DevToCSSIntPixelsForBaseWindow() nor
@ -5511,13 +5510,12 @@ void nsGlobalWindowOuter::SizeToContentOuter(CallerType aCallerType,
MOZ_ASSERT(
presContext,
"Should be non-nullptr if nsIContentViewer::GetContentSize() succeeded");
nsIntSize cssSize(presContext->DevPixelsToIntCSSPixels(contentSize.width),
presContext->DevPixelsToIntCSSPixels(contentSize.height));
CSSIntSize cssSize = *contentSize;
CheckSecurityWidthAndHeight(&cssSize.width, &cssSize.height, aCallerType);
nsIntSize newDevSize(presContext->CSSPixelsToDevPixels(cssSize.width),
presContext->CSSPixelsToDevPixels(cssSize.height));
LayoutDeviceIntSize newDevSize(
presContext->CSSPixelsToDevPixels(cssSize.width),
presContext->CSSPixelsToDevPixels(cssSize.height));
nsCOMPtr<nsIDocShell> docShell = mDocShell;
aError =

Просмотреть файл

@ -625,6 +625,7 @@ class nsGlobalWindowOuter final : public mozilla::dom::EventTarget,
MOZ_CAN_RUN_SCRIPT_BOUNDARY
void SizeToContentOuter(mozilla::dom::CallerType aCallerType,
int32_t aMaxWidth, int32_t aMaxHeight,
mozilla::ErrorResult& aError);
nsIControllers* GetControllersOuter(mozilla::ErrorResult& aError);
nsresult GetControllers(nsIControllers** aControllers) override;

Просмотреть файл

@ -430,6 +430,11 @@ partial interface Window {
* Method for sizing this window to the content in the window.
*/
[Throws, NeedsCallerType] undefined sizeToContent();
/**
* Chrome-only method for sizing to content with a maximum-size constraint on
* either (or both) directions.
*/
[Throws, ChromeOnly] undefined sizeToContentConstrained(long width, long height);
// XXX Shouldn't this be in nsIDOMChromeWindow?
[ChromeOnly, Replaceable, Throws] readonly attribute XULControllers controllers;

Просмотреть файл

@ -376,10 +376,6 @@ class nsDocumentViewer final : public nsIContentViewer,
already_AddRefed<nsINode> GetPopupLinkNode();
already_AddRefed<nsIImageLoadingContent> GetPopupImageNode();
MOZ_CAN_RUN_SCRIPT_BOUNDARY
nsresult GetContentSizeInternal(int32_t* aWidth, int32_t* aHeight,
nscoord aMaxWidth, nscoord aMaxHeight);
void PrepareToStartLoad(void);
nsresult SyncParentSubDocMap();
@ -2601,11 +2597,26 @@ nsDocumentViewer::ForgetReloadEncoding() {
mReloadEncodingSource = kCharsetUninitialized;
}
nsresult nsDocumentViewer::GetContentSizeInternal(int32_t* aWidth,
int32_t* aHeight,
nscoord aMaxWidth,
nscoord aMaxHeight) {
NS_ENSURE_TRUE(mDocument, NS_ERROR_NOT_AVAILABLE);
MOZ_CAN_RUN_SCRIPT_BOUNDARY NS_IMETHODIMP nsDocumentViewer::GetContentSize(
int32_t aMaxWidth, int32_t aMaxHeight, int32_t* aWidth, int32_t* aHeight) {
RefPtr<BrowsingContext> bc = mContainer->GetBrowsingContext();
NS_ENSURE_TRUE(bc, NS_ERROR_NOT_AVAILABLE);
// It's only valid to access this from a top frame. Doesn't work from
// sub-frames.
NS_ENSURE_TRUE(bc->IsTop(), NS_ERROR_FAILURE);
// Convert max-width/height to app units.
if (aMaxWidth > 0) {
aMaxWidth = CSSPixel::ToAppUnits(aMaxWidth);
} else {
aMaxWidth = NS_UNCONSTRAINEDSIZE;
}
if (aMaxHeight > 0) {
aMaxHeight = CSSPixel::ToAppUnits(aMaxHeight);
} else {
aMaxHeight = NS_UNCONSTRAINEDSIZE;
}
RefPtr<PresShell> presShell = GetPresShell();
NS_ENSURE_TRUE(presShell, NS_ERROR_FAILURE);
@ -2648,46 +2659,12 @@ nsresult nsDocumentViewer::GetContentSizeInternal(int32_t* aWidth,
// Ceil instead of rounding here, so we can actually guarantee showing all the
// content.
*aWidth = std::ceil(presContext->AppUnitsToFloatDevPixels(shellArea.width));
*aHeight = std::ceil(presContext->AppUnitsToFloatDevPixels(shellArea.height));
*aWidth = std::ceil(CSSPixel::FromAppUnits(shellArea.width));
*aHeight = std::ceil(CSSPixel::FromAppUnits(shellArea.height));
return NS_OK;
}
NS_IMETHODIMP
nsDocumentViewer::GetContentSize(int32_t* aWidth, int32_t* aHeight) {
NS_ENSURE_TRUE(mContainer, NS_ERROR_NOT_AVAILABLE);
RefPtr<BrowsingContext> bc = mContainer->GetBrowsingContext();
NS_ENSURE_TRUE(bc, NS_ERROR_NOT_AVAILABLE);
// It's only valid to access this from a top frame. Doesn't work from
// sub-frames.
NS_ENSURE_TRUE(bc->IsTop(), NS_ERROR_FAILURE);
return GetContentSizeInternal(aWidth, aHeight, NS_UNCONSTRAINEDSIZE,
NS_UNCONSTRAINEDSIZE);
}
NS_IMETHODIMP
nsDocumentViewer::GetContentSizeConstrained(int32_t aMaxWidth,
int32_t aMaxHeight, int32_t* aWidth,
int32_t* aHeight) {
RefPtr<nsPresContext> presContext = GetPresContext();
NS_ENSURE_TRUE(presContext, NS_ERROR_FAILURE);
nscoord maxWidth = NS_UNCONSTRAINEDSIZE;
nscoord maxHeight = NS_UNCONSTRAINEDSIZE;
if (aMaxWidth > 0) {
maxWidth = presContext->DevPixelsToAppUnits(aMaxWidth);
}
if (aMaxHeight > 0) {
maxHeight = presContext->DevPixelsToAppUnits(aMaxHeight);
}
return GetContentSizeInternal(aWidth, aHeight, maxWidth, maxHeight);
}
NS_IMPL_ISUPPORTS(nsDocViewerSelectionListener, nsISelectionListener)
/*

Просмотреть файл

@ -255,21 +255,17 @@ const BrowserListener = {
this.oldBackground = background;
// Adjust the size of the browser based on its content's preferred size.
let { contentViewer } = docShell;
let ratio = content.devicePixelRatio;
let w = {},
h = {};
contentViewer.getContentSizeConstrained(
this.maxWidth * ratio,
this.maxHeight * ratio,
docShell.contentViewer.getContentSize(
this.maxWidth,
this.maxHeight,
w,
h
);
let width = Math.ceil((w.value * zoom) / ratio);
let height = Math.ceil((h.value * zoom) / ratio);
let width = Math.ceil(w.value * zoom);
let height = Math.ceil(h.value * zoom);
result = { width, height, detail };
}

Просмотреть файл

@ -2649,10 +2649,12 @@ void AppWindow::SizeShell() {
nsCOMPtr<nsIDocShellTreeOwner> treeOwner;
docShell->GetTreeOwner(getter_AddRefs(treeOwner));
if (treeOwner) {
// GetContentSize can fail, so initialise |width| and |height| to be
// on the safe side.
int32_t width = 0, height = 0;
if (NS_SUCCEEDED(cv->GetContentSize(&width, &height))) {
if (Maybe<CSSIntSize> size = cv->GetContentSize()) {
nsPresContext* pc = cv->GetPresContext();
MOZ_ASSERT(pc, "Should have pres context");
int32_t width = pc->CSSPixelsToDevPixels(size->width);
int32_t height = pc->CSSPixelsToDevPixels(size->height);
treeOwner->SizeShellTo(docShell, width, height);
// Update specified size for the final LoadPositionFromXUL call.
specWidth = width + windowDiff.width;