Skip to content

Commit afdbabf

Browse files
masayuki-nakanomoz-wptsync-bot
authored andcommitted
Make PresShell::EventHandler::DispatchPrecedingPointerEvent update event target after dispatching a pointer event
The reason of the bug is, no `mouseup` event is fired after the `pointerup` event listener removed the target. Therefore, `nsIFrame::HandleRelease()` does not run and nobody cleans up the drag state of the `nsFrameSelection`. This is caused by that `PresShell::EventHandler::DispatchPrecedingPointerEvent()` updates only event target frame of the following mouse event target if the pointer event target was removed from the tree, however, the frame may not be ready. In this case, `PresShell::GetCurrentContent()` will clear both current event target content and frame because its composed document (`nullptr`) never matches with the document for the `PresShell`. Therefore, it needs to update the target too. This patch makes all developers won't create similar bugs, this encapsulate `EventTargetData::mContent` and `EventTargetData::mFrame` to make their setters clean up or automatically check the relation. Differential Revision: https://phabricator.services.mozilla.com/D201053 bugzilla-url: https://bugzilla.mozilla.org/show_bug.cgi?id=1877815 gecko-commit: 88c50740c90849f41b36a3ebdea5c1182d010b62 gecko-reviewers: smaug
1 parent 86c2abe commit afdbabf

File tree

1 file changed

+96
-0
lines changed

1 file changed

+96
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
<!doctype html>
2+
<html>
3+
<head>
4+
<meta charset="utf-8">
5+
<title>After pointerup target is removed, selection should not be updated by pointer move</title>
6+
<script src='/resources/testharness.js'></script>
7+
<script src='/resources/testharnessreport.js'></script>
8+
<script src="/resources/testdriver.js"></script>
9+
<script src="/resources/testdriver-actions.js"></script>
10+
<script src="/resources/testdriver-vendor.js"></script>
11+
<script>
12+
"use strict";
13+
14+
/**
15+
* This behavior is not defined in any spec, but even if browser supports
16+
* expanding selection across text nodes with dragging a pointer, it should
17+
* not work after pointerup whose target is removed by a pointerup event
18+
* listener.
19+
*/
20+
21+
addEventListener("load", async () => {
22+
const span1 = document.querySelector("span");
23+
const span2 = span1.nextSibling;
24+
const span3 = span2.nextSibling;
25+
const button = document.querySelector("button");
26+
27+
promise_test(async () => {
28+
const overlay = document.createElement("div");
29+
overlay.className = "overlay";
30+
overlay.addEventListener("pointerup", () => {
31+
overlay.remove();
32+
});
33+
document.body.appendChild(overlay);
34+
overlay.style.display = "block";
35+
await new Promise(resolve => {
36+
requestAnimationFrame(() => requestAnimationFrame(resolve));
37+
});
38+
await new test_driver.Actions()
39+
.pointerMove(10, 10, {origin: span1})
40+
.pointerDown()
41+
.pointerUp()
42+
.pointerMove(10, 10, {origin: span2})
43+
.addTick()
44+
.pointerMove(10, 10, {origin: span3})
45+
.addTick()
46+
.send();
47+
assert_true(getSelection().isCollapsed);
48+
}, "pointermove after pointerup which deletes the overlay should not keep expanding selection");
49+
50+
promise_test(async () => {
51+
const overlay = document.createElement("div");
52+
overlay.className = "overlay";
53+
overlay.addEventListener("pointerup", () => {
54+
button.focus();
55+
overlay.remove();
56+
});
57+
document.body.appendChild(overlay);
58+
overlay.style.display = "block";
59+
await new Promise(resolve => {
60+
requestAnimationFrame(() => requestAnimationFrame(resolve));
61+
});
62+
await new test_driver.Actions()
63+
.pointerMove(10, 10, {origin: span1})
64+
.pointerDown()
65+
.pointerUp()
66+
.pointerMove(10, 10, {origin: span2})
67+
.addTick()
68+
.pointerMove(10, 10, {origin: span3})
69+
.addTick()
70+
.send();
71+
assert_true(getSelection().isCollapsed);
72+
}, "pointermove after pointerup which deletes the overlay and move focus to the button should not keep expanding selection");
73+
}, {once: true});
74+
</script>
75+
<style>
76+
div.overlay {
77+
position: fixed;
78+
top: 0;
79+
left: 0;
80+
width: 100%;
81+
height: 100%;
82+
background: rgba(0, 0, 0, 0.5);
83+
display: none;
84+
}
85+
#container {
86+
font-size: 32px;
87+
}
88+
</style>
89+
</head>
90+
<body>
91+
<div id="container">
92+
<span>abc</span><span>def</span><span>ghi</span><br>
93+
<button>button</button>
94+
</div>
95+
</body>
96+
</html>

0 commit comments

Comments
 (0)