aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/components/main/compositing/mod.rs3
-rw-r--r--src/components/main/compositing/run.rs55
-rw-r--r--src/components/main/compositing/run_headless.rs6
-rw-r--r--src/components/main/constellation.rs102
-rw-r--r--src/components/main/layout/layout_task.rs26
-rw-r--r--src/components/main/pipeline.rs46
-rwxr-xr-xsrc/components/main/servo.rc32
-rw-r--r--src/components/msg/constellation_msg.rs9
-rw-r--r--src/components/script/dom/htmliframeelement.rs14
-rw-r--r--src/components/script/html/hubbub_html_parser.rs34
-rw-r--r--src/components/script/script_task.rs110
-rw-r--r--src/test/html/summit2.html1
12 files changed, 242 insertions, 196 deletions
diff --git a/src/components/main/compositing/mod.rs b/src/components/main/compositing/mod.rs
index 56472b895d1..9cf6df5f2aa 100644
--- a/src/components/main/compositing/mod.rs
+++ b/src/components/main/compositing/mod.rs
@@ -148,6 +148,7 @@ pub enum Msg {
pub struct CompositorTask {
opts: Opts,
port: Port<Msg>,
+ constellation_chan: ConstellationChan,
profiler_chan: ProfilerChan,
shutdown_chan: SharedChan<()>,
}
@@ -155,12 +156,14 @@ pub struct CompositorTask {
impl CompositorTask {
pub fn new(opts: Opts,
port: Port<Msg>,
+ constellation_chan: ConstellationChan,
profiler_chan: ProfilerChan,
shutdown_chan: Chan<()>)
-> CompositorTask {
CompositorTask {
opts: opts,
port: port,
+ constellation_chan: constellation_chan,
profiler_chan: profiler_chan,
shutdown_chan: SharedChan::new(shutdown_chan),
}
diff --git a/src/components/main/compositing/run.rs b/src/components/main/compositing/run.rs
index a498b7fc9b6..b8125665543 100644
--- a/src/components/main/compositing/run.rs
+++ b/src/components/main/compositing/run.rs
@@ -2,41 +2,35 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+use compositing::compositor_layer::CompositorLayer;
+use compositing::*;
use platform::{Application, Window};
-
use windowing::{ApplicationMethods, WindowEvent, WindowMethods};
use windowing::{IdleWindowEvent, ResizeWindowEvent, LoadUrlWindowEvent, MouseWindowEventClass};
use windowing::{ScrollWindowEvent, ZoomWindowEvent, NavigationWindowEvent, FinishedWindowEvent};
use windowing::{QuitWindowEvent, MouseWindowClickEvent, MouseWindowMouseDownEvent, MouseWindowMouseUpEvent};
-use servo_msg::constellation_msg::{ConstellationChan, NavigateMsg, ResizedWindowMsg, LoadUrlMsg};
-use servo_msg::constellation_msg;
-
use azure::azure_hl::SourceSurfaceMethods;
use azure::azure_hl;
-use std::comm::Port;
-use std::num::Orderable;
-use std::vec;
-use std::path::Path;
-use std::rt::io::timer::Timer;
+use extra::time::precise_time_s;
use geom::matrix::identity;
use geom::point::Point2D;
-use geom::size::Size2D;
use geom::rect::Rect;
+use geom::size::Size2D;
use layers::layers::{ContainerLayer, ContainerLayerKind};
use layers::rendergl;
use layers::scene::Scene;
use opengles::gl2;
use png;
-use servo_util::{time, url};
+use servo_msg::constellation_msg::{ConstellationChan, NavigateMsg, ResizedWindowMsg, LoadUrlMsg};
+use servo_msg::constellation_msg;
use servo_util::time::profile;
-
-use extra::future::Future;
-use extra::time::precise_time_s;
-
-use compositing::compositor_layer::CompositorLayer;
-
-use compositing::*;
+use servo_util::{time, url};
+use std::comm::Port;
+use std::num::Orderable;
+use std::path::Path;
+use std::rt::io::timer::Timer;
+use std::vec;
/// Starts the compositor, which listens for messages on the specified port.
pub fn run_compositor(compositor: &CompositorTask) {
@@ -63,7 +57,7 @@ pub fn run_compositor(compositor: &CompositorTask) {
// The root CompositorLayer
let mut compositor_layer: Option<CompositorLayer> = None;
- let mut constellation_chan: Option<ConstellationChan> = None;
+ let mut constellation_chan: ConstellationChan = compositor.constellation_chan.clone();
// Get BufferRequests from each layer.
let ask_for_tiles = || {
@@ -128,7 +122,7 @@ pub fn run_compositor(compositor: &CompositorTask) {
window_size.height as uint);
new_constellation_chan.send(ResizedWindowMsg(window_size));
- constellation_chan = Some(new_constellation_chan);
+ constellation_chan = new_constellation_chan;
}
GetGraphicsMetadata(chan) => chan.send(Some(azure_hl::current_graphics_metadata())),
@@ -252,10 +246,7 @@ pub fn run_compositor(compositor: &CompositorTask) {
if window_size != new_size {
debug!("osmain: window resized to {:u}x{:u}", width, height);
window_size = new_size;
- match constellation_chan {
- Some(ref chan) => chan.send(ResizedWindowMsg(new_size)),
- None => error!("Compositor: Received resize event without initialized layout chan"),
- }
+ constellation_chan.send(ResizedWindowMsg(new_size))
} else {
debug!("osmain: dropping window resize since size is still {:u}x{:u}", width, height);
}
@@ -267,12 +258,8 @@ pub fn run_compositor(compositor: &CompositorTask) {
Some(ref layer) => layer.pipeline.id.clone(),
None => fail!("Compositor: Received LoadUrlWindowEvent without initialized compositor layers"),
};
- match constellation_chan {
- Some(ref chan) => chan.send(LoadUrlMsg(root_pipeline_id,
- url::make_url(url_string.to_str(), None),
- Future::from_value(window_size))),
- None => error!("Compositor: Received loadurl event without initialized layout chan"),
- }
+ constellation_chan.send(LoadUrlMsg(root_pipeline_id,
+ url::make_url(url_string.to_str(), None)))
}
MouseWindowEventClass(mouse_window_event) => {
@@ -327,10 +314,7 @@ pub fn run_compositor(compositor: &CompositorTask) {
windowing::Forward => constellation_msg::Forward,
windowing::Back => constellation_msg::Back,
};
- match constellation_chan {
- Some(ref chan) => chan.send(NavigateMsg(direction)),
- None => error!("Compositor: Received navigation event without initialized layout chan"),
- }
+ constellation_chan.send(NavigateMsg(direction))
}
FinishedWindowEvent => {
@@ -403,6 +387,9 @@ pub fn run_compositor(compositor: &CompositorTask) {
if exit { done = true; }
};
+ // Tell the constellation about the initial window size.
+ constellation_chan.send(ResizedWindowMsg(window_size));
+
// Enter the main event loop.
let mut tm = Timer::new().unwrap();
while !done {
diff --git a/src/components/main/compositing/run_headless.rs b/src/components/main/compositing/run_headless.rs
index 29a8e1db96c..9c7b8c3482d 100644
--- a/src/components/main/compositing/run_headless.rs
+++ b/src/components/main/compositing/run_headless.rs
@@ -4,11 +4,17 @@
use compositing::*;
+use geom::size::Size2D;
+use servo_msg::constellation_msg::ResizedWindowMsg;
+
/// Starts the compositor, which listens for messages on the specified port.
///
/// This is the null compositor which doesn't draw anything to the screen.
/// It's intended for headless testing.
pub fn run_compositor(compositor: &CompositorTask) {
+ // Tell the constellation about the initial fake size.
+ compositor.constellation_chan.send(ResizedWindowMsg(Size2D(640u, 480u)));
+
loop {
match compositor.port.recv() {
Exit => break,
diff --git a/src/components/main/constellation.rs b/src/components/main/constellation.rs
index 43ca99a62f6..bdd1b87c8d5 100644
--- a/src/components/main/constellation.rs
+++ b/src/components/main/constellation.rs
@@ -4,28 +4,27 @@
use compositing::{CompositorChan, SetIds, SetLayerClipRect};
-use std::comm;
-use std::comm::Port;
-use std::task::spawn_with;
-use geom::size::Size2D;
+use extra::url::Url;
use geom::rect::Rect;
+use geom::size::Size2D;
use gfx::opts::Opts;
use pipeline::Pipeline;
+use script::script_task::{ResizeMsg, ResizeInactiveMsg};
use servo_msg::constellation_msg::{ConstellationChan, ExitMsg, FailureMsg, FrameRectMsg};
-use servo_msg::constellation_msg::{IFrameSandboxState, InitLoadUrlMsg, LoadIframeUrlMsg, LoadUrlMsg};
-use servo_msg::constellation_msg::{Msg, NavigateMsg, NavigationType, IFrameUnsandboxed};
+use servo_msg::constellation_msg::{IFrameSandboxState, IFrameUnsandboxed, InitLoadUrlMsg};
+use servo_msg::constellation_msg::{LoadIframeUrlMsg, LoadUrlMsg, Msg, NavigateMsg, NavigationType};
use servo_msg::constellation_msg::{PipelineId, RendererReadyMsg, ResizedWindowMsg, SubpageId};
use servo_msg::constellation_msg;
-use script::script_task::{ResizeMsg, ResizeInactiveMsg};
use servo_net::image_cache_task::{ImageCacheTask, ImageCacheTaskClient};
use servo_net::resource_task::ResourceTask;
use servo_net::resource_task;
use servo_util::time::ProfilerChan;
use servo_util::url::make_url;
+use std::comm::Port;
+use std::comm;
use std::hashmap::{HashMap, HashSet};
+use std::task::spawn_with;
use std::util::replace;
-use extra::url::Url;
-use extra::future::Future;
/// Maintains the pipelines and navigation context and grants permission to composite
pub struct Constellation {
@@ -249,18 +248,27 @@ impl NavigationContext {
}
impl Constellation {
- pub fn start(compositor_chan: CompositorChan,
+ pub fn start(constellation_port: Port<Msg>,
+ constellation_chan: ConstellationChan,
+ compositor_chan: CompositorChan,
opts: &Opts,
resource_task: ResourceTask,
image_cache_task: ImageCacheTask,
- profiler_chan: ProfilerChan)
- -> ConstellationChan {
- let (constellation_port, constellation_chan) = special_stream!(ConstellationChan);
- do spawn_with((constellation_port, constellation_chan.clone(),
- compositor_chan, resource_task, image_cache_task,
- profiler_chan, opts.clone()))
- |(constellation_port, constellation_chan, compositor_chan, resource_task,
- image_cache_task, profiler_chan, opts)| {
+ profiler_chan: ProfilerChan) {
+ do spawn_with((constellation_port,
+ constellation_chan.clone(),
+ compositor_chan,
+ resource_task,
+ image_cache_task,
+ profiler_chan,
+ opts.clone()))
+ |(constellation_port,
+ constellation_chan,
+ compositor_chan,
+ resource_task,
+ image_cache_task,
+ profiler_chan,
+ opts)| {
let mut constellation = Constellation {
chan: constellation_chan,
request_port: constellation_port,
@@ -278,7 +286,6 @@ impl Constellation {
};
constellation.run();
}
- constellation_chan
}
fn run(&mut self) {
@@ -324,32 +331,38 @@ impl Constellation {
}
// This should only be called once per constellation, and only by the browser
InitLoadUrlMsg(url) => {
+ debug!("constellation got init load URL message");
self.handle_init_load(url);
}
- // A layout assigned a size and position to a subframe. This needs to be reflected by all
- // frame trees in the navigation context containing the subframe.
+ // A layout assigned a size and position to a subframe. This needs to be reflected by
+ // all frame trees in the navigation context containing the subframe.
FrameRectMsg(pipeline_id, subpage_id, rect) => {
+ debug!("constellation got frame rect message");
self.handle_frame_rect_msg(pipeline_id, subpage_id, rect);
}
- LoadIframeUrlMsg(url, source_pipeline_id, subpage_id, size_future, sandbox) => {
- self.handle_load_iframe_url_msg(url, source_pipeline_id, subpage_id, size_future, sandbox);
+ LoadIframeUrlMsg(url, source_pipeline_id, subpage_id, sandbox) => {
+ debug!("constellation got iframe URL load message");
+ self.handle_load_iframe_url_msg(url, source_pipeline_id, subpage_id, sandbox);
}
// Load a new page, usually -- but not always -- from a mouse click or typed url
// If there is already a pending page (self.pending_frames), it will not be overridden;
// However, if the id is not encompassed by another change, it will be.
- LoadUrlMsg(source_id, url, size_future) => {
- self.handle_load_url_msg(source_id, url, size_future);
+ LoadUrlMsg(source_id, url) => {
+ debug!("constellation got URL load message");
+ self.handle_load_url_msg(source_id, url);
}
// Handle a forward or back request
NavigateMsg(direction) => {
+ debug!("constellation got navigation message");
self.handle_navigate_msg(direction);
}
// Notification that rendering has finished and is requesting permission to paint.
RendererReadyMsg(pipeline_id) => {
+ debug!("constellation got renderer ready message");
self.handle_renderer_ready_msg(pipeline_id);
}
-
ResizedWindowMsg(new_size) => {
+ debug!("constellation got window resize message");
self.handle_resized_window_msg(new_size);
}
}
@@ -375,8 +388,7 @@ impl Constellation {
self.image_cache_task.clone(),
self.resource_task.clone(),
self.profiler_chan.clone(),
- self.opts.clone(),
- Future::from_value(self.window_size));
+ self.opts.clone());
let failure = ~"about:failure";
let url = make_url(failure, None);
pipeline.load(url);
@@ -397,11 +409,10 @@ impl Constellation {
self.image_cache_task.clone(),
self.resource_task.clone(),
self.profiler_chan.clone(),
- self.opts.clone(),
- Future::from_value(self.window_size));
+ self.opts.clone());
pipeline.load(url);
- self.pending_frames.push(FrameChange{
+ self.pending_frames.push(FrameChange {
before: None,
after: @mut FrameTree {
pipeline: pipeline,
@@ -476,7 +487,6 @@ impl Constellation {
url: Url,
source_pipeline_id: PipelineId,
subpage_id: SubpageId,
- size_future: Future<Size2D<uint>>,
sandbox: IFrameSandboxState) {
// A message from the script associated with pipeline_id that it has
// parsed an iframe during html parsing. This iframe will result in a
@@ -524,8 +534,7 @@ impl Constellation {
self.image_cache_task.clone(),
self.profiler_chan.clone(),
self.opts.clone(),
- source_pipeline,
- size_future)
+ source_pipeline)
} else {
debug!("Constellation: loading cross-origin iframe at {:?}", url);
// Create a new script task if not same-origin url's
@@ -536,8 +545,7 @@ impl Constellation {
self.image_cache_task.clone(),
self.resource_task.clone(),
self.profiler_chan.clone(),
- self.opts.clone(),
- size_future)
+ self.opts.clone())
};
debug!("Constellation: sending load msg to pipeline {:?}", pipeline.id);
@@ -556,7 +564,7 @@ impl Constellation {
self.pipelines.insert(pipeline.id, pipeline);
}
- fn handle_load_url_msg(&mut self, source_id: PipelineId, url: Url, size_future: Future<Size2D<uint>>) {
+ fn handle_load_url_msg(&mut self, source_id: PipelineId, url: Url) {
debug!("Constellation: received message to load {:s}", url.to_str());
// Make sure no pending page would be overridden.
let source_frame = self.current_frame().get_ref().find(source_id).expect(
@@ -590,8 +598,7 @@ impl Constellation {
self.image_cache_task.clone(),
self.resource_task.clone(),
self.profiler_chan.clone(),
- self.opts.clone(),
- size_future);
+ self.opts.clone());
pipeline.load(url);
@@ -723,13 +730,16 @@ impl Constellation {
}
}
}
- self.grant_paint_permission(next_frame_tree, frame_change.navigation_type);
+
+ self.grant_paint_permission(next_frame_tree, frame_change.navigation_type);
}
}
+ /// Called when the window is resized.
fn handle_resized_window_msg(&mut self, new_size: Size2D<uint>) {
let mut already_seen = HashSet::new();
for &@FrameTree { pipeline: pipeline, _ } in self.current_frame().iter() {
+ debug!("constellation sending resize message to active frame");
pipeline.script_chan.send(ResizeMsg(pipeline.id, new_size));
already_seen.insert(pipeline.id);
}
@@ -737,10 +747,22 @@ impl Constellation {
.chain(self.navigation_context.next.iter()) {
let pipeline = &frame_tree.pipeline;
if !already_seen.contains(&pipeline.id) {
+ debug!("constellation sending resize message to inactive frame");
pipeline.script_chan.send(ResizeInactiveMsg(pipeline.id, new_size));
already_seen.insert(pipeline.id);
}
}
+
+ // If there are any pending outermost frames, then tell them to resize. (This is how the
+ // initial window size gets sent to the first page loaded, giving it permission to reflow.)
+ for change in self.pending_frames.iter() {
+ let frame_tree = change.after;
+ if frame_tree.parent.is_none() {
+ debug!("constellation sending resize message to pending outer frame");
+ frame_tree.pipeline.script_chan.send(ResizeMsg(frame_tree.pipeline.id, new_size))
+ }
+ }
+
self.window_size = new_size;
}
diff --git a/src/components/main/layout/layout_task.rs b/src/components/main/layout/layout_task.rs
index 3519a782607..ec82722afa0 100644
--- a/src/components/main/layout/layout_task.rs
+++ b/src/components/main/layout/layout_task.rs
@@ -295,7 +295,9 @@ impl LayoutTask {
}
}
PrepareToExitMsg(response_chan) => {
- self.prepare_to_exit(response_chan)
+ debug!("layout: PrepareToExitMsg received");
+ self.prepare_to_exit(response_chan);
+ return false
}
ExitNowMsg => {
debug!("layout: ExitNowMsg received");
@@ -312,15 +314,21 @@ impl LayoutTask {
/// response channel.
fn prepare_to_exit(&mut self, response_chan: Chan<()>) {
response_chan.send(());
- match self.port.recv() {
- ReapLayoutDataMsg(dead_layout_data) => {
- unsafe {
- self.handle_reap_layout_data(dead_layout_data)
+ loop {
+ match self.port.recv() {
+ ReapLayoutDataMsg(dead_layout_data) => {
+ unsafe {
+ self.handle_reap_layout_data(dead_layout_data)
+ }
+ }
+ ExitNowMsg => {
+ self.exit_now();
+ break
+ }
+ _ => {
+ fail!("layout: message that wasn't `ExitNowMsg` received after \
+ `PrepareToExitMsg`")
}
- }
- ExitNowMsg => self.exit_now(),
- _ => {
- fail!("layout: message that wasn't `ExitNowMsg` received after `PrepareToExitMsg`")
}
}
}
diff --git a/src/components/main/pipeline.rs b/src/components/main/pipeline.rs
index 77ac8741787..e277beccbd9 100644
--- a/src/components/main/pipeline.rs
+++ b/src/components/main/pipeline.rs
@@ -2,23 +2,22 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-use extra::url::Url;
use compositing::CompositorChan;
-use gfx::render_task::{RenderChan, RenderTask};
-use gfx::render_task::{PaintPermissionGranted, PaintPermissionRevoked};
-use gfx::opts::Opts;
use layout::layout_task::LayoutTask;
+
+use extra::url::Url;
+use gfx::opts::Opts;
+use gfx::render_task::{PaintPermissionGranted, PaintPermissionRevoked};
+use gfx::render_task::{RenderChan, RenderTask};
+use script::dom::node::AbstractNode;
use script::layout_interface::LayoutChan;
use script::script_task::LoadMsg;
-use servo_msg::constellation_msg::{ConstellationChan, FailureMsg, PipelineId, SubpageId};
-use script::dom::node::AbstractNode;
use script::script_task::{AttachLayoutMsg, NewLayoutInfo, ScriptTask, ScriptChan};
use script::script_task;
+use servo_msg::constellation_msg::{ConstellationChan, FailureMsg, PipelineId, SubpageId};
use servo_net::image_cache_task::ImageCacheTask;
use servo_net::resource_task::ResourceTask;
use servo_util::time::ProfilerChan;
-use geom::size::Size2D;
-use extra::future::Future;
use std::task;
/// A uniquely-identifiable pipeline of script task, layout task, and render task.
@@ -34,7 +33,8 @@ pub struct Pipeline {
}
impl Pipeline {
- /// Starts a render task, layout task, and script task. Returns the channels wrapped in a struct.
+ /// Starts a render task, layout task, and script task. Returns the channels wrapped in a
+ /// struct.
pub fn with_script(id: PipelineId,
subpage_id: Option<SubpageId>,
constellation_chan: ConstellationChan,
@@ -42,8 +42,8 @@ impl Pipeline {
image_cache_task: ImageCacheTask,
profiler_chan: ProfilerChan,
opts: Opts,
- script_pipeline: &Pipeline,
- size_future: Future<Size2D<uint>>) -> Pipeline {
+ script_pipeline: &Pipeline)
+ -> Pipeline {
let (layout_port, layout_chan) = special_stream!(LayoutChan);
let (render_port, render_chan) = special_stream!(RenderChan);
@@ -67,7 +67,6 @@ impl Pipeline {
old_id: script_pipeline.id.clone(),
new_id: id,
layout_chan: layout_chan.clone(),
- size_future: size_future,
};
script_pipeline.script_chan.send(AttachLayoutMsg(new_layout_info));
@@ -86,9 +85,8 @@ impl Pipeline {
image_cache_task: ImageCacheTask,
resource_task: ResourceTask,
profiler_chan: ProfilerChan,
- opts: Opts,
- size: Future<Size2D<uint>>) -> Pipeline {
-
+ opts: Opts)
+ -> Pipeline {
let (script_port, script_chan) = special_stream!(ScriptChan);
let (layout_port, layout_chan) = special_stream!(LayoutChan);
let (render_port, render_chan) = special_stream!(RenderChan);
@@ -106,9 +104,15 @@ impl Pipeline {
let task_port = supervised_task.future_result();
supervised_task.supervised();
- spawn_with!(supervised_task, [script_port, resource_task, size, render_port,
- layout_port, constellation_chan, image_cache_task,
- profiler_chan], {
+ spawn_with!(supervised_task, [
+ script_port,
+ resource_task,
+ render_port,
+ layout_port,
+ constellation_chan,
+ image_cache_task,
+ profiler_chan
+ ], {
ScriptTask::create(id,
compositor_chan.clone(),
layout_chan.clone(),
@@ -116,8 +120,7 @@ impl Pipeline {
script_chan.clone(),
constellation_chan.clone(),
resource_task,
- image_cache_task.clone(),
- size);
+ image_cache_task.clone());
RenderTask::create(id,
render_port,
@@ -187,8 +190,7 @@ impl Pipeline {
}
pub fn exit(&self) {
- // Script task handles shutting down layout,
- // and layout handles shutting down the renderer.
+ // Script task handles shutting down layout, and layout handles shutting down the renderer.
self.script_chan.try_send(script_task::ExitPipelineMsg(self.id));
}
}
diff --git a/src/components/main/servo.rc b/src/components/main/servo.rc
index f286368b332..a19c0ba6dcb 100755
--- a/src/components/main/servo.rc
+++ b/src/components/main/servo.rc
@@ -41,7 +41,7 @@ extern mod core_text = "rust-core-text";
use compositing::{CompositorChan, CompositorTask};
use constellation::Constellation;
-use servo_msg::constellation_msg::{ExitMsg, InitLoadUrlMsg};
+use servo_msg::constellation_msg::{ConstellationChan, ExitMsg, InitLoadUrlMsg};
#[cfg(not(test))]
use gfx::opts;
@@ -127,21 +127,32 @@ fn run(opts: Opts) {
let (shutdown_port, shutdown_chan) = comm::stream();
let (profiler_port, profiler_chan) = special_stream!(ProfilerChan);
let (compositor_port, compositor_chan) = special_stream!(CompositorChan);
+ let (constellation_port, constellation_chan) = special_stream!(ConstellationChan);
Profiler::create(profiler_port, profiler_chan.clone(), opts.profiler_period);
- do spawn_with((profiler_chan.clone(), compositor_chan, opts.clone()))
- |(profiler_chan, compositor_chan, opts)| {
-
+ do spawn_with((constellation_port,
+ constellation_chan.clone(),
+ profiler_chan.clone(),
+ compositor_chan,
+ opts.clone()))
+ |(constellation_port,
+ constellation_chan,
+ profiler_chan,
+ compositor_chan,
+ opts)| {
let opts = &opts;
+
// Create a Servo instance.
let resource_task = ResourceTask();
let image_cache_task = ImageCacheTask(resource_task.clone());
- let constellation_chan = Constellation::start(compositor_chan,
- opts,
- resource_task,
- image_cache_task,
- profiler_chan.clone());
+ Constellation::start(constellation_port,
+ constellation_chan.clone(),
+ compositor_chan,
+ opts,
+ resource_task,
+ image_cache_task,
+ profiler_chan.clone());
// Send the URL command to the constellation.
for filename in opts.urls.iter() {
@@ -158,11 +169,12 @@ fn run(opts: Opts) {
exit_response_from_constellation.recv();
}
-
let compositor_task = CompositorTask::new(opts,
compositor_port,
+ constellation_chan,
profiler_chan,
shutdown_chan);
+
debug!("preparing to enter main loop");
compositor_task.run();
}
diff --git a/src/components/msg/constellation_msg.rs b/src/components/msg/constellation_msg.rs
index d24619fd9af..5c91b329379 100644
--- a/src/components/msg/constellation_msg.rs
+++ b/src/components/msg/constellation_msg.rs
@@ -5,11 +5,10 @@
//! The high-level interface from script to constellation. Using this abstract interface helps reduce
/// coupling between these two components
-use std::comm::{Chan, SharedChan};
use extra::url::Url;
-use extra::future::Future;
-use geom::size::Size2D;
use geom::rect::Rect;
+use geom::size::Size2D;
+use std::comm::{Chan, SharedChan};
#[deriving(Clone)]
pub struct ConstellationChan(SharedChan<Msg>);
@@ -32,8 +31,8 @@ pub enum Msg {
FailureMsg(PipelineId, Option<SubpageId>),
InitLoadUrlMsg(Url),
FrameRectMsg(PipelineId, SubpageId, Rect<f32>),
- LoadUrlMsg(PipelineId, Url, Future<Size2D<uint>>),
- LoadIframeUrlMsg(Url, PipelineId, SubpageId, Future<Size2D<uint>>, IFrameSandboxState),
+ LoadUrlMsg(PipelineId, Url),
+ LoadIframeUrlMsg(Url, PipelineId, SubpageId, IFrameSandboxState),
NavigateMsg(NavigationDirection),
RendererReadyMsg(PipelineId),
ResizedWindowMsg(Size2D<uint>),
diff --git a/src/components/script/dom/htmliframeelement.rs b/src/components/script/dom/htmliframeelement.rs
index 73172cb0ad8..7f39cfa58d8 100644
--- a/src/components/script/dom/htmliframeelement.rs
+++ b/src/components/script/dom/htmliframeelement.rs
@@ -9,15 +9,11 @@ use dom::element::HTMLIframeElementTypeId;
use dom::htmlelement::HTMLElement;
use dom::node::{AbstractNode, Node, ScriptView};
use dom::windowproxy::WindowProxy;
-use geom::size::Size2D;
-use geom::rect::Rect;
+use extra::url::Url;
+use geom::rect::Rect;
use servo_msg::constellation_msg::{ConstellationChan, FrameRectMsg, PipelineId, SubpageId};
-
use std::ascii::StrAsciiExt;
-use std::comm::ChanOne;
-use extra::url::Url;
-use std::util::replace;
enum SandboxAllowance {
AllowNothing = 0x00,
@@ -39,17 +35,11 @@ pub struct HTMLIFrameElement {
struct IFrameSize {
pipeline_id: PipelineId,
subpage_id: SubpageId,
- future_chan: Option<ChanOne<Size2D<uint>>>,
constellation_chan: ConstellationChan,
}
impl IFrameSize {
pub fn set_rect(&mut self, rect: Rect<f32>) {
- let future_chan = replace(&mut self.future_chan, None);
- do future_chan.map |future_chan| {
- let Size2D { width, height } = rect.size;
- future_chan.send(Size2D(width as uint, height as uint));
- };
self.constellation_chan.send(FrameRectMsg(self.pipeline_id, self.subpage_id, rect));
}
}
diff --git a/src/components/script/html/hubbub_html_parser.rs b/src/components/script/html/hubbub_html_parser.rs
index b36e1d60cf2..e73d1205950 100644
--- a/src/components/script/html/hubbub_html_parser.rs
+++ b/src/components/script/html/hubbub_html_parser.rs
@@ -12,26 +12,24 @@ use dom::namespace;
use dom::node::{AbstractNode, ElementNodeTypeId, ScriptView};
use dom::types::*;
use html::cssparse::{InlineProvenance, StylesheetProvenance, UrlProvenance, spawn_css_parser};
-use js::jsapi::JSContext;
-use style::Stylesheet;
use script_task::page_from_context;
-use std::cast;
-use std::cell::Cell;
-use std::comm;
-use std::comm::{Port, SharedChan};
-use std::str;
-use std::str::eq_slice;
-use std::from_str::FromStr;
+use extra::url::Url;
use hubbub::hubbub;
+use js::jsapi::JSContext;
use servo_msg::constellation_msg::{ConstellationChan, SubpageId};
use servo_net::image_cache_task::ImageCacheTask;
use servo_net::resource_task::{Load, Payload, Done, ResourceTask, load_whole_resource};
use servo_util::tree::{TreeNodeRef, ElementLike};
use servo_util::url::make_url;
-use extra::future::Future;
-use extra::url::Url;
-use geom::size::Size2D;
+use std::cast;
+use std::cell::Cell;
+use std::comm::{Port, SharedChan};
+use std::comm;
+use std::from_str::FromStr;
+use std::str::eq_slice;
+use std::str;
+use style::Stylesheet;
macro_rules! handle_element(
($document: expr,
@@ -67,7 +65,7 @@ enum JSMessage {
/// Messages generated by the HTML parser upon discovery of additional resources
pub enum HtmlDiscoveryMessage {
HtmlDiscoveredStyle(Stylesheet),
- HtmlDiscoveredIFrame((Url, SubpageId, Future<Size2D<uint>>, bool)),
+ HtmlDiscoveredIFrame((Url, SubpageId, bool)),
HtmlDiscoveredScript(JSResult)
}
@@ -374,10 +372,6 @@ pub fn parse_html(cx: *JSContext,
let iframe_url = make_url(src.clone(), Some(url2.clone()));
iframe_element.frame = Some(iframe_url.clone());
- // Size future
- let (port, chan) = comm::oneshot();
- let size_future = Future::from_port(port);
-
// Subpage Id
let subpage_id = next_subpage_id.take();
next_subpage_id.put_back(SubpageId(*subpage_id + 1));
@@ -391,11 +385,11 @@ pub fn parse_html(cx: *JSContext,
iframe_element.size = Some(IFrameSize {
pipeline_id: pipeline_id,
subpage_id: subpage_id,
- future_chan: Some(chan),
constellation_chan: constellation_chan.clone(),
});
- iframe_chan.send(HtmlDiscoveredIFrame((iframe_url, subpage_id,
- size_future, sandboxed)));
+ iframe_chan.send(HtmlDiscoveredIFrame((iframe_url,
+ subpage_id,
+ sandboxed)));
}
}
}
diff --git a/src/components/script/script_task.rs b/src/components/script/script_task.rs
index b77b383f4ed..4676639a6a4 100644
--- a/src/components/script/script_task.rs
+++ b/src/components/script/script_task.rs
@@ -27,11 +27,9 @@ use layout_interface::ContentChangedDocumentDamage;
use layout_interface;
use dom::node::ScriptView;
-use extra::future::Future;
use extra::url::Url;
-use std::str::eq_slice;
-use geom::size::Size2D;
use geom::point::Point2D;
+use geom::size::Size2D;
use js::JSVAL_NULL;
use js::global::debug_fns;
use js::glue::RUST_JSVAL_TO_OBJECT;
@@ -53,6 +51,7 @@ use std::cell::Cell;
use std::comm::{Port, SharedChan};
use std::comm;
use std::ptr;
+use std::str::eq_slice;
use std::task::{spawn_sched, SingleThreaded};
use std::util::replace;
@@ -84,7 +83,6 @@ pub struct NewLayoutInfo {
old_id: PipelineId,
new_id: PipelineId,
layout_chan: LayoutChan,
- size_future: Future<Size2D<uint>>,
}
/// Encapsulates external communication with the script task.
@@ -118,8 +116,8 @@ pub struct Page {
/// What parts of the document are dirty, if any.
damage: Option<DocumentDamage>,
- /// The current size of the window, in pixels.
- window_size: Future<Size2D<uint>>,
+ /// The current size of the window, in pixels. If `None`, we do not know the window size yet.
+ window_size: Option<Size2D<uint>>,
js_info: Option<JSPageInfo>,
@@ -148,7 +146,7 @@ pub struct PageTreeIterator<'self> {
}
impl PageTree {
- fn new(id: PipelineId, layout_chan: LayoutChan, size_future: Future<Size2D<uint>>) -> PageTree {
+ fn new(id: PipelineId, layout_chan: LayoutChan) -> PageTree {
PageTree {
page: @mut Page {
id: id,
@@ -156,7 +154,7 @@ impl PageTree {
layout_chan: layout_chan,
layout_join_port: None,
damage: None,
- window_size: size_future,
+ window_size: None,
js_info: None,
url: None,
next_subpage_id: SubpageId(0),
@@ -280,18 +278,32 @@ impl Page {
response_port.recv()
}
- /// This method will wait until the layout task has completed its current action, join the
- /// layout task, and then request a new layout run. It won't wait for the new layout
- /// computation to finish.
+ /// Reflows the page if it's possible to do so. This method will wait until the layout task has
+ /// completed its current action, join the layout task, and then request a new layout run. It
+ /// won't wait for the new layout computation to finish.
+ ///
+ /// If there is no window size yet, the page is presumed invisible and no reflow is performed.
///
/// This function fails if there is no root frame.
- pub fn reflow(&mut self, goal: ReflowGoal, script_chan: ScriptChan, compositor: @ScriptListener) {
+ pub fn reflow(&mut self,
+ goal: ReflowGoal,
+ script_chan: ScriptChan,
+ compositor: @ScriptListener) {
let root = match self.frame {
None => return,
Some(ref frame) => {
frame.document.document().GetDocumentElement()
}
};
+
+ let window_size = match self.window_size {
+ None => {
+ debug!("not reflowing due to lack of a window size");
+ return
+ }
+ Some(window_size) => window_size,
+ };
+
match root {
None => {},
Some(root) => {
@@ -314,7 +326,7 @@ impl Page {
document_root: root,
url: self.url.get_ref().first().clone(),
goal: goal,
- window_size: self.window_size.get(),
+ window_size: window_size,
script_chan: script_chan,
script_join_chan: join_chan,
damage: replace(&mut self.damage, None).unwrap(),
@@ -329,8 +341,8 @@ impl Page {
}
pub fn initialize_js_info(&mut self, js_context: @Cx, global: *JSObject) {
- // Note that the order that these variables are initialized is _not_ arbitrary. Switching them around
- // can -- and likely will -- lead to things breaking.
+ // Note that the order that these variables are initialized is _not_ arbitrary. Switching
+ // them around can -- and likely will -- lead to things breaking.
js_context.set_default_options_and_version();
js_context.set_logging_error_reporter();
@@ -425,13 +437,12 @@ impl ScriptTask {
chan: ScriptChan,
constellation_chan: ConstellationChan,
resource_task: ResourceTask,
- img_cache_task: ImageCacheTask,
- initial_size: Future<Size2D<uint>>)
+ img_cache_task: ImageCacheTask)
-> @mut ScriptTask {
let js_runtime = js::rust::rt();
let script_task = @mut ScriptTask {
- page_tree: PageTree::new(id, layout_chan, initial_size),
+ page_tree: PageTree::new(id, layout_chan),
image_cache_task: img_cache_task,
resource_task: resource_task,
@@ -463,25 +474,33 @@ impl ScriptTask {
chan: ScriptChan,
constellation_chan: ConstellationChan,
resource_task: ResourceTask,
- image_cache_task: ImageCacheTask,
- initial_size: Future<Size2D<uint>>) {
- let parms = Cell::new((compositor, layout_chan, port, chan, constellation_chan,
- resource_task, image_cache_task, initial_size));
+ image_cache_task: ImageCacheTask) {
+ let parms = Cell::new((compositor,
+ layout_chan,
+ port,
+ chan,
+ constellation_chan,
+ resource_task,
+ image_cache_task));
// Since SpiderMonkey is blocking it needs to run in its own thread.
// If we don't do this then we'll just end up with a bunch of SpiderMonkeys
// starving all the other tasks.
do spawn_sched(SingleThreaded) {
- let (compositor, layout_chan, port, chan, constellation_chan,
- resource_task, image_cache_task, initial_size) = parms.take();
+ let (compositor,
+ layout_chan,
+ port,
+ chan,
+ constellation_chan,
+ resource_task,
+ image_cache_task) = parms.take();
let script_task = ScriptTask::new(id,
- @compositor as @ScriptListener,
- layout_chan,
- port,
- chan,
- constellation_chan,
- resource_task,
- image_cache_task,
- initial_size);
+ @compositor as @ScriptListener,
+ layout_chan,
+ port,
+ chan,
+ constellation_chan,
+ resource_task,
+ image_cache_task);
script_task.start();
}
}
@@ -512,6 +531,7 @@ impl ScriptTask {
let event = self.port.recv();
match event {
ResizeMsg(id, size) => {
+ debug!("script got resize message");
let page = self.page_tree.find(id).expect("resize sent to nonexistent pipeline").page;
page.resize_event = Some(size);
}
@@ -538,7 +558,10 @@ impl ScriptTask {
ReflowCompleteMsg(id, reflow_id) => self.handle_reflow_complete_msg(id, reflow_id),
ResizeInactiveMsg(id, new_size) => self.handle_resize_inactive_msg(id, new_size),
ExitPipelineMsg(id) => if self.handle_exit_pipeline_msg(id) { return false },
- ExitWindowMsg(id) => if self.handle_exit_window_msg(id) { return false },
+ ExitWindowMsg(id) => {
+ self.handle_exit_window_msg(id);
+ return false
+ },
ResizeMsg(*) => fail!("should have handled ResizeMsg already"),
}
}
@@ -551,14 +574,13 @@ impl ScriptTask {
let NewLayoutInfo {
old_id,
new_id,
- layout_chan,
- size_future
+ layout_chan
} = new_layout_info;
let parent_page_tree = self.page_tree.find(old_id).expect("ScriptTask: received a layout
whose parent has a PipelineId which does not correspond to a pipeline in the script
task's page tree. This is a bug.");
- let new_page_tree = PageTree::new(new_id, layout_chan, size_future);
+ let new_page_tree = PageTree::new(new_id, layout_chan);
parent_page_tree.inner.push(new_page_tree);
}
@@ -612,30 +634,30 @@ impl ScriptTask {
fn handle_resize_inactive_msg(&mut self, id: PipelineId, new_size: Size2D<uint>) {
let page = self.page_tree.find(id).expect("Received resize message for PipelineId not associated
with a page in the page tree. This is a bug.").page;
- page.window_size = Future::from_value(new_size);
+ page.window_size = Some(new_size);
let last_loaded_url = replace(&mut page.url, None);
for url in last_loaded_url.iter() {
page.url = Some((url.first(), true));
}
}
- fn handle_exit_window_msg(&mut self, id: PipelineId) -> bool {
+ fn handle_exit_window_msg(&mut self, id: PipelineId) {
+ debug!("script task handling exit window msg");
self.handle_exit_pipeline_msg(id);
// TODO(tkuehn): currently there is only one window,
// so this can afford to be naive and just shut down the
// compositor. In the future it'll need to be smarter.
self.compositor.close();
- true
}
-
/// Handles a request to exit the script task and shut down layout.
/// Returns true if the script task should shut down and false otherwise.
fn handle_exit_pipeline_msg(&mut self, id: PipelineId) -> bool {
// If root is being exited, shut down all pages
if self.page_tree.page.id == id {
for page in self.page_tree.iter() {
+ debug!("shutting down layout for root page {:?}", page.id);
shut_down_layout(page)
}
return true
@@ -645,6 +667,7 @@ impl ScriptTask {
match self.page_tree.remove(id) {
Some(ref mut page_tree) => {
for page in page_tree.iter() {
+ debug!("shutting down layout for page {:?}", page.id);
shut_down_layout(page)
}
false
@@ -727,7 +750,7 @@ impl ScriptTask {
Some(HtmlDiscoveredStyle(sheet)) => {
page.layout_chan.send(AddStylesheetMsg(sheet));
}
- Some(HtmlDiscoveredIFrame((iframe_url, subpage_id, size_future, sandboxed))) => {
+ Some(HtmlDiscoveredIFrame((iframe_url, subpage_id, sandboxed))) => {
page.next_subpage_id = SubpageId(*subpage_id + 1);
let sandboxed = if sandboxed {
IFrameSandboxed
@@ -737,7 +760,6 @@ impl ScriptTask {
self.constellation_chan.send(LoadIframeUrlMsg(iframe_url,
pipeline_id,
subpage_id,
- size_future,
sandboxed));
}
None => break
@@ -824,7 +846,7 @@ impl ScriptTask {
ResizeEvent(new_width, new_height) => {
debug!("script got resize event: {:u}, {:u}", new_width, new_height);
- page.window_size = Future::from_value(Size2D(new_width, new_height));
+ page.window_size = Some(Size2D(new_width, new_height));
if page.frame.is_some() {
page.damage(ReflowDocumentDamage);
@@ -906,7 +928,7 @@ impl ScriptTask {
None => {}
}
} else {
- self.constellation_chan.send(LoadUrlMsg(page.id, url, Future::from_value(page.window_size.get())));
+ self.constellation_chan.send(LoadUrlMsg(page.id, url));
}
}
}
diff --git a/src/test/html/summit2.html b/src/test/html/summit2.html
index caac423845f..98b0d4a9b0f 100644
--- a/src/test/html/summit2.html
+++ b/src/test/html/summit2.html
@@ -22,6 +22,7 @@
</style>
</head>
<body>
+ <div></div>
<div class="frame">
<iframe id="frameone" sandbox="allow-scripts" src="summit-two.html">
</iframe>