From b742eeca050856b3055668c9021bacfb19b3de4a Mon Sep 17 00:00:00 2001 From: Avi Weinstock Date: Wed, 22 Apr 2015 13:25:05 -0400 Subject: [PATCH 1/4] Made the clipboard-related functionality in TextInput more testable. Added test_clipboard_paste to the "test-unit" suite. --- components/script/clipboard_provider.rs | 48 ++ components/script/dom/document.rs | 8 +- components/script/dom/htmlinputelement.rs | 5 +- components/script/dom/htmltextareaelement.rs | 5 +- components/script/dom/keyboardevent.rs | 790 ++++++++++--------- components/script/lib.rs | 1 + components/script/textinput.rs | 70 +- components/servo/Cargo.lock | 1 + tests/unit/script/Cargo.toml | 3 + tests/unit/script/lib.rs | 1 + tests/unit/script/textinput.rs | 36 +- 11 files changed, 532 insertions(+), 436 deletions(-) create mode 100644 components/script/clipboard_provider.rs 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 17768a76c8b..58f34e791b7 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, value_changed: Cell, size: Cell, - textinput: DOMRefCell, + textinput: DOMRefCell>, activation_state: DOMRefCell, } @@ -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 5e6724d5c63..bbd19b2d65c 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: DOMRefCell>, cols: Cell, rows: Cell, // 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..2ff4018801e 100644 --- a/components/script/dom/keyboardevent.rs +++ b/components/script/dom/keyboardevent.rs @@ -14,15 +14,19 @@ use dom::event::{Event, EventTypeId}; use dom::uievent::UIEvent; use dom::window::Window; use msg::constellation_msg; +use msg::constellation_msg::{Key, KeyModifiers}; 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, + key: Cell>, + key_string: RefCell, code: RefCell, location: Cell, ctrl: Cell, @@ -45,7 +49,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 +76,8 @@ impl KeyboardEvent { cancelable: bool, view: Option>, _detail: i32, - key: DOMString, + key: Option, + key_string: DOMString, code: DOMString, location: u32, repeat: bool, @@ -83,10 +89,11 @@ impl KeyboardEvent { char_code: Option, key_code: u32) -> Temporary { 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 +112,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, None, 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 +120,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 +132,350 @@ impl KeyboardEvent { } } +pub trait KeyboardEventHelpers { + fn get_key(&self) -> Option; + fn get_key_modifiers(&self) -> KeyModifiers; +} + +impl<'a> KeyboardEventHelpers for JSRef<'a, KeyboardEvent> { + fn get_key(&self) -> Option { + 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", } } // 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", + 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", - constellation_msg::Key::World1 | - constellation_msg::Key::World2 => panic!("unknown char code for {:?}", key), + Key::World1 | + 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::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 +483,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 { - 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 { + 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 +573,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, @@ -568,15 +604,15 @@ impl<'a> KeyboardEventMethods for JSRef<'a, KeyboardEvent> { let uievent: JSRef = 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..b676ab2f13e 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 { /// Current text input content, split across lines without trailing '\n' lines: Vec, /// Current cursor input point @@ -42,7 +42,7 @@ pub struct TextInput { selection_begin: Option, /// Is this a multiline input? multiline: bool, - constellation_channel: Option + clipboard_provider: T, } /// Resulting action to be taken by the owner of a text input that is handling an event. @@ -79,24 +79,24 @@ 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) -> 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) -> bool { - event.CtrlKey() && !event.MetaKey() && !event.AltKey() +fn is_control_key(mods: KeyModifiers) -> bool { + mods.contains(CONTROL) && !mods.contains(SUPER | ALT) } -impl TextInput { +impl TextInput { /// Instantiate a new text input control - pub fn new(lines: Lines, initial: DOMString, cc: Option) -> TextInput { + pub fn new(lines: Lines, initial: DOMString, clipboard_provider: T) -> TextInput { 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,28 +283,22 @@ impl TextInput { /// Process a given `KeyboardEvent` and return an action for the caller to execute. pub fn handle_keydown(&mut self, event: JSRef) -> KeyReaction { - //A simple way to convert an event to a selection - fn maybe_select(event: JSRef) -> 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_value(key, mods) { + "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); - } + "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 @@ -325,19 +319,19 @@ impl TextInput { KeyReaction::DispatchInput } "ArrowLeft" => { - self.adjust_horizontal(-1, maybe_select(event)); + self.adjust_horizontal(-1, maybe_select); KeyReaction::Nothing } "ArrowRight" => { - self.adjust_horizontal(1, maybe_select(event)); + self.adjust_horizontal(1, maybe_select); KeyReaction::Nothing } "ArrowUp" => { - self.adjust_vertical(-1, maybe_select(event)); + self.adjust_vertical(-1, maybe_select); KeyReaction::Nothing } "ArrowDown" => { - self.adjust_vertical(1, maybe_select(event)); + self.adjust_vertical(1, maybe_select); KeyReaction::Nothing } "Enter" => self.handle_return(), @@ -350,11 +344,11 @@ impl TextInput { KeyReaction::Nothing } "PageUp" => { - self.adjust_vertical(-28, maybe_select(event)); + self.adjust_vertical(-28, maybe_select); KeyReaction::Nothing } "PageDown" => { - self.adjust_vertical(28, maybe_select(event)); + self.adjust_vertical(28, maybe_select); KeyReaction::Nothing } "Tab" => KeyReaction::TriggerDefaultAction, diff --git a/components/servo/Cargo.lock b/components/servo/Cargo.lock index 060328b59da..437e3bba76c 100644 --- a/components/servo/Cargo.lock +++ b/components/servo/Cargo.lock @@ -1035,6 +1035,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..c5ede5262d1 100644 --- a/tests/unit/script/textinput.rs +++ b/tests/unit/script/textinput.rs @@ -7,12 +7,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use msg::constellation_msg::{Key, 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 +29,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 +41,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 +58,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 +68,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 +80,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 +97,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 +117,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 +130,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 +141,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 +167,11 @@ fn test_textinput_set_content() { assert_eq!(textinput.edit_point.index, 2); } +#[test] +fn test_clipboard_paste() { + 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, CONTROL); + assert_eq!(textinput.get_content(), "abcdefg"); +} From 29f83060897119dfc7fa07ff235263c56df25088 Mon Sep 17 00:00:00 2001 From: Avi Weinstock Date: Sun, 3 May 2015 12:42:01 -0400 Subject: [PATCH 2/4] Heuristically create a Key value in KeyboardEvent::Constructor based on the string provided. --- components/script/dom/keyboardevent.rs | 181 ++++++++++++++++++++++++- 1 file changed, 180 insertions(+), 1 deletion(-) diff --git a/components/script/dom/keyboardevent.rs b/components/script/dom/keyboardevent.rs index 2ff4018801e..557f66d6d12 100644 --- a/components/script/dom/keyboardevent.rs +++ b/components/script/dom/keyboardevent.rs @@ -15,6 +15,7 @@ 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; @@ -108,11 +109,16 @@ impl KeyboardEvent { pub fn Constructor(global: GlobalRef, type_: DOMString, init: &KeyboardEventBinding::KeyboardEventInit) -> Fallible> { + let key = if let Some((key, _)) = key_from_string(init.key.as_slice()) { + Some(key) + } else { + None + }; let event = KeyboardEvent::new(global.as_window(), type_, init.parent.parent.parent.bubbles, init.parent.parent.parent.cancelable, init.parent.parent.view.r(), - init.parent.parent.detail, None, + init.parent.parent.detail, key, init.key.clone(), init.code.clone(), init.location, init.repeat, init.isComposing, init.parent.ctrlKey, init.parent.altKey, init.parent.shiftKey, init.parent.metaKey, @@ -335,6 +341,179 @@ pub fn key_value(key: Key, mods: KeyModifiers) -> &'static str { } } +pub fn key_from_string(key_string: &str) -> Option<(Key, KeyModifiers)> { + match key_string { + " " => Some((Key::Space, KeyModifiers::empty())), + "\"" => Some((Key::Apostrophe, SHIFT)), + "'" => Some((Key::Apostrophe, KeyModifiers::empty())), + "<" => Some((Key::Comma, SHIFT)), + "," => Some((Key::Comma, KeyModifiers::empty())), + "_" => Some((Key::Minus, SHIFT)), + "-" => Some((Key::Minus, KeyModifiers::empty())), + ">" => Some((Key::Period, SHIFT)), + "." => Some((Key::Period, KeyModifiers::empty())), + "?" => Some((Key::Slash, SHIFT)), + "/" => Some((Key::Slash, KeyModifiers::empty())), + "~" => Some((Key::GraveAccent, SHIFT)), + "`" => Some((Key::GraveAccent, KeyModifiers::empty())), + ")" => Some((Key::Num0, SHIFT)), + "0" => Some((Key::Num0, KeyModifiers::empty())), + "!" => Some((Key::Num1, SHIFT)), + "1" => Some((Key::Num1, KeyModifiers::empty())), + "@" => Some((Key::Num2, SHIFT)), + "2" => Some((Key::Num2, KeyModifiers::empty())), + "#" => Some((Key::Num3, SHIFT)), + "3" => Some((Key::Num3, KeyModifiers::empty())), + "$" => Some((Key::Num4, SHIFT)), + "4" => Some((Key::Num4, KeyModifiers::empty())), + "%" => Some((Key::Num5, SHIFT)), + "5" => Some((Key::Num5, KeyModifiers::empty())), + "^" => Some((Key::Num6, SHIFT)), + "6" => Some((Key::Num6, KeyModifiers::empty())), + "&" => Some((Key::Num7, SHIFT)), + "7" => Some((Key::Num7, KeyModifiers::empty())), + "*" => Some((Key::Num8, SHIFT)), + "8" => Some((Key::Num8, KeyModifiers::empty())), + "(" => Some((Key::Num9, SHIFT)), + "9" => Some((Key::Num9, KeyModifiers::empty())), + ":" => Some((Key::Semicolon, SHIFT)), + ";" => Some((Key::Semicolon, KeyModifiers::empty())), + "+" => Some((Key::Equal, SHIFT)), + "=" => Some((Key::Equal, KeyModifiers::empty())), + "A" => Some((Key::A, SHIFT)), + "a" => Some((Key::A, KeyModifiers::empty())), + "B" => Some((Key::B, SHIFT)), + "b" => Some((Key::B, KeyModifiers::empty())), + "C" => Some((Key::C, SHIFT)), + "c" => Some((Key::C, KeyModifiers::empty())), + "D" => Some((Key::D, SHIFT)), + "d" => Some((Key::D, KeyModifiers::empty())), + "E" => Some((Key::E, SHIFT)), + "e" => Some((Key::E, KeyModifiers::empty())), + "F" => Some((Key::F, SHIFT)), + "f" => Some((Key::F, KeyModifiers::empty())), + "G" => Some((Key::G, SHIFT)), + "g" => Some((Key::G, KeyModifiers::empty())), + "H" => Some((Key::H, SHIFT)), + "h" => Some((Key::H, KeyModifiers::empty())), + "I" => Some((Key::I, SHIFT)), + "i" => Some((Key::I, KeyModifiers::empty())), + "J" => Some((Key::J, SHIFT)), + "j" => Some((Key::J, KeyModifiers::empty())), + "K" => Some((Key::K, SHIFT)), + "k" => Some((Key::K, KeyModifiers::empty())), + "L" => Some((Key::L, SHIFT)), + "l" => Some((Key::L, KeyModifiers::empty())), + "M" => Some((Key::M, SHIFT)), + "m" => Some((Key::M, KeyModifiers::empty())), + "N" => Some((Key::N, SHIFT)), + "n" => Some((Key::N, KeyModifiers::empty())), + "O" => Some((Key::O, SHIFT)), + "o" => Some((Key::O, KeyModifiers::empty())), + "P" => Some((Key::P, SHIFT)), + "p" => Some((Key::P, KeyModifiers::empty())), + "Q" => Some((Key::Q, SHIFT)), + "q" => Some((Key::Q, KeyModifiers::empty())), + "R" => Some((Key::R, SHIFT)), + "r" => Some((Key::R, KeyModifiers::empty())), + "S" => Some((Key::S, SHIFT)), + "s" => Some((Key::S, KeyModifiers::empty())), + "T" => Some((Key::T, SHIFT)), + "t" => Some((Key::T, KeyModifiers::empty())), + "U" => Some((Key::U, SHIFT)), + "u" => Some((Key::U, KeyModifiers::empty())), + "V" => Some((Key::V, SHIFT)), + "v" => Some((Key::V, KeyModifiers::empty())), + "W" => Some((Key::W, SHIFT)), + "w" => Some((Key::W, KeyModifiers::empty())), + "X" => Some((Key::X, SHIFT)), + "x" => Some((Key::X, KeyModifiers::empty())), + "Y" => Some((Key::Y, SHIFT)), + "y" => Some((Key::Y, KeyModifiers::empty())), + "Z" => Some((Key::Z, SHIFT)), + "z" => Some((Key::Z, KeyModifiers::empty())), + "{" => Some((Key::LeftBracket, SHIFT)), + "[" => Some((Key::LeftBracket, KeyModifiers::empty())), + "|" => Some((Key::Backslash, SHIFT)), + "\\" => Some((Key::Backslash, KeyModifiers::empty())), + "}" => Some((Key::RightBracket, SHIFT)), + "]" => Some((Key::RightBracket, KeyModifiers::empty())), + "Unidentified" => Some((Key::World1, KeyModifiers::empty())), + /*"Unidentified" => Some((Key::World2, KeyModifiers::empty())),*/ + "Escape" => Some((Key::Escape, KeyModifiers::empty())), + "Enter" => Some((Key::Enter, KeyModifiers::empty())), + "Tab" => Some((Key::Tab, KeyModifiers::empty())), + "Backspace" => Some((Key::Backspace, KeyModifiers::empty())), + "Insert" => Some((Key::Insert, KeyModifiers::empty())), + "Delete" => Some((Key::Delete, KeyModifiers::empty())), + "ArrowRight" => Some((Key::Right, KeyModifiers::empty())), + "ArrowLeft" => Some((Key::Left, KeyModifiers::empty())), + "ArrowDown" => Some((Key::Down, KeyModifiers::empty())), + "ArrowUp" => Some((Key::Up, KeyModifiers::empty())), + "PageUp" => Some((Key::PageUp, KeyModifiers::empty())), + "PageDown" => Some((Key::PageDown, KeyModifiers::empty())), + "Home" => Some((Key::Home, KeyModifiers::empty())), + "End" => Some((Key::End, KeyModifiers::empty())), + "CapsLock" => Some((Key::CapsLock, KeyModifiers::empty())), + "ScrollLock" => Some((Key::ScrollLock, KeyModifiers::empty())), + "NumLock" => Some((Key::NumLock, KeyModifiers::empty())), + "PrintScreen" => Some((Key::PrintScreen, KeyModifiers::empty())), + "Pause" => Some((Key::Pause, KeyModifiers::empty())), + "F1" => Some((Key::F1, KeyModifiers::empty())), + "F2" => Some((Key::F2, KeyModifiers::empty())), + "F3" => Some((Key::F3, KeyModifiers::empty())), + "F4" => Some((Key::F4, KeyModifiers::empty())), + "F5" => Some((Key::F5, KeyModifiers::empty())), + "F6" => Some((Key::F6, KeyModifiers::empty())), + "F7" => Some((Key::F7, KeyModifiers::empty())), + "F8" => Some((Key::F8, KeyModifiers::empty())), + "F9" => Some((Key::F9, KeyModifiers::empty())), + "F10" => Some((Key::F10, KeyModifiers::empty())), + "F11" => Some((Key::F11, KeyModifiers::empty())), + "F12" => Some((Key::F12, KeyModifiers::empty())), + "F13" => Some((Key::F13, KeyModifiers::empty())), + "F14" => Some((Key::F14, KeyModifiers::empty())), + "F15" => Some((Key::F15, KeyModifiers::empty())), + "F16" => Some((Key::F16, KeyModifiers::empty())), + "F17" => Some((Key::F17, KeyModifiers::empty())), + "F18" => Some((Key::F18, KeyModifiers::empty())), + "F19" => Some((Key::F19, KeyModifiers::empty())), + "F20" => Some((Key::F20, KeyModifiers::empty())), + "F21" => Some((Key::F21, KeyModifiers::empty())), + "F22" => Some((Key::F22, KeyModifiers::empty())), + "F23" => Some((Key::F23, KeyModifiers::empty())), + "F24" => Some((Key::F24, KeyModifiers::empty())), + "F25" => Some((Key::F25, KeyModifiers::empty())), + /*"0" => Some((Key::Kp0, KeyModifiers::empty())), + "1" => Some((Key::Kp1, KeyModifiers::empty())), + "2" => Some((Key::Kp2, KeyModifiers::empty())), + "3" => Some((Key::Kp3, KeyModifiers::empty())), + "4" => Some((Key::Kp4, KeyModifiers::empty())), + "5" => Some((Key::Kp5, KeyModifiers::empty())), + "6" => Some((Key::Kp6, KeyModifiers::empty())), + "7" => Some((Key::Kp7, KeyModifiers::empty())), + "8" => Some((Key::Kp8, KeyModifiers::empty())), + "9" => Some((Key::Kp9, KeyModifiers::empty())), + "." => Some((Key::KpDecimal, KeyModifiers::empty())), + "/" => Some((Key::KpDivide, KeyModifiers::empty())), + "*" => Some((Key::KpMultiply, KeyModifiers::empty())), + "-" => Some((Key::KpSubtract, KeyModifiers::empty())), + "+" => Some((Key::KpAdd, KeyModifiers::empty())), + "Enter" => Some((Key::KpEnter, KeyModifiers::empty())), + "=" => Some((Key::KpEqual, KeyModifiers::empty())),*/ + "Shift" => Some((Key::LeftShift, SHIFT)), + "Control" => Some((Key::LeftControl, CONTROL)), + "Alt" => Some((Key::LeftAlt, ALT)), + "Super" => Some((Key::LeftSuper, SUPER)), + /*"Shift" => Some((Key::RightShift, SHIFT)), + "Control" => Some((Key::RightControl, CONTROL)), + "Alt" => Some((Key::RightAlt, ALT)), + "Super" => Some((Key::RightSuper, SUPER)),*/ + "ContextMenu" => Some((Key::Menu, KeyModifiers::empty())), + _ => None + } +} + // https://dvcs.w3.org/hg/dom3events/raw-file/tip/html/DOM3Events-code.html fn code_value(key: Key) -> &'static str { match key { From 05877179447cfd4b33e7b8e17b7e8e5082d89cd8 Mon Sep 17 00:00:00 2001 From: Avi Weinstock Date: Sun, 3 May 2015 13:07:45 -0400 Subject: [PATCH 3/4] Change the dispatch in TextInput::handle_keydown_aux match on enum values instead of strings. --- components/script/dom/keyboardevent.rs | 341 ++++++++++++------------- components/script/textinput.rs | 55 ++-- 2 files changed, 203 insertions(+), 193 deletions(-) diff --git a/components/script/dom/keyboardevent.rs b/components/script/dom/keyboardevent.rs index 557f66d6d12..d0ac71c814c 100644 --- a/components/script/dom/keyboardevent.rs +++ b/components/script/dom/keyboardevent.rs @@ -109,16 +109,11 @@ impl KeyboardEvent { pub fn Constructor(global: GlobalRef, type_: DOMString, init: &KeyboardEventBinding::KeyboardEventInit) -> Fallible> { - let key = if let Some((key, _)) = key_from_string(init.key.as_slice()) { - Some(key) - } else { - None - }; let event = KeyboardEvent::new(global.as_window(), type_, init.parent.parent.parent.bubbles, init.parent.parent.parent.cancelable, init.parent.parent.view.r(), - init.parent.parent.detail, key, + 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, @@ -341,175 +336,173 @@ pub fn key_value(key: Key, mods: KeyModifiers) -> &'static str { } } -pub fn key_from_string(key_string: &str) -> Option<(Key, KeyModifiers)> { +fn key_from_string(key_string: &str, location: u32) -> Option { match key_string { - " " => Some((Key::Space, KeyModifiers::empty())), - "\"" => Some((Key::Apostrophe, SHIFT)), - "'" => Some((Key::Apostrophe, KeyModifiers::empty())), - "<" => Some((Key::Comma, SHIFT)), - "," => Some((Key::Comma, KeyModifiers::empty())), - "_" => Some((Key::Minus, SHIFT)), - "-" => Some((Key::Minus, KeyModifiers::empty())), - ">" => Some((Key::Period, SHIFT)), - "." => Some((Key::Period, KeyModifiers::empty())), - "?" => Some((Key::Slash, SHIFT)), - "/" => Some((Key::Slash, KeyModifiers::empty())), - "~" => Some((Key::GraveAccent, SHIFT)), - "`" => Some((Key::GraveAccent, KeyModifiers::empty())), - ")" => Some((Key::Num0, SHIFT)), - "0" => Some((Key::Num0, KeyModifiers::empty())), - "!" => Some((Key::Num1, SHIFT)), - "1" => Some((Key::Num1, KeyModifiers::empty())), - "@" => Some((Key::Num2, SHIFT)), - "2" => Some((Key::Num2, KeyModifiers::empty())), - "#" => Some((Key::Num3, SHIFT)), - "3" => Some((Key::Num3, KeyModifiers::empty())), - "$" => Some((Key::Num4, SHIFT)), - "4" => Some((Key::Num4, KeyModifiers::empty())), - "%" => Some((Key::Num5, SHIFT)), - "5" => Some((Key::Num5, KeyModifiers::empty())), - "^" => Some((Key::Num6, SHIFT)), - "6" => Some((Key::Num6, KeyModifiers::empty())), - "&" => Some((Key::Num7, SHIFT)), - "7" => Some((Key::Num7, KeyModifiers::empty())), - "*" => Some((Key::Num8, SHIFT)), - "8" => Some((Key::Num8, KeyModifiers::empty())), - "(" => Some((Key::Num9, SHIFT)), - "9" => Some((Key::Num9, KeyModifiers::empty())), - ":" => Some((Key::Semicolon, SHIFT)), - ";" => Some((Key::Semicolon, KeyModifiers::empty())), - "+" => Some((Key::Equal, SHIFT)), - "=" => Some((Key::Equal, KeyModifiers::empty())), - "A" => Some((Key::A, SHIFT)), - "a" => Some((Key::A, KeyModifiers::empty())), - "B" => Some((Key::B, SHIFT)), - "b" => Some((Key::B, KeyModifiers::empty())), - "C" => Some((Key::C, SHIFT)), - "c" => Some((Key::C, KeyModifiers::empty())), - "D" => Some((Key::D, SHIFT)), - "d" => Some((Key::D, KeyModifiers::empty())), - "E" => Some((Key::E, SHIFT)), - "e" => Some((Key::E, KeyModifiers::empty())), - "F" => Some((Key::F, SHIFT)), - "f" => Some((Key::F, KeyModifiers::empty())), - "G" => Some((Key::G, SHIFT)), - "g" => Some((Key::G, KeyModifiers::empty())), - "H" => Some((Key::H, SHIFT)), - "h" => Some((Key::H, KeyModifiers::empty())), - "I" => Some((Key::I, SHIFT)), - "i" => Some((Key::I, KeyModifiers::empty())), - "J" => Some((Key::J, SHIFT)), - "j" => Some((Key::J, KeyModifiers::empty())), - "K" => Some((Key::K, SHIFT)), - "k" => Some((Key::K, KeyModifiers::empty())), - "L" => Some((Key::L, SHIFT)), - "l" => Some((Key::L, KeyModifiers::empty())), - "M" => Some((Key::M, SHIFT)), - "m" => Some((Key::M, KeyModifiers::empty())), - "N" => Some((Key::N, SHIFT)), - "n" => Some((Key::N, KeyModifiers::empty())), - "O" => Some((Key::O, SHIFT)), - "o" => Some((Key::O, KeyModifiers::empty())), - "P" => Some((Key::P, SHIFT)), - "p" => Some((Key::P, KeyModifiers::empty())), - "Q" => Some((Key::Q, SHIFT)), - "q" => Some((Key::Q, KeyModifiers::empty())), - "R" => Some((Key::R, SHIFT)), - "r" => Some((Key::R, KeyModifiers::empty())), - "S" => Some((Key::S, SHIFT)), - "s" => Some((Key::S, KeyModifiers::empty())), - "T" => Some((Key::T, SHIFT)), - "t" => Some((Key::T, KeyModifiers::empty())), - "U" => Some((Key::U, SHIFT)), - "u" => Some((Key::U, KeyModifiers::empty())), - "V" => Some((Key::V, SHIFT)), - "v" => Some((Key::V, KeyModifiers::empty())), - "W" => Some((Key::W, SHIFT)), - "w" => Some((Key::W, KeyModifiers::empty())), - "X" => Some((Key::X, SHIFT)), - "x" => Some((Key::X, KeyModifiers::empty())), - "Y" => Some((Key::Y, SHIFT)), - "y" => Some((Key::Y, KeyModifiers::empty())), - "Z" => Some((Key::Z, SHIFT)), - "z" => Some((Key::Z, KeyModifiers::empty())), - "{" => Some((Key::LeftBracket, SHIFT)), - "[" => Some((Key::LeftBracket, KeyModifiers::empty())), - "|" => Some((Key::Backslash, SHIFT)), - "\\" => Some((Key::Backslash, KeyModifiers::empty())), - "}" => Some((Key::RightBracket, SHIFT)), - "]" => Some((Key::RightBracket, KeyModifiers::empty())), - "Unidentified" => Some((Key::World1, KeyModifiers::empty())), - /*"Unidentified" => Some((Key::World2, KeyModifiers::empty())),*/ - "Escape" => Some((Key::Escape, KeyModifiers::empty())), - "Enter" => Some((Key::Enter, KeyModifiers::empty())), - "Tab" => Some((Key::Tab, KeyModifiers::empty())), - "Backspace" => Some((Key::Backspace, KeyModifiers::empty())), - "Insert" => Some((Key::Insert, KeyModifiers::empty())), - "Delete" => Some((Key::Delete, KeyModifiers::empty())), - "ArrowRight" => Some((Key::Right, KeyModifiers::empty())), - "ArrowLeft" => Some((Key::Left, KeyModifiers::empty())), - "ArrowDown" => Some((Key::Down, KeyModifiers::empty())), - "ArrowUp" => Some((Key::Up, KeyModifiers::empty())), - "PageUp" => Some((Key::PageUp, KeyModifiers::empty())), - "PageDown" => Some((Key::PageDown, KeyModifiers::empty())), - "Home" => Some((Key::Home, KeyModifiers::empty())), - "End" => Some((Key::End, KeyModifiers::empty())), - "CapsLock" => Some((Key::CapsLock, KeyModifiers::empty())), - "ScrollLock" => Some((Key::ScrollLock, KeyModifiers::empty())), - "NumLock" => Some((Key::NumLock, KeyModifiers::empty())), - "PrintScreen" => Some((Key::PrintScreen, KeyModifiers::empty())), - "Pause" => Some((Key::Pause, KeyModifiers::empty())), - "F1" => Some((Key::F1, KeyModifiers::empty())), - "F2" => Some((Key::F2, KeyModifiers::empty())), - "F3" => Some((Key::F3, KeyModifiers::empty())), - "F4" => Some((Key::F4, KeyModifiers::empty())), - "F5" => Some((Key::F5, KeyModifiers::empty())), - "F6" => Some((Key::F6, KeyModifiers::empty())), - "F7" => Some((Key::F7, KeyModifiers::empty())), - "F8" => Some((Key::F8, KeyModifiers::empty())), - "F9" => Some((Key::F9, KeyModifiers::empty())), - "F10" => Some((Key::F10, KeyModifiers::empty())), - "F11" => Some((Key::F11, KeyModifiers::empty())), - "F12" => Some((Key::F12, KeyModifiers::empty())), - "F13" => Some((Key::F13, KeyModifiers::empty())), - "F14" => Some((Key::F14, KeyModifiers::empty())), - "F15" => Some((Key::F15, KeyModifiers::empty())), - "F16" => Some((Key::F16, KeyModifiers::empty())), - "F17" => Some((Key::F17, KeyModifiers::empty())), - "F18" => Some((Key::F18, KeyModifiers::empty())), - "F19" => Some((Key::F19, KeyModifiers::empty())), - "F20" => Some((Key::F20, KeyModifiers::empty())), - "F21" => Some((Key::F21, KeyModifiers::empty())), - "F22" => Some((Key::F22, KeyModifiers::empty())), - "F23" => Some((Key::F23, KeyModifiers::empty())), - "F24" => Some((Key::F24, KeyModifiers::empty())), - "F25" => Some((Key::F25, KeyModifiers::empty())), - /*"0" => Some((Key::Kp0, KeyModifiers::empty())), - "1" => Some((Key::Kp1, KeyModifiers::empty())), - "2" => Some((Key::Kp2, KeyModifiers::empty())), - "3" => Some((Key::Kp3, KeyModifiers::empty())), - "4" => Some((Key::Kp4, KeyModifiers::empty())), - "5" => Some((Key::Kp5, KeyModifiers::empty())), - "6" => Some((Key::Kp6, KeyModifiers::empty())), - "7" => Some((Key::Kp7, KeyModifiers::empty())), - "8" => Some((Key::Kp8, KeyModifiers::empty())), - "9" => Some((Key::Kp9, KeyModifiers::empty())), - "." => Some((Key::KpDecimal, KeyModifiers::empty())), - "/" => Some((Key::KpDivide, KeyModifiers::empty())), - "*" => Some((Key::KpMultiply, KeyModifiers::empty())), - "-" => Some((Key::KpSubtract, KeyModifiers::empty())), - "+" => Some((Key::KpAdd, KeyModifiers::empty())), - "Enter" => Some((Key::KpEnter, KeyModifiers::empty())), - "=" => Some((Key::KpEqual, KeyModifiers::empty())),*/ - "Shift" => Some((Key::LeftShift, SHIFT)), - "Control" => Some((Key::LeftControl, CONTROL)), - "Alt" => Some((Key::LeftAlt, ALT)), - "Super" => Some((Key::LeftSuper, SUPER)), - /*"Shift" => Some((Key::RightShift, SHIFT)), - "Control" => Some((Key::RightControl, CONTROL)), - "Alt" => Some((Key::RightAlt, ALT)), - "Super" => Some((Key::RightSuper, SUPER)),*/ - "ContextMenu" => Some((Key::Menu, KeyModifiers::empty())), + " " => 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 } } diff --git a/components/script/textinput.rs b/components/script/textinput.rs index b676ab2f13e..abe74f2f330 100644 --- a/components/script/textinput.rs +++ b/components/script/textinput.rs @@ -88,6 +88,24 @@ 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 { /// Instantiate a new text input control pub fn new(lines: Lines, initial: DOMString, clipboard_provider: T) -> TextInput { @@ -291,67 +309,66 @@ impl TextInput { } 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_value(key, mods) { - "a" if is_control_key(mods) => { + match key { + Key::A if is_control_key(mods) => { self.select_all(); KeyReaction::Nothing }, - "v" if is_control_key(mods) => { + 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" => { + Key::Left => { self.adjust_horizontal(-1, maybe_select); KeyReaction::Nothing } - "ArrowRight" => { + Key::Right => { self.adjust_horizontal(1, maybe_select); KeyReaction::Nothing } - "ArrowUp" => { + Key::Up => { self.adjust_vertical(-1, maybe_select); KeyReaction::Nothing } - "ArrowDown" => { + 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" => { + Key::PageUp => { self.adjust_vertical(-28, maybe_select); KeyReaction::Nothing } - "PageDown" => { + Key::PageDown => { self.adjust_vertical(28, maybe_select); KeyReaction::Nothing } - "Tab" => KeyReaction::TriggerDefaultAction, + Key::Tab => KeyReaction::TriggerDefaultAction, _ => KeyReaction::Nothing, } } From d054946f7d3bf9834a91cdf4ffa9de6f10099ccf Mon Sep 17 00:00:00 2001 From: Avi Weinstock Date: Wed, 6 May 2015 15:30:29 -0400 Subject: [PATCH 4/4] Fix test_clipboard_paste to pass on Mac OS. --- tests/unit/script/textinput.rs | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/tests/unit/script/textinput.rs b/tests/unit/script/textinput.rs index c5ede5262d1..653507983a2 100644 --- a/tests/unit/script/textinput.rs +++ b/tests/unit/script/textinput.rs @@ -7,7 +7,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use msg::constellation_msg::{Key, CONTROL}; +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; @@ -169,9 +175,14 @@ fn test_textinput_set_content() { #[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, CONTROL); + textinput.handle_keydown_aux(Key::V, MODIFIERS); assert_eq!(textinput.get_content(), "abcdefg"); }