Use pipe streams for keyboard events.

Termination detection in pipes also allows Servo to close on its own accord (issue #3)
This commit is contained in:
Eric Holk 2012-07-09 17:13:05 -07:00
parent 10a1e8b109
commit b10b052639
6 changed files with 39 additions and 28 deletions

View file

@ -34,7 +34,8 @@ fn Layout(renderer: Renderer) -> Layout {
ping_channel.send(content::PongMsg); ping_channel.send(content::PongMsg);
} }
ExitMsg { ExitMsg {
break; #debug("layout: ExitMsg received");
break;
} }
BuildMsg(node, styles) { BuildMsg(node, styles) {
#debug("layout: received layout request for:"); #debug("layout: received layout request for:");

View file

@ -17,7 +17,7 @@ import parser::parser_util::{parse_display_type, parse_font_size, parse_size};
import util::color::parsing::parse_color; import util::color::parsing::parse_color;
import vec::push; import vec::push;
type TokenReader = {stream : port<Token>, mut lookahead : option<Token>}; type TokenReader = {stream : comm::port<Token>, mut lookahead : option<Token>};
trait util_methods { trait util_methods {
fn get() -> Token; fn get() -> Token;
@ -195,7 +195,7 @@ impl parser_methods of parser_methods for TokenReader {
} }
} }
fn build_stylesheet(stream : port<Token>) -> ~[~style::Rule] { fn build_stylesheet(stream : comm::port<Token>) -> ~[~style::Rule] {
let mut rule_list = ~[]; let mut rule_list = ~[];
let reader = {stream : stream, mut lookahead : none}; let reader = {stream : stream, mut lookahead : none};

View file

@ -94,7 +94,7 @@ spawned, collates them, and sends them to the given result channel.
* `from_parent` - A port on which to receive new links. * `from_parent` - A port on which to receive new links.
"] "]
fn css_link_listener(to_parent : chan<Stylesheet>, from_parent : port<CSSMessage>) { fn css_link_listener(to_parent : comm::chan<Stylesheet>, from_parent : comm::port<CSSMessage>) {
let mut result_vec = ~[]; let mut result_vec = ~[];
loop { loop {
@ -124,7 +124,7 @@ fn css_link_listener(to_parent : chan<Stylesheet>, from_parent : port<CSSMessage
to_parent.send(css_rules); to_parent.send(css_rules);
} }
fn js_script_listener(to_parent : chan<~[~[u8]]>, from_parent : port<js_message>) { fn js_script_listener(to_parent : chan<~[~[u8]]>, from_parent : comm::port<js_message>) {
let mut result_vec = ~[]; let mut result_vec = ~[];
loop { loop {
@ -155,7 +155,7 @@ fn js_script_listener(to_parent : chan<~[~[u8]]>, from_parent : port<js_message>
} }
#[warn(no_non_implicitly_copyable_typarams)] #[warn(no_non_implicitly_copyable_typarams)]
fn build_dom(scope: NodeScope, stream: port<Token>) -> (Node, port<Stylesheet>, port<~[~[u8]]>) { fn build_dom(scope: NodeScope, stream: comm::port<Token>) -> (Node, comm::port<Stylesheet>, comm::port<~[~[u8]]>) {
// The current reference node. // The current reference node.
let mut cur_node = scope.new_node(Element(ElementData(~"html", ~HTMLDivElement))); let mut cur_node = scope.new_node(Element(ElementData(~"html", ~HTMLDivElement)));
// We will spawn a separate task to parse any css that is // We will spawn a separate task to parse any css that is

View file

@ -16,13 +16,15 @@ import std::cmp::fuzzy_eq;
import task::task_builder; import task::task_builder;
import vec::push; import vec::push;
type OSMain = chan<Msg>; import pipes::chan;
type OSMain = comm::chan<Msg>;
enum Msg { enum Msg {
BeginDrawing(chan<AzDrawTargetRef>), BeginDrawing(comm::chan<AzDrawTargetRef>),
Draw(chan<AzDrawTargetRef>, AzDrawTargetRef), Draw(comm::chan<AzDrawTargetRef>, AzDrawTargetRef),
AddKeyHandler(chan<()>), AddKeyHandler(pipes::chan<()>),
AddEventListener(chan<Event>), AddEventListener(comm::chan<Event>),
Exit Exit
} }
@ -36,12 +38,17 @@ fn OSMain() -> OSMain {
} }
fn mainloop(po: port<Msg>) { fn mainloop(po: port<Msg>) {
let key_handlers: @dvec<chan<()>> = @dvec(); let key_handlers: @dvec<pipes::chan<()>> = @dvec();
let event_listeners: @dvec<chan<Event>> = @dvec(); let event_listeners: @dvec<comm::chan<Event>> = @dvec();
glut::init(); glut::init();
glut::init_display_mode(glut::DOUBLE); glut::init_display_mode(glut::DOUBLE);
#macro[
[#move[x],
unsafe { let y <- *ptr::addr_of(x); y }]
];
let surfaces = @surface_set(); let surfaces = @surface_set();
let window = glut::create_window(~"Servo"); let window = glut::create_window(~"Servo");
@ -65,7 +72,7 @@ fn mainloop(po: port<Msg>) {
while po.peek() { while po.peek() {
alt po.recv() { alt po.recv() {
AddKeyHandler(key_ch) { AddKeyHandler(key_ch) {
key_handlers.push(key_ch); key_handlers.push(#move(key_ch));
} }
AddEventListener(event_listener) { AddEventListener(event_listener) {
event_listeners.push(event_listener); event_listeners.push(event_listener);
@ -131,13 +138,13 @@ Implementation to allow the osmain channel to be used as a graphics
sink for the renderer sink for the renderer
"] "]
impl OSMain of Sink for OSMain { impl OSMain of Sink for OSMain {
fn begin_drawing(next_dt: chan<AzDrawTargetRef>) { fn begin_drawing(next_dt: comm::chan<AzDrawTargetRef>) {
self.send(BeginDrawing(next_dt)) self.send(BeginDrawing(next_dt))
} }
fn draw(next_dt: chan<AzDrawTargetRef>, draw_me: AzDrawTargetRef) { fn draw(next_dt: comm::chan<AzDrawTargetRef>, draw_me: AzDrawTargetRef) {
self.send(Draw(next_dt, draw_me)) self.send(Draw(next_dt, draw_me))
} }
fn add_event_listener(listener: chan<Event>) { fn add_event_listener(listener: comm::chan<Event>) {
self.send(AddEventListener(listener)); self.send(AddEventListener(listener));
} }
} }
@ -153,7 +160,7 @@ type surface_set = {
} }
}; };
fn lend_surface(surfaces: surface_set, recvr: chan<AzDrawTargetRef>) { fn lend_surface(surfaces: surface_set, recvr: comm::chan<AzDrawTargetRef>) {
// We are in a position to lend out the surface? // We are in a position to lend out the surface?
assert surfaces.s1.have; assert surfaces.s1.have;
// Ok then take it // Ok then take it

View file

@ -114,4 +114,3 @@ mod opts;
mod engine; mod engine;
import servo_text = text; import servo_text = text;

View file

@ -5,6 +5,8 @@ import osmain::{OSMain, AddKeyHandler};
import opts::{Opts, Screen, Png}; import opts::{Opts, Screen, Png};
import engine::{Engine, LoadURLMsg}; import engine::{Engine, LoadURLMsg};
import pipes::port;
fn main(args: ~[~str]) { fn main(args: ~[~str]) {
run(opts::from_cmdline_args(args)) run(opts::from_cmdline_args(args))
} }
@ -35,16 +37,18 @@ fn run_pipeline_screen(urls: ~[~str]) {
let engine_chan = engine.start(); let engine_chan = engine.start();
// Send each file to render then wait for keypress // Send each file to render then wait for keypress
listen(|keypress_from_osmain| { let (keypress_to_engine, keypress_from_osmain) = pipes::stream();
osmain.send(AddKeyHandler(keypress_from_osmain)); osmain.send(AddKeyHandler(keypress_to_engine));
for urls.each |filename| { for urls.each |filename| {
#debug["master: Sending filename `%s`", filename]; #debug["master: Sending filename `%s`", filename];
engine_chan.send(LoadURLMsg(copy filename)); engine_chan.send(LoadURLMsg(copy filename));
#debug["master: Waiting for keypress"]; #debug["master: Waiting for keypress"];
keypress_from_osmain.recv(); alt keypress_from_osmain.try_recv() {
} some(*) { }
}); none { #error("keypress stream closed unexpectedly") }
};
}
// Shut everything down // Shut everything down
#debug["master: Shut down"]; #debug["master: Shut down"];