diff options
-rw-r--r-- | Cargo.lock | 1 | ||||
-rw-r--r-- | components/constellation/constellation.rs | 35 | ||||
-rw-r--r-- | components/embedder_traits/lib.rs | 6 | ||||
-rw-r--r-- | components/script/clipboard_provider.rs | 33 | ||||
-rw-r--r-- | components/script_traits/script_msg.rs | 6 | ||||
-rw-r--r-- | ports/glutin/Cargo.toml | 1 | ||||
-rw-r--r-- | ports/glutin/browser.rs | 33 | ||||
-rw-r--r-- | ports/libmlservo/src/lib.rs | 6 | ||||
-rw-r--r-- | ports/libsimpleservo/api/src/lib.rs | 12 | ||||
-rw-r--r-- | ports/libsimpleservo/capi/src/lib.rs | 21 | ||||
-rw-r--r-- | ports/libsimpleservo/jniapi/src/lib.rs | 6 | ||||
-rw-r--r-- | tests/unit/script/textinput.rs | 23 |
12 files changed, 117 insertions, 66 deletions
diff --git a/Cargo.lock b/Cargo.lock index ea57cbd81f8..367997a39ad 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4019,6 +4019,7 @@ dependencies = [ "backtrace 0.3.26 (registry+https://github.com/rust-lang/crates.io-index)", "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)", + "clipboard 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-channel 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "euclid 0.19.8 (registry+https://github.com/rust-lang/crates.io-index)", "gleam 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/components/constellation/constellation.rs b/components/constellation/constellation.rs index 558734031ec..3fd21e735e4 100644 --- a/components/constellation/constellation.rs +++ b/components/constellation/constellation.rs @@ -107,7 +107,6 @@ use canvas::canvas_paint_thread::CanvasPaintThread; use canvas::webgl_thread::WebGLThreads; use canvas_traits::canvas::CanvasId; use canvas_traits::canvas::CanvasMsg; -use clipboard::{ClipboardContext, ClipboardProvider}; use compositing::compositor_thread::CompositorProxy; use compositing::compositor_thread::Msg as ToCompositorMsg; use compositing::SendableFrameTree; @@ -361,9 +360,6 @@ pub struct Constellation<Message, LTF, STF> { /// The size of the top-level window. window_size: WindowSizeData, - /// Means of accessing the clipboard - clipboard_ctx: Option<ClipboardContext>, - /// Bits of state used to interact with the webdriver implementation webdriver: WebDriverData, @@ -734,13 +730,6 @@ where device_pixel_ratio: TypedScale::new(device_pixels_per_px.unwrap_or(1.0)), }, phantom: PhantomData, - clipboard_ctx: match ClipboardContext::new() { - Ok(c) => Some(c), - Err(e) => { - warn!("Error creating clipboard context ({})", e); - None - }, - }, webdriver: WebDriverData::new(), scheduler_chan: TimerScheduler::start(), document_states: HashMap::new(), @@ -1524,30 +1513,6 @@ where FromScriptMsg::Focus => { self.handle_focus_msg(source_pipeline_id); }, - FromScriptMsg::GetClipboardContents(sender) => { - let contents = match self.clipboard_ctx { - Some(ref mut ctx) => { - match ctx.get_contents() { - Ok(c) => c, - Err(e) => { - warn!("Error getting clipboard contents ({}), defaulting to empty string", e); - "".to_owned() - }, - } - }, - None => "".to_owned(), - }; - if let Err(e) = sender.send(contents) { - warn!("Failed to send clipboard ({})", e); - } - }, - FromScriptMsg::SetClipboardContents(s) => { - if let Some(ref mut ctx) = self.clipboard_ctx { - if let Err(e) = ctx.set_contents(s) { - warn!("Error setting clipboard contents ({})", e); - } - } - }, FromScriptMsg::VisibilityChangeComplete(is_visible) => { self.handle_visibility_change_complete(source_pipeline_id, is_visible); }, diff --git a/components/embedder_traits/lib.rs b/components/embedder_traits/lib.rs index 297972516b6..ac427c42995 100644 --- a/components/embedder_traits/lib.rs +++ b/components/embedder_traits/lib.rs @@ -132,6 +132,10 @@ pub enum EmbedderMsg { AllowUnload(IpcSender<bool>), /// Sends an unconsumed key event back to the embedder. Keyboard(KeyboardEvent), + /// Gets system clipboard contents + GetClipboardContents(IpcSender<String>), + /// Sets system clipboard contents + SetClipboardContents(String), /// Changes the cursor. SetCursor(Cursor), /// A favicon was detected @@ -175,6 +179,8 @@ impl Debug for EmbedderMsg { EmbedderMsg::AllowUnload(..) => write!(f, "AllowUnload"), EmbedderMsg::AllowNavigationRequest(..) => write!(f, "AllowNavigationRequest"), EmbedderMsg::Keyboard(..) => write!(f, "Keyboard"), + EmbedderMsg::GetClipboardContents(..) => write!(f, "GetClipboardContents"), + EmbedderMsg::SetClipboardContents(..) => write!(f, "SetClipboardContents"), EmbedderMsg::SetCursor(..) => write!(f, "SetCursor"), EmbedderMsg::NewFavicon(..) => write!(f, "NewFavicon"), EmbedderMsg::HeadParsed => write!(f, "HeadParsed"), diff --git a/components/script/clipboard_provider.rs b/components/script/clipboard_provider.rs index 72afd5727d2..666bf74c825 100644 --- a/components/script/clipboard_provider.rs +++ b/components/script/clipboard_provider.rs @@ -2,9 +2,9 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ +use embedder_traits::EmbedderMsg; use ipc_channel::ipc::channel; use script_traits::{ScriptMsg, ScriptToConstellationChan}; -use std::borrow::ToOwned; pub trait ClipboardProvider { // blocking method to get the clipboard contents @@ -16,31 +16,16 @@ pub trait ClipboardProvider { impl ClipboardProvider for ScriptToConstellationChan { fn clipboard_contents(&mut self) -> String { let (tx, rx) = channel().unwrap(); - self.send(ScriptMsg::GetClipboardContents(tx)).unwrap(); + self.send(ScriptMsg::ForwardToEmbedder( + EmbedderMsg::GetClipboardContents(tx), + )) + .unwrap(); rx.recv().unwrap() } fn set_clipboard_contents(&mut self, s: String) { - self.send(ScriptMsg::SetClipboardContents(s)).unwrap(); - } -} - -pub struct DummyClipboardContext { - content: String, -} - -impl DummyClipboardContext { - pub fn new(s: &str) -> DummyClipboardContext { - DummyClipboardContext { - content: s.to_owned(), - } - } -} - -impl ClipboardProvider for DummyClipboardContext { - fn clipboard_contents(&mut self) -> String { - self.content.clone() - } - fn set_clipboard_contents(&mut self, s: String) { - self.content = s; + self.send(ScriptMsg::ForwardToEmbedder( + EmbedderMsg::SetClipboardContents(s), + )) + .unwrap(); } } diff --git a/components/script_traits/script_msg.rs b/components/script_traits/script_msg.rs index 48862e8378f..6f11e2356df 100644 --- a/components/script_traits/script_msg.rs +++ b/components/script_traits/script_msg.rs @@ -121,8 +121,6 @@ pub enum ScriptMsg { CreateCanvasPaintThread(Size2D<u64>, IpcSender<(IpcSender<CanvasMsg>, CanvasId)>), /// Notifies the constellation that this frame has received focus. Focus, - /// Requests that the constellation retrieve the current contents of the clipboard - GetClipboardContents(IpcSender<String>), /// Get the top-level browsing context info for a given browsing context. GetTopForBrowsingContext( BrowsingContextId, @@ -183,8 +181,6 @@ pub enum ScriptMsg { AuxiliaryBrowsingContextLoadInfo, IpcSender<LayoutControlMsg>, ), - /// Requests that the constellation set the contents of the clipboard - SetClipboardContents(String), /// Mark a new document as active ActivateDocument, /// Set the document state for a pipeline (used by screenshot / reftests) @@ -224,7 +220,6 @@ impl fmt::Debug for ScriptMsg { ChangeRunningAnimationsState(..) => "ChangeRunningAnimationsState", CreateCanvasPaintThread(..) => "CreateCanvasPaintThread", Focus => "Focus", - GetClipboardContents(..) => "GetClipboardContents", GetBrowsingContextInfo(..) => "GetBrowsingContextInfo", GetTopForBrowsingContext(..) => "GetParentBrowsingContext", GetChildBrowsingContextId(..) => "GetChildBrowsingContextId", @@ -242,7 +237,6 @@ impl fmt::Debug for ScriptMsg { ScriptLoadedURLInIFrame(..) => "ScriptLoadedURLInIFrame", ScriptNewIFrame(..) => "ScriptNewIFrame", ScriptNewAuxiliary(..) => "ScriptNewAuxiliary", - SetClipboardContents(..) => "SetClipboardContents", ActivateDocument => "ActivateDocument", SetDocumentState(..) => "SetDocumentState", SetFinalUrl(..) => "SetFinalUrl", diff --git a/ports/glutin/Cargo.toml b/ports/glutin/Cargo.toml index a75452b2660..2727c6cb8cc 100644 --- a/ports/glutin/Cargo.toml +++ b/ports/glutin/Cargo.toml @@ -55,6 +55,7 @@ log = "0.4" rust-webvr = { version = "0.13", features = ["glwindow"] } webxr = { git = "https://github.com/servo/webxr", features = ["glwindow"] } tinyfiledialogs = "3.0" +clipboard = "0.5" [target.'cfg(any(target_os = "linux", target_os = "windows"))'.dependencies] image = "0.21" diff --git a/ports/glutin/browser.rs b/ports/glutin/browser.rs index e2f7d397919..042f84072c7 100644 --- a/ports/glutin/browser.rs +++ b/ports/glutin/browser.rs @@ -16,6 +16,7 @@ use servo::servo_config::opts; use servo::servo_config::pref; use servo::servo_url::ServoUrl; use servo::webrender_api::ScrollLocation; +use clipboard::{ClipboardContext, ClipboardProvider}; use std::env; use std::fs::File; use std::io::Write; @@ -43,6 +44,7 @@ pub struct Browser<Window: WindowPortsMethods + ?Sized> { loading_state: Option<LoadingState>, window: Rc<Window>, event_queue: Vec<WindowEvent>, + clipboard_ctx: Option<ClipboardContext>, shutdown_requested: bool, } @@ -66,6 +68,13 @@ where favicon: None, loading_state: None, window: window, + clipboard_ctx: match ClipboardContext::new() { + Ok(c) => Some(c), + Err(e) => { + warn!("Error creating clipboard context ({})", e); + None + }, + }, event_queue: Vec::new(), shutdown_requested: false, } @@ -344,6 +353,30 @@ where EmbedderMsg::Keyboard(key_event) => { self.handle_key_from_servo(browser_id, key_event); }, + EmbedderMsg::GetClipboardContents(sender) => { + let contents = match self.clipboard_ctx { + Some(ref mut ctx) => { + match ctx.get_contents() { + Ok(c) => c, + Err(e) => { + warn!("Error getting clipboard contents ({}), defaulting to empty string", e); + "".to_owned() + }, + } + }, + None => "".to_owned(), + }; + if let Err(e) = sender.send(contents) { + warn!("Failed to send clipboard ({})", e); + } + } + EmbedderMsg::SetClipboardContents(text) => { + if let Some(ref mut ctx) = self.clipboard_ctx { + if let Err(e) = ctx.set_contents(text) { + warn!("Error setting clipboard contents ({})", e); + } + } + } EmbedderMsg::SetCursor(cursor) => { self.window.set_cursor(cursor); }, diff --git a/ports/libmlservo/src/lib.rs b/ports/libmlservo/src/lib.rs index 6ad7b19d9ca..b71900c17ea 100644 --- a/ports/libmlservo/src/lib.rs +++ b/ports/libmlservo/src/lib.rs @@ -378,6 +378,12 @@ impl HostTrait for HostCallbacks { keyboard(self.app, show) } } + + fn get_clipboard_contents(&self) -> Option<String> { + None + } + + fn set_clipboard_contents(&self, _contents: String) {} } pub struct ServoInstance { diff --git a/ports/libsimpleservo/api/src/lib.rs b/ports/libsimpleservo/api/src/lib.rs index 41d2a937e89..1adf4d14eea 100644 --- a/ports/libsimpleservo/api/src/lib.rs +++ b/ports/libsimpleservo/api/src/lib.rs @@ -25,6 +25,7 @@ use servo::servo_url::ServoUrl; use servo::webrender_api::{DevicePixel, FramebufferPixel, ScrollLocation}; use servo::webvr::{VRExternalShmemPtr, VRMainThreadHeartbeat, VRService, VRServiceManager}; use servo::{self, gl, BrowserId, Servo}; + use std::cell::RefCell; use std::mem; use std::os::raw::c_void; @@ -118,6 +119,10 @@ pub trait HostTrait { fn on_shutdown_complete(&self); /// A text input is focused. fn on_ime_state_changed(&self, show: bool); + /// Gets sytem clipboard contents + fn get_clipboard_contents(&self) -> Option<String>; + /// Sets system clipboard contents + fn set_clipboard_contents(&self, contents: String); } pub struct ServoGlue { @@ -528,6 +533,13 @@ impl ServoGlue { } self.events.push(WindowEvent::SelectBrowser(new_browser_id)); }, + EmbedderMsg::GetClipboardContents(sender) => { + let contents = self.callbacks.host_callbacks.get_clipboard_contents(); + let _ = sender.send(contents.unwrap_or("".to_owned())); + }, + EmbedderMsg::SetClipboardContents(text) => { + self.callbacks.host_callbacks.set_clipboard_contents(text); + }, EmbedderMsg::CloseBrowser => { // TODO: close the appropriate "tab". let _ = self.browsers.pop(); diff --git a/ports/libsimpleservo/capi/src/lib.rs b/ports/libsimpleservo/capi/src/lib.rs index 514b87a7421..ecf958ed913 100644 --- a/ports/libsimpleservo/capi/src/lib.rs +++ b/ports/libsimpleservo/capi/src/lib.rs @@ -43,6 +43,8 @@ pub struct CHostCallbacks { pub on_animating_changed: extern "C" fn(animating: bool), pub on_shutdown_complete: extern "C" fn(), pub on_ime_state_changed: extern "C" fn(show: bool), + pub get_clipboard_contents: extern "C" fn() -> *const c_char, + pub set_clipboard_contents: extern "C" fn(contents: *const c_char), } /// Servo options @@ -358,4 +360,23 @@ impl HostTrait for HostCallbacks { debug!("on_ime_state_changed"); (self.0.on_ime_state_changed)(show); } + + fn get_clipboard_contents(&self) -> Option<String> { + debug!("get_clipboard_contents"); + let raw_contents = (self.0.get_clipboard_contents)(); + if raw_contents.is_null() { + return None; + } + let c_str = unsafe { CStr::from_ptr(raw_contents) }; + let contents_str = c_str.to_str().expect("Can't create str"); + Some(contents_str.to_owned()) + } + + fn set_clipboard_contents(&self, contents: String) { + debug!("set_clipboard_contents"); + let contents = CString::new(contents).expect("Can't create string"); + let contents_ptr = contents.as_ptr(); + mem::forget(contents); + (self.0.set_clipboard_contents)(contents_ptr); + } } diff --git a/ports/libsimpleservo/jniapi/src/lib.rs b/ports/libsimpleservo/jniapi/src/lib.rs index a8da503c256..d342a1a6c29 100644 --- a/ports/libsimpleservo/jniapi/src/lib.rs +++ b/ports/libsimpleservo/jniapi/src/lib.rs @@ -476,6 +476,12 @@ impl HostTrait for HostCallbacks { } fn on_ime_state_changed(&self, _show: bool) {} + + fn get_clipboard_contents(&self) -> Option<String> { + None + } + + fn set_clipboard_contents(&self, _contents: String) {} } fn initialize_android_glue(env: &JNIEnv, activity: JObject) { diff --git a/tests/unit/script/textinput.rs b/tests/unit/script/textinput.rs index aa4bc51b206..001938134c8 100644 --- a/tests/unit/script/textinput.rs +++ b/tests/unit/script/textinput.rs @@ -8,13 +8,34 @@ // except according to those terms. use keyboard_types::{Key, Modifiers}; -use script::clipboard_provider::DummyClipboardContext; +use script::clipboard_provider::ClipboardProvider; use script::test::DOMString; use script::textinput::{ Direction, Lines, Selection, SelectionDirection, TextInput, TextPoint, UTF16CodeUnits, UTF8Bytes, }; +pub struct DummyClipboardContext { + content: String, +} + +impl DummyClipboardContext { + pub fn new(s: &str) -> DummyClipboardContext { + DummyClipboardContext { + content: s.to_owned(), + } + } +} + +impl ClipboardProvider for DummyClipboardContext { + fn clipboard_contents(&mut self) -> String { + self.content.clone() + } + fn set_clipboard_contents(&mut self, s: String) { + self.content = s; + } +} + fn text_input(lines: Lines, s: &str) -> TextInput<DummyClipboardContext> { TextInput::new( lines, |