mirror of
https://github.com/servo/servo.git
synced 2025-06-04 07:35:36 +00:00
Let input
JS event be dispatched by keydown
instead of keypress
(#37078)
1. Let `input` JS event be dispatched by `keydown` instead of `keypress`, according to spec 2. Fire `input` event for Backspace and Delete. But do so only when something is actually deleted Testing: Manually tested and compared with other browsers. Fixes: #37051 cc @xiaochengh Signed-off-by: Euclid Ye <yezhizhenjiakang@gmail.com>
This commit is contained in:
parent
8ebf344e5e
commit
45072ae2e0
4 changed files with 51 additions and 28 deletions
|
@ -2374,6 +2374,9 @@ impl Document {
|
|||
let mut cancel_state = event.get_cancel_state();
|
||||
|
||||
// https://w3c.github.io/uievents/#keys-cancelable-keys
|
||||
// it MUST prevent the respective beforeinput and input
|
||||
// (and keypress if supported) events from being generated
|
||||
// TODO: keypress should be deprecated and superceded by beforeinput
|
||||
if keyboard_event.state == KeyState::Down &&
|
||||
is_character_value_key(&(keyboard_event.key)) &&
|
||||
!keyboard_event.is_composing &&
|
||||
|
|
|
@ -2883,6 +2883,17 @@ impl VirtualMethods for HTMLInputElement {
|
|||
self.implicit_submission(can_gc);
|
||||
},
|
||||
DispatchInput => {
|
||||
if event.IsTrusted() {
|
||||
self.owner_global()
|
||||
.task_manager()
|
||||
.user_interaction_task_source()
|
||||
.queue_event(
|
||||
self.upcast(),
|
||||
atom!("input"),
|
||||
EventBubbles::Bubbles,
|
||||
EventCancelable::NotCancelable,
|
||||
);
|
||||
}
|
||||
self.value_dirty.set(true);
|
||||
self.update_placeholder_shown_state();
|
||||
self.upcast::<Node>().dirty(NodeDamage::OtherNodeDamage);
|
||||
|
@ -2899,17 +2910,9 @@ impl VirtualMethods for HTMLInputElement {
|
|||
!event.DefaultPrevented() &&
|
||||
self.input_type().is_textual_or_password()
|
||||
{
|
||||
if event.IsTrusted() {
|
||||
self.owner_global()
|
||||
.task_manager()
|
||||
.user_interaction_task_source()
|
||||
.queue_event(
|
||||
self.upcast(),
|
||||
atom!("input"),
|
||||
EventBubbles::Bubbles,
|
||||
EventCancelable::NotCancelable,
|
||||
);
|
||||
}
|
||||
// keypress should be deprecated and replaced by beforeinput.
|
||||
// keypress was supposed to fire "blur" and "focus" events
|
||||
// but already done in `document.rs`
|
||||
} else if (event.type_() == atom!("compositionstart") ||
|
||||
event.type_() == atom!("compositionupdate") ||
|
||||
event.type_() == atom!("compositionend")) &&
|
||||
|
|
|
@ -643,6 +643,17 @@ impl VirtualMethods for HTMLTextAreaElement {
|
|||
match action {
|
||||
KeyReaction::TriggerDefaultAction => (),
|
||||
KeyReaction::DispatchInput => {
|
||||
if event.IsTrusted() {
|
||||
self.owner_global()
|
||||
.task_manager()
|
||||
.user_interaction_task_source()
|
||||
.queue_event(
|
||||
self.upcast(),
|
||||
atom!("input"),
|
||||
EventBubbles::Bubbles,
|
||||
EventCancelable::NotCancelable,
|
||||
);
|
||||
}
|
||||
self.value_dirty.set(true);
|
||||
self.update_placeholder_shown_state();
|
||||
self.upcast::<Node>().dirty(NodeDamage::OtherNodeDamage);
|
||||
|
@ -656,17 +667,9 @@ impl VirtualMethods for HTMLTextAreaElement {
|
|||
}
|
||||
}
|
||||
} else if event.type_() == atom!("keypress") && !event.DefaultPrevented() {
|
||||
if event.IsTrusted() {
|
||||
self.owner_global()
|
||||
.task_manager()
|
||||
.user_interaction_task_source()
|
||||
.queue_event(
|
||||
self.upcast(),
|
||||
atom!("input"),
|
||||
EventBubbles::Bubbles,
|
||||
EventCancelable::NotCancelable,
|
||||
);
|
||||
}
|
||||
// keypress should be deprecated and replaced by beforeinput.
|
||||
// keypress was supposed to fire "blur" and "focus" events
|
||||
// but already done in `document.rs`
|
||||
} else if event.type_() == atom!("compositionstart") ||
|
||||
event.type_() == atom!("compositionupdate") ||
|
||||
event.type_() == atom!("compositionend")
|
||||
|
|
|
@ -319,11 +319,18 @@ impl<T: ClipboardProvider> TextInput<T> {
|
|||
}
|
||||
|
||||
/// Remove a character at the current editing point
|
||||
pub fn delete_char(&mut self, dir: Direction) {
|
||||
///
|
||||
/// Returns true if any character was deleted
|
||||
pub fn delete_char(&mut self, dir: Direction) -> bool {
|
||||
if self.selection_origin.is_none() || self.selection_origin == Some(self.edit_point) {
|
||||
self.adjust_horizontal_by_one(dir, Selection::Selected);
|
||||
}
|
||||
self.replace_selection(DOMString::new());
|
||||
if self.selection_start() == self.selection_end() {
|
||||
false
|
||||
} else {
|
||||
self.replace_selection(DOMString::new());
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
/// Insert a character at the current editing point
|
||||
|
@ -895,6 +902,7 @@ impl<T: ClipboardProvider> TextInput<T> {
|
|||
KeyReaction::RedrawSelection
|
||||
})
|
||||
.shortcut(CMD_OR_CONTROL, 'X', || {
|
||||
// FIXME: this is unreachable because ClipboardEvent is fired instead of keydown
|
||||
if let Some(text) = self.get_selection_text() {
|
||||
self.clipboard_provider.set_text(text);
|
||||
self.delete_char(Direction::Backward);
|
||||
|
@ -914,12 +922,18 @@ impl<T: ClipboardProvider> TextInput<T> {
|
|||
KeyReaction::DispatchInput
|
||||
})
|
||||
.shortcut(Modifiers::empty(), Key::Delete, || {
|
||||
self.delete_char(Direction::Forward);
|
||||
KeyReaction::DispatchInput
|
||||
if self.delete_char(Direction::Forward) {
|
||||
KeyReaction::DispatchInput
|
||||
} else {
|
||||
KeyReaction::Nothing
|
||||
}
|
||||
})
|
||||
.shortcut(Modifiers::empty(), Key::Backspace, || {
|
||||
self.delete_char(Direction::Backward);
|
||||
KeyReaction::DispatchInput
|
||||
if self.delete_char(Direction::Backward) {
|
||||
KeyReaction::DispatchInput
|
||||
} else {
|
||||
KeyReaction::Nothing
|
||||
}
|
||||
})
|
||||
.optional_shortcut(macos, Modifiers::META, Key::ArrowLeft, || {
|
||||
self.adjust_horizontal_to_line_end(Direction::Backward, maybe_select);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue