diff options
-rw-r--r-- | components/script/clipboard_provider.rs | 48 | ||||
-rw-r--r-- | components/script/dom/document.rs | 8 | ||||
-rw-r--r-- | components/script/dom/htmlinputelement.rs | 5 | ||||
-rw-r--r-- | components/script/dom/htmltextareaelement.rs | 5 | ||||
-rw-r--r-- | components/script/dom/keyboardevent.rs | 966 | ||||
-rw-r--r-- | components/script/lib.rs | 1 | ||||
-rw-r--r-- | components/script/textinput.rs | 119 | ||||
-rw-r--r-- | components/servo/Cargo.lock | 1 | ||||
-rw-r--r-- | tests/unit/script/Cargo.toml | 3 | ||||
-rw-r--r-- | tests/unit/script/lib.rs | 1 | ||||
-rw-r--r-- | tests/unit/script/textinput.rs | 47 |
11 files changed, 750 insertions, 454 deletions
diff --git a/components/script/clipboard_provider.rs b/components/script/clipboard_provider.rs new file mode 100644 index 00000000000..060c857b64b --- /dev/null +++ b/components/script/clipboard_provider.rs @@ -0,0 +1,48 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +use msg::constellation_msg::ConstellationChan; +use msg::constellation_msg::Msg as ConstellationMsg; + +use collections::borrow::ToOwned; +use std::sync::mpsc::channel; + +pub trait ClipboardProvider { + // blocking method to get the clipboard contents + fn get_clipboard_contents(&mut self) -> String; + // blocking method to set the clipboard contents + fn set_clipboard_contents(&mut self, &str); +} + +impl ClipboardProvider for ConstellationChan { + fn get_clipboard_contents(&mut self) -> String { + let (tx, rx) = channel(); + self.0.send(ConstellationMsg::GetClipboardContents(tx)).unwrap(); + rx.recv().unwrap() + } + fn set_clipboard_contents(&mut self, _: &str) { + panic!("not yet implemented"); + } +} + +pub struct DummyClipboardContext { + content: String +} + +impl DummyClipboardContext { + pub fn new(s: &str) -> DummyClipboardContext { + DummyClipboardContext { + content: s.to_owned() + } + } +} + +impl ClipboardProvider for DummyClipboardContext { + fn get_clipboard_contents(&mut self) -> String { + self.content.clone() + } + fn set_clipboard_contents(&mut self, s: &str) { + self.content = s.to_owned(); + } +} diff --git a/components/script/dom/document.rs b/components/script/dom/document.rs index cbb8b8daec4..9c3b0b00511 100644 --- a/components/script/dom/document.rs +++ b/components/script/dom/document.rs @@ -701,8 +701,8 @@ impl<'a> DocumentHelpers<'a> for JSRef<'a, Document> { let props = KeyboardEvent::key_properties(key, modifiers); let keyevent = KeyboardEvent::new(window.r(), ev_type, true, true, - Some(window.r()), 0, - props.key.to_owned(), props.code.to_owned(), + Some(window.r()), 0, Some(key), + props.key_string.to_owned(), props.code.to_owned(), props.location, is_repeating, is_composing, ctrl, alt, shift, meta, None, props.key_code).root(); @@ -714,8 +714,8 @@ impl<'a> DocumentHelpers<'a> for JSRef<'a, Document> { if state != KeyState::Released && props.is_printable() && !prevented { // https://dvcs.w3.org/hg/dom3events/raw-file/tip/html/DOM3-Events.html#keypress-event-order let event = KeyboardEvent::new(window.r(), "keypress".to_owned(), - true, true, Some(window.r()), - 0, props.key.to_owned(), props.code.to_owned(), + true, true, Some(window.r()), 0, Some(key), + props.key_string.to_owned(), props.code.to_owned(), props.location, is_repeating, is_composing, ctrl, alt, shift, meta, props.char_code, 0).root(); diff --git a/components/script/dom/htmlinputelement.rs b/components/script/dom/htmlinputelement.rs index 1378e6ecd76..e077cfac737 100644 --- a/components/script/dom/htmlinputelement.rs +++ b/components/script/dom/htmlinputelement.rs @@ -35,6 +35,7 @@ use dom::window::WindowHelpers; use textinput::TextInput; use textinput::KeyReaction::{TriggerDefaultAction, DispatchInput, Nothing}; use textinput::Lines::Single; +use msg::constellation_msg::ConstellationChan; use util::str::DOMString; use string_cache::Atom; @@ -72,7 +73,7 @@ pub struct HTMLInputElement { indeterminate: Cell<bool>, value_changed: Cell<bool>, size: Cell<u32>, - textinput: DOMRefCell<TextInput>, + textinput: DOMRefCell<TextInput<ConstellationChan>>, activation_state: DOMRefCell<InputActivationState>, } @@ -122,7 +123,7 @@ impl HTMLInputElement { checked_changed: Cell::new(false), value_changed: Cell::new(false), size: Cell::new(DEFAULT_INPUT_SIZE), - textinput: DOMRefCell::new(TextInput::new(Single, "".to_owned(), Some(chan))), + textinput: DOMRefCell::new(TextInput::new(Single, "".to_owned(), chan)), activation_state: DOMRefCell::new(InputActivationState::new()) } } diff --git a/components/script/dom/htmltextareaelement.rs b/components/script/dom/htmltextareaelement.rs index d3e08c2092e..dc2f89c6122 100644 --- a/components/script/dom/htmltextareaelement.rs +++ b/components/script/dom/htmltextareaelement.rs @@ -30,6 +30,7 @@ use textinput::{TextInput, Lines, KeyReaction}; use dom::virtualmethods::VirtualMethods; use dom::window::WindowHelpers; use script_task::{ScriptMsg, Runnable}; +use msg::constellation_msg::ConstellationChan; use util::str::DOMString; use string_cache::Atom; @@ -40,7 +41,7 @@ use std::cell::Cell; #[dom_struct] pub struct HTMLTextAreaElement { htmlelement: HTMLElement, - textinput: DOMRefCell<TextInput>, + textinput: DOMRefCell<TextInput<ConstellationChan>>, cols: Cell<u32>, rows: Cell<u32>, // https://html.spec.whatwg.org/multipage/#concept-textarea-dirty @@ -95,7 +96,7 @@ impl HTMLTextAreaElement { let chan = document.window().root().r().constellation_chan(); HTMLTextAreaElement { htmlelement: HTMLElement::new_inherited(HTMLElementTypeId::HTMLTextAreaElement, localName, prefix, document), - textinput: DOMRefCell::new(TextInput::new(Lines::Multiple, "".to_owned(), Some(chan))), + textinput: DOMRefCell::new(TextInput::new(Lines::Multiple, "".to_owned(), chan)), cols: Cell::new(DEFAULT_COLS), rows: Cell::new(DEFAULT_ROWS), value_changed: Cell::new(false), diff --git a/components/script/dom/keyboardevent.rs b/components/script/dom/keyboardevent.rs index ab93eddbefa..d0ac71c814c 100644 --- a/components/script/dom/keyboardevent.rs +++ b/components/script/dom/keyboardevent.rs @@ -14,15 +14,20 @@ use dom::event::{Event, EventTypeId}; use dom::uievent::UIEvent; use dom::window::Window; use msg::constellation_msg; +use msg::constellation_msg::{Key, KeyModifiers}; +use msg::constellation_msg::{SHIFT, CONTROL, ALT, SUPER}; use util::str::DOMString; use std::borrow::ToOwned; use std::cell::{RefCell, Cell}; +no_jsmanaged_fields!(Key); + #[dom_struct] pub struct KeyboardEvent { uievent: UIEvent, - key: RefCell<DOMString>, + key: Cell<Option<Key>>, + key_string: RefCell<DOMString>, code: RefCell<DOMString>, location: Cell<u32>, ctrl: Cell<bool>, @@ -45,7 +50,8 @@ impl KeyboardEvent { fn new_inherited() -> KeyboardEvent { KeyboardEvent { uievent: UIEvent::new_inherited(EventTypeId::KeyboardEvent), - key: RefCell::new("".to_owned()), + key: Cell::new(None), + key_string: RefCell::new("".to_owned()), code: RefCell::new("".to_owned()), location: Cell::new(0), ctrl: Cell::new(false), @@ -71,7 +77,8 @@ impl KeyboardEvent { cancelable: bool, view: Option<JSRef<Window>>, _detail: i32, - key: DOMString, + key: Option<Key>, + key_string: DOMString, code: DOMString, location: u32, repeat: bool, @@ -83,10 +90,11 @@ impl KeyboardEvent { char_code: Option<u32>, key_code: u32) -> Temporary<KeyboardEvent> { let ev = KeyboardEvent::new_uninitialized(window).root(); - ev.r().InitKeyboardEvent(type_, canBubble, cancelable, view, key, location, + ev.r().InitKeyboardEvent(type_, canBubble, cancelable, view, key_string, location, "".to_owned(), repeat, "".to_owned()); // FIXME(https://github.com/rust-lang/rust/issues/23338) let ev = ev.r(); + ev.key.set(key); *ev.code.borrow_mut() = code; ev.ctrl.set(ctrlKey); ev.alt.set(altKey); @@ -105,7 +113,7 @@ impl KeyboardEvent { init.parent.parent.parent.bubbles, init.parent.parent.parent.cancelable, init.parent.parent.view.r(), - init.parent.parent.detail, + init.parent.parent.detail, key_from_string(&init.key, init.location), init.key.clone(), init.code.clone(), init.location, init.repeat, init.isComposing, init.parent.ctrlKey, init.parent.altKey, init.parent.shiftKey, init.parent.metaKey, @@ -113,10 +121,10 @@ impl KeyboardEvent { Ok(event) } - pub fn key_properties(key: constellation_msg::Key, mods: constellation_msg::KeyModifiers) + pub fn key_properties(key: Key, mods: KeyModifiers) -> KeyEventProperties { KeyEventProperties { - key: key_value(key, mods), + key_string: key_value(key, mods), code: code_value(key), location: key_location(key), char_code: key_charcode(key, mods), @@ -125,321 +133,521 @@ impl KeyboardEvent { } } +pub trait KeyboardEventHelpers { + fn get_key(&self) -> Option<Key>; + fn get_key_modifiers(&self) -> KeyModifiers; +} + +impl<'a> KeyboardEventHelpers for JSRef<'a, KeyboardEvent> { + fn get_key(&self) -> Option<Key> { + self.key.get().clone() + } + + fn get_key_modifiers(&self) -> KeyModifiers { + let mut result = KeyModifiers::empty(); + if self.shift.get() { + result = result | constellation_msg::SHIFT; + } + if self.ctrl.get() { + result = result | constellation_msg::CONTROL; + } + if self.alt.get() { + result = result | constellation_msg::ALT; + } + if self.meta.get() { + result = result | constellation_msg::SUPER; + } + return result; + } +} + + // https://dvcs.w3.org/hg/dom3events/raw-file/tip/html/DOM3Events-key.html -fn key_value(key: constellation_msg::Key, mods: constellation_msg::KeyModifiers) -> &'static str { +pub fn key_value(key: Key, mods: KeyModifiers) -> &'static str { let shift = mods.contains(constellation_msg::SHIFT); match key { - constellation_msg::Key::Space => " ", - constellation_msg::Key::Apostrophe if shift => "\"", - constellation_msg::Key::Apostrophe => "'", - constellation_msg::Key::Comma if shift => "<", - constellation_msg::Key::Comma => ",", - constellation_msg::Key::Minus if shift => "_", - constellation_msg::Key::Minus => "-", - constellation_msg::Key::Period if shift => ">", - constellation_msg::Key::Period => ".", - constellation_msg::Key::Slash if shift => "?", - constellation_msg::Key::Slash => "/", - constellation_msg::Key::GraveAccent if shift => "~", - constellation_msg::Key::GraveAccent => "`", - constellation_msg::Key::Num0 if shift => ")", - constellation_msg::Key::Num0 => "0", - constellation_msg::Key::Num1 if shift => "!", - constellation_msg::Key::Num1 => "1", - constellation_msg::Key::Num2 if shift => "@", - constellation_msg::Key::Num2 => "2", - constellation_msg::Key::Num3 if shift => "#", - constellation_msg::Key::Num3 => "3", - constellation_msg::Key::Num4 if shift => "$", - constellation_msg::Key::Num4 => "4", - constellation_msg::Key::Num5 if shift => "%", - constellation_msg::Key::Num5 => "5", - constellation_msg::Key::Num6 if shift => "^", - constellation_msg::Key::Num6 => "6", - constellation_msg::Key::Num7 if shift => "&", - constellation_msg::Key::Num7 => "7", - constellation_msg::Key::Num8 if shift => "*", - constellation_msg::Key::Num8 => "8", - constellation_msg::Key::Num9 if shift => "(", - constellation_msg::Key::Num9 => "9", - constellation_msg::Key::Semicolon if shift => ":", - constellation_msg::Key::Semicolon => ";", - constellation_msg::Key::Equal if shift => "+", - constellation_msg::Key::Equal => "=", - constellation_msg::Key::A if shift => "A", - constellation_msg::Key::A => "a", - constellation_msg::Key::B if shift => "B", - constellation_msg::Key::B => "b", - constellation_msg::Key::C if shift => "C", - constellation_msg::Key::C => "c", - constellation_msg::Key::D if shift => "D", - constellation_msg::Key::D => "d", - constellation_msg::Key::E if shift => "E", - constellation_msg::Key::E => "e", - constellation_msg::Key::F if shift => "F", - constellation_msg::Key::F => "f", - constellation_msg::Key::G if shift => "G", - constellation_msg::Key::G => "g", - constellation_msg::Key::H if shift => "H", - constellation_msg::Key::H => "h", - constellation_msg::Key::I if shift => "I", - constellation_msg::Key::I => "i", - constellation_msg::Key::J if shift => "J", - constellation_msg::Key::J => "j", - constellation_msg::Key::K if shift => "K", - constellation_msg::Key::K => "k", - constellation_msg::Key::L if shift => "L", - constellation_msg::Key::L => "l", - constellation_msg::Key::M if shift => "M", - constellation_msg::Key::M => "m", - constellation_msg::Key::N if shift => "N", - constellation_msg::Key::N => "n", - constellation_msg::Key::O if shift => "O", - constellation_msg::Key::O => "o", - constellation_msg::Key::P if shift => "P", - constellation_msg::Key::P => "p", - constellation_msg::Key::Q if shift => "Q", - constellation_msg::Key::Q => "q", - constellation_msg::Key::R if shift => "R", - constellation_msg::Key::R => "r", - constellation_msg::Key::S if shift => "S", - constellation_msg::Key::S => "s", - constellation_msg::Key::T if shift => "T", - constellation_msg::Key::T => "t", - constellation_msg::Key::U if shift => "U", - constellation_msg::Key::U => "u", - constellation_msg::Key::V if shift => "V", - constellation_msg::Key::V => "v", - constellation_msg::Key::W if shift => "W", - constellation_msg::Key::W => "w", - constellation_msg::Key::X if shift => "X", - constellation_msg::Key::X => "x", - constellation_msg::Key::Y if shift => "Y", - constellation_msg::Key::Y => "y", - constellation_msg::Key::Z if shift => "Z", - constellation_msg::Key::Z => "z", - constellation_msg::Key::LeftBracket if shift => "{", - constellation_msg::Key::LeftBracket => "[", - constellation_msg::Key::Backslash if shift => "|", - constellation_msg::Key::Backslash => "\\", - constellation_msg::Key::RightBracket if shift => "}", - constellation_msg::Key::RightBracket => "]", - constellation_msg::Key::World1 => "Unidentified", - constellation_msg::Key::World2 => "Unidentified", - constellation_msg::Key::Escape => "Escape", - constellation_msg::Key::Enter => "Enter", - constellation_msg::Key::Tab => "Tab", - constellation_msg::Key::Backspace => "Backspace", - constellation_msg::Key::Insert => "Insert", - constellation_msg::Key::Delete => "Delete", - constellation_msg::Key::Right => "ArrowRight", - constellation_msg::Key::Left => "ArrowLeft", - constellation_msg::Key::Down => "ArrowDown", - constellation_msg::Key::Up => "ArrowUp", - constellation_msg::Key::PageUp => "PageUp", - constellation_msg::Key::PageDown => "PageDown", - constellation_msg::Key::Home => "Home", - constellation_msg::Key::End => "End", - constellation_msg::Key::CapsLock => "CapsLock", - constellation_msg::Key::ScrollLock => "ScrollLock", - constellation_msg::Key::NumLock => "NumLock", - constellation_msg::Key::PrintScreen => "PrintScreen", - constellation_msg::Key::Pause => "Pause", - constellation_msg::Key::F1 => "F1", - constellation_msg::Key::F2 => "F2", - constellation_msg::Key::F3 => "F3", - constellation_msg::Key::F4 => "F4", - constellation_msg::Key::F5 => "F5", - constellation_msg::Key::F6 => "F6", - constellation_msg::Key::F7 => "F7", - constellation_msg::Key::F8 => "F8", - constellation_msg::Key::F9 => "F9", - constellation_msg::Key::F10 => "F10", - constellation_msg::Key::F11 => "F11", - constellation_msg::Key::F12 => "F12", - constellation_msg::Key::F13 => "F13", - constellation_msg::Key::F14 => "F14", - constellation_msg::Key::F15 => "F15", - constellation_msg::Key::F16 => "F16", - constellation_msg::Key::F17 => "F17", - constellation_msg::Key::F18 => "F18", - constellation_msg::Key::F19 => "F19", - constellation_msg::Key::F20 => "F20", - constellation_msg::Key::F21 => "F21", - constellation_msg::Key::F22 => "F22", - constellation_msg::Key::F23 => "F23", - constellation_msg::Key::F24 => "F24", - constellation_msg::Key::F25 => "F25", - constellation_msg::Key::Kp0 => "0", - constellation_msg::Key::Kp1 => "1", - constellation_msg::Key::Kp2 => "2", - constellation_msg::Key::Kp3 => "3", - constellation_msg::Key::Kp4 => "4", - constellation_msg::Key::Kp5 => "5", - constellation_msg::Key::Kp6 => "6", - constellation_msg::Key::Kp7 => "7", - constellation_msg::Key::Kp8 => "8", - constellation_msg::Key::Kp9 => "9", - constellation_msg::Key::KpDecimal => ".", - constellation_msg::Key::KpDivide => "/", - constellation_msg::Key::KpMultiply => "*", - constellation_msg::Key::KpSubtract => "-", - constellation_msg::Key::KpAdd => "+", - constellation_msg::Key::KpEnter => "Enter", - constellation_msg::Key::KpEqual => "=", - constellation_msg::Key::LeftShift => "Shift", - constellation_msg::Key::LeftControl => "Control", - constellation_msg::Key::LeftAlt => "Alt", - constellation_msg::Key::LeftSuper => "Super", - constellation_msg::Key::RightShift => "Shift", - constellation_msg::Key::RightControl => "Control", - constellation_msg::Key::RightAlt => "Alt", - constellation_msg::Key::RightSuper => "Super", - constellation_msg::Key::Menu => "ContextMenu", + Key::Space => " ", + Key::Apostrophe if shift => "\"", + Key::Apostrophe => "'", + Key::Comma if shift => "<", + Key::Comma => ",", + Key::Minus if shift => "_", + Key::Minus => "-", + Key::Period if shift => ">", + Key::Period => ".", + Key::Slash if shift => "?", + Key::Slash => "/", + Key::GraveAccent if shift => "~", + Key::GraveAccent => "`", + Key::Num0 if shift => ")", + Key::Num0 => "0", + Key::Num1 if shift => "!", + Key::Num1 => "1", + Key::Num2 if shift => "@", + Key::Num2 => "2", + Key::Num3 if shift => "#", + Key::Num3 => "3", + Key::Num4 if shift => "$", + Key::Num4 => "4", + Key::Num5 if shift => "%", + Key::Num5 => "5", + Key::Num6 if shift => "^", + Key::Num6 => "6", + Key::Num7 if shift => "&", + Key::Num7 => "7", + Key::Num8 if shift => "*", + Key::Num8 => "8", + Key::Num9 if shift => "(", + Key::Num9 => "9", + Key::Semicolon if shift => ":", + Key::Semicolon => ";", + Key::Equal if shift => "+", + Key::Equal => "=", + Key::A if shift => "A", + Key::A => "a", + Key::B if shift => "B", + Key::B => "b", + Key::C if shift => "C", + Key::C => "c", + Key::D if shift => "D", + Key::D => "d", + Key::E if shift => "E", + Key::E => "e", + Key::F if shift => "F", + Key::F => "f", + Key::G if shift => "G", + Key::G => "g", + Key::H if shift => "H", + Key::H => "h", + Key::I if shift => "I", + Key::I => "i", + Key::J if shift => "J", + Key::J => "j", + Key::K if shift => "K", + Key::K => "k", + Key::L if shift => "L", + Key::L => "l", + Key::M if shift => "M", + Key::M => "m", + Key::N if shift => "N", + Key::N => "n", + Key::O if shift => "O", + Key::O => "o", + Key::P if shift => "P", + Key::P => "p", + Key::Q if shift => "Q", + Key::Q => "q", + Key::R if shift => "R", + Key::R => "r", + Key::S if shift => "S", + Key::S => "s", + Key::T if shift => "T", + Key::T => "t", + Key::U if shift => "U", + Key::U => "u", + Key::V if shift => "V", + Key::V => "v", + Key::W if shift => "W", + Key::W => "w", + Key::X if shift => "X", + Key::X => "x", + Key::Y if shift => "Y", + Key::Y => "y", + Key::Z if shift => "Z", + Key::Z => "z", + Key::LeftBracket if shift => "{", + Key::LeftBracket => "[", + Key::Backslash if shift => "|", + Key::Backslash => "\\", + Key::RightBracket if shift => "}", + Key::RightBracket => "]", + Key::World1 => "Unidentified", + Key::World2 => "Unidentified", + Key::Escape => "Escape", + Key::Enter => "Enter", + Key::Tab => "Tab", + Key::Backspace => "Backspace", + Key::Insert => "Insert", + Key::Delete => "Delete", + Key::Right => "ArrowRight", + Key::Left => "ArrowLeft", + Key::Down => "ArrowDown", + Key::Up => "ArrowUp", + Key::PageUp => "PageUp", + Key::PageDown => "PageDown", + Key::Home => "Home", + Key::End => "End", + Key::CapsLock => "CapsLock", + Key::ScrollLock => "ScrollLock", + Key::NumLock => "NumLock", + Key::PrintScreen => "PrintScreen", + Key::Pause => "Pause", + Key::F1 => "F1", + Key::F2 => "F2", + Key::F3 => "F3", + Key::F4 => "F4", + Key::F5 => "F5", + Key::F6 => "F6", + Key::F7 => "F7", + Key::F8 => "F8", + Key::F9 => "F9", + Key::F10 => "F10", + Key::F11 => "F11", + Key::F12 => "F12", + Key::F13 => "F13", + Key::F14 => "F14", + Key::F15 => "F15", + Key::F16 => "F16", + Key::F17 => "F17", + Key::F18 => "F18", + Key::F19 => "F19", + Key::F20 => "F20", + Key::F21 => "F21", + Key::F22 => "F22", + Key::F23 => "F23", + Key::F24 => "F24", + Key::F25 => "F25", + Key::Kp0 => "0", + Key::Kp1 => "1", + Key::Kp2 => "2", + Key::Kp3 => "3", + Key::Kp4 => "4", + Key::Kp5 => "5", + Key::Kp6 => "6", + Key::Kp7 => "7", + Key::Kp8 => "8", + Key::Kp9 => "9", + Key::KpDecimal => ".", + Key::KpDivide => "/", + Key::KpMultiply => "*", + Key::KpSubtract => "-", + Key::KpAdd => "+", + Key::KpEnter => "Enter", + Key::KpEqual => "=", + Key::LeftShift => "Shift", + Key::LeftControl => "Control", + Key::LeftAlt => "Alt", + Key::LeftSuper => "Super", + Key::RightShift => "Shift", + Key::RightControl => "Control", + Key::RightAlt => "Alt", + Key::RightSuper => "Super", + Key::Menu => "ContextMenu", + } +} + +fn key_from_string(key_string: &str, location: u32) -> Option<Key> { + match key_string { + " " => Some(Key::Space), + "\"" => Some(Key::Apostrophe), + "'" => Some(Key::Apostrophe), + "<" => Some(Key::Comma), + "," => Some(Key::Comma), + "_" => Some(Key::Minus), + "-" if location == KeyboardEventConstants::DOM_KEY_LOCATION_STANDARD => Some(Key::Minus), + ">" => Some(Key::Period), + "." if location == KeyboardEventConstants::DOM_KEY_LOCATION_STANDARD => Some(Key::Period), + "?" => Some(Key::Slash), + "/" if location == KeyboardEventConstants::DOM_KEY_LOCATION_STANDARD => Some(Key::Slash), + "~" => Some(Key::GraveAccent), + "`" => Some(Key::GraveAccent), + ")" => Some(Key::Num0), + "0" if location == KeyboardEventConstants::DOM_KEY_LOCATION_STANDARD => Some(Key::Num0), + "!" => Some(Key::Num1), + "1" if location == KeyboardEventConstants::DOM_KEY_LOCATION_STANDARD => Some(Key::Num1), + "@" => Some(Key::Num2), + "2" if location == KeyboardEventConstants::DOM_KEY_LOCATION_STANDARD => Some(Key::Num2), + "#" => Some(Key::Num3), + "3" if location == KeyboardEventConstants::DOM_KEY_LOCATION_STANDARD => Some(Key::Num3), + "$" => Some(Key::Num4), + "4" if location == KeyboardEventConstants::DOM_KEY_LOCATION_STANDARD => Some(Key::Num4), + "%" => Some(Key::Num5), + "5" if location == KeyboardEventConstants::DOM_KEY_LOCATION_STANDARD => Some(Key::Num5), + "^" => Some(Key::Num6), + "6" if location == KeyboardEventConstants::DOM_KEY_LOCATION_STANDARD => Some(Key::Num6), + "&" => Some(Key::Num7), + "7" if location == KeyboardEventConstants::DOM_KEY_LOCATION_STANDARD => Some(Key::Num7), + "*" if location == KeyboardEventConstants::DOM_KEY_LOCATION_STANDARD => Some(Key::Num8), + "8" if location == KeyboardEventConstants::DOM_KEY_LOCATION_STANDARD => Some(Key::Num8), + "(" => Some(Key::Num9), + "9" if location == KeyboardEventConstants::DOM_KEY_LOCATION_STANDARD => Some(Key::Num9), + ":" => Some(Key::Semicolon), + ";" => Some(Key::Semicolon), + "+" if location == KeyboardEventConstants::DOM_KEY_LOCATION_STANDARD => Some(Key::Equal), + "=" if location == KeyboardEventConstants::DOM_KEY_LOCATION_STANDARD => Some(Key::Equal), + "A" => Some(Key::A), + "a" => Some(Key::A), + "B" => Some(Key::B), + "b" => Some(Key::B), + "C" => Some(Key::C), + "c" => Some(Key::C), + "D" => Some(Key::D), + "d" => Some(Key::D), + "E" => Some(Key::E), + "e" => Some(Key::E), + "F" => Some(Key::F), + "f" => Some(Key::F), + "G" => Some(Key::G), + "g" => Some(Key::G), + "H" => Some(Key::H), + "h" => Some(Key::H), + "I" => Some(Key::I), + "i" => Some(Key::I), + "J" => Some(Key::J), + "j" => Some(Key::J), + "K" => Some(Key::K), + "k" => Some(Key::K), + "L" => Some(Key::L), + "l" => Some(Key::L), + "M" => Some(Key::M), + "m" => Some(Key::M), + "N" => Some(Key::N), + "n" => Some(Key::N), + "O" => Some(Key::O), + "o" => Some(Key::O), + "P" => Some(Key::P), + "p" => Some(Key::P), + "Q" => Some(Key::Q), + "q" => Some(Key::Q), + "R" => Some(Key::R), + "r" => Some(Key::R), + "S" => Some(Key::S), + "s" => Some(Key::S), + "T" => Some(Key::T), + "t" => Some(Key::T), + "U" => Some(Key::U), + "u" => Some(Key::U), + "V" => Some(Key::V), + "v" => Some(Key::V), + "W" => Some(Key::W), + "w" => Some(Key::W), + "X" => Some(Key::X), + "x" => Some(Key::X), + "Y" => Some(Key::Y), + "y" => Some(Key::Y), + "Z" => Some(Key::Z), + "z" => Some(Key::Z), + "{" => Some(Key::LeftBracket), + "[" => Some(Key::LeftBracket), + "|" => Some(Key::Backslash), + "\\" => Some(Key::Backslash), + "}" => Some(Key::RightBracket), + "]" => Some(Key::RightBracket), + "Escape" => Some(Key::Escape), + "Enter" if location == KeyboardEventConstants::DOM_KEY_LOCATION_STANDARD => Some(Key::Enter), + "Tab" => Some(Key::Tab), + "Backspace" => Some(Key::Backspace), + "Insert" => Some(Key::Insert), + "Delete" => Some(Key::Delete), + "ArrowRight" => Some(Key::Right), + "ArrowLeft" => Some(Key::Left), + "ArrowDown" => Some(Key::Down), + "ArrowUp" => Some(Key::Up), + "PageUp" => Some(Key::PageUp), + "PageDown" => Some(Key::PageDown), + "Home" => Some(Key::Home), + "End" => Some(Key::End), + "CapsLock" => Some(Key::CapsLock), + "ScrollLock" => Some(Key::ScrollLock), + "NumLock" => Some(Key::NumLock), + "PrintScreen" => Some(Key::PrintScreen), + "Pause" => Some(Key::Pause), + "F1" => Some(Key::F1), + "F2" => Some(Key::F2), + "F3" => Some(Key::F3), + "F4" => Some(Key::F4), + "F5" => Some(Key::F5), + "F6" => Some(Key::F6), + "F7" => Some(Key::F7), + "F8" => Some(Key::F8), + "F9" => Some(Key::F9), + "F10" => Some(Key::F10), + "F11" => Some(Key::F11), + "F12" => Some(Key::F12), + "F13" => Some(Key::F13), + "F14" => Some(Key::F14), + "F15" => Some(Key::F15), + "F16" => Some(Key::F16), + "F17" => Some(Key::F17), + "F18" => Some(Key::F18), + "F19" => Some(Key::F19), + "F20" => Some(Key::F20), + "F21" => Some(Key::F21), + "F22" => Some(Key::F22), + "F23" => Some(Key::F23), + "F24" => Some(Key::F24), + "F25" => Some(Key::F25), + "0" if location == KeyboardEventConstants::DOM_KEY_LOCATION_NUMPAD => Some(Key::Kp0), + "1" if location == KeyboardEventConstants::DOM_KEY_LOCATION_NUMPAD => Some(Key::Kp1), + "2" if location == KeyboardEventConstants::DOM_KEY_LOCATION_NUMPAD => Some(Key::Kp2), + "3" if location == KeyboardEventConstants::DOM_KEY_LOCATION_NUMPAD => Some(Key::Kp3), + "4" if location == KeyboardEventConstants::DOM_KEY_LOCATION_NUMPAD => Some(Key::Kp4), + "5" if location == KeyboardEventConstants::DOM_KEY_LOCATION_NUMPAD => Some(Key::Kp5), + "6" if location == KeyboardEventConstants::DOM_KEY_LOCATION_NUMPAD => Some(Key::Kp6), + "7" if location == KeyboardEventConstants::DOM_KEY_LOCATION_NUMPAD => Some(Key::Kp7), + "8" if location == KeyboardEventConstants::DOM_KEY_LOCATION_NUMPAD => Some(Key::Kp8), + "9" if location == KeyboardEventConstants::DOM_KEY_LOCATION_NUMPAD => Some(Key::Kp9), + "." if location == KeyboardEventConstants::DOM_KEY_LOCATION_NUMPAD => Some(Key::KpDecimal), + "/" if location == KeyboardEventConstants::DOM_KEY_LOCATION_NUMPAD => Some(Key::KpDivide), + "*" if location == KeyboardEventConstants::DOM_KEY_LOCATION_NUMPAD => Some(Key::KpMultiply), + "-" if location == KeyboardEventConstants::DOM_KEY_LOCATION_NUMPAD => Some(Key::KpSubtract), + "+" if location == KeyboardEventConstants::DOM_KEY_LOCATION_NUMPAD => Some(Key::KpAdd), + "Enter" if location == KeyboardEventConstants::DOM_KEY_LOCATION_NUMPAD => Some(Key::KpEnter), + "=" if location == KeyboardEventConstants::DOM_KEY_LOCATION_NUMPAD => Some(Key::KpEqual), + "Shift" if location == KeyboardEventConstants::DOM_KEY_LOCATION_LEFT => Some(Key::LeftShift), + "Control" if location == KeyboardEventConstants::DOM_KEY_LOCATION_LEFT => Some(Key::LeftControl), + "Alt" if location == KeyboardEventConstants::DOM_KEY_LOCATION_LEFT => Some(Key::LeftAlt), + "Super" if location == KeyboardEventConstants::DOM_KEY_LOCATION_LEFT => Some(Key::LeftSuper), + "Shift" if location == KeyboardEventConstants::DOM_KEY_LOCATION_RIGHT => Some(Key::RightShift), + "Control" if location == KeyboardEventConstants::DOM_KEY_LOCATION_RIGHT => Some(Key::RightControl), + "Alt" if location == KeyboardEventConstants::DOM_KEY_LOCATION_RIGHT => Some(Key::RightAlt), + "Super" if location == KeyboardEventConstants::DOM_KEY_LOCATION_RIGHT => Some(Key::RightSuper), + "ContextMenu" => Some(Key::Menu), + _ => None } } // https://dvcs.w3.org/hg/dom3events/raw-file/tip/html/DOM3Events-code.html -fn code_value(key: constellation_msg::Key) -> &'static str { +fn code_value(key: Key) -> &'static str { match key { - constellation_msg::Key::Space => "Space", - constellation_msg::Key::Apostrophe => "Quote", - constellation_msg::Key::Comma => "Comma", - constellation_msg::Key::Minus => "Minus", - constellation_msg::Key::Period => "Period", - constellation_msg::Key::Slash => "Slash", - constellation_msg::Key::GraveAccent => "Backquote", - constellation_msg::Key::Num0 => "Digit0", - constellation_msg::Key::Num1 => "Digit1", - constellation_msg::Key::Num2 => "Digit2", - constellation_msg::Key::Num3 => "Digit3", - constellation_msg::Key::Num4 => "Digit4", - constellation_msg::Key::Num5 => "Digit5", - constellation_msg::Key::Num6 => "Digit6", - constellation_msg::Key::Num7 => "Digit7", - constellation_msg::Key::Num8 => "Digit8", - constellation_msg::Key::Num9 => "Digit9", - constellation_msg::Key::Semicolon => "Semicolon", - constellation_msg::Key::Equal => "Equal", - constellation_msg::Key::A => "KeyA", - constellation_msg::Key::B => "KeyB", - constellation_msg::Key::C => "KeyC", - constellation_msg::Key::D => "KeyD", - constellation_msg::Key::E => "KeyE", - constellation_msg::Key::F => "KeyF", - constellation_msg::Key::G => "KeyG", - constellation_msg::Key::H => "KeyH", - constellation_msg::Key::I => "KeyI", - constellation_msg::Key::J => "KeyJ", - constellation_msg::Key::K => "KeyK", - constellation_msg::Key::L => "KeyL", - constellation_msg::Key::M => "KeyM", - constellation_msg::Key::N => "KeyN", - constellation_msg::Key::O => "KeyO", - constellation_msg::Key::P => "KeyP", - constellation_msg::Key::Q => "KeyQ", - constellation_msg::Key::R => "KeyR", - constellation_msg::Key::S => "KeyS", - constellation_msg::Key::T => "KeyT", - constellation_msg::Key::U => "KeyU", - constellation_msg::Key::V => "KeyV", - constellation_msg::Key::W => "KeyW", - constellation_msg::Key::X => "KeyX", - constellation_msg::Key::Y => "KeyY", - constellation_msg::Key::Z => "KeyZ", - constellation_msg::Key::LeftBracket => "BracketLeft", - constellation_msg::Key::Backslash => "Backslash", - constellation_msg::Key::RightBracket => "BracketRight", - - constellation_msg::Key::World1 | - constellation_msg::Key::World2 => panic!("unknown char code for {:?}", key), - - constellation_msg::Key::Escape => "Escape", - constellation_msg::Key::Enter => "Enter", - constellation_msg::Key::Tab => "Tab", - constellation_msg::Key::Backspace => "Backspace", - constellation_msg::Key::Insert => "Insert", - constellation_msg::Key::Delete => "Delete", - constellation_msg::Key::Right => "ArrowRight", - constellation_msg::Key::Left => "ArrowLeft", - constellation_msg::Key::Down => "ArrowDown", - constellation_msg::Key::Up => "ArrowUp", - constellation_msg::Key::PageUp => "PageUp", - constellation_msg::Key::PageDown => "PageDown", - constellation_msg::Key::Home => "Home", - constellation_msg::Key::End => "End", - constellation_msg::Key::CapsLock => "CapsLock", - constellation_msg::Key::ScrollLock => "ScrollLock", - constellation_msg::Key::NumLock => "NumLock", - constellation_msg::Key::PrintScreen => "PrintScreen", - constellation_msg::Key::Pause => "Pause", - constellation_msg::Key::F1 => "F1", - constellation_msg::Key::F2 => "F2", - constellation_msg::Key::F3 => "F3", - constellation_msg::Key::F4 => "F4", - constellation_msg::Key::F5 => "F5", - constellation_msg::Key::F6 => "F6", - constellation_msg::Key::F7 => "F7", - constellation_msg::Key::F8 => "F8", - constellation_msg::Key::F9 => "F9", - constellation_msg::Key::F10 => "F10", - constellation_msg::Key::F11 => "F11", - constellation_msg::Key::F12 => "F12", - constellation_msg::Key::F13 => "F13", - constellation_msg::Key::F14 => "F14", - constellation_msg::Key::F15 => "F15", - constellation_msg::Key::F16 => "F16", - constellation_msg::Key::F17 => "F17", - constellation_msg::Key::F18 => "F18", - constellation_msg::Key::F19 => "F19", - constellation_msg::Key::F20 => "F20", - constellation_msg::Key::F21 => "F21", - constellation_msg::Key::F22 => "F22", - constellation_msg::Key::F23 => "F23", - constellation_msg::Key::F24 => "F24", - constellation_msg::Key::F25 => "F25", - constellation_msg::Key::Kp0 => "Numpad0", - constellation_msg::Key::Kp1 => "Numpad1", - constellation_msg::Key::Kp2 => "Numpad2", - constellation_msg::Key::Kp3 => "Numpad3", - constellation_msg::Key::Kp4 => "Numpad4", - constellation_msg::Key::Kp5 => "Numpad5", - constellation_msg::Key::Kp6 => "Numpad6", - constellation_msg::Key::Kp7 => "Numpad7", - constellation_msg::Key::Kp8 => "Numpad8", - constellation_msg::Key::Kp9 => "Numpad9", - constellation_msg::Key::KpDecimal => "NumpadDecimal", - constellation_msg::Key::KpDivide => "NumpadDivide", - constellation_msg::Key::KpMultiply => "NumpadMultiply", - constellation_msg::Key::KpSubtract => "NumpadSubtract", - constellation_msg::Key::KpAdd => "NumpadAdd", - constellation_msg::Key::KpEnter => "NumpadEnter", - constellation_msg::Key::KpEqual => "NumpadEqual", - constellation_msg::Key::LeftShift | constellation_msg::Key::RightShift => "Shift", - constellation_msg::Key::LeftControl | constellation_msg::Key::RightControl => "Control", - constellation_msg::Key::LeftAlt | constellation_msg::Key::RightAlt => "Alt", - constellation_msg::Key::LeftSuper | constellation_msg::Key::RightSuper => "Super", - constellation_msg::Key::Menu => "Menu", + Key::Space => "Space", + Key::Apostrophe => "Quote", + Key::Comma => "Comma", + Key::Minus => "Minus", + Key::Period => "Period", + Key::Slash => "Slash", + Key::GraveAccent => "Backquote", + Key::Num0 => "Digit0", + Key::Num1 => "Digit1", + Key::Num2 => "Digit2", + Key::Num3 => "Digit3", + Key::Num4 => "Digit4", + Key::Num5 => "Digit5", + Key::Num6 => "Digit6", + Key::Num7 => "Digit7", + Key::Num8 => "Digit8", + Key::Num9 => "Digit9", + Key::Semicolon => "Semicolon", + Key::Equal => "Equal", + Key::A => "KeyA", + Key::B => "KeyB", + Key::C => "KeyC", + Key::D => "KeyD", + Key::E => "KeyE", + Key::F => "KeyF", + Key::G => "KeyG", + Key::H => "KeyH", + Key::I => "KeyI", + Key::J => "KeyJ", + Key::K => "KeyK", + Key::L => "KeyL", + Key::M => "KeyM", + Key::N => "KeyN", + Key::O => "KeyO", + Key::P => "KeyP", + Key::Q => "KeyQ", + Key::R => "KeyR", + Key::S => "KeyS", + Key::T => "KeyT", + Key::U => "KeyU", + Key::V => "KeyV", + Key::W => "KeyW", + Key::X => "KeyX", + Key::Y => "KeyY", + Key::Z => "KeyZ", + Key::LeftBracket => "BracketLeft", + Key::Backslash => "Backslash", + Key::RightBracket => "BracketRight", + + Key::World1 | + Key::World2 => panic!("unknown char code for {:?}", key), + + Key::Escape => "Escape", + Key::Enter => "Enter", + Key::Tab => "Tab", + Key::Backspace => "Backspace", + Key::Insert => "Insert", + Key::Delete => "Delete", + Key::Right => "ArrowRight", + Key::Left => "ArrowLeft", + Key::Down => "ArrowDown", + Key::Up => "ArrowUp", + Key::PageUp => "PageUp", + Key::PageDown => "PageDown", + Key::Home => "Home", + Key::End => "End", + Key::CapsLock => "CapsLock", + Key::ScrollLock => "ScrollLock", + Key::NumLock => "NumLock", + Key::PrintScreen => "PrintScreen", + Key::Pause => "Pause", + Key::F1 => "F1", + Key::F2 => "F2", + Key::F3 => "F3", + Key::F4 => "F4", + Key::F5 => "F5", + Key::F6 => "F6", + Key::F7 => "F7", + Key::F8 => "F8", + Key::F9 => "F9", + Key::F10 => "F10", + Key::F11 => "F11", + Key::F12 => "F12", + Key::F13 => "F13", + Key::F14 => "F14", + Key::F15 => "F15", + Key::F16 => "F16", + Key::F17 => "F17", + Key::F18 => "F18", + Key::F19 => "F19", + Key::F20 => "F20", + Key::F21 => "F21", + Key::F22 => "F22", + Key::F23 => "F23", + Key::F24 => "F24", + Key::F25 => "F25", + Key::Kp0 => "Numpad0", + Key::Kp1 => "Numpad1", + Key::Kp2 => "Numpad2", + Key::Kp3 => "Numpad3", + Key::Kp4 => "Numpad4", + Key::Kp5 => "Numpad5", + Key::Kp6 => "Numpad6", + Key::Kp7 => "Numpad7", + Key::Kp8 => "Numpad8", + Key::Kp9 => "Numpad9", + Key::KpDecimal => "NumpadDecimal", + Key::KpDivide => "NumpadDivide", + Key::KpMultiply => "NumpadMultiply", + Key::KpSubtract => "NumpadSubtract", + Key::KpAdd => "NumpadAdd", + Key::KpEnter => "NumpadEnter", + Key::KpEqual => "NumpadEqual", + Key::LeftShift | Key::RightShift => "Shift", + Key::LeftControl | Key::RightControl => "Control", + Key::LeftAlt | Key::RightAlt => "Alt", + Key::LeftSuper | Key::RightSuper => "Super", + Key::Menu => "Menu", } } -fn key_location(key: constellation_msg::Key) -> u32 { +fn key_location(key: Key) -> u32 { match key { - constellation_msg::Key::Kp0 | constellation_msg::Key::Kp1 | constellation_msg::Key::Kp2 | - constellation_msg::Key::Kp3 | constellation_msg::Key::Kp4 | constellation_msg::Key::Kp5 | - constellation_msg::Key::Kp6 | constellation_msg::Key::Kp7 | constellation_msg::Key::Kp8 | - constellation_msg::Key::Kp9 | constellation_msg::Key::KpDecimal | - constellation_msg::Key::KpDivide | constellation_msg::Key::KpMultiply | - constellation_msg::Key::KpSubtract | constellation_msg::Key::KpAdd | - constellation_msg::Key::KpEnter | constellation_msg::Key::KpEqual => + Key::Kp0 | Key::Kp1 | Key::Kp2 | + Key::Kp3 | Key::Kp4 | Key::Kp5 | + Key::Kp6 | Key::Kp7 | Key::Kp8 | + Key::Kp9 | Key::KpDecimal | + Key::KpDivide | Key::KpMultiply | + Key::KpSubtract | Key::KpAdd | + Key::KpEnter | Key::KpEqual => KeyboardEventConstants::DOM_KEY_LOCATION_NUMPAD, - constellation_msg::Key::LeftShift | constellation_msg::Key::LeftAlt | - constellation_msg::Key::LeftControl | constellation_msg::Key::LeftSuper => + Key::LeftShift | Key::LeftAlt | + Key::LeftControl | Key::LeftSuper => KeyboardEventConstants::DOM_KEY_LOCATION_LEFT, - constellation_msg::Key::RightShift | constellation_msg::Key::RightAlt | - constellation_msg::Key::RightControl | constellation_msg::Key::RightSuper => + Key::RightShift | Key::RightAlt | + Key::RightControl | Key::RightSuper => KeyboardEventConstants::DOM_KEY_LOCATION_RIGHT, _ => KeyboardEventConstants::DOM_KEY_LOCATION_STANDARD, @@ -447,89 +655,89 @@ fn key_location(key: constellation_msg::Key) -> u32 { } // https://dvcs.w3.org/hg/dom3events/raw-file/tip/html/DOM3-Events.html#widl-KeyboardEvent-charCode -fn key_charcode(key: constellation_msg::Key, mods: constellation_msg::KeyModifiers) -> Option<u32> { - let key = key_value(key, mods); - if key.len() == 1 { - Some(key.chars().next().unwrap() as u32) +fn key_charcode(key: Key, mods: KeyModifiers) -> Option<u32> { + let key_string = key_value(key, mods); + if key_string.len() == 1 { + Some(key_string.chars().next().unwrap() as u32) } else { None } } // https://dvcs.w3.org/hg/dom3events/raw-file/tip/html/DOM3-Events.html#legacy-key-models -fn key_keycode(key: constellation_msg::Key) -> u32 { +fn key_keycode(key: Key) -> u32 { match key { // https://dvcs.w3.org/hg/dom3events/raw-file/tip/html/DOM3-Events.html#legacy-key-models - constellation_msg::Key::Backspace => 8, - constellation_msg::Key::Tab => 9, - constellation_msg::Key::Enter => 13, - constellation_msg::Key::LeftShift | constellation_msg::Key::RightShift => 16, - constellation_msg::Key::LeftControl | constellation_msg::Key::RightControl => 17, - constellation_msg::Key::LeftAlt | constellation_msg::Key::RightAlt => 18, - constellation_msg::Key::CapsLock => 20, - constellation_msg::Key::Escape => 27, - constellation_msg::Key::Space => 32, - constellation_msg::Key::PageUp => 33, - constellation_msg::Key::PageDown => 34, - constellation_msg::Key::End => 35, - constellation_msg::Key::Home => 36, - constellation_msg::Key::Left => 37, - constellation_msg::Key::Up => 38, - constellation_msg::Key::Right => 39, - constellation_msg::Key::Down => 40, - constellation_msg::Key::Delete => 46, + Key::Backspace => 8, + Key::Tab => 9, + Key::Enter => 13, + Key::LeftShift | Key::RightShift => 16, + Key::LeftControl | Key::RightControl => 17, + Key::LeftAlt | Key::RightAlt => 18, + Key::CapsLock => 20, + Key::Escape => 27, + Key::Space => 32, + Key::PageUp => 33, + Key::PageDown => 34, + Key::End => 35, + Key::Home => 36, + Key::Left => 37, + Key::Up => 38, + Key::Right => 39, + Key::Down => 40, + Key::Delete => 46, // https://dvcs.w3.org/hg/dom3events/raw-file/tip/html/DOM3-Events.html#optionally-fixed-virtual-key-codes - constellation_msg::Key::Semicolon => 186, - constellation_msg::Key::Equal => 187, - constellation_msg::Key::Comma => 188, - constellation_msg::Key::Minus => 189, - constellation_msg::Key::Period => 190, - constellation_msg::Key::Slash => 191, - constellation_msg::Key::LeftBracket => 219, - constellation_msg::Key::Backslash => 220, - constellation_msg::Key::RightBracket => 221, - constellation_msg::Key::Apostrophe => 222, + Key::Semicolon => 186, + Key::Equal => 187, + Key::Comma => 188, + Key::Minus => 189, + Key::Period => 190, + Key::Slash => 191, + Key::LeftBracket => 219, + Key::Backslash => 220, + Key::RightBracket => 221, + Key::Apostrophe => 222, //§ B.2.1.3 - constellation_msg::Key::Num0 | - constellation_msg::Key::Num1 | - constellation_msg::Key::Num2 | - constellation_msg::Key::Num3 | - constellation_msg::Key::Num4 | - constellation_msg::Key::Num5 | - constellation_msg::Key::Num6 | - constellation_msg::Key::Num7 | - constellation_msg::Key::Num8 | - constellation_msg::Key::Num9 => key as u32 - constellation_msg::Key::Num0 as u32 + '0' as u32, + Key::Num0 | + Key::Num1 | + Key::Num2 | + Key::Num3 | + Key::Num4 | + Key::Num5 | + Key::Num6 | + Key::Num7 | + Key::Num8 | + Key::Num9 => key as u32 - Key::Num0 as u32 + '0' as u32, //§ B.2.1.4 - constellation_msg::Key::A | - constellation_msg::Key::B | - constellation_msg::Key::C | - constellation_msg::Key::D | - constellation_msg::Key::E | - constellation_msg::Key::F | - constellation_msg::Key::G | - constellation_msg::Key::H | - constellation_msg::Key::I | - constellation_msg::Key::J | - constellation_msg::Key::K | - constellation_msg::Key::L | - constellation_msg::Key::M | - constellation_msg::Key::N | - constellation_msg::Key::O | - constellation_msg::Key::P | - constellation_msg::Key::Q | - constellation_msg::Key::R | - constellation_msg::Key::S | - constellation_msg::Key::T | - constellation_msg::Key::U | - constellation_msg::Key::V | - constellation_msg::Key::W | - constellation_msg::Key::X | - constellation_msg::Key::Y | - constellation_msg::Key::Z => key as u32 - constellation_msg::Key::A as u32 + 'A' as u32, + Key::A | + Key::B | + Key::C | + Key::D | + Key::E | + Key::F | + Key::G | + Key::H | + Key::I | + Key::J | + Key::K | + Key::L | + Key::M | + Key::N | + Key::O | + Key::P | + Key::Q | + Key::R | + Key::S | + Key::T | + Key::U | + Key::V | + Key::W | + Key::X | + Key::Y | + Key::Z => key as u32 - Key::A as u32 + 'A' as u32, //§ B.2.1.8 _ => 0 @@ -537,7 +745,7 @@ fn key_keycode(key: constellation_msg::Key) -> u32 { } pub struct KeyEventProperties { - pub key: &'static str, + pub key_string: &'static str, pub code: &'static str, pub location: u32, pub char_code: Option<u32>, @@ -568,15 +776,15 @@ impl<'a> KeyboardEventMethods for JSRef<'a, KeyboardEvent> { let uievent: JSRef<UIEvent> = UIEventCast::from_ref(self); uievent.InitUIEvent(typeArg, canBubbleArg, cancelableArg, viewArg, 0); - *self.key.borrow_mut() = keyArg; + *self.key_string.borrow_mut() = keyArg; self.location.set(locationArg); self.repeat.set(repeat); } fn Key(self) -> DOMString { // FIXME(https://github.com/rust-lang/rust/issues/23338) - let key = self.key.borrow(); - key.clone() + let key_string = self.key_string.borrow(); + key_string.clone() } fn Code(self) -> DOMString { diff --git a/components/script/lib.rs b/components/script/lib.rs index 3232ecec963..09340e7446e 100644 --- a/components/script/lib.rs +++ b/components/script/lib.rs @@ -66,6 +66,7 @@ pub mod page; pub mod script_task; mod timers; pub mod textinput; +pub mod clipboard_provider; mod devtools; mod horribly_inefficient_timers; mod webdriver_handlers; diff --git a/components/script/textinput.rs b/components/script/textinput.rs index f99f5e8781c..abe74f2f330 100644 --- a/components/script/textinput.rs +++ b/components/script/textinput.rs @@ -4,17 +4,17 @@ //! Common handling of keyboard input and state management for text input controls -use dom::bindings::codegen::Bindings::KeyboardEventBinding::KeyboardEventMethods; +use clipboard_provider::ClipboardProvider; use dom::bindings::js::JSRef; -use msg::constellation_msg::ConstellationChan; -use msg::constellation_msg::Msg as ConstellationMsg; -use dom::keyboardevent::KeyboardEvent; +use dom::keyboardevent::{KeyboardEvent, KeyboardEventHelpers, key_value}; +use msg::constellation_msg::{SHIFT, CONTROL, ALT, SUPER}; +use msg::constellation_msg::{Key, KeyModifiers}; use util::str::DOMString; use std::borrow::ToOwned; use std::cmp::{min, max}; use std::default::Default; -use std::sync::mpsc::channel; + #[derive(Copy, Clone, PartialEq)] pub enum Selection { @@ -33,7 +33,7 @@ pub struct TextPoint { /// Encapsulated state for handling keyboard input in a single or multiline text input control. #[jstraceable] -pub struct TextInput { +pub struct TextInput<T: ClipboardProvider> { /// Current text input content, split across lines without trailing '\n' lines: Vec<DOMString>, /// Current cursor input point @@ -42,7 +42,7 @@ pub struct TextInput { selection_begin: Option<TextPoint>, /// Is this a multiline input? multiline: bool, - constellation_channel: Option<ConstellationChan> + clipboard_provider: T, } /// Resulting action to be taken by the owner of a text input that is handling an event. @@ -79,24 +79,42 @@ pub enum DeleteDir { /// Was the keyboard event accompanied by the standard control modifier, /// i.e. cmd on Mac OS or ctrl on other platforms. #[cfg(target_os="macos")] -fn is_control_key(event: JSRef<KeyboardEvent>) -> bool { - event.MetaKey() && !event.CtrlKey() && !event.AltKey() +fn is_control_key(mods: KeyModifiers) -> bool { + mods.contains(SUPER) && !mods.contains(CONTROL | ALT) } #[cfg(not(target_os="macos"))] -fn is_control_key(event: JSRef<KeyboardEvent>) -> bool { - event.CtrlKey() && !event.MetaKey() && !event.AltKey() +fn is_control_key(mods: KeyModifiers) -> bool { + mods.contains(CONTROL) && !mods.contains(SUPER | ALT) +} + +fn is_printable_key(key: Key) -> bool { + match key { + Key::Space | Key::Apostrophe | Key::Comma | Key::Minus | + Key::Period | Key::Slash | Key::GraveAccent | Key::Num0 | + Key::Num1 | Key::Num2 | Key::Num3 | Key::Num4 | Key::Num5 | + Key::Num6 | Key::Num7 | Key::Num8 | Key::Num9 | Key::Semicolon | + Key::Equal | Key::A | Key::B | Key::C | Key::D | Key::E | Key::F | + Key::G | Key::H | Key::I | Key::J | Key::K | Key::L | Key::M | Key::N | + Key::O | Key::P | Key::Q | Key::R | Key::S | Key::T | Key::U | Key::V | + Key::W | Key::X | Key::Y | Key::Z | Key::LeftBracket | Key::Backslash | + Key::RightBracket | Key::Kp0 | Key::Kp1 | Key::Kp2 | Key::Kp3 | + Key::Kp4 | Key::Kp5 | Key::Kp6 | Key::Kp7 | Key::Kp8 | Key::Kp9 | + Key::KpDecimal | Key::KpDivide | Key::KpMultiply | Key::KpSubtract | + Key::KpAdd | Key::KpEqual => true, + _ => false, + } } -impl TextInput { +impl<T: ClipboardProvider> TextInput<T> { /// Instantiate a new text input control - pub fn new(lines: Lines, initial: DOMString, cc: Option<ConstellationChan>) -> TextInput { + pub fn new(lines: Lines, initial: DOMString, clipboard_provider: T) -> TextInput<T> { let mut i = TextInput { lines: vec!(), edit_point: Default::default(), selection_begin: None, multiline: lines == Lines::Multiple, - constellation_channel: cc, + clipboard_provider: clipboard_provider }; i.set_content(initial); i @@ -283,81 +301,74 @@ impl TextInput { /// Process a given `KeyboardEvent` and return an action for the caller to execute. pub fn handle_keydown(&mut self, event: JSRef<KeyboardEvent>) -> KeyReaction { - //A simple way to convert an event to a selection - fn maybe_select(event: JSRef<KeyboardEvent>) -> Selection { - if event.ShiftKey() { - return Selection::Selected - } - return Selection::NotSelected + if let Some(key) = event.get_key() { + self.handle_keydown_aux(key, event.get_key_modifiers()) + } else { + KeyReaction::Nothing } - match &*event.Key() { - "a" if is_control_key(event) => { + } + pub fn handle_keydown_aux(&mut self, key: Key, mods: KeyModifiers) -> KeyReaction { + let maybe_select = if mods.contains(SHIFT) { Selection::Selected } else { Selection::NotSelected }; + match key { + Key::A if is_control_key(mods) => { self.select_all(); KeyReaction::Nothing }, - "v" if is_control_key(event) => { - let (tx, rx) = channel(); - let mut contents = None; - if let Some(ref cc) = self.constellation_channel { - cc.0.send(ConstellationMsg::GetClipboardContents(tx)).unwrap(); - contents = Some(rx.recv().unwrap()); - } - if let Some(contents) = contents { - self.insert_string(&contents); - } + Key::V if is_control_key(mods) => { + let contents = self.clipboard_provider.get_clipboard_contents(); + self.insert_string(&contents); KeyReaction::DispatchInput }, - // printable characters have single-character key values - c if c.len() == 1 => { - self.insert_char(c.chars().next().unwrap()); + _ if is_printable_key(key) => { + self.insert_string(key_value(key, mods)); KeyReaction::DispatchInput } - "Space" => { + Key::Space => { self.insert_char(' '); KeyReaction::DispatchInput } - "Delete" => { + Key::Delete => { self.delete_char(DeleteDir::Forward); KeyReaction::DispatchInput } - "Backspace" => { + Key::Backspace => { self.delete_char(DeleteDir::Backward); KeyReaction::DispatchInput } - "ArrowLeft" => { - self.adjust_horizontal(-1, maybe_select(event)); + Key::Left => { + self.adjust_horizontal(-1, maybe_select); KeyReaction::Nothing } - "ArrowRight" => { - self.adjust_horizontal(1, maybe_select(event)); + Key::Right => { + self.adjust_horizontal(1, maybe_select); KeyReaction::Nothing } - "ArrowUp" => { - self.adjust_vertical(-1, maybe_select(event)); + Key::Up => { + self.adjust_vertical(-1, maybe_select); KeyReaction::Nothing } - "ArrowDown" => { - self.adjust_vertical(1, maybe_select(event)); + Key::Down => { + self.adjust_vertical(1, maybe_select); KeyReaction::Nothing } - "Enter" => self.handle_return(), - "Home" => { + Key::Enter | Key::KpEnter => self.handle_return(), + Key::Home => { self.edit_point.index = 0; KeyReaction::Nothing } - "End" => { + Key::End => { self.edit_point.index = self.current_line_length(); KeyReaction::Nothing } - "PageUp" => { - self.adjust_vertical(-28, maybe_select(event)); + Key::PageUp => { + self.adjust_vertical(-28, maybe_select); KeyReaction::Nothing } - "PageDown" => { - self.adjust_vertical(28, maybe_select(event)); + Key::PageDown => { + self.adjust_vertical(28, maybe_select); KeyReaction::Nothing } - "Tab" => KeyReaction::TriggerDefaultAction, + Key::Tab => KeyReaction::TriggerDefaultAction, _ => KeyReaction::Nothing, } } diff --git a/components/servo/Cargo.lock b/components/servo/Cargo.lock index 2494f04f668..771d149dc58 100644 --- a/components/servo/Cargo.lock +++ b/components/servo/Cargo.lock @@ -1037,6 +1037,7 @@ dependencies = [ name = "script_tests" version = "0.0.1" dependencies = [ + "msg 0.0.1", "script 0.0.1", ] diff --git a/tests/unit/script/Cargo.toml b/tests/unit/script/Cargo.toml index 759e0581545..52b4e4b2e80 100644 --- a/tests/unit/script/Cargo.toml +++ b/tests/unit/script/Cargo.toml @@ -8,5 +8,8 @@ name = "script_tests" path = "lib.rs" doctest = false +[dependencies.msg] +path = "../../../components/msg" + [dependencies.script] path = "../../../components/script" diff --git a/tests/unit/script/lib.rs b/tests/unit/script/lib.rs index 3073fcb8588..f0d22cd2ca6 100644 --- a/tests/unit/script/lib.rs +++ b/tests/unit/script/lib.rs @@ -3,6 +3,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ extern crate script; +extern crate msg; #[cfg(all(test, target_pointer_width = "64"))] mod size_of; #[cfg(test)] mod textinput; diff --git a/tests/unit/script/textinput.rs b/tests/unit/script/textinput.rs index 0d7326685db..653507983a2 100644 --- a/tests/unit/script/textinput.rs +++ b/tests/unit/script/textinput.rs @@ -7,12 +7,20 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use msg::constellation_msg::{Key, KeyModifiers}; + +#[cfg(target_os="macos")] +use msg::constellation_msg::SUPER; +#[cfg(not(target_os="macos"))] +use msg::constellation_msg::CONTROL; + use script::textinput::{TextInput, Selection, Lines, DeleteDir}; +use script::clipboard_provider::DummyClipboardContext; use std::borrow::ToOwned; #[test] fn test_textinput_delete_char() { - let mut textinput = TextInput::new(Lines::Single, "abcdefg".to_owned(), None); + let mut textinput = TextInput::new(Lines::Single, "abcdefg".to_owned(), DummyClipboardContext::new("")); textinput.adjust_horizontal(2, Selection::NotSelected); textinput.delete_char(DeleteDir::Backward); assert_eq!(textinput.get_content(), "acdefg"); @@ -27,7 +35,7 @@ fn test_textinput_delete_char() { #[test] fn test_textinput_insert_char() { - let mut textinput = TextInput::new(Lines::Single, "abcdefg".to_owned(), None); + let mut textinput = TextInput::new(Lines::Single, "abcdefg".to_owned(), DummyClipboardContext::new("")); textinput.adjust_horizontal(2, Selection::NotSelected); textinput.insert_char('a'); assert_eq!(textinput.get_content(), "abacdefg"); @@ -39,7 +47,7 @@ fn test_textinput_insert_char() { #[test] fn test_textinput_get_sorted_selection() { - let mut textinput = TextInput::new(Lines::Single, "abcdefg".to_owned(), None); + let mut textinput = TextInput::new(Lines::Single, "abcdefg".to_owned(), DummyClipboardContext::new("")); textinput.adjust_horizontal(2, Selection::NotSelected); textinput.adjust_horizontal(2, Selection::Selected); let (begin, end) = textinput.get_sorted_selection(); @@ -56,7 +64,7 @@ fn test_textinput_get_sorted_selection() { #[test] fn test_textinput_replace_selection() { - let mut textinput = TextInput::new(Lines::Single, "abcdefg".to_owned(), None); + let mut textinput = TextInput::new(Lines::Single, "abcdefg".to_owned(), DummyClipboardContext::new("")); textinput.adjust_horizontal(2, Selection::NotSelected); textinput.adjust_horizontal(2, Selection::Selected); @@ -66,7 +74,7 @@ fn test_textinput_replace_selection() { #[test] fn test_textinput_current_line_length() { - let mut textinput = TextInput::new(Lines::Multiple, "abc\nde\nf".to_owned(), None); + let mut textinput = TextInput::new(Lines::Multiple, "abc\nde\nf".to_owned(), DummyClipboardContext::new("")); assert_eq!(textinput.current_line_length(), 3); textinput.adjust_vertical(1, Selection::NotSelected); @@ -78,7 +86,7 @@ fn test_textinput_current_line_length() { #[test] fn test_textinput_adjust_vertical() { - let mut textinput = TextInput::new(Lines::Multiple, "abc\nde\nf".to_owned(), None); + let mut textinput = TextInput::new(Lines::Multiple, "abc\nde\nf".to_owned(), DummyClipboardContext::new("")); textinput.adjust_horizontal(3, Selection::NotSelected); textinput.adjust_vertical(1, Selection::NotSelected); assert_eq!(textinput.edit_point.line, 1); @@ -95,7 +103,7 @@ fn test_textinput_adjust_vertical() { #[test] fn test_textinput_adjust_horizontal() { - let mut textinput = TextInput::new(Lines::Multiple, "abc\nde\nf".to_owned(), None); + let mut textinput = TextInput::new(Lines::Multiple, "abc\nde\nf".to_owned(), DummyClipboardContext::new("")); textinput.adjust_horizontal(4, Selection::NotSelected); assert_eq!(textinput.edit_point.line, 1); assert_eq!(textinput.edit_point.index, 0); @@ -115,12 +123,12 @@ fn test_textinput_adjust_horizontal() { #[test] fn test_textinput_handle_return() { - let mut single_line_textinput = TextInput::new(Lines::Single, "abcdef".to_owned(), None); + let mut single_line_textinput = TextInput::new(Lines::Single, "abcdef".to_owned(), DummyClipboardContext::new("")); single_line_textinput.adjust_horizontal(3, Selection::NotSelected); single_line_textinput.handle_return(); assert_eq!(single_line_textinput.get_content(), "abcdef"); - let mut multi_line_textinput = TextInput::new(Lines::Multiple, "abcdef".to_owned(), None); + let mut multi_line_textinput = TextInput::new(Lines::Multiple, "abcdef".to_owned(), DummyClipboardContext::new("")); multi_line_textinput.adjust_horizontal(3, Selection::NotSelected); multi_line_textinput.handle_return(); assert_eq!(multi_line_textinput.get_content(), "abc\ndef"); @@ -128,7 +136,7 @@ fn test_textinput_handle_return() { #[test] fn test_textinput_select_all() { - let mut textinput = TextInput::new(Lines::Multiple, "abc\nde\nf".to_owned(), None); + let mut textinput = TextInput::new(Lines::Multiple, "abc\nde\nf".to_owned(), DummyClipboardContext::new("")); assert_eq!(textinput.edit_point.line, 0); assert_eq!(textinput.edit_point.index, 0); @@ -139,16 +147,16 @@ fn test_textinput_select_all() { #[test] fn test_textinput_get_content() { - let single_line_textinput = TextInput::new(Lines::Single, "abcdefg".to_owned(), None); + let single_line_textinput = TextInput::new(Lines::Single, "abcdefg".to_owned(), DummyClipboardContext::new("")); assert_eq!(single_line_textinput.get_content(), "abcdefg"); - let multi_line_textinput = TextInput::new(Lines::Multiple, "abc\nde\nf".to_owned(), None); + let multi_line_textinput = TextInput::new(Lines::Multiple, "abc\nde\nf".to_owned(), DummyClipboardContext::new("")); assert_eq!(multi_line_textinput.get_content(), "abc\nde\nf"); } #[test] fn test_textinput_set_content() { - let mut textinput = TextInput::new(Lines::Multiple, "abc\nde\nf".to_owned(), None); + let mut textinput = TextInput::new(Lines::Multiple, "abc\nde\nf".to_owned(), DummyClipboardContext::new("")); assert_eq!(textinput.get_content(), "abc\nde\nf"); textinput.set_content("abc\nf".to_owned()); @@ -165,3 +173,16 @@ fn test_textinput_set_content() { assert_eq!(textinput.edit_point.index, 2); } +#[test] +fn test_clipboard_paste() { + #[cfg(target_os="macos")] + const MODIFIERS: KeyModifiers = SUPER; + #[cfg(not(target_os="macos"))] + const MODIFIERS: KeyModifiers = CONTROL; + + let mut textinput = TextInput::new(Lines::Single, "defg".to_owned(), DummyClipboardContext::new("abc")); + assert_eq!(textinput.get_content(), "defg"); + assert_eq!(textinput.edit_point.index, 0); + textinput.handle_keydown_aux(Key::V, MODIFIERS); + assert_eq!(textinput.get_content(), "abcdefg"); +} |