aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/components/main/dom/bindings/element.rs6
-rw-r--r--src/components/main/dom/element.rs22
-rw-r--r--src/components/main/dom/window.rs2
-rw-r--r--src/components/main/engine.rs14
-rw-r--r--src/components/main/layout/layout_task.rs160
-rw-r--r--src/components/main/layout_interface.rs103
-rw-r--r--src/components/main/scripting/script_task.rs19
-rwxr-xr-xsrc/components/main/servo.rc1
8 files changed, 193 insertions, 134 deletions
diff --git a/src/components/main/dom/bindings/element.rs b/src/components/main/dom/bindings/element.rs
index 66d47931f73..11930321136 100644
--- a/src/components/main/dom/bindings/element.rs
+++ b/src/components/main/dom/bindings/element.rs
@@ -8,7 +8,7 @@ use dom::bindings::utils::{domstring_to_jsval, WrapNewBindingObject};
use dom::bindings::utils::{str, CacheableWrapper, DOM_OBJECT_SLOT, DOMString};
use dom::element::*;
use dom::node::{AbstractNode, Element, ElementNodeTypeId, ScriptView};
-use layout::layout_task;
+use layout_interface::{ContentBoxQuery, ContentBoxResponse};
use scripting::script_task::task_from_context;
use super::utils;
@@ -216,10 +216,10 @@ extern fn HTMLImageElement_getWidth(cx: *JSContext, _argc: c_uint, vp: *mut JSVa
let width = match node.type_id() {
ElementNodeTypeId(HTMLImageElementTypeId) => {
let script_context = task_from_context(cx);
- match (*script_context).query_layout(layout_task::ContentBox(node)) {
+ match (*script_context).query_layout(ContentBoxQuery(node)) {
Ok(rect) => {
match rect {
- layout_task::ContentRect(rect) => rect.size.width.to_px(),
+ ContentBoxResponse(rect) => rect.size.width.to_px(),
_ => fail!(~"unexpected layout reply")
}
}
diff --git a/src/components/main/dom/element.rs b/src/components/main/dom/element.rs
index e3a5e59dae3..742fdb46682 100644
--- a/src/components/main/dom/element.rs
+++ b/src/components/main/dom/element.rs
@@ -2,19 +2,17 @@
* 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/. */
-//
-// Element nodes.
-//
+//! Element nodes.
-use dom::node::{ElementNodeTypeId, Node, ScriptView};
+use dom::bindings::utils::DOMString;
use dom::clientrect::ClientRect;
use dom::clientrectlist::ClientRectList;
-use dom::bindings::utils::DOMString;
-
-use layout::layout_task;
+use dom::node::{ElementNodeTypeId, Node, ScriptView};
+use layout_interface::{ContentBoxQuery, ContentBoxResponse, ContentBoxesQuery};
+use layout_interface::{ContentBoxesResponse};
-use core::str::eq_slice;
use core::cell::Cell;
+use core::str::eq_slice;
use std::net::url::Url;
pub struct Element {
@@ -169,9 +167,9 @@ pub impl<'self> Element {
let script_context = unsafe {
&mut *win.script_context
};
- match script_context.query_layout(layout_task::ContentBoxes(node)) {
+ match script_context.query_layout(ContentBoxesQuery(node)) {
Ok(rects) => match rects {
- layout_task::ContentRects(rects) =>
+ ContentBoxesResponse(rects) =>
do rects.map |r| {
ClientRect::new(
r.origin.y.to_f32(),
@@ -209,9 +207,9 @@ pub impl<'self> Element {
let node = self.parent.abstract.get();
assert!(node.is_element());
let script_context = unsafe { &mut *win.script_context };
- match script_context.query_layout(layout_task::ContentBox(node)) {
+ match script_context.query_layout(ContentBoxQuery(node)) {
Ok(rect) => match rect {
- layout_task::ContentRect(rect) =>
+ ContentBoxResponse(rect) =>
Some(ClientRect::new(
rect.origin.y.to_f32(),
(rect.origin.y + rect.size.height).to_f32(),
diff --git a/src/components/main/dom/window.rs b/src/components/main/dom/window.rs
index c7eaacd7f31..439dca0fd79 100644
--- a/src/components/main/dom/window.rs
+++ b/src/components/main/dom/window.rs
@@ -4,8 +4,8 @@
use dom::bindings::utils::WrapperCache;
use dom::bindings::window;
+use layout_interface::MatchSelectorsDamage;
use scripting::script_task::{ExitMsg, FireTimerMsg, ScriptMsg, ScriptContext};
-use layout::layout_task::MatchSelectorsDamage;
use util::task::spawn_listener;
use core::comm::{Port, Chan, SharedChan};
diff --git a/src/components/main/engine.rs b/src/components/main/engine.rs
index 575fbc57bbf..c26686262d4 100644
--- a/src/components/main/engine.rs
+++ b/src/components/main/engine.rs
@@ -3,8 +3,9 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use compositing::CompositorTask;
-use layout::layout_task::LayoutTask;
use layout::layout_task;
+use layout_interface::LayoutTask;
+use layout_interface;
use scripting::script_task::{ExecuteMsg, LoadMsg, ScriptMsg, ScriptTask};
use scripting::script_task;
use util::task::spawn_listener;
@@ -18,7 +19,6 @@ use servo_net::image_cache_task::{ImageCacheTask, ImageCacheTaskClient};
use servo_net::resource_task::ResourceTask;
use servo_net::resource_task;
use servo_util::time::{ProfilerChan, ProfilerPort, ProfilerTask};
-use servo_util::time;
use std::net::url::Url;
pub type EngineTask = Chan<Msg>;
@@ -61,10 +61,10 @@ impl Engine {
let profiler_task = ProfilerTask::new(profiler_port.take(), profiler_chan.clone());
let opts = opts.take();
- let layout_task = LayoutTask(render_task.clone(),
- image_cache_task.clone(),
- opts,
- profiler_task.chan.clone());
+ let layout_task = layout_task::create_layout_task(render_task.clone(),
+ image_cache_task.clone(),
+ opts,
+ profiler_task.chan.clone());
let script_task = ScriptTask::new(script_port.take(),
script_chan.take(),
@@ -105,7 +105,7 @@ impl Engine {
ExitMsg(sender) => {
self.script_task.chan.send(script_task::ExitMsg);
- self.layout_task.send(layout_task::ExitMsg);
+ self.layout_task.chan.send(layout_interface::ExitMsg);
let (response_port, response_chan) = comm::stream();
diff --git a/src/components/main/layout/layout_task.rs b/src/components/main/layout/layout_task.rs
index 5da211854bf..d23d377e244 100644
--- a/src/components/main/layout/layout_task.rs
+++ b/src/components/main/layout/layout_task.rs
@@ -2,19 +2,23 @@
* 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/. */
-/// The layout task. Performs layout on the DOM, builds display lists and sends them to be
+//! The layout task. Performs layout on the DOM, builds display lists and sends them to be
/// rendered.
use css::matching::MatchMethods;
use css::select::new_css_select_ctx;
use dom::event::ReflowEvent;
-use dom::node::{AbstractNode, LayoutView, ScriptView};
+use dom::node::{AbstractNode, LayoutView};
use layout::aux::{LayoutData, LayoutAuxMethods};
use layout::box_builder::LayoutTreeBuilder;
use layout::context::LayoutContext;
use layout::debug::{BoxedMutDebugMethods, DebugMethods};
use layout::display_list_builder::{DisplayListBuilder, FlowDisplayListBuilderMethods};
use layout::flow::FlowContext;
+use layout_interface::{AddStylesheetMsg, BuildData, BuildMsg, ContentBoxQuery, ContentBoxResponse};
+use layout_interface::{ContentBoxesQuery, ContentBoxesResponse, ExitMsg, LayoutQuery};
+use layout_interface::{LayoutResponse, LayoutTask, MatchSelectorsDamage, Msg, NoDamage, QueryMsg};
+use layout_interface::{ReflowDamage};
use scripting::script_task::{ScriptMsg, SendEventMsg};
use util::task::spawn_listener;
use servo_util::time;
@@ -40,128 +44,80 @@ use newcss::types::OriginAuthor;
use servo_net::image_cache_task::{ImageCacheTask, ImageResponseMsg};
use servo_net::local_image_cache::LocalImageCache;
use servo_util::tree::TreeUtils;
-use std::net::url::Url;
-pub type LayoutTask = SharedChan<Msg>;
-
-pub enum LayoutQuery {
- ContentBox(AbstractNode<ScriptView>),
- ContentBoxes(AbstractNode<ScriptView>),
-}
-
-pub type LayoutQueryResponse = Result<LayoutQueryResponse_, ()>;
-
-pub enum LayoutQueryResponse_ {
- ContentRect(Rect<Au>),
- ContentRects(~[Rect<Au>])
-}
-
-pub enum Msg {
- AddStylesheet(Stylesheet),
- BuildMsg(~BuildData),
- QueryMsg(LayoutQuery, Chan<LayoutQueryResponse>),
- ExitMsg
-}
-
-// Dirty bits for layout.
-pub enum Damage {
- NoDamage, // Document is clean; do nothing.
- ReflowDamage, // Reflow; don't perform CSS selector matching.
- MatchSelectorsDamage, // Perform CSS selector matching and reflow.
-}
+pub fn create_layout_task(render_task: RenderTask,
+ img_cache_task: ImageCacheTask,
+ opts: Opts,
+ profiler_chan: ProfilerChan)
+ -> LayoutTask {
+ let chan = do spawn_listener::<Msg> |from_script| {
+ let mut layout = Layout::new(render_task.clone(),
+ img_cache_task.clone(),
+ from_script,
+ &opts,
+ profiler_chan.clone());
+ layout.start();
+ };
-impl Damage {
- fn add(&mut self, new_damage: Damage) {
- match (*self, new_damage) {
- (NoDamage, _) => *self = new_damage,
- (ReflowDamage, NoDamage) => *self = ReflowDamage,
- (ReflowDamage, new_damage) => *self = new_damage,
- (MatchSelectorsDamage, _) => *self = MatchSelectorsDamage
- }
+ LayoutTask {
+ chan: SharedChan::new(chan),
}
}
-pub struct BuildData {
- node: AbstractNode<ScriptView>,
- url: Url,
- script_chan: SharedChan<ScriptMsg>,
- window_size: Size2D<uint>,
- script_join_chan: Chan<()>,
- damage: Damage,
-}
-
-pub fn LayoutTask(render_task: RenderTask,
- img_cache_task: ImageCacheTask,
- opts: Opts,
- prof_chan: ProfilerChan)
- -> LayoutTask {
- SharedChan::new(do spawn_listener::<Msg> |from_script| {
- let mut layout = Layout(render_task.clone(),
- img_cache_task.clone(),
- from_script,
- &opts,
- prof_chan.clone());
- layout.start();
- })
-}
-
struct Layout {
render_task: RenderTask,
image_cache_task: ImageCacheTask,
local_image_cache: @mut LocalImageCache,
from_script: Port<Msg>,
font_ctx: @mut FontContext,
- // This is used to root reader data
+
+ /// This is used to root reader data.
layout_refs: ~[@mut LayoutData],
- css_select_ctx: @mut SelectCtx,
- prof_chan: ProfilerChan,
-}
-fn Layout(render_task: RenderTask,
- image_cache_task: ImageCacheTask,
- from_script: Port<Msg>,
- opts: &Opts,
- prof_chan: ProfilerChan)
- -> Layout {
- let fctx = @mut FontContext::new(opts.render_backend, true, prof_chan.clone());
-
- Layout {
- render_task: render_task,
- image_cache_task: image_cache_task.clone(),
- local_image_cache: @mut LocalImageCache(image_cache_task),
- from_script: from_script,
- font_ctx: fctx,
- layout_refs: ~[],
- css_select_ctx: @mut new_css_select_ctx(),
- prof_chan: prof_chan.clone()
- }
+ css_select_ctx: @mut SelectCtx,
+ profiler_chan: ProfilerChan,
}
impl Layout {
+ fn new(render_task: RenderTask,
+ image_cache_task: ImageCacheTask,
+ from_script: Port<Msg>,
+ opts: &Opts,
+ profiler_chan: ProfilerChan)
+ -> Layout {
+ let fctx = @mut FontContext::new(opts.render_backend, true, profiler_chan.clone());
+
+ Layout {
+ render_task: render_task,
+ image_cache_task: image_cache_task.clone(),
+ local_image_cache: @mut LocalImageCache(image_cache_task),
+ from_script: from_script,
+ font_ctx: fctx,
+ layout_refs: ~[],
+ css_select_ctx: @mut new_css_select_ctx(),
+ profiler_chan: profiler_chan,
+ }
+ }
fn start(&mut self) {
while self.handle_request() {
- // loop indefinitely
+ // Loop indefinitely.
}
}
fn handle_request(&mut self) -> bool {
-
match self.from_script.recv() {
- AddStylesheet(sheet) => {
- self.handle_add_stylesheet(sheet);
- }
+ AddStylesheetMsg(sheet) => self.handle_add_stylesheet(sheet),
BuildMsg(data) => {
let data = Cell(data);
- do profile(time::LayoutPerformCategory, self.prof_chan.clone()) {
+ do profile(time::LayoutPerformCategory, self.profiler_chan.clone()) {
self.handle_build(data.take());
}
-
}
QueryMsg(query, chan) => {
let chan = Cell(chan);
- do profile(time::LayoutQueryCategory, self.prof_chan.clone()) {
+ do profile(time::LayoutQueryCategory, self.profiler_chan.clone()) {
self.handle_query(query, chan.take())
}
}
@@ -212,7 +168,7 @@ impl Layout {
// Initialize layout data for each node.
//
// FIXME: This is inefficient. We don't need an entire traversal to do this!
- do profile(time::LayoutAuxInitCategory, self.prof_chan.clone()) {
+ do profile(time::LayoutAuxInitCategory, self.profiler_chan.clone()) {
node.initialize_style_for_subtree(&mut self.layout_refs);
}
@@ -220,7 +176,7 @@ impl Layout {
match data.damage {
NoDamage | ReflowDamage => {}
MatchSelectorsDamage => {
- do profile(time::LayoutSelectorMatchCategory, self.prof_chan.clone()) {
+ do profile(time::LayoutSelectorMatchCategory, self.profiler_chan.clone()) {
node.restyle_subtree(self.css_select_ctx);
}
}
@@ -228,7 +184,7 @@ impl Layout {
// Construct the flow tree.
let layout_root: FlowContext = do profile(time::LayoutTreeBuilderCategory,
- self.prof_chan.clone()) {
+ self.profiler_chan.clone()) {
let mut builder = LayoutTreeBuilder::new();
let layout_root: FlowContext = match builder.construct_trees(&layout_ctx, *node) {
Ok(root) => root,
@@ -243,7 +199,7 @@ impl Layout {
// Perform the primary layout passes over the flow tree to compute the locations of all
// the boxes.
- do profile(time::LayoutMainCategory, self.prof_chan.clone()) {
+ do profile(time::LayoutMainCategory, self.profiler_chan.clone()) {
for layout_root.traverse_postorder |flow| {
flow.bubble_widths(&mut layout_ctx);
};
@@ -256,7 +212,7 @@ impl Layout {
}
// Build the display list, and send it to the renderer.
- do profile(time::LayoutDispListBuildCategory, self.prof_chan.clone()) {
+ do profile(time::LayoutDispListBuildCategory, self.profiler_chan.clone()) {
let builder = DisplayListBuilder {
ctx: &layout_ctx,
};
@@ -281,9 +237,9 @@ impl Layout {
/// Handles a query from the script task. This is the main routine that DOM functions like
/// `getClientRects()` or `getBoundingClientRect()` ultimately invoke.
- fn handle_query(&self, query: LayoutQuery, reply_chan: Chan<LayoutQueryResponse>) {
+ fn handle_query(&self, query: LayoutQuery, reply_chan: Chan<Result<LayoutResponse,()>>) {
match query {
- ContentBox(node) => {
+ ContentBoxQuery(node) => {
// FIXME: Isolate this transmutation into a single "bridge" module.
let node: AbstractNode<LayoutView> = unsafe {
transmute(node)
@@ -308,14 +264,14 @@ impl Layout {
error!("no boxes for node");
Err(())
}
- Some(rect) => Ok(ContentRect(rect))
+ Some(rect) => Ok(ContentBoxResponse(rect))
}
}
};
reply_chan.send(response)
}
- ContentBoxes(node) => {
+ ContentBoxesQuery(node) => {
// FIXME: Isolate this transmutation into a single "bridge" module.
let node: AbstractNode<LayoutView> = unsafe {
transmute(node)
@@ -329,7 +285,7 @@ impl Layout {
boxes.push(box.content_box());
}
- Ok(ContentRects(boxes))
+ Ok(ContentBoxesResponse(boxes))
}
};
diff --git a/src/components/main/layout_interface.rs b/src/components/main/layout_interface.rs
new file mode 100644
index 00000000000..fc99bb3dcab
--- /dev/null
+++ b/src/components/main/layout_interface.rs
@@ -0,0 +1,103 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * 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/. */
+
+//! The high-level interface from script to layout. Using this abstract interface helps reduce
+/// coupling between these two components, and enables the DOM to be placed in a separate crate
+/// from layout.
+
+use dom::node::{AbstractNode, ScriptView};
+use scripting::script_task::ScriptMsg;
+
+use core::comm::{Chan, SharedChan};
+use geom::rect::Rect;
+use geom::size::Size2D;
+use gfx::geometry::Au;
+use newcss::stylesheet::Stylesheet;
+use std::net::url::Url;
+
+/// Asynchronous messages that script can send to layout.
+///
+/// FIXME(pcwalton): I think this should probably be merged with `LayoutQuery` below.
+pub enum Msg {
+ /// Adds the given stylesheet to the document.
+ AddStylesheetMsg(Stylesheet),
+
+ /// Requests a reflow.
+ ///
+ /// FIXME(pcwalton): Call this `reflow` instead?
+ BuildMsg(~BuildData),
+
+ /// Performs a synchronous layout request.
+ ///
+ /// FIXME(pcwalton): As noted below, this isn't very type safe.
+ QueryMsg(LayoutQuery, Chan<Result<LayoutResponse,()>>),
+
+ /// Requests that the layout task shut down and exit.
+ ExitMsg,
+}
+
+/// Synchronous messages that script can send to layout.
+pub enum LayoutQuery {
+ /// Requests the dimensions of the content box, as in the `getBoundingClientRect()` call.
+ ContentBoxQuery(AbstractNode<ScriptView>),
+ /// Requests the dimensions of all the content boxes, as in the `getClientRects()` call.
+ ContentBoxesQuery(AbstractNode<ScriptView>),
+}
+
+/// The reply of a synchronous message from script to layout.
+///
+/// FIXME(pcwalton): This isn't very type safe. Maybe `LayoutQuery` objects should include
+/// response channels?
+pub enum LayoutResponse {
+ /// A response to the `ContentBoxQuery` message.
+ ContentBoxResponse(Rect<Au>),
+ /// A response to the `ContentBoxesQuery` message.
+ ContentBoxesResponse(~[Rect<Au>]),
+}
+
+/// Dirty bits for layout.
+pub enum Damage {
+ /// The document is clean; nothing needs to be done.
+ NoDamage,
+ /// Reflow, but do not perform CSS selector matching.
+ ReflowDamage,
+ /// Perform CSS selector matching and reflow.
+ MatchSelectorsDamage,
+}
+
+impl Damage {
+ /// Sets this damage to the maximum of this damage and the given damage.
+ ///
+ /// FIXME(pcwalton): This could be refactored to use `max` and the `Ord` trait, and this
+ /// function removed.
+ fn add(&mut self, new_damage: Damage) {
+ match (*self, new_damage) {
+ (NoDamage, _) => *self = new_damage,
+ (ReflowDamage, NoDamage) => *self = ReflowDamage,
+ (ReflowDamage, new_damage) => *self = new_damage,
+ (MatchSelectorsDamage, _) => *self = MatchSelectorsDamage
+ }
+ }
+}
+
+/// Information needed for a reflow.
+pub struct BuildData {
+ node: AbstractNode<ScriptView>,
+ /// What reflow needs to be done.
+ damage: Damage,
+ /// The URL of the page.
+ url: Url,
+ /// The channel through which messages can be sent back to the script task.
+ script_chan: SharedChan<ScriptMsg>,
+ /// The current window size.
+ window_size: Size2D<uint>,
+ script_join_chan: Chan<()>,
+}
+
+/// Encapsulates a channel to the layout task.
+#[deriving(Clone)]
+pub struct LayoutTask {
+ chan: SharedChan<Msg>,
+}
+
diff --git a/src/components/main/scripting/script_task.rs b/src/components/main/scripting/script_task.rs
index fb01adef9b7..cf99428c677 100644
--- a/src/components/main/scripting/script_task.rs
+++ b/src/components/main/scripting/script_task.rs
@@ -10,10 +10,10 @@ use dom::document::Document;
use dom::event::{Event, ResizeEvent, ReflowEvent};
use dom::node::define_bindings;
use dom::window::Window;
-use layout::layout_task::{AddStylesheet, BuildData, BuildMsg, Damage, LayoutQuery};
-use layout::layout_task::{LayoutQueryResponse, LayoutTask, MatchSelectorsDamage, NoDamage};
-use layout::layout_task::{QueryMsg, ReflowDamage};
-use layout::layout_task;
+use layout_interface::{AddStylesheetMsg, BuildData, BuildMsg, Damage, LayoutQuery};
+use layout_interface::{LayoutResponse, LayoutTask, MatchSelectorsDamage, NoDamage};
+use layout_interface::{QueryMsg, ReflowDamage};
+use layout_interface;
use core::cast::transmute;
use core::cell::Cell;
@@ -292,7 +292,8 @@ impl ScriptContext {
for self.root_frame.each |frame| {
frame.document.teardown();
}
- self.layout_task.send(layout_task::ExitMsg)
+
+ self.layout_task.chan.send(layout_interface::ExitMsg)
}
/// The entry point to document loading. Defines bindings, sets up the window and document
@@ -321,7 +322,7 @@ impl ScriptContext {
// in the script task.
loop {
match html_parsing_result.style_port.recv() {
- Some(sheet) => self.layout_task.send(AddStylesheet(sheet)),
+ Some(sheet) => self.layout_task.chan.send(AddStylesheetMsg(sheet)),
None => break,
}
}
@@ -416,7 +417,7 @@ impl ScriptContext {
damage: replace(&mut self.damage, NoDamage),
};
- self.layout_task.send(BuildMsg(data))
+ self.layout_task.chan.send(BuildMsg(data))
}
}
@@ -424,11 +425,11 @@ impl ScriptContext {
}
/// Sends the given query to layout.
- pub fn query_layout(&mut self, query: LayoutQuery) -> LayoutQueryResponse {
+ pub fn query_layout(&mut self, query: LayoutQuery) -> Result<LayoutResponse,()> {
self.join_layout();
let (response_port, response_chan) = comm::stream();
- self.layout_task.send(QueryMsg(query, response_chan));
+ self.layout_task.chan.send(QueryMsg(query, response_chan));
response_port.recv()
}
diff --git a/src/components/main/servo.rc b/src/components/main/servo.rc
index e4526bacf23..94692bfddfc 100755
--- a/src/components/main/servo.rc
+++ b/src/components/main/servo.rc
@@ -121,6 +121,7 @@ pub mod html {
pub mod hubbub_html_parser;
}
+pub mod layout_interface;
pub mod windowing;
#[path="platform/mod.rs"]