Auto merge of #5547 - aweinstock314:x11-clipboard, r=jdm

Manual re-opening of #5479 (since it seems that GitHub disables re-opening with the same number after a rebase).

<!-- Reviewable:start -->
[<img src="https://reviewable.io/review_button.png" height=40 alt="Review on Reviewable"/>](https://reviewable.io/reviews/servo/servo/5547)
<!-- Reviewable:end -->
This commit is contained in:
bors-servo 2015-04-21 14:41:32 -05:00
commit 9974ebb2f9
12 changed files with 104 additions and 23 deletions

View file

@ -29,6 +29,7 @@ use dom::htmlformelement::{SubmittedFrom, ResetFrom};
use dom::node::{DisabledStateHelpers, Node, NodeHelpers, NodeDamage, NodeTypeId};
use dom::node::{document_from_node, window_from_node};
use dom::virtualmethods::VirtualMethods;
use dom::window::WindowHelpers;
use textinput::TextInput;
use textinput::KeyReaction::{TriggerDefaultAction, DispatchInput, Nothing};
use textinput::Lines::Single;
@ -109,6 +110,7 @@ static DEFAULT_INPUT_SIZE: u32 = 20;
impl HTMLInputElement {
fn new_inherited(localName: DOMString, prefix: Option<DOMString>, document: JSRef<Document>) -> HTMLInputElement {
let chan = document.window().root().r().constellation_chan();
HTMLInputElement {
htmlelement: HTMLElement::new_inherited(HTMLElementTypeId::HTMLInputElement, localName, prefix, document),
input_type: Cell::new(InputType::InputText),
@ -118,7 +120,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())),
textinput: DOMRefCell::new(TextInput::new(Single, "".to_owned(), Some(chan))),
activation_state: DOMRefCell::new(InputActivationState::new())
}
}

View file

@ -27,6 +27,7 @@ use dom::node::{DisabledStateHelpers, Node, NodeHelpers, NodeDamage, NodeTypeId}
use dom::node::{document_from_node, window_from_node};
use textinput::{TextInput, Lines, KeyReaction};
use dom::virtualmethods::VirtualMethods;
use dom::window::WindowHelpers;
use script_task::{ScriptMsg, Runnable};
use util::str::DOMString;
@ -90,9 +91,10 @@ static DEFAULT_ROWS: u32 = 2;
impl HTMLTextAreaElement {
fn new_inherited(localName: DOMString, prefix: Option<DOMString>, document: JSRef<Document>) -> 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())),
textinput: DOMRefCell::new(TextInput::new(Lines::Multiple, "".to_owned(), Some(chan))),
cols: Cell::new(DEFAULT_COLS),
rows: Cell::new(DEFAULT_ROWS),
value_changed: Cell::new(false),

View file

@ -6,6 +6,8 @@
use dom::bindings::codegen::Bindings::KeyboardEventBinding::KeyboardEventMethods;
use dom::bindings::js::JSRef;
use msg::constellation_msg::ConstellationChan;
use msg::constellation_msg::Msg as ConstellationMsg;
use dom::keyboardevent::KeyboardEvent;
use util::str::DOMString;
@ -13,6 +15,7 @@ use std::borrow::ToOwned;
use std::cmp::{min, max};
use std::default::Default;
use std::num::SignedInt;
use std::sync::mpsc::channel;
#[derive(Copy, PartialEq)]
pub enum Selection {
@ -40,6 +43,7 @@ pub struct TextInput {
selection_begin: Option<TextPoint>,
/// Is this a multiline input?
multiline: bool,
constellation_channel: Option<ConstellationChan>
}
/// Resulting action to be taken by the owner of a text input that is handling an event.
@ -87,12 +91,13 @@ fn is_control_key(event: JSRef<KeyboardEvent>) -> bool {
impl TextInput {
/// Instantiate a new text input control
pub fn new(lines: Lines, initial: DOMString) -> TextInput {
pub fn new(lines: Lines, initial: DOMString, cc: Option<ConstellationChan>) -> TextInput {
let mut i = TextInput {
lines: vec!(),
edit_point: Default::default(),
selection_begin: None,
multiline: lines == Lines::Multiple,
constellation_channel: cc,
};
i.set_content(initial);
i
@ -118,6 +123,15 @@ impl TextInput {
self.replace_selection(ch.to_string());
}
/// Insert a string at the current editing point
fn insert_string(&mut self, s: &str) {
// it looks like this could be made performant by avoiding some redundant
// selection-related checks, but use the simple implementation for now
for ch in s.chars() {
self.insert_char(ch);
}
}
pub fn get_sorted_selection(&self) -> (TextPoint, TextPoint) {
let begin = self.selection_begin.unwrap();
let end = self.edit_point;
@ -282,10 +296,22 @@ impl TextInput {
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.as_slice());
}
KeyReaction::DispatchInput
},
// printable characters have single-character key values
c if c.len() == 1 => {
self.insert_char(c.char_at(0));
return KeyReaction::DispatchInput;
KeyReaction::DispatchInput
}
"Space" => {
self.insert_char(' ');