Bug 1712724 - Don't trigger select on programmatic focus during keyboard events. r=smaug

Depends on D115900

Differential Revision: https://phabricator.services.mozilla.com/D115901
This commit is contained in:
Emilio Cobos Álvarez 2021-05-25 22:29:02 +00:00
parent 8dea5d3fa5
commit ef6415ef1f
4 changed files with 37 additions and 5 deletions

View File

@ -3640,7 +3640,7 @@ nsresult nsFocusManager::DetermineElementToMoveFocus(
}
uint32_t nsFocusManager::ProgrammaticFocusFlags(const FocusOptions& aOptions) {
uint32_t flags = 0;
uint32_t flags = FLAG_BYJS;
if (aOptions.mPreventScroll) {
flags |= FLAG_NOSCROLL;
}

View File

@ -3739,16 +3739,19 @@ nsresult HTMLInputElement::PostHandleEvent(EventChainPostVisitor& aVisitor) {
// for text and password fields when the field was focused by the
// keyboard or a navigation, the platform allows it, and it wasn't
// just because we raised a window.
//
// While it'd usually make sense, we don't do this for JS callers
// because it causes some compat issues, see bug 1712724 for example.
nsFocusManager* fm = nsFocusManager::GetFocusManager();
if (fm && IsSingleLineTextControl(false) &&
!aVisitor.mEvent->AsFocusEvent()->mFromRaise &&
SelectTextFieldOnFocus()) {
Document* document = GetComposedDoc();
if (document) {
if (Document* document = GetComposedDoc()) {
uint32_t lastFocusMethod;
fm->GetLastFocusMethod(document->GetWindow(), &lastFocusMethod);
if (lastFocusMethod & (nsIFocusManager::FLAG_BYKEY |
nsIFocusManager::FLAG_BYMOVEFOCUS)) {
nsIFocusManager::FLAG_BYMOVEFOCUS) &&
!(lastFocusMethod & nsIFocusManager::FLAG_BYJS)) {
RefPtr<nsPresContext> presContext =
GetPresContext(eForComposedDoc);
DispatchSelectEvent(presContext);

View File

@ -236,11 +236,14 @@ interface nsIFocusManager : nsISupports
*/
const unsigned long FLAG_BYTOUCH = 0x200000;
/** Focus is changing due to a JS focus() call or similar operation. */
const unsigned long FLAG_BYJS = 0x400000;
/** Focus is changing due to a long press operation by touch or mouse. */
const unsigned long FLAG_BYLONGPRESS = 0x800000;
/** Mask with all the focus methods. */
const unsigned long METHOD_MASK = FLAG_BYMOUSE | FLAG_BYKEY | FLAG_BYMOVEFOCUS | FLAG_BYTOUCH | FLAG_BYLONGPRESS;
const unsigned long METHOD_MASK = FLAG_BYMOUSE | FLAG_BYKEY | FLAG_BYMOVEFOCUS | FLAG_BYTOUCH | FLAG_BYJS | FLAG_BYLONGPRESS;
/** Mask with all the focus methods, plus the SHOW / NOSHOWRING flags. */
const unsigned long METHODANDRING_MASK = METHOD_MASK | FLAG_SHOWRING | FLAG_NOSHOWRING;

View File

@ -0,0 +1,26 @@
<!doctype html>
<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io">
<link rel="author" title="Mozilla" href="https://mozilla.org">
<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1712724">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/resources/testdriver.js"></script>
<script src="/resources/testdriver-vendor.js"></script>
<input type=text id=text value=abc>
<script>
let text = document.getElementById("text");
document.addEventListener("keyup", function(e) {
text.focus();
});
promise_test(async t => {
await test_driver.send_keys(document.body, " ");
assert_equals(document.activeElement, text, "#text should be focused by our event listener");
assert_true(text.matches(":focus"), "#text should match :focus");
assert_true(text.matches(":focus-visible"), "#text should match :focus-visible");
assert_equals(text.selectionStart, text.selectionEnd, "#text should not be selected");
assert_equals(text.value, "abc", "#text should not have changed value");
});
</script>