forked from mirrors/gecko-dev
Bug 1733509 - Use TryInferEnclosingResolution for event retargeting. r=botond
Differential Revision: https://phabricator.services.mozilla.com/D205378
This commit is contained in:
parent
1f3a258de0
commit
5cd899a399
7 changed files with 147 additions and 15 deletions
|
|
@ -91,5 +91,17 @@ GpuProcessQueryId GpuProcessQueryId::GetNext() {
|
|||
return GpuProcessQueryId{++sCounter};
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, ScrollDirection aDirection) {
|
||||
switch (aDirection) {
|
||||
case ScrollDirection::eHorizontal:
|
||||
os << "horizontal";
|
||||
break;
|
||||
case ScrollDirection::eVertical:
|
||||
os << "vertical";
|
||||
break;
|
||||
}
|
||||
return os;
|
||||
}
|
||||
|
||||
} // namespace layers
|
||||
} // namespace mozilla
|
||||
|
|
|
|||
|
|
@ -463,6 +463,8 @@ MOZ_DEFINE_ENUM_CLASS_WITH_BASE(ScrollDirection, uint8_t, (
|
|||
eHorizontal
|
||||
));
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, ScrollDirection aDirection);
|
||||
|
||||
using ScrollDirections = EnumSet<ScrollDirection, uint8_t>;
|
||||
|
||||
constexpr ScrollDirections EitherScrollDirection(ScrollDirection::eVertical,ScrollDirection::eHorizontal);
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
#include "PositionedEventTargeting.h"
|
||||
|
||||
#include "Units.h"
|
||||
#include "mozilla/EventListenerManager.h"
|
||||
#include "mozilla/MouseEvents.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
|
|
@ -13,18 +14,23 @@
|
|||
#include "mozilla/StaticPrefs_dom.h"
|
||||
#include "mozilla/StaticPrefs_ui.h"
|
||||
#include "mozilla/ToString.h"
|
||||
#include "mozilla/ViewportUtils.h"
|
||||
#include "mozilla/dom/MouseEventBinding.h"
|
||||
#include "mozilla/gfx/Matrix.h"
|
||||
#include "mozilla/layers/LayersTypes.h"
|
||||
#include "nsContainerFrame.h"
|
||||
#include "nsCoord.h"
|
||||
#include "nsFrameList.h" // for DEBUG_FRAME_DUMP
|
||||
#include "nsHTMLParts.h"
|
||||
#include "nsLayoutUtils.h"
|
||||
#include "nsGkAtoms.h"
|
||||
#include "nsFontMetrics.h"
|
||||
#include "nsIContentInlines.h"
|
||||
#include "nsPresContext.h"
|
||||
#include "nsPrintfCString.h"
|
||||
#include "mozilla/dom/Element.h"
|
||||
#include "nsRegion.h"
|
||||
#include "nsDeviceContext.h"
|
||||
#include "nsIContentInlines.h"
|
||||
#include "nsIFrame.h"
|
||||
#include <algorithm>
|
||||
|
||||
|
|
@ -276,15 +282,40 @@ static nsIContent* GetClickableAncestor(
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
static nscoord AppUnitsFromMM(RelativeTo aFrame, uint32_t aMM) {
|
||||
nsPresContext* pc = aFrame.mFrame->PresContext();
|
||||
float result = float(aMM) * (pc->DeviceContext()->AppUnitsPerPhysicalInch() /
|
||||
MM_PER_INCH_FLOAT);
|
||||
if (aFrame.mViewportType == ViewportType::Layout) {
|
||||
PresShell* presShell = pc->PresShell();
|
||||
result = result / presShell->GetResolution();
|
||||
static Scale2D AppUnitsToMMScale(RelativeTo aFrame) {
|
||||
nsPresContext* presContext = aFrame.mFrame->PresContext();
|
||||
|
||||
const int32_t appUnitsPerInch =
|
||||
presContext->DeviceContext()->AppUnitsPerPhysicalInch();
|
||||
const float appUnits =
|
||||
static_cast<float>(appUnitsPerInch) / MM_PER_INCH_FLOAT;
|
||||
|
||||
// Visual coordinates are only used for quantities relative to the
|
||||
// cross-process root content document's root frame. There should
|
||||
// not be an enclosing resolution or transform scale above that.
|
||||
if (aFrame.mViewportType != ViewportType::Layout) {
|
||||
const nscoord scale = NSToCoordRound(appUnits);
|
||||
return Scale2D{static_cast<float>(scale), static_cast<float>(scale)};
|
||||
}
|
||||
return NSToCoordRound(result);
|
||||
|
||||
Scale2D localResolution{1.0f, 1.0f};
|
||||
Scale2D enclosingResolution{1.0f, 1.0f};
|
||||
|
||||
if (auto* pc = presContext->GetInProcessRootContentDocumentPresContext()) {
|
||||
PresShell* presShell = pc->PresShell();
|
||||
localResolution = {presShell->GetResolution(), presShell->GetResolution()};
|
||||
enclosingResolution = ViewportUtils::TryInferEnclosingResolution(presShell);
|
||||
}
|
||||
|
||||
const gfx::MatrixScales parentScale =
|
||||
nsLayoutUtils::GetTransformToAncestorScale(aFrame.mFrame);
|
||||
const Scale2D resolution =
|
||||
localResolution * parentScale * enclosingResolution;
|
||||
|
||||
const nscoord scaleX = NSToCoordRound(appUnits / resolution.xScale);
|
||||
const nscoord scaleY = NSToCoordRound(appUnits / resolution.yScale);
|
||||
|
||||
return {static_cast<float>(scaleX), static_cast<float>(scaleY)};
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -303,10 +334,11 @@ static nsRect GetTargetRect(RelativeTo aRootFrame,
|
|||
const nsPoint& aPointRelativeToRootFrame,
|
||||
const nsIFrame* aRestrictToDescendants,
|
||||
const EventRadiusPrefs& aPrefs, uint32_t aFlags) {
|
||||
nsMargin m(AppUnitsFromMM(aRootFrame, aPrefs.mRadiusTopmm),
|
||||
AppUnitsFromMM(aRootFrame, aPrefs.mRadiusRightmm),
|
||||
AppUnitsFromMM(aRootFrame, aPrefs.mRadiusBottommm),
|
||||
AppUnitsFromMM(aRootFrame, aPrefs.mRadiusLeftmm));
|
||||
const Scale2D scale = AppUnitsToMMScale(aRootFrame);
|
||||
nsMargin m(aPrefs.mRadiusTopmm * scale.yScale,
|
||||
aPrefs.mRadiusRightmm * scale.xScale,
|
||||
aPrefs.mRadiusBottommm * scale.yScale,
|
||||
aPrefs.mRadiusLeftmm * scale.xScale);
|
||||
nsRect r(aPointRelativeToRootFrame, nsSize(0, 0));
|
||||
r.Inflate(m);
|
||||
if (!(aFlags & INPUT_IGNORE_ROOT_SCROLL_FRAME)) {
|
||||
|
|
|
|||
|
|
@ -260,6 +260,9 @@ const nsIFrame* ViewportUtils::IsZoomedContentRoot(const nsIFrame* aFrame) {
|
|||
}
|
||||
|
||||
Scale2D ViewportUtils::TryInferEnclosingResolution(PresShell* aShell) {
|
||||
if (!XRE_IsContentProcess()) {
|
||||
return {1.0f, 1.0f};
|
||||
}
|
||||
MOZ_ASSERT(aShell && aShell->GetPresContext());
|
||||
MOZ_ASSERT(!aShell->GetPresContext()->GetParentPresContext(),
|
||||
"TryInferEnclosingResolution can only be called for a root pres "
|
||||
|
|
|
|||
30
layout/base/tests/helper_bug1733509.html
Normal file
30
layout/base/tests/helper_bug1733509.html
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
<html>
|
||||
<script src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<script src="/tests/SimpleTest/paint_listener.js"></script>
|
||||
<script src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="/tests/gfx/layers/apz/test/mochitest/apz_test_utils.js"></script>
|
||||
<style>
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 20;
|
||||
background-color: blueviolet;
|
||||
}
|
||||
|
||||
button {
|
||||
margin: 0;
|
||||
}
|
||||
</style>
|
||||
|
||||
<body>
|
||||
<button id="btn">Click me</button>
|
||||
</body>
|
||||
|
||||
<script>
|
||||
// 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>
|
||||
|
|
@ -247,6 +247,7 @@ support-files = ["file_dynamic_toolbar_max_height.html"]
|
|||
["test_emulate_color_scheme.html"]
|
||||
|
||||
["test_event_target_radius.html"]
|
||||
support-files = ["helper_bug1733509.html"]
|
||||
skip-if = ["xorigin"] # JavaScript error: resource://specialpowers/SpecialPowersChild.sys.mjs, line 73: SecurityError: Permission denied to access property "windowUtils" on cross-origin object
|
||||
|
||||
["test_frame_reconstruction_body_table.html"]
|
||||
|
|
|
|||
|
|
@ -2,14 +2,19 @@
|
|||
<html id="html" style="height:100%">
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=780847
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=1733509
|
||||
-->
|
||||
<head>
|
||||
<title>Test radii for mouse events</title>
|
||||
<script src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<script src="/tests/SimpleTest/paint_listener.js"></script>
|
||||
<script src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="/tests/gfx/layers/apz/test/mochitest/apz_test_utils.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<style>
|
||||
.target { position:absolute; left:100px; top:100px; width:100px; height:100px; background:blue; }
|
||||
.scaled { background: green; transform: scale(0.5); }
|
||||
iframe { margin:0; padding:0; width:50; height:50; border:1px solid black; background:yellowgreen; }
|
||||
</style>
|
||||
</head>
|
||||
<body id="body" onload="setTimeout(startTest, 0)" style="margin:0; width:100%; height:100%; overflow:hidden">
|
||||
|
|
@ -73,6 +78,10 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=780847
|
|||
<div id="t13_touchlistener" style="width: 50px; height: 50px; background:red" ontouchend="x=1"></div>
|
||||
<div id="t13_notouchlistener" style="width: 50px; height: 50px; background:green"></div>
|
||||
</div>
|
||||
|
||||
<div id="t14" class="target scaled" hidden>
|
||||
<iframe id="t14iframe"></iframe>
|
||||
</div>
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
|
@ -414,7 +423,50 @@ function testTouchable() {
|
|||
testTouch("t13", 10, 50 - (2*mm), "t13_touchlistener", "touch inside t13_touchlistener bottom edge");
|
||||
setShowing("t13", false);
|
||||
|
||||
endTest();
|
||||
test4();
|
||||
}
|
||||
|
||||
// https://bugzilla.mozilla.org/show_bug.cgi?id=1733509
|
||||
function test4() {
|
||||
// Skip non-Fission for now because of bug 1890522
|
||||
if (SpecialPowers.Services.appinfo.fissionAutostart) {
|
||||
waitUntilApzStable().then(async () => doTest4()).then(endTest);
|
||||
} else {
|
||||
endTest();
|
||||
}
|
||||
}
|
||||
|
||||
async function doTest4() {
|
||||
setShowing("t14", true);
|
||||
|
||||
let iframeURL = SimpleTest.getTestFileURL("helper_bug1733509.html");
|
||||
// todo: Also perform this test for an in-process iframe
|
||||
// once bug 1890522 is fixed.
|
||||
const iframe = document.querySelector("#t14iframe");
|
||||
iframeURL = iframeURL.replace(window.location.origin, "https://example.com");
|
||||
await setupIframe(iframe, iframeURL);
|
||||
|
||||
var result = await SpecialPowers.spawn(iframe, [], async () => {
|
||||
await content.wrappedJSObject.waitUntilApzStable();
|
||||
var iframeEventTarget = null;
|
||||
content.window.onmousedown = function (event) { iframeEventTarget = event.target; };
|
||||
content.wrappedJSObject.synthesizeMouse(content.document.documentElement, 2, 2, {});
|
||||
return iframeEventTarget && iframeEventTarget.id === "btn";
|
||||
});
|
||||
|
||||
ok(result, "Failed to target button inside iframe");
|
||||
setShowing("t14", false);
|
||||
}
|
||||
|
||||
async function setupIframe(aIFrame, aURL) {
|
||||
const iframeLoadPromise = promiseOneEvent(aIFrame, "load", null);
|
||||
aIFrame.src = aURL;
|
||||
await iframeLoadPromise;
|
||||
|
||||
await SpecialPowers.spawn(aIFrame, [], async () => {
|
||||
await content.wrappedJSObject.waitUntilApzStable();
|
||||
await SpecialPowers.contentTransformsReceived(content);
|
||||
});
|
||||
}
|
||||
</script>
|
||||
</pre>
|
||||
|
|
|
|||
Loading…
Reference in a new issue