diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/components/main/compositing/mod.rs | 3 | ||||
-rw-r--r-- | src/components/main/compositing/run.rs | 55 | ||||
-rw-r--r-- | src/components/main/compositing/run_headless.rs | 6 | ||||
-rw-r--r-- | src/components/main/constellation.rs | 102 | ||||
-rw-r--r-- | src/components/main/layout/layout_task.rs | 26 | ||||
-rw-r--r-- | src/components/main/pipeline.rs | 46 | ||||
-rwxr-xr-x | src/components/main/servo.rc | 32 | ||||
-rw-r--r-- | src/components/msg/constellation_msg.rs | 9 | ||||
-rw-r--r-- | src/components/script/dom/htmliframeelement.rs | 14 | ||||
-rw-r--r-- | src/components/script/html/hubbub_html_parser.rs | 34 | ||||
-rw-r--r-- | src/components/script/script_task.rs | 110 | ||||
-rw-r--r-- | src/test/html/summit2.html | 1 |
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> |