Convert the content task's control messages and dom events to pipes

This commit is contained in:
Brian Anderson 2012-10-14 02:08:54 -07:00
parent c2377c574c
commit bee47744a3
7 changed files with 70 additions and 40 deletions

View file

@ -42,6 +42,7 @@ use std::net::url::Url;
use url_to_str = std::net::url::to_str;
use util::url::make_url;
use task::{task, SingleThreaded};
use std::cell::Cell;
use js::glue::bindgen::RUST_JSVAL_TO_OBJECT;
use js::JSVAL_NULL;
@ -60,17 +61,30 @@ pub enum PingMsg {
PongMsg
}
pub type ContentTask = Chan<ControlMsg>;
pub type ContentTask = pipes::SharedChan<ControlMsg>;
fn ContentTask<S: Compositor Send Copy>(layout_task: LayoutTask,
compositor: S,
resource_task: ResourceTask,
img_cache_task: ImageCacheTask) -> ContentTask {
do task().sched_mode(SingleThreaded).spawn_listener::<ControlMsg> |from_master| {
let content = Content(layout_task, from_master, resource_task, img_cache_task.clone());
compositor.add_event_listener(content.event_port.chan());
let (control_chan, control_port) = pipes::stream();
let control_chan = pipes::SharedChan(control_chan);
let control_chan_copy = control_chan.clone();
let control_port = Cell(move control_port);
do task().sched_mode(SingleThreaded).spawn |move control_port| {
let (event_chan, event_port) = pipes::stream();
let event_chan = pipes::SharedChan(event_chan);
let content = Content(layout_task, control_port.take(), control_chan_copy.clone(),
resource_task,
img_cache_task.clone(), move event_port, event_chan.clone());
compositor.add_event_listener(move event_chan);
content.start();
}
return control_chan;
}
struct Content {
@ -78,8 +92,10 @@ struct Content {
mut layout_join_port: Option<pipes::Port<()>>,
image_cache_task: ImageCacheTask,
from_master: comm::Port<ControlMsg>,
event_port: comm::Port<Event>,
control_port: pipes::Port<ControlMsg>,
control_chan: pipes::SharedChan<ControlMsg>,
event_port: pipes::Port<Event>,
event_chan: pipes::SharedChan<Event>,
scope: NodeScope,
jsrt: jsrt,
@ -96,13 +112,15 @@ struct Content {
}
fn Content(layout_task: LayoutTask,
from_master: Port<ControlMsg>,
control_port: pipes::Port<ControlMsg>,
control_chan: pipes::SharedChan<ControlMsg>,
resource_task: ResourceTask,
img_cache_task: ImageCacheTask) -> @Content {
img_cache_task: ImageCacheTask,
event_port: pipes::Port<Event>,
event_chan: pipes::SharedChan<Event>) -> @Content {
let jsrt = jsrt();
let cx = jsrt.cx();
let event_port = Port();
cx.set_default_options_and_version();
cx.set_logging_error_reporter();
@ -116,8 +134,10 @@ fn Content(layout_task: LayoutTask,
layout_task : layout_task,
layout_join_port : None,
image_cache_task : img_cache_task,
from_master : from_master,
control_port : control_port,
control_chan : control_chan,
event_port : event_port,
event_chan : event_chan,
scope : NodeScope(),
jsrt : jsrt,
@ -145,15 +165,15 @@ fn task_from_context(cx: *JSContext) -> *Content unsafe {
impl Content {
fn start() {
while self.handle_msg(select2(self.from_master, self.event_port)) {
// Go on...
while self.handle_msg() {
// Go on ...
}
}
fn handle_msg(msg: Either<ControlMsg,Event>) -> bool {
match move msg {
Left(move control_msg) => self.handle_control_msg(control_msg),
Right(move event) => self.handle_event(event)
fn handle_msg() -> bool {
match pipes::select2i(&self.control_port, &self.event_port) {
either::Left(*) => self.handle_control_msg(self.control_port.recv()),
either::Right(*) => self.handle_event(self.event_port.recv())
}
}
@ -180,7 +200,7 @@ impl Content {
debug!("js_scripts: %?", js_scripts);
let document = Document(root, self.scope, css_rules);
let window = Window(self.from_master);
let window = Window(self.control_chan.clone());
self.relayout(&document, &url);
self.document = Some(@document);
self.window = Some(@window);
@ -283,7 +303,7 @@ impl Content {
// Send new document and relevant styles to layout
// FIXME: Put CSS rules in an arc or something.
self.layout_task.send(BuildMsg(document.root, clone(&document.css_rules), copy *doc_url,
self.event_port.chan(), self.window_size, join_chan));
self.event_chan.clone(), self.window_size, join_chan));
// Indicate that reader was forked so any further
// changes will be isolated.

View file

@ -63,8 +63,7 @@ impl Window {
}
}
fn Window(content_port: Port<ControlMsg>) -> Window {
let content_chan = Chan(&content_port);
fn Window(content_chan: pipes::SharedChan<ControlMsg>) -> Window {
Window {
timer_chan: do task::spawn_listener |timer_port: Port<TimerControlMsg>| {

View file

@ -8,6 +8,6 @@ each rendered frame and submit them to be drawn to the display
trait Compositor {
fn begin_drawing(next_dt: pipes::Chan<LayerBuffer>);
fn draw(next_dt: pipes::Chan<LayerBuffer>, +draw_me: LayerBuffer);
fn add_event_listener(listener: comm::Chan<Event>);
fn add_event_listener(listener: pipes::SharedChan<Event>);
}

View file

@ -45,7 +45,7 @@ impl Chan<Msg> : Compositor {
fn draw(next_dt: pipes::Chan<LayerBuffer>, draw_me: LayerBuffer) {
self.send(Draw(next_dt, draw_me))
}
fn add_event_listener(_listener: Chan<Event>) {
fn add_event_listener(_listener: pipes::SharedChan<Event>) {
// No events in this compositor.
}
}

View file

@ -47,7 +47,7 @@ enum LayoutQueryResponse_ {
}
pub enum Msg {
BuildMsg(Node, ARC<Stylesheet>, Url, comm::Chan<Event>, Size2D<uint>, pipes::Chan<()>),
BuildMsg(Node, ARC<Stylesheet>, Url, pipes::SharedChan<Event>, Size2D<uint>, pipes::Chan<()>),
QueryMsg(LayoutQuery, comm::Chan<LayoutQueryResponse>),
ExitMsg
}
@ -96,14 +96,14 @@ impl Layout {
match self.from_content.recv() {
BuildMsg(move node, move styles, move doc_url,
move to_content, move window_size, move join_chan) => {
move dom_event_chan, move window_size, move join_chan) => {
let styles = Cell(styles);
let doc_url = Cell(doc_url);
let join_chan = Cell(join_chan);
do time("layout: performing layout") {
self.handle_build(node, styles.take(), doc_url.take(), to_content, window_size, join_chan.take());
self.handle_build(node, styles.take(), doc_url.take(), dom_event_chan.clone(), window_size, join_chan.take());
}
}
@ -122,14 +122,14 @@ impl Layout {
}
fn handle_build(node: Node, styles: ARC<Stylesheet>, doc_url: Url,
to_content: comm::Chan<Event>, window_size: Size2D<uint>,
join_chan: pipes::Chan<()>) {
dom_event_chan: pipes::SharedChan<Event>, window_size: Size2D<uint>,
content_join_chan: pipes::Chan<()>) {
debug!("layout: received layout request for: %s", doc_url.to_str());
debug!("layout: parsed Node tree");
debug!("%?", node.dump());
// Reset the image cache
self.local_image_cache.next_round(self.make_on_image_available_cb(to_content));
self.local_image_cache.next_round(self.make_on_image_available_cb(move dom_event_chan));
let screen_size = Size2D(au::from_px(window_size.width as int),
au::from_px(window_size.height as int));
@ -187,7 +187,7 @@ impl Layout {
} // time(layout: display list building)
// Tell content we're done
join_chan.send(());
content_join_chan.send(());
}
@ -225,10 +225,21 @@ impl Layout {
}
// When images can't be loaded in time to display they trigger
// this callback in some task somewhere. This w
fn make_on_image_available_cb(to_content: comm::Chan<Event>) -> ~fn(ImageResponseMsg) {
let f: ~fn(ImageResponseMsg) = |_msg| {
to_content.send(ReflowEvent)
// this callback in some task somewhere. This will send a message
// to the content task, and ultimately cause the image to be
// re-requested. We probably don't need to go all the way back to
// the content task for this.
fn make_on_image_available_cb(dom_event_chan: pipes::SharedChan<Event>) -> @fn() -> ~fn(ImageResponseMsg) {
// This has a crazy signature because the image cache needs to
// make multiple copies of the callback, and the dom event
// channel is not a copyable type, so this is actually a
// little factory to produce callbacks
let f: @fn() -> ~fn(ImageResponseMsg) = |move dom_event_chan| {
let dom_event_chan = dom_event_chan.clone();
let f: ~fn(ImageResponseMsg) = |_msg, move dom_event_chan| {
dom_event_chan.send(ReflowEvent)
};
f
};
return f;
}

View file

@ -32,7 +32,7 @@ pub enum Msg {
BeginDrawing(pipes::Chan<LayerBuffer>),
Draw(pipes::Chan<LayerBuffer>, LayerBuffer),
AddKeyHandler(pipes::Chan<()>),
AddEventListener(comm::Chan<Event>),
AddEventListener(pipes::SharedChan<Event>),
Exit
}
@ -55,7 +55,7 @@ fn OSMain() -> OSMain {
fn mainloop(mode: Mode, po: comm::Port<Msg>) {
let key_handlers: @DVec<pipes::Chan<()>> = @DVec();
let event_listeners: @DVec<comm::Chan<Event>> = @DVec();
let event_listeners: @DVec<pipes::SharedChan<Event>> = @DVec();
let window;
match mode {
@ -98,7 +98,7 @@ fn mainloop(mode: Mode, po: comm::Port<Msg>) {
while po.peek() {
match po.recv() {
AddKeyHandler(move key_ch) => key_handlers.push(move key_ch),
AddEventListener(event_listener) => event_listeners.push(event_listener),
AddEventListener(move event_listener) => event_listeners.push(event_listener),
BeginDrawing(move sender) => lend_surface(surfaces, sender),
Draw(move sender, move dt) => {
#debug("osmain: received new frame");
@ -181,7 +181,7 @@ impl OSMain : Compositor {
fn draw(next_dt: pipes::Chan<LayerBuffer>, draw_me: LayerBuffer) {
self.send(Draw(next_dt, draw_me))
}
fn add_event_listener(listener: comm::Chan<Event>) {
fn add_event_listener(listener: pipes::SharedChan<Event>) {
self.send(AddEventListener(listener));
}
}

View file

@ -24,7 +24,7 @@ pub fn LocalImageCache(
pub struct LocalImageCache {
priv image_cache_task: ImageCacheTask,
priv mut round_number: uint,
priv mut on_image_available: Option<~fn(ImageResponseMsg)>,
priv mut on_image_available: Option<@fn() -> ~fn(ImageResponseMsg)>,
priv state_map: UrlMap<@ImageState>
}
@ -40,7 +40,7 @@ pub impl LocalImageCache {
/// The local cache will only do a single remote request for a given
/// URL in each 'round'. Layout should call this each time it begins
// FIXME: 'pub' is an unexpected token?
/* pub */ fn next_round(on_image_available: ~fn(ImageResponseMsg)) {
/* pub */ fn next_round(on_image_available: @fn() -> ~fn(ImageResponseMsg)) {
self.round_number += 1;
self.on_image_available = Some(move on_image_available);
}
@ -109,7 +109,7 @@ pub impl LocalImageCache {
// on the image to load and triggering layout
let image_cache_task = self.image_cache_task.clone();
assert self.on_image_available.is_some();
let on_image_available = {copy *self.on_image_available.get_ref()};
let on_image_available = self.on_image_available.get()();
let url = copy *url;
do task::spawn |move url, move on_image_available| {
let (response_chan, response_port) = pipes::stream();