Backed out 4 changesets (bug 1786048) for causing multiple failures. CLOSED TREE

Backed out changeset ae94135e68ef (bug 1786048)
Backed out changeset f505df8a481a (bug 1786048)
Backed out changeset 999a18d6f33e (bug 1786048)
Backed out changeset e71e8644b8a9 (bug 1786048)
This commit is contained in:
Sandor Molnar 2022-12-02 20:30:07 +02:00
Родитель f355713f7a
Коммит a1e9c1d43b
47 изменённых файлов: 850 добавлений и 1266 удалений

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

@ -40,19 +40,3 @@ skip-if = debug # This test triggers Bug 1578794 due to opening many popups.
[browser_popup_new_window_size.js]
support-files =
popup_size.html
[browser_popup_move.js]
skip-if = os == 'linux' && !headless # Wayland doesn't like moving windows, X11/XWayland unreliable current positions
[browser_popup_move_instant.js]
skip-if = os == 'linux' && !headless # Wayland doesn't like moving windows, X11/XWayland unreliable current positions
[browser_popup_resize.js]
skip-if = os == 'linux' && !headless # outdated current sizes
[browser_popup_resize_instant.js]
skip-if = os == 'linux' && !headless # outdated current sizes
[browser_popup_resize_repeat.js]
skip-if = os == 'linux' && !headless # outdated current sizes
[browser_popup_resize_repeat_instant.js]
skip-if = os == 'linux' && !headless # outdated current sizes
[browser_popup_resize_revert.js]
skip-if = os == 'linux' && !headless # outdated current sizes
[browser_popup_resize_revert_instant.js]
skip-if = os == 'linux' && !headless # outdated current sizes

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

@ -1,6 +0,0 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
createGenericMoveTests(/* aInstant */ false, "Move");

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

@ -1,6 +0,0 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
createGenericMoveTests(/* aInstant */ true, "Move");

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

@ -1,6 +0,0 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
createGenericResizeTests(9, 10, /* aInstant */ false, "Resize");

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

@ -1,6 +0,0 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
createGenericResizeTests(9, 10, /* aInstant */ true, "Resize");

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

@ -1,6 +0,0 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
createGenericResizeTests(10, 10, /* aInstant */ false, "Resize repeat");

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

@ -1,6 +0,0 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
createGenericResizeTests(10, 10, /* aInstant */ true, "Resize repeat");

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

@ -1,6 +0,0 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
createGenericResizeTests(10, 0, /* aInstant */ false, "Resize revert");

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

@ -1,6 +0,0 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
createGenericResizeTests(10, 0, /* aInstant */ true, "Resize revert");

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

@ -3,10 +3,6 @@
"use strict";
const gfxInfo = Cc["@mozilla.org/gfx/info;1"].getService(
SpecialPowers.Ci.nsIGfxInfo
);
async function waitForBlockedPopups(numberOfPopups, { doc }) {
let toolbarDoc = doc || document;
let menupopup = toolbarDoc.getElementById("blockedPopupOptions");
@ -15,476 +11,3 @@ async function waitForBlockedPopups(numberOfPopups, { doc }) {
return popups.length == numberOfPopups;
}, `Waiting for ${numberOfPopups} popups`);
}
/*
* Tests that a sequence of size changes ultimately results in the latest
* requested size. The test also fails when an unexpected window size is
* observed in a resize event.
*
* aPropertyDeltas List of objects where keys describe the name of a window
* property and the values the difference to its initial
* value.
*
* aInstant Issue changes without additional waiting in between.
*
* A brief example of the resutling code that is effectively run for the
* following list of deltas:
* [{outerWidth: 5, outerHeight: 10}, {outerWidth: 10}]
*
* let initialWidth = win.outerWidth;
* let initialHeight = win.outerHeight;
*
* if (aInstant) {
* win.outerWidth = initialWidth + 5;
* win.outerHeight = initialHeight + 10;
*
* win.outerWidth = initialWidth + 10;
* } else {
* win.requestAnimationFrame(() => {
* win.outerWidth = initialWidth + 5;
* win.outerHeight = initialHeight + 10;
*
* win.requestAnimationFrame(() => {
* win.outerWidth = initialWidth + 10;
* });
* });
* }
*/
async function testPropertyDeltas(aPropertyDeltas, aInstant, aPropInfo, aMsg) {
let msg = `[${aMsg}]`;
let win = this.content.popup || this.content.wrappedJSObject;
// Property names and mapping from ResizeMoveTest
let {
sizeProps,
positionProps /* can be empty/incomplete as workaround on Linux */,
readonlyProps,
crossBoundsMapping,
} = aPropInfo;
let stringifyState = state => {
let stateMsg = sizeProps
.concat(positionProps)
.filter(prop => state[prop] !== undefined)
.map(prop => `${prop}: ${state[prop]}`)
.join(", ");
return `{ ${stateMsg} }`;
};
let initialState = {};
let finalState = {};
info("Initializing all values to current state.");
for (let prop of sizeProps.concat(positionProps)) {
let value = win[prop];
initialState[prop] = value;
finalState[prop] = value;
}
// List of potential states during resize events. The current state is also
// considered valid, as the resize event might still be outstanding.
let validResizeStates = [initialState];
let updateFinalState = (aProp, aDelta) => {
if (
readonlyProps.includes(aProp) ||
!sizeProps.concat(positionProps).includes(aProp)
) {
throw new Error(`Unexpected property "${aProp}".`);
}
// Update both properties of the same axis.
let otherProp = crossBoundsMapping[aProp];
finalState[aProp] = initialState[aProp] + aDelta;
finalState[otherProp] = initialState[otherProp] + aDelta;
// Mark size as valid in resize event.
if (sizeProps.includes(aProp)) {
let state = {};
sizeProps.forEach(p => (state[p] = finalState[p]));
validResizeStates.push(state);
}
};
info("Adding resize event listener.");
let resizeCount = 0;
let resizeListener = evt => {
resizeCount++;
let currentSizeState = {};
sizeProps.forEach(p => (currentSizeState[p] = win[p]));
info(
`${msg} ${resizeCount}. resize event: ${stringifyState(currentSizeState)}`
);
let matchingIndex = validResizeStates.findIndex(state =>
sizeProps.every(p => state[p] == currentSizeState[p])
);
if (matchingIndex < 0) {
info(`${msg} Size state should have been one of:`);
for (let state of validResizeStates) {
info(stringifyState(state));
}
}
if (win.gBrowser && evt.target != win) {
// Without e10s we receive content resize events in chrome windows.
todo(false, `${msg} Resize event target is our window.`);
return;
}
ok(
matchingIndex >= 0,
`${msg} Valid intermediate state. Current: ` +
stringifyState(currentSizeState)
);
// No longer allow current and preceding states.
validResizeStates.splice(0, matchingIndex + 1);
};
win.addEventListener("resize", resizeListener);
info("Starting property changes.");
await new Promise(resolve => {
let index = 0;
let next = async () => {
let pre = `${msg} [${index + 1}/${aPropertyDeltas.length}]`;
let deltaObj = aPropertyDeltas[index];
for (let prop in deltaObj) {
updateFinalState(prop, deltaObj[prop]);
let targetValue = initialState[prop] + deltaObj[prop];
info(`${pre} Setting ${prop} to ${targetValue}.`);
win[prop] = targetValue;
}
index++;
if (index < aPropertyDeltas.length) {
scheduleNext();
} else {
resolve();
}
};
let scheduleNext = () => {
if (aInstant) {
next();
} else {
info(`${msg} Requesting animation frame.`);
win.requestAnimationFrame(next);
}
};
scheduleNext();
});
try {
info(`${msg} Waiting for window to match the final state.`);
await ContentTaskUtils.waitForCondition(
() => sizeProps.concat(positionProps).every(p => win[p] == finalState[p]),
"Waiting for final state."
);
} catch (e) {}
info(`${msg} Checking final state.`);
info(`${msg} Exepected: ${stringifyState(finalState)}`);
info(`${msg} Actual: ${stringifyState(win)}`);
for (let prop of sizeProps.concat(positionProps)) {
is(win[prop], finalState[prop], `${msg} Expected final value for ${prop}`);
}
win.removeEventListener("resize", resizeListener);
}
function roundedCenter(aDimension, aOrigin) {
let center = aOrigin + Math.floor(aDimension / 2);
return center - (center % 100);
}
class ResizeMoveTest {
static WindowWidth = 200;
static WindowHeight = 200;
static WindowLeft = roundedCenter(screen.availWidth - 200, screen.left);
static WindowTop = roundedCenter(screen.availHeight - 200, screen.top);
static PropInfo = {
sizeProps: ["outerWidth", "outerHeight", "innerWidth", "innerHeight"],
positionProps: [
"screenX",
"screenY",
/* readonly */ "mozInnerScreenX",
/* readonly */ "mozInnerScreenY",
],
readonlyProps: ["mozInnerScreenX", "mozInnerScreenY"],
crossAxisMapping: {
outerWidth: "outerHeight",
outerHeight: "outerWidth",
innerWidth: "innerHeight",
innerHeight: "innerWidth",
screenX: "screenY",
screenY: "screenX",
mozInnerScreenX: "mozInnerScreenY",
mozInnerScreenY: "mozInnerScreenX",
},
crossBoundsMapping: {
outerWidth: "innerWidth",
outerHeight: "innerHeight",
innerWidth: "outerWidth",
innerHeight: "outerHeight",
screenX: "mozInnerScreenX",
screenY: "mozInnerScreenY",
mozInnerScreenX: "screenX",
mozInnerScreenY: "screenY",
},
};
constructor(aPropertyDeltas, aInstant = false, aMsg = "ResizeMoveTest") {
this.propertyDeltas = aPropertyDeltas;
this.instant = aInstant;
this.msg = aMsg;
if (!ResizeMoveTest.hasCleanUpTask) {
ResizeMoveTest.hasCleanUpTask = true;
registerCleanupFunction(ResizeMoveTest.Cleanup);
}
add_task(async () => {
let tab = await ResizeMoveTest.GetOrCreateTab();
let browsingContext = await ResizeMoveTest.GetOrCreatePopupBrowsingContext();
if (!browsingContext) {
return;
}
info("=== Running in content. ===");
await this.run(browsingContext, `${this.msg} (content)`);
await this.restorePopupState(browsingContext);
info("=== Running in chrome. ===");
let popupChrome = browsingContext.topChromeWindow;
await this.run(popupChrome.browsingContext, `${this.msg} (chrome)`);
await this.restorePopupState(browsingContext);
info("=== Running in opener. ===");
await this.run(tab.linkedBrowser, `${this.msg} (opener)`);
await this.restorePopupState(browsingContext);
});
}
async run(aBrowsingContext, aMsg) {
let testType = this.instant ? "instant" : "fanned out";
let msg = `${aMsg} (${testType})`;
info(`${msg}: ` + JSON.stringify(this.propertyDeltas));
await SpecialPowers.spawn(
aBrowsingContext,
[this.propertyDeltas, this.instant, ResizeMoveTest.PropInfo, msg],
testPropertyDeltas
);
}
async restorePopupState(aBrowsingContext) {
info("Restore popup state.");
let { deltaWidth, deltaHeight } = await SpecialPowers.spawn(
aBrowsingContext,
[],
() => {
return {
deltaWidth: this.content.outerWidth - this.content.innerWidth,
deltaHeight: this.content.outerHeight - this.content.innerHeight,
};
}
);
let chromeWindow = aBrowsingContext.topChromeWindow;
let {
WindowLeft: left,
WindowTop: top,
WindowWidth: width,
WindowHeight: height,
} = ResizeMoveTest;
chromeWindow.resizeTo(width + deltaWidth, height + deltaHeight);
chromeWindow.moveTo(left, top);
await SpecialPowers.spawn(
aBrowsingContext,
[left, top, width, height],
async (aLeft, aTop, aWidth, aHeight) => {
let win = this.content.wrappedJSObject;
info("Waiting for restored size.");
await ContentTaskUtils.waitForCondition(
() => win.innerWidth == aWidth && win.innerHeight === aHeight,
"Waiting for restored size."
);
is(win.innerWidth, aWidth, "Restored width.");
is(win.innerHeight, aHeight, "Restored height.");
info("Waiting for restored position.");
await ContentTaskUtils.waitForCondition(
() => win.screenX == aLeft && win.screenY === aTop,
"Waiting for restored position."
);
is(win.screenX, aLeft, "Restored screenX.");
is(win.screenY, aTop, "Restored screenY.");
}
);
}
static async GetOrCreateTab() {
if (ResizeMoveTest.tab) {
return ResizeMoveTest.tab;
}
info("Opening tab.");
ResizeMoveTest.tab = await BrowserTestUtils.openNewForegroundTab(
window.gBrowser,
"https://example.net/browser/browser/base/content/test/popups/popup_blocker_a.html"
);
return ResizeMoveTest.tab;
}
static async GetOrCreatePopupBrowsingContext() {
if (ResizeMoveTest.popupBrowsingContext) {
if (!ResizeMoveTest.popupBrowsingContext.isActive) {
return undefined;
}
return ResizeMoveTest.popupBrowsingContext;
}
let tab = await ResizeMoveTest.GetOrCreateTab();
info("Opening popup.");
ResizeMoveTest.popupBrowsingContext = await SpecialPowers.spawn(
tab.linkedBrowser,
[
ResizeMoveTest.WindowWidth,
ResizeMoveTest.WindowHeight,
ResizeMoveTest.WindowLeft,
ResizeMoveTest.WindowTop,
],
async (aWidth, aHeight, aLeft, aTop) => {
let win = this.content.open(
this.content.document.location.href,
"_blank",
`left=${aLeft},top=${aTop},width=${aWidth},height=${aHeight}`
);
this.content.popup = win;
await new Promise(r => (win.onload = r));
return win.browsingContext;
}
);
return ResizeMoveTest.popupBrowsingContext;
}
static async Cleanup() {
let browsingContext = ResizeMoveTest.popupBrowsingContext;
if (browsingContext) {
await SpecialPowers.spawn(browsingContext, [], () => {
this.content.close();
});
delete ResizeMoveTest.popupBrowsingContext;
}
let tab = ResizeMoveTest.tab;
if (tab) {
await BrowserTestUtils.removeTab(tab);
delete ResizeMoveTest.tab;
}
ResizeMoveTest.hasCleanUpTask = false;
}
}
function chaosRequestLongerTimeout(aDoRequest) {
if (aDoRequest && parseInt(Services.env.get("MOZ_CHAOSMODE"), 16)) {
requestLongerTimeout(2);
}
}
function createGenericResizeTests(aFirstValue, aSecondValue, aInstant, aMsg) {
// Runtime almost doubles in chaos mode on Mac.
chaosRequestLongerTimeout(AppConstants.platform == "macosx");
let { crossBoundsMapping, crossAxisMapping } = ResizeMoveTest.PropInfo;
for (let prop of ["innerWidth", "outerHeight"]) {
// Mixing inner and outer property.
for (let secondProp of [prop, crossBoundsMapping[prop]]) {
let first = {};
first[prop] = aFirstValue;
let second = {};
second[secondProp] = aSecondValue;
new ResizeMoveTest(
[first, second],
aInstant,
`${aMsg} ${prop},${secondProp}`
);
}
}
for (let prop of ["innerHeight", "outerWidth"]) {
let first = {};
first[prop] = aFirstValue;
let second = {};
second[prop] = aSecondValue;
// Setting property of other axis before/between two changes.
let otherProps = [
crossAxisMapping[prop],
crossAxisMapping[crossBoundsMapping[prop]],
];
for (let interferenceProp of otherProps) {
let interference = {};
interference[interferenceProp] = 20;
new ResizeMoveTest(
[first, interference, second],
aInstant,
`${aMsg} ${prop},${interferenceProp},${prop}`
);
new ResizeMoveTest(
[interference, first, second],
aInstant,
`${aMsg} ${interferenceProp},${prop},${prop}`
);
}
}
}
function createGenericMoveTests(aInstant, aMsg) {
// Runtime almost doubles in chaos mode on Mac.
chaosRequestLongerTimeout(AppConstants.platform == "macosx");
let { crossAxisMapping } = ResizeMoveTest.PropInfo;
for (let prop of ["screenX", "screenY"]) {
for (let [v1, v2, msg] of [
[9, 10, `${aMsg}`],
[11, 11, `${aMsg} repeat`],
[12, 0, `${aMsg} revert`],
]) {
let first = {};
first[prop] = v1;
let second = {};
second[prop] = v2;
new ResizeMoveTest([first, second], aInstant, `${msg} ${prop},${prop}`);
let interferenceProp = crossAxisMapping[prop];
let interference = {};
interference[interferenceProp] = 20;
new ResizeMoveTest(
[first, interference, second],
aInstant,
`${aMsg} ${prop},${interferenceProp},${prop}`
);
new ResizeMoveTest(
[interference, first, second],
aInstant,
`${msg} ${interferenceProp},${prop},${prop}`
);
}
}
}

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

@ -4783,17 +4783,6 @@ void nsDocShell::DoGetPositionAndSize(int32_t* aX, int32_t* aY, int32_t* aWidth,
}
}
NS_IMETHODIMP
nsDocShell::SetDimensions(DimensionRequest&& aRequest) {
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsDocShell::GetDimensions(DimensionKind aDimensionKind, int32_t* aX,
int32_t* aY, int32_t* aCX, int32_t* aCY) {
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsDocShell::Repaint(bool aForce) {
PresShell* presShell = GetPresShell();
@ -4919,13 +4908,7 @@ nsDocShell::GetVisibility(bool* aVisibility) {
// Check with the tree owner as well to give embedders a chance to
// expose visibility as well.
nsresult rv = treeOwnerAsWin->GetVisibility(aVisibility);
if (rv == NS_ERROR_NOT_IMPLEMENTED) {
// The tree owner had no opinion on our visibility.
*aVisibility = true;
return NS_OK;
}
return rv;
return treeOwnerAsWin->GetVisibility(aVisibility);
}
void nsDocShell::ActivenessMaybeChanged() {

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

@ -453,20 +453,16 @@ nsDocShellTreeOwner::SizeShellTo(nsIDocShellTreeItem* aShellItem, int32_t aCX,
do_QueryInterface(webBrowserChrome);
if (browserChild) {
// The XUL window to resize is in the parent process, but there we
// won't be able to get the size of aShellItem. We can ask the parent
// process to change our size instead.
// won't be able to get aShellItem to do the hack in
// AppWindow::SizeShellTo, so let's send the width and height of
// aShellItem too.
nsCOMPtr<nsIBaseWindow> shellAsWin(do_QueryInterface(aShellItem));
NS_ENSURE_TRUE(shellAsWin, NS_ERROR_FAILURE);
LayoutDeviceIntSize shellSize;
shellAsWin->GetSize(&shellSize.width, &shellSize.height);
LayoutDeviceIntSize deltaSize = LayoutDeviceIntSize(aCX, aCY) - shellSize;
LayoutDeviceIntSize currentSize;
GetSize(&currentSize.width, &currentSize.height);
LayoutDeviceIntSize newSize = currentSize + deltaSize;
return SetSize(newSize.width, newSize.height, true);
int32_t width = 0;
int32_t height = 0;
shellAsWin->GetSize(&width, &height);
return browserChild->RemoteSizeShellTo(aCX, aCY, width, height);
}
// XXX: this is weird, but we used to call a method here
// (webBrowserChrome->SizeBrowserTo()) whose implementations all failed
@ -558,62 +554,68 @@ nsDocShellTreeOwner::SetPositionDesktopPix(int32_t aX, int32_t aY) {
NS_IMETHODIMP
nsDocShellTreeOwner::SetPosition(int32_t aX, int32_t aY) {
return SetDimensions(
{DimensionKind::Outer, Some(aX), Some(aY), Nothing(), Nothing()});
nsCOMPtr<nsIEmbeddingSiteWindow> ownerWin = GetOwnerWin();
if (ownerWin) {
return ownerWin->SetDimensions(nsIEmbeddingSiteWindow::DIM_FLAGS_POSITION,
aX, aY, 0, 0);
}
return NS_ERROR_NULL_POINTER;
}
NS_IMETHODIMP
nsDocShellTreeOwner::GetPosition(int32_t* aX, int32_t* aY) {
return GetDimensions(DimensionKind::Outer, aX, aY, nullptr, nullptr);
nsCOMPtr<nsIEmbeddingSiteWindow> ownerWin = GetOwnerWin();
if (ownerWin) {
return ownerWin->GetDimensions(nsIEmbeddingSiteWindow::DIM_FLAGS_POSITION,
aX, aY, nullptr, nullptr);
}
return NS_ERROR_NULL_POINTER;
}
NS_IMETHODIMP
nsDocShellTreeOwner::SetSize(int32_t aCX, int32_t aCY, bool aRepaint) {
return SetDimensions(
{DimensionKind::Outer, Nothing(), Nothing(), Some(aCX), Some(aCY)});
nsCOMPtr<nsIEmbeddingSiteWindow> ownerWin = GetOwnerWin();
if (ownerWin) {
return ownerWin->SetDimensions(nsIEmbeddingSiteWindow::DIM_FLAGS_SIZE_OUTER,
0, 0, aCX, aCY);
}
return NS_ERROR_NULL_POINTER;
}
NS_IMETHODIMP
nsDocShellTreeOwner::GetSize(int32_t* aCX, int32_t* aCY) {
return GetDimensions(DimensionKind::Outer, nullptr, nullptr, aCX, aCY);
nsCOMPtr<nsIEmbeddingSiteWindow> ownerWin = GetOwnerWin();
if (ownerWin) {
return ownerWin->GetDimensions(nsIEmbeddingSiteWindow::DIM_FLAGS_SIZE_OUTER,
nullptr, nullptr, aCX, aCY);
}
return NS_ERROR_NULL_POINTER;
}
NS_IMETHODIMP
nsDocShellTreeOwner::SetPositionAndSize(int32_t aX, int32_t aY, int32_t aCX,
int32_t aCY, uint32_t aFlags) {
return SetDimensions(
{DimensionKind::Outer, Some(aX), Some(aY), Some(aCX), Some(aCY)});
nsCOMPtr<nsIEmbeddingSiteWindow> ownerWin = GetOwnerWin();
if (ownerWin) {
return ownerWin->SetDimensions(
nsIEmbeddingSiteWindow::DIM_FLAGS_SIZE_OUTER |
nsIEmbeddingSiteWindow::DIM_FLAGS_POSITION,
aX, aY, aCX, aCY);
}
return NS_ERROR_NULL_POINTER;
}
NS_IMETHODIMP
nsDocShellTreeOwner::GetPositionAndSize(int32_t* aX, int32_t* aY, int32_t* aCX,
int32_t* aCY) {
return GetDimensions(DimensionKind::Outer, aX, aY, aCX, aCY);
}
NS_IMETHODIMP
nsDocShellTreeOwner::SetDimensions(DimensionRequest&& aRequest) {
nsCOMPtr<nsIBaseWindow> ownerWin = GetOwnerWin();
nsCOMPtr<nsIEmbeddingSiteWindow> ownerWin = GetOwnerWin();
if (ownerWin) {
return ownerWin->SetDimensions(std::move(aRequest));
return ownerWin->GetDimensions(
nsIEmbeddingSiteWindow::DIM_FLAGS_SIZE_OUTER |
nsIEmbeddingSiteWindow::DIM_FLAGS_POSITION,
aX, aY, aCX, aCY);
}
nsCOMPtr<nsIWebBrowserChrome> webBrowserChrome = GetWebBrowserChrome();
NS_ENSURE_STATE(webBrowserChrome);
return webBrowserChrome->SetDimensions(std::move(aRequest));
}
NS_IMETHODIMP
nsDocShellTreeOwner::GetDimensions(DimensionKind aDimensionKind, int32_t* aX,
int32_t* aY, int32_t* aCX, int32_t* aCY) {
nsCOMPtr<nsIBaseWindow> ownerWin = GetOwnerWin();
if (ownerWin) {
return ownerWin->GetDimensions(aDimensionKind, aX, aY, aCX, aCY);
}
nsCOMPtr<nsIWebBrowserChrome> webBrowserChrome = GetWebBrowserChrome();
NS_ENSURE_STATE(webBrowserChrome);
return webBrowserChrome->GetDimensions(aDimensionKind, aX, aY, aCX, aCY);
return NS_ERROR_NULL_POINTER;
}
NS_IMETHODIMP
@ -631,9 +633,9 @@ nsDocShellTreeOwner::SetParentWidget(nsIWidget* aParentWidget) {
NS_IMETHODIMP
nsDocShellTreeOwner::GetParentNativeWindow(nativeWindow* aParentNativeWindow) {
nsCOMPtr<nsIBaseWindow> ownerWin = GetOwnerWin();
nsCOMPtr<nsIEmbeddingSiteWindow> ownerWin = GetOwnerWin();
if (ownerWin) {
return ownerWin->GetParentNativeWindow(aParentNativeWindow);
return ownerWin->GetSiteWindow(aParentNativeWindow);
}
return NS_ERROR_NULL_POINTER;
}
@ -651,17 +653,16 @@ nsDocShellTreeOwner::GetNativeHandle(nsAString& aNativeHandle) {
NS_IMETHODIMP
nsDocShellTreeOwner::GetVisibility(bool* aVisibility) {
nsCOMPtr<nsIBaseWindow> ownerWin = GetOwnerWin();
nsCOMPtr<nsIEmbeddingSiteWindow> ownerWin = GetOwnerWin();
if (ownerWin) {
return ownerWin->GetVisibility(aVisibility);
}
return NS_ERROR_NOT_IMPLEMENTED;
return NS_ERROR_NULL_POINTER;
}
NS_IMETHODIMP
nsDocShellTreeOwner::SetVisibility(bool aVisibility) {
nsCOMPtr<nsIBaseWindow> ownerWin = GetOwnerWin();
nsCOMPtr<nsIEmbeddingSiteWindow> ownerWin = GetOwnerWin();
if (ownerWin) {
return ownerWin->SetVisibility(aVisibility);
}
@ -687,7 +688,7 @@ nsDocShellTreeOwner::GetMainWidget(nsIWidget** aMainWidget) {
NS_IMETHODIMP
nsDocShellTreeOwner::GetTitle(nsAString& aTitle) {
nsCOMPtr<nsIBaseWindow> ownerWin = GetOwnerWin();
nsCOMPtr<nsIEmbeddingSiteWindow> ownerWin = GetOwnerWin();
if (ownerWin) {
return ownerWin->GetTitle(aTitle);
}
@ -696,7 +697,7 @@ nsDocShellTreeOwner::GetTitle(nsAString& aTitle) {
NS_IMETHODIMP
nsDocShellTreeOwner::SetTitle(const nsAString& aTitle) {
nsCOMPtr<nsIBaseWindow> ownerWin = GetOwnerWin();
nsCOMPtr<nsIEmbeddingSiteWindow> ownerWin = GetOwnerWin();
if (ownerWin) {
return ownerWin->SetTitle(aTitle);
}
@ -818,7 +819,8 @@ nsDocShellTreeOwner::SetWebBrowserChrome(
if (supportsweak) {
supportsweak->GetWeakReference(getter_AddRefs(mWebBrowserChromeWeak));
} else {
nsCOMPtr<nsIBaseWindow> ownerWin(do_QueryInterface(aWebBrowserChrome));
nsCOMPtr<nsIEmbeddingSiteWindow> ownerWin(
do_QueryInterface(aWebBrowserChrome));
nsCOMPtr<nsIInterfaceRequestor> requestor(
do_QueryInterface(aWebBrowserChrome));
@ -990,8 +992,8 @@ nsDocShellTreeOwner::GetWebBrowserChrome() {
return chrome.forget();
}
already_AddRefed<nsIBaseWindow> nsDocShellTreeOwner::GetOwnerWin() {
nsCOMPtr<nsIBaseWindow> win;
already_AddRefed<nsIEmbeddingSiteWindow> nsDocShellTreeOwner::GetOwnerWin() {
nsCOMPtr<nsIEmbeddingSiteWindow> win;
if (mWebBrowserChromeWeak) {
win = do_QueryReferent(mWebBrowserChromeWeak);
} else if (mOwnerWin) {

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

@ -18,6 +18,7 @@
#include "nsIInterfaceRequestorUtils.h"
#include "nsIWebBrowserChrome.h"
#include "nsIDOMEventListener.h"
#include "nsIEmbeddingSiteWindow.h"
#include "nsIWebProgressListener.h"
#include "nsWeakReference.h"
#include "nsITimer.h"
@ -81,7 +82,7 @@ class nsDocShellTreeOwner final : public nsIDocShellTreeOwner,
// that object. Otherwise, they return an addrefed pointer. If the
// WebBrowserChrome object doesn't exist, they return nullptr.
already_AddRefed<nsIWebBrowserChrome> GetWebBrowserChrome();
already_AddRefed<nsIBaseWindow> GetOwnerWin();
already_AddRefed<nsIEmbeddingSiteWindow> GetOwnerWin();
already_AddRefed<nsIInterfaceRequestor> GetOwnerRequestor();
protected:
@ -91,7 +92,7 @@ class nsDocShellTreeOwner final : public nsIDocShellTreeOwner,
nsIDocShellTreeItem* mPrimaryContentShell;
nsIWebBrowserChrome* mWebBrowserChrome;
nsIBaseWindow* mOwnerWin;
nsIEmbeddingSiteWindow* mOwnerWin;
nsIInterfaceRequestor* mOwnerRequestor;
nsWeakPtr mWebBrowserChromeWeak; // nsIWebBrowserChrome

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

@ -66,22 +66,22 @@ interface nsIDocShellTreeOwner : nsISupports
void sizeShellTo(in nsIDocShellTreeItem shell, in long cx, in long cy);
/*
Gets the size of the primary content area in device pixels. This should work
Gets the size of the primary content area in CSS pixels. This should work
for both in-process and out-of-process content areas.
*/
void getPrimaryContentSize(out long width, out long height);
/*
Sets the size of the primary content area in device pixels. This should work
Sets the size of the primary content area in CSS pixels. This should work
for both in-process and out-of-process content areas.
*/
void setPrimaryContentSize(in long width, in long height);
/*
Gets the size of the root docshell in device pixels.
Gets the size of the root docshell in CSS pixels.
*/
void getRootShellSize(out long width, out long height);
/*
Sets the size of the root docshell in device pixels.
Sets the size of the root docshell in CSS pixels.
*/
void setRootShellSize(in long width, in long height);

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

@ -133,6 +133,7 @@
#include "mozilla/dom/Document.h"
#include "Crypto.h"
#include "nsDOMString.h"
#include "nsIEmbeddingSiteWindow.h"
#include "nsThreadUtils.h"
#include "nsILoadContext.h"
#include "nsIScrollableFrame.h"
@ -3526,66 +3527,40 @@ nsresult nsGlobalWindowOuter::GetInnerWidth(double* aInnerWidth) {
FORWARD_TO_INNER(GetInnerWidth, (aInnerWidth), NS_ERROR_UNEXPECTED);
}
void nsGlobalWindowOuter::SetInnerSize(int32_t aLengthCSSPixels, bool aIsWidth,
mozilla::dom::CallerType aCallerType,
mozilla::ErrorResult& aError) {
void nsGlobalWindowOuter::SetInnerWidthOuter(double aInnerWidth,
CallerType aCallerType,
ErrorResult& aError) {
if (!mDocShell) {
aError.Throw(NS_ERROR_UNEXPECTED);
return;
}
CSSIntCoord length(aLengthCSSPixels);
CheckSecurityWidthAndHeight((aIsWidth ? &length.value : nullptr),
(aIsWidth ? nullptr : &length.value),
aCallerType);
// We only allow setting integers, for now.
int32_t value = std::round(ToZeroIfNonfinite(aInnerWidth));
CheckSecurityWidthAndHeight(&value, nullptr, aCallerType);
RefPtr<PresShell> presShell = mDocShell->GetPresShell();
// Setting inner size should set the CSS viewport. If the CSS viewport
// Setting inner width should set the CSS viewport. If the CSS viewport
// has been overridden, change the override.
if (presShell && presShell->UsesMobileViewportSizing()) {
nscoord height = 0;
RefPtr<nsPresContext> presContext;
presContext = presShell->GetPresContext();
nsRect shellArea = presContext->GetVisibleArea();
if (aIsWidth) {
shellArea.width = CSSPixel::ToAppUnits(CSSCoord(length));
} else {
shellArea.height = CSSPixel::ToAppUnits(CSSCoord(length));
}
SetCSSViewportWidthAndHeight(shellArea.Width(), shellArea.Height());
height = shellArea.Height();
SetCSSViewportWidthAndHeight(CSSPixel::ToAppUnits(value), height);
return;
}
nsCOMPtr<nsIBaseWindow> treeOwnerAsWin = GetTreeOwnerWindow();
if (!treeOwnerAsWin) {
aError.Throw(NS_ERROR_FAILURE);
return;
}
auto scale = CSSToDevScaleForBaseWindow(treeOwnerAsWin);
LayoutDeviceIntCoord valueDev = (CSSCoord(length) * scale).Rounded();
Maybe<LayoutDeviceIntCoord> width, height;
if (aIsWidth) {
width.emplace(valueDev);
} else {
height.emplace(valueDev);
}
aError = treeOwnerAsWin->SetDimensions(
{DimensionKind::Inner, Nothing(), Nothing(), width, height});
CheckForDPIChange();
}
void nsGlobalWindowOuter::SetInnerWidthOuter(double aInnerWidth,
CallerType aCallerType,
ErrorResult& aError) {
SetInnerSize(NSToIntRound(ToZeroIfNonfinite(aInnerWidth)),
/* aIsWidth */ true, aCallerType, aError);
// Nothing has been overridden, so change the docshell itself.
nsCOMPtr<nsIBaseWindow> docShellAsWin(do_QueryInterface(mDocShell));
LayoutDeviceIntSize size = docShellAsWin->GetSize();
size.width =
(CSSCoord(value) * CSSToDevScaleForBaseWindow(docShellAsWin)).Rounded();
aError = SetDocShellSize(size);
}
double nsGlobalWindowOuter::GetInnerHeightOuter(ErrorResult& aError) {
@ -3601,8 +3576,35 @@ nsresult nsGlobalWindowOuter::GetInnerHeight(double* aInnerHeight) {
void nsGlobalWindowOuter::SetInnerHeightOuter(double aInnerHeight,
CallerType aCallerType,
ErrorResult& aError) {
SetInnerSize(NSToIntRound(ToZeroIfNonfinite(aInnerHeight)),
/* aIsWidth */ false, aCallerType, aError);
if (!mDocShell) {
aError.Throw(NS_ERROR_UNEXPECTED);
return;
}
int32_t value = std::round(ToZeroIfNonfinite(aInnerHeight));
CheckSecurityWidthAndHeight(nullptr, &value, aCallerType);
RefPtr<PresShell> presShell = mDocShell->GetPresShell();
// Setting inner height should set the CSS viewport. If the CSS viewport
// has been overridden, change the override.
if (presShell && presShell->UsesMobileViewportSizing()) {
nscoord width = 0;
RefPtr<nsPresContext> presContext;
presContext = presShell->GetPresContext();
nsRect shellArea = presContext->GetVisibleArea();
width = shellArea.Width();
SetCSSViewportWidthAndHeight(width, CSSPixel::ToAppUnits(value));
return;
}
// Nothing has been overriden, so change the docshell itself.
nsCOMPtr<nsIBaseWindow> docShellAsWin(do_QueryInterface(mDocShell));
LayoutDeviceIntSize size = docShellAsWin->GetSize();
size.height =
(CSSCoord(value) * CSSToDevScaleForBaseWindow(docShellAsWin)).Rounded();
aError = SetDocShellSize(size);
}
CSSIntSize nsGlobalWindowOuter::GetOuterSize(CallerType aCallerType,
@ -3655,19 +3657,11 @@ void nsGlobalWindowOuter::SetOuterSize(int32_t aLengthCSSPixels, bool aIsWidth,
aIsWidth ? nullptr : &aLengthCSSPixels,
aCallerType);
LayoutDeviceIntSize size = treeOwnerAsWin->GetSize();
auto scale = CSSToDevScaleForBaseWindow(treeOwnerAsWin);
LayoutDeviceIntCoord value =
(CSSCoord(CSSIntCoord(aLengthCSSPixels)) * scale).Rounded();
Maybe<LayoutDeviceIntCoord> width, height;
if (aIsWidth) {
width.emplace(value);
} else {
height.emplace(value);
}
aError = treeOwnerAsWin->SetDimensions(
{DimensionKind::Outer, Nothing(), Nothing(), width, height});
(aIsWidth ? size.width : size.height) =
(CSSCoord(aLengthCSSPixels) * scale).Rounded();
aError = treeOwnerAsWin->SetSize(size.width, size.height, true);
CheckForDPIChange();
}
@ -3798,41 +3792,27 @@ float nsGlobalWindowOuter::GetMozInnerScreenYOuter(CallerType aCallerType) {
return nsPresContext::AppUnitsToFloatCSSPixels(r.y);
}
void nsGlobalWindowOuter::SetScreenCoord(int32_t aCoordCSSPixels, bool aIsX,
CallerType aCallerType,
ErrorResult& aError) {
void nsGlobalWindowOuter::SetScreenXOuter(int32_t aScreenX,
CallerType aCallerType,
ErrorResult& aError) {
nsCOMPtr<nsIBaseWindow> treeOwnerAsWin = GetTreeOwnerWindow();
if (!treeOwnerAsWin) {
aError.Throw(NS_ERROR_FAILURE);
return;
}
CheckSecurityLeftAndTop(aIsX ? &aCoordCSSPixels : nullptr,
aIsX ? nullptr : &aCoordCSSPixels, aCallerType);
LayoutDeviceIntPoint pos = treeOwnerAsWin->GetPosition();
auto scale = CSSToDevScaleForBaseWindow(treeOwnerAsWin);
LayoutDeviceIntCoord coord =
(CSSCoord(CSSIntCoord(aCoordCSSPixels)) * scale).Rounded();
CheckSecurityLeftAndTop(&aScreenX, nullptr, aCallerType);
Maybe<LayoutDeviceIntCoord> x, y;
if (aIsX) {
x.emplace(coord);
} else {
y.emplace(coord);
}
pos.x = (CSSCoord(aScreenX) * CSSToDevScaleForBaseWindow(treeOwnerAsWin))
.Rounded();
aError = treeOwnerAsWin->SetDimensions(
{DimensionKind::Outer, x, y, Nothing(), Nothing()});
aError = treeOwnerAsWin->SetPosition(pos.x, pos.y);
CheckForDPIChange();
}
void nsGlobalWindowOuter::SetScreenXOuter(int32_t aScreenX,
CallerType aCallerType,
ErrorResult& aError) {
SetScreenCoord(aScreenX, /* aIsX */ true, aCallerType, aError);
}
int32_t nsGlobalWindowOuter::GetScreenYOuter(CallerType aCallerType,
ErrorResult& aError) {
return GetScreenXY(aCallerType, aError).y;
@ -3841,7 +3821,19 @@ int32_t nsGlobalWindowOuter::GetScreenYOuter(CallerType aCallerType,
void nsGlobalWindowOuter::SetScreenYOuter(int32_t aScreenY,
CallerType aCallerType,
ErrorResult& aError) {
SetScreenCoord(aScreenY, /* aIsX */ false, aCallerType, aError);
nsCOMPtr<nsIBaseWindow> treeOwnerAsWin = GetTreeOwnerWindow();
if (!treeOwnerAsWin) {
aError.Throw(NS_ERROR_FAILURE);
return;
}
LayoutDeviceIntPoint pos = treeOwnerAsWin->GetPosition();
CheckSecurityLeftAndTop(nullptr, &aScreenY, aCallerType);
pos.y = (CSSCoord(aScreenY) * CSSToDevScaleForBaseWindow(treeOwnerAsWin))
.Rounded();
aError = treeOwnerAsWin->SetPosition(pos.x, pos.y);
CheckForDPIChange();
}
// NOTE: Arguments to this function should have values scaled to
@ -3870,6 +3862,22 @@ void nsGlobalWindowOuter::CheckSecurityWidthAndHeight(int32_t* aWidth,
}
}
// NOTE: Arguments to this function should have values in device pixels
nsresult nsGlobalWindowOuter::SetDocShellSize(
const LayoutDeviceIntSize& aSize) {
NS_ENSURE_TRUE(mDocShell, NS_ERROR_FAILURE);
nsCOMPtr<nsIDocShell> docShell = mDocShell;
nsCOMPtr<nsIDocShellTreeOwner> treeOwner;
docShell->GetTreeOwner(getter_AddRefs(treeOwner));
NS_ENSURE_TRUE(treeOwner, NS_ERROR_FAILURE);
NS_ENSURE_SUCCESS(treeOwner->SizeShellTo(docShell, aSize.width, aSize.height),
NS_ERROR_FAILURE);
return NS_OK;
}
// NOTE: Arguments to this function should have values in app units
void nsGlobalWindowOuter::SetCSSViewportWidthAndHeight(nscoord aInnerWidth,
nscoord aInnerHeight) {
@ -5024,9 +5032,27 @@ void nsGlobalWindowOuter::BlurOuter(CallerType aCallerType) {
return;
}
nsCOMPtr<nsIWebBrowserChrome> chrome = GetWebBrowserChrome();
if (chrome) {
chrome->Blur();
// If embedding apps don't implement nsIEmbeddingSiteWindow, we
// shouldn't throw exceptions to web content.
nsCOMPtr<nsIDocShellTreeOwner> treeOwner = GetTreeOwner();
nsCOMPtr<nsIEmbeddingSiteWindow> siteWindow(do_GetInterface(treeOwner));
if (siteWindow) {
// This method call may cause mDocShell to become nullptr.
siteWindow->Blur();
// if the root is focused, clear the focus
if (mDoc) {
if (RefPtr<nsFocusManager> fm = nsFocusManager::GetFocusManager()) {
RefPtr<Element> element;
fm->GetFocusedElementForWindow(this, false, nullptr,
getter_AddRefs(element));
if (element == mDoc->GetRootElement()) {
OwningNonNull<nsGlobalWindowOuter> kungFuDeathGrip(*this);
fm->ClearFocus(kungFuDeathGrip);
}
}
}
}
}

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

@ -687,7 +687,7 @@ class nsGlobalWindowOuter final : public mozilla::dom::EventTarget,
double GetInnerWidthOuter(mozilla::ErrorResult& aError);
protected:
nsresult GetInnerWidth(double* aInnerWidth) override;
nsresult GetInnerWidth(double* aWidth) override;
void SetInnerWidthOuter(double aInnerWidth,
mozilla::dom::CallerType aCallerType,
mozilla::ErrorResult& aError);
@ -696,7 +696,7 @@ class nsGlobalWindowOuter final : public mozilla::dom::EventTarget,
double GetInnerHeightOuter(mozilla::ErrorResult& aError);
protected:
nsresult GetInnerHeight(double* aInnerHeight) override;
nsresult GetInnerHeight(double* aHeight) override;
void SetInnerHeightOuter(double aInnerHeight,
mozilla::dom::CallerType aCallerType,
mozilla::ErrorResult& aError);
@ -830,6 +830,9 @@ class nsGlobalWindowOuter final : public mozilla::dom::EventTarget,
// Outer windows only.
// Arguments to this function should have values in app units
void SetCSSViewportWidthAndHeight(nscoord width, nscoord height);
// Arguments to this function should have values in device pixels
MOZ_CAN_RUN_SCRIPT_BOUNDARY
nsresult SetDocShellSize(const mozilla::LayoutDeviceIntSize& aInnerSize);
static bool CanSetProperty(const char* aPrefName);
@ -858,12 +861,6 @@ class nsGlobalWindowOuter final : public mozilla::dom::EventTarget,
void SetOuterSize(int32_t aLengthCSSPixels, bool aIsWidth,
mozilla::dom::CallerType aCallerType,
mozilla::ErrorResult& aError);
void SetInnerSize(int32_t aLengthCSSPixels, bool aIsWidth,
mozilla::dom::CallerType aCallerType,
mozilla::ErrorResult& aError);
void SetScreenCoord(int32_t aCoordCSSPixels, bool aIsX,
mozilla::dom::CallerType aCallerType,
mozilla::ErrorResult& aError);
nsRect GetInnerScreenRect();
static mozilla::Maybe<mozilla::CSSIntSize> GetRDMDeviceSize(
const Document& aDocument);

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

@ -22,6 +22,9 @@ interface nsIBrowserChild : nsISupports
[notxpcom] void sendRequestFocus(in boolean canFocus, in CallerType aCallerType);
[noscript] void remoteSizeShellTo(in int32_t width, in int32_t height,
in int32_t shellItemWidth, in int32_t shellItemHeight);
void remoteDropLinks(in Array<nsIDroppedLinkItem> links);
/**

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

@ -548,6 +548,7 @@ NS_IMPL_CYCLE_COLLECTION_TRACE_END
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(BrowserChild)
NS_INTERFACE_MAP_ENTRY(nsIWebBrowserChrome)
NS_INTERFACE_MAP_ENTRY(nsIEmbeddingSiteWindow)
NS_INTERFACE_MAP_ENTRY(nsIWebBrowserChromeFocus)
NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor)
NS_INTERFACE_MAP_ENTRY(nsIWindowProvider)
@ -576,6 +577,32 @@ BrowserChild::SetChromeFlags(uint32_t aChromeFlags) {
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
BrowserChild::RemoteSizeShellTo(int32_t aWidth, int32_t aHeight,
int32_t aShellItemWidth,
int32_t aShellItemHeight) {
nsCOMPtr<nsIDocShell> ourDocShell = do_GetInterface(WebNavigation());
nsCOMPtr<nsIBaseWindow> docShellAsWin(do_QueryInterface(ourDocShell));
NS_ENSURE_STATE(docShellAsWin);
int32_t width, height;
docShellAsWin->GetSize(&width, &height);
uint32_t flags = 0;
if (width == aWidth) {
flags |= nsIEmbeddingSiteWindow::DIM_FLAGS_IGNORE_CX;
}
if (height == aHeight) {
flags |= nsIEmbeddingSiteWindow::DIM_FLAGS_IGNORE_CY;
}
bool sent = SendSizeShellTo(flags, aWidth, aHeight, aShellItemWidth,
aShellItemHeight);
return sent ? NS_OK : NS_ERROR_FAILURE;
}
NS_IMETHODIMP
BrowserChild::RemoteDropLinks(
const nsTArray<RefPtr<nsIDroppedLinkItem>>& aLinks) {
@ -629,32 +656,47 @@ BrowserChild::SetLinkStatus(const nsAString& aStatusText) {
}
NS_IMETHODIMP
BrowserChild::SetDimensions(DimensionRequest&& aRequest) {
BrowserChild::SetDimensions(uint32_t aFlags, int32_t aX, int32_t aY,
int32_t aCx, int32_t aCy) {
// The parent is in charge of the dimension changes. If JS code wants to
// change the dimensions (moveTo, screenX, etc.) we send a message to the
// parent about the new requested dimension, the parent does the resize/move
// then send a message to the child to update itself. For APIs like screenX
// this function is called with only the changed values. In a series of calls
// like window.screenX = 10; window.screenY = 10; for the second call, since
// screenX is not yet updated we might accidentally reset back screenX to it's
// old value. To avoid this, if a parameter did not change, we want the parent
// to handle the unchanged values.
// this function is called with the current value for the non-changed values.
// In a series of calls like window.screenX = 10; window.screenY = 10; for
// the second call, since screenX is not yet updated we might accidentally
// reset back screenX to it's old value. To avoid this if a parameter did not
// change we want the parent to ignore its value.
int32_t x, y, cx, cy;
GetDimensions(aFlags, &x, &y, &cx, &cy);
if (x == aX) {
aFlags |= nsIEmbeddingSiteWindow::DIM_FLAGS_IGNORE_X;
}
if (y == aY) {
aFlags |= nsIEmbeddingSiteWindow::DIM_FLAGS_IGNORE_Y;
}
if (cx == aCx) {
aFlags |= nsIEmbeddingSiteWindow::DIM_FLAGS_IGNORE_CX;
}
if (cy == aCy) {
aFlags |= nsIEmbeddingSiteWindow::DIM_FLAGS_IGNORE_CY;
}
double scale = mPuppetWidget ? mPuppetWidget->GetDefaultScale().scale : 1.0;
SendSetDimensions(aRequest, scale);
Unused << SendSetDimensions(aFlags, aX, aY, aCx, aCy, scale);
return NS_OK;
}
NS_IMETHODIMP
BrowserChild::GetDimensions(DimensionKind aDimensionKind, int32_t* aX,
int32_t* aY, int32_t* aCx, int32_t* aCy) {
BrowserChild::GetDimensions(uint32_t aFlags, int32_t* aX, int32_t* aY,
int32_t* aCx, int32_t* aCy) {
ScreenIntRect rect = GetOuterRect();
if (aDimensionKind == DimensionKind::Inner) {
if (aX || aY) {
return NS_ERROR_NOT_IMPLEMENTED;
}
rect.SizeTo(GetInnerSize());
}
if (aX) {
*aX = rect.x;
}
@ -667,9 +709,43 @@ BrowserChild::GetDimensions(DimensionKind aDimensionKind, int32_t* aX,
if (aCy) {
*aCy = rect.height;
}
return NS_OK;
}
NS_IMETHODIMP
BrowserChild::GetVisibility(bool* aVisibility) {
*aVisibility = true;
return NS_OK;
}
NS_IMETHODIMP
BrowserChild::SetVisibility(bool aVisibility) {
// should the platform support this? Bug 666365
return NS_OK;
}
NS_IMETHODIMP
BrowserChild::GetTitle(nsAString& aTitle) {
NS_WARNING("BrowserChild::GetTitle not supported in BrowserChild");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
BrowserChild::SetTitle(const nsAString& aTitle) {
// JavaScript sends the "DOMTitleChanged" event to the parent
// via the message manager.
return NS_OK;
}
NS_IMETHODIMP
BrowserChild::GetSiteWindow(void** aSiteWindow) {
NS_WARNING("BrowserChild::GetSiteWindow not supported in BrowserChild");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
BrowserChild::Blur() { return NS_ERROR_NOT_IMPLEMENTED; }
@ -3197,7 +3273,7 @@ mozilla::ipc::IPCResult BrowserChild::RecvSafeAreaInsetsChanged(
// aSafeAreaInsets is for current screen. But we have to calculate
// safe insets for content window.
int32_t x, y, cx, cy;
GetDimensions(DimensionKind::Outer, &x, &y, &cx, &cy);
GetDimensions(0, &x, &y, &cx, &cy);
nsCOMPtr<nsIScreen> screen;
screenMgr->ScreenForRect(x, y, cx, cy, getter_AddRefs(screen));

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

@ -12,6 +12,7 @@
#include "nsIWebNavigation.h"
#include "nsCOMPtr.h"
#include "nsIWebBrowserChrome.h"
#include "nsIEmbeddingSiteWindow.h"
#include "nsIWebBrowserChromeFocus.h"
#include "nsIDOMEventListener.h"
#include "nsIInterfaceRequestor.h"
@ -140,6 +141,7 @@ class BrowserChild final : public nsMessageManagerScriptExecutor,
public ipc::MessageManagerCallback,
public PBrowserChild,
public nsIWebBrowserChrome,
public nsIEmbeddingSiteWindow,
public nsIWebBrowserChromeFocus,
public nsIInterfaceRequestor,
public nsIWindowProvider,
@ -197,6 +199,7 @@ class BrowserChild final : public nsMessageManagerScriptExecutor,
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_NSIWEBBROWSERCHROME
NS_DECL_NSIEMBEDDINGSITEWINDOW
NS_DECL_NSIWEBBROWSERCHROMEFOCUS
NS_DECL_NSIINTERFACEREQUESTOR
NS_DECL_NSIWINDOWPROVIDER

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

@ -809,6 +809,37 @@ mozilla::ipc::IPCResult BrowserParent::RecvMoveFocus(
return IPC_OK();
}
mozilla::ipc::IPCResult BrowserParent::RecvSizeShellTo(
const uint32_t& aFlags, const int32_t& aWidth, const int32_t& aHeight,
const int32_t& aShellItemWidth, const int32_t& aShellItemHeight) {
NS_ENSURE_TRUE(mFrameElement, IPC_OK());
nsCOMPtr<nsIDocShell> docShell = mFrameElement->OwnerDoc()->GetDocShell();
NS_ENSURE_TRUE(docShell, IPC_OK());
nsCOMPtr<nsIDocShellTreeOwner> treeOwner;
nsresult rv = docShell->GetTreeOwner(getter_AddRefs(treeOwner));
NS_ENSURE_SUCCESS(rv, IPC_OK());
int32_t width = aWidth;
int32_t height = aHeight;
if (aFlags & nsIEmbeddingSiteWindow::DIM_FLAGS_IGNORE_CX) {
width = mDimensions.width;
}
if (aFlags & nsIEmbeddingSiteWindow::DIM_FLAGS_IGNORE_CY) {
height = mDimensions.height;
}
nsCOMPtr<nsIAppWindow> appWin(do_GetInterface(treeOwner));
NS_ENSURE_TRUE(appWin, IPC_OK());
appWin->SizeShellToWithLimit(width, height, aShellItemWidth,
aShellItemHeight);
return IPC_OK();
}
mozilla::ipc::IPCResult BrowserParent::RecvDropLinks(
nsTArray<nsString>&& aLinks) {
nsCOMPtr<nsIBrowser> browser =
@ -946,7 +977,11 @@ bool BrowserParent::Show(const OwnerShowInfo& aOwnerInfo) {
}
mozilla::ipc::IPCResult BrowserParent::RecvSetDimensions(
mozilla::DimensionRequest aRequest, const double& aScale) {
const uint32_t& aFlags, const int32_t& aX, const int32_t& aY,
const int32_t& aCx, const int32_t& aCy, const double& aScale) {
MOZ_ASSERT(!(aFlags & nsIEmbeddingSiteWindow::DIM_FLAGS_SIZE_INNER),
"We should never see DIM_FLAGS_SIZE_INNER here!");
NS_ENSURE_TRUE(mFrameElement, IPC_OK());
nsCOMPtr<nsIDocShell> docShell = mFrameElement->OwnerDoc()->GetDocShell();
NS_ENSURE_TRUE(docShell, IPC_OK());
@ -955,8 +990,8 @@ mozilla::ipc::IPCResult BrowserParent::RecvSetDimensions(
nsCOMPtr<nsIBaseWindow> treeOwnerAsWin = do_QueryInterface(treeOwner);
NS_ENSURE_TRUE(treeOwnerAsWin, IPC_OK());
// `BrowserChild` only sends the values to actually be changed, see more
// details in `BrowserChild::SetDimensions()`.
// We only care about the parameters that actually changed, see more details
// in `BrowserChild::SetDimensions()`.
// Note that `BrowserChild::SetDimensions()` may be called before receiving
// our `SendUIResolutionChanged()` call. Therefore, if given each coordinate
// shouldn't be ignored, we need to recompute it if DPI has been changed.
@ -965,26 +1000,64 @@ mozilla::ipc::IPCResult BrowserParent::RecvSetDimensions(
// NOTE(emilio): We use GetWidgetCSSToDeviceScale() because the old scale is a
// widget scale, and we only use the current scale to scale up/down the
// relevant values.
double currentScale = treeOwnerAsWin->GetWidgetCSSToDeviceScale();
CSSToLayoutDeviceScale oldScale((float)aScale);
CSSToLayoutDeviceScale currentScale(
(float)treeOwnerAsWin->GetWidgetCSSToDeviceScale());
int32_t x = aX;
int32_t y = aY;
if (aFlags & nsIEmbeddingSiteWindow::DIM_FLAGS_POSITION) {
if (aFlags & nsIEmbeddingSiteWindow::DIM_FLAGS_IGNORE_X) {
int32_t unused;
treeOwnerAsWin->GetPosition(&x, &unused);
} else if (aScale != currentScale) {
x = x * currentScale / aScale;
}
if (oldScale != currentScale) {
auto rescaleFunc = [&oldScale, &currentScale](LayoutDeviceIntCoord& aVal) {
aVal = (LayoutDeviceCoord(aVal) / oldScale * currentScale).Rounded();
};
aRequest.mX.apply(rescaleFunc);
aRequest.mY.apply(rescaleFunc);
aRequest.mWidth.apply(rescaleFunc);
aRequest.mHeight.apply(rescaleFunc);
if (aFlags & nsIEmbeddingSiteWindow::DIM_FLAGS_IGNORE_Y) {
int32_t unused;
treeOwnerAsWin->GetPosition(&unused, &y);
} else if (aScale != currentScale) {
y = y * currentScale / aScale;
}
}
// treeOwner is the chrome tree owner, but we wan't the content tree owner.
nsCOMPtr<nsIWebBrowserChrome> webBrowserChrome = do_GetInterface(treeOwner);
NS_ENSURE_TRUE(webBrowserChrome, IPC_OK());
webBrowserChrome->SetDimensions(std::move(aRequest));
return IPC_OK();
int32_t cx = aCx;
int32_t cy = aCy;
if (aFlags & nsIEmbeddingSiteWindow::DIM_FLAGS_SIZE_OUTER) {
if (aFlags & nsIEmbeddingSiteWindow::DIM_FLAGS_IGNORE_CX) {
int32_t unused;
treeOwnerAsWin->GetSize(&cx, &unused);
} else if (aScale != currentScale) {
cx = cx * currentScale / aScale;
}
if (aFlags & nsIEmbeddingSiteWindow::DIM_FLAGS_IGNORE_CY) {
int32_t unused;
treeOwnerAsWin->GetSize(&unused, &cy);
} else if (aScale != currentScale) {
cy = cy * currentScale / aScale;
}
}
if (aFlags & nsIEmbeddingSiteWindow::DIM_FLAGS_POSITION &&
aFlags & nsIEmbeddingSiteWindow::DIM_FLAGS_SIZE_OUTER) {
treeOwnerAsWin->SetPositionAndSize(x, y, cx, cy, nsIBaseWindow::eRepaint);
return IPC_OK();
}
if (aFlags & nsIEmbeddingSiteWindow::DIM_FLAGS_POSITION) {
treeOwnerAsWin->SetPosition(x, y);
mUpdatedDimensions = false;
UpdatePosition();
return IPC_OK();
}
if (aFlags & nsIEmbeddingSiteWindow::DIM_FLAGS_SIZE_OUTER) {
treeOwnerAsWin->SetSize(cx, cy, true);
return IPC_OK();
}
MOZ_ASSERT(false, "Unknown flags!");
return IPC_FAIL_NO_REASON(this);
}
nsresult BrowserParent::UpdatePosition() {

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

@ -265,6 +265,12 @@ class BrowserParent final : public PBrowserParent,
mozilla::ipc::IPCResult RecvMoveFocus(const bool& aForward,
const bool& aForDocumentNavigation);
mozilla::ipc::IPCResult RecvSizeShellTo(const uint32_t& aFlags,
const int32_t& aWidth,
const int32_t& aHeight,
const int32_t& aShellItemWidth,
const int32_t& aShellItemHeight);
mozilla::ipc::IPCResult RecvDropLinks(nsTArray<nsString>&& aLinks);
// TODO: Use MOZ_CAN_RUN_SCRIPT when it gains IPDL support (bug 1539864)
@ -730,8 +736,9 @@ class BrowserParent final : public PBrowserParent,
mozilla::ipc::IPCResult RecvPaintWhileInterruptingJSNoOp(
const LayersObserverEpoch& aEpoch);
mozilla::ipc::IPCResult RecvSetDimensions(mozilla::DimensionRequest aRequest,
const double& aScale);
mozilla::ipc::IPCResult RecvSetDimensions(
const uint32_t& aFlags, const int32_t& aX, const int32_t& aY,
const int32_t& aCx, const int32_t& aCy, const double& aScale);
mozilla::ipc::IPCResult RecvShowCanvasPermissionPrompt(
const nsCString& aOrigin, const bool& aHideDoorHanger);

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

@ -83,7 +83,6 @@ using nsIWidget::TouchPointerState from "nsIWidget.h";
using nsIWidget::TouchpadGesturePhase from "nsIWidget.h";
using nsCursor from "nsIWidget.h";
using struct LookAndFeelInt from "mozilla/widget/WidgetMessageUtils.h";
using struct mozilla::DimensionRequest from "mozilla/widget/WidgetMessageUtils.h";
using class mozilla::dom::MessagePort from "mozilla/dom/MessagePort.h";
using class mozilla::dom::ipc::StructuredCloneData from "mozilla/dom/ipc/StructuredCloneData.h";
using mozilla::dom::MaybeDiscardedWindowContext from "mozilla/dom/WindowContext.h";
@ -242,6 +241,21 @@ parent:
*/
async MoveFocus(bool forward, bool forDocumentNavigation);
/**
* SizeShellTo request propagation to parent.
*
* aFlag Can indicate if one of the dimensions should be ignored.
* If only one dimension has changed it has to be indicated
* by the nsIEmbeddingSiteWindow::DIM_FLAGS_IGNORE_* flags.
* aShellItemWidth,
* aShellItemHeight On parent side we won't be able to decide the dimensions
* of the shell item parameter in the original SizeShellTo
* call so we send over its dimensions that will be used
* for the actual resize.
**/
async SizeShellTo(uint32_t aFlag, int32_t aWidth, int32_t aHeight,
int32_t aShellItemWidth, int32_t aShellItemHeight);
/**
* Called by the child to inform the parent that links are dropped into
* content area.
@ -608,14 +622,10 @@ parent:
/**
* Sent by the child to the parent to inform it that an update to the
* dimensions has been requested.
*
* @param aRequest The requested change of inner or outer dimensions.
* @param aScale The scale at the time of the request. This is to allow
* the parent to recompute the dimensions in case of an
* ongoing scale change.
* dimensions has been requested, likely through win.moveTo or resizeTo
*/
async SetDimensions(DimensionRequest aRequest, double aScale);
async SetDimensions(uint32_t aFlags, int32_t aX, int32_t aY,
int32_t aCx, int32_t aCy, double aScale);
[Nested=inside_sync] sync DispatchWheelEvent(WidgetWheelEvent event);
[Nested=inside_sync] sync DispatchMouseEvent(WidgetMouseEvent event);

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

@ -10,6 +10,7 @@ with Files("**"):
DIRS += ["build"]
XPIDL_SOURCES += [
"nsIEmbeddingSiteWindow.idl",
"nsIWebBrowser.idl",
"nsIWebBrowserChrome.idl",
"nsIWebBrowserChromeFocus.idl",

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

@ -0,0 +1,152 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsISupports.idl"
/* THIS IS A PUBLIC EMBEDDING API */
/**
* The nsIEmbeddingSiteWindow is implemented by the embedder to provide
* Gecko with the means to call up to the host to resize the window,
* hide or show it and set/get its title.
*/
[scriptable, uuid(0b976267-4aaa-4f36-a2d4-27b5ca8d73bb)]
interface nsIEmbeddingSiteWindow : nsISupports
{
/**
* Flag indicates that position of the top left corner of the outer area
* is required/specified.
*
* @see setDimensions
* @see getDimensions
*/
const unsigned long DIM_FLAGS_POSITION = 1;
/**
* Flag indicates that the size of the inner area is required/specified.
*
* @note The inner and outer flags are mutually exclusive and it is
* invalid to combine them.
*
* @see setDimensions
* @see getDimensions
* @see DIM_FLAGS_SIZE_OUTER
*/
const unsigned long DIM_FLAGS_SIZE_INNER = 2;
/**
* Flag indicates that the size of the outer area is required/specified.
*
* @see setDimensions
* @see getDimensions
* @see DIM_FLAGS_SIZE_INNER
*/
const unsigned long DIM_FLAGS_SIZE_OUTER = 4;
/**
* Flag indicates that the x parameter should be ignored.
*
* @see setDimensions
*/
const unsigned long DIM_FLAGS_IGNORE_X = 8;
/**
* Flag indicates that the y parameter should be ignored.
*
* @see setDimensions
*/
const unsigned long DIM_FLAGS_IGNORE_Y = 16;
/**
* Flag indicates that the cx parameter should be ignored.
*
* @see setDimensions
*/
const unsigned long DIM_FLAGS_IGNORE_CX = 32;
/**
* Flag indicates that the cy parameter should be ignored.
*
* @see setDimensions
*/
const unsigned long DIM_FLAGS_IGNORE_CY = 64;
/**
* Sets the dimensions for the window; the position & size. The
* flags to indicate what the caller wants to set and whether the size
* refers to the inner or outer area. The inner area refers to just
* the embedded area, wheras the outer area can also include any
* surrounding chrome, window frame, title bar, and so on.
*
* @param flags Combination of position, inner and outer size flags.
* The ignore flags are telling the parent to use the
* current values for those dimensions and ignore the
* corresponding parameters the child sends.
* @param x Left hand corner of the outer area.
* @param y Top corner of the outer area.
* @param cx Width of the inner or outer area.
* @param cy Height of the inner or outer area.
*
* @return <code>NS_OK</code> if operation was performed correctly;
* <code>NS_ERROR_UNEXPECTED</code> if window could not be
* destroyed;
* <code>NS_ERROR_INVALID_ARG</code> for bad flag combination
* or illegal dimensions.
*
* @see getDimensions
* @see DIM_FLAGS_POSITION
* @see DIM_FLAGS_SIZE_OUTER
* @see DIM_FLAGS_SIZE_INNER
*/
void setDimensions(in unsigned long flags, in long x, in long y, in long cx, in long cy);
/**
* Gets the dimensions of the window. The caller may pass
* <CODE>nullptr</CODE> for any value it is uninterested in receiving.
*
* @param flags Combination of position, inner and outer size flag .
* @param x Left hand corner of the outer area; or <CODE>nullptr</CODE>.
* @param y Top corner of the outer area; or <CODE>nullptr</CODE>.
* @param cx Width of the inner or outer area; or <CODE>nullptr</CODE>.
* @param cy Height of the inner or outer area; or <CODE>nullptr</CODE>.
*
* @see setDimensions
* @see DIM_FLAGS_POSITION
* @see DIM_FLAGS_SIZE_OUTER
* @see DIM_FLAGS_SIZE_INNER
*/
void getDimensions(in unsigned long flags, out long x, out long y, out long cx, out long cy);
/**
* Visibility of the window.
*/
attribute boolean visibility;
/**
* Title of the window.
*/
attribute AString title;
/**
* Native window for the site's window. The implementor should copy the
* native window object into the address supplied by the caller. The
* type of the native window that the address refers to is platform
* and OS specific as follows:
*
* <ul>
* <li>On Win32 it is an <CODE>HWND</CODE>.</li>
* <li>On MacOS this is a <CODE>WindowPtr</CODE>.</li>
* <li>On GTK this is a <CODE>GtkWidget*</CODE>.</li>
* </ul>
*/
[noscript] readonly attribute voidPtr siteWindow;
/**
* Blur the window. This should unfocus the window and send an onblur event.
*/
void blur();
};

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

@ -37,6 +37,8 @@ interface nsIWebBrowser : nsISupports
* this property to point to the chrome object before creating the browser
* window via the browser's <CODE>nsIBaseWindow</CODE> interface.
*
* The chrome object must also implement <CODE>nsIEmbeddingSiteWindow</CODE>.
*
* The chrome may optionally implement <CODE>nsIInterfaceRequestor</CODE>,
* <CODE>nsIWebBrowserChromeFocus</CODE>,
* <CODE>nsIContextMenuListener</CODE> and
@ -56,6 +58,7 @@ interface nsIWebBrowser : nsISupports
*
* @see nsIBaseWindow
* @see nsIWebBrowserChrome
* @see nsIEmbeddingSiteWindow
* @see nsIInterfaceRequestor
* @see nsIWebBrowserChromeFocus
* @see nsIContextMenuListener

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

@ -5,7 +5,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsISupports.idl"
#include "nsIBaseWindow.idl"
interface nsIWebBrowser;
interface nsIDocShellTreeItem;
@ -114,29 +113,4 @@ interface nsIWebBrowserChrome : nsISupports
* @return true if it's a modal window
*/
boolean isWindowModal();
/**
* Allows to request the change of individual dimensions of a window
* without specifying all dimensions.
*
* Gets called as fallback when no nsIBaseWindow is available.
*
* @see nsIBaseWindow
*/
void setDimensions(in DimensionRequest aRequest);
/**
* Gets the dimensions of the window. The caller may pass
* <CODE>nullptr</CODE> for any value it is uninterested in receiving.
*
* Gets called as fallback when no nsIBaseWindow is available.
*
* @see nsIBaseWindow
*/
void getDimensions(in DimensionKind aDimensionKind, out long aX, out long aY, out long aCX, out long aCY);
/**
* Blur the window. This should unfocus the window and send an onblur event.
*/
void blur();
};

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

@ -956,22 +956,12 @@ nsWebBrowser::GetPositionAndSize(int32_t* aX, int32_t* aY, int32_t* aCX,
*aCY = bounds.Height();
}
return NS_OK;
} else {
// Can directly return this as it is the
// same interface, thus same returns.
return mDocShell->GetPositionAndSize(aX, aY, aCX, aCY);
}
// Can directly return this as it is the
// same interface, thus same returns.
return mDocShell->GetPositionAndSize(aX, aY, aCX, aCY);
}
NS_IMETHODIMP
nsWebBrowser::SetDimensions(DimensionRequest&& aRequest) {
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsWebBrowser::GetDimensions(DimensionKind aDimensionKind, int32_t* aX,
int32_t* aY, int32_t* aCX, int32_t* aCY) {
return NS_ERROR_NOT_IMPLEMENTED;
return NS_OK;
}
NS_IMETHODIMP

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

@ -21,28 +21,26 @@ function closeEnough(actual, expected) {
}
async function resizeWindow(x, y) {
// For Linux we have to change only one dimension at a time. (Bug 1803611)
if (window.innerWidth != x) {
let resizePromise = BrowserTestUtils.waitForEvent(window, "resize");
window.innerWidth = x;
await resizePromise;
}
if (window.innerHeight != y) {
let resizePromise = BrowserTestUtils.waitForEvent(window, "resize");
window.innerHeight = y;
await resizePromise;
}
window.innerWidth = x;
window.innerHeight = y;
await waitForAnimationFrames();
ok(
closeEnough(window.innerWidth, x),
`Window innerWidth ${window.innerWidth} is close enough to ${x}`
);
ok(
closeEnough(window.innerHeight, y),
`Window innerHeight ${window.innerHeight} is close enough to ${y}`
await TestUtils.waitForCondition(
() => {
info(`window is ${window.innerWidth} x ${window.innerHeight}`);
if (
closeEnough(window.innerWidth, x) &&
closeEnough(window.innerHeight, y)
) {
return true;
}
window.innerWidth = x;
window.innerHeight = y;
return false;
},
`Wait for ${x}x${y}`,
250
);
}

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

@ -2260,19 +2260,16 @@ static void SizeOpenedWindow(nsIDocShellTreeOwner* aTreeOwner,
left = (LayoutDeviceCoord(devPxRect.x) / devToDesktopScale).Rounded();
top = (LayoutDeviceCoord(devPxRect.y) / devToDesktopScale).Rounded();
LayoutDeviceIntSize contentSize;
int32_t contentWidth, contentHeight; // CSS pixels.
bool hasPrimaryContent = false;
aTreeOwner->GetHasPrimaryContent(&hasPrimaryContent);
if (hasPrimaryContent) {
aTreeOwner->GetPrimaryContentSize(&contentSize.width,
&contentSize.height);
aTreeOwner->GetPrimaryContentSize(&contentWidth, &contentHeight);
} else {
aTreeOwner->GetRootShellSize(&contentSize.width, &contentSize.height);
aTreeOwner->GetRootShellSize(&contentWidth, &contentHeight);
}
CSSIntSize contentSizeCSS = RoundedToInt(contentSize / cssToDevScale);
chromeWidth = width - contentSizeCSS.width;
chromeHeight = height - contentSizeCSS.height;
chromeWidth = width - contentWidth;
chromeHeight = height - contentHeight;
}
// Set up left/top

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

@ -1,119 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "DimensionRequest.h"
#include "nsIBaseWindow.h"
#include "nsIDocShellTreeOwner.h"
namespace mozilla {
nsresult DimensionRequest::SupplementFrom(nsIBaseWindow* aSource) {
NS_ENSURE_ARG_POINTER(aSource);
int32_t x = 0, y = 0, width = 0, height = 0;
bool needsPosition = mX.isSome() != mY.isSome();
bool needsSize = mWidth.isSome() != mHeight.isSome();
if (!needsPosition && !needsSize) {
return NS_OK;
}
MOZ_TRY(aSource->GetDimensions(mDimensionKind, needsPosition ? &x : nullptr,
needsPosition ? &y : nullptr,
needsSize ? &width : nullptr,
needsSize ? &height : nullptr));
if (needsPosition) {
if (mX.isNothing()) {
mX.emplace(x);
}
if (mY.isNothing()) {
mY.emplace(y);
}
}
if (needsSize) {
if (mWidth.isNothing()) {
mWidth.emplace(width);
}
if (mHeight.isNothing()) {
mHeight.emplace(height);
}
}
MOZ_ASSERT(mX.isSome() == mY.isSome());
MOZ_ASSERT(mWidth.isSome() == mHeight.isSome());
return NS_OK;
}
nsresult DimensionRequest::ApplyOuterTo(nsIBaseWindow* aTarget) {
NS_ENSURE_ARG_POINTER(aTarget);
MOZ_ASSERT(mX.isSome() == mY.isSome(),
"Missing dimensions should have been completed.");
MOZ_ASSERT(mWidth.isSome() == mHeight.isSome(),
"Missing dimensions should have been completed.");
if (mDimensionKind != DimensionKind::Outer) {
MOZ_ASSERT_UNREACHABLE("Expected outer dimensions.");
return NS_ERROR_UNEXPECTED;
}
bool havePosition = mX.isSome() && mY.isSome();
bool haveSize = mWidth.isSome() && mHeight.isSome();
if (!havePosition && !haveSize) {
return NS_OK;
}
if (havePosition && haveSize) {
return aTarget->SetPositionAndSize(*mX, *mY, *mWidth, *mHeight, true);
}
if (havePosition) {
return aTarget->SetPosition(*mX, *mY);
}
if (haveSize) {
return aTarget->SetSize(*mWidth, *mHeight, true);
}
MOZ_ASSERT_UNREACHABLE();
return NS_ERROR_UNEXPECTED;
}
nsresult DimensionRequest::ApplyInnerTo(nsIDocShellTreeOwner* aTarget,
bool aAsRootShell) {
NS_ENSURE_ARG_POINTER(aTarget);
MOZ_ASSERT(mX.isSome() == mY.isSome(),
"Missing dimensions should have been completed.");
MOZ_ASSERT(mWidth.isSome() == mHeight.isSome(),
"Missing dimensions should have been completed.");
if (mDimensionKind != DimensionKind::Inner) {
MOZ_ASSERT_UNREACHABLE("Expected inner dimensions.");
return NS_ERROR_UNEXPECTED;
}
bool havePosition = mX.isSome() && mY.isSome();
bool haveSize = mWidth.isSome() && mHeight.isSome();
if (!havePosition && !haveSize) {
return NS_OK;
}
if (havePosition) {
MOZ_ASSERT_UNREACHABLE("Inner position is not implemented.");
return NS_ERROR_NOT_IMPLEMENTED;
}
if (haveSize) {
if (aAsRootShell) {
return aTarget->SetRootShellSize(*mWidth, *mHeight);
}
return aTarget->SetPrimaryContentSize(*mWidth, *mHeight);
}
MOZ_ASSERT_UNREACHABLE();
return NS_ERROR_UNEXPECTED;
}
} // namespace mozilla

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

@ -1,71 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_DimensionRequest_h
#define mozilla_DimensionRequest_h
#include "Units.h"
#include "mozilla/Maybe.h"
class nsIBaseWindow;
class nsIDocShellTreeOwner;
namespace mozilla {
enum class DimensionKind { Inner, Outer };
/**
* DimensionRequest allows to request the change of some dimensions without
* having to specify the unchanged dimensions. This is specifically necessary
* when a change is initiated from a child process, which might not have an
* up-to-date view of its latest dimensions. Having to specify the missing
* dimensions with an outdated view can revert a previous change.
*
* The following series of changes `window.screenX = 10; window.screenY = 10;`
* essentially translates into two moveTo() calls. For the second call we want
* to account for changes made by the first call. From a child process we would
* end up crafting the second call without knowing the results of the first
* call. In the parent process we have access to results of the first call
* before crafting the second one. Although on Linux even the parent process
* doesn't have immediate access to the results of the last change.
*
* Note: The concept of an inner position is not present on
* nsIDocShellTreeOwner and nsIBaseWindow. A request specifying an inner
* position will return an NS_ERROR_NOT_IMPLEMENTED.
*/
struct DimensionRequest {
DimensionKind mDimensionKind;
Maybe<LayoutDeviceIntCoord> mX;
Maybe<LayoutDeviceIntCoord> mY;
Maybe<LayoutDeviceIntCoord> mWidth;
Maybe<LayoutDeviceIntCoord> mHeight;
/**
* Fills the missing dimensions with values obtained from `aSource`. Whether
* inner dimensions are supported depends on the implementation of
* `nsIBaseWindow::GetDimensions` for `aSource`.
*
* @param aSource The source for the missing dimensions.
*/
nsresult SupplementFrom(nsIBaseWindow* aSource);
/**
* Changes the outer size and or position of `aTarget`. Only outer dimensions
* are supported.
*
* @param aTarget The target whose size or position we want to change.
*/
nsresult ApplyOuterTo(nsIBaseWindow* aTarget);
/**
* Changes the inner size of `aTarget`. Only inner dimensions are supported.
*
* @param aTarget The target whose size we want to change.
*/
nsresult ApplyInnerTo(nsIDocShellTreeOwner* aTarget, bool aAsRootShell);
};
} // namespace mozilla
#endif // mozilla_DimensionRequest_h

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

@ -1021,9 +1021,9 @@ LayoutDeviceIntPoint PuppetWidget::GetWindowPosition() {
}
int32_t winX, winY, winW, winH;
NS_ENSURE_SUCCESS(GetOwningBrowserChild()->GetDimensions(
DimensionKind::Outer, &winX, &winY, &winW, &winH),
LayoutDeviceIntPoint());
NS_ENSURE_SUCCESS(
GetOwningBrowserChild()->GetDimensions(0, &winX, &winY, &winW, &winH),
LayoutDeviceIntPoint());
return LayoutDeviceIntPoint(winX, winY) +
GetOwningBrowserChild()->GetClientOffset();
}

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

@ -7,7 +7,6 @@
#include "nsIFrame.h"
#include "nsNativeTheme.h"
#include "mozilla/StaticPrefs_widget.h"
using namespace mozilla;
using namespace mozilla::widget;

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

@ -7,7 +7,6 @@
#include "ipc/EnumSerializer.h"
#include "ipc/IPCMessageUtils.h"
#include "mozilla/DimensionRequest.h"
#include "mozilla/LookAndFeel.h"
#include "mozilla/widget/ThemeChangeKind.h"
#include "nsIWidget.h"
@ -58,16 +57,6 @@ struct ParamTraits<nsIWidget::TouchPointerState>
: public BitFlagsEnumSerializer<nsIWidget::TouchPointerState,
nsIWidget::TouchPointerState::ALL_BITS> {};
template <>
struct ParamTraits<mozilla::DimensionKind>
: public ContiguousEnumSerializerInclusive<mozilla::DimensionKind,
mozilla::DimensionKind::Inner,
mozilla::DimensionKind::Outer> {
};
DEFINE_IPC_SERIALIZER_WITH_FIELDS(mozilla::DimensionRequest, mDimensionKind, mX,
mY, mWidth, mHeight);
} // namespace IPC
#endif // WidgetMessageUtils_h

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

@ -236,19 +236,14 @@ void HeadlessWidget::Move(double aX, double aY) {
SetSizeMode(nsSizeMode_Normal);
}
MoveInternal(x, y);
}
void HeadlessWidget::MoveInternal(int32_t aX, int32_t aY) {
// Since a popup window's x/y coordinates are in relation to
// the parent, the parent might have moved so we always move a
// popup window.
if (mBounds.IsEqualXY(aX, aY) && mWindowType != eWindowType_popup) {
if (mBounds.IsEqualXY(x, y) && mWindowType != eWindowType_popup) {
return;
}
mBounds.MoveTo(aX, aY);
NotifyWindowMoved(aX, aY);
mBounds.MoveTo(x, y);
}
LayoutDeviceIntPoint HeadlessWidget::WidgetToScreenOffset() {
@ -272,20 +267,10 @@ void HeadlessWidget::SetCompositorWidgetDelegate(
}
void HeadlessWidget::Resize(double aWidth, double aHeight, bool aRepaint) {
if (mWindowType == eWindowType_toplevel ||
mWindowType == eWindowType_dialog) {
SetSizeMode(nsSizeMode_Normal);
}
int32_t width = NSToIntRound(aWidth);
int32_t height = NSToIntRound(aHeight);
ResizeInternal(width, height, aRepaint);
}
void HeadlessWidget::ResizeInternal(int32_t aWidth, int32_t aHeight,
bool aRepaint) {
ConstrainSize(&aWidth, &aHeight);
mBounds.SizeTo(LayoutDeviceIntSize(aWidth, aHeight));
ConstrainSize(&width, &height);
mBounds.SizeTo(LayoutDeviceIntSize(width, height));
if (mCompositorWidget) {
mCompositorWidget->NotifyClientSizeChanged(
@ -302,9 +287,10 @@ void HeadlessWidget::ResizeInternal(int32_t aWidth, int32_t aHeight,
void HeadlessWidget::Resize(double aX, double aY, double aWidth, double aHeight,
bool aRepaint) {
// Move will change the size mode if necessary.
Move(aX, aY);
Resize(aWidth, aHeight, aRepaint);
if (!mBounds.IsEqualXY(aX, aY)) {
NotifyWindowMoved(aX, aY);
}
return Resize(aWidth, aHeight, aRepaint);
}
void HeadlessWidget::SetSizeMode(nsSizeMode aMode) {
@ -340,8 +326,8 @@ void HeadlessWidget::ApplySizeModeSideEffects() {
switch (mSizeMode) {
case nsSizeMode_Normal: {
MoveInternal(mRestoreBounds.X(), mRestoreBounds.Y());
ResizeInternal(mRestoreBounds.Width(), mRestoreBounds.Height(), false);
Resize(mRestoreBounds.X(), mRestoreBounds.Y(), mRestoreBounds.Width(),
mRestoreBounds.Height(), false);
break;
}
case nsSizeMode_Minimized:
@ -352,8 +338,7 @@ void HeadlessWidget::ApplySizeModeSideEffects() {
int32_t left, top, width, height;
if (NS_SUCCEEDED(
screen->GetRectDisplayPix(&left, &top, &width, &height))) {
MoveInternal(0, 0);
ResizeInternal(width, height, true);
Resize(0, 0, width, height, true);
}
}
break;

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

@ -160,10 +160,6 @@ class HeadlessWidget : public nsBaseWidget {
// across size mode changes, so we must track it to emulate.
LayoutDeviceIntRect mRestoreBounds;
void ApplySizeModeSideEffects();
// Move while maintaining size mode.
void MoveInternal(int32_t aX, int32_t aY);
// Resize while maintaining size mode.
void ResizeInternal(int32_t aWidth, int32_t aHeight, bool aRepaint);
// Similarly, we must track the active window ourselves in order
// to dispatch (de)activation events properly.
void RaiseWindow();

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

@ -171,7 +171,6 @@ EXPORTS.mozilla += [
"ContentCache.h",
"ContentData.h",
"ContentEvents.h",
"DimensionRequest.h",
"EventClassList.h",
"EventForwards.h",
"EventMessageList.h",
@ -215,7 +214,6 @@ UNIFIED_SOURCES += [
"CompositorWidget.cpp",
"ContentCache.cpp",
"ContentData.cpp",
"DimensionRequest.cpp",
"GfxDriverInfo.cpp",
"GfxInfoBase.cpp",
"GfxInfoCollector.cpp",

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

@ -11,14 +11,11 @@
[ptr] native nsIWidget(nsIWidget);
%{C++
#include "Units.h"
#include "mozilla/DimensionRequest.h"
class nsIWidget;
%}
typedef voidPtr nativeWindow;
native DimensionRequest(mozilla::DimensionRequest&&);
native DimensionKind(mozilla::DimensionKind);
/**
* The nsIBaseWindow describes a generic window and basic operations that
@ -149,37 +146,6 @@ interface nsIBaseWindow : nsISupports
}
%}
/**
* Allows to request the change of individual dimensions without specifying
* the other components.
*
* @param aRequest - The requested change. A request to change only the width
* may look like:
* {DimensionKind::Outer, Nothing(), Nothing(), Some(20), Nothing()}
*
* Note: Inner position is not supported.
*
* @see DimensionRequest
*/
void setDimensions(in DimensionRequest aRequest);
/**
* Gets the dimensions of the window. The caller may pass nullptr for any
* value it is uninterested in receiving.
*
* @param aDimensionKind Specifies whether the dimensions are in reference
* to the inner or outer dimensions.
* @param aX Left hand corner of the outer area; or nullptr.
* @param aY Top corner of the outer area; or nullptr.
* @param aCX Width of the inner or outer area; or nullptr.
* @param aCY Height of the inner or outer area; or nullptr.
*
* Note: Inner position is not supported.
*
* @see DimensionRequest
*/
void getDimensions(in DimensionKind aDimensionKind, out long aX, out long aY, out long aCX, out long aCY);
/**
* Tell the window to repaint itself
* @param aForce - if true, repaint immediately

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

@ -120,17 +120,6 @@ async function runTest() {
gWindow.resizeTo(gWindow.outerWidth, gWindow.outerHeight + 10);
});
// Resizing a maximized window should change to normal sizemode.
info("maximize() in preparation for resize");
await expectSizeModeChange(gWindow.STATE_MAXIMIZED, function () {
gWindow.maximize();
});
info("Testing resizeTo() from maximized");
await expectSizeModeChange(gWindow.STATE_NORMAL, function () {
gWindow.resizeTo(gWindow.outerWidth - 10, gWindow.outerHeight - 10);
});
gWindow.removeEventListener("sizemodechange", sizemodeChanged);
gWindow.close();
SimpleTest.finish();

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

@ -11,6 +11,7 @@
#include "nsIBrowserChild.h"
#include "nsIDialogParamBlock.h"
#include "nsIDocShell.h"
#include "nsIEmbeddingSiteWindow.h"
#include "nsIInterfaceRequestorUtils.h"
#include "nsIPrintSettings.h"
#include "nsIWebBrowserChrome.h"
@ -154,10 +155,10 @@ HWND nsPrintDialogServiceWin::GetHWNDForDOMWindow(mozIDOMWindowProxy* aWindow) {
}
if (chrome) {
nsCOMPtr<nsIBaseWindow> site(do_QueryInterface(chrome));
nsCOMPtr<nsIEmbeddingSiteWindow> site(do_QueryInterface(chrome));
if (site) {
HWND w;
site->GetParentNativeWindow(reinterpret_cast<void**>(&w));
site->GetSiteWindow(reinterpret_cast<void**>(&w));
return w;
}
}

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

@ -29,6 +29,7 @@
#include "mozilla/dom/Document.h"
#include "nsPIDOMWindow.h"
#include "nsScreen.h"
#include "nsIEmbeddingSiteWindow.h"
#include "nsIInterfaceRequestor.h"
#include "nsIInterfaceRequestorUtils.h"
#include "nsIIOService.h"
@ -283,9 +284,13 @@ NS_IMETHODIMP AppWindow::GetInterface(const nsIID& aIID, void** aSink) {
}
if (aIID.Equals(NS_GET_IID(nsIWebBrowserChrome)) &&
NS_SUCCEEDED(EnsureContentTreeOwner()) &&
NS_SUCCEEDED(mContentTreeOwner->QueryInterface(aIID, aSink))) {
NS_SUCCEEDED(mContentTreeOwner->QueryInterface(aIID, aSink)))
return NS_OK;
if (aIID.Equals(NS_GET_IID(nsIEmbeddingSiteWindow)) &&
NS_SUCCEEDED(EnsureContentTreeOwner()) &&
NS_SUCCEEDED(mContentTreeOwner->QueryInterface(aIID, aSink)))
return NS_OK;
}
return QueryInterface(aIID, aSink);
}
@ -786,23 +791,6 @@ NS_IMETHODIMP AppWindow::GetPositionAndSize(int32_t* x, int32_t* y, int32_t* cx,
return NS_OK;
}
NS_IMETHODIMP
AppWindow::SetDimensions(DimensionRequest&& aRequest) {
// For the chrome the inner size is the root shell size, and for the content
// it's the primary content size. We lack an indicator here that would allow
// us to distinguish between the two.
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
AppWindow::GetDimensions(DimensionKind aDimensionKind, int32_t* aX, int32_t* aY,
int32_t* aCX, int32_t* aCY) {
// For the chrome the inner size is the root shell size, and for the content
// it's the primary content size. We lack an indicator here that would allow
// us to distinguish between the two.
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP AppWindow::Center(nsIAppWindow* aRelative, bool aScreen,
bool aAlert) {
DesktopIntRect rect;
@ -1117,39 +1105,48 @@ NS_IMETHODIMP AppWindow::ForceRoundedDimensions() {
return NS_OK;
}
CSSToLayoutDeviceScale scale = UnscaledDevicePixelsPerCSSPixel();
int32_t availWidthCSS = 0;
int32_t availHeightCSS = 0;
int32_t contentWidthCSS = 0;
int32_t contentHeightCSS = 0;
int32_t windowWidthCSS = 0;
int32_t windowHeightCSS = 0;
double devicePerCSSPixels = UnscaledDevicePixelsPerCSSPixel().scale;
CSSIntSize availSizeCSS;
GetAvailScreenSize(&availSizeCSS.width, &availSizeCSS.height);
GetAvailScreenSize(&availWidthCSS, &availHeightCSS);
// To get correct chrome size, we have to resize the window to a proper
// size first. So, here, we size it to its available size.
SetSpecifiedSize(availSizeCSS.width, availSizeCSS.height);
SetSpecifiedSize(availWidthCSS, availHeightCSS);
// Get the current window size for calculating chrome UI size.
CSSIntSize windowSizeCSS = RoundedToInt(GetSize() / scale);
GetSize(&windowWidthCSS, &windowHeightCSS); // device pixels
windowWidthCSS = NSToIntRound(windowWidthCSS / devicePerCSSPixels);
windowHeightCSS = NSToIntRound(windowHeightCSS / devicePerCSSPixels);
// Get the content size for calculating chrome UI size.
LayoutDeviceIntSize contentSizeDev;
GetPrimaryContentSize(&contentSizeDev.width, &contentSizeDev.height);
CSSIntSize contentSizeCSS = RoundedToInt(contentSizeDev / scale);
GetPrimaryContentSize(&contentWidthCSS, &contentHeightCSS);
// Calculate the chrome UI size.
CSSIntSize chromeSizeCSS = windowSizeCSS - contentSizeCSS;
int32_t chromeWidth = 0, chromeHeight = 0;
chromeWidth = windowWidthCSS - contentWidthCSS;
chromeHeight = windowHeightCSS - contentHeightCSS;
int32_t targetContentWidth = 0, targetContentHeight = 0;
CSSIntSize targetSizeCSS;
// Here, we use the available screen dimensions as the input dimensions to
// force the window to be rounded as the maximum available content size.
nsContentUtils::CalcRoundedWindowSizeForResistingFingerprinting(
chromeSizeCSS.width, chromeSizeCSS.height, availSizeCSS.width,
availSizeCSS.height, availSizeCSS.width, availSizeCSS.height,
chromeWidth, chromeHeight, availWidthCSS, availHeightCSS, availWidthCSS,
availHeightCSS,
false, // aSetOuterWidth
false, // aSetOuterHeight
&targetSizeCSS.width, &targetSizeCSS.height);
&targetContentWidth, &targetContentHeight);
LayoutDeviceIntSize targetSizeDev = RoundedToInt(targetSizeCSS * scale);
targetContentWidth = NSToIntRound(targetContentWidth * devicePerCSSPixels);
targetContentHeight = NSToIntRound(targetContentHeight * devicePerCSSPixels);
SetPrimaryContentSize(targetSizeDev.width, targetSizeDev.height);
SetPrimaryContentSize(targetContentWidth, targetContentHeight);
return NS_OK;
}
@ -1373,15 +1370,12 @@ void AppWindow::SetSpecifiedSize(int32_t aSpecWidth, int32_t aSpecHeight) {
mIntrinsicallySized = false;
// Convert specified values to device pixels, and resize
// Convert specified values to device pixels, and resize if needed
auto newSize = RoundedToInt(CSSIntSize(aSpecWidth, aSpecHeight) *
UnscaledDevicePixelsPerCSSPixel());
// Note: Because of the asynchronous resizing on Linux we have to call
// SetSize even when the size doesn't appear to change. A previous call that
// has yet to complete can still change the size. We want the latest call to
// define the final size.
SetSize(newSize.width, newSize.height, false);
if (newSize != GetSize()) {
SetSize(newSize.width, newSize.height, false);
}
}
/* Miscellaneous persistent attributes are attributes named in the
@ -2169,15 +2163,8 @@ nsresult AppWindow::GetPrimaryRemoteTabSize(int32_t* aWidth, int32_t* aHeight) {
RefPtr<dom::Element> element = host->GetOwnerElement();
NS_ENSURE_STATE(element);
CSSIntSize size(element->ClientWidth(), element->ClientHeight());
LayoutDeviceIntSize sizeDev =
RoundedToInt(size * UnscaledDevicePixelsPerCSSPixel());
if (aWidth) {
*aWidth = sizeDev.width;
}
if (aHeight) {
*aHeight = sizeDev.height;
}
*aWidth = element->ClientWidth();
*aHeight = element->ClientHeight();
return NS_OK;
}
@ -2188,13 +2175,14 @@ nsresult AppWindow::GetPrimaryContentShellSize(int32_t* aWidth,
nsCOMPtr<nsIBaseWindow> shellWindow(do_QueryInterface(mPrimaryContentShell));
NS_ENSURE_STATE(shellWindow);
LayoutDeviceIntSize sizeDev = shellWindow->GetSize();
if (aWidth) {
*aWidth = sizeDev.width;
}
if (aHeight) {
*aHeight = sizeDev.height;
}
// We want to return CSS pixels. First, we get device pixels
// from the content area...
// And then get the device pixel scaling factor. Dividing device
// pixels by this scaling factor gives us CSS pixels.
CSSIntSize size = RoundedToInt(
shellWindow->GetSize() / shellWindow->UnscaledDevicePixelsPerCSSPixel());
*aWidth = size.width;
*aHeight = size.height;
return NS_OK;
}
@ -2202,8 +2190,7 @@ NS_IMETHODIMP
AppWindow::SetPrimaryContentSize(int32_t aWidth, int32_t aHeight) {
if (mPrimaryBrowserParent) {
return SetPrimaryRemoteTabSize(aWidth, aHeight);
}
if (mPrimaryContentShell) {
} else if (mPrimaryContentShell) {
return SizeShellTo(mPrimaryContentShell, aWidth, aHeight);
}
return NS_ERROR_UNEXPECTED;
@ -2212,7 +2199,12 @@ AppWindow::SetPrimaryContentSize(int32_t aWidth, int32_t aHeight) {
nsresult AppWindow::SetPrimaryRemoteTabSize(int32_t aWidth, int32_t aHeight) {
int32_t shellWidth, shellHeight;
GetPrimaryRemoteTabSize(&shellWidth, &shellHeight);
SizeShellToWithLimit(aWidth, aHeight, shellWidth, shellHeight);
// FIXME: This is wrong (pre-existing), the above call acounts for zoom and
// this one doesn't.
double scale = UnscaledDevicePixelsPerCSSPixel().scale;
SizeShellToWithLimit(aWidth, aHeight, shellWidth * scale,
shellHeight * scale);
return NS_OK;
}
@ -2745,10 +2737,6 @@ NS_IMETHODIMP AppWindow::SetXULBrowserWindow(
return NS_OK;
}
// Given the dimensions of some content area held within this XUL window, and
// assuming that that content area will change its dimensions in linear
// proportion to the dimensions of this XUL window, changes the size of the XUL
// window so that the content area reaches a particular size.
void AppWindow::SizeShellToWithLimit(int32_t aDesiredWidth,
int32_t aDesiredHeight,
int32_t shellItemWidth,
@ -2756,22 +2744,19 @@ void AppWindow::SizeShellToWithLimit(int32_t aDesiredWidth,
int32_t widthDelta = aDesiredWidth - shellItemWidth;
int32_t heightDelta = aDesiredHeight - shellItemHeight;
int32_t winWidth = 0;
int32_t winHeight = 0;
if (widthDelta || heightDelta) {
int32_t winWidth = 0;
int32_t winHeight = 0;
GetSize(&winWidth, &winHeight);
// There's no point in trying to make the window smaller than the
// desired content area size --- that's not likely to work. This whole
// function assumes that the outer docshell is adding some constant
// "border" chrome to the content area.
winWidth = std::max(winWidth + widthDelta, aDesiredWidth);
winHeight = std::max(winHeight + heightDelta, aDesiredHeight);
// Note: Because of the asynchronous resizing on Linux we have to call
// SetSize even when the size doesn't appear to change. A previous call that
// has yet to complete can still change the size. We want the latest call to
// define the final size.
SetSize(winWidth, winHeight, true);
GetSize(&winWidth, &winHeight);
// There's no point in trying to make the window smaller than the
// desired content area size --- that's not likely to work. This whole
// function assumes that the outer docshell is adding some constant
// "border" chrome to the content area.
winWidth = std::max(winWidth + widthDelta, aDesiredWidth);
winHeight = std::max(winHeight + heightDelta, aDesiredHeight);
SetSize(winWidth, winHeight, true);
}
}
nsresult AppWindow::GetTabCount(uint32_t* aResult) {

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

@ -385,8 +385,6 @@ class AppWindow final : public nsIBaseWindow,
GetPrimaryRemoteTabSize(int32_t* aWidth, int32_t* aHeight);
nsresult GetPrimaryContentShellSize(int32_t* aWidth, int32_t* aHeight);
nsresult SetPrimaryRemoteTabSize(int32_t aWidth, int32_t aHeight);
void SizeShellToWithLimit(int32_t aDesiredWidth, int32_t aDesiredHeight,
int32_t shellItemWidth, int32_t shellItemHeight);
#ifndef MOZ_NEW_XULSTORE
nsCOMPtr<nsIXULStore> mLocalStore;
#endif

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

@ -17,6 +17,7 @@
#include "nsWidgetInitData.h"
#include "nsWidgetsCID.h"
#include "nsIWidget.h"
#include "nsIEmbeddingSiteWindow.h"
#include "nsAppDirectoryServiceDefs.h"
#include "nsAppShellService.h"
@ -194,11 +195,12 @@ nsAppShellService::CreateTopLevelWindow(nsIAppWindow* aParent, nsIURI* aUrl,
* by nsAppShellService::CreateWindowlessBrowser
*/
class WebBrowserChrome2Stub final : public nsIWebBrowserChrome,
public nsIEmbeddingSiteWindow,
public nsIInterfaceRequestor,
public nsSupportsWeakReference {
protected:
nsCOMPtr<nsIWebBrowser> mBrowser;
virtual ~WebBrowserChrome2Stub() = default;
virtual ~WebBrowserChrome2Stub() {}
public:
void SetBrowser(nsIWebBrowser* aBrowser) { mBrowser = aBrowser; }
@ -206,6 +208,7 @@ class WebBrowserChrome2Stub final : public nsIWebBrowserChrome,
NS_DECL_ISUPPORTS
NS_DECL_NSIWEBBROWSERCHROME
NS_DECL_NSIINTERFACEREQUESTOR
NS_DECL_NSIEMBEDDINGSITEWINDOW
};
NS_INTERFACE_MAP_BEGIN(WebBrowserChrome2Stub)
@ -213,6 +216,7 @@ NS_INTERFACE_MAP_BEGIN(WebBrowserChrome2Stub)
NS_INTERFACE_MAP_ENTRY(nsIWebBrowserChrome)
NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor)
NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
NS_INTERFACE_MAP_ENTRY(nsIEmbeddingSiteWindow)
NS_INTERFACE_MAP_END
NS_IMPL_ADDREF(WebBrowserChrome2Stub)
@ -254,32 +258,59 @@ WebBrowserChrome2Stub::GetInterface(const nsIID& aIID, void** aSink) {
return QueryInterface(aIID, aSink);
}
// nsIEmbeddingSiteWindow impl
NS_IMETHODIMP
WebBrowserChrome2Stub::GetDimensions(DimensionKind aDimensionKind, int32_t* aX,
int32_t* aY, int32_t* aCX, int32_t* aCY) {
if (aX) {
*aX = 0;
WebBrowserChrome2Stub::GetDimensions(uint32_t flags, int32_t* x, int32_t* y,
int32_t* cx, int32_t* cy) {
if (x) {
*x = 0;
}
if (aY) {
*aY = 0;
if (y) {
*y = 0;
}
if (aCX) {
*aCX = 0;
if (cx) {
*cx = 0;
}
if (aCY) {
*aCY = 0;
if (cy) {
*cy = 0;
}
return NS_OK;
}
NS_IMETHODIMP
WebBrowserChrome2Stub::SetDimensions(DimensionRequest&& aRequest) {
nsCOMPtr<nsIBaseWindow> window(do_QueryInterface(mBrowser));
NS_ENSURE_STATE(window);
// Inner and outer dimensions are equal.
aRequest.mDimensionKind = DimensionKind::Outer;
MOZ_TRY(aRequest.SupplementFrom(window));
return aRequest.ApplyOuterTo(window);
WebBrowserChrome2Stub::SetDimensions(uint32_t flags, int32_t x, int32_t y,
int32_t cx, int32_t cy) {
nsCOMPtr<nsIBaseWindow> window = do_QueryInterface(mBrowser);
NS_ENSURE_TRUE(window, NS_ERROR_FAILURE);
window->SetSize(cx, cy, true);
return NS_OK;
}
NS_IMETHODIMP
WebBrowserChrome2Stub::GetVisibility(bool* aVisibility) {
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
WebBrowserChrome2Stub::SetVisibility(bool aVisibility) {
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
WebBrowserChrome2Stub::GetTitle(nsAString& aTitle) {
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
WebBrowserChrome2Stub::SetTitle(const nsAString& aTitle) {
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
WebBrowserChrome2Stub::GetSiteWindow(void** aSiteWindow) {
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP

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

@ -10,6 +10,7 @@
// Helper Classes
#include "nsString.h"
#include "nsIEmbeddingSiteWindow.h"
#include "nsIDocShellTreeItem.h"
// Interfaces needed to include
@ -76,6 +77,10 @@ NS_IMETHODIMP nsChromeTreeOwner::GetInterface(const nsIID& aIID, void** aSink) {
NS_ENSURE_STATE(mAppWindow);
return mAppWindow->GetInterface(aIID, aSink);
}
if (aIID.Equals(NS_GET_IID(nsIEmbeddingSiteWindow))) {
NS_ENSURE_STATE(mAppWindow);
return mAppWindow->GetInterface(aIID, aSink);
}
if (aIID.Equals(NS_GET_IID(nsIAppWindow))) {
NS_ENSURE_STATE(mAppWindow);
return mAppWindow->QueryInterface(aIID, aSink);
@ -306,27 +311,6 @@ NS_IMETHODIMP nsChromeTreeOwner::GetPositionAndSize(int32_t* x, int32_t* y,
return mAppWindow->GetPositionAndSize(x, y, cx, cy);
}
NS_IMETHODIMP
nsChromeTreeOwner::SetDimensions(DimensionRequest&& aRequest) {
MOZ_TRY(aRequest.SupplementFrom(this));
if (aRequest.mDimensionKind == DimensionKind::Outer) {
return aRequest.ApplyOuterTo(this);
}
return aRequest.ApplyInnerTo(this, /* aAsRootShell */ true);
}
NS_IMETHODIMP
nsChromeTreeOwner::GetDimensions(DimensionKind aDimensionKind, int32_t* aX,
int32_t* aY, int32_t* aCX, int32_t* aCY) {
if (aDimensionKind == DimensionKind::Outer) {
return GetPositionAndSize(aX, aY, aCX, aCY);
}
if (aY || aX) {
return NS_ERROR_NOT_IMPLEMENTED;
}
return GetRootShellSize(aCX, aCY);
}
NS_IMETHODIMP nsChromeTreeOwner::Repaint(bool aForce) {
NS_ENSURE_STATE(mAppWindow);
return mAppWindow->Repaint(aForce);

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

@ -13,6 +13,7 @@
#include "nsIDOMWindow.h"
#include "nsIDOMChromeWindow.h"
#include "nsIBrowserDOMWindow.h"
#include "nsIEmbeddingSiteWindow.h"
#include "nsIOpenWindowInfo.h"
#include "nsIPrompt.h"
#include "nsIAuthPrompt.h"
@ -43,12 +44,41 @@
using namespace mozilla;
//*****************************************************************************
//*** nsSiteWindow declaration
//*****************************************************************************
class nsSiteWindow : public nsIEmbeddingSiteWindow {
// nsSiteWindow shares a lifetime with nsContentTreeOwner, and proxies it's
// AddRef and Release calls to said object.
// When nsContentTreeOwner is destroyed, nsSiteWindow will be destroyed as
// well. nsContentTreeOwner is a friend class of nsSiteWindow such that it can
// call nsSiteWindow's destructor, which is private, as public destructors on
// reference counted classes are generally unsafe.
friend class nsContentTreeOwner;
public:
explicit nsSiteWindow(nsContentTreeOwner* aAggregator);
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSIEMBEDDINGSITEWINDOW
private:
virtual ~nsSiteWindow();
nsContentTreeOwner* mAggregator;
};
//*****************************************************************************
//*** nsContentTreeOwner: Object Management
//*****************************************************************************
nsContentTreeOwner::nsContentTreeOwner(bool fPrimary)
: mAppWindow(nullptr), mPrimary(fPrimary) {}
: mAppWindow(nullptr), mPrimary(fPrimary) {
// note if this fails, QI on nsIEmbeddingSiteWindow(2) will simply fail
mSiteWindow = new nsSiteWindow(this);
}
nsContentTreeOwner::~nsContentTreeOwner() { delete mSiteWindow; }
//*****************************************************************************
// nsContentTreeOwner::nsISupports
@ -64,6 +94,15 @@ NS_INTERFACE_MAP_BEGIN(nsContentTreeOwner)
NS_INTERFACE_MAP_ENTRY(nsIWebBrowserChrome)
NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor)
NS_INTERFACE_MAP_ENTRY(nsIWindowProvider)
// NOTE: This is using aggregation because there are some properties and
// method on nsIBaseWindow (which we implement) and on
// nsIEmbeddingSiteWindow (which we also implement) that have the same name.
// And it just so happens that we want different behavior for these methods
// and properties depending on the interface through which they're called
// (SetFocus() is a good example here). If it were not for that, we could
// ditch the aggregation and just deal with not being able to use NS_DECL_*
// macros for this stuff....
NS_INTERFACE_MAP_ENTRY_AGGREGATED(nsIEmbeddingSiteWindow, mSiteWindow)
NS_INTERFACE_MAP_END
//*****************************************************************************
@ -73,7 +112,7 @@ NS_INTERFACE_MAP_END
NS_IMETHODIMP nsContentTreeOwner::GetInterface(const nsIID& aIID,
void** aSink) {
NS_ENSURE_ARG_POINTER(aSink);
*aSink = nullptr;
*aSink = 0;
if (aIID.Equals(NS_GET_IID(nsIPrompt))) {
NS_ENSURE_STATE(mAppWindow);
@ -408,27 +447,6 @@ NS_IMETHODIMP nsContentTreeOwner::GetPositionAndSize(int32_t* aX, int32_t* aY,
return mAppWindow->GetPositionAndSize(aX, aY, aCX, aCY);
}
NS_IMETHODIMP
nsContentTreeOwner::SetDimensions(DimensionRequest&& aRequest) {
MOZ_TRY(aRequest.SupplementFrom(this));
if (aRequest.mDimensionKind == DimensionKind::Outer) {
return aRequest.ApplyOuterTo(this);
}
return aRequest.ApplyInnerTo(this, /* aAsRootShell */ false);
}
NS_IMETHODIMP
nsContentTreeOwner::GetDimensions(DimensionKind aDimensionKind, int32_t* aX,
int32_t* aY, int32_t* aCX, int32_t* aCY) {
if (aDimensionKind == DimensionKind::Outer) {
return GetPositionAndSize(aX, aY, aCX, aCY);
}
if (aY || aX) {
return NS_ERROR_NOT_IMPLEMENTED;
}
return GetPrimaryContentSize(aCX, aCY);
}
NS_IMETHODIMP nsContentTreeOwner::Repaint(bool aForce) {
NS_ENSURE_STATE(mAppWindow);
return mAppWindow->Repaint(aForce);
@ -593,23 +611,56 @@ void nsContentTreeOwner::AppWindow(mozilla::AppWindow* aAppWindow) {
mozilla::AppWindow* nsContentTreeOwner::AppWindow() { return mAppWindow; }
//*****************************************************************************
//*** nsSiteWindow implementation
//*****************************************************************************
nsSiteWindow::nsSiteWindow(nsContentTreeOwner* aAggregator) {
mAggregator = aAggregator;
}
nsSiteWindow::~nsSiteWindow() {}
NS_IMPL_ADDREF_USING_AGGREGATOR(nsSiteWindow, mAggregator)
NS_IMPL_RELEASE_USING_AGGREGATOR(nsSiteWindow, mAggregator)
NS_INTERFACE_MAP_BEGIN(nsSiteWindow)
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_ENTRY(nsIEmbeddingSiteWindow)
NS_INTERFACE_MAP_END_AGGREGATED(mAggregator)
NS_IMETHODIMP
nsSiteWindow::SetDimensions(uint32_t aFlags, int32_t aX, int32_t aY,
int32_t aCX, int32_t aCY) {
// XXX we're ignoring aFlags
return mAggregator->SetPositionAndSize(aX, aY, aCX, aCY,
nsIBaseWindow::eRepaint);
}
NS_IMETHODIMP
nsSiteWindow::GetDimensions(uint32_t aFlags, int32_t* aX, int32_t* aY,
int32_t* aCX, int32_t* aCY) {
// XXX we're ignoring aFlags
return mAggregator->GetPositionAndSize(aX, aY, aCX, aCY);
}
/* this implementation focuses another window. if there isn't another
window to focus, we do nothing. */
NS_IMETHODIMP
nsContentTreeOwner::Blur() {
nsSiteWindow::Blur(void) {
NS_DEFINE_CID(kWindowMediatorCID, NS_WINDOWMEDIATOR_CID);
nsCOMPtr<nsISimpleEnumerator> windowEnumerator;
nsCOMPtr<nsIAppWindow> appWindow;
bool more, foundUs;
AppWindow* ourWindow = mAggregator->AppWindow();
{
nsCOMPtr<nsIWindowMediator> windowMediator(
do_GetService(kWindowMediatorCID));
if (windowMediator) {
if (windowMediator)
windowMediator->GetZOrderAppWindowEnumerator(
nullptr, true, getter_AddRefs(windowEnumerator));
}
0, true, getter_AddRefs(windowEnumerator));
}
if (!windowEnumerator) return NS_ERROR_FAILURE;
@ -634,9 +685,7 @@ nsContentTreeOwner::Blur() {
if (!appWindow) appWindow = nextAppWindow;
// look for us
if (nextAppWindow == mAppWindow) {
foundUs = true;
}
if (nextAppWindow == ourWindow) foundUs = true;
windowEnumerator->HasMoreElements(&more);
}
@ -654,3 +703,28 @@ nsContentTreeOwner::Blur() {
}
return NS_OK;
}
NS_IMETHODIMP
nsSiteWindow::GetVisibility(bool* aVisibility) {
return mAggregator->GetVisibility(aVisibility);
}
NS_IMETHODIMP
nsSiteWindow::SetVisibility(bool aVisibility) {
return mAggregator->SetVisibility(aVisibility);
}
NS_IMETHODIMP
nsSiteWindow::GetTitle(nsAString& aTitle) {
return mAggregator->GetTitle(aTitle);
}
NS_IMETHODIMP
nsSiteWindow::SetTitle(const nsAString& aTitle) {
return mAggregator->SetTitle(aTitle);
}
NS_IMETHODIMP
nsSiteWindow::GetSiteWindow(void** aSiteWindow) {
return mAggregator->GetParentNativeWindow(aSiteWindow);
}

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

@ -22,6 +22,7 @@
namespace mozilla {
class AppWindow;
}
class nsSiteWindow;
class nsContentTreeOwner final : public nsIDocShellTreeOwner,
public nsIBaseWindow,
@ -29,6 +30,7 @@ class nsContentTreeOwner final : public nsIDocShellTreeOwner,
public nsIWebBrowserChrome,
public nsIWindowProvider {
friend class mozilla::AppWindow;
friend class nsSiteWindow;
public:
NS_DECL_ISUPPORTS
@ -36,25 +38,19 @@ class nsContentTreeOwner final : public nsIDocShellTreeOwner,
NS_DECL_NSIBASEWINDOW
NS_DECL_NSIDOCSHELLTREEOWNER
NS_DECL_NSIINTERFACEREQUESTOR
NS_DECL_NSIWEBBROWSERCHROME
NS_DECL_NSIWINDOWPROVIDER
/* nsIWebBrowserChrome (Get/SetDimensions overlap with nsIBaseWindow) */
NS_IMETHOD SetLinkStatus(const nsAString& status) override;
NS_IMETHOD GetChromeFlags(uint32_t* aChromeFlags) override;
NS_IMETHOD SetChromeFlags(uint32_t aChromeFlags) override;
NS_IMETHOD ShowAsModal() override;
NS_IMETHOD IsWindowModal(bool* _retval) override;
NS_IMETHOD Blur() override;
protected:
explicit nsContentTreeOwner(bool fPrimary);
virtual ~nsContentTreeOwner() = default;
virtual ~nsContentTreeOwner();
void AppWindow(mozilla::AppWindow* aAppWindow);
mozilla::AppWindow* AppWindow();
protected:
mozilla::AppWindow* mAppWindow;
nsSiteWindow* mSiteWindow;
bool mPrimary;
};

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

@ -153,6 +153,34 @@ interface nsIAppWindow : nsISupports
*/
[noscript] void beforeStartLayout();
/**
* Given the dimensions of some content area held within this
* XUL window, and assuming that that content area will change
* its dimensions in linear proportion to the dimensions of this
* XUL window, changes the size of the XUL window so that the
* content area reaches a particular size.
*
* We need to supply the content area dimensions because sometimes
* the child's nsDocShellTreeOwner needs to propagate a SizeShellTo
* call to the parent. But the shellItem argument of the call will
* not be available on the parent side.
*
* Note: this is an internal method, other consumers should never call this.
*
* @param aDesiredWidth
* The desired width of the content area in device pixels.
* @param aDesiredHeight
* The desired height of the content area in device pixels.
* @param shellItemWidth
* The current width of the content area.
* @param shellItemHeight
* The current height of the content area.
*/
[noscript, notxpcom] void sizeShellToWithLimit(in int32_t aDesiredWidth,
in int32_t aDesiredHeight,
in int32_t shellItemWidth,
in int32_t shellItemHeight);
/**
* If the window was opened as a content window, this will return the initial
* nsIOpenWindowInfo to use.