After bug 1710459, native menus are supported for content select menus on macOS behind the pref `widget.macos.native-anchored-select` which is disabled by default. This patch makes the necessary changes to enable this by default: - Tests involving content select have been updated to use more native-menu-friendly functions instead of synthesizing events where applicable. Tests which specifically test non-native menu behavior have been updated to disable native menus for content select. - The pref `widget.macos.native-anchored-select` has been renamed to be more accurate, as other prefs can cause native menus to be disabled too. Changes to the pref no longer require a browser restart, so the pref can be toggled during tests. Differential Revision: https://phabricator.services.mozilla.com/D284414
167 lines
4.9 KiB
JavaScript
167 lines
4.9 KiB
JavaScript
/* Any copyright is dedicated to the Public Domain.
|
|
* https://creativecommons.org/publicdomain/zero/1.0/ */
|
|
|
|
add_setup(async () => {
|
|
if (AppConstants.platform == "macosx") {
|
|
// This test requires preventing default on popuphiding which native menus
|
|
// do not support
|
|
await SpecialPowers.pushPrefEnv({
|
|
set: [["widget.macos.allow-native-select", false]],
|
|
});
|
|
}
|
|
});
|
|
|
|
add_task(async function test_select_popup_closing_enables_pointer_events() {
|
|
const INITIAL_PAGE = `
|
|
<!doctype html>
|
|
<html>
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<title>Initial Page</title>
|
|
</head>
|
|
<body>
|
|
<h1 id="heading">Initial Page</h1>
|
|
<button id="testbutton">Click Me</button>
|
|
<script>
|
|
window.addEventListener("unload", () => {});
|
|
</script>
|
|
</body>
|
|
</html>
|
|
`;
|
|
|
|
const SELECT_PAGE = `
|
|
<!doctype html>
|
|
<html>
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<title>Select Page</title>
|
|
</head>
|
|
<body>
|
|
<select id="testselect">
|
|
<option>Option 1</option>
|
|
<option>Option 2</option>
|
|
<option>Option 3</option>
|
|
</select>
|
|
<script>
|
|
window.addEventListener("unload", () => {});
|
|
</script>
|
|
</body>
|
|
</html>
|
|
`;
|
|
|
|
const initialUrl = "data:text/html," + encodeURI(INITIAL_PAGE);
|
|
const selectUrl = "data:text/html," + encodeURI(SELECT_PAGE);
|
|
|
|
await BrowserTestUtils.withNewTab(
|
|
{
|
|
gBrowser,
|
|
url: initialUrl,
|
|
},
|
|
async function (browser) {
|
|
// Navigate to the page with the select element
|
|
let loaded = BrowserTestUtils.browserLoaded(browser, false, selectUrl);
|
|
BrowserTestUtils.startLoadingURIString(browser, selectUrl);
|
|
await loaded;
|
|
|
|
// Focus the select element
|
|
await SpecialPowers.spawn(browser, [], async () => {
|
|
const select = content.document.getElementById("testselect");
|
|
const focusPromise = new Promise(resolve => {
|
|
select.addEventListener("focus", resolve, { once: true });
|
|
});
|
|
select.focus();
|
|
await focusPromise;
|
|
});
|
|
|
|
// Open the select popup
|
|
let popup = await openSelectPopup("key");
|
|
ok(popup, "Select popup should be open");
|
|
|
|
// Verify popup is showing
|
|
is(popup.state, "open", "Popup should be in open state");
|
|
|
|
// Verify that pointer events are disabled on the browser while popup is open
|
|
is(
|
|
browser.style.pointerEvents,
|
|
"none",
|
|
"Browser pointer events should be disabled while popup is open"
|
|
);
|
|
|
|
// There are some race conditions when the popup might get hidden, so
|
|
// for consistency prevent that always when navigating back.
|
|
function preventDefault(event) {
|
|
event.preventDefault();
|
|
}
|
|
popup.addEventListener("popuphiding", preventDefault);
|
|
|
|
// Wait for pageshow event to know when navigation completes
|
|
let pageshown = BrowserTestUtils.waitForContentEvent(browser, "pageshow");
|
|
|
|
// Dispatch AppCommand "Back" event to mimic the behavior a hardware back
|
|
// button on a mouse does.
|
|
let commandEvent = new CommandEvent("AppCommand", {
|
|
bubbles: true,
|
|
cancelable: true,
|
|
command: "Back",
|
|
});
|
|
document.documentElement.dispatchEvent(commandEvent);
|
|
|
|
// Wait for back navigation to complete
|
|
await pageshown;
|
|
|
|
// Popup should still be open after navigation
|
|
is(
|
|
popup.state,
|
|
"open",
|
|
"Popup should still be open after back navigation"
|
|
);
|
|
|
|
popup.removeEventListener("popuphiding", preventDefault);
|
|
|
|
// Now dispatch ESC to close the popup
|
|
// This should not throw an exception even though the actor is invalid
|
|
EventUtils.synthesizeKey("KEY_Escape", {}, window);
|
|
|
|
// Wait for the popup to close
|
|
await TestUtils.waitForCondition(
|
|
() => popup.state === "closed",
|
|
"Waiting for popup to close after ESC",
|
|
100,
|
|
50
|
|
);
|
|
|
|
ok(true, "Popup closed without throwing exception");
|
|
|
|
// Verify that pointer events are restored on the browser after popup closes
|
|
is(
|
|
browser.style.pointerEvents,
|
|
"",
|
|
"Browser pointer events should be restored after popup closes"
|
|
);
|
|
|
|
// Verify that mouse events dispatched in parent process can reach the page
|
|
// Set up click listener in content on the window
|
|
let clickReceivedPromise = BrowserTestUtils.waitForContentEvent(
|
|
browser,
|
|
"click"
|
|
);
|
|
|
|
// We intentionally turn off this a11y check, because the following click
|
|
// is sent on an arbitrary web content that is not expected to be tested
|
|
// by itself with the browser mochitests, therefore this rule check shall
|
|
// be ignored by a11y-checks suite.
|
|
AccessibilityUtils.setEnv({ mustHaveAccessibleRule: false });
|
|
|
|
// Dispatch mouse click in parent process at center of browser element
|
|
EventUtils.synthesizeMouseAtCenter(browser, {}, window);
|
|
AccessibilityUtils.resetEnv();
|
|
|
|
let clickReceived = await clickReceivedPromise;
|
|
ok(
|
|
clickReceived,
|
|
"Mouse events should reach the page after popup closes"
|
|
);
|
|
}
|
|
);
|
|
});
|