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::event::{Event, ResizeEvent, ReflowEvent};
use dom::window::Window; use dom::window::Window;
use geom::size::Size2D; use geom::size::Size2D;
use gfx::compositor::Compositor;
use layout::layout_task; use layout::layout_task;
use layout_task::{LayoutTask, BuildMsg}; use layout_task::{LayoutTask, BuildMsg};
use resource::image_cache_task::ImageCacheTask; use resource::image_cache_task::ImageCacheTask;
@ -63,8 +62,9 @@ pub enum PingMsg {
pub type ContentTask = pipes::SharedChan<ControlMsg>; pub type ContentTask = pipes::SharedChan<ControlMsg>;
fn ContentTask<S: Compositor Send Copy>(layout_task: LayoutTask, fn ContentTask(layout_task: LayoutTask,
compositor: S, dom_event_port: pipes::Port<Event>,
dom_event_chan: pipes::SharedChan<Event>,
resource_task: ResourceTask, resource_task: ResourceTask,
img_cache_task: ImageCacheTask) -> ContentTask { img_cache_task: ImageCacheTask) -> ContentTask {
@ -72,15 +72,14 @@ fn ContentTask<S: Compositor Send Copy>(layout_task: LayoutTask,
let control_chan = pipes::SharedChan(control_chan); let control_chan = pipes::SharedChan(control_chan);
let control_chan_copy = control_chan.clone(); 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| { do task().sched_mode(SingleThreaded).spawn {
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(), let content = Content(layout_task, control_port.take(), control_chan_copy.clone(),
resource_task, resource_task, img_cache_task.clone(),
img_cache_task.clone(), move event_port, event_chan.clone()); dom_event_port.take(), dom_event_chan.take());
compositor.add_event_listener(move event_chan);
content.start(); content.start();
} }

View file

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

View file

@ -8,6 +8,5 @@ each rendered frame and submit them to be drawn to the display
trait Compositor { trait Compositor {
fn begin_drawing(next_dt: pipes::Chan<LayerBuffer>); fn begin_drawing(next_dt: pipes::Chan<LayerBuffer>);
fn draw(next_dt: pipes::Chan<LayerBuffer>, +draw_me: 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) { fn draw(next_dt: pipes::Chan<LayerBuffer>, draw_me: LayerBuffer) {
self.send(Draw(next_dt, draw_me)) 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 { pub fn PngCompositor(output: Chan<~[u8]>) -> PngCompositor {

View file

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

View file

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