зеркало из 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) {
|
if (aType === SCREEN_LENGTH_TYPE_PIXEL) {
|
||||||
return aLength;
|
return aLength;
|
||||||
} else if (aType === SCREEN_LENGTH_TYPE_VIEWPORT_WIDTH) {
|
} 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) {
|
} else if (aType === SCREEN_LENGTH_TYPE_VIEWPORT_HEIGHT) {
|
||||||
return aLength * content.innerHeight;
|
return aLength * content.visualViewport.height;
|
||||||
} else if (aType === SCREEN_LENGTH_DOCUMENT_WIDTH) {
|
} else if (aType === SCREEN_LENGTH_DOCUMENT_WIDTH) {
|
||||||
return aLength * content.document.body.scrollWidth;
|
return aLength * content.document.body.scrollWidth;
|
||||||
} else if (aType === SCREEN_LENGTH_DOCUMENT_HEIGHT) {
|
} else if (aType === SCREEN_LENGTH_DOCUMENT_HEIGHT) {
|
||||||
|
|
|
@ -26,6 +26,9 @@ const APIS = {
|
||||||
SetPrefs: function({ oldPrefs, newPrefs }) {
|
SetPrefs: function({ oldPrefs, newPrefs }) {
|
||||||
return browser.test.setPrefs(oldPrefs, newPrefs);
|
return browser.test.setPrefs(oldPrefs, newPrefs);
|
||||||
},
|
},
|
||||||
|
SetResolutionAndScaleTo: function({ resolution }) {
|
||||||
|
return browser.test.setResolutionAndScaleTo(resolution);
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
port.onMessage.addListener(async message => {
|
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 {
|
this.test = class extends ExtensionAPI {
|
||||||
getAPI(context) {
|
getAPI(context) {
|
||||||
return {
|
return {
|
||||||
|
@ -112,6 +121,31 @@ this.test = class extends ExtensionAPI {
|
||||||
async setScalar(id, value) {
|
async setScalar(id, value) {
|
||||||
return Services.telemetry.scalarSet(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": "value"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "setResolutionAndScaleTo",
|
||||||
|
"type": "function",
|
||||||
|
"async": true,
|
||||||
|
"description": "Invokes nsIDOMWindowUtils.setResolutionAndScaleTo.",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"type": "number",
|
||||||
|
"name": "resolution"
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<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">
|
<style type="text/css">
|
||||||
body {
|
body {
|
||||||
background-color: white;
|
background-color: white;
|
||||||
|
|
|
@ -163,6 +163,46 @@ class PanZoomControllerTest : BaseSessionTest() {
|
||||||
scrollToVertical(PanZoomController.SCROLL_BEHAVIOR_AUTO)
|
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) {
|
private fun scrollToVerticalTwice(mode: Int) {
|
||||||
setup()
|
setup()
|
||||||
val vh = mainSession.evaluateJS("window.innerHeight") as Double
|
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) {
|
private Object webExtensionApiCall(final String apiName, SetArgs argsSetter) {
|
||||||
// Ensure background script is connected
|
// Ensure background script is connected
|
||||||
UiThreadUtils.waitForCondition(() -> RuntimeCreator.backgroundPort() != null,
|
UiThreadUtils.waitForCondition(() -> RuntimeCreator.backgroundPort() != null,
|
||||||
|
|
Загрузка…
Ссылка в новой задаче