Bug 1679461 - Use SetSelectionRange in Select(), regardless of focus state r=masayuki

SelectAll() also is no-op without a frame, so this replaces it with SetSelectionRange.

Differential Revision: https://phabricator.services.mozilla.com/D98184
This commit is contained in:
Kagami Sascha Rosylight
2020-12-02 19:27:19 +00:00
parent f91ab1a158
commit cf1b536d67
5 changed files with 30 additions and 74 deletions

View File

@@ -3020,17 +3020,11 @@ void HTMLInputElement::Select() {
return; return;
} }
// XXX Bug? We have to give the input focus before contents can be TextControlState* state = GetEditorState();
// selected MOZ_ASSERT(state, "Single line text controls are expected to have a state");
FocusTristate state = FocusState(); if (FocusState() != eUnfocusable) {
if (state == eUnfocusable) { RefPtr<nsFrameSelection> fs = state->GetConstFrameSelection();
return;
}
TextControlState* tes = GetEditorState();
if (tes) {
RefPtr<nsFrameSelection> fs = tes->GetConstFrameSelection();
if (fs && fs->MouseDownRecorded()) { if (fs && fs->MouseDownRecorded()) {
// This means that we're being called while the frame selection has a // This means that we're being called while the frame selection has a
// mouse down event recorded to adjust the caret during the mouse up // mouse down event recorded to adjust the caret during the mouse up
@@ -3039,27 +3033,24 @@ void HTMLInputElement::Select() {
// select() call takes effect. // select() call takes effect.
fs->SetDelayedCaretData(nullptr); fs->SetDelayedCaretData(nullptr);
} }
}
nsFocusManager* fm = nsFocusManager::GetFocusManager(); if (RefPtr<nsFocusManager> fm = nsFocusManager::GetFocusManager()) {
RefPtr<nsPresContext> presContext = GetPresContext(eForComposedDoc);
if (state == eInactiveWindow) {
if (fm) fm->SetFocus(this, nsIFocusManager::FLAG_NOSCROLL);
SelectAll(presContext);
return;
}
DispatchSelectEvent(presContext);
if (fm) {
fm->SetFocus(this, nsIFocusManager::FLAG_NOSCROLL); fm->SetFocus(this, nsIFocusManager::FLAG_NOSCROLL);
// ensure that the element is actually focused // A focus event handler may change the type attribute, which will destroy
if (this == fm->GetFocusedElement()) { // the previous state object.
// Now Select all the text! state = GetEditorState();
SelectAll(presContext); if (!state) {
return;
} }
} }
}
// Directly call TextControlState::SetSelectionRange because
// HTMLInputElement::SetSelectionRange only applies to fewer types
state->SetSelectionRange(0, UINT32_MAX,
nsITextControlFrame::SelectionDirection::eNone,
IgnoredErrorResult());
} }
void HTMLInputElement::DispatchSelectEvent(nsPresContext* aPresContext) { void HTMLInputElement::DispatchSelectEvent(nsPresContext* aPresContext) {

View File

@@ -670,7 +670,7 @@ class HTMLInputElement final : public TextControlElement,
already_AddRefed<nsINodeList> GetLabels(); already_AddRefed<nsINodeList> GetLabels();
void Select(); MOZ_CAN_RUN_SCRIPT void Select();
Nullable<uint32_t> GetSelectionStart(ErrorResult& aRv); Nullable<uint32_t> GetSelectionStart(ErrorResult& aRv);
MOZ_CAN_RUN_SCRIPT void SetSelectionStart(const Nullable<uint32_t>& aValue, MOZ_CAN_RUN_SCRIPT void SetSelectionStart(const Nullable<uint32_t>& aValue,

View File

@@ -132,37 +132,14 @@ nsresult HTMLTextAreaElement::Clone(dom::NodeInfo* aNodeInfo,
// nsIContent // nsIContent
void HTMLTextAreaElement::Select() { void HTMLTextAreaElement::Select() {
// XXX Bug? We have to give the input focus before contents can be if (FocusState() != eUnfocusable) {
// selected if (RefPtr<nsFocusManager> fm = nsFocusManager::GetFocusManager()) {
FocusTristate state = FocusState();
if (state == eUnfocusable) {
return;
}
nsFocusManager* fm = nsFocusManager::GetFocusManager();
RefPtr<nsPresContext> presContext = GetPresContext(eForComposedDoc);
if (state == eInactiveWindow) {
if (fm) fm->SetFocus(this, nsIFocusManager::FLAG_NOSCROLL);
SelectAll(presContext);
return;
}
WidgetGUIEvent event(true, eFormSelect, nullptr);
// XXXbz HTMLInputElement guards against this reentering; shouldn't we?
EventDispatcher::Dispatch(static_cast<nsIContent*>(this), presContext,
&event);
if (fm) {
fm->SetFocus(this, nsIFocusManager::FLAG_NOSCROLL); fm->SetFocus(this, nsIFocusManager::FLAG_NOSCROLL);
}
}
// ensure that the element is actually focused SetSelectionRange(0, UINT32_MAX, mozilla::dom::Optional<nsAString>(),
if (this == fm->GetFocusedElement()) { IgnoredErrorResult());
// Now Select all the text!
SelectAll(presContext);
}
}
} }
NS_IMETHODIMP NS_IMETHODIMP

View File

@@ -254,7 +254,7 @@ class HTMLTextAreaElement final : public TextControlElement,
// via bindings. // via bindings.
void SetCustomValidity(const nsAString& aError); void SetCustomValidity(const nsAString& aError);
void Select(); MOZ_CAN_RUN_SCRIPT void Select();
Nullable<uint32_t> GetSelectionStart(ErrorResult& aError); Nullable<uint32_t> GetSelectionStart(ErrorResult& aError);
MOZ_CAN_RUN_SCRIPT void SetSelectionStart( MOZ_CAN_RUN_SCRIPT void SetSelectionStart(
const Nullable<uint32_t>& aSelectionStart, ErrorResult& aError); const Nullable<uint32_t>& aSelectionStart, ErrorResult& aError);

View File

@@ -95,12 +95,9 @@
// to the character that immediately follows the text entry cursor. // to the character that immediately follows the text entry cursor.
assert_equals(el.selectionStart, el.value.length, assert_equals(el.selectionStart, el.value.length,
"SelectionStart offset without selection in " + el.id); "SelectionStart offset without selection in " + el.id);
if (!el.parentNode) {
return;
}
el.select(); el.select();
assert_equals(el.selectionStart, 0, "SelectionStart offset"); assert_equals(el.selectionStart, 0, "SelectionStart offset");
el.parentNode.removeChild(el); el.remove();
}, "test SelectionStart offset for input that is " + }, "test SelectionStart offset for input that is " +
(append ? "appended" : " not appended")); (append ? "appended" : " not appended"));
} }
@@ -112,12 +109,9 @@
// to the character that immediately follows the text entry cursor. // to the character that immediately follows the text entry cursor.
assert_equals(el.selectionStart, el.value.length, assert_equals(el.selectionStart, el.value.length,
"SelectionStart offset without selection in " + el.id); "SelectionStart offset without selection in " + el.id);
if (!el.parentNode) {
return;
}
el.select(); el.select();
assert_equals(el.selectionStart, 0, "SelectionStart offset"); assert_equals(el.selectionStart, 0, "SelectionStart offset");
el.parentNode.removeChild(el); el.remove();
}, "test SelectionStart offset for textarea that is " + }, "test SelectionStart offset for textarea that is " +
(append ? "appended" : " not appended")); (append ? "appended" : " not appended"));
} }
@@ -129,12 +123,9 @@
// to the character that immediately follows the text entry cursor. // to the character that immediately follows the text entry cursor.
assert_equals(el.selectionEnd, el.value.length, assert_equals(el.selectionEnd, el.value.length,
"SelectionEnd offset without selection in " + el.id); "SelectionEnd offset without selection in " + el.id);
if (!el.parentNode) {
return;
}
el.select(); el.select();
assert_equals(el.selectionEnd, el.value.length, "SelectionEnd offset"); assert_equals(el.selectionEnd, el.value.length, "SelectionEnd offset");
el.parentNode.removeChild(el); el.remove();
}, "test SelectionEnd offset for input that is " + }, "test SelectionEnd offset for input that is " +
(append ? "appended" : " not appended")); (append ? "appended" : " not appended"));
} }
@@ -147,12 +138,9 @@
// to the character that immediately follows the text entry cursor. // to the character that immediately follows the text entry cursor.
assert_equals(el.selectionEnd, el.value.length, assert_equals(el.selectionEnd, el.value.length,
"SelectionEnd offset without selection in " + el.id); "SelectionEnd offset without selection in " + el.id);
if (!el.parentNode) {
return;
}
el.select(); el.select();
assert_equals(el.selectionEnd, el.value.length, "SelectionEnd offset"); assert_equals(el.selectionEnd, el.value.length, "SelectionEnd offset");
el.parentNode.removeChild(el); el.remove();
}, "test SelectionEnd offset for textarea that is " + }, "test SelectionEnd offset for textarea that is " +
(append ? "appended" : " not appended")); (append ? "appended" : " not appended"));
} }