зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1715603 - part 2: Make `AutoScrollChild` not start autoscroll if a modifier key is pressed r=Gijs
Now, `nsIFrame::HandleEvent` moves selection at middle mouse button down. This occurs before dispatching the event into the system event group. Therefore, `AutoScrollChild` cannot prevent it. On the other hand, Chrome does not start autoscroll when a modifier is pressed. This means that our users may not be able to use middle click with modifiers if web apps do not call `preventDefault()` as expected. So, this difference is a potential risk of web-compat. Therefore, this patch makes `AutoScrollChild` stop starting autoscroll if `Shift` key is pressed. Differential Revision: https://phabricator.services.mozilla.com/D119253
This commit is contained in:
Родитель
1125b625c3
Коммит
f334ac54b8
|
@ -221,6 +221,14 @@ pref("general.config.obscure_value", 13); // for MCD .cfg files
|
|||
pref("general.warnOnAboutConfig", true);
|
||||
#endif
|
||||
|
||||
// Whether middle button click with a modifier key starts to autoscroll or
|
||||
// does nothing.
|
||||
pref("general.autoscroll.prevent_to_start.shiftKey", true); // Shift
|
||||
pref("general.autoscroll.prevent_to_start.ctrlKey", false); // Control
|
||||
pref("general.autoscroll.prevent_to_start.altKey", false); // Alt
|
||||
pref("general.autoscroll.prevent_to_start.metaKey", false); // Command on macOS
|
||||
pref("general.autoscroll.prevent_to_start.osKey", false); // Windows key on Windows or Super key on Linux
|
||||
|
||||
// maximum number of dated backups to keep at any time
|
||||
pref("browser.bookmarks.max_backups", 5);
|
||||
|
||||
|
|
|
@ -337,6 +337,36 @@ class AutoScrollChild extends JSWindowActorChild {
|
|||
this._scrollable.ownerGlobal.requestAnimationFrame(this.autoscrollLoop);
|
||||
}
|
||||
|
||||
canStartAutoScrollWith(event) {
|
||||
if (
|
||||
!event.isTrusted ||
|
||||
event.defaultPrevented ||
|
||||
event.button !== 1 ||
|
||||
event.clickEventPrevented()
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (const modifier of ["shift", "alt", "ctrl", "meta"]) {
|
||||
if (
|
||||
event[modifier + "Key"] &&
|
||||
Services.prefs.getBoolPref(
|
||||
`general.autoscroll.prevent_to_start.${modifier}Key`,
|
||||
false
|
||||
)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (
|
||||
event.getModifierState("OS") &&
|
||||
Services.prefs.getBoolPref("general.autoscroll.prevent_to_start.osKey")
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
handleEvent(event) {
|
||||
switch (event.type) {
|
||||
case "mousemove":
|
||||
|
@ -345,10 +375,7 @@ class AutoScrollChild extends JSWindowActorChild {
|
|||
break;
|
||||
case "mousedown":
|
||||
if (
|
||||
event.isTrusted &&
|
||||
!event.defaultPrevented &&
|
||||
event.button === 1 &&
|
||||
!event.clickEventPrevented() &&
|
||||
this.canStartAutoScrollWith(event) &&
|
||||
!this._scrollable &&
|
||||
!this.isAutoscrollBlocker(event.originalTarget)
|
||||
) {
|
||||
|
|
|
@ -143,6 +143,7 @@ add_task(async function() {
|
|||
}
|
||||
}
|
||||
|
||||
await SpecialPowers.pushPrefEnv({ set: [["middlemouse.paste", true]] });
|
||||
await (async function testMouseEventsAtStartingAutoScrolling() {
|
||||
info(
|
||||
"Waiting autoscroller popup for testing mouse events at starting autoscrolling"
|
||||
|
@ -204,6 +205,111 @@ add_task(async function() {
|
|||
await waitForAutoScrollEnd;
|
||||
})();
|
||||
|
||||
if (
|
||||
// Bug 1693240: We don't support setting modifiers while posting a mouse event on Windows.
|
||||
!navigator.platform.includes("Win") &&
|
||||
// Bug 1693237: We don't support setting modifiers on Android.
|
||||
!navigator.appVersion.includes("Android") &&
|
||||
// In Headless mode, modifiers are not supported by this kind of APIs.
|
||||
!Cc["@mozilla.org/gfx/info;1"].getService(Ci.nsIGfxInfo).isHeadless
|
||||
) {
|
||||
await SpecialPowers.pushPrefEnv({
|
||||
set: [
|
||||
["general.autoscroll.prevent_to_start.shiftKey", true],
|
||||
["general.autoscroll.prevent_to_start.altKey", true],
|
||||
["general.autoscroll.prevent_to_start.ctrlKey", true],
|
||||
["general.autoscroll.prevent_to_start.metaKey", true],
|
||||
],
|
||||
});
|
||||
for (const modifier of ["Shift", "Control", "Alt", "Meta"]) {
|
||||
if (modifier == "Meta" && !navigator.platform.includes("Mac")) {
|
||||
continue; // Delete this after fixing bug 1232918.
|
||||
}
|
||||
await (async function modifiersPreventToStartAutoScrolling() {
|
||||
info(
|
||||
`Waiting to check not to open autoscroller popup with middle button click with ${modifier}`
|
||||
);
|
||||
await promiseFlushLayoutInContent();
|
||||
let eventsInContent = new ContentEventCounter(browser, [
|
||||
"click",
|
||||
"auxclick",
|
||||
"mousedown",
|
||||
"mouseup",
|
||||
"paste",
|
||||
]);
|
||||
// Ensure that the event listeners added in the content with accessing
|
||||
// the remote content.
|
||||
await promiseFlushLayoutInContent();
|
||||
await EventUtils.promiseNativeMouseEvent({
|
||||
type: "mousemove",
|
||||
target: browser,
|
||||
atCenter: true,
|
||||
});
|
||||
info(
|
||||
`Waiting to MozAutoScrollNoStart event for the middle button click with ${modifier}`
|
||||
);
|
||||
await EventUtils.promiseNativeMouseEvent({
|
||||
type: "mousedown",
|
||||
target: browser,
|
||||
atCenter: true,
|
||||
button: 1, // middle button
|
||||
modifiers: {
|
||||
altKey: modifier == "Alt",
|
||||
ctrlKey: modifier == "Control",
|
||||
metaKey: modifier == "Meta",
|
||||
shiftKey: modifier == "Shift",
|
||||
},
|
||||
});
|
||||
try {
|
||||
await TestUtils.waitForCondition(
|
||||
() => autoScroller?.state == "open",
|
||||
`Waiting to check not to open autoscroller popup with ${modifier}`,
|
||||
100,
|
||||
10
|
||||
);
|
||||
ok(
|
||||
false,
|
||||
`The autoscroller popup shouldn't be opened by middle click with ${modifier}`
|
||||
);
|
||||
} catch (ex) {
|
||||
ok(
|
||||
true,
|
||||
`The autoscroller popup was not open as expected after middle click with ${modifier}`
|
||||
);
|
||||
}
|
||||
// In the wild, native "mouseup" event occurs after the popup is open.
|
||||
await EventUtils.promiseNativeMouseEvent({
|
||||
type: "mouseup",
|
||||
target: browser,
|
||||
atCenter: true,
|
||||
button: 1, // middle button
|
||||
});
|
||||
await promiseFlushLayoutInContent();
|
||||
await promiseContentTick();
|
||||
await eventsInContent.promiseMouseEvents(
|
||||
["paste"],
|
||||
`At middle clicking with ${modifier}`
|
||||
);
|
||||
for (let eventType of [
|
||||
"mousedown",
|
||||
"mouseup",
|
||||
"click",
|
||||
"auxclick",
|
||||
"paste",
|
||||
]) {
|
||||
is(
|
||||
eventsInContent.getCountAndRemoveEventListener(eventType),
|
||||
1,
|
||||
`"${eventType}" event should be fired in the content when a middle click with ${modifier}`
|
||||
);
|
||||
}
|
||||
info(
|
||||
"Waiting autoscroller close for preparing the following tests"
|
||||
);
|
||||
})();
|
||||
}
|
||||
}
|
||||
|
||||
async function doTestMouseEventsAtStoppingAutoScrolling({
|
||||
aButton = 0,
|
||||
aClickOutsideAutoScroller = false,
|
||||
|
|
Загрузка…
Ссылка в новой задаче