зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1601933 - Use visual viewport width or height for GeckoView::ScrollBy and ScrollTo. r=botond,rbarker,agi
Since bug 1514429 window.inner{Width,Height} don't return the visual viewport size so once after the content scale changed, i.e. the visual viewport size doesn't match window inner size, GeckoView::ScrollBy and ScrollTo don't work as expected. This commit has JUnit tests to generate the situation by calling nsIDOMWindowUtils.setResolutionAndScaleTo. Differential Revision: https://phabricator.services.mozilla.com/D56321 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
a20a9e1065
Коммит
abc58dd4e5
|
@ -100,9 +100,9 @@ class GeckoViewContentChild extends GeckoViewChildModule {
|
|||
if (aType === SCREEN_LENGTH_TYPE_PIXEL) {
|
||||
return aLength;
|
||||
} else if (aType === SCREEN_LENGTH_TYPE_VIEWPORT_WIDTH) {
|
||||
return aLength * content.innerWidth;
|
||||
return aLength * content.visualViewport.width;
|
||||
} else if (aType === SCREEN_LENGTH_TYPE_VIEWPORT_HEIGHT) {
|
||||
return aLength * content.innerHeight;
|
||||
return aLength * content.visualViewport.height;
|
||||
} else if (aType === SCREEN_LENGTH_DOCUMENT_WIDTH) {
|
||||
return aLength * content.document.body.scrollWidth;
|
||||
} else if (aType === SCREEN_LENGTH_DOCUMENT_HEIGHT) {
|
||||
|
|
|
@ -26,6 +26,9 @@ const APIS = {
|
|||
SetPrefs: function({ oldPrefs, newPrefs }) {
|
||||
return browser.test.setPrefs(oldPrefs, newPrefs);
|
||||
},
|
||||
SetResolutionAndScaleTo: function({ resolution }) {
|
||||
return browser.test.setResolutionAndScaleTo(resolution);
|
||||
},
|
||||
};
|
||||
|
||||
port.onMessage.addListener(async message => {
|
||||
|
|
|
@ -35,6 +35,15 @@ function linkColorFrameScript() {
|
|||
});
|
||||
}
|
||||
|
||||
function setResolutionAndScaleToFrameScript(resolution) {
|
||||
addMessageListener("PanZoomControllerTest:SetResolutionAndScaleTo", () => {
|
||||
content.window.visualViewport.addEventListener("resize", () => {
|
||||
sendAsyncMessage("PanZoomControllerTest:SetResolutionAndScaleTo");
|
||||
});
|
||||
content.windowUtils.setResolutionAndScaleTo(resolution);
|
||||
});
|
||||
}
|
||||
|
||||
this.test = class extends ExtensionAPI {
|
||||
getAPI(context) {
|
||||
return {
|
||||
|
@ -112,6 +121,31 @@ this.test = class extends ExtensionAPI {
|
|||
async setScalar(id, value) {
|
||||
return Services.telemetry.scalarSet(id, value);
|
||||
},
|
||||
|
||||
async setResolutionAndScaleTo(resolution) {
|
||||
const frameScript = `data:text/javascript,(${encodeURI(
|
||||
setResolutionAndScaleToFrameScript
|
||||
)}).call(this, ${resolution})`;
|
||||
Services.mm.loadFrameScript(frameScript, true);
|
||||
|
||||
return new Promise(resolve => {
|
||||
const onMessage = () => {
|
||||
Services.mm.removeMessageListener(
|
||||
"PanZoomControllerTest:SetResolutionAndScaleTo",
|
||||
onMessage
|
||||
);
|
||||
resolve();
|
||||
};
|
||||
|
||||
Services.mm.addMessageListener(
|
||||
"PanZoomControllerTest:SetResolutionAndScaleTo",
|
||||
onMessage
|
||||
);
|
||||
Services.mm.broadcastAsyncMessage(
|
||||
"PanZoomControllerTest:SetResolutionAndScaleTo"
|
||||
);
|
||||
});
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
|
|
@ -104,6 +104,18 @@
|
|||
"name": "value"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "setResolutionAndScaleTo",
|
||||
"type": "function",
|
||||
"async": true,
|
||||
"description": "Invokes nsIDOMWindowUtils.setResolutionAndScaleTo.",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "number",
|
||||
"name": "resolution"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=0.5">
|
||||
<style type="text/css">
|
||||
body {
|
||||
background-color: white;
|
||||
|
|
|
@ -163,6 +163,46 @@ class PanZoomControllerTest : BaseSessionTest() {
|
|||
scrollToVertical(PanZoomController.SCROLL_BEHAVIOR_AUTO)
|
||||
}
|
||||
|
||||
private fun scrollToVerticalOnZoomedContent(mode: Int) {
|
||||
setup()
|
||||
|
||||
val originalVH = mainSession.evaluateJS("window.visualViewport.height") as Double
|
||||
assertThat("Visual viewport height is not zero", originalVH, greaterThan(0.0))
|
||||
|
||||
val innerHeight = mainSession.evaluateJS("window.innerHeight") as Double
|
||||
assertThat("Visual viewport height equals to window.innerHeight", originalVH, equalTo(innerHeight))
|
||||
|
||||
val originalScale = mainSession.evaluateJS("visualViewport.scale") as Double
|
||||
assertThat("Visual viewport scale is the initial scale", originalScale, closeTo(0.5, 0.01))
|
||||
|
||||
// Change the resolution so that the visual viewport will be different from the layout viewport.
|
||||
sessionRule.setResolutionAndScaleTo(2.0f)
|
||||
|
||||
val scale = mainSession.evaluateJS("visualViewport.scale") as Double
|
||||
assertThat("Visual viewport scale is now greater than the initial scale", scale, greaterThan(originalScale))
|
||||
|
||||
val vh = mainSession.evaluateJS("window.visualViewport.height") as Double
|
||||
assertThat("Visual viewport height has been changed", vh, lessThan(originalVH))
|
||||
|
||||
sessionRule.session.panZoomController.scrollTo(ScreenLength.zero(), ScreenLength.fromViewportHeight(1.0), mode)
|
||||
|
||||
waitForVerticalScroll(vh, scrollWaitTimeout)
|
||||
val scrollY = mainSession.evaluateJS("window.visualViewport.pageTop") as Double
|
||||
assertThat("scrollBy should have scrolled along y axis one viewport", scrollY, closeTo(vh, errorEpsilon))
|
||||
}
|
||||
|
||||
@WithDisplay(width = 100, height = 100)
|
||||
@Test
|
||||
fun scrollToVerticalOnZoomedContentSmooth() {
|
||||
scrollToVerticalOnZoomedContent(PanZoomController.SCROLL_BEHAVIOR_SMOOTH)
|
||||
}
|
||||
|
||||
@WithDisplay(width = 100, height = 100)
|
||||
@Test
|
||||
fun scrollToVerticalOnZoomedContentAuto() {
|
||||
scrollToVerticalOnZoomedContent(PanZoomController.SCROLL_BEHAVIOR_AUTO)
|
||||
}
|
||||
|
||||
private fun scrollToVerticalTwice(mode: Int) {
|
||||
setup()
|
||||
val vh = mainSession.evaluateJS("window.innerHeight") as Double
|
||||
|
|
|
@ -2060,6 +2060,15 @@ public class GeckoSessionTestRule implements TestRule {
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Invokes nsIDOMWindowUtils.setResolutionAndScaleTo.
|
||||
*/
|
||||
public void setResolutionAndScaleTo(final float resolution) {
|
||||
webExtensionApiCall("SetResolutionAndScaleTo", args -> {
|
||||
args.put("resolution", resolution);
|
||||
});
|
||||
}
|
||||
|
||||
private Object webExtensionApiCall(final String apiName, SetArgs argsSetter) {
|
||||
// Ensure background script is connected
|
||||
UiThreadUtils.waitForCondition(() -> RuntimeCreator.backgroundPort() != null,
|
||||
|
|
Загрузка…
Ссылка в новой задаче