mirror of
https://github.com/servo/servo.git
synced 2025-07-22 23:03:42 +01:00
Made the clipboard-related functionality in TextInput more testable. Added test_clipboard_paste to the "test-unit" suite.
This commit is contained in:
parent
387836c42e
commit
b742eeca05
11 changed files with 532 additions and 436 deletions
|
@ -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,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<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)
|
||||
}
|
||||
|
||||
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,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<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_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,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue