mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-21 09:15:35 +00:00
servo: Merge #6654 - Add copy-to-clipboard feature under x11 (from aweinstock314:add-x11-copy-to-clipboard); r=jdm
The main work is in the the rust-clipboard library, this PR updates Cargo.lock and adds plumbing.
0337e48b3f
Source-Repo: https://github.com/servo/servo
Source-Revision: 28e163d6c44f1d85fbaea7f236da40972b6a63b1
This commit is contained in:
parent
f6493dee57
commit
6a5f0dd49d
@ -475,6 +475,13 @@ impl<LTF: LayoutTaskFactory, STF: ScriptTaskFactory> Constellation<LTF, STF> {
|
||||
);
|
||||
sender.send(result).unwrap();
|
||||
}
|
||||
ConstellationMsg::SetClipboardContents(s) => {
|
||||
if let Some(ref mut ctx) = self.clipboard_ctx {
|
||||
if let Err(e) = ctx.set_contents(s) {
|
||||
debug!("Error setting clipboard contents ({})", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
ConstellationMsg::WebDriverCommand(command) => {
|
||||
debug!("constellation got webdriver command message");
|
||||
self.handle_webdriver_msg(command);
|
||||
|
@ -247,6 +247,8 @@ pub enum Msg {
|
||||
Focus(PipelineId),
|
||||
/// Requests that the constellation retrieve the current contents of the clipboard
|
||||
GetClipboardContents(IpcSender<String>),
|
||||
/// Requests that the constellation set the contents of the clipboard
|
||||
SetClipboardContents(String),
|
||||
/// Dispatch a webdriver command
|
||||
WebDriverCommand(WebDriverCommandMsg),
|
||||
/// Notifies the constellation that the viewport has been constrained in some manner
|
||||
|
@ -13,7 +13,7 @@ pub trait ClipboardProvider {
|
||||
// blocking method to get the clipboard contents
|
||||
fn clipboard_contents(&mut self) -> String;
|
||||
// blocking method to set the clipboard contents
|
||||
fn set_clipboard_contents(&mut self, &str);
|
||||
fn set_clipboard_contents(&mut self, String);
|
||||
}
|
||||
|
||||
impl ClipboardProvider for ConstellationChan {
|
||||
@ -22,8 +22,8 @@ impl ClipboardProvider for ConstellationChan {
|
||||
self.0.send(ConstellationMsg::GetClipboardContents(tx)).unwrap();
|
||||
rx.recv().unwrap()
|
||||
}
|
||||
fn set_clipboard_contents(&mut self, _: &str) {
|
||||
panic!("not yet implemented");
|
||||
fn set_clipboard_contents(&mut self, s: String) {
|
||||
self.0.send(ConstellationMsg::SetClipboardContents(s)).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
@ -43,7 +43,7 @@ impl ClipboardProvider for DummyClipboardContext {
|
||||
fn clipboard_contents(&mut self) -> String {
|
||||
self.content.clone()
|
||||
}
|
||||
fn set_clipboard_contents(&mut self, s: &str) {
|
||||
self.content = s.to_owned();
|
||||
fn set_clipboard_contents(&mut self, s: String) {
|
||||
self.content = s;
|
||||
}
|
||||
}
|
||||
|
@ -143,51 +143,71 @@ impl<T: ClipboardProvider> TextInput<T> {
|
||||
self.replace_selection(s.into());
|
||||
}
|
||||
|
||||
pub fn get_sorted_selection(&self) -> (TextPoint, TextPoint) {
|
||||
let begin = self.selection_begin.unwrap();
|
||||
let end = self.edit_point;
|
||||
pub fn get_sorted_selection(&self) -> Option<(TextPoint, TextPoint)> {
|
||||
self.selection_begin.map(|begin| {
|
||||
let end = self.edit_point;
|
||||
|
||||
if begin.line < end.line || (begin.line == end.line && begin.index < end.index) {
|
||||
(begin, end)
|
||||
} else {
|
||||
(end, begin)
|
||||
}
|
||||
if begin.line < end.line || (begin.line == end.line && begin.index < end.index) {
|
||||
(begin, end)
|
||||
} else {
|
||||
(end, begin)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub fn get_selection_text(&self) -> Option<String> {
|
||||
self.get_sorted_selection().map(|(begin, end)| {
|
||||
if begin.line != end.line {
|
||||
let mut s = String::new();
|
||||
s.push_str(self.lines[begin.line].slice_chars(begin.index, self.lines[begin.line].len()));
|
||||
for (_, line) in self.lines.iter().enumerate().filter(|&(i,_)| begin.line < i && i < end.line) {
|
||||
s.push_str("\n");
|
||||
s.push_str(line);
|
||||
}
|
||||
s.push_str("\n");
|
||||
s.push_str(self.lines[end.line].slice_chars(0, end.index));
|
||||
s
|
||||
} else {
|
||||
self.lines[begin.line].slice_chars(begin.index, end.index).to_owned()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub fn replace_selection(&mut self, insert: String) {
|
||||
let (begin, end) = self.get_sorted_selection();
|
||||
self.clear_selection();
|
||||
if let Some((begin, end)) = self.get_sorted_selection() {
|
||||
self.clear_selection();
|
||||
|
||||
let new_lines = {
|
||||
let prefix = self.lines[begin.line].slice_chars(0, begin.index);
|
||||
let suffix = self.lines[end.line].slice_chars(end.index, self.lines[end.line].chars().count());
|
||||
let lines_prefix = &self.lines[..begin.line];
|
||||
let lines_suffix = &self.lines[end.line + 1..];
|
||||
let new_lines = {
|
||||
let prefix = self.lines[begin.line].slice_chars(0, begin.index);
|
||||
let suffix = self.lines[end.line].slice_chars(end.index, self.lines[end.line].chars().count());
|
||||
let lines_prefix = &self.lines[..begin.line];
|
||||
let lines_suffix = &self.lines[end.line + 1..];
|
||||
|
||||
let mut insert_lines = if self.multiline {
|
||||
insert.split('\n').map(|s| s.to_owned()).collect()
|
||||
} else {
|
||||
vec!(insert)
|
||||
let mut insert_lines = if self.multiline {
|
||||
insert.split('\n').map(|s| s.to_owned()).collect()
|
||||
} else {
|
||||
vec!(insert)
|
||||
};
|
||||
|
||||
let mut new_line = prefix.to_owned();
|
||||
new_line.push_str(&insert_lines[0]);
|
||||
insert_lines[0] = new_line;
|
||||
|
||||
let last_insert_lines_index = insert_lines.len() - 1;
|
||||
self.edit_point.index = insert_lines[last_insert_lines_index].chars().count();
|
||||
self.edit_point.line = begin.line + last_insert_lines_index;
|
||||
|
||||
insert_lines[last_insert_lines_index].push_str(suffix);
|
||||
|
||||
let mut new_lines = vec!();
|
||||
new_lines.push_all(lines_prefix);
|
||||
new_lines.push_all(&insert_lines);
|
||||
new_lines.push_all(lines_suffix);
|
||||
new_lines
|
||||
};
|
||||
|
||||
let mut new_line = prefix.to_owned();
|
||||
new_line.push_str(&insert_lines[0]);
|
||||
insert_lines[0] = new_line;
|
||||
|
||||
let last_insert_lines_index = insert_lines.len() - 1;
|
||||
self.edit_point.index = insert_lines[last_insert_lines_index].chars().count();
|
||||
self.edit_point.line = begin.line + last_insert_lines_index;
|
||||
|
||||
insert_lines[last_insert_lines_index].push_str(suffix);
|
||||
|
||||
let mut new_lines = vec!();
|
||||
new_lines.push_all(lines_prefix);
|
||||
new_lines.push_all(&insert_lines);
|
||||
new_lines.push_all(lines_suffix);
|
||||
new_lines
|
||||
};
|
||||
|
||||
self.lines = new_lines;
|
||||
self.lines = new_lines;
|
||||
}
|
||||
}
|
||||
|
||||
/// Return the length of the current line under the editing point.
|
||||
@ -237,8 +257,7 @@ impl<T: ClipboardProvider> TextInput<T> {
|
||||
self.selection_begin = Some(self.edit_point);
|
||||
}
|
||||
} else {
|
||||
if self.selection_begin.is_some() {
|
||||
let (begin, end) = self.get_sorted_selection();
|
||||
if let Some((begin, end)) = self.get_sorted_selection() {
|
||||
self.edit_point = if adjust < 0 {begin} else {end};
|
||||
self.clear_selection();
|
||||
return
|
||||
@ -304,11 +323,17 @@ impl<T: ClipboardProvider> TextInput<T> {
|
||||
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) => {
|
||||
Key::A if is_control_key(mods) => {
|
||||
self.select_all();
|
||||
KeyReaction::Nothing
|
||||
},
|
||||
Key::V if is_control_key(mods) => {
|
||||
Key::C if is_control_key(mods) => {
|
||||
if let Some(text) = self.get_selection_text() {
|
||||
self.clipboard_provider.set_clipboard_contents(text);
|
||||
}
|
||||
KeyReaction::DispatchInput
|
||||
},
|
||||
Key::V if is_control_key(mods) => {
|
||||
let contents = self.clipboard_provider.clipboard_contents();
|
||||
self.insert_string(contents);
|
||||
KeyReaction::DispatchInput
|
||||
|
2
servo/components/servo/Cargo.lock
generated
2
servo/components/servo/Cargo.lock
generated
@ -131,7 +131,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "clipboard"
|
||||
version = "0.0.1"
|
||||
source = "git+https://github.com/aweinstock314/rust-clipboard#d271be958151cbc90d4cea670f028afe05e75cbe"
|
||||
source = "git+https://github.com/aweinstock314/rust-clipboard#67ec94ac27b28ff4ed3a4dde212f57e302f7cc35"
|
||||
dependencies = [
|
||||
"libc 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"x11 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
2
servo/ports/cef/Cargo.lock
generated
2
servo/ports/cef/Cargo.lock
generated
@ -130,7 +130,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "clipboard"
|
||||
version = "0.0.1"
|
||||
source = "git+https://github.com/aweinstock314/rust-clipboard#d271be958151cbc90d4cea670f028afe05e75cbe"
|
||||
source = "git+https://github.com/aweinstock314/rust-clipboard#67ec94ac27b28ff4ed3a4dde212f57e302f7cc35"
|
||||
dependencies = [
|
||||
"libc 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"x11 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
2
servo/ports/gonk/Cargo.lock
generated
2
servo/ports/gonk/Cargo.lock
generated
@ -117,7 +117,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "clipboard"
|
||||
version = "0.0.1"
|
||||
source = "git+https://github.com/aweinstock314/rust-clipboard#d271be958151cbc90d4cea670f028afe05e75cbe"
|
||||
source = "git+https://github.com/aweinstock314/rust-clipboard#67ec94ac27b28ff4ed3a4dde212f57e302f7cc35"
|
||||
dependencies = [
|
||||
"libc 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"x11 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -50,14 +50,14 @@ fn test_textinput_get_sorted_selection() {
|
||||
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();
|
||||
let (begin, end) = textinput.get_sorted_selection().unwrap();
|
||||
assert_eq!(begin.index, 2);
|
||||
assert_eq!(end.index, 4);
|
||||
|
||||
textinput.clear_selection();
|
||||
|
||||
textinput.adjust_horizontal(-2, Selection::Selected);
|
||||
let (begin, end) = textinput.get_sorted_selection();
|
||||
let (begin, end) = textinput.get_sorted_selection().unwrap();
|
||||
assert_eq!(begin.index, 2);
|
||||
assert_eq!(end.index, 4);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user