Bug 1840804 - Make TextEditor::OnBlur stop finalizing Selection if new element already gets focus r=m_kato, a=dsmith

Before bug 1770874, `EditorBase::OnBlur` checked that for both `TextEditor`
and `HTMLEditor`.  However, accidentally, I removed the check from `TextEditor`.
Therefore, a call of `EditorBase::FinalizeSelection()` will hide the caret
even after another editor gets focus.

Therefore, this patch just take it back into `TextEditor::OnBlur`.

Note that I don't think the design mode handling is required there because
`TextEditor`s shouldn't be created in the design mode document.

Differential Revision: https://phabricator.services.mozilla.com/D182468
This commit is contained in:
Masayuki Nakano 2023-06-30 00:17:05 +00:00
parent a494255ad0
commit d0189a6dce
5 changed files with 77 additions and 0 deletions

View File

@ -43,6 +43,7 @@
#include "nsDebug.h"
#include "nsDependentSubstring.h"
#include "nsError.h"
#include "nsFocusManager.h"
#include "nsGkAtoms.h"
#include "nsIClipboard.h"
#include "nsIContent.h"
@ -742,6 +743,19 @@ nsresult TextEditor::OnFocus(const nsINode& aOriginalEventTargetNode) {
}
nsresult TextEditor::OnBlur(const EventTarget* aEventTarget) {
// check if something else is focused. If another element is focused, then
// we should not change the selection.
nsFocusManager* focusManager = nsFocusManager::GetFocusManager();
if (MOZ_UNLIKELY(!focusManager)) {
return NS_OK;
}
// If another element already has focus, we should not maintain the selection
// because we may not have the rights doing it.
if (focusManager->GetFocusedElement()) {
return NS_OK;
}
nsresult rv = FinalizeSelection();
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
"EditorBase::FinalizeSelection() failed");

View File

@ -0,0 +1,27 @@
<!doctype html>
<html class="reftest-wait">
<meta charset="utf-8">
<title>Move Selection into an editing host before TextEditor gets blur event</title>
<script src="/tests/SimpleTest/SimpleTest.js"></script>
<style>
div[contenteditable] {
outline: none;
}
input {
border: none;
outline: none;
}
</style>
<script>
SimpleTest.waitForFocus(() => {
const editingHost = document.querySelector("div[contenteditable]");
editingHost.addEventListener("focus", () => {
requestAnimationFrame(
() => document.documentElement.removeAttribute("class")
);
}, { once: true });
getSelection().collapse(editingHost, 0);
});
</script>
<input>
<div contenteditable="true" spellcheck="false"><br></div>

View File

@ -0,0 +1,33 @@
<!doctype html>
<html class="reftest-wait">
<meta charset="utf-8">
<title>Move Selection into an editing host before TextEditor gets blur event</title>
<script src="/tests/SimpleTest/SimpleTest.js"></script>
<style>
div[contenteditable] {
outline: none;
}
input {
border: none;
outline: none;
}
</style>
<script>
SimpleTest.waitForFocus(() => {
const input = document.querySelector("input");
input.focus();
input.addEventListener("blur", () => {
const editingHost = document.querySelector("div[contenteditable]");
editingHost.addEventListener("focus", () => {
requestAnimationFrame(
() => document.documentElement.removeAttribute("class")
);
}, { once: true });
getSelection().collapse(editingHost, 0);
}, { once: true });
requestAnimationFrame(() => input.blur());
});
</script>
<input>
<div contenteditable="true" spellcheck="false"><br></div>

View File

@ -386,6 +386,8 @@ support-files =
bug1670531-3.html
bug1670531-3-ref.html
bug1670531-4.html
collapse-selection-into-editing-host-during-blur-of-input.html
collapse-selection-into-editing-host-during-blur-of-input-ref.html
image_rgrg-256x256.png
input-invalid-ref.html
input-maxlength-invalid-change.html

View File

@ -301,6 +301,7 @@ var tests = [
[ 'bug1529492-1.html' , 'bug1529492-1-ref.html' ] ,
function() {SpecialPowers.pushPrefEnv({'clear': [['accessibility.browsewithcaret']]}, nextTest);} ,
[ 'interlinePosition-after-Selection-addRange.html', 'interlinePosition-after-Selection-addRange-ref.html' ] ,
[ 'collapse-selection-into-editing-host-during-blur-of-input.html', 'collapse-selection-into-editing-host-during-blur-of-input-ref.html' ] ,
];
if (!navigator.appVersion.includes("Android")) {