diff --git a/components/compositing/Cargo.toml b/components/compositing/Cargo.toml index f543f6c0780..0c027195b25 100644 --- a/components/compositing/Cargo.toml +++ b/components/compositing/Cargo.toml @@ -52,6 +52,9 @@ git = "https://github.com/servo/rust-png" [dependencies.clipboard] git = "https://github.com/aweinstock314/rust-clipboard" +[dependencies.ipc-channel] +git = "https://github.com/pcwalton/ipc-channel" + [dependencies] log = "*" num = "0.1.24" diff --git a/components/compositing/compositor_task.rs b/components/compositing/compositor_task.rs index 15e5f59f513..d8ada04bbdf 100644 --- a/components/compositing/compositor_task.rs +++ b/components/compositing/compositor_task.rs @@ -13,10 +13,11 @@ use windowing::{WindowEvent, WindowMethods}; use euclid::point::Point2D; use euclid::rect::Rect; +use ipc_channel::ipc::IpcReceiver; use layers::platform::surface::NativeDisplay; use layers::layers::{BufferRequest, LayerBuffer, LayerBufferSet}; use msg::compositor_msg::{Epoch, LayerId, LayerProperties, FrameTreeId}; -use msg::compositor_msg::{PaintListener, ScriptListener}; +use msg::compositor_msg::{PaintListener, ScriptToCompositorMsg}; use msg::constellation_msg::{AnimationState, ConstellationChan, PipelineId}; use msg::constellation_msg::{Key, KeyState, KeyModifiers}; use profile_traits::mem; @@ -61,31 +62,28 @@ impl CompositorReceiver for Receiver { } } -/// Implementation of the abstract `ScriptListener` interface. -impl ScriptListener for Box { - fn scroll_fragment_point(&mut self, - pipeline_id: PipelineId, - layer_id: LayerId, - point: Point2D) { - self.send(Msg::ScrollFragmentPoint(pipeline_id, layer_id, point)); - } +pub fn run_script_listener_thread(mut compositor_proxy: Box, + receiver: IpcReceiver) { + while let Ok(msg) = receiver.recv() { + match msg { + ScriptToCompositorMsg::ScrollFragmentPoint(pipeline_id, layer_id, point) => { + compositor_proxy.send(Msg::ScrollFragmentPoint(pipeline_id, layer_id, point)); + } - fn close(&mut self) { - let (chan, port) = channel(); - self.send(Msg::Exit(chan)); - port.recv().unwrap(); - } + ScriptToCompositorMsg::Exit => { + let (chan, port) = channel(); + compositor_proxy.send(Msg::Exit(chan)); + port.recv().unwrap(); + } - fn dup(&mut self) -> Box { - box self.clone_compositor_proxy() as Box - } + ScriptToCompositorMsg::SetTitle(pipeline_id, title) => { + compositor_proxy.send(Msg::ChangePageTitle(pipeline_id, title)) + } - fn set_title(&mut self, pipeline_id: PipelineId, title: Option) { - self.send(Msg::ChangePageTitle(pipeline_id, title)) - } - - fn send_key_event(&mut self, key: Key, state: KeyState, modifiers: KeyModifiers) { - self.send(Msg::KeyEvent(key, state, modifiers)); + ScriptToCompositorMsg::SendKeyEvent(key, key_state, key_modifiers) => { + compositor_proxy.send(Msg::KeyEvent(key, key_state, key_modifiers)) + } + } } } diff --git a/components/compositing/lib.rs b/components/compositing/lib.rs index c3f64f8703f..a9cb24eeb8d 100644 --- a/components/compositing/lib.rs +++ b/components/compositing/lib.rs @@ -14,6 +14,7 @@ extern crate azure; extern crate devtools_traits; extern crate euclid; extern crate gfx; +extern crate ipc_channel; extern crate layers; extern crate layout_traits; extern crate png; diff --git a/components/compositing/pipeline.rs b/components/compositing/pipeline.rs index 4305e686951..6bbbccbe731 100644 --- a/components/compositing/pipeline.rs +++ b/components/compositing/pipeline.rs @@ -7,13 +7,16 @@ use layout_traits::{LayoutControlMsg, LayoutTaskFactory, LayoutControlChan}; use script_traits::{ScriptControlChan, ScriptTaskFactory}; use script_traits::{NewLayoutInfo, ConstellationControlMsg}; +use compositor_task; use devtools_traits::DevtoolsControlChan; use euclid::rect::{TypedRect}; use euclid::scale_factor::ScaleFactor; use gfx::paint_task::Msg as PaintMsg; use gfx::paint_task::{PaintChan, PaintTask}; use gfx::font_cache_task::FontCacheTask; +use ipc_channel::ipc; use layers::geometry::DevicePixel; +use msg::compositor_msg::ScriptListener; use msg::constellation_msg::{ConstellationChan, Failure, FrameId, PipelineId, SubpageId}; use msg::constellation_msg::{LoadData, WindowSizeData, PipelineExitType, MozBrowserEvent}; use profile_traits::mem; @@ -22,6 +25,7 @@ use net_traits::ResourceTask; use net_traits::image_cache_task::ImageCacheTask; use net_traits::storage_task::StorageTask; use std::sync::mpsc::{Receiver, channel}; +use std::thread; use url::Url; use util::geometry::{PagePx, ViewportPx}; use util::opts; @@ -91,6 +95,8 @@ impl Pipeline { let script_chan = match script_chan { None => { let (script_chan, script_port) = channel(); + let (script_to_compositor_chan, script_to_compositor_port) = + ipc::channel().unwrap(); let window_size = window_rect.map(|rect| { WindowSizeData { @@ -100,10 +106,18 @@ impl Pipeline { } }); + let compositor_proxy_for_script_listener_thread = + compositor_proxy.clone_compositor_proxy(); + thread::spawn(move || { + compositor_task::run_script_listener_thread( + compositor_proxy_for_script_listener_thread, + script_to_compositor_port) + }); + ScriptTaskFactory::create(None::<&mut STF>, id, parent_info, - compositor_proxy.clone_compositor_proxy(), + ScriptListener::new(script_to_compositor_chan), &layout_pair, ScriptControlChan(script_chan.clone()), script_port, diff --git a/components/msg/Cargo.toml b/components/msg/Cargo.toml index 081dea247b0..a6d895986cf 100644 --- a/components/msg/Cargo.toml +++ b/components/msg/Cargo.toml @@ -22,12 +22,17 @@ git = "https://github.com/servo/rust-layers" [dependencies.png] git = "https://github.com/servo/rust-png" +[dependencies.ipc-channel] +git = "https://github.com/pcwalton/ipc-channel" + [dependencies] url = "0.2.35" bitflags = "*" hyper = "0.5" rustc-serialize = "0.3.4" euclid = "0.1" +serde = "*" +serde_macros = "*" [target.x86_64-apple-darwin.dependencies] core-foundation = "*" diff --git a/components/msg/compositor_msg.rs b/components/msg/compositor_msg.rs index 80f0548dbc4..be86e7d4994 100644 --- a/components/msg/compositor_msg.rs +++ b/components/msg/compositor_msg.rs @@ -7,6 +7,7 @@ use constellation_msg::{Key, KeyState, KeyModifiers}; use euclid::point::Point2D; use euclid::rect::Rect; use euclid::Matrix4; +use ipc_channel::ipc::IpcSender; use layers::platform::surface::NativeDisplay; use layers::layers::{BufferRequest, LayerBufferSet}; use std::fmt::{Formatter, Debug}; @@ -35,7 +36,7 @@ impl FrameTreeId { } } -#[derive(Clone, PartialEq, Eq, Copy, Hash)] +#[derive(Clone, PartialEq, Eq, Copy, Hash, Deserialize, Serialize)] pub struct LayerId(pub usize, pub u32); impl Debug for LayerId { @@ -115,16 +116,47 @@ pub trait PaintListener { fn notify_paint_task_exiting(&mut self, pipeline_id: PipelineId); } +#[derive(Deserialize, Serialize)] +pub enum ScriptToCompositorMsg { + ScrollFragmentPoint(PipelineId, LayerId, Point2D), + SetTitle(PipelineId, Option), + SendKeyEvent(Key, KeyState, KeyModifiers), + Exit, +} + /// The interface used by the script task to tell the compositor to update its ready state, /// which is used in displaying the appropriate message in the window's title. -pub trait ScriptListener { - fn scroll_fragment_point(&mut self, - pipeline_id: PipelineId, - layer_id: LayerId, - point: Point2D); - /// Informs the compositor that the title of the page with the given pipeline ID has changed. - fn set_title(&mut self, pipeline_id: PipelineId, new_title: Option); - fn close(&mut self); - fn dup(&mut self) -> Box; - fn send_key_event(&mut self, key: Key, state: KeyState, modifiers: KeyModifiers); +#[derive(Clone)] +pub struct ScriptListener(IpcSender); + +impl ScriptListener { + pub fn new(sender: IpcSender) -> ScriptListener { + ScriptListener(sender) + } + + pub fn scroll_fragment_point(&mut self, + pipeline_id: PipelineId, + layer_id: LayerId, + point: Point2D) { + self.0 + .send(ScriptToCompositorMsg::ScrollFragmentPoint(pipeline_id, layer_id, point)) + .unwrap() + } + + pub fn close(&mut self) { + self.0.send(ScriptToCompositorMsg::Exit).unwrap() + } + + pub fn dup(&mut self) -> ScriptListener { + self.clone() + } + + pub fn set_title(&mut self, pipeline_id: PipelineId, title: Option) { + self.0.send(ScriptToCompositorMsg::SetTitle(pipeline_id, title)).unwrap() + } + + pub fn send_key_event(&mut self, key: Key, state: KeyState, modifiers: KeyModifiers) { + self.0.send(ScriptToCompositorMsg::SendKeyEvent(key, state, modifiers)).unwrap() + } } + diff --git a/components/msg/constellation_msg.rs b/components/msg/constellation_msg.rs index 67436e5b09c..68a13cddc1c 100644 --- a/components/msg/constellation_msg.rs +++ b/components/msg/constellation_msg.rs @@ -57,7 +57,7 @@ pub struct WindowSizeData { pub device_pixel_ratio: ScaleFactor, } -#[derive(PartialEq, Eq, Copy, Clone)] +#[derive(PartialEq, Eq, Copy, Clone, Deserialize, Serialize)] pub enum KeyState { Pressed, Released, @@ -65,7 +65,7 @@ pub enum KeyState { } //N.B. Based on the glutin key enum -#[derive(Debug, PartialEq, Eq, Copy, Clone)] +#[derive(Debug, PartialEq, Eq, Copy, Clone, Deserialize, Serialize)] pub enum Key { Space, Apostrophe, @@ -191,6 +191,7 @@ pub enum Key { } bitflags! { + #[derive(Deserialize, Serialize)] flags KeyModifiers: u8 { const NONE = 0x00, const SHIFT = 0x01, @@ -368,10 +369,10 @@ pub struct FrameId(pub u32); #[derive(Clone, PartialEq, Eq, Copy, Hash, Debug)] pub struct WorkerId(pub u32); -#[derive(Clone, PartialEq, Eq, Copy, Hash, Debug)] +#[derive(Clone, PartialEq, Eq, Copy, Hash, Debug, Deserialize, Serialize)] pub struct PipelineId(pub u32); -#[derive(Clone, PartialEq, Eq, Copy, Hash, Debug)] +#[derive(Clone, PartialEq, Eq, Copy, Hash, Debug, Deserialize, Serialize)] pub struct SubpageId(pub u32); // The type of pipeline exit. During complete shutdowns, pipelines do not have to diff --git a/components/msg/lib.rs b/components/msg/lib.rs index 3e8427840d5..35aa6444b0f 100644 --- a/components/msg/lib.rs +++ b/components/msg/lib.rs @@ -2,13 +2,18 @@ * 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/. */ +#![feature(custom_derive, plugin)] +#![plugin(serde_macros)] + extern crate azure; #[macro_use] extern crate bitflags; extern crate euclid; extern crate hyper; +extern crate ipc_channel; extern crate layers; extern crate png; extern crate rustc_serialize; +extern crate serde; extern crate util; extern crate url; extern crate style; diff --git a/components/script/dom/bindings/trace.rs b/components/script/dom/bindings/trace.rs index b64d46a212e..43e9814242e 100644 --- a/components/script/dom/bindings/trace.rs +++ b/components/script/dom/bindings/trace.rs @@ -328,7 +328,7 @@ impl JSTraceable for fn(A) -> B { } } -impl JSTraceable for Box { +impl JSTraceable for ScriptListener { #[inline] fn trace(&self, _: *mut JSTracer) { // Do nothing diff --git a/components/script/dom/document.rs b/components/script/dom/document.rs index 7f8a864dcdc..1e024ea3edd 100644 --- a/components/script/dom/document.rs +++ b/components/script/dom/document.rs @@ -251,8 +251,11 @@ pub trait DocumentHelpers<'a> { fn title_changed(self); fn send_title_to_compositor(self); fn dirty_all_nodes(self); - fn dispatch_key_event(self, key: Key, state: KeyState, - modifiers: KeyModifiers, compositor: &mut Box); + fn dispatch_key_event(self, + key: Key, + state: KeyState, + modifiers: KeyModifiers, + compositor: &mut ScriptListener); fn node_from_nodes_and_strings(self, nodes: Vec) -> Fallible>; fn get_body_attribute(self, local_name: &Atom) -> DOMString; @@ -763,10 +766,11 @@ impl<'a> DocumentHelpers<'a> for &'a Document { } /// The entry point for all key processing for web content - fn dispatch_key_event(self, key: Key, + fn dispatch_key_event(self, + key: Key, state: KeyState, modifiers: KeyModifiers, - compositor: &mut Box) { + compositor: &mut ScriptListener) { let window = self.window.root(); let focused = self.get_focused_element(); let body = self.GetBody(); diff --git a/components/script/dom/window.rs b/components/script/dom/window.rs index b781d7e19a1..984a8d4fb01 100644 --- a/components/script/dom/window.rs +++ b/components/script/dom/window.rs @@ -105,7 +105,7 @@ pub struct Window { navigator: MutNullableHeap>, image_cache_task: ImageCacheTask, image_cache_chan: ImageCacheChan, - compositor: DOMRefCell>, + compositor: DOMRefCell, browser_context: DOMRefCell>, page: Rc, performance: MutNullableHeap>, @@ -241,7 +241,7 @@ impl Window { &self.image_cache_task } - pub fn compositor<'a>(&'a self) -> RefMut<'a, Box> { + pub fn compositor<'a>(&'a self) -> RefMut<'a, ScriptListener> { self.compositor.borrow_mut() } @@ -964,7 +964,7 @@ impl Window { script_chan: Box, image_cache_chan: ImageCacheChan, control_chan: ScriptControlChan, - compositor: Box, + compositor: ScriptListener, image_cache_task: ImageCacheTask, resource_task: ResourceTask, storage_task: StorageTask, diff --git a/components/script/script_task.rs b/components/script/script_task.rs index 49f9ecdfa2d..693e89058ef 100644 --- a/components/script/script_task.rs +++ b/components/script/script_task.rs @@ -297,8 +297,9 @@ pub struct ScriptTask { /// For communicating load url messages to the constellation constellation_chan: ConstellationChan, + /// A handle to the compositor for communicating ready state messages. - compositor: DOMRefCell>, + compositor: DOMRefCell, /// The port on which we receive messages from the image cache image_cache_port: Receiver, @@ -374,29 +375,28 @@ impl ScriptTaskFactory for ScriptTask { box pair.sender() as Box } - fn create(_phantom: Option<&mut ScriptTask>, - id: PipelineId, - parent_info: Option<(PipelineId, SubpageId)>, - compositor: C, - layout_chan: &OpaqueScriptLayoutChannel, - control_chan: ScriptControlChan, - control_port: Receiver, - constellation_chan: ConstellationChan, - failure_msg: Failure, - resource_task: ResourceTask, - storage_task: StorageTask, - image_cache_task: ImageCacheTask, - devtools_chan: Option, - window_size: Option, - load_data: LoadData) - where C: ScriptListener + Send + 'static { + fn create(_phantom: Option<&mut ScriptTask>, + id: PipelineId, + parent_info: Option<(PipelineId, SubpageId)>, + compositor: ScriptListener, + layout_chan: &OpaqueScriptLayoutChannel, + control_chan: ScriptControlChan, + control_port: Receiver, + constellation_chan: ConstellationChan, + failure_msg: Failure, + resource_task: ResourceTask, + storage_task: StorageTask, + image_cache_task: ImageCacheTask, + devtools_chan: Option, + window_size: Option, + load_data: LoadData) { let ConstellationChan(const_chan) = constellation_chan.clone(); let (script_chan, script_port) = channel(); let layout_chan = LayoutChan(layout_chan.sender()); spawn_named_with_send_on_failure(format!("ScriptTask {:?}", id), task_state::SCRIPT, move || { let roots = RootCollection::new(); let _stack_roots_tls = StackRootTLS::new(&roots); - let script_task = ScriptTask::new(box compositor as Box, + let script_task = ScriptTask::new(compositor, script_port, NonWorkerScriptChan(script_chan), control_chan, @@ -464,7 +464,7 @@ impl ScriptTask { } /// Creates a new script task. - pub fn new(compositor: Box, + pub fn new(compositor: ScriptListener, port: Receiver, chan: NonWorkerScriptChan, control_chan: ScriptControlChan, diff --git a/components/script_traits/lib.rs b/components/script_traits/lib.rs index f8c5ccc9d90..3d7375b6409 100644 --- a/components/script_traits/lib.rs +++ b/components/script_traits/lib.rs @@ -150,22 +150,21 @@ pub struct ScriptControlChan(pub Sender); /// crate. pub trait ScriptTaskFactory { /// Create a `ScriptTask`. - fn create(_phantom: Option<&mut Self>, - id: PipelineId, - parent_info: Option<(PipelineId, SubpageId)>, - compositor: C, - layout_chan: &OpaqueScriptLayoutChannel, - control_chan: ScriptControlChan, - control_port: Receiver, - constellation_msg: ConstellationChan, - failure_msg: Failure, - resource_task: ResourceTask, - storage_task: StorageTask, - image_cache_task: ImageCacheTask, - devtools_chan: Option, - window_size: Option, - load_data: LoadData) - where C: ScriptListener + Send; + fn create(_phantom: Option<&mut Self>, + id: PipelineId, + parent_info: Option<(PipelineId, SubpageId)>, + compositor: ScriptListener, + layout_chan: &OpaqueScriptLayoutChannel, + control_chan: ScriptControlChan, + control_port: Receiver, + constellation_msg: ConstellationChan, + failure_msg: Failure, + resource_task: ResourceTask, + storage_task: StorageTask, + image_cache_task: ImageCacheTask, + devtools_chan: Option, + window_size: Option, + load_data: LoadData); /// Create a script -> layout channel (`Sender`, `Receiver` pair). fn create_layout_channel(_phantom: Option<&mut Self>) -> OpaqueScriptLayoutChannel; /// Clone the `Sender` in `pair`. diff --git a/components/servo/Cargo.lock b/components/servo/Cargo.lock index 82652008b21..3ca04f3bfa8 100644 --- a/components/servo/Cargo.lock +++ b/components/servo/Cargo.lock @@ -47,6 +47,11 @@ name = "android_glue" version = "0.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "aster" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "azure" version = "0.1.0" @@ -157,6 +162,7 @@ dependencies = [ "gfx 0.0.1", "gfx_traits 0.0.1", "gleam 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "ipc-channel 0.1.0 (git+https://github.com/pcwalton/ipc-channel)", "layers 0.1.0 (git+https://github.com/servo/rust-layers)", "layout_traits 0.0.1", "libc 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -612,6 +618,17 @@ dependencies = [ "libc 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "ipc-channel" +version = "0.1.0" +source = "git+https://github.com/pcwalton/ipc-channel#aa2eab807ba1e7e287d283c2788c317c53d26970" +dependencies = [ + "libc 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_macros 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "js" version = "0.1.0" @@ -789,9 +806,12 @@ dependencies = [ "euclid 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "hyper 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", "io-surface 0.1.0 (git+https://github.com/servo/io-surface-rs)", + "ipc-channel 0.1.0 (git+https://github.com/pcwalton/ipc-channel)", "layers 0.1.0 (git+https://github.com/servo/rust-layers)", "png 0.1.0 (git+https://github.com/servo/rust-png)", "rustc-serialize 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_macros 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "style 0.0.1", "url 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)", "util 0.0.1", @@ -1007,6 +1027,27 @@ dependencies = [ "url 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "quasi" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "quasi_codegen" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "aster 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "quasi_macros" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "quasi_codegen 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "quicksort" version = "1.0.0" @@ -1124,6 +1165,32 @@ dependencies = [ "string_cache_plugin 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "serde" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "num 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "serde_codegen" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "aster 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "quasi 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "quasi_macros 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "serde_macros" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "serde_codegen 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "shared_library" version = "0.1.0"