зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1715179 - Handle `overflow: visible` case in OOP iframes. r=botond
Differential Revision: https://phabricator.services.mozilla.com/D193755
This commit is contained in:
Родитель
80e4683e9e
Коммит
d3d4a5137d
|
@ -79,6 +79,7 @@ async function test(aTestFile) {
|
|||
let resolution = await getResolution();
|
||||
ok(resolution > 0,
|
||||
"The initial_resolution is " + resolution + ", which is some sane value");
|
||||
let initial_resolution = resolution;
|
||||
|
||||
let pos = await targetElementPosition();
|
||||
const iframe = document.querySelector("iframe");
|
||||
|
@ -97,11 +98,18 @@ async function test(aTestFile) {
|
|||
|
||||
let zoomedOutState = cloneVisualViewport();
|
||||
|
||||
// Reset the scale to the initial one since in the `visible: overflow` case
|
||||
// the second double-tap doesn't restore to the initial scale.
|
||||
SpecialPowers.DOMWindowUtils.setResolutionAndScaleTo(initial_resolution);
|
||||
await promiseApzFlushedRepaints();
|
||||
|
||||
// Now load the document in an OOP iframe.
|
||||
iframeURL = iframeURL.replace(window.location.origin, "https://example.com");
|
||||
await setupIframe(iframeURL);
|
||||
|
||||
pos = await targetElementPosition();
|
||||
await doubleTapOn(iframe, pos.x + 10, pos.y + 10, useTouchpad);
|
||||
|
||||
prev_resolution = resolution;
|
||||
resolution = await getResolution();
|
||||
ok(resolution > prev_resolution, "The first double-tap has increased the resolution to " + resolution);
|
||||
|
@ -132,6 +140,10 @@ waitUntilApzStable()
|
|||
.then(async () => test("helper_doubletap_zoom_oopif_subframe-1.html"))
|
||||
// A test case where the layout scroll offset in the iframe isn't zero.
|
||||
.then(async () => test("helper_doubletap_zoom_oopif_subframe-2.html#target"))
|
||||
// A test case where the double-tap-to-zoom target element is `overflow: visible`.
|
||||
.then(async () => test("helper_doubletap_zoom_oopif_subframe-3.html#target"))
|
||||
// Similar to above but the target element has positive `margin-top`.
|
||||
.then(async () => test("helper_doubletap_zoom_oopif_subframe-4.html#target"))
|
||||
.then(subtestDone, subtestFailed);
|
||||
|
||||
</script>
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<script src="apz_test_native_event_utils.js"></script>
|
||||
<script src="apz_test_utils.js"></script>
|
||||
<script src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script src="/tests/SimpleTest/paint_listener.js"></script>
|
||||
<style>
|
||||
.container {
|
||||
background-color: #eee;
|
||||
width: 200px;
|
||||
height: 50px;
|
||||
border: 1px dotted black;
|
||||
overflow: visible;
|
||||
}
|
||||
</style>
|
||||
<div class="container"></div>
|
||||
<script>
|
||||
let text = "";
|
||||
for (let i = 0; i < 200; i++) {
|
||||
text += "Text text text text text text text text text text text text text text text text\n";
|
||||
}
|
||||
text += '<div id="target" style="width: 100%; height: 10px; background-color: red; position: relative; top: -20px; z-index: -1"></div>';
|
||||
document.querySelector(".container").innerHTML = text;
|
||||
|
||||
// Silence SimpleTest warning about missing assertions by having it wait
|
||||
// indefinitely. We don't need to give it an explicit finish because the
|
||||
// entire window this test runs in will be closed after the main browser test
|
||||
// finished.
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
</script>
|
||||
</html>
|
|
@ -0,0 +1,31 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<script src="apz_test_native_event_utils.js"></script>
|
||||
<script src="apz_test_utils.js"></script>
|
||||
<script src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script src="/tests/SimpleTest/paint_listener.js"></script>
|
||||
<style>
|
||||
.container {
|
||||
background-color: #eee;
|
||||
width: 200px;
|
||||
height: 50px;
|
||||
border: 1px dotted black;
|
||||
overflow: visible;
|
||||
margin-top: 200px;
|
||||
}
|
||||
</style>
|
||||
<div class="container"></div>
|
||||
<script>
|
||||
let text = '<div id="target" style="width: 100%; height: 10px; background-color: red; position: relative; top: 60px; z-index: -1"></div>';
|
||||
for (let i = 0; i < 200; i++) {
|
||||
text += "Text text text text text text text text text text text text text text text text\n";
|
||||
}
|
||||
document.querySelector(".container").innerHTML = text;
|
||||
|
||||
// Silence SimpleTest warning about missing assertions by having it wait
|
||||
// indefinitely. We don't need to give it an explicit finish because the
|
||||
// entire window this test runs in will be closed after the main browser test
|
||||
// finished.
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
</script>
|
||||
</html>
|
|
@ -11,6 +11,8 @@
|
|||
#include "mozilla/PresShell.h"
|
||||
#include "mozilla/AlreadyAddRefed.h"
|
||||
#include "mozilla/dom/Element.h"
|
||||
#include "mozilla/dom/EffectsInfo.h"
|
||||
#include "mozilla/dom/BrowserChild.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIContent.h"
|
||||
#include "mozilla/dom/Document.h"
|
||||
|
@ -104,9 +106,10 @@ static CSSRect GetBoundingContentRect(
|
|||
const nsIScrollableFrame* aRootScrollFrame,
|
||||
const DoubleTapToZoomMetrics& aMetrics,
|
||||
mozilla::Maybe<CSSRect>* aOutNearestScrollClip = nullptr) {
|
||||
CSSRect result = nsLayoutUtils::GetBoundingContentRect(
|
||||
aElement, aRootScrollFrame, aOutNearestScrollClip);
|
||||
if (aInProcessRootContentDocument->IsTopLevelContentDocument()) {
|
||||
return nsLayoutUtils::GetBoundingContentRect(aElement, aRootScrollFrame,
|
||||
aOutNearestScrollClip);
|
||||
return result;
|
||||
}
|
||||
|
||||
nsIFrame* frame = aElement->GetPrimaryFrame();
|
||||
|
@ -114,6 +117,24 @@ static CSSRect GetBoundingContentRect(
|
|||
return CSSRect();
|
||||
}
|
||||
|
||||
// If the nearest scroll frame is |aRootScrollFrame|,
|
||||
// nsLayoutUtils::GetBoundingContentRect doesn't set |aOutNearestScrollClip|,
|
||||
// thus in the cases of OOP iframs, we need to use the visible rect of the
|
||||
// iframe as the nearest scroll clip.
|
||||
if (aOutNearestScrollClip && aOutNearestScrollClip->isNothing()) {
|
||||
if (dom::BrowserChild* browserChild =
|
||||
dom::BrowserChild::GetFrom(frame->PresShell())) {
|
||||
const dom::EffectsInfo& effectsInfo = browserChild->GetEffectsInfo();
|
||||
if (effectsInfo.IsVisible()) {
|
||||
*aOutNearestScrollClip =
|
||||
effectsInfo.mVisibleRect.map([&aMetrics](const nsRect& aRect) {
|
||||
return aMetrics.mTransformMatrix.TransformBounds(
|
||||
CSSRect::FromAppUnits(aRect));
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// In the case of an element inside an OOP iframe, |aMetrics.mTransformMatrix|
|
||||
// includes the translation information about the root layout scroll offset,
|
||||
// thus we use nsIFrame::GetBoundingClientRect rather than
|
||||
|
@ -301,6 +322,15 @@ ZoomTarget CalculateRectToZoomTo(
|
|||
res == nsLayoutUtils::NONINVERTIBLE_TRANSFORM);
|
||||
if (res == nsLayoutUtils::TRANSFORM_SUCCEEDED) {
|
||||
CSSRect overflowRectCSS = CSSRect::FromAppUnits(overflowRect);
|
||||
|
||||
// In the case of OOP iframes, above |overflowRectCSS| in the iframe
|
||||
// documents coords, we need to convert it into the top level coords.
|
||||
if (!aInProcessRootContentDocument->IsTopLevelContentDocument()) {
|
||||
overflowRectCSS.MoveBy(
|
||||
CSSPoint::FromAppUnits(-rootScrollFrame->GetScrollPosition()));
|
||||
overflowRectCSS =
|
||||
aMetrics.mTransformMatrix.TransformBounds(overflowRectCSS);
|
||||
}
|
||||
if (nearestScrollClip.isSome()) {
|
||||
overflowRectCSS = nearestScrollClip->Intersect(overflowRectCSS);
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче