diff options
author | Pyfisch <pyfisch@gmail.com> | 2018-10-06 17:35:45 +0200 |
---|---|---|
committer | Pyfisch <pyfisch@gmail.com> | 2018-10-07 22:39:00 +0200 |
commit | 0ccaa7e1a9e9bf9472d869576019b9cda350ad87 (patch) | |
tree | 812a25be7dcad507d183b25d683a9ebaec3d493c /components/script/textinput.rs | |
parent | 76ddbe4d7afd48b83b23f3fd0cff47b214a0a290 (diff) | |
download | servo-0ccaa7e1a9e9bf9472d869576019b9cda350ad87.tar.gz servo-0ccaa7e1a9e9bf9472d869576019b9cda350ad87.zip |
Use keyboard-types crate
Have embedders send DOM keys to servo and use a strongly typed KeyboardEvent
from the W3C UI Events spec. All keyboard handling now uses the new types.
Introduce a ShortcutMatcher to recognize key bindings. Shortcuts are now
recognized in a uniform way.
Updated the winit port.
Updated webdriver integration.
part of #20331
Diffstat (limited to 'components/script/textinput.rs')
-rw-r--r-- | components/script/textinput.rs | 174 |
1 files changed, 76 insertions, 98 deletions
diff --git a/components/script/textinput.rs b/components/script/textinput.rs index 7f462ba43fb..dfa469c1a08 100644 --- a/components/script/textinput.rs +++ b/components/script/textinput.rs @@ -7,7 +7,7 @@ use clipboard_provider::ClipboardProvider; use dom::bindings::str::DOMString; use dom::keyboardevent::KeyboardEvent; -use msg::constellation_msg::{Key, KeyModifiers}; +use keyboard_types::{Key, KeyState, Modifiers, ShortcutMatcher}; use std::borrow::ToOwned; use std::cmp::{max, min}; use std::default::Default; @@ -130,17 +130,11 @@ pub enum Direction { Backward, } -/// Was the keyboard event accompanied by the standard control modifier, -/// i.e. cmd on Mac OS or ctrl on other platforms. +// Some shortcuts use Cmd on Mac and Control on other systems. #[cfg(target_os = "macos")] -fn is_control_key(mods: KeyModifiers) -> bool { - mods.contains(KeyModifiers::SUPER) && !mods.contains(KeyModifiers::CONTROL | KeyModifiers::ALT) -} - +pub const CMD_OR_CONTROL: Modifiers = Modifiers::META; #[cfg(not(target_os = "macos"))] -fn is_control_key(mods: KeyModifiers) -> bool { - mods.contains(KeyModifiers::CONTROL) && !mods.contains(KeyModifiers::SUPER | KeyModifiers::ALT) -} +pub const CMD_OR_CONTROL: Modifiers = Modifiers::CONTROL; /// The length in bytes of the first n characters in a UTF-8 string. /// @@ -685,155 +679,139 @@ impl<T: ClipboardProvider> TextInput<T> { /// Process a given `KeyboardEvent` and return an action for the caller to execute. pub fn handle_keydown(&mut self, event: &KeyboardEvent) -> KeyReaction { - if let Some(key) = event.get_key() { - self.handle_keydown_aux(event.printable(), key, event.get_key_modifiers()) - } else { - KeyReaction::Nothing - } + let key = event.key(); + let mods = event.modifiers(); + self.handle_keydown_aux(key, mods, cfg!(target_os = "macos")) } + // This function exists for easy unit testing. + // To test Mac OS shortcuts on other systems a flag is passed. pub fn handle_keydown_aux( &mut self, - printable: Option<char>, key: Key, - mods: KeyModifiers, + mut mods: Modifiers, + macos: bool, ) -> KeyReaction { - let maybe_select = if mods.contains(KeyModifiers::SHIFT) { + let maybe_select = if mods.contains(Modifiers::SHIFT) { Selection::Selected } else { Selection::NotSelected }; - - match (printable, key) { - (_, Key::B) if mods.contains(KeyModifiers::CONTROL | KeyModifiers::ALT) => { + mods.remove(Modifiers::SHIFT); + ShortcutMatcher::new(KeyState::Down, key.clone(), mods) + .shortcut(Modifiers::CONTROL | Modifiers::ALT, 'B', || { self.adjust_horizontal_by_word(Direction::Backward, maybe_select); KeyReaction::RedrawSelection - }, - (_, Key::F) if mods.contains(KeyModifiers::CONTROL | KeyModifiers::ALT) => { + }) + .shortcut(Modifiers::CONTROL | Modifiers::ALT, 'F', || { self.adjust_horizontal_by_word(Direction::Forward, maybe_select); KeyReaction::RedrawSelection - }, - (_, Key::A) if mods.contains(KeyModifiers::CONTROL | KeyModifiers::ALT) => { + }) + .shortcut(Modifiers::CONTROL | Modifiers::ALT, 'A', || { self.adjust_horizontal_to_line_end(Direction::Backward, maybe_select); KeyReaction::RedrawSelection - }, - (_, Key::E) if mods.contains(KeyModifiers::CONTROL | KeyModifiers::ALT) => { + }) + .shortcut(Modifiers::CONTROL | Modifiers::ALT, 'E', || { self.adjust_horizontal_to_line_end(Direction::Forward, maybe_select); KeyReaction::RedrawSelection - }, - #[cfg(target_os = "macos")] - (None, Key::A) if mods == KeyModifiers::CONTROL => - { + }) + .optional_shortcut(macos, Modifiers::CONTROL, 'A', || { self.adjust_horizontal_to_line_end(Direction::Backward, maybe_select); KeyReaction::RedrawSelection - } - #[cfg(target_os = "macos")] - (None, Key::E) if mods == KeyModifiers::CONTROL => - { + }) + .optional_shortcut(macos, Modifiers::CONTROL, 'E', || { self.adjust_horizontal_to_line_end(Direction::Forward, maybe_select); KeyReaction::RedrawSelection - } - (_, Key::A) if is_control_key(mods) => { + }) + .shortcut(CMD_OR_CONTROL, 'A', || { self.select_all(); KeyReaction::RedrawSelection - }, - (_, Key::C) if is_control_key(mods) => { + }) + .shortcut(CMD_OR_CONTROL, 'C', || { if let Some(text) = self.get_selection_text() { self.clipboard_provider.set_clipboard_contents(text); } KeyReaction::DispatchInput - }, - (_, Key::V) if is_control_key(mods) => { + }) + .shortcut(CMD_OR_CONTROL, 'V', || { let contents = self.clipboard_provider.clipboard_contents(); self.insert_string(contents); KeyReaction::DispatchInput - }, - (Some(c), _) => { - self.insert_char(c); - KeyReaction::DispatchInput - }, - (None, Key::Delete) => { + }) + .shortcut(Modifiers::empty(), Key::Delete, || { self.delete_char(Direction::Forward); KeyReaction::DispatchInput - }, - (None, Key::Backspace) => { + }) + .shortcut(Modifiers::empty(), Key::Backspace, || { self.delete_char(Direction::Backward); KeyReaction::DispatchInput - }, - #[cfg(target_os = "macos")] - (None, Key::Left) if mods.contains(KeyModifiers::SUPER) => - { + }) + .optional_shortcut(macos, Modifiers::META, Key::ArrowLeft, || { self.adjust_horizontal_to_line_end(Direction::Backward, maybe_select); KeyReaction::RedrawSelection - } - #[cfg(target_os = "macos")] - (None, Key::Right) if mods.contains(KeyModifiers::SUPER) => - { + }) + .optional_shortcut(macos, Modifiers::META, Key::ArrowRight, || { self.adjust_horizontal_to_line_end(Direction::Forward, maybe_select); KeyReaction::RedrawSelection - } - #[cfg(target_os = "macos")] - (None, Key::Up) if mods.contains(KeyModifiers::SUPER) => - { + }) + .optional_shortcut(macos, Modifiers::META, Key::ArrowUp, || { self.adjust_horizontal_to_limit(Direction::Backward, maybe_select); KeyReaction::RedrawSelection - } - #[cfg(target_os = "macos")] - (None, Key::Down) if mods.contains(KeyModifiers::SUPER) => - { + }) + .optional_shortcut(macos, Modifiers::META, Key::ArrowDown, || { self.adjust_horizontal_to_limit(Direction::Forward, maybe_select); KeyReaction::RedrawSelection - } - (None, Key::Left) if mods.contains(KeyModifiers::ALT) => { + }) + .shortcut(Modifiers::ALT, Key::ArrowLeft, || { self.adjust_horizontal_by_word(Direction::Backward, maybe_select); KeyReaction::RedrawSelection - }, - (None, Key::Right) if mods.contains(KeyModifiers::ALT) => { + }) + .shortcut(Modifiers::ALT, Key::ArrowRight, || { self.adjust_horizontal_by_word(Direction::Forward, maybe_select); KeyReaction::RedrawSelection - }, - (None, Key::Left) => { + }) + .shortcut(Modifiers::empty(), Key::ArrowLeft, || { self.adjust_horizontal_by_one(Direction::Backward, maybe_select); KeyReaction::RedrawSelection - }, - (None, Key::Right) => { + }) + .shortcut(Modifiers::empty(), Key::ArrowRight, || { self.adjust_horizontal_by_one(Direction::Forward, maybe_select); KeyReaction::RedrawSelection - }, - (None, Key::Up) => { + }) + .shortcut(Modifiers::empty(), Key::ArrowUp, || { self.adjust_vertical(-1, maybe_select); KeyReaction::RedrawSelection - }, - (None, Key::Down) => { + }) + .shortcut(Modifiers::empty(), Key::ArrowDown, || { self.adjust_vertical(1, maybe_select); KeyReaction::RedrawSelection - }, - (None, Key::Enter) | (None, Key::KpEnter) => self.handle_return(), - (None, Key::Home) => { - #[cfg(not(target_os = "macos"))] - { - self.edit_point.index = 0; - } + }) + .shortcut(Modifiers::empty(), Key::Enter, || self.handle_return()) + .optional_shortcut(macos, Modifiers::empty(), Key::Home, || { + self.edit_point.index = 0; KeyReaction::RedrawSelection - }, - (None, Key::End) => { - #[cfg(not(target_os = "macos"))] - { - self.edit_point.index = self.current_line_length(); - self.assert_ok_selection(); - } + }) + .optional_shortcut(macos, Modifiers::empty(), Key::End, || { + self.edit_point.index = self.current_line_length(); + self.assert_ok_selection(); KeyReaction::RedrawSelection - }, - (None, Key::PageUp) => { + }) + .shortcut(Modifiers::empty(), Key::PageUp, || { self.adjust_vertical(-28, maybe_select); KeyReaction::RedrawSelection - }, - (None, Key::PageDown) => { + }) + .shortcut(Modifiers::empty(), Key::PageDown, || { self.adjust_vertical(28, maybe_select); KeyReaction::RedrawSelection - }, - _ => KeyReaction::Nothing, - } + }) + .otherwise(|| { + if let Key::Character(ref c) = key { + self.insert_string(c.as_str()); + return KeyReaction::DispatchInput; + } + KeyReaction::Nothing + }) + .unwrap() } /// Whether the content is empty. |