Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

compositing: Make `ScriptListener` and `LayoutControlChan` messages go over IPC. #6596

Merged
merged 2 commits into from Jul 14, 2015
Merged
Changes from 1 commit
Commits
File filter...
Filter file types
Jump to…
Jump to file
Failed to load files.

Always

Just for now

Next

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.
  • Loading branch information
pcwalton committed Jul 14, 2015
commit e84106535175211526729e532058a7514a0de372
@@ -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"
@@ -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));
}

fn close(&mut self) {
let (chan, port) = channel();
self.send(Msg::Exit(chan));
port.recv().unwrap();
}
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 dup(&mut self) -> Box<ScriptListener+'static> {
box self.clone_compositor_proxy() as Box<ScriptListener+'static>
}
ScriptToCompositorMsg::Exit => {
let (chan, port) = channel();
compositor_proxy.send(Msg::Exit(chan));
port.recv().unwrap();
}

fn set_title(&mut self, pipeline_id: PipelineId, title: Option<String>) {
self.send(Msg::ChangePageTitle(pipeline_id, title))
}
ScriptToCompositorMsg::SetTitle(pipeline_id, title) => {
compositor_proxy.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))
}
}
}
}

@@ -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;
@@ -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,
@@ -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 = "*"
@@ -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<f32>),
SetTitle(PipelineId, Option<String>),
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<f32>);
/// 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<String>);
fn close(&mut self);
fn dup(&mut self) -> Box<ScriptListener+'static>;
fn send_key_event(&mut self, key: Key, state: KeyState, modifiers: KeyModifiers);
#[derive(Clone)]
pub struct ScriptListener(IpcSender<ScriptToCompositorMsg>);

impl ScriptListener {
pub fn new(sender: IpcSender<ScriptToCompositorMsg>) -> ScriptListener {
ScriptListener(sender)
}

pub fn scroll_fragment_point(&mut self,
pipeline_id: PipelineId,
layer_id: LayerId,
point: Point2D<f32>) {
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<String>) {
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()
}
}

@@ -57,15 +57,15 @@ pub struct WindowSizeData {
pub device_pixel_ratio: ScaleFactor<ViewportPx, DevicePixel, f32>,
}

#[derive(PartialEq, Eq, Copy, Clone)]
#[derive(PartialEq, Eq, Copy, Clone, Deserialize, Serialize)]
pub enum KeyState {
Pressed,
Released,
Repeated,
}

//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
@@ -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;
@@ -328,7 +328,7 @@ impl<A,B> JSTraceable for fn(A) -> B {
}
}

impl JSTraceable for Box<ScriptListener+'static> {
impl JSTraceable for ScriptListener {
#[inline]
fn trace(&self, _: *mut JSTracer) {
// Do nothing
@@ -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<ScriptListener+'static>);
fn dispatch_key_event(self,
key: Key,
state: KeyState,
modifiers: KeyModifiers,
compositor: &mut ScriptListener);
fn node_from_nodes_and_strings(self, nodes: Vec<NodeOrString>)
-> Fallible<Root<Node>>;
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<ScriptListener+'static>) {
compositor: &mut ScriptListener) {
let window = self.window.root();
let focused = self.get_focused_element();
let body = self.GetBody();
@@ -105,7 +105,7 @@ pub struct Window {
navigator: MutNullableHeap<JS<Navigator>>,
image_cache_task: ImageCacheTask,
image_cache_chan: ImageCacheChan,
compositor: DOMRefCell<Box<ScriptListener+'static>>,
compositor: DOMRefCell<ScriptListener>,
browser_context: DOMRefCell<Option<BrowserContext>>,
page: Rc<Page>,
performance: MutNullableHeap<JS<Performance>>,
@@ -241,7 +241,7 @@ impl Window {
&self.image_cache_task
}

pub fn compositor<'a>(&'a self) -> RefMut<'a, Box<ScriptListener+'static>> {
pub fn compositor<'a>(&'a self) -> RefMut<'a, ScriptListener> {
self.compositor.borrow_mut()
}

@@ -964,7 +964,7 @@ impl Window {
script_chan: Box<ScriptChan+Send>,
image_cache_chan: ImageCacheChan,
control_chan: ScriptControlChan,
compositor: Box<ScriptListener+'static>,
compositor: ScriptListener,
image_cache_task: ImageCacheTask,
resource_task: ResourceTask,
storage_task: StorageTask,
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.