Bug 1699570 - Make mouse_focuses_formcontrol on chrome documents match the old behavior. r=mstange

For that, we make accessibility.mouse_focuses_formcontrol a static pref,
and make it work in all platforms because it's simpler and allows to
test mac-specific things on other platforms more easily.

Differential Revision: https://phabricator.services.mozilla.com/D109006
This commit is contained in:
Emilio Cobos Álvarez 2021-03-18 23:01:45 +00:00
Родитель cfce9044e0
Коммит f2d4b8c005
14 изменённых файлов: 72 добавлений и 57 удалений

Просмотреть файл

@ -165,14 +165,12 @@ NS_IMPL_CYCLE_COLLECTION_WEAK(nsFocusManager, mActiveWindow,
mWindowBeingLowered, mDelayedBlurFocusEvents)
StaticRefPtr<nsFocusManager> nsFocusManager::sInstance;
bool nsFocusManager::sMouseFocusesFormControl = false;
bool nsFocusManager::sTestMode = false;
uint64_t nsFocusManager::sFocusActionCounter = 0;
static const char* kObservedPrefs[] = {
"accessibility.browsewithcaret", "accessibility.tabfocus_applies_to_xul",
"accessibility.mouse_focuses_formcontrol", "focusmanager.testmode",
nullptr};
static const char* kObservedPrefs[] = {"accessibility.browsewithcaret",
"accessibility.tabfocus_applies_to_xul",
"focusmanager.testmode", nullptr};
nsFocusManager::nsFocusManager()
: mActionIdForActiveBrowsingContextInContent(0),
@ -198,9 +196,6 @@ nsresult nsFocusManager::Init() {
Preferences::GetBool("accessibility.tabfocus_applies_to_xul",
nsIContent::sTabFocusModelAppliesToXUL);
sMouseFocusesFormControl =
Preferences::GetBool("accessibility.mouse_focuses_formcontrol", false);
sTestMode = Preferences::GetBool("focusmanager.testmode", false);
Preferences::RegisterCallbacks(nsFocusManager::PrefChanged, kObservedPrefs,
@ -230,9 +225,6 @@ void nsFocusManager::PrefChanged(const char* aPref) {
nsIContent::sTabFocusModelAppliesToXUL =
Preferences::GetBool("accessibility.tabfocus_applies_to_xul",
nsIContent::sTabFocusModelAppliesToXUL);
} else if (pref.EqualsLiteral("accessibility.mouse_focuses_formcontrol")) {
sMouseFocusesFormControl =
Preferences::GetBool("accessibility.mouse_focuses_formcontrol", false);
} else if (pref.EqualsLiteral("focusmanager.testmode")) {
sTestMode = Preferences::GetBool("focusmanager.testmode", false);
}

Просмотреть файл

@ -295,8 +295,6 @@ class nsFocusManager final : public nsIFocusManager,
*/
void NotifyOfReFocus(nsIContent& aContent);
static bool sMouseFocusesFormControl;
static void MarkUncollectableForCCGeneration(uint32_t aGeneration);
struct BlurredElementInfo {

Просмотреть файл

@ -128,7 +128,7 @@ function* tests() {
// Release.
sendMouseEvent("mouseup", label);
yield undefined;
var focusOnMouse = navigator.platform.indexOf("Mac") != 0 || SpecialPowers.getBoolPref("accessibility.mouse_focuses_formcontrol");
var focusOnMouse = SpecialPowers.getIntPref("accessibility.mouse_focuses_formcontrol") > 0;
compareSnapshots_(focusOnMouse ? normalFocusedButtonCanvas : normalButtonCanvas,
currentSnapshot, true, "Releasing the mouse over the label should have unpressed" +
(focusOnMouse ? " (and focused)" : "") + " the button.");

Просмотреть файл

@ -118,11 +118,7 @@ bool HTMLButtonElement::IsHTMLFocusable(bool aWithMouse, bool* aIsFocusable,
return true;
}
*aIsFocusable =
#ifdef XP_MACOSX
(!aWithMouse || nsFocusManager::sMouseFocusesFormControl) &&
#endif
!IsDisabled();
*aIsFocusable = IsFormControlDefaultFocusable(aWithMouse) && !IsDisabled();
return false;
}

Просмотреть файл

@ -528,11 +528,8 @@ bool HTMLImageElement::IsHTMLFocusable(bool aWithMouse, bool* aIsFocusable,
*aTabIndex = (sTabFocusModel & eTabFocus_formElementsMask) ? tabIndex : -1;
}
*aIsFocusable =
#ifdef XP_MACOSX
(!aWithMouse || nsFocusManager::sMouseFocusesFormControl) &&
#endif
(tabIndex >= 0 || GetTabIndexAttrValue().isSome());
*aIsFocusable = IsFormControlDefaultFocusable(aWithMouse) &&
(tabIndex >= 0 || GetTabIndexAttrValue().isSome());
return false;
}

Просмотреть файл

@ -6131,13 +6131,7 @@ bool HTMLInputElement::IsHTMLFocusable(bool aWithMouse, bool* aIsFocusable,
return false;
}
#ifdef XP_MACOSX
const bool defaultFocusable =
!aWithMouse || nsFocusManager::sMouseFocusesFormControl;
#else
const bool defaultFocusable = true;
#endif
const bool defaultFocusable = IsFormControlDefaultFocusable(aWithMouse);
if (CreatesDateTimeWidget()) {
if (aTabIndex) {
// We only want our native anonymous child to be tabable to, not ourself.

Просмотреть файл

@ -18,6 +18,7 @@
#include "mozilla/TextEditor.h"
#include "mozilla/StaticPrefs_html5.h"
#include "mozilla/StaticPrefs_layout.h"
#include "mozilla/StaticPrefs_accessibility.h"
#include "nscore.h"
#include "nsGenericHTMLElement.h"
@ -1589,6 +1590,21 @@ bool nsGenericHTMLElement::LegacyTouchAPIEnabled(JSContext* aCx,
return TouchEvent::LegacyAPIEnabled(aCx, aGlobal);
}
bool nsGenericHTMLElement::IsFormControlDefaultFocusable(
bool aWithMouse) const {
if (!aWithMouse) {
return true;
}
switch (StaticPrefs::accessibility_mouse_focuses_formcontrol()) {
case 0:
return false;
case 1:
return true;
default:
return !IsInChromeDocument();
}
}
//----------------------------------------------------------------------
nsGenericHTMLFormElement::nsGenericHTMLFormElement(
@ -1962,10 +1978,7 @@ bool nsGenericHTMLFormElement::IsHTMLFocusable(bool aWithMouse,
return true;
}
#ifdef XP_MACOSX
*aIsFocusable = (!aWithMouse || nsFocusManager::sMouseFocusesFormControl) &&
*aIsFocusable;
#endif
*aIsFocusable = *aIsFocusable && IsFormControlDefaultFocusable(aWithMouse);
return false;
}

Просмотреть файл

@ -152,6 +152,9 @@ class nsGenericHTMLElement : public nsGenericHTMLElementBase {
}
}
/** Returns whether a form control should be default-focusable. */
bool IsFormControlDefaultFocusable(bool aWithMouse) const;
/**
* Returns the count of descendants (inclusive of this node) in
* the uncomposed document that are explicitly set as editable.

Просмотреть файл

@ -16,7 +16,6 @@ if (navigator.platform.startsWith("Win")) {
SimpleTest.waitForExplicitFinish();
async function runTest()
{
await SpecialPowers.pushPrefEnv({"set": [['accessibility.mouse_focuses_formcontrol', false]]});
window.openDialog("window_focus.xhtml", "_blank", "chrome,width=600,height=550,noopener", window);
}
</script>

Просмотреть файл

@ -281,7 +281,8 @@ function mouseWillTriggerFocus(element)
return false;
}
if (navigator.platform.indexOf("Mac") != 0) {
if (SpecialPowers.getIntPref("accessibility.mouse_focuses_formcontrol") == 1) {
// This is a chrome document, so we'll only trigger focus with the mouse if the value of the pref is 1.
return true;
}

Просмотреть файл

@ -18,6 +18,8 @@
SimpleTest.waitForExplicitFinish();
const kIsMac = navigator.platform.includes("Mac");
function snapShot(element) {
var rect = element.getBoundingClientRect();
adjustedRect = { left: rect.left - 6, top: rect.top - 6,
@ -25,18 +27,25 @@ function snapShot(element) {
return SpecialPowers.snapshotRect(window, adjustedRect, "transparent");
}
function initTest()
{
SpecialPowers.pushPrefEnv({
"set": [
['accessibility.mouse_focuses_formcontrol', false],
]
}, runTest);
async function initTest() {
if (kIsMac) {
// FIXME: Historically this pref was only respected on mac,
// and the test uses that assumption.
//
// Ideally it should be refactored to test with the different
// values of the pref, independently of the platform.
await SpecialPowers.pushPrefEnv({
"set": [
['accessibility.mouse_focuses_formcontrol', 0],
]
});
}
runTest();
}
function runTest()
{
var isMac = (navigator.platform.includes("Mac"));
var isWinOrLinux = navigator.platform.includes("Win") || navigator.platform.includes("Linux");
function checkFocus(element, visible, testid)
@ -61,7 +70,7 @@ function runTest()
// the test regardless of which user input last occurred.
$("l1").focus();
var expectedVisible = (!isWinOrLinux || getComputedStyle($("l1"), "").outlineWidth == "2px");
testHTMLElements(htmlElements, isMac, isWinOrLinux && !expectedVisible);
testHTMLElements(htmlElements, isWinOrLinux && !expectedVisible);
$("l1").focus();
checkFocus($("l1"), expectedVisible, "appearance on list after focus() with :moz-focusring");
@ -80,15 +89,15 @@ function runTest()
checkFocus($("b1"), false, "appearance on button after mouse focus with :moz-focusring");
synthesizeMouse($("b2"), 4, 4, { });
checkFocus($("b2"), !isMac, "appearance on button after mouse focus with :focus");
checkFocus($("b2"), !kIsMac, "appearance on button after mouse focus with :focus");
// after a key is pressed, the focus ring will always be visible
$("l2").focus();
synthesizeKey("KEY_Tab");
checkFocus($("l3"), true, "appearance on list after tab focus");
if (isMac) {
SpecialPowers.pushPrefEnv({"set": [['accessibility.mouse_focuses_formcontrol', true]]}, testMacFocusesFormControl);
if (kIsMac) {
SpecialPowers.pushPrefEnv({"set": [['accessibility.mouse_focuses_formcontrol', 1]]}, testMacFocusesFormControl);
}
else {
SimpleTest.finish();
@ -97,7 +106,7 @@ function runTest()
function testMacFocusesFormControl()
{
testHTMLElements(htmlElementsMacPrefSet, true, false);
testHTMLElements(htmlElementsMacPrefSet, false);
SimpleTest.finish();
}
@ -126,8 +135,7 @@ function createElement(str) {
return doc.body.firstChild;
}
function testHTMLElements(list, isMac, expectedNoRingsOnWin)
{
function testHTMLElements(list, expectedNoRingsOnWin) {
var childwin = frames[0];
var childdoc = childwin.document;
var container = childdoc.getElementById("container");
@ -137,7 +145,7 @@ function testHTMLElements(list, isMac, expectedNoRingsOnWin)
var elem = childdoc.adoptNode(createElement(list[e]));
container.appendChild(elem);
var shouldFocus = !isMac || (elem.className == "canfocus");
var shouldFocus = !kIsMac || (elem.className == "canfocus");
var ringSize = (shouldFocus ? (expectedNoRingsOnWin ? 2 : 1) : 0) + "px";
var expectedMatchWithMouse = shouldFocus && !expectedNoRingsOnWin;
@ -156,7 +164,7 @@ function testHTMLElements(list, isMac, expectedNoRingsOnWin)
if (elem.localName == "a") {
mouseRingSize = ringSize = "0px";
expectedMatchWithMouse = expectedMatchWithMouse && !isMac;
expectedMatchWithMouse = expectedMatchWithMouse && !kIsMac;
}
synthesizeMouse(elem, 8, 8, { }, childwin);

Просмотреть файл

@ -200,6 +200,23 @@
value: false
mirror: always
# Whether form controls and images should be focusable with mouse, in content
# documents.
#
# This matches historical macOS / Safari behavior.
#
# * 0: never
# * 1: always
# * 2: on content documents
- name: accessibility.mouse_focuses_formcontrol
type: int32_t
#ifdef XP_MACOSX
value: 2
#else
value: 1
#endif
mirror: always
#---------------------------------------------------------------------------
# Prefs starting with "alerts."
#---------------------------------------------------------------------------

Просмотреть файл

@ -720,7 +720,6 @@ pref("accessibility.force_disabled", 0);
pref("focusmanager.testmode", false);
pref("accessibility.usetexttospeech", "");
pref("accessibility.mouse_focuses_formcontrol", true);
// Type Ahead Find
pref("accessibility.typeaheadfind", true);

Просмотреть файл

@ -1,2 +0,0 @@
[focus-visible-005.html]
prefs: [accessibility.mouse_focuses_formcontrol:true]