Source-Repo: https://github.com/servo/servo
Source-Revision: b9f103a879d2f6b59de9a29a2cf2d0a366133a9b
This commit is contained in:
Patrick Walton 2012-07-12 15:49:05 -07:00
Родитель 0575af237c
Коммит 173ae430f3
8 изменённых файлов: 104 добавлений и 47 удалений

Просмотреть файл

@ -7,14 +7,16 @@ export Content;
export ControlMsg, ExecuteMsg, ParseMsg, ExitMsg;
export PingMsg, PongMsg;
import comm::{port, chan, listen};
import comm::{port, chan, listen, select2};
import task::{spawn, spawn_listener};
import io::{read_whole_file, println};
import result::{ok, err};
import dom::base::NodeScope;
import dom::event::ResizeEvent;
import dom::rcu::WriterMethods;
import dom::style;
import gfx::renderer::Sink;
import parser::html_lexer::spawn_html_lexer_task;
import parser::css_builder::build_stylesheet;
import parser::html_builder::build_dom;
@ -25,6 +27,7 @@ import jsrt = js::rust::rt;
import js::rust::methods;
import js::global::{global_class, debug_fns};
import either::{left, right};
import result::extensions;
type Content = chan<ControlMsg>;
@ -53,13 +56,16 @@ fn join_layout(scope: NodeScope, layout: Layout) {
}
#[warn(no_non_implicitly_copyable_typarams)]
fn Content(layout: Layout) -> Content {
fn Content<S:Sink send copy>(layout: Layout, sink: S) -> Content {
spawn_listener::<ControlMsg>(|from_master| {
let event_port = port();
sink.add_event_listener(event_port.chan());
let scope = NodeScope();
let rt = jsrt();
loop {
alt from_master.recv() {
ParseMsg(filename) {
alt select2(from_master, event_port) {
left(ParseMsg(filename)) {
#debug["content: Received filename `%s` to parse", *filename];
// Note: we can parse the next document in parallel
@ -85,7 +91,7 @@ fn Content(layout: Layout) -> Content {
scope.reader_forked();
}
ExecuteMsg(filename) {
left(ExecuteMsg(filename)) {
#debug["content: Received filename `%s` to execute", *filename];
alt read_whole_file(*filename) {
@ -104,10 +110,14 @@ fn Content(layout: Layout) -> Content {
}
}
ExitMsg {
left(ExitMsg) {
layout.send(layout_task::ExitMsg);
break;
}
right(ResizeEvent(new_width, new_height)) {
#debug("content got resize event: %d, %d", new_width, new_height);
}
}
}
})

Просмотреть файл

@ -0,0 +1,4 @@
enum Event {
ResizeEvent(int, int)
}

Просмотреть файл

@ -5,46 +5,61 @@ import layout::layout_task;
import layout_task::Layout;
import content::{Content, ExecuteMsg, ParseMsg, ExitMsg};
type Engine = chan<Msg>;
class Engine<S:Sink send copy> {
let sink: S;
let renderer: Renderer;
let layout: Layout;
let content: Content;
new(sink: S) {
self.sink = sink;
let renderer = Renderer(sink);
let layout = Layout(renderer);
let content = Content(layout, sink);
self.renderer = renderer;
self.layout = layout;
self.content = content;
}
fn start() -> chan<Msg> {
do spawn_listener::<Msg> |request| {
while self.handle_request(request.recv()) {
// Go on...
}
}
}
fn handle_request(request: Msg) -> bool {
alt request {
LoadURLMsg(url) {
let url = copy url;
if (*url).ends_with(".js") {
self.content.send(ExecuteMsg(url))
} else {
self.content.send(ParseMsg(url))
}
ret true;
}
ExitMsg(sender) {
self.content.send(content::ExitMsg);
self.layout.send(layout_task::ExitMsg);
do listen |response_channel| {
self.renderer.send(renderer::ExitMsg(response_channel));
response_channel.recv();
}
sender.send(());
ret false;
}
}
}
}
enum Msg {
LoadURLMsg(~str),
ExitMsg(chan<()>)
}
fn Engine<S: Sink send copy>(sink: S) -> Engine {
spawn_listener::<Msg>(|request| {
// The renderer
let renderer = Renderer(sink);
// The layout task
let layout = Layout(renderer);
// The content task
let content = Content(layout);
loop {
alt request.recv() {
LoadURLMsg(url) {
let url = copy url;
if (*url).ends_with(".js") {
content.send(ExecuteMsg(url))
} else {
content.send(ParseMsg(url))
}
}
ExitMsg(sender) {
content.send(content::ExitMsg);
layout.send(layout_task::ExitMsg);
listen(|response_channel| {
renderer.send(renderer::ExitMsg(response_channel));
response_channel.recv();
});
sender.send(());
break;
}
}
}
})
}

Просмотреть файл

@ -23,6 +23,7 @@ import comm::chan;
import unsafe::reinterpret_cast;
import vec_from_buf = vec::unsafe::from_buf;
import ptr::addr_of;
import dom::event::Event;
type PngSink = chan<Msg>;
@ -39,6 +40,9 @@ impl PngSink of Sink for chan<Msg> {
fn draw(next_dt: chan<AzDrawTargetRef>, draw_me: AzDrawTargetRef) {
self.send(Draw(next_dt, draw_me))
}
fn add_event_listener(_listener: chan<Event>) {
// No events in this sink.
}
}
fn PngSink(output: chan<[u8]>) -> PngSink {

Просмотреть файл

@ -7,6 +7,7 @@ import azure::*;
import azure::bindgen::*;
import libc::size_t;
import text::text_run::TextRun;
import dom::event::{Event, ResizeEvent};
type Renderer = chan<Msg>;
@ -18,10 +19,13 @@ enum Msg {
#[doc = "
The interface used to by the renderer to aquire draw targets for
each rendered frame and submit them to be drawn to the display
FIXME: Change this name to Compositor.
"]
iface Sink {
fn begin_drawing(next_dt: chan<AzDrawTargetRef>);
fn draw(next_dt: chan<AzDrawTargetRef>, draw_me: AzDrawTargetRef);
fn add_event_listener(listener: chan<Event>);
}
fn Renderer<S: Sink send copy>(sink: S) -> chan<Msg> {

Просмотреть файл

@ -6,8 +6,10 @@ import azure::bindgen::*;
import azure::cairo;
import azure::cairo::bindgen::*;
import comm::*;
import dvec::{dvec, extensions};
import azure::cairo::cairo_surface_t;
import gfx::renderer::{Sink};
import dom::event::{Event, ResizeEvent};
import layers::ImageLayer;
import geom::size::Size2D;
import std::cmp::fuzzy_eq;
@ -18,6 +20,7 @@ enum Msg {
BeginDrawing(chan<AzDrawTargetRef>),
Draw(chan<AzDrawTargetRef>, AzDrawTargetRef),
AddKeyHandler(chan<()>),
AddEventListener(chan<Event>),
Exit
}
@ -32,6 +35,7 @@ fn OSMain() -> OSMain {
fn mainloop(po: port<Msg>) {
let mut key_handlers: [chan<()>] = [];
let event_listeners: @dvec<chan<Event>> = @dvec();
glut::init();
glut::init_display_mode(glut::DOUBLE);
@ -51,6 +55,13 @@ fn mainloop(po: port<Msg>) {
let scene = @mut layers::scene::Scene(layers::layers::ImageLayerKind(image_layer),
Size2D(800.0f32, 600.0f32));
do glut::reshape_func(window) |width, height| {
#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 int, height as int));
}
}
loop {
do glut::display_func() {
#debug("osmain: drawing to screen");
@ -66,6 +77,9 @@ fn mainloop(po: port<Msg>) {
AddKeyHandler(key_ch) {
key_handlers += [key_ch];
}
AddEventListener(event_listener) {
event_listeners.push(event_listener);
}
BeginDrawing(sender) {
lend_surface(surfaces, sender);
}
@ -107,6 +121,9 @@ impl OSMain of Sink for OSMain {
fn draw(next_dt: chan<AzDrawTargetRef>, draw_me: AzDrawTargetRef) {
self.send(Draw(next_dt, draw_me))
}
fn add_event_listener(listener: chan<Event>) {
self.send(AddEventListener(listener));
}
}
type surface_set = {

Просмотреть файл

@ -20,6 +20,7 @@ use layers;
mod dom {
mod base;
mod event;
mod rcu;
mod style;
}

Просмотреть файл

@ -32,6 +32,7 @@ fn run_pipeline_screen(urls: [str]) {
// Create a serve instance
let engine = Engine(osmain);
let engine_chan = engine.start();
// Send each file to render then wait for keypress
listen(|keypress_from_osmain| {
@ -39,7 +40,7 @@ fn run_pipeline_screen(urls: [str]) {
for urls.each |filename| {
#debug["master: Sending filename `%s`", filename];
engine.send(LoadURLMsg(~copy filename));
engine_chan.send(LoadURLMsg(~copy filename));
#debug["master: Waiting for keypress"];
keypress_from_osmain.recv();
}
@ -48,7 +49,7 @@ fn run_pipeline_screen(urls: [str]) {
// Shut everything down
#debug["master: Shut down"];
listen(|exit_response_from_engine| {
engine.send(engine::ExitMsg(exit_response_from_engine));
engine_chan.send(engine::ExitMsg(exit_response_from_engine));
exit_response_from_engine.recv();
});
osmain.send(osmain::Exit);
@ -65,8 +66,9 @@ fn run_pipeline_png(-url: str, outfile: str) {
listen(|pngdata_from_sink| {
let sink = PngSink(pngdata_from_sink);
let engine = Engine(sink);
let engine_chan = engine.start();
let url = copy url;
engine.send(LoadURLMsg(~url));
engine_chan.send(LoadURLMsg(~url));
alt buffered_file_writer(outfile) {
ok(writer) {
writer.write(pngdata_from_sink.recv())
@ -74,7 +76,7 @@ fn run_pipeline_png(-url: str, outfile: str) {
err(e) { fail e }
}
listen(|exit_response_from_engine| {
engine.send(engine::ExitMsg(exit_response_from_engine));
engine_chan.send(engine::ExitMsg(exit_response_from_engine));
exit_response_from_engine.recv();
});
sink.send(pngsink::Exit);