diff --git a/src/components/main/layout/layout_task.rs b/src/components/main/layout/layout_task.rs index 7034593fbe2..69d1e6a031b 100644 --- a/src/components/main/layout/layout_task.rs +++ b/src/components/main/layout/layout_task.rs @@ -36,7 +36,7 @@ use script::layout_interface::{AddStylesheetMsg, BuildData, BuildMsg, ContentBox use script::layout_interface::{HitTestQuery, ContentBoxResponse, HitTestResponse}; use script::layout_interface::{ContentBoxesQuery, ContentBoxesResponse, ExitMsg, LayoutQuery}; use script::layout_interface::{LayoutResponse, LayoutTask, MatchSelectorsDamage, Msg, NoDamage}; -use script::layout_interface::{QueryMsg, ReflowDamage}; +use script::layout_interface::{QueryMsg, ReflowDamage, ReflowForDisplay}; use script::script_task::{ScriptMsg, SendEventMsg}; use servo_net::image_cache_task::{ImageCacheTask, ImageResponseMsg}; use servo_net::local_image_cache::LocalImageCache; @@ -227,29 +227,31 @@ impl Layout { }; } - // Build the display list, and send it to the renderer. - do profile(time::LayoutDispListBuildCategory, self.profiler_chan.clone()) { - let builder = DisplayListBuilder { - ctx: &layout_ctx, - }; + // Build the display list if necessary, and send it to the renderer. + if data.goal == ReflowForDisplay { + do profile(time::LayoutDispListBuildCategory, self.profiler_chan.clone()) { + let builder = DisplayListBuilder { + ctx: &layout_ctx, + }; - let display_list = @Cell(DisplayList::new()); - - // TODO: Set options on the builder before building. - // TODO: Be smarter about what needs painting. - layout_root.build_display_list(&builder, &layout_root.position(), display_list); + let display_list = @Cell(DisplayList::new()); - let root_size = do layout_root.with_base |base| { - base.position.size - }; + // TODO: Set options on the builder before building. + // TODO: Be smarter about what needs painting. + layout_root.build_display_list(&builder, &layout_root.position(), display_list); - let render_layer = RenderLayer { - display_list: display_list.take(), - size: Size2D(root_size.width.to_px() as uint, root_size.height.to_px() as uint) - }; + let root_size = do layout_root.with_base |base| { + base.position.size + }; - self.render_task.channel.send(RenderMsg(render_layer)); - } // time(layout: display list building) + let render_layer = RenderLayer { + display_list: display_list.take(), + size: Size2D(root_size.width.to_px() as uint, root_size.height.to_px() as uint) + }; + + self.render_task.channel.send(RenderMsg(render_layer)); + } // time(layout: display list building) + } // Tell script that we're done. data.script_join_chan.send(()); diff --git a/src/components/script/layout_interface.rs b/src/components/script/layout_interface.rs index 86077244ecd..b4570f2a972 100644 --- a/src/components/script/layout_interface.rs +++ b/src/components/script/layout_interface.rs @@ -86,11 +86,22 @@ impl Damage { } } +/// Why we're doing reflow. +#[deriving(Eq)] +pub enum ReflowGoal { + /// We're reflowing in order to send a display list to the screen. + ReflowForDisplay, + /// We're reflowing in order to satisfy a script query. No display list will be created. + ReflowForScriptQuery, +} + /// Information needed for a reflow. pub struct BuildData { node: AbstractNode, /// What reflow needs to be done. damage: Damage, + /// The goal of reflow: either to render to the screen or to flush layout info for script. + goal: ReflowGoal, /// The URL of the page. url: Url, /// The channel through which messages can be sent back to the script task. diff --git a/src/components/script/script_task.rs b/src/components/script/script_task.rs index 094336bf1ab..d82f4e0895e 100644 --- a/src/components/script/script_task.rs +++ b/src/components/script/script_task.rs @@ -12,7 +12,7 @@ use dom::node::define_bindings; use dom::window::Window; use layout_interface::{AddStylesheetMsg, BuildData, BuildMsg, Damage, LayoutQuery, HitTestQuery}; use layout_interface::{LayoutResponse, HitTestResponse, LayoutTask, MatchSelectorsDamage, NoDamage}; -use layout_interface::{QueryMsg, ReflowDamage}; +use layout_interface::{QueryMsg, ReflowDamage, ReflowForDisplay, ReflowForScriptQuery, ReflowGoal}; use layout_interface; use core::cast::transmute; @@ -283,7 +283,7 @@ impl ScriptContext { null(), &rval); - self.relayout() + self.relayout(ReflowForScriptQuery) } /// Handles a request to exit the script task and shut down layout. @@ -349,7 +349,7 @@ impl ScriptContext { // Perform the initial reflow. self.damage.add(MatchSelectorsDamage); - self.relayout(); + self.relayout(ReflowForDisplay); // Define debug functions. self.js_compartment.define_functions(debug_fns); @@ -383,10 +383,10 @@ impl ScriptContext { } } - /// Initiate an asynchronous relayout operation + /// Initiate an asynchronous relayout operation to handle a script layout query. pub fn trigger_relayout(&mut self, damage: Damage) { self.damage.add(damage); - self.relayout(); + self.relayout(ReflowForScriptQuery); } /// This method will wait until the layout task has completed its current action, join the @@ -394,7 +394,7 @@ impl ScriptContext { /// computation to finish. /// /// This function fails if there is no root frame. - fn relayout(&mut self) { + fn relayout(&mut self, goal: ReflowGoal) { debug!("script: performing relayout"); // Now, join the layout so that they will see the latest changes we have made. @@ -411,6 +411,7 @@ impl ScriptContext { let data = ~BuildData { node: root_frame.document.root, url: copy root_frame.url, + goal: goal, script_chan: self.script_chan.clone(), window_size: self.window_size, script_join_chan: join_chan, @@ -445,7 +446,7 @@ impl ScriptContext { self.window_size = Size2D(new_width, new_height); if self.root_frame.is_some() { - self.relayout() + self.relayout(ReflowForDisplay) } response_chan.send(()) @@ -457,7 +458,7 @@ impl ScriptContext { self.damage.add(MatchSelectorsDamage); if self.root_frame.is_some() { - self.relayout() + self.relayout(ReflowForDisplay) } }