compositing: Move messages that go over the ScriptListener to go over

an IPC channel instead.

Because this used a boxed trait object to invoke messages across a
process boundary, and boxed trait objects are not supported across IPC,
we spawn a helper thread inside the compositor to perform the marshaling
for us.
This commit is contained in:
Patrick Walton 2015-07-10 18:08:03 -07:00
parent 2947d78e4e
commit e841065351
14 changed files with 211 additions and 82 deletions

View file

@ -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"

View file

@ -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<Msg> {
}
}
/// Implementation of the abstract `ScriptListener` interface.
impl ScriptListener for Box<CompositorProxy+'static+Send> {
fn scroll_fragment_point(&mut self,
pipeline_id: PipelineId,
layer_id: LayerId,
point: Point2D<f32>) {
self.send(Msg::ScrollFragmentPoint(pipeline_id, layer_id, point));
}
pub fn run_script_listener_thread(mut compositor_proxy: Box<CompositorProxy + 'static + Send>,
receiver: IpcReceiver<ScriptToCompositorMsg>) {
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<ScriptListener+'static> {
box self.clone_compositor_proxy() as Box<ScriptListener+'static>
}
ScriptToCompositorMsg::SetTitle(pipeline_id, title) => {
compositor_proxy.send(Msg::ChangePageTitle(pipeline_id, title))
}
fn set_title(&mut self, pipeline_id: PipelineId, title: Option<String>) {
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))
}
}
}
}

View file

@ -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;

View file

@ -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,