Bug 1578985 - Saving the last location and size of Picture in Picture window and opening there the next time. r=mconley

Differential Revision: https://phabricator.services.mozilla.com/D90813
This commit is contained in:
Niklas Baumgardner 2020-11-05 17:24:57 +00:00
Родитель a5d95630e1
Коммит ce9cac5aae
5 изменённых файлов: 654 добавлений и 120 удалений

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

@ -39,12 +39,19 @@ add_task(async function testNoSrcOrErrorMediaEntersPIPMode() {
tab.linkedBrowser,
testVideoId
);
await BrowserTestUtils.closeWindow(winPIP);
await ensureMessageAndClosePiP(
tab.linkedBrowser,
testVideoId,
winPIP,
false
);
}
ok(!controller.isActive, "controller is still inactive");
info(`remove tab`);
await BrowserTestUtils.removeTab(tab);
await SimpleTest.promiseFocus(window);
}
});

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

@ -271,7 +271,8 @@ var PictureInPicture = {
reason,
1
);
// Saves the location of the Picture in Picture window
this.savePosition(window);
this.clearPipTabIcon();
delete this._weakPipPlayer;
delete this.browser;
@ -332,8 +333,9 @@ var PictureInPicture = {
},
/**
* Calculate the desired size and position for a Picture in Picture window
* for the provided window and videoData.
* This function tries to restore the last known Picture-in-Picture location
* and size. If those values are unknown or offscreen, then a default
* location and size is used.
*
* @param windowOrPlayer (chrome window|player window)
* The window hosting the browser that requested the Picture in
@ -350,7 +352,7 @@ var PictureInPicture = {
* videoWidth (int):
* The preferred width of the video.
*
* @returns object
* @returns (object)
* The size and position for the player window.
*
* top (int):
@ -367,74 +369,121 @@ var PictureInPicture = {
*/
fitToScreen(windowOrPlayer, videoData) {
let { videoHeight, videoWidth } = videoData;
// if current PiP window is being resized, the underlying video is changing,
// then save the location and size for opening the new window
let isPlayerWindow = windowOrPlayer == this.getWeakPipPlayer();
if (isPlayerWindow) {
this.savePosition(windowOrPlayer);
}
// The Picture in Picture window will open on the same display as the
// originating window, and anchor to the bottom right.
let screenManager = Cc["@mozilla.org/gfx/screenmanager;1"].getService(
Ci.nsIScreenManager
);
let screen = screenManager.screenForRect(
// The last PiP location and size
let { top, left, width, height } = this.loadPosition();
// Check that previous location and size were loaded
if (!isNaN(top) && !isNaN(left) && !isNaN(width) && !isNaN(height)) {
// Center position of PiP window
let centerX = left + width / 2;
let centerY = top + height / 2;
// Get the screen of the last PiP using the center of the PiP
// window to check.
// PiP screen will be the default screen if the center was
// not on a screen.
let PiPScreen = this.getWorkingScreen(centerX, centerY);
// We have the screen, now we will get the dimensions of the screen
let [
PiPScreenLeft,
PiPScreenTop,
PiPScreenWidth,
PiPScreenHeight,
] = this.getAvailScreenSize(PiPScreen);
// Check that the center of the last PiP location is within the screen limits
// If it's not, then we will use the default size and position
if (
PiPScreenLeft <= centerX &&
centerX <= PiPScreenLeft + PiPScreenWidth &&
PiPScreenTop <= centerY &&
centerY <= PiPScreenTop + PiPScreenHeight
) {
let oldWidth = width;
// The new PiP window will keep the height of the old
// PiP window and adjust the width to the correct ratio
width = Math.round((height * videoWidth) / videoHeight);
// Minimum window size on Windows is 136
if (AppConstants.platform == "win") {
width = 136 > width ? 136 : width;
}
// WIGGLE_ROOM allows the PiP window to be within 5 pixels of the right
// side of the screen to stay snapped to the right side
const WIGGLE_ROOM = 5;
// If the PiP window was right next to the right side of the screen
// then move the PiP window to the right the same distance that
// the width changes from previous width to current width
let rightScreen = PiPScreenLeft + PiPScreenWidth;
let distFromRight = rightScreen - (left + width);
if (
0 < distFromRight &&
distFromRight <= WIGGLE_ROOM + (oldWidth - width)
) {
left += distFromRight;
}
// Checks if some of the PiP window is off screen and
// if so it will adjust to move everything on screen
if (left < PiPScreenLeft) {
// off the left of the screen
// slide right
left += PiPScreenLeft - left;
}
if (top < PiPScreenTop) {
// off the top of the screen
// slide down
top += PiPScreenTop - top;
}
if (left + width > PiPScreenLeft + PiPScreenWidth) {
// off the right of the screen
// slide left
left += PiPScreenLeft + PiPScreenWidth - left - width;
}
if (top + height > PiPScreenTop + PiPScreenHeight) {
// off the bottom of the screen
// slide up
top += PiPScreenTop + PiPScreenHeight - top - height;
}
return { top, left, width, height };
}
}
// We don't have the size or position of the last PiP window, so fall
// back to calculating the default location.
let screen = this.getWorkingScreen(
windowOrPlayer.screenX,
windowOrPlayer.screenY,
1,
1
windowOrPlayer.screenY
);
// Now that we have the right screen, let's see how much available
// real-estate there is for us to work with.
let screenLeft = {},
screenTop = {},
screenWidth = {},
screenHeight = {};
screen.GetAvailRectDisplayPix(
let [
screenLeft,
screenTop,
screenWidth,
screenHeight
);
let fullLeft = {},
fullTop = {},
fullWidth = {},
fullHeight = {};
screen.GetRectDisplayPix(fullLeft, fullTop, fullWidth, fullHeight);
screenHeight,
] = this.getAvailScreenSize(screen);
// We have to divide these dimensions by the CSS scale factor for the
// display in order for the video to be positioned correctly on displays
// that are not at a 1.0 scaling.
let scaleFactor = screen.contentsScaleFactor / screen.defaultCSSScaleFactor;
screenWidth.value *= scaleFactor;
screenHeight.value *= scaleFactor;
screenLeft.value =
(screenLeft.value - fullLeft.value) * scaleFactor + fullLeft.value;
screenTop.value =
(screenTop.value - fullTop.value) * scaleFactor + fullTop.value;
// If we have a player window, maintain the previous player window's size by
// clamping the new video's largest dimension to the player window's
// largest dimension.
//
// Otherwise the Picture in Picture window will be a maximum of a quarter of
// The Picture in Picture window will be a maximum of a quarter of
// the screen height, and a third of the screen width.
let preferredSize;
if (isPlayerWindow) {
let prevWidth = windowOrPlayer.innerWidth;
let prevHeight = windowOrPlayer.innerHeight;
preferredSize = prevWidth >= prevHeight ? prevWidth : prevHeight;
}
const MAX_HEIGHT = preferredSize || screenHeight.value / 4;
const MAX_WIDTH = preferredSize || screenWidth.value / 3;
const MAX_HEIGHT = screenHeight / 4;
const MAX_WIDTH = screenWidth / 3;
let width = videoWidth;
let height = videoHeight;
width = videoWidth;
height = videoHeight;
let aspectRatio = videoWidth / videoHeight;
if (
videoHeight > MAX_HEIGHT ||
videoWidth > MAX_WIDTH ||
(isPlayerWindow && videoHeight < MAX_HEIGHT && videoWidth < MAX_WIDTH)
) {
// We're bigger than the max, or smaller than the previous player window.
if (videoHeight > MAX_HEIGHT || videoWidth > MAX_WIDTH) {
// We're bigger than the max.
// Take the largest dimension and clamp it to the associated max.
// Recalculate the other dimension to maintain aspect ratio.
if (videoWidth >= videoHeight) {
@ -454,43 +503,6 @@ var PictureInPicture = {
}
}
// Figure out where to position the window on screen. If we have a player
// window this will account for any change in video size. Otherwise the
// video will be positioned in the bottom right.
if (isPlayerWindow) {
// We might need to move the window to keep its positioning in a similar
// part of the screen.
//
// Find the distance from each edge of the screen of the old video, we'll
// keep the closest edge in the same spot.
let prevWidth = windowOrPlayer.innerWidth;
let prevHeight = windowOrPlayer.innerHeight;
let distanceLeft = windowOrPlayer.screenX;
let distanceRight =
screenWidth.value - windowOrPlayer.screenX - prevWidth;
let distanceTop = windowOrPlayer.screenY;
let distanceBottom =
screenHeight.value - windowOrPlayer.screenY - prevHeight;
let left = windowOrPlayer.screenX;
let top = windowOrPlayer.screenY;
if (distanceRight < distanceLeft) {
// Closer to the right edge than the left. Move the window right by
// the difference in the video widths.
left += prevWidth - width;
}
if (distanceBottom < distanceTop) {
// Closer to the bottom edge than the top. Move the window down by
// the difference in the video heights.
top += prevHeight - height;
}
return { top, left, width, height };
}
// Now that we have the dimensions of the video, we need to figure out how
// to position it in the bottom right corner. Since we know the width of the
// available rect, we need to subtract the dimensions of the window we're
@ -506,10 +518,8 @@ var PictureInPicture = {
// the screenLeft and screenTop values, which tell us where this screen is
// located relative to the "origin" in absolute coordinates.
let isRTL = Services.locale.isAppLocaleRTL;
let left = isRTL
? screenLeft.value
: screenLeft.value + screenWidth.value - width;
let top = screenTop.value + screenHeight.value - height;
left = isRTL ? screenLeft : screenLeft + screenWidth - width;
top = screenTop + screenHeight - height;
return { top, left, width, height };
},
@ -558,4 +568,145 @@ var PictureInPicture = {
hideToggle() {
Services.prefs.setBoolPref(TOGGLE_ENABLED_PREF, false);
},
/**
* This function takes a screen and will return the left, top, width and
* height of the screen
* @param screen
* The screen we need to get the sizec and coordinates of
*
* @returns array
* Size and location of screen
*
* screenLeft.value (int):
* The left position for the screen.
*
* screenTop.value (int):
* The top position for the screen.
*
* screenWidth.value (int):
* The width of the screen.
*
* screenHeight.value (int):
* The height of the screen.
*/
getAvailScreenSize(screen) {
let screenLeft = {},
screenTop = {},
screenWidth = {},
screenHeight = {};
screen.GetAvailRectDisplayPix(
screenLeft,
screenTop,
screenWidth,
screenHeight
);
let fullLeft = {},
fullTop = {},
fullWidth = {},
fullHeight = {};
screen.GetRectDisplayPix(fullLeft, fullTop, fullWidth, fullHeight);
// We have to divide these dimensions by the CSS scale factor for the
// display in order for the video to be positioned correctly on displays
// that are not at a 1.0 scaling.
let scaleFactor = screen.contentsScaleFactor / screen.defaultCSSScaleFactor;
screenWidth.value *= scaleFactor;
screenHeight.value *= scaleFactor;
screenLeft.value =
(screenLeft.value - fullLeft.value) * scaleFactor + fullLeft.value;
screenTop.value =
(screenTop.value - fullTop.value) * scaleFactor + fullTop.value;
return [
screenLeft.value,
screenTop.value,
screenWidth.value,
screenHeight.value,
];
},
/**
* This function takes in a left and top value and returns the screen they
* are located on.
* If the left and top are not on any screen, it will return the
* default screen
* @param left
* left or x coordinate
* @param top
* top or y coordinate
*
* @returns screen
* the screen the left and top are on otherwise, default screen
*/
getWorkingScreen(left, top) {
// Get the screen manager
let screenManager = Cc["@mozilla.org/gfx/screenmanager;1"].getService(
Ci.nsIScreenManager
);
// use screenForRect to get screen
// this returns the default screen if left and top are not
// on any screen
let screen = screenManager.screenForRect(left, top, 1, 1);
return screen;
},
/**
* Saves position and size of Picture-in-Picture window
* @param win The Picture-in-Picture window
*/
savePosition(win) {
let xulStore = Services.xulStore;
let left = win.screenX;
let top = win.screenY;
let width = win.innerWidth;
let height = win.innerHeight;
xulStore.setValue(PLAYER_URI, "picture-in-picture", "left", left);
xulStore.setValue(PLAYER_URI, "picture-in-picture", "top", top);
xulStore.setValue(PLAYER_URI, "picture-in-picture", "width", width);
xulStore.setValue(PLAYER_URI, "picture-in-picture", "height", height);
},
/**
* Load last Picture in Picture location and size
* @returns object
* The size and position of the last Picture in Picture window.
*
* top (int):
* The top position for the last player window.
* Otherwise NaN
*
* left (int):
* The left position for the last player window.
* Otherwise NaN
*
* width (int):
* The width of the player last window.
* Otherwise NaN
*
* height (int):
* The height of the player last window.
* Otherwise NaN
*/
loadPosition() {
let xulStore = Services.xulStore;
let left = parseInt(
xulStore.getValue(PLAYER_URI, "picture-in-picture", "left")
);
let top = parseInt(
xulStore.getValue(PLAYER_URI, "picture-in-picture", "top")
);
let width = parseInt(
xulStore.getValue(PLAYER_URI, "picture-in-picture", "width")
);
let height = parseInt(
xulStore.getValue(PLAYER_URI, "picture-in-picture", "height")
);
return { top, left, width, height };
},
};

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

@ -47,6 +47,8 @@ skip-if = debug
[browser_rerequestPiP.js]
[browser_resizeVideo.js]
skip-if = os == 'linux' # Bug 1594223
[browser_saveLastPiPLoc.js]
skip-if = os == 'linux' # Bug 1673465
[browser_shortcutsAfterFocus.js]
[browser_showMessage.js]
[browser_smallVideoLayout.js]

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

@ -59,17 +59,17 @@ async function testVideo(browser, videoID, pipWin, { pinX, pinY } = {}) {
newWidth,
newHeight
) {
if (pinX) {
if (pinX || previousScreenX == 0) {
Assert.equal(
previousScreenX,
newScreenX,
"New video is still in the same X position"
);
} else {
Assert.equal(
previousScreenX + previousWidth,
newScreenX + newWidth,
"New video ends at the same screen X position"
Assert.less(
Math.abs(previousScreenX + previousWidth - (newScreenX + newWidth)),
2,
"New video ends at the same screen X position (within 1 pixel)"
);
}
if (pinY) {
@ -112,8 +112,12 @@ async function testVideo(browser, videoID, pipWin, { pinX, pinY } = {}) {
133, // 4 / 3 = 1.333333333
"Resized aspect ratio is 4:3"
);
Assert.equal(initialWidth, resizedWidth, "Resized video has the same width");
Assert.greater(resizedHeight, initialHeight, "Resized video grew vertically");
Assert.less(resizedWidth, initialWidth, "Resized video has smaller width");
Assert.equal(
resizedHeight,
initialHeight,
"Resized video is the same vertically"
);
let resizedScreenX = pipWin.mozInnerScreenX;
let resizedScreenY = pipWin.mozInnerScreenY;
@ -133,16 +137,27 @@ async function testVideo(browser, videoID, pipWin, { pinX, pinY } = {}) {
let verticalWidth = pipWin.innerWidth;
let verticalHeight = pipWin.innerHeight;
let verticalAspectRatio = verticalWidth / verticalHeight;
Assert.equal(
Math.floor(verticalAspectRatio * 100),
50, // 1 / 2 = 0.5
"Vertical aspect ratio is 1:2"
);
if (verticalWidth == 136) {
// The video is minimun width allowed
Assert.equal(
Math.floor(verticalAspectRatio * 100),
56, // 1 / 2 = 0.5
"Vertical aspect ratio is 1:2"
);
} else {
Assert.equal(
Math.floor(verticalAspectRatio * 100),
50, // 1 / 2 = 0.5
"Vertical aspect ratio is 1:2"
);
}
Assert.less(verticalWidth, resizedWidth, "Vertical video width shrunk");
Assert.equal(
resizedWidth,
verticalHeight,
"Vertical video height matches previous width"
initialHeight,
"Vertical video height matches previous height"
);
let verticalScreenX = pipWin.mozInnerScreenX;
@ -168,9 +183,9 @@ async function testVideo(browser, videoID, pipWin, { pinX, pinY } = {}) {
177,
"Restored aspect ratio is still 16:9"
);
Assert.equal(
initialWidth,
pipWin.innerWidth,
Assert.less(
Math.abs(initialWidth - pipWin.innerWidth),
2,
"Restored video has its original width"
);
Assert.equal(
@ -244,6 +259,5 @@ add_task(async () => {
}
);
}
await SpecialPowers.popPrefEnv();
});

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

@ -0,0 +1,360 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
/**
* This function tests that the browser saves the last location of size of
* the PiP window and will open the next PiP window in the same location
* with the size. It adjusts for aspect ratio by keeping the same height and
* adjusting the width of the PiP window.
*/
add_task(async () => {
await BrowserTestUtils.withNewTab(
{
url: TEST_PAGE,
gBrowser,
},
// Function to switch video source.
async browser => {
async function switchVideoSource(src) {
let videoResized = BrowserTestUtils.waitForEvent(pipWin, "resize");
await ContentTask.spawn(browser, { src }, async ({ src }) => {
let doc = content.document;
let video = doc.getElementById("with-controls");
video.src = src;
});
await videoResized;
}
// This function is used because the rounding of the width can be off
// by about 1 pixel sometimes so this checks that val1 and val2 are
// within 1 pixel
function checkIfEqual(val1, val2, str) {
let equal = Math.abs(val1 - val2);
if (equal <= 1) {
is(equal <= 1, true, str);
} else {
is(val1, val2, str);
}
}
// Used for clearing the size and location of the PiP window
const PLAYER_URI =
"chrome://global/content/pictureinpicture/player.xhtml";
// The PiP window now stores information between tests and needs to be
// cleared before the test begins
function clearSaved() {
let xulStore = Services.xulStore;
xulStore.setValue(PLAYER_URI, "picture-in-picture", "left", NaN);
xulStore.setValue(PLAYER_URI, "picture-in-picture", "top", NaN);
xulStore.setValue(PLAYER_URI, "picture-in-picture", "width", NaN);
xulStore.setValue(PLAYER_URI, "picture-in-picture", "height", NaN);
}
function getAvailScreenSize(screen) {
let screenLeft = {},
screenTop = {},
screenWidth = {},
screenHeight = {};
screen.GetAvailRectDisplayPix(
screenLeft,
screenTop,
screenWidth,
screenHeight
);
let fullLeft = {},
fullTop = {},
fullWidth = {},
fullHeight = {};
screen.GetRectDisplayPix(fullLeft, fullTop, fullWidth, fullHeight);
// We have to divide these dimensions by the CSS scale factor for the
// display in order for the video to be positioned correctly on displays
// that are not at a 1.0 scaling.
let scaleFactor =
screen.contentsScaleFactor / screen.defaultCSSScaleFactor;
screenWidth.value *= scaleFactor;
screenHeight.value *= scaleFactor;
screenLeft.value =
(screenLeft.value - fullLeft.value) * scaleFactor + fullLeft.value;
screenTop.value =
(screenTop.value - fullTop.value) * scaleFactor + fullTop.value;
return [
screenLeft.value,
screenTop.value,
screenWidth.value,
screenHeight.value,
];
}
let screen = Cc["@mozilla.org/gfx/screenmanager;1"]
.getService(Ci.nsIScreenManager)
.screenForRect(1, 1, 1, 1);
let [
defaultX,
defaultY,
defaultWidth,
defaultHeight,
] = getAvailScreenSize(screen);
// Default size of PiP window
let rightEdge = defaultX + defaultWidth;
let bottomEdge = defaultY + defaultHeight;
// tab height
// Used only for Linux as the PiP window has a tab
let tabHeight = 35;
// clear already saved information
clearSaved();
// Open PiP
let pipWin = await triggerPictureInPicture(browser, "with-controls");
ok(pipWin, "Got Picture-in-Picture window.");
let defaultPiPWidth = pipWin.innerWidth;
let defaultPiPHeight = pipWin.innerHeight;
// Check that it is opened at default location
checkIfEqual(
pipWin.screenX,
rightEdge - defaultPiPWidth,
"Default PiP X location"
);
if (AppConstants.platform == "linux") {
checkIfEqual(
pipWin.screenY,
bottomEdge - defaultPiPHeight - tabHeight,
"Default PiP Y location"
);
} else {
checkIfEqual(
pipWin.screenY,
bottomEdge - defaultPiPHeight,
"Default PiP Y location"
);
}
checkIfEqual(pipWin.innerHeight, defaultPiPHeight, "Default PiP height");
checkIfEqual(pipWin.innerWidth, defaultPiPWidth, "Default PiP width");
let top = defaultY;
let left = defaultX;
pipWin.moveTo(left, top);
let height = pipWin.innerHeight / 2;
let width = pipWin.innerWidth / 2;
pipWin.resizeTo(width, height);
// CLose first PiP window and open another
await ensureMessageAndClosePiP(browser, "with-controls", pipWin, true);
pipWin = await triggerPictureInPicture(browser, "with-controls");
ok(pipWin, "Got Picture-in-Picture window.");
// PiP is opened at 0, 0 with size 1/4 default width and 1/4 default height
checkIfEqual(pipWin.screenX, left, "Opened at last X location");
checkIfEqual(pipWin.screenY, top, "Opened at last Y location");
checkIfEqual(
pipWin.innerHeight,
height,
"Opened with 1/2 default height"
);
checkIfEqual(pipWin.innerWidth, width, "Opened with 1/2 default width");
// Mac and Linux did not allow moving to coordinates offscreen so this
// test is skipped on those platforms
if (AppConstants.platform == "win") {
// Move to -1111, -1111 and adjust size to 1/4 width and 1/4 height
left = -11111;
top = -11111;
pipWin.moveTo(left, top);
pipWin.resizeTo(pipWin.innerWidth / 4, pipWin.innerHeight / 4);
await ensureMessageAndClosePiP(browser, "with-controls", pipWin, true);
pipWin = await triggerPictureInPicture(browser, "with-controls");
ok(pipWin, "Got Picture-in-Picture window.");
// because the coordinates are off screen, the default size and location will be used
checkIfEqual(
pipWin.screenX,
rightEdge - defaultPiPWidth,
"Opened at default X location"
);
checkIfEqual(
pipWin.screenY,
bottomEdge - defaultPiPHeight,
"Opened at default Y location"
);
checkIfEqual(
pipWin.innerWidth,
defaultPiPWidth,
"Opened at default PiP width"
);
checkIfEqual(
pipWin.innerHeight,
defaultPiPHeight,
"Opened at default PiP height"
);
}
// Linux doesn't handle switching the video source well and it will
// cause the tests to failed in unexpected ways. Possibly caused by
// bug 1594223 https://bugzilla.mozilla.org/show_bug.cgi?id=1594223
if (AppConstants.platform != "linux") {
// Save width and height for when aspect ratio is changed
height = pipWin.innerHeight;
width = pipWin.innerWidth;
left = 200;
top = 100;
pipWin.moveTo(left, top);
// Now switch the video so the video ratio is different
await switchVideoSource("test-video-cropped.mp4");
await ensureMessageAndClosePiP(browser, "with-controls", pipWin, true);
pipWin = await triggerPictureInPicture(browser, "with-controls");
ok(pipWin, "Got Picture-in-Picture window.");
checkIfEqual(pipWin.screenX, left, "Opened at last X location");
checkIfEqual(pipWin.screenY, top, "Opened at last Y location");
checkIfEqual(
pipWin.innerHeight,
height,
"Opened height with previous width"
);
checkIfEqual(
pipWin.innerWidth,
height * (pipWin.innerWidth / pipWin.innerHeight),
"Width is changed to adjust for aspect ration"
);
left = 300;
top = 300;
pipWin.moveTo(left, top);
pipWin.resizeTo(defaultPiPWidth / 2, defaultPiPHeight / 2);
// Save height for when aspect ratio is changed
height = pipWin.innerHeight;
// Now switch the video so the video ratio is different
await switchVideoSource("test-video.mp4");
await ensureMessageAndClosePiP(browser, "with-controls", pipWin, true);
pipWin = await triggerPictureInPicture(browser, "with-controls");
ok(pipWin, "Got Picture-in-Picture window.");
checkIfEqual(pipWin.screenX, left, "Opened at last X location");
checkIfEqual(pipWin.screenY, top, "Opened at last Y location");
checkIfEqual(pipWin.innerHeight, height, "Opened with previous height");
checkIfEqual(
pipWin.innerWidth,
height * (pipWin.innerWidth / pipWin.innerHeight),
"Width is changed to adjust for aspect ration"
);
}
// Move so that part of PiP is off screen (bottom right)
left = rightEdge - Math.round((3 * pipWin.innerWidth) / 4);
top = bottomEdge - Math.round((3 * pipWin.innerHeight) / 4);
let movePromise = BrowserTestUtils.waitForEvent(
pipWin.windowRoot,
"MozUpdateWindowPos"
);
pipWin.moveTo(left, top);
await movePromise;
await ensureMessageAndClosePiP(browser, "with-controls", pipWin, true);
pipWin = await triggerPictureInPicture(browser, "with-controls");
ok(pipWin, "Got Picture-in-Picture window.");
// Redefine top and left to where the PiP windop will open
left = rightEdge - pipWin.innerWidth;
top = bottomEdge - pipWin.innerHeight;
// await new Promise(r => setTimeout(r, 5000));
// PiP is opened bottom right but not off screen
checkIfEqual(
pipWin.screenX,
left,
"Opened at last X location but shifted back on screen"
);
if (AppConstants.platform == "linux") {
checkIfEqual(
pipWin.screenY,
top - tabHeight,
"Opened at last Y location but shifted back on screen"
);
} else {
checkIfEqual(
pipWin.screenY,
top,
"Opened at last Y location but shifted back on screen"
);
}
// Move so that part of PiP is off screen (top left)
left = defaultX - Math.round(pipWin.innerWidth / 4);
top = defaultY - Math.round(pipWin.innerHeight / 4);
movePromise = BrowserTestUtils.waitForEvent(
pipWin.windowRoot,
"MozUpdateWindowPos"
);
pipWin.moveTo(left, top);
await movePromise;
await ensureMessageAndClosePiP(browser, "with-controls", pipWin, true);
pipWin = await triggerPictureInPicture(browser, "with-controls");
ok(pipWin, "Got Picture-in-Picture window.");
// PiP is opened top left on screen
checkIfEqual(
pipWin.screenX,
defaultX,
"Opened at last X location but shifted back on screen"
);
checkIfEqual(
pipWin.screenY,
defaultY,
"Opened at last Y location but shifted back on screen"
);
if (AppConstants.platform != "linux") {
// test that if video is on right edge and new video with smaller width
// is opened next, it is still on the right edge
left = rightEdge - pipWin.innerWidth;
top = Math.round(bottomEdge / 4);
pipWin.moveTo(left, top);
// Used to ensure that video width decreases for next PiP window
width = pipWin.innerWidth;
checkIfEqual(
pipWin.innerWidth + pipWin.screenX,
rightEdge,
"Video is on right edge before video is changed"
);
// Now switch the video so the video width is smaller
await switchVideoSource("test-video-cropped.mp4");
await ensureMessageAndClosePiP(browser, "with-controls", pipWin, true);
pipWin = await triggerPictureInPicture(browser, "with-controls");
ok(pipWin, "Got Picture-in-Picture window.");
checkIfEqual(
pipWin.innerWidth < width,
true,
"New video width is smaller"
);
checkIfEqual(
pipWin.innerWidth + pipWin.screenX,
rightEdge,
"Video is on right edge after video is changed"
);
}
}
);
});