aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--components/script/dom/node.rs4
-rw-r--r--components/script/dom/window.rs16
-rw-r--r--components/script/page.rs36
-rw-r--r--components/script/script_task.rs3
4 files changed, 46 insertions, 13 deletions
diff --git a/components/script/dom/node.rs b/components/script/dom/node.rs
index f419798a110..6ce21d13b94 100644
--- a/components/script/dom/node.rs
+++ b/components/script/dom/node.rs
@@ -588,7 +588,7 @@ impl<'m, 'n> NodeHelpers<'m, 'n> for JSRef<'n, Node> {
let page = window.deref().page();
let addr = self.to_trusted_node_address();
- let ContentBoxResponse(rect) = page.layout_rpc.content_box(addr);
+ let ContentBoxResponse(rect) = page.layout().content_box(addr);
rect
}
@@ -596,7 +596,7 @@ impl<'m, 'n> NodeHelpers<'m, 'n> for JSRef<'n, Node> {
let window = window_from_node(self).root();
let page = window.deref().page();
let addr = self.to_trusted_node_address();
- let ContentBoxesResponse(rects) = page.layout_rpc.content_boxes(addr);
+ let ContentBoxesResponse(rects) = page.layout().content_boxes(addr);
rects
}
diff --git a/components/script/dom/window.rs b/components/script/dom/window.rs
index ce60f3cdb19..54f9c9ac2f9 100644
--- a/components/script/dom/window.rs
+++ b/components/script/dom/window.rs
@@ -19,7 +19,7 @@ use dom::location::Location;
use dom::navigator::Navigator;
use dom::performance::Performance;
use dom::screen::Screen;
-use layout_interface::{ReflowForDisplay, DocumentDamageLevel};
+use layout_interface::{ReflowGoal, DocumentDamageLevel};
use page::Page;
use script_task::{ExitWindowMsg, FireTimerMsg, ScriptChan, TriggerLoadMsg, TriggerFragmentMsg};
use script_traits::ScriptControlChan;
@@ -77,14 +77,14 @@ impl TimerHandle {
pub struct Window {
eventtarget: EventTarget,
pub script_chan: ScriptChan,
- control_chan: ScriptControlChan,
+ pub control_chan: ScriptControlChan,
console: Cell<Option<JS<Console>>>,
location: Cell<Option<JS<Location>>>,
navigator: Cell<Option<JS<Navigator>>>,
pub image_cache_task: ImageCacheTask,
pub active_timers: Traceable<RefCell<HashMap<TimerId, TimerHandle>>>,
next_timer_handle: Traceable<Cell<i32>>,
- compositor: Untraceable<Box<ScriptListener>>,
+ pub compositor: Untraceable<Box<ScriptListener>>,
pub browser_context: Traceable<RefCell<Option<BrowserContext>>>,
pub page: Rc<Page>,
performance: Cell<Option<JS<Performance>>>,
@@ -355,6 +355,7 @@ impl Reflectable for Window {
pub trait WindowHelpers {
fn damage_and_reflow(&self, damage: DocumentDamageLevel);
+ fn flush_layout(&self, goal: ReflowGoal);
fn wait_until_safe_to_modify_dom(&self);
fn init_browser_context(&self, doc: &JSRef<Document>);
fn load_url(&self, href: DOMString);
@@ -387,11 +388,12 @@ impl<'a> WindowHelpers for JSRef<'a, Window> {
}
fn damage_and_reflow(&self, damage: DocumentDamageLevel) {
- // FIXME This should probably be ReflowForQuery, not Display. All queries currently
- // currently rely on the display list, which means we can't destroy it by
- // doing a query reflow.
self.page().damage(damage);
- self.page().reflow(ReflowForDisplay, self.control_chan.clone(), *self.compositor);
+ self.page().avoided_reflows.set(self.page().avoided_reflows.get() + 1);
+ }
+
+ fn flush_layout(&self, goal: ReflowGoal) {
+ self.page().flush_layout(goal);
}
fn wait_until_safe_to_modify_dom(&self) {
diff --git a/components/script/page.rs b/components/script/page.rs
index cf532783c8b..76bfbbe328c 100644
--- a/components/script/page.rs
+++ b/components/script/page.rs
@@ -13,7 +13,7 @@ use dom::document::{Document, DocumentHelpers};
use dom::element::{Element, AttributeHandlers};
use dom::node::{Node, NodeHelpers};
use dom::window::Window;
-use layout_interface::{DocumentDamage};
+use layout_interface::{DocumentDamage, ReflowForDisplay};
use layout_interface::{DocumentDamageLevel, HitTestResponse, MouseOverResponse};
use layout_interface::{GetRPCMsg, LayoutChan, LayoutRPC};
use layout_interface::{Reflow, ReflowGoal, ReflowMsg};
@@ -56,7 +56,7 @@ pub struct Page {
pub layout_chan: Untraceable<LayoutChan>,
/// A handle to perform RPC calls into the layout, quickly.
- pub layout_rpc: Untraceable<Box<LayoutRPC>>,
+ layout_rpc: Untraceable<Box<LayoutRPC>>,
/// The port that we will use to join layout. If this is `None`, then layout is not running.
pub layout_join_port: Untraceable<RefCell<Option<Receiver<()>>>>,
@@ -94,6 +94,9 @@ pub struct Page {
/// Number of pending reflows that were sent while layout was active.
pub pending_reflows: Cell<int>,
+
+ /// Number of unnecessary potential reflows that were skipped since the last reflow
+ pub avoided_reflows: Cell<int>,
}
pub struct PageIterator {
@@ -158,9 +161,31 @@ impl Page {
constellation_chan: Untraceable::new(constellation_chan),
children: Traceable::new(RefCell::new(vec!())),
pending_reflows: Cell::new(0),
+ avoided_reflows: Cell::new(0),
+ }
+ }
+
+ pub fn flush_layout(&self, goal: ReflowGoal) {
+ let damaged = self.damage.borrow().is_some();
+ if damaged {
+ let frame = self.frame();
+ let window = frame.get_ref().window.root();
+ self.reflow(goal, window.control_chan.clone(), *window.compositor);
+ } else {
+ self.avoided_reflows.set(self.avoided_reflows.get() + 1);
}
}
+ pub fn layout(&self) -> &LayoutRPC {
+ // FIXME This should probably be ReflowForQuery, not Display. All queries currently
+ // currently rely on the display list, which means we can't destroy it by
+ // doing a query reflow.
+ self.flush_layout(ReflowForDisplay);
+ self.join_layout(); //FIXME: is this necessary, or is layout_rpc's mutex good enough?
+ let layout_rpc: &LayoutRPC = *self.layout_rpc;
+ layout_rpc
+ }
+
// must handle root case separately
pub fn remove(&self, id: PipelineId) -> Option<Rc<Page>> {
let remove_idx = {
@@ -322,6 +347,9 @@ impl Page {
match root.root() {
None => {},
Some(root) => {
+ debug!("avoided {:d} reflows", self.avoided_reflows.get());
+ self.avoided_reflows.set(0);
+
debug!("script: performing reflow for goal {:?}", goal);
// Now, join the layout so that they will see the latest changes we have made.
@@ -390,7 +418,7 @@ impl Page {
}
let root = root.unwrap();
let root: &JSRef<Node> = NodeCast::from_ref(&*root);
- let address = match self.layout_rpc.hit_test(root.to_trusted_node_address(), *point) {
+ let address = match self.layout().hit_test(root.to_trusted_node_address(), *point) {
Ok(HitTestResponse(node_address)) => {
Some(node_address)
}
@@ -411,7 +439,7 @@ impl Page {
}
let root = root.unwrap();
let root: &JSRef<Node> = NodeCast::from_ref(&*root);
- let address = match self.layout_rpc.mouse_over(root.to_trusted_node_address(), *point) {
+ let address = match self.layout().mouse_over(root.to_trusted_node_address(), *point) {
Ok(MouseOverResponse(node_address)) => {
Some(node_address)
}
diff --git a/components/script/script_task.rs b/components/script/script_task.rs
index a705398d4c1..6584b052bf7 100644
--- a/components/script/script_task.rs
+++ b/components/script/script_task.rs
@@ -693,6 +693,7 @@ impl ScriptTask {
// Kick off the initial reflow of the page.
debug!("kicking off initial reflow of {}", url);
document.deref().content_changed();
+ window.flush_layout(ReflowForDisplay);
let fragment = url.fragment.as_ref().map(|ref fragment| fragment.to_string());
@@ -722,6 +723,8 @@ impl ScriptTask {
Ok(_) => (),
Err(_) => println!("evaluate_script failed")
}
+
+ window.flush_layout(ReflowForDisplay);
}
});