Refactor how dom events are propagated

There is no longer an out-of-place add_event_listener method on Compositor.
Instead the creator of Engine sets of the dom (Port, SharedChan) pair and
distributes a channel to OSMain and the Port to ContentTask.
This commit is contained in:
Brian Anderson 2012-10-14 03:12:22 -07:00
parent bee47744a3
commit a06d45f2a5
6 changed files with 41 additions and 33 deletions

View file

@ -19,7 +19,6 @@ use dom::node::{Node, NodeScope, define_bindings};
use dom::event::{Event, ResizeEvent, ReflowEvent};
use dom::window::Window;
use geom::size::Size2D;
use gfx::compositor::Compositor;
use layout::layout_task;
use layout_task::{LayoutTask, BuildMsg};
use resource::image_cache_task::ImageCacheTask;
@ -63,24 +62,24 @@ pub enum PingMsg {
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 {
fn ContentTask(layout_task: LayoutTask,
dom_event_port: pipes::Port<Event>,
dom_event_chan: pipes::SharedChan<Event>,
resource_task: ResourceTask,
img_cache_task: ImageCacheTask) -> ContentTask {
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);
let control_port = Cell(control_port);
let dom_event_port = Cell(dom_event_port);
let dom_event_chan = Cell(dom_event_chan);
do task().sched_mode(SingleThreaded).spawn |move control_port| {
let (event_chan, event_port) = pipes::stream();
let event_chan = pipes::SharedChan(event_chan);
do task().sched_mode(SingleThreaded).spawn {
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);
resource_task, img_cache_task.clone(),
dom_event_port.take(), dom_event_chan.take());
content.start();
}

View file

@ -12,6 +12,8 @@ use std::net::url::Url;
use resource::image_cache_task;
use image_cache_task::{ImageCacheTask, image_cache_task, ImageCacheTaskClient};
use pipes::{Port, Chan};
use dom::event::Event;
use std::cell::Cell;
pub type EngineTask = comm::Chan<Msg>;
@ -31,12 +33,20 @@ struct Engine<C:Compositor Send Copy> {
}
fn Engine<C:Compositor Send Copy>(compositor: C,
dom_event_port: pipes::Port<Event>,
dom_event_chan: pipes::SharedChan<Event>,
resource_task: ResourceTask,
image_cache_task: ImageCacheTask) -> EngineTask {
do spawn_listener::<Msg> |request| {
let dom_event_port = Cell(dom_event_port);
let dom_event_chan = Cell(dom_event_chan);
do spawn_listener::<Msg> |request, move dom_event_port, move dom_event_chan| {
let render_task = RenderTask(compositor);
let layout_task = LayoutTask(render_task, image_cache_task.clone());
let content_task = ContentTask(layout_task, compositor, resource_task, image_cache_task.clone());
let content_task = ContentTask(layout_task,
dom_event_port.take(), dom_event_chan.take(),
resource_task, image_cache_task.clone());
Engine {
request_port: request,

View file

@ -8,6 +8,5 @@ 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: pipes::SharedChan<Event>);
}

View file

@ -45,9 +45,6 @@ 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: pipes::SharedChan<Event>) {
// No events in this compositor.
}
}
pub fn PngCompositor(output: Chan<~[u8]>) -> PngCompositor {

View file

@ -14,6 +14,7 @@ use std::cmp::FuzzyEq;
use task::TaskBuilder;
use vec::push;
use pipes::Chan;
use std::cell::Cell;
pub type OSMain = comm::Chan<Msg>;
@ -32,11 +33,11 @@ pub enum Msg {
BeginDrawing(pipes::Chan<LayerBuffer>),
Draw(pipes::Chan<LayerBuffer>, LayerBuffer),
AddKeyHandler(pipes::Chan<()>),
AddEventListener(pipes::SharedChan<Event>),
Exit
}
fn OSMain() -> OSMain {
fn OSMain(dom_event_chan: pipes::SharedChan<Event>) -> OSMain {
let dom_event_chan = Cell(dom_event_chan);
do on_osmain::<Msg> |po| {
do platform::runmain {
#debug("preparing to enter main loop");
@ -48,14 +49,16 @@ fn OSMain() -> OSMain {
None => mode = GlutMode
}
mainloop(mode, po);
mainloop(mode, po, dom_event_chan.take());
}
}
}
fn mainloop(mode: Mode, po: comm::Port<Msg>) {
fn mainloop(mode: Mode, po: comm::Port<Msg>, dom_event_chan: pipes::SharedChan<Event>) {
let dom_event_chan = @move dom_event_chan;
let key_handlers: @DVec<pipes::Chan<()>> = @DVec();
let event_listeners: @DVec<pipes::SharedChan<Event>> = @DVec();
let window;
match mode {
@ -98,7 +101,6 @@ 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(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");
@ -134,9 +136,7 @@ fn mainloop(mode: Mode, po: comm::Port<Msg>) {
check_for_messages();
#debug("osmain: window resized to %d,%d", width as int, height as int);
for event_listeners.each |event_listener| {
event_listener.send(ResizeEvent(width as uint, height as uint));
}
dom_event_chan.send(ResizeEvent(width as uint, height as uint));
}
do glut::display_func() {
@ -181,9 +181,6 @@ 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: pipes::SharedChan<Event>) {
self.send(AddEventListener(listener));
}
}
struct SurfaceSet {

View file

@ -32,8 +32,11 @@ fn run(opts: &Opts) {
fn run_pipeline_screen(urls: &[~str]) {
let (dom_event_chan, dom_event_port) = pipes::stream();
let dom_event_chan = pipes::SharedChan(move dom_event_chan);
// The platform event handler thread
let osmain = OSMain();
let osmain = OSMain(dom_event_chan.clone());
// Send each file to render then wait for keypress
let (keypress_to_engine, keypress_from_osmain) = pipes::stream();
@ -42,7 +45,7 @@ fn run_pipeline_screen(urls: &[~str]) {
// Create a servo instance
let resource_task = ResourceTask();
let image_cache_task = ImageCacheTask(resource_task);
let engine_task = Engine(osmain, resource_task, image_cache_task);
let engine_task = Engine(osmain, dom_event_port, dom_event_chan, resource_task, image_cache_task);
for urls.each |filename| {
let url = make_url(copy *filename, None);
@ -74,12 +77,15 @@ fn run_pipeline_png(url: ~str, outfile: &str) {
use resource::image_cache_task::SyncImageCacheTask;
listen(|pngdata_from_compositor| {
let (dom_event_chan, dom_event_port) = pipes::stream();
let dom_event_chan = pipes::SharedChan(move dom_event_chan);
let compositor = PngCompositor(pngdata_from_compositor);
let resource_task = ResourceTask();
// For the PNG pipeline we are using a synchronous image task so that all images will be
// fulfilled before the first paint.
let image_cache_task = SyncImageCacheTask(resource_task);
let engine_task = Engine(compositor, resource_task, image_cache_task);
let engine_task = Engine(compositor, dom_event_port, dom_event_chan, resource_task, image_cache_task);
engine_task.send(LoadURLMsg(make_url(copy url, None)));
match buffered_file_writer(&Path(outfile)) {