auto merge of #1405 : pcwalton/servo/defuture, r=larsbergstrom

This will allow us to stop going to the DOM in order to handle iframe
sizing. Instead we can just store the pipeline and frame IDs of iframes
inside the flow tree itself.

r? @kmcallister
This commit is contained in:
bors-servo 2013-12-13 11:28:10 -08:00
commit aa1ebbbdb0
12 changed files with 243 additions and 197 deletions

View file

@ -148,6 +148,7 @@ pub enum Msg {
pub struct CompositorTask { pub struct CompositorTask {
opts: Opts, opts: Opts,
port: Port<Msg>, port: Port<Msg>,
constellation_chan: ConstellationChan,
profiler_chan: ProfilerChan, profiler_chan: ProfilerChan,
shutdown_chan: SharedChan<()>, shutdown_chan: SharedChan<()>,
} }
@ -155,12 +156,14 @@ pub struct CompositorTask {
impl CompositorTask { impl CompositorTask {
pub fn new(opts: Opts, pub fn new(opts: Opts,
port: Port<Msg>, port: Port<Msg>,
constellation_chan: ConstellationChan,
profiler_chan: ProfilerChan, profiler_chan: ProfilerChan,
shutdown_chan: Chan<()>) shutdown_chan: Chan<()>)
-> CompositorTask { -> CompositorTask {
CompositorTask { CompositorTask {
opts: opts, opts: opts,
port: port, port: port,
constellation_chan: constellation_chan,
profiler_chan: profiler_chan, profiler_chan: profiler_chan,
shutdown_chan: SharedChan::new(shutdown_chan), shutdown_chan: SharedChan::new(shutdown_chan),
} }

View file

@ -2,41 +2,35 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * 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/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use compositing::compositor_layer::CompositorLayer;
use compositing::*;
use platform::{Application, Window}; use platform::{Application, Window};
use windowing::{ApplicationMethods, WindowEvent, WindowMethods}; use windowing::{ApplicationMethods, WindowEvent, WindowMethods};
use windowing::{IdleWindowEvent, ResizeWindowEvent, LoadUrlWindowEvent, MouseWindowEventClass}; use windowing::{IdleWindowEvent, ResizeWindowEvent, LoadUrlWindowEvent, MouseWindowEventClass};
use windowing::{ScrollWindowEvent, ZoomWindowEvent, NavigationWindowEvent, FinishedWindowEvent}; use windowing::{ScrollWindowEvent, ZoomWindowEvent, NavigationWindowEvent, FinishedWindowEvent};
use windowing::{QuitWindowEvent, MouseWindowClickEvent, MouseWindowMouseDownEvent, MouseWindowMouseUpEvent}; 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::SourceSurfaceMethods;
use azure::azure_hl; use azure::azure_hl;
use std::comm::Port; use extra::time::precise_time_s;
use std::num::Orderable;
use std::vec;
use std::path::Path;
use std::rt::io::timer::Timer;
use geom::matrix::identity; use geom::matrix::identity;
use geom::point::Point2D; use geom::point::Point2D;
use geom::size::Size2D;
use geom::rect::Rect; use geom::rect::Rect;
use geom::size::Size2D;
use layers::layers::{ContainerLayer, ContainerLayerKind}; use layers::layers::{ContainerLayer, ContainerLayerKind};
use layers::rendergl; use layers::rendergl;
use layers::scene::Scene; use layers::scene::Scene;
use opengles::gl2; use opengles::gl2;
use png; 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 servo_util::time::profile;
use servo_util::{time, url};
use extra::future::Future; use std::comm::Port;
use extra::time::precise_time_s; use std::num::Orderable;
use std::path::Path;
use compositing::compositor_layer::CompositorLayer; use std::rt::io::timer::Timer;
use std::vec;
use compositing::*;
/// Starts the compositor, which listens for messages on the specified port. /// Starts the compositor, which listens for messages on the specified port.
pub fn run_compositor(compositor: &CompositorTask) { pub fn run_compositor(compositor: &CompositorTask) {
@ -63,7 +57,7 @@ pub fn run_compositor(compositor: &CompositorTask) {
// The root CompositorLayer // The root CompositorLayer
let mut compositor_layer: Option<CompositorLayer> = None; 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. // Get BufferRequests from each layer.
let ask_for_tiles = || { let ask_for_tiles = || {
@ -128,7 +122,7 @@ pub fn run_compositor(compositor: &CompositorTask) {
window_size.height as uint); window_size.height as uint);
new_constellation_chan.send(ResizedWindowMsg(window_size)); 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())), 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 { if window_size != new_size {
debug!("osmain: window resized to {:u}x{:u}", width, height); debug!("osmain: window resized to {:u}x{:u}", width, height);
window_size = new_size; window_size = new_size;
match constellation_chan { constellation_chan.send(ResizedWindowMsg(new_size))
Some(ref chan) => chan.send(ResizedWindowMsg(new_size)),
None => error!("Compositor: Received resize event without initialized layout chan"),
}
} else { } else {
debug!("osmain: dropping window resize since size is still {:u}x{:u}", width, height); 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(), Some(ref layer) => layer.pipeline.id.clone(),
None => fail!("Compositor: Received LoadUrlWindowEvent without initialized compositor layers"), None => fail!("Compositor: Received LoadUrlWindowEvent without initialized compositor layers"),
}; };
match constellation_chan { constellation_chan.send(LoadUrlMsg(root_pipeline_id,
Some(ref chan) => chan.send(LoadUrlMsg(root_pipeline_id, url::make_url(url_string.to_str(), None)))
url::make_url(url_string.to_str(), None),
Future::from_value(window_size))),
None => error!("Compositor: Received loadurl event without initialized layout chan"),
}
} }
MouseWindowEventClass(mouse_window_event) => { MouseWindowEventClass(mouse_window_event) => {
@ -327,10 +314,7 @@ pub fn run_compositor(compositor: &CompositorTask) {
windowing::Forward => constellation_msg::Forward, windowing::Forward => constellation_msg::Forward,
windowing::Back => constellation_msg::Back, windowing::Back => constellation_msg::Back,
}; };
match constellation_chan { constellation_chan.send(NavigateMsg(direction))
Some(ref chan) => chan.send(NavigateMsg(direction)),
None => error!("Compositor: Received navigation event without initialized layout chan"),
}
} }
FinishedWindowEvent => { FinishedWindowEvent => {
@ -403,6 +387,9 @@ pub fn run_compositor(compositor: &CompositorTask) {
if exit { done = true; } if exit { done = true; }
}; };
// Tell the constellation about the initial window size.
constellation_chan.send(ResizedWindowMsg(window_size));
// Enter the main event loop. // Enter the main event loop.
let mut tm = Timer::new().unwrap(); let mut tm = Timer::new().unwrap();
while !done { while !done {

View file

@ -4,11 +4,17 @@
use compositing::*; use compositing::*;
use geom::size::Size2D;
use servo_msg::constellation_msg::ResizedWindowMsg;
/// Starts the compositor, which listens for messages on the specified port. /// Starts the compositor, which listens for messages on the specified port.
/// ///
/// This is the null compositor which doesn't draw anything to the screen. /// This is the null compositor which doesn't draw anything to the screen.
/// It's intended for headless testing. /// It's intended for headless testing.
pub fn run_compositor(compositor: &CompositorTask) { pub fn run_compositor(compositor: &CompositorTask) {
// Tell the constellation about the initial fake size.
compositor.constellation_chan.send(ResizedWindowMsg(Size2D(640u, 480u)));
loop { loop {
match compositor.port.recv() { match compositor.port.recv() {
Exit => break, Exit => break,

View file

@ -4,28 +4,27 @@
use compositing::{CompositorChan, SetIds, SetLayerClipRect}; use compositing::{CompositorChan, SetIds, SetLayerClipRect};
use std::comm; use extra::url::Url;
use std::comm::Port;
use std::task::spawn_with;
use geom::size::Size2D;
use geom::rect::Rect; use geom::rect::Rect;
use geom::size::Size2D;
use gfx::opts::Opts; use gfx::opts::Opts;
use pipeline::Pipeline; use pipeline::Pipeline;
use script::script_task::{ResizeMsg, ResizeInactiveMsg};
use servo_msg::constellation_msg::{ConstellationChan, ExitMsg, FailureMsg, FrameRectMsg}; use servo_msg::constellation_msg::{ConstellationChan, ExitMsg, FailureMsg, FrameRectMsg};
use servo_msg::constellation_msg::{IFrameSandboxState, InitLoadUrlMsg, LoadIframeUrlMsg, LoadUrlMsg}; use servo_msg::constellation_msg::{IFrameSandboxState, IFrameUnsandboxed, InitLoadUrlMsg};
use servo_msg::constellation_msg::{Msg, NavigateMsg, NavigationType, IFrameUnsandboxed}; use servo_msg::constellation_msg::{LoadIframeUrlMsg, LoadUrlMsg, Msg, NavigateMsg, NavigationType};
use servo_msg::constellation_msg::{PipelineId, RendererReadyMsg, ResizedWindowMsg, SubpageId}; use servo_msg::constellation_msg::{PipelineId, RendererReadyMsg, ResizedWindowMsg, SubpageId};
use servo_msg::constellation_msg; use servo_msg::constellation_msg;
use script::script_task::{ResizeMsg, ResizeInactiveMsg};
use servo_net::image_cache_task::{ImageCacheTask, ImageCacheTaskClient}; use servo_net::image_cache_task::{ImageCacheTask, ImageCacheTaskClient};
use servo_net::resource_task::ResourceTask; use servo_net::resource_task::ResourceTask;
use servo_net::resource_task; use servo_net::resource_task;
use servo_util::time::ProfilerChan; use servo_util::time::ProfilerChan;
use servo_util::url::make_url; use servo_util::url::make_url;
use std::comm::Port;
use std::comm;
use std::hashmap::{HashMap, HashSet}; use std::hashmap::{HashMap, HashSet};
use std::task::spawn_with;
use std::util::replace; use std::util::replace;
use extra::url::Url;
use extra::future::Future;
/// Maintains the pipelines and navigation context and grants permission to composite /// Maintains the pipelines and navigation context and grants permission to composite
pub struct Constellation { pub struct Constellation {
@ -249,18 +248,27 @@ impl NavigationContext {
} }
impl Constellation { impl Constellation {
pub fn start(compositor_chan: CompositorChan, pub fn start(constellation_port: Port<Msg>,
constellation_chan: ConstellationChan,
compositor_chan: CompositorChan,
opts: &Opts, opts: &Opts,
resource_task: ResourceTask, resource_task: ResourceTask,
image_cache_task: ImageCacheTask, image_cache_task: ImageCacheTask,
profiler_chan: ProfilerChan) profiler_chan: ProfilerChan) {
-> ConstellationChan { do spawn_with((constellation_port,
let (constellation_port, constellation_chan) = special_stream!(ConstellationChan); constellation_chan.clone(),
do spawn_with((constellation_port, constellation_chan.clone(), compositor_chan,
compositor_chan, resource_task, image_cache_task, resource_task,
profiler_chan, opts.clone())) image_cache_task,
|(constellation_port, constellation_chan, compositor_chan, resource_task, profiler_chan,
image_cache_task, profiler_chan, opts)| { opts.clone()))
|(constellation_port,
constellation_chan,
compositor_chan,
resource_task,
image_cache_task,
profiler_chan,
opts)| {
let mut constellation = Constellation { let mut constellation = Constellation {
chan: constellation_chan, chan: constellation_chan,
request_port: constellation_port, request_port: constellation_port,
@ -278,7 +286,6 @@ impl Constellation {
}; };
constellation.run(); constellation.run();
} }
constellation_chan
} }
fn run(&mut self) { fn run(&mut self) {
@ -324,32 +331,38 @@ impl Constellation {
} }
// This should only be called once per constellation, and only by the browser // This should only be called once per constellation, and only by the browser
InitLoadUrlMsg(url) => { InitLoadUrlMsg(url) => {
debug!("constellation got init load URL message");
self.handle_init_load(url); self.handle_init_load(url);
} }
// A layout assigned a size and position to a subframe. This needs to be reflected by all // A layout assigned a size and position to a subframe. This needs to be reflected by
// frame trees in the navigation context containing the subframe. // all frame trees in the navigation context containing the subframe.
FrameRectMsg(pipeline_id, subpage_id, rect) => { FrameRectMsg(pipeline_id, subpage_id, rect) => {
debug!("constellation got frame rect message");
self.handle_frame_rect_msg(pipeline_id, subpage_id, rect); self.handle_frame_rect_msg(pipeline_id, subpage_id, rect);
} }
LoadIframeUrlMsg(url, source_pipeline_id, subpage_id, size_future, sandbox) => { LoadIframeUrlMsg(url, source_pipeline_id, subpage_id, sandbox) => {
self.handle_load_iframe_url_msg(url, source_pipeline_id, subpage_id, size_future, 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 // 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; // 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. // However, if the id is not encompassed by another change, it will be.
LoadUrlMsg(source_id, url, size_future) => { LoadUrlMsg(source_id, url) => {
self.handle_load_url_msg(source_id, url, size_future); debug!("constellation got URL load message");
self.handle_load_url_msg(source_id, url);
} }
// Handle a forward or back request // Handle a forward or back request
NavigateMsg(direction) => { NavigateMsg(direction) => {
debug!("constellation got navigation message");
self.handle_navigate_msg(direction); self.handle_navigate_msg(direction);
} }
// Notification that rendering has finished and is requesting permission to paint. // Notification that rendering has finished and is requesting permission to paint.
RendererReadyMsg(pipeline_id) => { RendererReadyMsg(pipeline_id) => {
debug!("constellation got renderer ready message");
self.handle_renderer_ready_msg(pipeline_id); self.handle_renderer_ready_msg(pipeline_id);
} }
ResizedWindowMsg(new_size) => { ResizedWindowMsg(new_size) => {
debug!("constellation got window resize message");
self.handle_resized_window_msg(new_size); self.handle_resized_window_msg(new_size);
} }
} }
@ -375,8 +388,7 @@ impl Constellation {
self.image_cache_task.clone(), self.image_cache_task.clone(),
self.resource_task.clone(), self.resource_task.clone(),
self.profiler_chan.clone(), self.profiler_chan.clone(),
self.opts.clone(), self.opts.clone());
Future::from_value(self.window_size));
let failure = ~"about:failure"; let failure = ~"about:failure";
let url = make_url(failure, None); let url = make_url(failure, None);
pipeline.load(url); pipeline.load(url);
@ -397,11 +409,10 @@ impl Constellation {
self.image_cache_task.clone(), self.image_cache_task.clone(),
self.resource_task.clone(), self.resource_task.clone(),
self.profiler_chan.clone(), self.profiler_chan.clone(),
self.opts.clone(), self.opts.clone());
Future::from_value(self.window_size));
pipeline.load(url); pipeline.load(url);
self.pending_frames.push(FrameChange{ self.pending_frames.push(FrameChange {
before: None, before: None,
after: @mut FrameTree { after: @mut FrameTree {
pipeline: pipeline, pipeline: pipeline,
@ -476,7 +487,6 @@ impl Constellation {
url: Url, url: Url,
source_pipeline_id: PipelineId, source_pipeline_id: PipelineId,
subpage_id: SubpageId, subpage_id: SubpageId,
size_future: Future<Size2D<uint>>,
sandbox: IFrameSandboxState) { sandbox: IFrameSandboxState) {
// A message from the script associated with pipeline_id that it has // A message from the script associated with pipeline_id that it has
// parsed an iframe during html parsing. This iframe will result in a // parsed an iframe during html parsing. This iframe will result in a
@ -524,8 +534,7 @@ impl Constellation {
self.image_cache_task.clone(), self.image_cache_task.clone(),
self.profiler_chan.clone(), self.profiler_chan.clone(),
self.opts.clone(), self.opts.clone(),
source_pipeline, source_pipeline)
size_future)
} else { } else {
debug!("Constellation: loading cross-origin iframe at {:?}", url); debug!("Constellation: loading cross-origin iframe at {:?}", url);
// Create a new script task if not same-origin url's // Create a new script task if not same-origin url's
@ -536,8 +545,7 @@ impl Constellation {
self.image_cache_task.clone(), self.image_cache_task.clone(),
self.resource_task.clone(), self.resource_task.clone(),
self.profiler_chan.clone(), self.profiler_chan.clone(),
self.opts.clone(), self.opts.clone())
size_future)
}; };
debug!("Constellation: sending load msg to pipeline {:?}", pipeline.id); debug!("Constellation: sending load msg to pipeline {:?}", pipeline.id);
@ -556,7 +564,7 @@ impl Constellation {
self.pipelines.insert(pipeline.id, pipeline); 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()); debug!("Constellation: received message to load {:s}", url.to_str());
// Make sure no pending page would be overridden. // Make sure no pending page would be overridden.
let source_frame = self.current_frame().get_ref().find(source_id).expect( let source_frame = self.current_frame().get_ref().find(source_id).expect(
@ -590,8 +598,7 @@ impl Constellation {
self.image_cache_task.clone(), self.image_cache_task.clone(),
self.resource_task.clone(), self.resource_task.clone(),
self.profiler_chan.clone(), self.profiler_chan.clone(),
self.opts.clone(), self.opts.clone());
size_future);
pipeline.load(url); 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>) { fn handle_resized_window_msg(&mut self, new_size: Size2D<uint>) {
let mut already_seen = HashSet::new(); let mut already_seen = HashSet::new();
for &@FrameTree { pipeline: pipeline, _ } in self.current_frame().iter() { 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)); pipeline.script_chan.send(ResizeMsg(pipeline.id, new_size));
already_seen.insert(pipeline.id); already_seen.insert(pipeline.id);
} }
@ -737,10 +747,22 @@ impl Constellation {
.chain(self.navigation_context.next.iter()) { .chain(self.navigation_context.next.iter()) {
let pipeline = &frame_tree.pipeline; let pipeline = &frame_tree.pipeline;
if !already_seen.contains(&pipeline.id) { if !already_seen.contains(&pipeline.id) {
debug!("constellation sending resize message to inactive frame");
pipeline.script_chan.send(ResizeInactiveMsg(pipeline.id, new_size)); pipeline.script_chan.send(ResizeInactiveMsg(pipeline.id, new_size));
already_seen.insert(pipeline.id); 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; self.window_size = new_size;
} }

View file

@ -295,7 +295,9 @@ impl LayoutTask {
} }
} }
PrepareToExitMsg(response_chan) => { PrepareToExitMsg(response_chan) => {
self.prepare_to_exit(response_chan) debug!("layout: PrepareToExitMsg received");
self.prepare_to_exit(response_chan);
return false
} }
ExitNowMsg => { ExitNowMsg => {
debug!("layout: ExitNowMsg received"); debug!("layout: ExitNowMsg received");
@ -312,15 +314,21 @@ impl LayoutTask {
/// response channel. /// response channel.
fn prepare_to_exit(&mut self, response_chan: Chan<()>) { fn prepare_to_exit(&mut self, response_chan: Chan<()>) {
response_chan.send(()); response_chan.send(());
match self.port.recv() { loop {
ReapLayoutDataMsg(dead_layout_data) => { match self.port.recv() {
unsafe { ReapLayoutDataMsg(dead_layout_data) => {
self.handle_reap_layout_data(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`")
} }
} }
} }

View file

@ -2,23 +2,22 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * 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/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use extra::url::Url;
use compositing::CompositorChan; 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 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::layout_interface::LayoutChan;
use script::script_task::LoadMsg; 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::{AttachLayoutMsg, NewLayoutInfo, ScriptTask, ScriptChan};
use script::script_task; use script::script_task;
use servo_msg::constellation_msg::{ConstellationChan, FailureMsg, PipelineId, SubpageId};
use servo_net::image_cache_task::ImageCacheTask; use servo_net::image_cache_task::ImageCacheTask;
use servo_net::resource_task::ResourceTask; use servo_net::resource_task::ResourceTask;
use servo_util::time::ProfilerChan; use servo_util::time::ProfilerChan;
use geom::size::Size2D;
use extra::future::Future;
use std::task; use std::task;
/// A uniquely-identifiable pipeline of script task, layout task, and render task. /// A uniquely-identifiable pipeline of script task, layout task, and render task.
@ -34,7 +33,8 @@ pub struct Pipeline {
} }
impl 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, pub fn with_script(id: PipelineId,
subpage_id: Option<SubpageId>, subpage_id: Option<SubpageId>,
constellation_chan: ConstellationChan, constellation_chan: ConstellationChan,
@ -42,8 +42,8 @@ impl Pipeline {
image_cache_task: ImageCacheTask, image_cache_task: ImageCacheTask,
profiler_chan: ProfilerChan, profiler_chan: ProfilerChan,
opts: Opts, opts: Opts,
script_pipeline: &Pipeline, script_pipeline: &Pipeline)
size_future: Future<Size2D<uint>>) -> Pipeline { -> Pipeline {
let (layout_port, layout_chan) = special_stream!(LayoutChan); let (layout_port, layout_chan) = special_stream!(LayoutChan);
let (render_port, render_chan) = special_stream!(RenderChan); let (render_port, render_chan) = special_stream!(RenderChan);
@ -67,7 +67,6 @@ impl Pipeline {
old_id: script_pipeline.id.clone(), old_id: script_pipeline.id.clone(),
new_id: id, new_id: id,
layout_chan: layout_chan.clone(), layout_chan: layout_chan.clone(),
size_future: size_future,
}; };
script_pipeline.script_chan.send(AttachLayoutMsg(new_layout_info)); script_pipeline.script_chan.send(AttachLayoutMsg(new_layout_info));
@ -86,9 +85,8 @@ impl Pipeline {
image_cache_task: ImageCacheTask, image_cache_task: ImageCacheTask,
resource_task: ResourceTask, resource_task: ResourceTask,
profiler_chan: ProfilerChan, profiler_chan: ProfilerChan,
opts: Opts, opts: Opts)
size: Future<Size2D<uint>>) -> Pipeline { -> Pipeline {
let (script_port, script_chan) = special_stream!(ScriptChan); let (script_port, script_chan) = special_stream!(ScriptChan);
let (layout_port, layout_chan) = special_stream!(LayoutChan); let (layout_port, layout_chan) = special_stream!(LayoutChan);
let (render_port, render_chan) = special_stream!(RenderChan); let (render_port, render_chan) = special_stream!(RenderChan);
@ -106,9 +104,15 @@ impl Pipeline {
let task_port = supervised_task.future_result(); let task_port = supervised_task.future_result();
supervised_task.supervised(); supervised_task.supervised();
spawn_with!(supervised_task, [script_port, resource_task, size, render_port, spawn_with!(supervised_task, [
layout_port, constellation_chan, image_cache_task, script_port,
profiler_chan], { resource_task,
render_port,
layout_port,
constellation_chan,
image_cache_task,
profiler_chan
], {
ScriptTask::create(id, ScriptTask::create(id,
compositor_chan.clone(), compositor_chan.clone(),
layout_chan.clone(), layout_chan.clone(),
@ -116,8 +120,7 @@ impl Pipeline {
script_chan.clone(), script_chan.clone(),
constellation_chan.clone(), constellation_chan.clone(),
resource_task, resource_task,
image_cache_task.clone(), image_cache_task.clone());
size);
RenderTask::create(id, RenderTask::create(id,
render_port, render_port,
@ -187,8 +190,7 @@ impl Pipeline {
} }
pub fn exit(&self) { pub fn exit(&self) {
// Script task handles shutting down layout, // Script task handles shutting down layout, and layout handles shutting down the renderer.
// and layout handles shutting down the renderer.
self.script_chan.try_send(script_task::ExitPipelineMsg(self.id)); self.script_chan.try_send(script_task::ExitPipelineMsg(self.id));
} }
} }

View file

@ -41,7 +41,7 @@ extern mod core_text = "rust-core-text";
use compositing::{CompositorChan, CompositorTask}; use compositing::{CompositorChan, CompositorTask};
use constellation::Constellation; use constellation::Constellation;
use servo_msg::constellation_msg::{ExitMsg, InitLoadUrlMsg}; use servo_msg::constellation_msg::{ConstellationChan, ExitMsg, InitLoadUrlMsg};
#[cfg(not(test))] #[cfg(not(test))]
use gfx::opts; use gfx::opts;
@ -127,21 +127,32 @@ fn run(opts: Opts) {
let (shutdown_port, shutdown_chan) = comm::stream(); let (shutdown_port, shutdown_chan) = comm::stream();
let (profiler_port, profiler_chan) = special_stream!(ProfilerChan); let (profiler_port, profiler_chan) = special_stream!(ProfilerChan);
let (compositor_port, compositor_chan) = special_stream!(CompositorChan); 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); Profiler::create(profiler_port, profiler_chan.clone(), opts.profiler_period);
do spawn_with((profiler_chan.clone(), compositor_chan, opts.clone())) do spawn_with((constellation_port,
|(profiler_chan, compositor_chan, opts)| { constellation_chan.clone(),
profiler_chan.clone(),
compositor_chan,
opts.clone()))
|(constellation_port,
constellation_chan,
profiler_chan,
compositor_chan,
opts)| {
let opts = &opts; let opts = &opts;
// Create a Servo instance. // Create a Servo instance.
let resource_task = ResourceTask(); let resource_task = ResourceTask();
let image_cache_task = ImageCacheTask(resource_task.clone()); let image_cache_task = ImageCacheTask(resource_task.clone());
let constellation_chan = Constellation::start(compositor_chan, Constellation::start(constellation_port,
opts, constellation_chan.clone(),
resource_task, compositor_chan,
image_cache_task, opts,
profiler_chan.clone()); resource_task,
image_cache_task,
profiler_chan.clone());
// Send the URL command to the constellation. // Send the URL command to the constellation.
for filename in opts.urls.iter() { for filename in opts.urls.iter() {
@ -158,11 +169,12 @@ fn run(opts: Opts) {
exit_response_from_constellation.recv(); exit_response_from_constellation.recv();
} }
let compositor_task = CompositorTask::new(opts, let compositor_task = CompositorTask::new(opts,
compositor_port, compositor_port,
constellation_chan,
profiler_chan, profiler_chan,
shutdown_chan); shutdown_chan);
debug!("preparing to enter main loop"); debug!("preparing to enter main loop");
compositor_task.run(); compositor_task.run();
} }

View file

@ -5,11 +5,10 @@
//! The high-level interface from script to constellation. Using this abstract interface helps reduce //! The high-level interface from script to constellation. Using this abstract interface helps reduce
/// coupling between these two components /// coupling between these two components
use std::comm::{Chan, SharedChan};
use extra::url::Url; use extra::url::Url;
use extra::future::Future;
use geom::size::Size2D;
use geom::rect::Rect; use geom::rect::Rect;
use geom::size::Size2D;
use std::comm::{Chan, SharedChan};
#[deriving(Clone)] #[deriving(Clone)]
pub struct ConstellationChan(SharedChan<Msg>); pub struct ConstellationChan(SharedChan<Msg>);
@ -32,8 +31,8 @@ pub enum Msg {
FailureMsg(PipelineId, Option<SubpageId>), FailureMsg(PipelineId, Option<SubpageId>),
InitLoadUrlMsg(Url), InitLoadUrlMsg(Url),
FrameRectMsg(PipelineId, SubpageId, Rect<f32>), FrameRectMsg(PipelineId, SubpageId, Rect<f32>),
LoadUrlMsg(PipelineId, Url, Future<Size2D<uint>>), LoadUrlMsg(PipelineId, Url),
LoadIframeUrlMsg(Url, PipelineId, SubpageId, Future<Size2D<uint>>, IFrameSandboxState), LoadIframeUrlMsg(Url, PipelineId, SubpageId, IFrameSandboxState),
NavigateMsg(NavigationDirection), NavigateMsg(NavigationDirection),
RendererReadyMsg(PipelineId), RendererReadyMsg(PipelineId),
ResizedWindowMsg(Size2D<uint>), ResizedWindowMsg(Size2D<uint>),

View file

@ -9,15 +9,11 @@ use dom::element::HTMLIframeElementTypeId;
use dom::htmlelement::HTMLElement; use dom::htmlelement::HTMLElement;
use dom::node::{AbstractNode, Node, ScriptView}; use dom::node::{AbstractNode, Node, ScriptView};
use dom::windowproxy::WindowProxy; use dom::windowproxy::WindowProxy;
use geom::size::Size2D;
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 extra::url::Url;
use std::util::replace; use geom::rect::Rect;
use servo_msg::constellation_msg::{ConstellationChan, FrameRectMsg, PipelineId, SubpageId};
use std::ascii::StrAsciiExt;
enum SandboxAllowance { enum SandboxAllowance {
AllowNothing = 0x00, AllowNothing = 0x00,
@ -39,17 +35,11 @@ pub struct HTMLIFrameElement {
struct IFrameSize { struct IFrameSize {
pipeline_id: PipelineId, pipeline_id: PipelineId,
subpage_id: SubpageId, subpage_id: SubpageId,
future_chan: Option<ChanOne<Size2D<uint>>>,
constellation_chan: ConstellationChan, constellation_chan: ConstellationChan,
} }
impl IFrameSize { impl IFrameSize {
pub fn set_rect(&mut self, rect: Rect<f32>) { 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)); self.constellation_chan.send(FrameRectMsg(self.pipeline_id, self.subpage_id, rect));
} }
} }

View file

@ -12,26 +12,24 @@ use dom::namespace;
use dom::node::{AbstractNode, ElementNodeTypeId, ScriptView}; use dom::node::{AbstractNode, ElementNodeTypeId, ScriptView};
use dom::types::*; use dom::types::*;
use html::cssparse::{InlineProvenance, StylesheetProvenance, UrlProvenance, spawn_css_parser}; use html::cssparse::{InlineProvenance, StylesheetProvenance, UrlProvenance, spawn_css_parser};
use js::jsapi::JSContext;
use style::Stylesheet;
use script_task::page_from_context; use script_task::page_from_context;
use std::cast; use extra::url::Url;
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 hubbub::hubbub; use hubbub::hubbub;
use js::jsapi::JSContext;
use servo_msg::constellation_msg::{ConstellationChan, SubpageId}; use servo_msg::constellation_msg::{ConstellationChan, SubpageId};
use servo_net::image_cache_task::ImageCacheTask; use servo_net::image_cache_task::ImageCacheTask;
use servo_net::resource_task::{Load, Payload, Done, ResourceTask, load_whole_resource}; use servo_net::resource_task::{Load, Payload, Done, ResourceTask, load_whole_resource};
use servo_util::tree::{TreeNodeRef, ElementLike}; use servo_util::tree::{TreeNodeRef, ElementLike};
use servo_util::url::make_url; use servo_util::url::make_url;
use extra::future::Future; use std::cast;
use extra::url::Url; use std::cell::Cell;
use geom::size::Size2D; 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( macro_rules! handle_element(
($document: expr, ($document: expr,
@ -67,7 +65,7 @@ enum JSMessage {
/// Messages generated by the HTML parser upon discovery of additional resources /// Messages generated by the HTML parser upon discovery of additional resources
pub enum HtmlDiscoveryMessage { pub enum HtmlDiscoveryMessage {
HtmlDiscoveredStyle(Stylesheet), HtmlDiscoveredStyle(Stylesheet),
HtmlDiscoveredIFrame((Url, SubpageId, Future<Size2D<uint>>, bool)), HtmlDiscoveredIFrame((Url, SubpageId, bool)),
HtmlDiscoveredScript(JSResult) HtmlDiscoveredScript(JSResult)
} }
@ -374,10 +372,6 @@ pub fn parse_html(cx: *JSContext,
let iframe_url = make_url(src.clone(), Some(url2.clone())); let iframe_url = make_url(src.clone(), Some(url2.clone()));
iframe_element.frame = Some(iframe_url.clone()); iframe_element.frame = Some(iframe_url.clone());
// Size future
let (port, chan) = comm::oneshot();
let size_future = Future::from_port(port);
// Subpage Id // Subpage Id
let subpage_id = next_subpage_id.take(); let subpage_id = next_subpage_id.take();
next_subpage_id.put_back(SubpageId(*subpage_id + 1)); next_subpage_id.put_back(SubpageId(*subpage_id + 1));
@ -391,11 +385,11 @@ pub fn parse_html(cx: *JSContext,
iframe_element.size = Some(IFrameSize { iframe_element.size = Some(IFrameSize {
pipeline_id: pipeline_id, pipeline_id: pipeline_id,
subpage_id: subpage_id, subpage_id: subpage_id,
future_chan: Some(chan),
constellation_chan: constellation_chan.clone(), constellation_chan: constellation_chan.clone(),
}); });
iframe_chan.send(HtmlDiscoveredIFrame((iframe_url, subpage_id, iframe_chan.send(HtmlDiscoveredIFrame((iframe_url,
size_future, sandboxed))); subpage_id,
sandboxed)));
} }
} }
} }

View file

@ -27,11 +27,9 @@ use layout_interface::ContentChangedDocumentDamage;
use layout_interface; use layout_interface;
use dom::node::ScriptView; use dom::node::ScriptView;
use extra::future::Future;
use extra::url::Url; use extra::url::Url;
use std::str::eq_slice;
use geom::size::Size2D;
use geom::point::Point2D; use geom::point::Point2D;
use geom::size::Size2D;
use js::JSVAL_NULL; use js::JSVAL_NULL;
use js::global::debug_fns; use js::global::debug_fns;
use js::glue::RUST_JSVAL_TO_OBJECT; use js::glue::RUST_JSVAL_TO_OBJECT;
@ -53,6 +51,7 @@ use std::cell::Cell;
use std::comm::{Port, SharedChan}; use std::comm::{Port, SharedChan};
use std::comm; use std::comm;
use std::ptr; use std::ptr;
use std::str::eq_slice;
use std::task::{spawn_sched, SingleThreaded}; use std::task::{spawn_sched, SingleThreaded};
use std::util::replace; use std::util::replace;
@ -84,7 +83,6 @@ pub struct NewLayoutInfo {
old_id: PipelineId, old_id: PipelineId,
new_id: PipelineId, new_id: PipelineId,
layout_chan: LayoutChan, layout_chan: LayoutChan,
size_future: Future<Size2D<uint>>,
} }
/// Encapsulates external communication with the script task. /// Encapsulates external communication with the script task.
@ -118,8 +116,8 @@ pub struct Page {
/// What parts of the document are dirty, if any. /// What parts of the document are dirty, if any.
damage: Option<DocumentDamage>, damage: Option<DocumentDamage>,
/// The current size of the window, in pixels. /// The current size of the window, in pixels. If `None`, we do not know the window size yet.
window_size: Future<Size2D<uint>>, window_size: Option<Size2D<uint>>,
js_info: Option<JSPageInfo>, js_info: Option<JSPageInfo>,
@ -148,7 +146,7 @@ pub struct PageTreeIterator<'self> {
} }
impl PageTree { impl PageTree {
fn new(id: PipelineId, layout_chan: LayoutChan, size_future: Future<Size2D<uint>>) -> PageTree { fn new(id: PipelineId, layout_chan: LayoutChan) -> PageTree {
PageTree { PageTree {
page: @mut Page { page: @mut Page {
id: id, id: id,
@ -156,7 +154,7 @@ impl PageTree {
layout_chan: layout_chan, layout_chan: layout_chan,
layout_join_port: None, layout_join_port: None,
damage: None, damage: None,
window_size: size_future, window_size: None,
js_info: None, js_info: None,
url: None, url: None,
next_subpage_id: SubpageId(0), next_subpage_id: SubpageId(0),
@ -280,18 +278,32 @@ impl Page {
response_port.recv() response_port.recv()
} }
/// This method will wait until the layout task has completed its current action, join the /// Reflows the page if it's possible to do so. This method will wait until the layout task has
/// layout task, and then request a new layout run. It won't wait for the new layout /// completed its current action, join the layout task, and then request a new layout run. It
/// computation to finish. /// 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. /// 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 { let root = match self.frame {
None => return, None => return,
Some(ref frame) => { Some(ref frame) => {
frame.document.document().GetDocumentElement() 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 { match root {
None => {}, None => {},
Some(root) => { Some(root) => {
@ -314,7 +326,7 @@ impl Page {
document_root: root, document_root: root,
url: self.url.get_ref().first().clone(), url: self.url.get_ref().first().clone(),
goal: goal, goal: goal,
window_size: self.window_size.get(), window_size: window_size,
script_chan: script_chan, script_chan: script_chan,
script_join_chan: join_chan, script_join_chan: join_chan,
damage: replace(&mut self.damage, None).unwrap(), 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) { 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 // Note that the order that these variables are initialized is _not_ arbitrary. Switching
// can -- and likely will -- lead to things breaking. // them around can -- and likely will -- lead to things breaking.
js_context.set_default_options_and_version(); js_context.set_default_options_and_version();
js_context.set_logging_error_reporter(); js_context.set_logging_error_reporter();
@ -425,13 +437,12 @@ impl ScriptTask {
chan: ScriptChan, chan: ScriptChan,
constellation_chan: ConstellationChan, constellation_chan: ConstellationChan,
resource_task: ResourceTask, resource_task: ResourceTask,
img_cache_task: ImageCacheTask, img_cache_task: ImageCacheTask)
initial_size: Future<Size2D<uint>>)
-> @mut ScriptTask { -> @mut ScriptTask {
let js_runtime = js::rust::rt(); let js_runtime = js::rust::rt();
let script_task = @mut ScriptTask { 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, image_cache_task: img_cache_task,
resource_task: resource_task, resource_task: resource_task,
@ -463,25 +474,33 @@ impl ScriptTask {
chan: ScriptChan, chan: ScriptChan,
constellation_chan: ConstellationChan, constellation_chan: ConstellationChan,
resource_task: ResourceTask, resource_task: ResourceTask,
image_cache_task: ImageCacheTask, image_cache_task: ImageCacheTask) {
initial_size: Future<Size2D<uint>>) { let parms = Cell::new((compositor,
let parms = Cell::new((compositor, layout_chan, port, chan, constellation_chan, layout_chan,
resource_task, image_cache_task, initial_size)); port,
chan,
constellation_chan,
resource_task,
image_cache_task));
// Since SpiderMonkey is blocking it needs to run in its own thread. // 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 // If we don't do this then we'll just end up with a bunch of SpiderMonkeys
// starving all the other tasks. // starving all the other tasks.
do spawn_sched(SingleThreaded) { do spawn_sched(SingleThreaded) {
let (compositor, layout_chan, port, chan, constellation_chan, let (compositor,
resource_task, image_cache_task, initial_size) = parms.take(); layout_chan,
port,
chan,
constellation_chan,
resource_task,
image_cache_task) = parms.take();
let script_task = ScriptTask::new(id, let script_task = ScriptTask::new(id,
@compositor as @ScriptListener, @compositor as @ScriptListener,
layout_chan, layout_chan,
port, port,
chan, chan,
constellation_chan, constellation_chan,
resource_task, resource_task,
image_cache_task, image_cache_task);
initial_size);
script_task.start(); script_task.start();
} }
} }
@ -512,6 +531,7 @@ impl ScriptTask {
let event = self.port.recv(); let event = self.port.recv();
match event { match event {
ResizeMsg(id, size) => { ResizeMsg(id, size) => {
debug!("script got resize message");
let page = self.page_tree.find(id).expect("resize sent to nonexistent pipeline").page; let page = self.page_tree.find(id).expect("resize sent to nonexistent pipeline").page;
page.resize_event = Some(size); page.resize_event = Some(size);
} }
@ -538,7 +558,10 @@ impl ScriptTask {
ReflowCompleteMsg(id, reflow_id) => self.handle_reflow_complete_msg(id, reflow_id), ReflowCompleteMsg(id, reflow_id) => self.handle_reflow_complete_msg(id, reflow_id),
ResizeInactiveMsg(id, new_size) => self.handle_resize_inactive_msg(id, new_size), ResizeInactiveMsg(id, new_size) => self.handle_resize_inactive_msg(id, new_size),
ExitPipelineMsg(id) => if self.handle_exit_pipeline_msg(id) { return false }, 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"), ResizeMsg(*) => fail!("should have handled ResizeMsg already"),
} }
} }
@ -551,14 +574,13 @@ impl ScriptTask {
let NewLayoutInfo { let NewLayoutInfo {
old_id, old_id,
new_id, new_id,
layout_chan, layout_chan
size_future
} = new_layout_info; } = new_layout_info;
let parent_page_tree = self.page_tree.find(old_id).expect("ScriptTask: received a layout 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 whose parent has a PipelineId which does not correspond to a pipeline in the script
task's page tree. This is a bug."); 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); 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>) { 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 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; 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); let last_loaded_url = replace(&mut page.url, None);
for url in last_loaded_url.iter() { for url in last_loaded_url.iter() {
page.url = Some((url.first(), true)); 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); self.handle_exit_pipeline_msg(id);
// TODO(tkuehn): currently there is only one window, // TODO(tkuehn): currently there is only one window,
// so this can afford to be naive and just shut down the // so this can afford to be naive and just shut down the
// compositor. In the future it'll need to be smarter. // compositor. In the future it'll need to be smarter.
self.compositor.close(); self.compositor.close();
true
} }
/// Handles a request to exit the script task and shut down layout. /// Handles a request to exit the script task and shut down layout.
/// Returns true if the script task should shut down and false otherwise. /// Returns true if the script task should shut down and false otherwise.
fn handle_exit_pipeline_msg(&mut self, id: PipelineId) -> bool { fn handle_exit_pipeline_msg(&mut self, id: PipelineId) -> bool {
// If root is being exited, shut down all pages // If root is being exited, shut down all pages
if self.page_tree.page.id == id { if self.page_tree.page.id == id {
for page in self.page_tree.iter() { for page in self.page_tree.iter() {
debug!("shutting down layout for root page {:?}", page.id);
shut_down_layout(page) shut_down_layout(page)
} }
return true return true
@ -645,6 +667,7 @@ impl ScriptTask {
match self.page_tree.remove(id) { match self.page_tree.remove(id) {
Some(ref mut page_tree) => { Some(ref mut page_tree) => {
for page in page_tree.iter() { for page in page_tree.iter() {
debug!("shutting down layout for page {:?}", page.id);
shut_down_layout(page) shut_down_layout(page)
} }
false false
@ -727,7 +750,7 @@ impl ScriptTask {
Some(HtmlDiscoveredStyle(sheet)) => { Some(HtmlDiscoveredStyle(sheet)) => {
page.layout_chan.send(AddStylesheetMsg(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); page.next_subpage_id = SubpageId(*subpage_id + 1);
let sandboxed = if sandboxed { let sandboxed = if sandboxed {
IFrameSandboxed IFrameSandboxed
@ -737,7 +760,6 @@ impl ScriptTask {
self.constellation_chan.send(LoadIframeUrlMsg(iframe_url, self.constellation_chan.send(LoadIframeUrlMsg(iframe_url,
pipeline_id, pipeline_id,
subpage_id, subpage_id,
size_future,
sandboxed)); sandboxed));
} }
None => break None => break
@ -824,7 +846,7 @@ impl ScriptTask {
ResizeEvent(new_width, new_height) => { ResizeEvent(new_width, new_height) => {
debug!("script got resize event: {:u}, {:u}", 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() { if page.frame.is_some() {
page.damage(ReflowDocumentDamage); page.damage(ReflowDocumentDamage);
@ -906,7 +928,7 @@ impl ScriptTask {
None => {} None => {}
} }
} else { } else {
self.constellation_chan.send(LoadUrlMsg(page.id, url, Future::from_value(page.window_size.get()))); self.constellation_chan.send(LoadUrlMsg(page.id, url));
} }
} }
} }

View file

@ -22,6 +22,7 @@
</style> </style>
</head> </head>
<body> <body>
<div></div>
<div class="frame"> <div class="frame">
<iframe id="frameone" sandbox="allow-scripts" src="summit-two.html"> <iframe id="frameone" sandbox="allow-scripts" src="summit-two.html">
</iframe> </iframe>